From 3aa1a5dafa9c54d23139ec833d5abd9de336e651 Mon Sep 17 00:00:00 2001 From: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com> Date: Fri, 28 Feb 2025 23:44:58 +0100 Subject: [PATCH] Rename `AudioPort` -> `AudioBusHandle` (#7712) No functional changes. --- include/AudioBusHandle.h | 110 ++++++++ include/AudioDevice.h | 10 +- include/AudioEngine.h | 12 +- include/AudioJack.h | 16 +- include/AudioPort.h | 139 ---------- include/InstrumentTrack.h | 8 +- include/PlayHandle.h | 14 +- include/SamplePlayHandle.h | 6 +- include/SampleTrack.h | 8 +- src/core/AudioBusHandle.cpp | 254 +++++++++++++++++++ src/core/AudioEngine.cpp | 40 +-- src/core/CMakeLists.txt | 2 +- src/core/InstrumentPlayHandle.cpp | 2 +- src/core/NotePlayHandle.cpp | 2 +- src/core/PresetPreviewPlayHandle.cpp | 2 +- src/core/SamplePlayHandle.cpp | 30 +-- src/core/audio/AudioDevice.cpp | 8 +- src/core/audio/AudioJack.cpp | 18 +- src/core/audio/AudioPort.cpp | 253 ------------------ src/gui/SampleTrackWindow.cpp | 2 +- src/gui/instrument/InstrumentTrackWindow.cpp | 12 +- src/tracks/InstrumentTrack.cpp | 57 ++--- src/tracks/SampleTrack.cpp | 38 +-- 23 files changed, 510 insertions(+), 533 deletions(-) create mode 100644 include/AudioBusHandle.h delete mode 100644 include/AudioPort.h create mode 100644 src/core/AudioBusHandle.cpp delete mode 100644 src/core/audio/AudioPort.cpp diff --git a/include/AudioBusHandle.h b/include/AudioBusHandle.h new file mode 100644 index 000000000..c58cb9379 --- /dev/null +++ b/include/AudioBusHandle.h @@ -0,0 +1,110 @@ +/* + * AudioBusHandle.h - ThreadableJob between PlayHandle and MixerChannel + * + * Copyright (c) 2005-2014 Tobias Doerffel + * Copyright (c) 2025 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef LMMS_AUDIO_BUS_HANDLE_H +#define LMMS_AUDIO_BUS_HANDLE_H + +#include +#include +#include + +#include "PlayHandle.h" + +namespace lmms +{ + +class EffectChain; +class FloatModel; +class BoolModel; + +/** + @brief Job between @ref PlayHandle and @ref MixerChannel + + A @ref ThreadableJob class located at the exit point of each @ref PlayHandle into a @ref MixerChannel + (or into an audio device, in case of @ref AudioJack, but this is not supported in AudioBusHandle yet). + It contains an optional @ref EffectChain which is e.g. visualized in the + @ref InstrumentTrackWindow or @ref SampleTrackWindow. + For processing, it adds all input play handles into an internal buffer, + processes the @ref EffectChain (if existing) on that buffer + and finally merges the buffer into its @ref MixerChannel. +*/ +class AudioBusHandle : public ThreadableJob +{ +public: + AudioBusHandle(const QString& name, bool hasEffectChain = true, + FloatModel* volumeModel = nullptr, FloatModel* panningModel = nullptr, + BoolModel* mutedModel = nullptr); + virtual ~AudioBusHandle(); + + SampleFrame* buffer() { return m_buffer; } + + // indicate whether JACK & Co should provide output-buffer at ext. port + bool extOutputEnabled() const { return m_extOutputEnabled; } + void setExtOutputEnabled(bool enabled); + + // next mixer-channel after this audio-bus-handle + // (-1 = none 0 = master) + mix_ch_t nextMixerChannel() const { return m_nextMixerChannel; } + void setNextMixerChannel(const mix_ch_t chnl) { m_nextMixerChannel = chnl; } + + const QString& name() const { return m_name; } + void setName(const QString& newName); + + EffectChain* effects() { return m_effects.get(); } + bool processEffects(); + + // ThreadableJob stuff + void doProcessing() override; + bool requiresProcessing() const override { return true; } + + void addPlayHandle(PlayHandle* handle); + void removePlayHandle(PlayHandle* handle); + +private: + volatile bool m_bufferUsage; + + SampleFrame* const m_buffer; + + bool m_extOutputEnabled; + mix_ch_t m_nextMixerChannel; + + QString m_name; + + std::unique_ptr m_effects; + + PlayHandleList m_playHandles; + QMutex m_playHandleLock; + + FloatModel* m_volumeModel; + FloatModel* m_panningModel; + BoolModel* m_mutedModel; + + friend class AudioEngine; + friend class AudioEngineWorkerThread; +}; + +} // namespace lmms + +#endif // LMMS_AUDIO_BUS_HANDLE_H diff --git a/include/AudioDevice.h b/include/AudioDevice.h index 80e392450..228b1c1aa 100644 --- a/include/AudioDevice.h +++ b/include/AudioDevice.h @@ -36,7 +36,7 @@ namespace lmms { class AudioEngine; -class AudioPort; +class AudioBusHandle; class SampleFrame; @@ -57,13 +57,13 @@ public: } - // if audio-driver supports ports, classes inherting AudioPort + // if audio-driver supports ports, classes inherting AudioBusHandle // (e.g. channel-tracks) can register themselves for making // audio-driver able to collect their individual output and provide // them at a specific port - currently only supported by JACK - virtual void registerPort( AudioPort * _port ); - virtual void unregisterPort( AudioPort * _port ); - virtual void renamePort( AudioPort * _port ); + virtual void registerPort(AudioBusHandle* port); + virtual void unregisterPort(AudioBusHandle* port); + virtual void renamePort(AudioBusHandle* port); inline bool supportsCapture() const { diff --git a/include/AudioEngine.h b/include/AudioEngine.h index b22830221..13758284d 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -47,7 +47,7 @@ namespace lmms class AudioDevice; class MidiClient; -class AudioPort; +class AudioBusHandle; class AudioEngineWorkerThread; @@ -172,15 +172,15 @@ public: } - // audio-port-stuff - inline void addAudioPort(AudioPort * port) + // audio-bus-handle-stuff + inline void addAudioBusHandle(AudioBusHandle* busHandle) { requestChangeInModel(); - m_audioPorts.push_back(port); + m_audioBusHandles.push_back(busHandle); doneChangeInModel(); } - void removeAudioPort(AudioPort * port); + void removeAudioBusHandle(AudioBusHandle* busHandle); // MIDI-client-stuff @@ -366,7 +366,7 @@ private: bool m_renderOnly; - std::vector m_audioPorts; + std::vector m_audioBusHandles; fpp_t m_framesPerPeriod; diff --git a/include/AudioJack.h b/include/AudioJack.h index 234f6ebf2..e13b4a5ef 100644 --- a/include/AudioJack.h +++ b/include/AudioJack.h @@ -36,9 +36,15 @@ #include #include +#ifdef AUDIO_BUS_HANDLE_SUPPORT +#include +#endif #include "AudioDevice.h" #include "AudioDeviceSetupWidget.h" +#ifdef AUDIO_BUS_HANDLE_SUPPORT +#include "AudioBusHandle.h" +#endif class QLineEdit; @@ -94,9 +100,9 @@ private: void startProcessing() override; void stopProcessing() override; - void registerPort(AudioPort* port) override; - void unregisterPort(AudioPort* port) override; - void renamePort(AudioPort* port) override; + void registerPort(AudioBusHandle* port) override; + void unregisterPort(AudioBusHandle* port) override; + void renamePort(AudioBusHandle* port) override; int processCallback(jack_nframes_t nframes); @@ -116,13 +122,13 @@ private: f_cnt_t m_framesDoneInCurBuf; f_cnt_t m_framesToDoInCurBuf; -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT struct StereoPort { jack_port_t* ports[2]; }; - using JackPortMap = QMap; + using JackPortMap = QMap; JackPortMap m_portMap; #endif diff --git a/include/AudioPort.h b/include/AudioPort.h deleted file mode 100644 index 12a0ec7d8..000000000 --- a/include/AudioPort.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * AudioPort.h - base-class for objects providing sound at a port - * - * Copyright (c) 2005-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#ifndef LMMS_AUDIO_PORT_H -#define LMMS_AUDIO_PORT_H - -#include -#include -#include - -#include "PlayHandle.h" - -namespace lmms -{ - -class EffectChain; -class FloatModel; -class BoolModel; - -class AudioPort : public ThreadableJob -{ -public: - AudioPort( const QString & _name, bool _has_effect_chain = true, - FloatModel * volumeModel = nullptr, FloatModel * panningModel = nullptr, - BoolModel * mutedModel = nullptr ); - virtual ~AudioPort(); - - inline SampleFrame* buffer() - { - return m_portBuffer; - } - - inline void lockBuffer() - { - m_portBufferLock.lock(); - } - - inline void unlockBuffer() - { - m_portBufferLock.unlock(); - } - - - // indicate whether JACK & Co should provide output-buffer at ext. port - inline bool extOutputEnabled() const - { - return m_extOutputEnabled; - } - - void setExtOutputEnabled( bool _enabled ); - - - // next mixer-channel after this audio-port - // (-1 = none 0 = master) - inline mix_ch_t nextMixerChannel() const - { - return m_nextMixerChannel; - } - - inline EffectChain * effects() - { - return m_effects.get(); - } - - void setNextMixerChannel( const mix_ch_t _chnl ) - { - m_nextMixerChannel = _chnl; - } - - - const QString & name() const - { - return m_name; - } - - void setName( const QString & _new_name ); - - - bool processEffects(); - - // ThreadableJob stuff - void doProcessing() override; - bool requiresProcessing() const override - { - return true; - } - - void addPlayHandle( PlayHandle * handle ); - void removePlayHandle( PlayHandle * handle ); - -private: - volatile bool m_bufferUsage; - - SampleFrame* m_portBuffer; - QMutex m_portBufferLock; - - bool m_extOutputEnabled; - mix_ch_t m_nextMixerChannel; - - QString m_name; - - std::unique_ptr m_effects; - - PlayHandleList m_playHandles; - QMutex m_playHandleLock; - - FloatModel * m_volumeModel; - FloatModel * m_panningModel; - BoolModel * m_mutedModel; - - friend class AudioEngine; - friend class AudioEngineWorkerThread; - -} ; - -} // namespace lmms - -#endif // LMMS_AUDIO_PORT_H diff --git a/include/InstrumentTrack.h b/include/InstrumentTrack.h index 689c962cd..17d3233da 100644 --- a/include/InstrumentTrack.h +++ b/include/InstrumentTrack.h @@ -28,7 +28,7 @@ #include -#include "AudioPort.h" +#include "AudioBusHandle.h" #include "InstrumentFunctions.h" #include "InstrumentSoundShaping.h" #include "Microtuner.h" @@ -144,9 +144,9 @@ public: const Plugin::Descriptor::SubPluginFeatures::Key* key = nullptr, bool keyFromDnd = false); - AudioPort * audioPort() + AudioBusHandle* audioBusHandle() { - return &m_audioPort; + return &m_audioBusHandle; } MidiPort * midiPort() @@ -293,7 +293,7 @@ private: FloatModel m_volumeModel; FloatModel m_panningModel; - AudioPort m_audioPort; + AudioBusHandle m_audioBusHandle; FloatModel m_pitchModel; IntModel m_pitchRangeModel; diff --git a/include/PlayHandle.h b/include/PlayHandle.h index f2e87136a..5f0256a1a 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -40,7 +40,7 @@ namespace lmms { class Track; -class AudioPort; +class AudioBusHandle; class SampleFrame; class LMMS_EXPORT PlayHandle : public ThreadableJob @@ -65,7 +65,7 @@ public: m_offset = p.m_offset; m_affinity = p.m_affinity; m_usesBuffer = p.m_usesBuffer; - m_audioPort = p.m_audioPort; + m_audioBusHandle = p.m_audioBusHandle; return *this; } @@ -134,14 +134,14 @@ public: m_usesBuffer = b; } - AudioPort * audioPort() + AudioBusHandle* audioBusHandle() { - return m_audioPort; + return m_audioBusHandle; } - void setAudioPort( AudioPort * port ) + void setAudioBusHandle(AudioBusHandle* busHandle) { - m_audioPort = port; + m_audioBusHandle = busHandle; } void releaseBuffer(); @@ -156,7 +156,7 @@ private: SampleFrame* m_playHandleBuffer; bool m_bufferReleased; bool m_usesBuffer; - AudioPort * m_audioPort; + AudioBusHandle* m_audioBusHandle; } ; using PlayHandleList = QList; diff --git a/include/SamplePlayHandle.h b/include/SamplePlayHandle.h index dde29b49b..b3fddd503 100644 --- a/include/SamplePlayHandle.h +++ b/include/SamplePlayHandle.h @@ -38,13 +38,13 @@ namespace lmms class PatternTrack; class SampleClip; class Track; -class AudioPort; +class AudioBusHandle; class LMMS_EXPORT SamplePlayHandle : public PlayHandle { public: - SamplePlayHandle(Sample* sample, bool ownAudioPort = true); + SamplePlayHandle(Sample* sample, bool ownAudioBusHandle = true); SamplePlayHandle( const QString& sampleFile ); SamplePlayHandle( SampleClip* clip ); ~SamplePlayHandle() override; @@ -88,7 +88,7 @@ private: f_cnt_t m_frame; Sample::PlaybackState m_state; - const bool m_ownAudioPort; + const bool m_ownAudioBusHandle; FloatModel m_defaultVolumeModel; FloatModel * m_volumeModel; diff --git a/include/SampleTrack.h b/include/SampleTrack.h index e79df0c2c..d333cd593 100644 --- a/include/SampleTrack.h +++ b/include/SampleTrack.h @@ -25,7 +25,7 @@ #ifndef LMMS_SAMPLE_TRACK_H #define LMMS_SAMPLE_TRACK_H -#include "AudioPort.h" +#include "AudioBusHandle.h" #include "Track.h" @@ -62,9 +62,9 @@ public: return &m_mixerChannelModel; } - inline AudioPort * audioPort() + inline AudioBusHandle* audioBusHandle() { - return &m_audioPort; + return &m_audioBusHandle; } QString nodeName() const override @@ -95,7 +95,7 @@ private: FloatModel m_volumeModel; FloatModel m_panningModel; IntModel m_mixerChannelModel; - AudioPort m_audioPort; + AudioBusHandle m_audioBusHandle; bool m_isPlaying; diff --git a/src/core/AudioBusHandle.cpp b/src/core/AudioBusHandle.cpp new file mode 100644 index 000000000..e27a8c8ad --- /dev/null +++ b/src/core/AudioBusHandle.cpp @@ -0,0 +1,254 @@ +/* + * AudioBusHandle.cpp - ThreadableJob between PlayHandle and MixerChannel + * + * Copyright (c) 2004-2014 Tobias Doerffel + * Copyright (c) 2025 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include + +#include "AudioBusHandle.h" +#include "AudioDevice.h" +#include "AudioEngine.h" +#include "EffectChain.h" +#include "Mixer.h" +#include "Engine.h" +#include "MixHelpers.h" +#include "BufferManager.h" + +namespace lmms +{ + +AudioBusHandle::AudioBusHandle(const QString& name, bool hasEffectChain, + FloatModel* volumeModel, FloatModel* panningModel, + BoolModel* mutedModel) : + m_bufferUsage(false), + m_buffer(BufferManager::acquire()), + m_extOutputEnabled(false), + m_nextMixerChannel(0), + m_name(name), + m_effects(hasEffectChain ? new EffectChain(nullptr) : nullptr), + m_volumeModel(volumeModel), + m_panningModel(panningModel), + m_mutedModel(mutedModel) +{ + Engine::audioEngine()->addAudioBusHandle(this); + setExtOutputEnabled(true); +} + + + + +AudioBusHandle::~AudioBusHandle() +{ + setExtOutputEnabled(false); + Engine::audioEngine()->removeAudioBusHandle(this); + BufferManager::release(m_buffer); +} + + + + +void AudioBusHandle::setExtOutputEnabled(bool enabled) +{ + if (enabled != m_extOutputEnabled) + { + m_extOutputEnabled = enabled; + if (m_extOutputEnabled) + { + Engine::audioEngine()->audioDev()->registerPort(this); + } + else + { + Engine::audioEngine()->audioDev()->unregisterPort(this); + } + } +} + + + + +void AudioBusHandle::setName(const QString& newName) +{ + m_name = newName; + Engine::audioEngine()->audioDev()->renamePort(this); +} + + + + +bool AudioBusHandle::processEffects() +{ + if (m_effects) + { + bool more = m_effects->processAudioBuffer(m_buffer, Engine::audioEngine()->framesPerPeriod(), m_bufferUsage); + return more; + } + return false; +} + + +void AudioBusHandle::doProcessing() +{ + if (m_mutedModel && m_mutedModel->value()) + { + return; + } + + const fpp_t fpp = Engine::audioEngine()->framesPerPeriod(); + + // clear the buffer + zeroSampleFrames(m_buffer, fpp); + + //qDebug( "Playhandles: %d", m_playHandles.size() ); + for (PlayHandle* ph : m_playHandles) // now we mix all playhandle buffers into our internal buffer + { + if (ph->buffer()) + { + if (ph->usesBuffer() + && (ph->type() == PlayHandle::Type::NotePlayHandle + || !MixHelpers::isSilent(ph->buffer(), fpp))) + { + m_bufferUsage = true; + MixHelpers::add(m_buffer, ph->buffer(), fpp); + } + ph->releaseBuffer(); // gets rid of playhandle's buffer and sets + // pointer to null, so if it doesn't get re-acquired we know to skip it next time + } + } + + if (m_bufferUsage) + { + // handle volume and panning + // has both vol and pan models + if (m_volumeModel && m_panningModel) + { + ValueBuffer* volBuf = m_volumeModel->valueBuffer(); + ValueBuffer* panBuf = m_panningModel->valueBuffer(); + + // both vol and pan have s.ex.data: + if (volBuf && panBuf) + { + for (f_cnt_t f = 0; f < fpp; ++f) + { + float v = volBuf->values()[f] * 0.01f; + float p = panBuf->values()[f] * 0.01f; + m_buffer[f][0] *= (p <= 0 ? 1.0f : 1.0f - p) * v; + m_buffer[f][1] *= (p >= 0 ? 1.0f : 1.0f + p) * v; + } + } + + // only vol has s.ex.data: + else if (volBuf) + { + float p = m_panningModel->value() * 0.01f; + float l = (p <= 0 ? 1.0f : 1.0f - p); + float r = (p >= 0 ? 1.0f : 1.0f + p); + for (f_cnt_t f = 0; f < fpp; ++f) + { + float v = volBuf->values()[f] * 0.01f; + m_buffer[f][0] *= v * l; + m_buffer[f][1] *= v * r; + } + } + + // only pan has s.ex.data: + else if (panBuf) + { + float v = m_volumeModel->value() * 0.01f; + for (f_cnt_t f = 0; f < fpp; ++f) + { + float p = panBuf->values()[f] * 0.01f; + m_buffer[f][0] *= (p <= 0 ? 1.0f : 1.0f - p) * v; + m_buffer[f][1] *= (p >= 0 ? 1.0f : 1.0f + p) * v; + } + } + + // neither has s.ex.data: + else + { + float p = m_panningModel->value() * 0.01f; + float v = m_volumeModel->value() * 0.01f; + for (f_cnt_t f = 0; f < fpp; ++f) + { + m_buffer[f][0] *= (p <= 0 ? 1.0f : 1.0f - p) * v; + m_buffer[f][1] *= (p >= 0 ? 1.0f : 1.0f + p) * v; + } + } + } + + // has vol model only + else if (m_volumeModel) + { + ValueBuffer* volBuf = m_volumeModel->valueBuffer(); + + if (volBuf) + { + for (f_cnt_t f = 0; f < fpp; ++f) + { + float v = volBuf->values()[f] * 0.01f; + m_buffer[f][0] *= v; + m_buffer[f][1] *= v; + } + } + else + { + float v = m_volumeModel->value() * 0.01f; + for (f_cnt_t f = 0; f < fpp; ++f) + { + m_buffer[f][0] *= v; + m_buffer[f][1] *= v; + } + } + } + } + // as of now there's no situation where we only have panning model but no volume model + // if we have neither, we don't have to do anything here - just pass the audio as is + + // handle effects + const bool anyOutputAfterEffects = processEffects(); + if (anyOutputAfterEffects || m_bufferUsage) + { + Engine::mixer()->mixToChannel(m_buffer, m_nextMixerChannel); // send output to mixer + // TODO: improve the flow here - convert to pull model + m_bufferUsage = false; + } +} + + +void AudioBusHandle::addPlayHandle(PlayHandle* handle) +{ + QMutexLocker lockGuard(&m_playHandleLock); + m_playHandles.append(handle); +} + + +void AudioBusHandle::removePlayHandle(PlayHandle* handle) +{ + QMutexLocker lockGuard(&m_playHandleLock); + PlayHandleList::Iterator it = std::find(m_playHandles.begin(), m_playHandles.end(), handle); + if (it != m_playHandles.end()) + { + m_playHandles.erase(it); + } +} + +} // namespace lmms diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 435fa38fa..8dcc37434 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -30,7 +30,7 @@ #include "lmmsconfig.h" #include "AudioEngineWorkerThread.h" -#include "AudioPort.h" +#include "AudioBusHandle.h" #include "Mixer.h" #include "Song.h" #include "EnvelopeAndLfoParameters.h" @@ -299,13 +299,13 @@ void AudioEngine::renderStageNoteSetup() if( it != m_playHandles.end() ) { - ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) + (*it)->audioBusHandle()->removePlayHandle(*it); + if((*it)->type() == PlayHandle::Type::NotePlayHandle) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandleManager::release((NotePlayHandle*)*it); } else delete *it; - m_playHandles.erase( it ); + m_playHandles.erase(it); } it_rem = m_playHandlesToRemove.erase( it_rem ); @@ -347,7 +347,7 @@ void AudioEngine::renderStageEffects() AudioEngineProfiler::Probe profilerProbe(m_profiler, AudioEngineProfiler::DetailType::Effects); // STAGE 2: process effects of all instrument- and sampletracks - AudioEngineWorkerThread::fillJobQueue(m_audioPorts); + AudioEngineWorkerThread::fillJobQueue(m_audioBusHandles); AudioEngineWorkerThread::startAndWaitForJobs(); // removed all play handles which are done @@ -362,13 +362,13 @@ void AudioEngine::renderStageEffects() } if( ( *it )->isFinished() ) { - ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) + (*it)->audioBusHandle()->removePlayHandle(*it); + if((*it)->type() == PlayHandle::Type::NotePlayHandle) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandleManager::release((NotePlayHandle*)*it); } else delete *it; - it = m_playHandles.erase( it ); + it = m_playHandles.erase(it); } else { @@ -556,14 +556,14 @@ void AudioEngine::restoreAudioDevice() -void AudioEngine::removeAudioPort(AudioPort * port) +void AudioEngine::removeAudioBusHandle(AudioBusHandle* busHandle) { requestChangeInModel(); - auto it = std::find(m_audioPorts.begin(), m_audioPorts.end(), port); - if (it != m_audioPorts.end()) + auto it = std::find(m_audioBusHandles.begin(), m_audioBusHandles.end(), busHandle); + if (it != m_audioBusHandles.end()) { - m_audioPorts.erase(it); + m_audioBusHandles.erase(it); } doneChangeInModel(); } @@ -577,7 +577,7 @@ bool AudioEngine::addPlayHandle( PlayHandle* handle ) if (handle->type() == PlayHandle::Type::InstrumentPlayHandle || !criticalXRuns()) { m_newPlayHandles.push( handle ); - handle->audioPort()->addPlayHandle( handle ); + handle->audioBusHandle()->addPlayHandle(handle); return true; } @@ -598,7 +598,7 @@ void AudioEngine::removePlayHandle(PlayHandle * ph) // which were created in a thread different than the audio engine thread if (ph->affinityMatters() && ph->affinity() == QThread::currentThread()) { - ph->audioPort()->removePlayHandle(ph); + ph->audioBusHandle()->removePlayHandle(ph); bool removedFromList = false; // Check m_newPlayHandles first because doing it the other way around // creates a race condition @@ -657,13 +657,13 @@ void AudioEngine::removePlayHandlesOfTypes(Track * track, PlayHandle::Types type { if ((*it)->isFromTrack(track) && ((*it)->type() & types)) { - ( *it )->audioPort()->removePlayHandle( ( *it ) ); - if( ( *it )->type() == PlayHandle::Type::NotePlayHandle ) + (*it)->audioBusHandle()->removePlayHandle(*it); + if((*it)->type() == PlayHandle::Type::NotePlayHandle) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandleManager::release((NotePlayHandle*)*it); } else delete *it; - it = m_playHandles.erase( it ); + it = m_playHandles.erase(it); } else { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1e2c4f3cf..74e3bf1b5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,6 +1,7 @@ set(LMMS_SRCS ${LMMS_SRCS} + core/AudioBusHandle.cpp core/AudioEngine.cpp core/AudioEngineProfiler.cpp core/AudioEngineWorkerThread.cpp @@ -100,7 +101,6 @@ set(LMMS_SRCS core/audio/AudioJack.cpp core/audio/AudioOss.cpp core/audio/AudioSndio.cpp - core/audio/AudioPort.cpp core/audio/AudioPortAudio.cpp core/audio/AudioSoundIo.cpp core/audio/AudioPulseAudio.cpp diff --git a/src/core/InstrumentPlayHandle.cpp b/src/core/InstrumentPlayHandle.cpp index afae852a0..0405944a9 100644 --- a/src/core/InstrumentPlayHandle.cpp +++ b/src/core/InstrumentPlayHandle.cpp @@ -37,7 +37,7 @@ InstrumentPlayHandle::InstrumentPlayHandle(Instrument * instrument, InstrumentTr PlayHandle(Type::InstrumentPlayHandle), m_instrument(instrument) { - setAudioPort(instrumentTrack->audioPort()); + setAudioBusHandle(instrumentTrack->audioBusHandle()); } void InstrumentPlayHandle::play(SampleFrame* working_buffer) diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 326e63eaf..0c27529df 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -114,7 +114,7 @@ NotePlayHandle::NotePlayHandle( InstrumentTrack* instrumentTrack, setUsesBuffer( false ); } - setAudioPort( instrumentTrack->audioPort() ); + setAudioBusHandle(instrumentTrack->audioBusHandle()); unlock(); } diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index e7e67185e..1d6b00e4f 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -178,7 +178,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, std::numeric_limits::max() / 2, Note( 0, 0, DefaultKey, 100 ) ); - setAudioPort( s_previewTC->previewInstrumentTrack()->audioPort() ); + setAudioBusHandle(s_previewTC->previewInstrumentTrack()->audioBusHandle()); s_previewTC->setPreviewNote( m_previewNote ); diff --git a/src/core/SamplePlayHandle.cpp b/src/core/SamplePlayHandle.cpp index f2ddc2a4a..eed727fc1 100644 --- a/src/core/SamplePlayHandle.cpp +++ b/src/core/SamplePlayHandle.cpp @@ -24,7 +24,7 @@ #include "SamplePlayHandle.h" #include "AudioEngine.h" -#include "AudioPort.h" +#include "AudioBusHandle.h" #include "Engine.h" #include "Note.h" #include "PatternTrack.h" @@ -35,20 +35,20 @@ namespace lmms { -SamplePlayHandle::SamplePlayHandle(Sample* sample, bool ownAudioPort) : - PlayHandle( Type::SamplePlayHandle ), +SamplePlayHandle::SamplePlayHandle(Sample* sample, bool ownAudioBusHandle) : + PlayHandle(Type::SamplePlayHandle), m_sample(sample), - m_doneMayReturnTrue( true ), - m_frame( 0 ), - m_ownAudioPort( ownAudioPort ), - m_defaultVolumeModel( DefaultVolume, MinVolume, MaxVolume, 1 ), - m_volumeModel( &m_defaultVolumeModel ), - m_track( nullptr ), - m_patternTrack( nullptr ) + m_doneMayReturnTrue(true), + m_frame(0), + m_ownAudioBusHandle(ownAudioBusHandle), + m_defaultVolumeModel(DefaultVolume, MinVolume, MaxVolume, 1), + m_volumeModel(&m_defaultVolumeModel), + m_track(nullptr), + m_patternTrack(nullptr) { - if (ownAudioPort) + if (ownAudioBusHandle) { - setAudioPort( new AudioPort( "SamplePlayHandle", false ) ); + setAudioBusHandle(new AudioBusHandle("SamplePlayHandle", false)); } } @@ -67,7 +67,7 @@ SamplePlayHandle::SamplePlayHandle( SampleClip* clip ) : SamplePlayHandle(&clip->sample(), false) { m_track = clip->getTrack(); - setAudioPort( ( (SampleTrack *)clip->getTrack() )->audioPort() ); + setAudioBusHandle(((SampleTrack *)clip->getTrack())->audioBusHandle()); } @@ -75,9 +75,9 @@ SamplePlayHandle::SamplePlayHandle( SampleClip* clip ) : SamplePlayHandle::~SamplePlayHandle() { - if( m_ownAudioPort ) + if(m_ownAudioBusHandle) { - delete audioPort(); + delete audioBusHandle(); delete m_sample; } } diff --git a/src/core/audio/AudioDevice.cpp b/src/core/audio/AudioDevice.cpp index 2047fffe9..c02ce5f99 100644 --- a/src/core/audio/AudioDevice.cpp +++ b/src/core/audio/AudioDevice.cpp @@ -109,21 +109,21 @@ void AudioDevice::stopProcessingThread( QThread * thread ) -void AudioDevice::registerPort( AudioPort * ) +void AudioDevice::registerPort(AudioBusHandle*) { } -void AudioDevice::unregisterPort( AudioPort * _port ) +void AudioDevice::unregisterPort(AudioBusHandle*) { } -void AudioDevice::renamePort( AudioPort * ) +void AudioDevice::renamePort(AudioBusHandle*) { } @@ -172,4 +172,4 @@ void AudioDevice::clearS16Buffer( int_sample_t * _outbuf, const fpp_t _frames ) memset( _outbuf, 0, _frames * channels() * BYTES_PER_INT_SAMPLE ); } -} // namespace lmms \ No newline at end of file +} // namespace lmms diff --git a/src/core/audio/AudioJack.cpp b/src/core/audio/AudioJack.cpp index bd5b8e514..b6da7c845 100644 --- a/src/core/audio/AudioJack.cpp +++ b/src/core/audio/AudioJack.cpp @@ -74,7 +74,7 @@ AudioJack::AudioJack(bool& successful, AudioEngine* audioEngineParam) AudioJack::~AudioJack() { AudioJack::stopProcessing(); -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT while (m_portMap.size()) { unregisterPort(m_portMap.begin().key()); @@ -229,9 +229,9 @@ void AudioJack::stopProcessing() m_stopped = true; } -void AudioJack::registerPort(AudioPort* port) +void AudioJack::registerPort(AudioBusHandle* port) { -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT // make sure, port is not already registered unregisterPort(port); const QString name[2] = {port->name() + " L", port->name() + " R"}; @@ -249,9 +249,9 @@ void AudioJack::registerPort(AudioPort* port) -void AudioJack::unregisterPort(AudioPort* port) +void AudioJack::unregisterPort(AudioBusHandle* port) { -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT if (m_portMap.contains(port)) { for (ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch) @@ -265,9 +265,9 @@ void AudioJack::unregisterPort(AudioPort* port) #endif } -void AudioJack::renamePort(AudioPort* port) +void AudioJack::renamePort(AudioBusHandle* port) { -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT if (m_portMap.contains(port)) { const QString name[2] = {port->name() + " L", port->name() + " R"}; @@ -282,7 +282,7 @@ void AudioJack::renamePort(AudioPort* port) } #else (void)port; -#endif // AUDIO_PORT_SUPPORT +#endif // AUDIO_BUS_HANDLE_SUPPORT } @@ -304,7 +304,7 @@ int AudioJack::processCallback(jack_nframes_t nframes) m_tempOutBufs[c] = (jack_default_audio_sample_t*)jack_port_get_buffer(m_outputPorts[c], nframes); } -#ifdef AUDIO_PORT_SUPPORT +#ifdef AUDIO_BUS_HANDLE_SUPPORT const int frames = std::min(nframes, audioEngine()->framesPerPeriod()); for (JackPortMap::iterator it = m_portMap.begin(); it != m_portMap.end(); ++it) { diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp deleted file mode 100644 index 8efdd2c11..000000000 --- a/src/core/audio/AudioPort.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * AudioPort.cpp - base-class for objects providing sound at a port - * - * Copyright (c) 2004-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "AudioPort.h" -#include "AudioDevice.h" -#include "AudioEngine.h" -#include "EffectChain.h" -#include "Mixer.h" -#include "Engine.h" -#include "MixHelpers.h" -#include "BufferManager.h" - -namespace lmms -{ - -AudioPort::AudioPort( const QString & _name, bool _has_effect_chain, - FloatModel * volumeModel, FloatModel * panningModel, - BoolModel * mutedModel ) : - m_bufferUsage( false ), - m_portBuffer( BufferManager::acquire() ), - m_extOutputEnabled( false ), - m_nextMixerChannel( 0 ), - m_name( "unnamed port" ), - m_effects( _has_effect_chain ? new EffectChain( nullptr ) : nullptr ), - m_volumeModel( volumeModel ), - m_panningModel( panningModel ), - m_mutedModel( mutedModel ) -{ - Engine::audioEngine()->addAudioPort( this ); - setExtOutputEnabled( true ); -} - - - - -AudioPort::~AudioPort() -{ - setExtOutputEnabled( false ); - Engine::audioEngine()->removeAudioPort( this ); - BufferManager::release( m_portBuffer ); -} - - - - -void AudioPort::setExtOutputEnabled( bool _enabled ) -{ - if( _enabled != m_extOutputEnabled ) - { - m_extOutputEnabled = _enabled; - if( m_extOutputEnabled ) - { - Engine::audioEngine()->audioDev()->registerPort( this ); - } - else - { - Engine::audioEngine()->audioDev()->unregisterPort( this ); - } - } -} - - - - -void AudioPort::setName( const QString & _name ) -{ - m_name = _name; - Engine::audioEngine()->audioDev()->renamePort( this ); -} - - - - -bool AudioPort::processEffects() -{ - if( m_effects ) - { - bool more = m_effects->processAudioBuffer( m_portBuffer, Engine::audioEngine()->framesPerPeriod(), m_bufferUsage ); - return more; - } - return false; -} - - -void AudioPort::doProcessing() -{ - if( m_mutedModel && m_mutedModel->value() ) - { - return; - } - - const fpp_t fpp = Engine::audioEngine()->framesPerPeriod(); - - // clear the buffer - zeroSampleFrames(m_portBuffer, fpp); - - //qDebug( "Playhandles: %d", m_playHandles.size() ); - for( PlayHandle * ph : m_playHandles ) // now we mix all playhandle buffers into the audioport buffer - { - if( ph->buffer() ) - { - if( ph->usesBuffer() - && ( ph->type() == PlayHandle::Type::NotePlayHandle - || !MixHelpers::isSilent( ph->buffer(), fpp ) ) ) - { - m_bufferUsage = true; - MixHelpers::add( m_portBuffer, ph->buffer(), fpp ); - } - ph->releaseBuffer(); // gets rid of playhandle's buffer and sets - // pointer to null, so if it doesn't get re-acquired we know to skip it next time - } - } - - if( m_bufferUsage ) - { - // handle volume and panning - // has both vol and pan models - if( m_volumeModel && m_panningModel ) - { - ValueBuffer * volBuf = m_volumeModel->valueBuffer(); - ValueBuffer * panBuf = m_panningModel->valueBuffer(); - - // both vol and pan have s.ex.data: - if( volBuf && panBuf ) - { - for( f_cnt_t f = 0; f < fpp; ++f ) - { - float v = volBuf->values()[ f ] * 0.01f; - float p = panBuf->values()[ f ] * 0.01f; - m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; - m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; - } - } - - // only vol has s.ex.data: - else if( volBuf ) - { - float p = m_panningModel->value() * 0.01f; - float l = ( p <= 0 ? 1.0f : 1.0f - p ); - float r = ( p >= 0 ? 1.0f : 1.0f + p ); - for( f_cnt_t f = 0; f < fpp; ++f ) - { - float v = volBuf->values()[ f ] * 0.01f; - m_portBuffer[f][0] *= v * l; - m_portBuffer[f][1] *= v * r; - } - } - - // only pan has s.ex.data: - else if( panBuf ) - { - float v = m_volumeModel->value() * 0.01f; - for( f_cnt_t f = 0; f < fpp; ++f ) - { - float p = panBuf->values()[ f ] * 0.01f; - m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; - m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; - } - } - - // neither has s.ex.data: - else - { - float p = m_panningModel->value() * 0.01f; - float v = m_volumeModel->value() * 0.01f; - for( f_cnt_t f = 0; f < fpp; ++f ) - { - m_portBuffer[f][0] *= ( p <= 0 ? 1.0f : 1.0f - p ) * v; - m_portBuffer[f][1] *= ( p >= 0 ? 1.0f : 1.0f + p ) * v; - } - } - } - - // has vol model only - else if( m_volumeModel ) - { - ValueBuffer * volBuf = m_volumeModel->valueBuffer(); - - if( volBuf ) - { - for( f_cnt_t f = 0; f < fpp; ++f ) - { - float v = volBuf->values()[ f ] * 0.01f; - m_portBuffer[f][0] *= v; - m_portBuffer[f][1] *= v; - } - } - else - { - float v = m_volumeModel->value() * 0.01f; - for( f_cnt_t f = 0; f < fpp; ++f ) - { - m_portBuffer[f][0] *= v; - m_portBuffer[f][1] *= v; - } - } - } - } - // as of now there's no situation where we only have panning model but no volume model - // if we have neither, we don't have to do anything here - just pass the audio as is - - // handle effects - const bool me = processEffects(); - if( me || m_bufferUsage ) - { - Engine::mixer()->mixToChannel( m_portBuffer, m_nextMixerChannel ); // send output to mixer - // TODO: improve the flow here - convert to pull model - m_bufferUsage = false; - } -} - - -void AudioPort::addPlayHandle( PlayHandle * handle ) -{ - m_playHandleLock.lock(); - m_playHandles.append( handle ); - m_playHandleLock.unlock(); -} - - -void AudioPort::removePlayHandle( PlayHandle * handle ) -{ - m_playHandleLock.lock(); - PlayHandleList::Iterator it = std::find( m_playHandles.begin(), m_playHandles.end(), handle ); - if( it != m_playHandles.end() ) - { - m_playHandles.erase( it ); - } - m_playHandleLock.unlock(); -} - -} // namespace lmms \ No newline at end of file diff --git a/src/gui/SampleTrackWindow.cpp b/src/gui/SampleTrackWindow.cpp index 1c7a56828..644ad291d 100644 --- a/src/gui/SampleTrackWindow.cpp +++ b/src/gui/SampleTrackWindow.cpp @@ -139,7 +139,7 @@ SampleTrackWindow::SampleTrackWindow(SampleTrackView * tv) : generalSettingsLayout->addLayout(basicControlsLayout); - m_effectRack = new EffectRackView(tv->model()->audioPort()->effects()); + m_effectRack = new EffectRackView(tv->model()->audioBusHandle()->effects()); m_effectRack->setFixedSize(EffectRackView::DEFAULT_WIDTH, 242); vlayout->addWidget(generalSettingsWidget); diff --git a/src/gui/instrument/InstrumentTrackWindow.cpp b/src/gui/instrument/InstrumentTrackWindow.cpp index f6f30d020..4df043041 100644 --- a/src/gui/instrument/InstrumentTrackWindow.cpp +++ b/src/gui/instrument/InstrumentTrackWindow.cpp @@ -251,7 +251,7 @@ InstrumentTrackWindow::InstrumentTrackWindow( InstrumentTrackView * _itv ) : m_midiView = new InstrumentMidiIOView(m_tabWidget); // FX tab - m_effectView = new EffectRackView(m_track->m_audioPort.effects(), m_tabWidget); + m_effectView = new EffectRackView(m_track->m_audioBusHandle.effects(), m_tabWidget); // Tuning tab m_tuningView = new InstrumentTuningView(m_track, m_tabWidget); @@ -381,11 +381,11 @@ void InstrumentTrackWindow::modelChanged() m_tuningView->microtunerGroupBox()->show(); } - m_ssView->setModel( &m_track->m_soundShaping ); - m_noteStackingView->setModel( &m_track->m_noteStacking ); - m_arpeggioView->setModel( &m_track->m_arpeggio ); - m_midiView->setModel( &m_track->m_midiPort ); - m_effectView->setModel( m_track->m_audioPort.effects() ); + m_ssView->setModel(&m_track->m_soundShaping); + m_noteStackingView->setModel(&m_track->m_noteStacking); + m_arpeggioView->setModel(&m_track->m_arpeggio); + m_midiView->setModel(&m_track->m_midiPort); + m_effectView->setModel(m_track->m_audioBusHandle.effects()); m_tuningView->pitchGroupBox()->setModel(&m_track->m_useMasterPitchModel); m_tuningView->microtunerGroupBox()->setModel(m_track->m_microtuner.enabledModel()); m_tuningView->scaleCombo()->setModel(m_track->m_microtuner.scaleModel()); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 66992bc4f..70ac7432e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -46,30 +46,29 @@ namespace lmms { -InstrumentTrack::InstrumentTrack( TrackContainer* tc ) : - Track( Track::Type::Instrument, tc ), +InstrumentTrack::InstrumentTrack(TrackContainer* tc) : + Track(Track::Type::Instrument, tc), MidiEventProcessor(), - m_midiPort( tr( "unnamed_track" ), Engine::audioEngine()->midiClient(), - this, this ), + m_midiPort(tr("unnamed_track"), Engine::audioEngine()->midiClient(), this, this), m_notes(), - m_sustainPedalPressed( false ), - m_silentBuffersProcessed( false ), - m_previewMode( false ), + m_sustainPedalPressed(false), + m_silentBuffersProcessed(false), + m_previewMode(false), m_baseNoteModel(0, 0, NumKeys - 1, this, tr("Base note")), m_firstKeyModel(0, 0, NumKeys - 1, this, tr("First note")), m_lastKeyModel(0, 0, NumKeys - 1, this, tr("Last note")), - m_hasAutoMidiDev( false ), - m_volumeModel( DefaultVolume, MinVolume, MaxVolume, 0.1f, this, tr( "Volume" ) ), - m_panningModel( DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr( "Panning" ) ), - m_audioPort( tr( "unnamed_track" ), true, &m_volumeModel, &m_panningModel, &m_mutedModel ), - m_pitchModel( 0, MinPitchDefault, MaxPitchDefault, 1, this, tr( "Pitch" ) ), - m_pitchRangeModel( 1, 1, 60, this, tr( "Pitch range" ) ), - m_mixerChannelModel( 0, 0, 0, this, tr( "Mixer channel" ) ), - m_useMasterPitchModel( true, this, tr( "Master pitch") ), - m_instrument( nullptr ), - m_soundShaping( this ), - m_arpeggio( this ), - m_noteStacking( this ), + m_hasAutoMidiDev(false), + m_volumeModel(DefaultVolume, MinVolume, MaxVolume, 0.1f, this, tr("Volume")), + m_panningModel(DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr("Panning")), + m_audioBusHandle(tr("unnamed_track"), true, &m_volumeModel, &m_panningModel, &m_mutedModel), + m_pitchModel(0, MinPitchDefault, MaxPitchDefault, 1, this, tr("Pitch")), + m_pitchRangeModel(1, 1, 60, this, tr("Pitch range")), + m_mixerChannelModel(0, 0, 0, this, tr("Mixer channel")), + m_useMasterPitchModel(true, this, tr("Master pitch")), + m_instrument(nullptr), + m_soundShaping(this), + m_arpeggio(this), + m_noteStacking(this), m_piano(this), m_microtuner() { @@ -250,7 +249,7 @@ void InstrumentTrack::processAudioBuffer( SampleFrame* buf, const fpp_t frames, // if effects "went to sleep" because there was no input, wake them up // now - m_audioPort.effects()->startRunning(); + m_audioBusHandle.effects()->startRunning(); // get volume knob data static const float DefaultVolumeRatio = 1.0f / DefaultVolume; @@ -620,11 +619,11 @@ void InstrumentTrack::deleteNotePluginData( NotePlayHandle* n ) -void InstrumentTrack::setName( const QString & _new_name ) +void InstrumentTrack::setName(const QString& new_name) { - Track::setName( _new_name ); - m_midiPort.setName( name() ); - m_audioPort.setName( name() ); + Track::setName(new_name); + m_midiPort.setName(name()); + m_audioBusHandle.setName(name()); } @@ -672,7 +671,7 @@ void InstrumentTrack::updatePitchRange() void InstrumentTrack::updateMixerChannel() { - m_audioPort.setNextMixerChannel( m_mixerChannelModel.value() ); + m_audioBusHandle.setNextMixerChannel(m_mixerChannelModel.value()); } @@ -877,7 +876,7 @@ void InstrumentTrack::saveTrackSpecificSettings(QDomDocument& doc, QDomElement& autoAssignMidiDevice(hasAuto); } - m_audioPort.effects()->saveState( doc, thisElement ); + m_audioBusHandle.effects()->saveState(doc, thisElement); } @@ -909,7 +908,7 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement m_microtuner.loadSettings(thisElement); // clear effect-chain just in case we load an old preset without FX-data - m_audioPort.effects()->clear(); + m_audioBusHandle.effects()->clear(); // We set MIDI CC enable to false so the knobs don't trigger MIDI CC events while // they are being loaded. After all knobs are loaded we load the right value of m_midiCCEnable. @@ -936,9 +935,9 @@ void InstrumentTrack::loadTrackSpecificSettings( const QDomElement & thisElement { m_midiPort.restoreState( node.toElement() ); } - else if( m_audioPort.effects()->nodeName() == node.nodeName() ) + else if (m_audioBusHandle.effects()->nodeName() == node.nodeName()) { - m_audioPort.effects()->restoreState( node.toElement() ); + m_audioBusHandle.effects()->restoreState(node.toElement()); } else if(node.nodeName() == "instrument") { diff --git a/src/tracks/SampleTrack.cpp b/src/tracks/SampleTrack.cpp index c17e3718c..fe83b99e2 100644 --- a/src/tracks/SampleTrack.cpp +++ b/src/tracks/SampleTrack.cpp @@ -49,7 +49,7 @@ SampleTrack::SampleTrack(TrackContainer* tc) : m_volumeModel(DefaultVolume, MinVolume, MaxVolume, 0.1f, this, tr("Volume")), m_panningModel(DefaultPanning, PanningLeft, PanningRight, 0.1f, this, tr("Panning")), m_mixerChannelModel(0, 0, 0, this, tr("Mixer channel")), - m_audioPort(tr("Sample track"), true, &m_volumeModel, &m_panningModel, &m_mutedModel), + m_audioBusHandle(tr("Sample track"), true, &m_volumeModel, &m_panningModel, &m_mutedModel), m_isPlaying(false) { setName(tr("Sample track")); @@ -73,7 +73,7 @@ SampleTrack::~SampleTrack() bool SampleTrack::play( const TimePos & _start, const fpp_t _frames, const f_cnt_t _offset, int _clip_num ) { - m_audioPort.effects()->startRunning(); + m_audioBusHandle.effects()->startRunning(); bool played_a_note = false; // will be return variable @@ -188,36 +188,36 @@ Clip * SampleTrack::createClip(const TimePos & pos) -void SampleTrack::saveTrackSpecificSettings(QDomDocument& _doc, QDomElement& _this, bool presetMode) +void SampleTrack::saveTrackSpecificSettings(QDomDocument& doc, QDomElement& thisElem, bool /*presetMode*/) { - m_audioPort.effects()->saveState( _doc, _this ); - m_volumeModel.saveSettings( _doc, _this, "vol" ); - m_panningModel.saveSettings( _doc, _this, "pan" ); - m_mixerChannelModel.saveSettings( _doc, _this, "mixch" ); + m_audioBusHandle.effects()->saveState(doc, thisElem); + m_volumeModel.saveSettings(doc, thisElem, "vol"); + m_panningModel.saveSettings(doc, thisElem, "pan"); + m_mixerChannelModel.saveSettings(doc, thisElem, "mixch"); } -void SampleTrack::loadTrackSpecificSettings( const QDomElement & _this ) +void SampleTrack::loadTrackSpecificSettings(const QDomElement & thisElem) { - QDomNode node = _this.firstChild(); - m_audioPort.effects()->clear(); - while( !node.isNull() ) + QDomNode node = thisElem.firstChild(); + m_audioBusHandle.effects()->clear(); + while(!node.isNull()) { - if( node.isElement() ) + if (node.isElement()) { - if( m_audioPort.effects()->nodeName() == node.nodeName() ) + if (m_audioBusHandle.effects()->nodeName() == node.nodeName()) { - m_audioPort.effects()->restoreState( node.toElement() ); + m_audioBusHandle.effects()->restoreState(node.toElement()); } } node = node.nextSibling(); } - m_volumeModel.loadSettings( _this, "vol" ); - m_panningModel.loadSettings( _this, "pan" ); - m_mixerChannelModel.setRange( 0, Engine::mixer()->numChannels() - 1 ); - m_mixerChannelModel.loadSettings( _this, "mixch" ); + m_volumeModel.loadSettings(thisElem, "vol"); + m_panningModel.loadSettings(thisElem, "pan"); + m_mixerChannelModel.setRange(0, Engine::mixer()->numChannels() - 1); + m_mixerChannelModel.loadSettings(thisElem, "mixch"); } @@ -247,7 +247,7 @@ void SampleTrack::setPlayingClips( bool isPlaying ) void SampleTrack::updateMixerChannel() { - m_audioPort.setNextMixerChannel( m_mixerChannelModel.value() ); + m_audioBusHandle.setNextMixerChannel(m_mixerChannelModel.value()); }