Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 70 additions & 47 deletions src/ResamplingReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ResamplingReader {
virtual TArray* createSourceBuffer() = 0;
virtual int16_t getSourceBufferValue(long index) = 0;
virtual void close(void) = 0;
int _lastInterpolationPosition[8] = {0};

void begin(void)
{
Expand Down Expand Up @@ -303,52 +304,56 @@ class ResamplingReader {
if (_remainder - _playbackRate < 0.0){
// we crossed over a whole number, make sure we update the samples for interpolation
if (!_useDualPlaybackHead) {
if ( _numInterpolationPoints < 2 &&_playbackRate > 1.0 && _bufferPosition1 - _numChannels > _header_offset * 2 ) {
if ( _numInterpolationPoints[channel] < 2 &&_playbackRate > 1.0 && _bufferPosition1 - _numChannels > _header_offset * 2 ) {
// need to update last sample
_interpolationPoints[channel][1].y = getSourceBufferValue(_bufferPosition1 - _numChannels);
}
}
_interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y;
_interpolationPoints[channel][1].y = result;
if (_numInterpolationPoints < 2)
_numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 2)
_numInterpolationPoints[channel]++;
}
}
else if (_playbackRate < 0) {
if (_remainder - _playbackRate > 0.0){
// we crossed over a whole number, make sure we update the samples for interpolation
if (!_useDualPlaybackHead) {
if (_numInterpolationPoints < 2 && _playbackRate < -1.0) {
if (_numInterpolationPoints[channel] < 2 && _playbackRate < -1.0) {
// need to update last sample
_interpolationPoints[channel][1].y = getSourceBufferValue(_bufferPosition1 + _numChannels);
}
}
_interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y;
_interpolationPoints[channel][1].y = result;
if (_numInterpolationPoints < 2)
_numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 2)
_numInterpolationPoints[channel]++;
}
}

if (_numInterpolationPoints > 1) {
if (_numInterpolationPoints[channel] > 1) {
result = abs_remainder * _interpolationPoints[channel][1].y + (1.0 - abs_remainder) * _interpolationPoints[channel][0].y;
}
} else {
_interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y;
_interpolationPoints[channel][1].y = result;
if (_numInterpolationPoints < 2)
_numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 2)
_numInterpolationPoints[channel]++;

result =_interpolationPoints[channel][0].y;
}
}
else if (_interpolationType == ResampleInterpolationType::resampleinterpolation_quadratic) {
double abs_remainder = abs(_remainder);
if (abs_remainder > 0.0) {
int delta = abs(_bufferPosition1/_numChannels - _lastInterpolationPosition[channel]);
//Serial.printf("delta %d %d:\n", delta, _bufferPosition1/_numChannels - _lastInterpolationPosition[channel]);
if (_numInterpolationPoints[channel] == 0){
_interpolationPoints[channel][3].y = result;
_numInterpolationPoints[channel] = 1;
}
if (delta > 0) {
if (_playbackRate > 0) {
if (_remainder - _playbackRate < 0.0){
// we crossed over a whole number, make sure we update the samples for interpolation
int numberOfSamplesToUpdate = - floor(_remainder - _playbackRate);
int numberOfSamplesToUpdate = delta;
if (numberOfSamplesToUpdate > 4)
numberOfSamplesToUpdate = 4; // if playbackrate > 4, only need to pop last 4 samples
for (int i=numberOfSamplesToUpdate; i > 0; i--) {
Expand All @@ -359,16 +364,18 @@ class ResamplingReader {
_interpolationPoints[channel][3].y = getSourceBufferValue(_bufferPosition1-(i*_numChannels)+1+channel);
} else
{
_interpolationPoints[channel][3].y = result;
_interpolationPoints[channel][3].y =
getSourceBufferValue(_bufferPosition1-(i*_numChannels)+1+channel) * _crossfade
+
getSourceBufferValue(_bufferPosition2-(i*_numChannels)+1+channel) * (1.0 -_crossfade);
}
if (_numInterpolationPoints < 4) _numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 4) _numInterpolationPoints[channel]++;
}
}
_lastInterpolationPosition[channel] = _bufferPosition1 / _numChannels;
}
else if (_playbackRate < 0) {
if (_remainder - _playbackRate > 0.0){
// we crossed over a whole number, make sure we update the samples for interpolation
int numberOfSamplesToUpdate = ceil(_remainder - _playbackRate);
int numberOfSamplesToUpdate = delta;
if (numberOfSamplesToUpdate > 4)
numberOfSamplesToUpdate = 4; // if playbackrate > 4, only need to pop last 4 samples
for (int i=numberOfSamplesToUpdate; i > 0; i--) {
Expand All @@ -379,40 +386,47 @@ class ResamplingReader {
_interpolationPoints[channel][3].y = getSourceBufferValue(_bufferPosition1+(i*_numChannels)-1+channel);
} else
{
_interpolationPoints[channel][3].y = result;
_interpolationPoints[channel][3].y =
getSourceBufferValue(_bufferPosition1+(i*_numChannels)-1+channel) * _crossfade
+
getSourceBufferValue(_bufferPosition2+(i*_numChannels)-1+channel) * (1.0 - _crossfade);
}
if (_numInterpolationPoints < 4) _numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 4) _numInterpolationPoints[channel]++;
_lastInterpolationPosition[channel] = _bufferPosition1 / _numChannels;
}
}
}

if (_numInterpolationPoints >= 4) {
//int16_t interpolation = interpolate(_interpolationPoints, 1.0 + abs_remainder, 4);
int16_t interpolation
= fastinterpolate(
_interpolationPoints[channel][0].y,
_interpolationPoints[channel][1].y,
_interpolationPoints[channel][2].y,
_interpolationPoints[channel][3].y,
1.0 + abs_remainder);
result = interpolation;
//Serial.printf("[%f]\n", interpolation);
} else
result = 0;
}
}
if (_remainder != 0.0) {
if (_numInterpolationPoints[channel] >= 4) {
//result = interpolate(_interpolationPoints[channel], _interpolationPoints[channel][0].x + ((_bufferPosition1 - _interpolationPoints[channel][0].x) * abs_remainder), 4);
int16_t interpolation
= fastinterpolate(
_interpolationPoints[channel][0].y,
_interpolationPoints[channel][1].y,
_interpolationPoints[channel][2].y,
_interpolationPoints[channel][3].y,
1.0 + abs(_remainder));
/*
Serial.printf("[%d %d %d %d] @ %f = %d \n",
_interpolationPoints[channel][0].y,
_interpolationPoints[channel][1].y,
_interpolationPoints[channel][2].y,
_interpolationPoints[channel][3].y,
1.0 + abs(_remainder),
interpolation
);
*/
result = interpolation;
} else
result = 0;
} else {
_interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y;
_interpolationPoints[channel][1].y = _interpolationPoints[channel][2].y;
_interpolationPoints[channel][2].y = _interpolationPoints[channel][3].y;
_interpolationPoints[channel][3].y = result;
if (_numInterpolationPoints < 4) {
_numInterpolationPoints++;
if (_numInterpolationPoints[channel] < 4) {
result = 0;
} else
result = _interpolationPoints[channel][1].y;
//Serial.printf("%f\n", result);
}
}

