Rubber Band DSP: Process larger blocks at a time

Attempt to completely fill the input buffer of the Rubber Band library
between each call to the process function, instead of processing in
as small an increment as the source node provides. May reduce processing
power required.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-02-12 14:56:32 -08:00
parent 7994929a80
commit 2364a7d469

View file

@ -373,6 +373,13 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
return nil;
}
double streamTimestamp;
double streamTimeRatio;
if(![self peekTimestamp:&streamTimestamp timeRatio:&streamTimeRatio]) {
processEntered = NO;
return nil;
}
if(!ts || memcmp(&inputFormat, &lastInputFormat, sizeof(inputFormat)) != 0 ||
inputChannelConfig != lastInputChannelConfig) {
lastInputFormat = inputFormat;
@ -388,8 +395,41 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
if(samplesToProcess > blockSize)
samplesToProcess = blockSize;
AudioChunk *chunk = [self readChunkAsFloat32:samplesToProcess];
if(!chunk) {
size_t totalFrameCount = 0;
AudioChunk *chunk;
int channels = (int)(inputFormat.mChannelsPerFrame);
BOOL isHDCD = NO;
while(!stopping && totalFrameCount < samplesToProcess) {
AudioStreamBasicDescription newInputFormat;
uint32_t newChannelConfig;
if(![self peekFormat:&newInputFormat channelConfig:&newChannelConfig] ||
memcmp(&newInputFormat, &inputFormat, sizeof(newInputFormat)) != 0 ||
newChannelConfig != inputChannelConfig) {
break;
}
chunk = [self readChunkAsFloat32:samplesToProcess - totalFrameCount];
if(!chunk) {
break;
}
if([chunk isHDCD]) {
isHDCD = YES;
}
size_t frameCount = [chunk frameCount];
NSData *sampleData = [chunk removeSamples:frameCount];
for (size_t i = 0; i < channels; ++i) {
cblas_scopy((int)frameCount, ((const float *)[sampleData bytes]) + i, channels, rsPtrs[i] + totalFrameCount, 1);
}
totalFrameCount += frameCount;
}
if(!totalFrameCount) {
processEntered = NO;
return nil;
}
@ -398,18 +438,9 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
bool endOfStream = [[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES;
size_t frameCount = [chunk frameCount];
double streamTimestamp = [chunk streamTimestamp];
size_t frameCount = totalFrameCount;
int len = (int)frameCount;
int channels = (int)(inputFormat.mChannelsPerFrame);
NSData *samples = [chunk removeSamples:frameCount];
float *ibuf = (float *)[samples bytes];
for(size_t i = 0; i < channels; ++i) {
cblas_scopy(len, ibuf + i, channels, rsPtrs[i], 1);
}
rubberband_process(ts, (const float * const *)rsPtrs, len, endOfStream);
@ -461,9 +492,9 @@ static void * kDSPRubberbandNodeContext = &kDSPRubberbandNodeContext;
if(inputChannelConfig) {
[outputChunk setChannelConfig:inputChannelConfig];
}
if([chunk isHDCD]) [outputChunk setHDCD];
if(isHDCD) [outputChunk setHDCD];
[outputChunk setStreamTimestamp:streamTimestamp];
[outputChunk setStreamTimeRatio:[chunk streamTimeRatio] * tempo];
[outputChunk setStreamTimeRatio:streamTimeRatio * tempo];
[outputChunk assignSamples:rsOutBuffer frameCount:samplesBuffered];
samplesBuffered = 0;
stretchOut += [outputChunk duration];