Core Audio output: Add sanity checking for supported formats, and support 64 bit float input data, in case anything actually uses that
parent
4dd46a1b5b
commit
ee05fe9e44
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue