Cog Audio: Make it possible to play obscene sample rate files without major failures

CQTexperiment
Christopher Snowhill 2022-01-14 02:00:32 -08:00
parent 5aa3f7dd0a
commit 903b457a28
4 changed files with 40 additions and 10 deletions

View File

@ -49,6 +49,9 @@
size_t floatConvertedSize;
float floatConvertedLast[CHUNK_SIZE];
void *extrapolateBuffer;
size_t extrapolateBufferSize;
AudioStreamBasicDescription inputFormat;
AudioStreamBasicDescription floatFormat;
AudioStreamBasicDescription dmFloatFormat; // downmixed/upmixed float format

View File

@ -63,6 +63,9 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
refillNode = nil;
originalPreviousNode = nil;
extrapolateBuffer = NULL;
extrapolateBufferSize = 0;
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil];
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputResampling" options:0 context:nil];
}
@ -376,12 +379,24 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
static const int extrapolate_order = 16;
static void extrapolate(float *buffer, size_t channels, size_t frameSize, size_t size, BOOL backward)
static void extrapolate(float *buffer, size_t channels, size_t frameSize, size_t size, BOOL backward, void ** extrapolateBuffer, size_t * extrapolateSize)
{
const size_t delta = (backward ? -1 : 1) * channels;
float lpc[extrapolate_order];
float work[frameSize];
size_t lpc_size = sizeof(float) * extrapolate_order;
size_t my_work_size = sizeof(float) * frameSize;
size_t their_work_size = sizeof(float) * (extrapolate_order + size);
size_t newSize = lpc_size + my_work_size + their_work_size;
if (!*extrapolateBuffer || *extrapolateSize < newSize)
{
*extrapolateBuffer = realloc(*extrapolateBuffer, newSize);
*extrapolateSize = newSize;
}
float *lpc = (float*)(*extrapolateBuffer);
float *work = (float*)(*extrapolateBuffer + lpc_size);
float *their_work = (float*)(*extrapolateBuffer + lpc_size + my_work_size);
for (size_t ch = 0; ch < channels; ch++)
{
@ -392,7 +407,7 @@ static void extrapolate(float *buffer, size_t channels, size_t frameSize, size_t
vorbis_lpc_from_data(work, lpc, (int)(frameSize - size), extrapolate_order);
vorbis_lpc_predict(lpc, work + frameSize - size - extrapolate_order, extrapolate_order, work + frameSize - size, size);
vorbis_lpc_predict(lpc, work + frameSize - size - extrapolate_order, extrapolate_order, work + frameSize - size, size, their_work);
chPcmBuf = buffer + ch + (backward ? frameSize : -1) * channels;
for (size_t i = 0; i < frameSize; i++) *(chPcmBuf += delta) = work[i];
@ -465,6 +480,12 @@ tryagain:
// Approximately the most we want on input
ioNumberPackets = (amount - amountRead) / outputFormat.mBytesPerPacket;
// We want to upscale this count if the ratio is below zero
if (sampleRatio < 1.0)
{
ioNumberPackets = ((uint32_t)(ioNumberPackets / sampleRatio) + 15) & ~15;
}
size_t newSize = ioNumberPackets * floatFormat.mBytesPerPacket;
if (!inputBuffer || inputBufferSize < newSize)
inputBuffer = realloc( inputBuffer, inputBufferSize = newSize * 3 );
@ -499,7 +520,7 @@ tryagain:
memcpy(((uint8_t*)floatConvertedLast) + floatConvertedSize, inputBuffer, inpSize);
extrapolate( floatConvertedLast, floatFormat.mChannelsPerFrame, inpTotal / floatFormat.mBytesPerPacket, extrapolateEnd, NO );
extrapolate( floatConvertedLast, floatFormat.mChannelsPerFrame, inpTotal / floatFormat.mBytesPerPacket, extrapolateEnd, NO, &extrapolateBuffer, &extrapolateBufferSize );
newSize = ioNumberPackets * floatFormat.mBytesPerPacket;
@ -510,7 +531,7 @@ tryagain:
}
else
{
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, newSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO );
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, newSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO, &extrapolateBuffer, &extrapolateBufferSize );
inpOffset = inpSize;
inpSize = newSize;
@ -644,7 +665,7 @@ tryagain:
// Extrapolate start
if (extrapolateStart)
{
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, bytesReadFromInput / floatFormat.mBytesPerPacket, extrapolateStart, YES);
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, bytesReadFromInput / floatFormat.mBytesPerPacket, extrapolateStart, YES, &extrapolateBuffer, &extrapolateBufferSize);
extrapolateStart = 0;
}
@ -985,6 +1006,12 @@ static float db_to_scale(float db)
resampler = NULL;
resampler_data = NULL;
}
if (extrapolateBuffer)
{
free(extrapolateBuffer);
extrapolateBuffer = NULL;
extrapolateBufferSize = 0;
}
if (floatBuffer)
{
free(floatBuffer);

View File

@ -127,7 +127,7 @@ float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
}
void vorbis_lpc_predict(float *coeff,float *prime,int m,
float *data,long n){
float *data,long n, float *work){
/* in: coeff[0...m-1] LPC coefficients
prime[0...m-1] initial values (allocated size of n+m-1)
@ -135,7 +135,7 @@ void vorbis_lpc_predict(float *coeff,float *prime,int m,
long i,j,o,p;
float y;
float work[m+n];
//float work[m+n];
if(!prime)
for(i=0;i<m;i++)

View File

@ -22,6 +22,6 @@
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
float *data,long n);
float *data,long n,float *work);
#endif