From 75ea7099d4faae545096c77bd32174c42104cf0a Mon Sep 17 00:00:00 2001 From: mealynn Date: Sun, 24 Nov 2024 12:11:12 +0100 Subject: [PATCH] enable recording for the jack backend --- include/AudioEngine.h | 6 ++++++ include/AudioJack.h | 4 ++++ src/core/audio/AudioJack.cpp | 30 +++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/AudioEngine.h b/include/AudioEngine.h index 921fa1b34..613976737 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -174,6 +174,7 @@ public: bool captureDeviceAvailable() const; + // audio-bus-handle-stuff inline void addAudioBusHandle(AudioBusHandle* busHandle) { @@ -360,6 +361,11 @@ private: return m_audioDev; } + const AudioDevice* audioDev() const + { + return m_audioDev; + } + void renderStageNoteSetup(); void renderStageInstruments(); void renderStageEffects(); diff --git a/include/AudioJack.h b/include/AudioJack.h index e13b4a5ef..19972da9f 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -106,6 +106,7 @@ private: int processCallback(jack_nframes_t nframes); + static int setBufferSizeCallback(jack_nframes_t nframes, void* udata); static int staticProcessCallback(jack_nframes_t nframes, void* udata); static void shutdownCallback(void* _udata); @@ -116,8 +117,11 @@ private: std::atomic m_midiClient; std::vector m_outputPorts; + std::vector m_inputPorts; jack_default_audio_sample_t** m_tempOutBufs; + jack_default_audio_sample_t* m_inputFrameBuffer; SampleFrame* m_outBuf; + SampleFrame* m_inBuf; f_cnt_t m_framesDoneInCurBuf; f_cnt_t m_framesToDoInCurBuf; diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index b6da7c845..eea1f69af 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -57,6 +57,7 @@ AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam) , m_midiClient(nullptr) , m_tempOutBufs(new jack_default_audio_sample_t*[channels()]) , m_outBuf(new SampleFrame[audioEngine()->framesPerPeriod()]) + , m_inBuf(new SampleFrame[audioEngine()->framesPerPeriod()]) , m_framesDoneInCurBuf(0) , m_framesToDoInCurBuf(0) { @@ -66,6 +67,8 @@ AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam) if (successful) { connect(this, SIGNAL(zombified()), this, SLOT(restartAfterZombified()), Qt::QueuedConnection); } + + m_supportsCapture = true; } @@ -90,6 +93,7 @@ AudioJack::~AudioJack() delete[] m_tempOutBufs; delete[] m_outBuf; + delete[] m_inBuf; } @@ -154,6 +158,10 @@ bool AudioJack::initJackClient() clientName.toLatin1().constData(), jack_get_client_name(m_client)); } + m_inputFrameBuffer = new jack_default_audio_sample_t[channels() * jack_get_buffer_size(m_client)]; + + jack_set_buffer_size_callback(m_client, setBufferSizeCallback, this); + // set process-callback jack_set_process_callback(m_client, staticProcessCallback, this); @@ -167,6 +175,10 @@ bool AudioJack::initJackClient() QString name = QString("master out ") + ((ch % 2) ? "R" : "L") + QString::number(ch / 2 + 1); m_outputPorts.push_back( jack_port_register(m_client, name.toLatin1().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)); + + QString input_name = QString("master in ") + ((ch % 2) ? "R" : "L") + QString::number(ch / 2 + 1); + m_inputPorts.push_back(jack_port_register(m_client, input_name.toLatin1().constData(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)); + if (m_outputPorts.back() == nullptr) { printf("no more JACK-ports available!\n"); @@ -286,11 +298,17 @@ void AudioJack::renamePort(AudioBusHandle* port) } +int AudioJack::setBufferSizeCallback(jack_nframes_t nframes, void* udata) +{ + auto thisClass = static_cast(udata); + delete[] thisClass->m_inputFrameBuffer; + thisClass->m_inputFrameBuffer = new jack_default_audio_sample_t[thisClass->channels() * nframes]; + return 0; +} int AudioJack::processCallback(jack_nframes_t nframes) { - // do midi processing first so that midi input can // add to the following sound processing if (m_midiClient && nframes > 0) @@ -356,6 +374,16 @@ int AudioJack::processCallback(jack_nframes_t nframes) } } + for (int c = 0; c < channels(); ++c) + { + jack_default_audio_sample_t* jack_input_buffer = (jack_default_audio_sample_t*) jack_port_get_buffer(m_inputPorts[c], nframes); + + for (jack_nframes_t frame = 0; frame < nframes; frame++) + { + m_inputFrameBuffer[frame * channels() + c] = jack_input_buffer[frame]; + } + } + audioEngine()->pushInputFrames ((SampleFrame*) m_inputFrameBuffer, nframes); return 0; }