Bug Fix: Restructure Rubber Band gapless handler
Change how samples are accounted for by the filter. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
bce00aff2e
commit
019bdd7a36
1 changed files with 15 additions and 13 deletions
|
@ -28,7 +28,8 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
BOOL tsrestartengine;
|
BOOL tsrestartengine;
|
||||||
double tempo, pitch;
|
double tempo, pitch;
|
||||||
double lastTempo, lastPitch;
|
double lastTempo, lastPitch;
|
||||||
double stretchIn, stretchOut;
|
double countIn;
|
||||||
|
uint64_t countOut;
|
||||||
|
|
||||||
double streamTimestamp;
|
double streamTimestamp;
|
||||||
double streamTimeRatio;
|
double streamTimeRatio;
|
||||||
|
@ -265,8 +266,8 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
tsrestartengine = NO;
|
tsrestartengine = NO;
|
||||||
flushed = NO;
|
flushed = NO;
|
||||||
|
|
||||||
stretchIn = 0.0;
|
countIn = 0.0;
|
||||||
stretchOut = 0.0;
|
countOut = 0;
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
@ -443,9 +444,9 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
streamTimeRatio = [chunk streamTimeRatio];
|
streamTimeRatio = [chunk streamTimeRatio];
|
||||||
isHDCD = [chunk isHDCD];
|
isHDCD = [chunk isHDCD];
|
||||||
|
|
||||||
stretchIn += [chunk duration] / tempo;
|
|
||||||
|
|
||||||
size_t frameCount = [chunk frameCount];
|
size_t frameCount = [chunk frameCount];
|
||||||
|
countIn += ((double)frameCount) / tempo;
|
||||||
|
|
||||||
NSData *sampleData = [chunk removeSamples:frameCount];
|
NSData *sampleData = [chunk removeSamples:frameCount];
|
||||||
|
|
||||||
for (size_t i = 0; i < channels; ++i) {
|
for (size_t i = 0; i < channels; ++i) {
|
||||||
|
@ -487,11 +488,10 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
|
|
||||||
if(flushed) {
|
if(flushed) {
|
||||||
if(samplesBuffered > 0) {
|
if(samplesBuffered > 0) {
|
||||||
ssize_t delta = (stretchIn - stretchOut) * inputFormat.mSampleRate;
|
ssize_t ideal = (ssize_t)floor(countIn + 0.5);
|
||||||
if(delta > 0 && samplesBuffered > delta) {
|
if(countOut + samplesBuffered > ideal) {
|
||||||
// Seems that Rubber Band over-flushes when it hits end of stream
|
// Rubber Band does not account for flushing duration in real time mode
|
||||||
// Also somehow, this was being miscalculated before and ending up negative
|
samplesBuffered = ideal - countOut;
|
||||||
samplesBuffered = delta;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,9 +507,9 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
[outputChunk setStreamTimestamp:streamTimestamp];
|
[outputChunk setStreamTimestamp:streamTimestamp];
|
||||||
[outputChunk setStreamTimeRatio:streamTimeRatio * tempo];
|
[outputChunk setStreamTimeRatio:streamTimeRatio * tempo];
|
||||||
[outputChunk assignSamples:&rsOutBuffer[0] frameCount:samplesBuffered];
|
[outputChunk assignSamples:&rsOutBuffer[0] frameCount:samplesBuffered];
|
||||||
|
countOut += samplesBuffered;
|
||||||
samplesBuffered = 0;
|
samplesBuffered = 0;
|
||||||
double chunkDuration = [outputChunk duration];
|
double chunkDuration = [outputChunk duration];
|
||||||
stretchOut += chunkDuration;
|
|
||||||
streamTimestamp += chunkDuration * [outputChunk streamTimeRatio];
|
streamTimestamp += chunkDuration * [outputChunk streamTimeRatio];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,9 +525,11 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
|
||||||
// how much audio will be lopped off at the end of the process.
|
// how much audio will be lopped off at the end of the process.
|
||||||
//
|
//
|
||||||
// Tested once, this tends to be close to zero when actually called.
|
// Tested once, this tends to be close to zero when actually called.
|
||||||
rbBuffered = stretchIn - stretchOut;
|
rbBuffered = countIn - (double)(countOut);
|
||||||
if(rbBuffered < 0.0) {
|
if(rbBuffered < 0) {
|
||||||
rbBuffered = 0.0;
|
rbBuffered = 0.0;
|
||||||
|
} else {
|
||||||
|
rbBuffered /= inputFormat.mSampleRate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [buffer listDuration] + rbBuffered;
|
return [buffer listDuration] + rbBuffered;
|
||||||
|
|
Loading…
Reference in a new issue