我是iOS及其C基础的新手,但不是一般的编程。我的困境是这样的。我正在基于AudioUnits的复杂应用程序中实现回声效果。该应用程序需要混响,回声和压缩等功能。但是,当我在我的应用程序中生成的音频样本使用特定的 AudioStreamBasicDescription 格式时,回声才有效。但是,此格式不适用于其他AudioUnits。 虽然有其他方法可以解决这个问题,但修复回声算法中的位错可能是最直接的方法。
与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
与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)引用相同的不动点8.24格式。显然有些不同,但我无法弄清楚是什么。
感谢您阅读这个长期的问题,并提前感谢您提供的任何见解。
答案 0 :(得分:11)
kAudioFormatFlagIsFloat
表示缓冲区包含浮点值。如果mBitsPerChannel
为32,那么您正在处理float
数据(也称为Float32),如果是64,则表示您正在处理double
数据。
kAudioFormatFlagsNativeEndian
指的是缓冲区中的数据与处理器的字节顺序相匹配,因此您不必担心字节交换。
kAudioFormatFlagIsPacked
表示数据中的每一位都很重要。例如,如果以32位存储24位音频数据,则不会设置此标志。
kAudioFormatFlagIsNonInterleaved
表示每个缓冲区由一个数据通道组成。音频数据交错是常见的,样本在L和R通道之间交替:LRLRLRLR
。对于DSP应用,通常可以更容易地对数据进行解交织并一次在一个通道上工作。
我认为在您的情况下,错误是您将浮点数据视为固定点。浮点数据通常缩放到区间[-1,+ 1)。要将float
转换为SInt16
,您需要将每个样本乘以最大16位值(1u << 15
,32768),然后剪切到区间[-32768,32767]。