From 49ae3bb42967ea13de6f0116354215bb782af496 Mon Sep 17 00:00:00 2001 From: Digital Artifex <7929434+DigitalArtifex@users.noreply.github.com> Date: Sun, 10 Aug 2025 05:06:15 -0400 Subject: [PATCH] Bug fixes for audio textures --- package/contents/ui/ShaderChannel.qml | 122 ++++++------------ .../ui/ShaderChannelConfiguration.qml | 20 +-- package/contents/ui/config.qml | 2 +- plugin/AudioImageProvider.h | 3 +- plugin/AudioModel.cpp | 9 +- plugin/AudioModel.h | 2 +- plugin/plugin.cpp | 11 +- 7 files changed, 73 insertions(+), 96 deletions(-) diff --git a/package/contents/ui/ShaderChannel.qml b/package/contents/ui/ShaderChannel.qml index c050072..84628cb 100644 --- a/package/contents/ui/ShaderChannel.qml +++ b/package/contents/ui/ShaderChannel.qml @@ -42,8 +42,8 @@ Item ImageChannel, VideoChannel, ShaderChannel, - CubeMapChannel - // AudioChannel + CubeMapChannel, + AudioChannel } property int type: ShaderChannel.Type.ImageChannel @@ -133,15 +133,15 @@ Item { loader.sourceComponent: channelShader } + }, + State + { + when: channel.type === ShaderChannel.Type.AudioChannel + PropertyChanges + { + loader.sourceComponent: channelAudio + } } - // State - // { - // when: channel.type === ShaderChannel.Type.AudioChannel - // PropertyChanges - // { - // loader.sourceComponent: channelAudio - // } - // } ] transform: Rotation @@ -373,80 +373,40 @@ Item // Supporting this as an mp3 feels kinda silly. Should really figure out how to capture desktop audio with qml // UPDATE: This is not currently supported in QML, so we will need to implement this in C++ later - // Component - // { - // id: channelAudio - // Rectangle - // { - // anchors.fill: parent - // color: "black" + Component + { + id: audioChannel - // property var audioData: new Array(512).fill(0) - // property alias texture: audioTexture + Item + { - // MediaDevices - // { - // id: devices - // } + Image + { + id: textureImage + source: "image://audiotexture/frame" + anchors.fill: parent + fillMode: Image.PreserveAspectFit + } - // AudioInput - // { - // id: audioInput - // device: devices.defaultAudioInput - // } + Timer + { + property int frame: 0 + interval: 16 + repeat: true + triggeredOnStart: true + running: true - // CaptureSession - // { - // id: captureSession - // audioInput: audioInput - // } + onTriggered: + { + frame++ + textureImage.source = "image://audiotexture/frame" + frame + } + } - // Timer - // { - // interval: 16 // ~60fps update - // running: true - // repeat: true - // onTriggered: - // { - // // Get audio levels and update texture - // // let buffer = audioInput.probe.audioBuffer() - // // if (buffer) - // // { - // // for (let i = 0; i < Math.min(buffer.length, 512); i++) { - // // audioData[i] = Math.abs(buffer[i]) - // // } - // // audioTexture.update() - // // } - // } - // } - - // ShaderEffectSource - // { - // id: audioTexture - // width: 512 - // height: 1 - // format: ShaderEffectSource.Alpha - // smooth: false - // hideSource: true - // sourceItem: Row - // { - // Repeater - // { - // model: 512 - // Rectangle - // { - // width: 1 - // height: 1 - // color: Qt.rgba(1, 1, 1, root.audioData[index]) - // } - // } - // } - // } - - // Component.onCompleted: - // { - // //captureSession.start() - // } - // } - // } + Component.onCompleted: + { + Komplex.AudioModel.startCapture() + } + } + } } \ No newline at end of file diff --git a/package/contents/ui/ShaderChannelConfiguration.qml b/package/contents/ui/ShaderChannelConfiguration.qml index 1468c20..acd4b40 100644 --- a/package/contents/ui/ShaderChannelConfiguration.qml +++ b/package/contents/ui/ShaderChannelConfiguration.qml @@ -88,16 +88,13 @@ Item { id: selectionModel - // Commented out Audio channel as it is not implemented yet - // ListElement - // { - // file: true - // name: "Audio" - // icon: "qrc:/icons/audio.svg" - // title: "Select an Audio File" - // filter: "MP3 Files (*.mp3):WAV Files (*.wav)" - // type: ShaderChannel.Type.AudioChannel - // } + ListElement + { + file: true + name: "Audio" + icon: "./icons/audio.svg" + type: ShaderChannel.Type.AudioChannel + } ListElement { @@ -271,6 +268,7 @@ Item RowLayout { + visible: window.tmp_type != ShaderChannel.Type.AudioChannel Layout.alignment: Qt.AlignTop Label @@ -611,6 +609,8 @@ Item case ShaderChannel.Type.VideoChannel: window.currentFolder = window.videoFolder break; + case ShaderChannel.Type.AudioChannel: + break; } // Set the current selection index diff --git a/package/contents/ui/config.qml b/package/contents/ui/config.qml index aca1ccf..7159f67 100644 --- a/package/contents/ui/config.qml +++ b/package/contents/ui/config.qml @@ -124,7 +124,7 @@ Kirigami.FormLayout model: [ { "label": i18nd("@option:komplex_mode", "ShaderToys") }, { "label": i18nd("@option:komplex_mode", "Komplex") } - ] + ] } } TabBar diff --git a/plugin/AudioImageProvider.h b/plugin/AudioImageProvider.h index 2ce4322..9746c7c 100644 --- a/plugin/AudioImageProvider.h +++ b/plugin/AudioImageProvider.h @@ -5,8 +5,9 @@ #include #include "AudioModel.h" +#include "Komplex_global.h" -class AudioImageProvider : public QQuickImageProvider +class KOMPLEX_EXPORT AudioImageProvider : public QQuickImageProvider { public: explicit AudioImageProvider(); diff --git a/plugin/AudioModel.cpp b/plugin/AudioModel.cpp index 3a3af8a..ec6469c 100644 --- a/plugin/AudioModel.cpp +++ b/plugin/AudioModel.cpp @@ -120,6 +120,9 @@ AudioModel::~AudioModel() void AudioModel::startCapture() { + if(!m_instance) + m_instance = new AudioModel(); + if(m_thread->isRunning()) return; @@ -139,6 +142,9 @@ void AudioModel::startCaptureAsync() QPixmap AudioModel::frame() { + if(!m_instance) + return QPixmap(); + return m_instance->m_frame; } @@ -319,7 +325,8 @@ void AudioModel::on_process(void *userdata) } // Blackman window function -std::vector AudioModel::createBlackmanWindow(int size) { +std::vector AudioModel::createBlackmanWindow(int size) +{ std::vector window(size); const double a0 = 0.42; const double a1 = 0.5; diff --git a/plugin/AudioModel.h b/plugin/AudioModel.h index b0e795e..54e6f78 100644 --- a/plugin/AudioModel.h +++ b/plugin/AudioModel.h @@ -12,7 +12,7 @@ * https://webaudio.github.io/web-audio-api/#smoothing-over-time * * The described smoothing method was resulting in inconsistent data. This - * is likely to a poor implementation. A linear smoothing algo seems to work + * is likely due to a poor implementation. A linear smoothing algo seems to work * (at least visually). Will need to revisit the temporal implementation if * things do not work as expected. * diff --git a/plugin/plugin.cpp b/plugin/plugin.cpp index d792aa0..39cfd38 100644 --- a/plugin/plugin.cpp +++ b/plugin/plugin.cpp @@ -7,6 +7,15 @@ #include "ShaderPackModel.h" #include "Komplex_global.h" +AudioModel *komplexAudioSingletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + + AudioModel *model = new AudioModel(); + return model; +} + class KOMPLEX_EXPORT KomplexPlugin : public QQmlExtensionPlugin { Q_OBJECT @@ -16,7 +25,7 @@ public: { Q_ASSERT(QLatin1String(uri) == QLatin1String("com.github.digitalartifex.komplex")); - qmlRegisterType(uri, 1, 0, "AudioModel"); + qmlRegisterSingletonType(uri, 1, 0, "AudioModel", komplexAudioSingletonProvider); qmlRegisterType(uri, 1, 0, "ShaderPackModel"); }