Cog Audio: Make it possible to play obscene sample rate files without major failures
parent
5aa3f7dd0a
commit
903b457a28
|
@ -48,6 +48,9 @@
|
||||||
|
|
||||||
size_t floatConvertedSize;
|
size_t floatConvertedSize;
|
||||||
float floatConvertedLast[CHUNK_SIZE];
|
float floatConvertedLast[CHUNK_SIZE];
|
||||||
|
|
||||||
|
void *extrapolateBuffer;
|
||||||
|
size_t extrapolateBufferSize;
|
||||||
|
|
||||||
AudioStreamBasicDescription inputFormat;
|
AudioStreamBasicDescription inputFormat;
|
||||||
AudioStreamBasicDescription floatFormat;
|
AudioStreamBasicDescription floatFormat;
|
||||||
|
|
|
@ -62,6 +62,9 @@ void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
|
||||||
|
|
||||||
refillNode = nil;
|
refillNode = nil;
|
||||||
originalPreviousNode = nil;
|
originalPreviousNode = nil;
|
||||||
|
|
||||||
|
extrapolateBuffer = NULL;
|
||||||
|
extrapolateBufferSize = 0;
|
||||||
|
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil];
|
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.volumeScaling" options:0 context:nil];
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.outputResampling" 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 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;
|
const size_t delta = (backward ? -1 : 1) * channels;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
float lpc[extrapolate_order];
|
size_t newSize = lpc_size + my_work_size + their_work_size;
|
||||||
float work[frameSize];
|
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++)
|
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_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;
|
chPcmBuf = buffer + ch + (backward ? frameSize : -1) * channels;
|
||||||
for (size_t i = 0; i < frameSize; i++) *(chPcmBuf += delta) = work[i];
|
for (size_t i = 0; i < frameSize; i++) *(chPcmBuf += delta) = work[i];
|
||||||
|
@ -465,6 +480,12 @@ tryagain:
|
||||||
// Approximately the most we want on input
|
// Approximately the most we want on input
|
||||||
ioNumberPackets = (amount - amountRead) / outputFormat.mBytesPerPacket;
|
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;
|
size_t newSize = ioNumberPackets * floatFormat.mBytesPerPacket;
|
||||||
if (!inputBuffer || inputBufferSize < newSize)
|
if (!inputBuffer || inputBufferSize < newSize)
|
||||||
inputBuffer = realloc( inputBuffer, inputBufferSize = newSize * 3 );
|
inputBuffer = realloc( inputBuffer, inputBufferSize = newSize * 3 );
|
||||||
|
@ -499,7 +520,7 @@ tryagain:
|
||||||
|
|
||||||
memcpy(((uint8_t*)floatConvertedLast) + floatConvertedSize, inputBuffer, inpSize);
|
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;
|
newSize = ioNumberPackets * floatFormat.mBytesPerPacket;
|
||||||
|
|
||||||
|
@ -510,7 +531,7 @@ tryagain:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, newSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO );
|
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, newSize / floatFormat.mBytesPerPacket, extrapolateEnd, NO, &extrapolateBuffer, &extrapolateBufferSize );
|
||||||
|
|
||||||
inpOffset = inpSize;
|
inpOffset = inpSize;
|
||||||
inpSize = newSize;
|
inpSize = newSize;
|
||||||
|
@ -644,7 +665,7 @@ tryagain:
|
||||||
// Extrapolate start
|
// Extrapolate start
|
||||||
if (extrapolateStart)
|
if (extrapolateStart)
|
||||||
{
|
{
|
||||||
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, bytesReadFromInput / floatFormat.mBytesPerPacket, extrapolateStart, YES);
|
extrapolate( inputBuffer, floatFormat.mChannelsPerFrame, bytesReadFromInput / floatFormat.mBytesPerPacket, extrapolateStart, YES, &extrapolateBuffer, &extrapolateBufferSize);
|
||||||
extrapolateStart = 0;
|
extrapolateStart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,6 +1006,12 @@ static float db_to_scale(float db)
|
||||||
resampler = NULL;
|
resampler = NULL;
|
||||||
resampler_data = NULL;
|
resampler_data = NULL;
|
||||||
}
|
}
|
||||||
|
if (extrapolateBuffer)
|
||||||
|
{
|
||||||
|
free(extrapolateBuffer);
|
||||||
|
extrapolateBuffer = NULL;
|
||||||
|
extrapolateBufferSize = 0;
|
||||||
|
}
|
||||||
if (floatBuffer)
|
if (floatBuffer)
|
||||||
{
|
{
|
||||||
free(floatBuffer);
|
free(floatBuffer);
|
||||||
|
|
|
@ -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,
|
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
|
/* in: coeff[0...m-1] LPC coefficients
|
||||||
prime[0...m-1] initial values (allocated size of n+m-1)
|
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;
|
long i,j,o,p;
|
||||||
float y;
|
float y;
|
||||||
float work[m+n];
|
//float work[m+n];
|
||||||
|
|
||||||
if(!prime)
|
if(!prime)
|
||||||
for(i=0;i<m;i++)
|
for(i=0;i<m;i++)
|
||||||
|
|
|
@ -22,6 +22,6 @@
|
||||||
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
|
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,
|
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||||
float *data,long n);
|
float *data,long n,float *work);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue