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
|
@ -243,13 +243,13 @@ static void upmix(float * buffer, int inchannels, int outchannels, size_t count)
|
|||
void scale_by_volume(float * buffer, size_t count, float volume)
|
||||
{
|
||||
if ( volume != 1.0 )
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
buffer[i] *= volume;
|
||||
}
|
||||
|
||||
static void convert_u8_to_s16(int16_t *output, uint8_t *input, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
uint16_t sample = (input[i] << 8) | input[i];
|
||||
sample ^= 0x8080;
|
||||
|
@ -259,7 +259,7 @@ static void convert_u8_to_s16(int16_t *output, uint8_t *input, size_t count)
|
|||
|
||||
static void convert_s8_to_s16(int16_t *output, uint8_t *input, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
uint16_t sample = (input[i] << 8) | input[i];
|
||||
output[i] = (int16_t)(sample);
|
||||
|
@ -268,7 +268,7 @@ static void convert_s8_to_s16(int16_t *output, uint8_t *input, size_t count)
|
|||
|
||||
static void convert_u16_to_s16(int16_t *buffer, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
buffer[i] ^= 0x8000;
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ static void convert_u16_to_s16(int16_t *buffer, size_t count)
|
|||
|
||||
static void convert_s24_to_s32(int32_t *output, uint8_t *input, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
int32_t sample = (input[i * 3] << 8) | (input[i * 3 + 1] << 16) | (input[i * 3 + 2] << 24);
|
||||
output[i] = sample;
|
||||
|
@ -285,7 +285,7 @@ static void convert_s24_to_s32(int32_t *output, uint8_t *input, size_t count)
|
|||
|
||||
static void convert_u24_to_s32(int32_t *output, uint8_t *input, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
int32_t sample = (input[i * 3] << 8) | (input[i * 3 + 1] << 16) | (input[i * 3 + 2] << 24);
|
||||
output[i] = sample ^ 0x80000000;
|
||||
|
@ -294,12 +294,20 @@ static void convert_u24_to_s32(int32_t *output, uint8_t *input, size_t count)
|
|||
|
||||
static void convert_u32_to_s32(int32_t *buffer, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i )
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
buffer[i] ^= 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -338,6 +346,25 @@ static void convert_be_to_le(uint8_t *buffer, size_t bitsPerSample, size_t bytes
|
|||
buffer += 4;
|
||||
}
|
||||
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;
|
||||
|
||||
BOOL isFloat = !!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat);
|
||||
|
||||
if (bytesReadFromInput &&
|
||||
(inputFormat.mFormatFlags & kAudioFormatFlagIsBigEndian))
|
||||
{
|
||||
|
@ -449,12 +478,19 @@ tryagain:
|
|||
convert_be_to_le(inputBuffer, inputFormat.mBitsPerChannel, bytesReadFromInput);
|
||||
}
|
||||
|
||||
if (bytesReadFromInput &&
|
||||
!(inputFormat.mFormatFlags & kAudioFormatFlagIsFloat))
|
||||
if (bytesReadFromInput && isFloat && inputFormat.mBitsPerChannel == 64)
|
||||
{
|
||||
// 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;
|
||||
BOOL isUnsigned = !(inputFormat.mFormatFlags & kAudioFormatFlagIsSignedInteger);
|
||||
BOOL isFloat = NO;
|
||||
if (bitsPerSample <= 8) {
|
||||
samplesRead = bytesReadFromInput;
|
||||
if (isUnsigned)
|
||||
|
@ -679,6 +715,12 @@ static float db_to_scale(float db)
|
|||
inputFormat = inf;
|
||||
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
|
||||
|
||||
floatFormat = inputFormat;
|
||||
|
|
Loading…
Reference in New Issue