5

我是 iOS 及其 C 基础的新手,但不是一般的编程新手。我的困境是这样的。我正在基于复杂 AudioUnits 的应用程序中实现回声效果。该应用程序需要混响、回声和压缩等。但是,只有当我为我的应用程序中生成的音频样本使用特定的AudioStreamBasicDescription格式时,回声才能正常工作。但是,这种格式不适用于其他 AudioUnit。虽然还有其他方法可以解决这个问题,但修复回显算法中的位旋转可能是最直接的方法。

与 echo 一起使用的* 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

除了 mFormatFlag 之外,与AudioUnits一起使用的流格式是相同的: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 格式。显然有些不同,但我不知道是什么。

感谢您阅读这个长长的问题,并提前感谢您提供的任何见解。

4

1 回答 1

12

kAudioFormatFlagIsFloat表示缓冲区包含浮点值。如果mBitsPerChannel是 32,那么您正在处理float数据(也称为 Float32),如果是 64,那么您正在处理double数据。

kAudioFormatFlagsNativeEndian指的是缓冲区中的数据与处理器的字节序匹配,因此您不必担心字节交换。

kAudioFormatFlagIsPacked意味着数据中的每一位都是重要的。例如,如果您以 32 位存储 24 位音频数据,则不会设置此标志。

kAudioFormatFlagIsNonInterleaved意味着每个单独的缓冲区由一个数据通道组成。音频数据通常是交错的,样本在 L 和 R 通道之间交替:LRLRLRLR. 对于 DSP 应用,通常更容易对数据进行去交错处理并一次在一个通道上工作。

我认为在您的情况下,错误是您将浮点数据视为定点。浮点数据通常缩放到区间 [-1, +1)。要转换floatSInt16您需要将每个样本乘以最大 16 位值 ( 1u << 15, 32768),然后剪辑到区间 [-32768, 32767]。

于 2012-04-11T13:12:25.430 回答