Сдвиг аудиосэмплов из Float32 в SInt16 приводит к сильному клиппированию

Я новичок в iOS и ее основах C, но не в программировании в целом. Моя дилемма такова. Я реализую эффект эха в сложном приложении на основе AudioUnits. Приложение, среди прочего, нуждается в реверберации, эхе и сжатии. Однако эхо работает правильно, только когда я использую определенный формат AudioStreamBasicDescriptionдля аудиосэмплов, созданных в моем приложении. Однако этот формат не работает с другими AudioUnits. Хотя есть и другие способы решения этой проблемы, исправление перестановки битов в эхо-алгоритме может быть самым прямым подходом.

* AudioStreamBasicDescription*, который работает с эхом, имеет mFormatFlagиз: kAudioFormatFlagsAudioUnitCanonical; Его особенности:

AudioUnit Stream Format (ECHO works, NO AUDIO UNITS)
Sample Rate:              44100
Format ID:                 lpcm
Format Flags:              3116 = kAudioFormatFlagsAudioUnitCanonical
Bytes per Packet:             4
Frames per Packet:            1
Bytes per Frame:              4
Channels per Frame:           2
Bits per Channel:            32
Set ASBD on input
Set ASBD on  output
au SampleRate rate: 0.000000, 2 channels, 12 formatflags, 1819304813 mFormatID, 16 bits per channel

Формат потока, который работает с AudioUnits, тот же, за исключением mFormatFlag: kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved-- Его особенности таковы:

AudioUnit Stream Format (NO ECHO, AUDIO UNITS WORK)
Sample Rate:              44100
Format ID:                 lpcm
Format Flags:                41 
Bytes per Packet:             4
Frames per Packet:            1
Bytes per Frame:              4
Channels per Frame:           2
Bits per Channel:            32
Set ASBD on input
Set ASBD on  output
au SampleRate rate: 44100.000000, 2 channels, 41 formatflags, 1819304813 mFormatID, 32 bits per channel

Чтобы создать эффект эха, я использую две функции, которые сдвигают данные выборки в пространство SInt16и обратно.Как я уже сказал, это работает для формата kAudioFormatFlagsAudioUnitCanonical, но не для другого. Когда это не удается, звуки обрезаются и искажаются, но они есть. Я думаю, это указывает на то, что разница между этими двумя форматами заключается в том, как данные расположены в Float32.

// convert sample vector from fixed point 8.24 to SInt16
void fixedPointToSInt16( SInt32 * source, SInt16 * target, int length ) {
    int i;
    for(i = 0;i < length; i++ ) {
        target[i] =  (SInt16) (source[i] >> 9);
        //target[i] *= 0.003;

    }
}

*Как видите, я попытался изменить амплитуду сэмплов, чтобы избавиться от клиппирования --ясно, что это не сработало.

// convert sample vector from SInt16 to fixed point 8.24 
void SInt16ToFixedPoint( SInt16 * source, SInt32 * target, int length ) {
    int i;
    for(i = 0;i < length; i++ ) {
        target[i] =  (SInt32) (source[i] << 9);
        if(source[i] < 0) { 
            target[i] |= 0xFF000000;
        }
        else {
            target[i] &= 0x00FFFFFF;
        }
    }
}

Если я могу определить разницу между kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved, то я могу соответствующим образом изменить вышеуказанные методы. Но я не уверен, как это понять. Документация в CoreAudio загадочна, но из того, что я там прочитал и почерпнул из файла CoreAudioTypes.h, оба mFormatFlag(s) относятся к одному и тому же формату Fixed Point 8.24. Явно что-то не так, но не могу понять что.

Спасибо, что прочитали этот длинный вопрос, и заранее спасибо за любую информацию, которую вы можете дать.

5
задан Joshua Weinberg 10 April 2012 в 00:02
поделиться