From 7cc89c9f92d890dd1cbb5da46fab16219bcdf854 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Thu, 13 Jan 2022 23:03:53 -0800 Subject: [PATCH] Cog Audio: Enhance track end extrapolator so it will always have a reasonable amount of buffered data for extrapolation --- Audio/Chain/ConverterNode.h | 3 +++ Audio/Chain/ConverterNode.m | 38 ++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Audio/Chain/ConverterNode.h b/Audio/Chain/ConverterNode.h index 8d5ab1bc5..f7bcd5992 100644 --- a/Audio/Chain/ConverterNode.h +++ b/Audio/Chain/ConverterNode.h @@ -45,6 +45,9 @@ void *floatBuffer; size_t floatBufferSize; size_t floatSize, floatOffset; + + size_t floatConvertedSize; + float floatConvertedLast[CHUNK_SIZE]; AudioStreamBasicDescription inputFormat; AudioStreamBasicDescription floatFormat; diff --git a/Audio/Chain/ConverterNode.m b/Audio/Chain/ConverterNode.m index 5f76af1d1..5190e1fb5 100644 --- a/Audio/Chain/ConverterNode.m +++ b/Audio/Chain/ConverterNode.m @@ -485,12 +485,35 @@ tryagain: extrapolateEnd = ioNumberPackets; // Extrapolate end samples - if (inpSize) + if ( inpSize < sizeof(floatConvertedLast)) { - extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, inpSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO); + size_t inpTotal = newSize + floatConvertedSize; + if (inpTotal > sizeof(floatConvertedLast)) + inpTotal = sizeof(floatConvertedLast); + + if (inpTotal - newSize < floatConvertedSize) + { + memmove(floatConvertedLast, ((uint8_t*)floatConvertedLast) + newSize, inpTotal - newSize); + floatConvertedSize = inpTotal - newSize; + } + + memcpy(((uint8_t*)floatConvertedLast) + floatConvertedSize, inputBuffer, inpSize); + + extrapolate( floatConvertedLast, floatFormat.mChannelsPerFrame, inpTotal / floatFormat.mBytesPerPacket, extrapolateEnd, NO ); + + newSize = ioNumberPackets * floatFormat.mBytesPerPacket; + + memcpy( inputBuffer, ((uint8_t*)floatConvertedLast) + inpTotal - newSize, newSize ); + + inpSize = newSize; + inpOffset = 0; + } + else + { + extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, newSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO ); inpOffset = inpSize; - inpSize += extrapolateEnd * floatFormat.mBytesPerPacket; + inpSize = newSize; } latencyPostfill = YES; break; @@ -628,6 +651,13 @@ tryagain: // Input now contains bytesReadFromInput worth of floats, in the input sample rate inpSize = bytesReadFromInput; inpOffset = 0; + + // Preserve last samples, for end extrapolator, if needed + size_t preserved = inpSize; + if (preserved > sizeof(floatConvertedLast)) + preserved = sizeof(floatConvertedLast); + memcpy(floatConvertedLast, inputBuffer + inpSize - preserved, preserved); + floatConvertedSize = preserved; } if (inpOffset != inpSize && floatOffset == floatSize) @@ -823,6 +853,8 @@ static float db_to_scale(float db) floatOffset = 0; floatSize = 0; + floatConvertedSize = 0; + // This is a post resampler, post-down/upmix format dmFloatFormat = floatFormat;