if (channel == _numChannels - 1) {
_remainder += _playbackRate;

Expand All @@ -428,7 +442,7 @@ class ResamplingReader {
_bufferPosition2 += (delta * _numChannels);
}
}

//Serial.printf("ch: %d, index: %d, value: %d\n", channel, _bufferPosition1, result);
*value = result;
return true;
}
Expand Down Expand Up @@ -498,7 +512,7 @@ class ResamplingReader {
if (_interpolationType != ResampleInterpolationType::resampleinterpolation_none) {
initializeInterpolationPoints();
}
_numInterpolationPoints = 0;

if (_playbackRate > 0.0) {
// forward playabck - set _file_offset to first audio block in file
if (_play_start == play_start::play_start_sample)
Expand All @@ -512,6 +526,15 @@ class ResamplingReader {
else
_bufferPosition1 = _loop_finish - _numChannels;
}

for(int i=0;i<8;i++) {
_numInterpolationPoints[i] = 0;
if (_playbackRate > 0.0)
_lastInterpolationPosition[i] = _bufferPosition1 / _numChannels;
else
_lastInterpolationPosition[i] = (_bufferPosition1 / _numChannels) + 1;
}

_crossfade = 0.0;
}

Expand Down Expand Up @@ -621,7 +644,7 @@ class ResamplingReader {
TArray *_sourceBuffer = nullptr;

ResampleInterpolationType _interpolationType = ResampleInterpolationType::resampleinterpolation_none;
unsigned int _numInterpolationPoints = 0;
unsigned int _numInterpolationPoints[8] = {0};
InterpolationData **_interpolationPoints = nullptr;

void initializeInterpolationPoints(void) {
Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ if (DEFINED BUILD_FOR_LINUX)
audio/output_test.cpp

audio/array/AudioArrayFixture.h
audio/array/test_array_mono_loop_backward_playback.cpp
audio/array/test_array_mono_loop_forward_playback.cpp
audio/array/test_array_stereo_loop_backward_playback.cpp
audio/array/test_array_stereo_loop_forward_playback.cpp

audio/wav/AudioWavFixture.h
Expand Down
Loading