Sample Track Recording with Jack backend (#7567)
Enable the `AudioJack` to take recorded input and push it to the `AudioEngine`. This adds functionality for `AudioJack` which already exists for `AudioSdl` and `AudioPortAudio`. Note that sample track recording in the LMMS core is not completed before #7786 . This PR also removes the reading and saving of the channel number configuration in several places as it will default to `DEFAULT_CHANNELS` all the time anyway. Co-authored-by: Johannes Lorenz <j.git@lorenz-ho.me> Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
This commit is contained in:
@@ -53,11 +53,6 @@ namespace lmms
|
||||
|
||||
class MidiJack;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
class LcdSpinBox;
|
||||
}
|
||||
|
||||
|
||||
class AudioJack : public QObject, public AudioDevice
|
||||
{
|
||||
@@ -82,13 +77,10 @@ public:
|
||||
{
|
||||
public:
|
||||
setupWidget(QWidget* parent);
|
||||
~setupWidget() override;
|
||||
|
||||
void saveSettings() override;
|
||||
|
||||
private:
|
||||
QLineEdit* m_clientName;
|
||||
gui::LcdSpinBox* m_channels;
|
||||
};
|
||||
|
||||
private slots:
|
||||
@@ -96,6 +88,7 @@ private slots:
|
||||
|
||||
private:
|
||||
bool initJackClient();
|
||||
void resizeInputBuffer(jack_nframes_t nframes);
|
||||
|
||||
void startProcessing() override;
|
||||
void stopProcessing() override;
|
||||
@@ -116,8 +109,11 @@ private:
|
||||
|
||||
std::atomic<MidiJack*> m_midiClient;
|
||||
std::vector<jack_port_t*> m_outputPorts;
|
||||
std::vector<jack_port_t*> m_inputPorts;
|
||||
jack_default_audio_sample_t** m_tempOutBufs;
|
||||
std::vector<SampleFrame> m_inputFrameBuffer;
|
||||
SampleFrame* m_outBuf;
|
||||
SampleFrame* m_inBuf;
|
||||
|
||||
f_cnt_t m_framesDoneInCurBuf;
|
||||
f_cnt_t m_framesToDoInCurBuf;
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "ConfigManager.h"
|
||||
#include "Engine.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "LcdSpinBox.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MidiJack.h"
|
||||
|
||||
@@ -44,19 +43,14 @@ namespace lmms
|
||||
|
||||
AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam)
|
||||
: AudioDevice(
|
||||
// clang-format off
|
||||
std::clamp<int>(
|
||||
ConfigManager::inst()->value("audiojack", "channels").toInt(),
|
||||
DEFAULT_CHANNELS,
|
||||
DEFAULT_CHANNELS
|
||||
),
|
||||
// clang-format on
|
||||
DEFAULT_CHANNELS,
|
||||
audioEngineParam)
|
||||
, m_client(nullptr)
|
||||
, m_active(false)
|
||||
, 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 +60,8 @@ AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam)
|
||||
if (successful) {
|
||||
connect(this, SIGNAL(zombified()), this, SLOT(restartAfterZombified()), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
m_supportsCapture = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +86,7 @@ AudioJack::~AudioJack()
|
||||
delete[] m_tempOutBufs;
|
||||
|
||||
delete[] m_outBuf;
|
||||
delete[] m_inBuf;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +151,16 @@ bool AudioJack::initJackClient()
|
||||
clientName.toLatin1().constData(), jack_get_client_name(m_client));
|
||||
}
|
||||
|
||||
resizeInputBuffer(jack_get_buffer_size(m_client));
|
||||
|
||||
// set buffer-size callback
|
||||
jack_set_buffer_size_callback(m_client,
|
||||
[](jack_nframes_t nframes, void* udata) -> int {
|
||||
static_cast<AudioJack*>(udata)->resizeInputBuffer(nframes);
|
||||
return 0;
|
||||
},
|
||||
this);
|
||||
|
||||
// set process-callback
|
||||
jack_set_process_callback(m_client, staticProcessCallback, this);
|
||||
|
||||
@@ -167,6 +174,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");
|
||||
@@ -180,6 +191,14 @@ bool AudioJack::initJackClient()
|
||||
|
||||
|
||||
|
||||
void AudioJack::resizeInputBuffer(jack_nframes_t nframes)
|
||||
{
|
||||
m_inputFrameBuffer.resize(nframes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AudioJack::startProcessing()
|
||||
{
|
||||
if (m_active || m_client == nullptr)
|
||||
@@ -290,7 +309,6 @@ void AudioJack::renamePort(AudioBusHandle* port)
|
||||
|
||||
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][c] = static_cast<sample_t>(jack_input_buffer[frame]);
|
||||
}
|
||||
}
|
||||
audioEngine()->pushInputFrames (m_inputFrameBuffer.data(), nframes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -390,24 +418,6 @@ AudioJack::setupWidget::setupWidget(QWidget* parent)
|
||||
m_clientName = new QLineEdit(cn, this);
|
||||
|
||||
form->addRow(tr("Client name"), m_clientName);
|
||||
|
||||
auto m = new gui::LcdSpinBoxModel(/* this */);
|
||||
m->setRange(DEFAULT_CHANNELS, DEFAULT_CHANNELS);
|
||||
m->setStep(2);
|
||||
m->setValue(ConfigManager::inst()->value("audiojack", "channels").toInt());
|
||||
|
||||
m_channels = new gui::LcdSpinBox(1, this);
|
||||
m_channels->setModel(m);
|
||||
|
||||
form->addRow(tr("Channels"), m_channels);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AudioJack::setupWidget::~setupWidget()
|
||||
{
|
||||
delete m_channels->model();
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +426,6 @@ AudioJack::setupWidget::~setupWidget()
|
||||
void AudioJack::setupWidget::saveSettings()
|
||||
{
|
||||
ConfigManager::inst()->setValue("audiojack", "clientname", m_clientName->text());
|
||||
ConfigManager::inst()->setValue("audiojack", "channels", QString::number(m_channels->value<int>()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user