3

我需要在这种格式之间进行转换:

        format.mSampleRate  = 44100.0; 
        format.mFormatID = kAudioFormatLinearPCM;
        format.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
        format.mBytesPerPacket = sizeof(AudioUnitSampleType);
        format.mFramesPerPacket = 1;
        format.mBytesPerFrame = sizeof(AudioUnitSampleType);
        format.mChannelsPerFrame = 2 ;
        format.mBitsPerChannel = sizeof(AudioUnitSampleType)*8;

和这种格式

format.mSampleRate  = 44100.0; 
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
format.mBytesPerPacket = sizeof(AudioUnitSampleType);
format.mFramesPerPacket = 1;
format.mBytesPerFrame = sizeof(AudioUnitSampleType);
format.mChannelsPerFrame = 2; 
format.mBitsPerChannel = sizeof(AudioUnitSampleType)*8;

在音频渲染回调的范围内,其中有以下代码,buffer[] 是第二种格式,array[] 需要第一种格式。

for (k = 0; k < channels; k++){
    buffer = (AudioUnitSampleType *) ioData->mBuffers[k].mData;
    for(j=0; j < samples; j++){
        array[j] = buffer[j];
    }
}

我知道您可以使用 Apple 转换器单元,但在我的情况下我不能使用 Apple Converter 音频单元(这是有原因的)。

基本上,这两种格式之间的唯一区别是 format.mFormatFlags (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift) 的以下标志。

如何将 buffer[](包含第二种格式的数据)转换为 array[](包含第一种格式的数据),反之亦然?

谢谢你。

4

2 回答 2

6

好吧,如果您参考 上的文档kAudioFormatFlagsAudioUnitCanonical,您会看到:

kAudioFormatFlagsAudioUnitCanonical The flags for the canonical audio unit sample 
type. This matches AudioUnitSampleType.

The canonical audio sample type for audio units and other audio processing in 
iPhone OS is noninterleaved linear PCM with 8.24-bit fixed-point samples.

因此,buffer[]数组中的样本是 8.24 位定点格式。这是什么意思?

8.24 位定点格式用于表示具有固定精度的浮点数 - 一个 32 位整数,其中前 8 位表示整个部分,后 24 位表示小数部分(小数点后的数字)。(进一步阅读

在 iOS 音频单元中,有一个细微的差别——这个浮点数(通常)在 [-1, 1) 范围内(准确地说是 [-1.000000000000, +0.999969482421875])。此范围之外的值在转换为 16 位 PCM 时会被简单地截断。您可以验证前 8 位在大多数情况下是 0x00 或 0xff(二进制补码中的 -1)。

要将此表示形式转换为 16 位数字,请使用以下命令:

SIGN((SInt8)(val >> 24)) * 32768 * (val & 0xFFFFFF)/(float)(1<<24)

即:从 8 MSB 中提取符号,从 24 LSB 中提取小数值,然后除以 24 位整数 (2^24) 的范围,得到 0 和 1 之间的浮点数,最后乘以 32768 得到一个值在想要的范围内。

不过,我自己还没有尝试过——你可能需要在这里和那里调整一些东西。

于 2013-05-17T10:43:11.640 回答
0

也许是一个迟到的答案,但是由于某种原因移位位方法对我不起作用,我发现这个替代方法效果很好,在音频图https://github.com/tkzic/audiograph

我从那里调整了一些方法,瞧:

void ConvertInputToInt16(AudioStreamBasicDescription inFormat, void *buf, void *outputBuf, size_t capacity)
 {  
   AudioConverterRef converter;
    OSStatus err;

    size_t bytesPerSample = sizeof(SInt16);
    AudioStreamBasicDescription outFormat = {0};
    outFormat.mFormatID = kAudioFormatLinearPCM;
    outFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    outFormat.mBitsPerChannel = 8 * bytesPerSample;
    outFormat.mFramesPerPacket = 1;
    outFormat.mChannelsPerFrame = 1;
    outFormat.mBytesPerPacket = bytesPerSample * outFormat.mFramesPerPacket;
    outFormat.mBytesPerFrame = bytesPerSample * outFormat.mChannelsPerFrame;
    outFormat.mSampleRate = inFormat.mSampleRate;

    NSLog(@"description for in format: %@", descriptionForAudioFormat(inFormat));
    NSLog(@"description for out format: %@", descriptionForAudioFormat(outFormat));

    UInt32 inSize = capacity*sizeof(SInt32);
    UInt32 outSize = capacity*sizeof(SInt16);

    // this is the famed audio converter

    err = AudioConverterNew(&inFormat, &outFormat, &converter);
    if(noErr != err) {
        NSLog(@"error in audioConverterNew: %d", (int)err);
    }


    err = AudioConverterConvertBuffer(converter, inSize, buf, &outSize, outputBuf);
    if(noErr != err) {
        NSLog(@"error in audioConverterConvertBuffer: %d", err);
    }

}
于 2014-07-03T15:10:12.820 回答