Core Audio output: Add sanity checking for supported formats, and support 64 bit float input data, in case anything actually uses that

CQTexperiment
Christopher Snowhill 2022-01-11 17:09:06 -08:00
parent 4dd46a1b5b
commit ee05fe9e44
1 changed files with 52 additions and 10 deletions

View File

@ -300,6 +300,14 @@ static void convert_u32_to_s32(int32_t *buffer, size_t count)
} }
} }
static void convert_f64_to_f32(float *output, double *input, size_t count)
{
for (size_t i = 0; i < count; ++i)
{
output[i] = (float)(input[i]);
}
}
static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes) static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes)
{ {
size_t i; size_t i;
@ -338,6 +346,25 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
buffer += 4; buffer += 4;
} }
break; break;
case 8:
for (i = 0; i < bytes; i += 8)
{
temp = buffer[7];
buffer[7] = buffer[0];
buffer[0] = temp;
temp = buffer[6];
buffer[6] = buffer[1];
buffer[1] = temp;
temp = buffer[5];
buffer[5] = buffer[2];
buffer[2] = temp;
temp = buffer[4];
buffer[4] = buffer[3];
buffer[3] = temp;
buffer += 8;
}
break;
} }
} }
@ -442,6 +469,8 @@ tryagain:
size_t bytesReadFromInput = [self readData:inputBuffer + amountToSkip amount:(int)amountToWrite] + amountToSkip; size_t bytesReadFromInput = [self readData:inputBuffer + amountToSkip amount:(int)amountToWrite] + amountToSkip;
BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat);
if (bytesReadFromInput && if (bytesReadFromInput &&
(inputFormat.mFormatFlags & kAudioFormatFlagIsBigEndian)) (inputFormat.mFormatFlags & kAudioFormatFlagIsBigEndian))
{ {
@ -449,12 +478,19 @@ tryagain:
convert_be_to_le(inputBuffer, inputFormat.mBitsPerChannel, bytesReadFromInput); convert_be_to_le(inputBuffer, inputFormat.mBitsPerChannel, bytesReadFromInput);
} }
if (bytesReadFromInput && if (bytesReadFromInput && isFloat && inputFormat.mBitsPerChannel == 64)
!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat)) {
// Time for precision loss from weird inputs
samplesRead = bytesReadFromInput / sizeof(double);
convert_f64_to_f32(inputBuffer + bytesReadFromInput, inputBuffer, samplesRead);
memmove(inputBuffer, inputBuffer + bytesReadFromInput, samplesRead * sizeof(float));
bytesReadFromInput = samplesRead * sizeof(float);
}
if (bytesReadFromInput && !isFloat)
{ {
size_t bitsPerSample = inputFormat.mBitsPerChannel; size_t bitsPerSample = inputFormat.mBitsPerChannel;
BOOL isUnsigned = !(inputFormat.mFormatFlags & kAudioFormatFlagIsSignedInteger); BOOL isUnsigned = !(inputFormat.mFormatFlags & kAudioFormatFlagIsSignedInteger);
BOOL isFloat = NO;
if (bitsPerSample <= 8) { if (bitsPerSample <= 8) {
samplesRead = bytesReadFromInput; samplesRead = bytesReadFromInput;
if (isUnsigned) if (isUnsigned)
@ -679,6 +715,12 @@ static float db_to_scale(float db)
inputFormat = inf; inputFormat = inf;
outputFormat = outf; outputFormat = outf;
// These are the only sample formats we support translating
BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat);
if ((!isFloat && !(inputFormat.mBitsPerChannel >= 1 && inputFormat.mBitsPerChannel <= 32))
|| (isFloat && !(inputFormat.mBitsPerChannel == 32 || inputFormat.mBitsPerChannel == 64)))
return NO;
// These are really placeholders, as we're doing everything internally now // These are really placeholders, as we're doing everything internally now
floatFormat = inputFormat; floatFormat = inputFormat;