summaryrefslogtreecommitdiffstats
path: root/src/engine/bufferscalers
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/bufferscalers')
-rw-r--r--src/engine/bufferscalers/enginebufferscale.cpp27
-rw-r--r--src/engine/bufferscalers/enginebufferscale.h13
-rw-r--r--src/engine/bufferscalers/enginebufferscalelinear.cpp10
-rw-r--r--src/engine/bufferscalers/enginebufferscalelinear.h2
-rw-r--r--src/engine/bufferscalers/enginebufferscalerubberband.cpp35
-rw-r--r--src/engine/bufferscalers/enginebufferscalerubberband.h4
-rw-r--r--src/engine/bufferscalers/enginebufferscalest.cpp46
-rw-r--r--src/engine/bufferscalers/enginebufferscalest.h13
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