【问题标题】:iOS Core Audio : Converting between kAudioFormatFlagsCanonical and kAudioFormatFlagsAudioUnitCanonicaliOS 核心音频:在 kAudioFormatFlagsCanonical 和 kAudioFormatFlagsAudioUnitCanonical 之间转换
【发布时间】:2013-05-10 08:26:51
【问题描述】:

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

        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 转换器音频单元(这是有原因的)。

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

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

谢谢。

【问题讨论】:

  • 为什么不能使用苹果转换器?
  • 我使用的音频引擎不支持音频渲染中的功能所需的格式(第一种格式)。简而言之,目前没有办法将转换器放入我想要使用的音频引擎中,而不需要破解它。在这个音频引擎之外,在我自己的 AUGraph 和项目中,使用转换器工作。

标签: ios macos core-audio


【解决方案1】:

好吧,如果您参考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 位表示小数部分(小数点后的数字) )。 (Further reading)

在 iOS 音频单元中,有一个细微的差别 - 这个浮点数(通常)在 [-1, 1) ([-1.000000000000, +0.999969482421875] to be exact) 范围内。此范围之外的值在转换为 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 得到获得所需范围内的值。

虽然我自己没有尝试过 - 您可能需要在这里和那里调整一些东西。

【讨论】:

  • 您好,转换成 32 位数字怎么样?它与 16 位数字有何不同?这实际上是我的问题。
  • 只需将32768 更改为0x80000000 (2^31)。
  • @lppier 我不想问,但如果答案解决了你的问题,请奖励赏金。
  • 您好,我已经找到了另一种方法来编写我的代码,所以我没有尝试过。但解释看起来没问题,谢谢!
【解决方案2】:

也许是一个迟到的答案,但由于某种原因移位位方法对我不起作用,我在音频图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);
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 2018-10-13
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    相关资源
    最近更新 更多