diff options
Diffstat (limited to 'src/engine/bufferscalers')
-rw-r--r-- | src/engine/bufferscalers/enginebufferscale.cpp | 27 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscale.h | 13 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalelinear.cpp | 10 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalelinear.h | 2 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalerubberband.cpp | 35 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalerubberband.h | 4 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalest.cpp | 46 | ||||
-rw-r--r-- | src/engine/bufferscalers/enginebufferscalest.h | 13 |
8 files changed, 76 insertions, 74 deletions
diff --git a/src/engine/bufferscalers/enginebufferscale.cpp b/src/engine/bufferscalers/enginebufferscale.cpp index 8e3f977ad0..b250c48f37 100644 --- a/src/engine/bufferscalers/enginebufferscale.cpp +++ b/src/engine/bufferscalers/enginebufferscale.cpp @@ -2,27 +2,26 @@ #include "engine/engine.h" #include "util/defs.h" -#include "util/sample.h" EngineBufferScale::EngineBufferScale() : m_audioSignal( - mixxx::AudioSignal::SampleLayout::Interleaved, - mixxx::AudioSignal::ChannelCount(mixxx::kEngineChannelCount), - mixxx::AudioSignal::SampleRate(44100)), + mixxx::audio::SignalInfo( + mixxx::kEngineChannelCount, + mixxx::audio::SampleRate(), + mixxx::kEngineSampleLayout)), m_dBaseRate(1.0), m_bSpeedAffectsPitch(false), m_dTempoRatio(1.0), m_dPitchRatio(1.0) { - DEBUG_ASSERT(m_audioSignal.verifyReadable()); + DEBUG_ASSERT(!m_audioSignal.isValid()); } -EngineBufferScale::~EngineBufferScale() { -} - -void EngineBufferScale::setSampleRate(SINT iSampleRate) { - m_audioSignal = mixxx::AudioSignal( - m_audioSignal.sampleLayout(), - m_audioSignal.channelCount(), - mixxx::AudioSignal::SampleRate(iSampleRate)); - DEBUG_ASSERT(m_audioSignal.verifyReadable()); +void EngineBufferScale::setSampleRate( + mixxx::audio::SampleRate sampleRate) { + DEBUG_ASSERT(sampleRate.isValid()); + if (sampleRate != m_audioSignal.getSampleRate()) { + m_audioSignal.setSampleRate(sampleRate); + onSampleRateChanged(); + } + DEBUG_ASSERT(m_audioSignal.isValid()); } diff --git a/src/engine/bufferscalers/enginebufferscale.h b/src/engine/bufferscalers/enginebufferscale.h index 609cf54fb5..f8ba5d827e 100644 --- a/src/engine/bufferscalers/enginebufferscale.h +++ b/src/engine/bufferscalers/enginebufferscale.h @@ -3,7 +3,7 @@ #include <QObject> -#include "util/audiosignal.h" +#include "audio/signalinfo.h" // MAX_SEEK_SPEED needs to be good and high to allow room for the very high // instantaneous velocities of advanced scratching (Uzi) and spin-backs. @@ -24,7 +24,7 @@ class EngineBufferScale : public QObject { Q_OBJECT public: EngineBufferScale(); - virtual ~EngineBufferScale(); + ~EngineBufferScale() override = default; // Sets the scaling parameters. // * The base rate (ratio of track sample rate to output sample rate). @@ -48,9 +48,10 @@ class EngineBufferScale : public QObject { } // Set the desired output sample rate. - virtual void setSampleRate(SINT iSampleRate); + void setSampleRate( + mixxx::audio::SampleRate sampleRate); - const mixxx::AudioSignal& getAudioSignal() const { + const mixxx::audio::SignalInfo& getAudioSignal() const { return m_audioSignal; } @@ -68,7 +69,9 @@ class EngineBufferScale : public QObject { SINT iOutputBufferSize) = 0; private: - mixxx::AudioSignal m_audioSignal; + mixxx::audio::SignalInfo m_audioSignal; + + virtual void onSampleRateChanged() = 0; protected: double m_dBaseRate; diff --git a/src/engine/bufferscalers/enginebufferscalelinear.cpp b/src/engine/bufferscalers/enginebufferscalelinear.cpp index c632158b20..e268cfee04 100644 --- a/src/engine/bufferscalers/enginebufferscalelinear.cpp +++ b/src/engine/bufferscalers/enginebufferscalelinear.cpp @@ -92,12 +92,12 @@ double EngineBufferScaleLinear::scaleBuffer( // if the buffer has extra samples, do a read so RAMAN ends up back where // it should be SINT iCurSample = getAudioSignal().frames2samples(static_cast<SINT>(ceil(m_dCurrentFrame))); - SINT extra_samples = m_bufferIntSize - iCurSample - getAudioSignal().channelCount(); + SINT extra_samples = m_bufferIntSize - iCurSample - getAudioSignal().getChannelCount(); if (extra_samples > 0) { - if (extra_samples % getAudioSignal().channelCount() != 0) { + if (extra_samples % getAudioSignal().getChannelCount() != 0) { // extra samples should include the whole frame - extra_samples -= extra_samples % getAudioSignal().channelCount(); - extra_samples += getAudioSignal().channelCount(); + extra_samples -= extra_samples % getAudioSignal().getChannelCount(); + extra_samples += getAudioSignal().getChannelCount(); } //qDebug() << "extra samples" << extra_samples; @@ -339,7 +339,7 @@ SINT EngineBufferScaleLinear::do_scale(CSAMPLE* buf, SINT buf_size) { // samples. This prevents the change from being discontinuous and helps // improve sound quality. rate_add += rate_delta_abs; - i += getAudioSignal().channelCount(); + i += getAudioSignal().getChannelCount(); } SampleUtil::clear(&buf[i], buf_size - i); diff --git a/src/engine/bufferscalers/enginebufferscalelinear.h b/src/engine/bufferscalers/enginebufferscalelinear.h index f30a951db8..d46f342ba6 100644 --- a/src/engine/bufferscalers/enginebufferscalelinear.h +++ b/src/engine/bufferscalers/enginebufferscalelinear.h @@ -24,6 +24,8 @@ class EngineBufferScaleLinear : public EngineBufferScale { double* pPitchRatio) override; private: + void onSampleRateChanged() override {} + SINT do_scale(CSAMPLE* buf, SINT buf_size); SINT do_copy(CSAMPLE* buf, SINT buf_size); diff --git a/src/engine/bufferscalers/enginebufferscalerubberband.cpp b/src/engine/bufferscalers/enginebufferscalerubberband.cpp index c17973804d..c403d16bf6 100644 --- a/src/engine/bufferscalers/enginebufferscalerubberband.cpp +++ b/src/engine/bufferscalers/enginebufferscalerubberband.cpp @@ -28,7 +28,6 @@ EngineBufferScaleRubberBand::EngineBufferScaleRubberBand( m_bBackwards(false) { m_retrieve_buffer[0] = SampleUtil::alloc(MAX_BUFFER_LEN); m_retrieve_buffer[1] = SampleUtil::alloc(MAX_BUFFER_LEN); - initRubberBand(); } EngineBufferScaleRubberBand::~EngineBufferScaleRubberBand() { @@ -37,19 +36,6 @@ EngineBufferScaleRubberBand::~EngineBufferScaleRubberBand() { SampleUtil::free(m_retrieve_buffer[1]); } -void EngineBufferScaleRubberBand::initRubberBand() { - m_pRubberBand = std::make_unique<RubberBandStretcher>( - getAudioSignal().sampleRate(), - getAudioSignal().channelCount(), - RubberBandStretcher::OptionProcessRealTime); - m_pRubberBand->setMaxProcessSize(kRubberBandBlockSize); - // Setting the time ratio to a very high value will cause RubberBand - // to preallocate buffers large enough to (almost certainly) - // avoid memory reallocations during playback. - m_pRubberBand->setTimeRatio(2.0); - m_pRubberBand->setTimeRatio(1.0); -} - void EngineBufferScaleRubberBand::setScaleParameters(double base_rate, double* pTempoRatio, double* pPitchRatio) { @@ -111,12 +97,27 @@ void EngineBufferScaleRubberBand::setScaleParameters(double base_rate, m_dPitchRatio = *pPitchRatio; } -void EngineBufferScaleRubberBand::setSampleRate(SINT iSampleRate) { - EngineBufferScale::setSampleRate(iSampleRate); - initRubberBand(); +void EngineBufferScaleRubberBand::onSampleRateChanged() { + if (!getAudioSignal().isValid()) { + m_pRubberBand.reset(); + return; + } + m_pRubberBand = std::make_unique<RubberBandStretcher>( + getAudioSignal().getSampleRate(), + getAudioSignal().getChannelCount(), + RubberBandStretcher::OptionProcessRealTime); + m_pRubberBand->setMaxProcessSize(kRubberBandBlockSize); + // Setting the time ratio to a very high value will cause RubberBand + // to preallocate buffers large enough to (almost certainly) + // avoid memory reallocations during playback. + m_pRubberBand->setTimeRatio(2.0); + m_pRubberBand->setTimeRatio(1.0); } void EngineBufferScaleRubberBand::clear() { + VERIFY_OR_DEBUG_ASSERT(m_pRubberBand) { + return; + } m_pRubberBand->reset(); } diff --git a/src/engine/bufferscalers/enginebufferscalerubberband.h b/src/engine/bufferscalers/enginebufferscalerubberband.h index 53d07370a7..7ee14e084c 100644 --- a/src/engine/bufferscalers/enginebufferscalerubberband.h +++ b/src/engine/bufferscalers/enginebufferscalerubberband.h @@ -22,8 +22,6 @@ class EngineBufferScaleRubberBand : public EngineBufferScale { double* pTempoRatio, double* pPitchRatio) override; - void setSampleRate(SINT iSampleRate) override; - double scaleBuffer( CSAMPLE* pOutputBuffer, SINT iOutputBufferSize) override; @@ -33,7 +31,7 @@ class EngineBufferScaleRubberBand : public EngineBufferScale { private: // Reset RubberBand library with new audio signal - void initRubberBand(); + void onSampleRateChanged() override; void deinterleaveAndProcess(const CSAMPLE* pBuffer, SINT frames, bool flush); SINT retrieveAndDeinterleave(CSAMPLE* pBuffer, SINT frames); diff --git a/src/engine/bufferscalers/enginebufferscalest.cpp b/src/engine/bufferscalers/enginebufferscalest.cpp index 59a19a8af8..4e62432e59 100644 --- a/src/engine/bufferscalers/enginebufferscalest.cpp +++ b/src/engine/bufferscalers/enginebufferscalest.cpp @@ -29,27 +29,14 @@ const SINT kSeekOffsetFrames = 519; EngineBufferScaleST::EngineBufferScaleST(ReadAheadManager *pReadAheadManager) : m_pReadAheadManager(pReadAheadManager), m_pSoundTouch(std::make_unique<soundtouch::SoundTouch>()), - buffer_back_size(getAudioSignal().frames2samples(kSeekOffsetFrames)), - buffer_back(SampleUtil::alloc(buffer_back_size)), m_bBackwards(false) { - DEBUG_ASSERT(getAudioSignal().verifyReadable()); - m_pSoundTouch->setChannels(getAudioSignal().channelCount()); - m_pSoundTouch->setSampleRate(getAudioSignal().sampleRate()); + m_pSoundTouch->setChannels(getAudioSignal().getChannelCount()); m_pSoundTouch->setRate(m_dBaseRate); m_pSoundTouch->setPitch(1.0); m_pSoundTouch->setSetting(SETTING_USE_QUICKSEEK, 1); - - // Setting the tempo to a very low value will force SoundTouch - // to preallocate buffers large enough to (almost certainly) - // avoid memory reallocations during playback. - m_pSoundTouch->setTempo(0.1); - m_pSoundTouch->putSamples(buffer_back, kSeekOffsetFrames); - m_pSoundTouch->clear(); - m_pSoundTouch->setTempo(m_dTempoRatio); } EngineBufferScaleST::~EngineBufferScaleST() { - SampleUtil::free(buffer_back); } void EngineBufferScaleST::setScaleParameters(double base_rate, @@ -98,17 +85,32 @@ void EngineBufferScaleST::setScaleParameters(double base_rate, // changed direction. I removed it because this is handled by EngineBuffer. } -void EngineBufferScaleST::setSampleRate(SINT iSampleRate) { - EngineBufferScale::setSampleRate(iSampleRate); - m_pSoundTouch->setSampleRate(iSampleRate); +void EngineBufferScaleST::onSampleRateChanged() { + buffer_back.clear(); + if (!getAudioSignal().isValid()) { + return; + } + m_pSoundTouch->setSampleRate(getAudioSignal().getSampleRate()); + const auto bufferSize = getAudioSignal().frames2samples(kSeekOffsetFrames); + if (bufferSize > buffer_back.size()) { + // grow buffer + buffer_back = mixxx::SampleBuffer(bufferSize); + } + // Setting the tempo to a very low value will force SoundTouch + // to preallocate buffers large enough to (almost certainly) + // avoid memory reallocations during playback. + m_pSoundTouch->setTempo(0.1); + m_pSoundTouch->putSamples(buffer_back.data(), kSeekOffsetFrames); + m_pSoundTouch->clear(); + m_pSoundTouch->setTempo(m_dTempoRatio); } void EngineBufferScaleST::clear() { m_pSoundTouch->clear(); // compensate seek offset for a rate of 1.0 - SampleUtil::clear(buffer_back, getAudioSignal().frames2samples(kSeekOffsetFrames)); - m_pSoundTouch->putSamples(buffer_back, kSeekOffsetFrames); + SampleUtil::clear(buffer_back.data(), buffer_back.size()); + m_pSoundTouch->putSamples(buffer_back.data(), kSeekOffsetFrames); } double EngineBufferScaleST::scaleBuffer( @@ -140,14 +142,14 @@ double EngineBufferScaleST::scaleBuffer( // The value doesn't matter here. All that matters is we // are going forward or backward. (m_bBackwards ? -1.0 : 1.0) * m_dBaseRate * m_dTempoRatio, - buffer_back, - buffer_back_size); + buffer_back.data(), + buffer_back.size()); SINT iAvailFrames = getAudioSignal().samples2frames(iAvailSamples); if (iAvailFrames > 0) { last_read_failed = false; total_read_frames += iAvailFrames; - m_pSoundTouch->putSamples(buffer_back, iAvailFrames); + m_pSoundTouch->putSamples(buffer_back.data(), iAvailFrames); } else { if (last_read_failed) { m_pSoundTouch->flush(); diff --git a/src/engine/bufferscalers/enginebufferscalest.h b/src/engine/bufferscalers/enginebufferscalest.h index 7ac8d61100..8212ecb75d 100644 --- a/src/engine/bufferscalers/enginebufferscalest.h +++ b/src/engine/bufferscalers/enginebufferscalest.h @@ -1,8 +1,8 @@ -#ifndef ENGINEBUFFERSCALEST_H -#define ENGINEBUFFERSCALEST_H +#pragma once #include "engine/bufferscalers/enginebufferscale.h" #include "util/memory.h" +#include "util/samplebuffer.h" class ReadAheadManager; @@ -22,8 +22,6 @@ class EngineBufferScaleST : public EngineBufferScale { double* pTempoRatio, double* pPitchRatio) override; - void setSampleRate(SINT iSampleRate) override; - // Scale buffer. double scaleBuffer( CSAMPLE* pOutputBuffer, @@ -33,6 +31,8 @@ class EngineBufferScaleST : public EngineBufferScale { void clear() override; private: + void onSampleRateChanged() override; + // The read-ahead manager that we use to fetch samples ReadAheadManager* m_pReadAheadManager; @@ -40,11 +40,8 @@ class EngineBufferScaleST : public EngineBufferScale { std::unique_ptr<soundtouch::SoundTouch> m_pSoundTouch; // Temporary buffer for reading from the RAMAN. - SINT buffer_back_size; - CSAMPLE* buffer_back; + mixxx::SampleBuffer buffer_back; // Holds the playback direction. bool m_bBackwards; }; - -#endif |