【问题标题】:Is kAudioFormatFlagIsFloat supported on iPhoneOS?iPhoneOS 是否支持 kAudioFormatFlagIsFloat?
【发布时间】:2011-02-22 08:18:04
【问题描述】:

我正在编写一个 iPhone 应用程序,该应用程序使用 Apple's recommendations 的 I/O 音频单元同时录制和播放音频。

我想在播放之前对录制的音频应用一些音效(混响等)。为了使这些效果正常工作,我需要样本是浮点数,而不是整数。通过在mFormatFlags 上设置kAudioFormatFlagIsFloat 来创建AudioStreamBasicDescription,这似乎应该是可能的。这是我的代码的样子:

AudioStreamBasicDescription streamDescription;

streamDescription.mSampleRate = 44100.0;
streamDescription.mFormatID = kAudioFormatLinearPCM;
streamDescription.mFormatFlags = kAudioFormatFlagIsFloat;
streamDescription.mBitsPerChannel = 32;
streamDescription.mBytesPerFrame = 4;
streamDescription.mBytesPerPacket = 4;
streamDescription.mChannelsPerFrame = 1;
streamDescription.mFramesPerPacket = 1;
streamDescription.mReserved = 0;

OSStatus status;

status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescription, sizeof(streamDescription));
if (status != noErr)
  fprintf(stderr, "AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input) returned status %ld\n", status);

status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &streamDescription, sizeof(streamDescription));
if (status != noErr)
  fprintf(stderr, "AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output) returned status %ld\n", status);

但是,当我运行这个(在运行 iPhoneOS 3.1.3 的 iPhone 3GS 上)时,我得到了这个:

AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input) returned error -10868
AudioUnitSetProperty (kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output) returned error -10868

(-10868 是kAudioUnitErr_FormatNotSupported 的值)

我在 Apple 的文档中没有发现任何有价值的东西,除了 recommendation 坚持使用 16 位小端整数。但是,aurioTouch 示例项目至少包含一些与kAudioFormatFlagIsFloat 相关的支持代码。

那么,是我的流描述不正确,还是 iPhoneOS 根本不支持 kAudioFormatFlagIsFloat

【问题讨论】:

    标签: iphone audiounit


    【解决方案1】:

    据我所知,不支持。您可以很容易地转换为浮点数,尽管使用 AudioConverter。我实时进行此转换(两种方式)以将 Accelerate 框架与 iOS 音频一起使用。 (注意:此代码是从更模块化的代码中复制粘贴的,因此可能存在一些小错别字)

    首先,您需要输入中的 AudioStreamBasicDescription。说

    AudioStreamBasicDescription aBasicDescription = {0};
    aBasicDescription.mSampleRate       = self.samplerate;
    aBasicDescription.mFormatID         = kAudioFormatLinearPCM;
    aBasicDescription.mFormatFlags      = kAudioFormatFlagIsSignedInteger |     kAudioFormatFlagIsPacked;
    aBasicDescription.mFramesPerPacket          = 1;
    aBasicDescription.mChannelsPerFrame     = 1;
    aBasicDescription.mBitsPerChannel       = 8 * sizeof(SInt16);
    aBasicDescription.mBytesPerPacket       = sizeof(SInt16) * aBasicDescription.mFramesPerPacket;
    aBasicDescription.mBytesPerFrame        = sizeof(SInt16) * aBasicDescription.mChannelsPerFrame
    

    然后,为float生成对应的AudioStreamBasicDescription。

    AudioStreamBasicDescription floatDesc = {0};
    floatDesc.mFormatID = kAudioFormatLinearPCM;      
    floatDesc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked;
    floatDesc.mBitsPerChannel = 8 * sizeof(float);
    floatDesc.mFramesPerPacket = 1;                                          
    floatDesc.mChannelsPerFrame = 1;           
    floatDesc.mBytesPerPacket = sizeof(float) * floatDesc.mFramesPerPacket;                                                                            
    floatDesc.mBytesPerFrame = sizeof(float) * floatDesc.mChannelsPerFrame;                                                                                   
    floatDesc.mSampleRate = [controller samplerate];
    

    做一些缓冲。

    UInt32 intSize = inNumberFrames * sizeof(SInt16);
    UInt32 floatSize = inNumberFrames * sizeof(float);
    float *dataBuffer = (float *)calloc(numberOfAudioFramesIn, sizeof(float));
    

    然后转换。 (ioData 是包含 int 音频的 AudioBufferList)

    AudioConverterRef converter;
    OSStatus err = noErr;
    err = AudioConverterNew(&aBasicDescription, &floatDesct, &converter);
    //check for error here in "real" code
    err = AudioConverterConvertBuffer(converter, intSize, ioData->mBuffers[0].mData, &floatSize, dataBuffer);
    //check for error here in "real" code
    //do stuff to dataBuffer, which now contains floats
    //convert the floats back by running the conversion the other way
    

    【讨论】:

    • 自 iOS 9(至少)以来,iOS 上的内部(不能使用术语规范,因为它已被弃用!:-))格式似乎是 Float32 for AudioUnits 。你的东西很好用!
    【解决方案2】:

    我正在做与AudioUnits 无关的事情,但我在iOS 上使用AudioStreamBasicDescription。我可以通过指定来使用浮点样本:

    dstFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked;
    

    Learning Core Audio: A Hands-on Guide to Audio Programming for Mac and iOS 这本书对此很有帮助。

    【讨论】:

      【解决方案3】:

      支持。

      问题是您还必须在mFormatFlags 上设置kAudioFormatFlagIsNonInterleaved。如果在设置kAudioFormatFlagIsFloat时不这样做,会出现格式错误。

      所以,在准备 AudioStreamBasicDescription 时,你想做这样的事情:

      streamDescription.mFormatFlags = kAudioFormatFlagIsFloat | 
                                       kAudioFormatFlagIsNonInterleaved;
      

      至于为什么 iOS 需要这个,我不确定 - 我只是通过反复试验偶然发现它。

      【讨论】:

        【解决方案4】:

        来自 Core Audio 文档:

        kAudioFormatFlagIsFloat
          Set for floating point, clear for integer.
          Available in iPhone OS 2.0 and later.
          Declared in CoreAudioTypes.h.
        

        我对您的信息流了解不够,无法评论其 [in] 正确性。

        【讨论】:

          【解决方案5】:

          您可以通过以下 ASBD 设置获得交错浮动 RemoteIO:

          // STEREO_CHANNEL = 2, defaultSampleRate = 44100
          AudioStreamBasicDescription const audioDescription = {
                              .mSampleRate        = defaultSampleRate,
                              .mFormatID          = kAudioFormatLinearPCM,
                              .mFormatFlags       = kAudioFormatFlagIsFloat,
                              .mBytesPerPacket    = STEREO_CHANNEL * sizeof(float),
                              .mFramesPerPacket   = 1,
                              .mBytesPerFrame     = STEREO_CHANNEL * sizeof(float),
                              .mChannelsPerFrame  = STEREO_CHANNEL,
                              .mBitsPerChannel    = 8 * sizeof(float),
                              .mReserved          = 0
                          };
          

          这对我有用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-08-08
            • 1970-01-01
            • 1970-01-01
            • 2021-06-07
            • 2020-04-23
            • 2019-08-28
            • 2015-07-04
            • 2016-07-15
            相关资源
            最近更新 更多