7

我正在使用音频单元框架在 mac os x 上开发一个 VOIP 应用程序。在我的程序中,我设置了一个输入 AUHAL 并使用默认的流格式(44.1kHz,32bit/channel)从麦克风捕获音频。在这种情况下,我的程序运行良好。

这是代码:

//The default setting in my program
CheckError(AudioUnitGetProperty(m_audCapUnit,
                                        kAudioUnitProperty_StreamFormat,
                                        kAudioUnitScope_Output,     //the value is 0
                                        inputBus,           //the value is 1
                                        &m_audCapUnitOutputStreamFormat,
                                        &propertySize),
                   "Couldn't get OutputSample ASBD from input unit") ;  

    //the inOutputSampleRate is 44100.0
        m_audCapUnitOutputStreamFormat.mSampleRate = inOutputSampleRate ; 

CheckError(AudioUnitSetProperty(m_audCapUnit,
                                        kAudioUnitProperty_StreamFormat,
                                        kAudioUnitScope_Output,
                                        inputBus,
                                        &m_audCapUnitOutputStreamFormat,
                                        propertySize),
                   "Couldn't set OutputSample ASBD on input unit"); 

//

由于我正在开发一个 VOIP 应用程序,默认格式(44.1kHz,32bits/Channel)不适合我的程序,所以我想将采样率更改为 8kHz。我编写了这段代码来更改程序中的格式:

//......
    inOutputFormat.mSampleRate = 8000.  ;
    inOutputFormat.mFormatID = kAudioFormatLinearPCM ;
    inOutputFormat.mChannelsPerFrame = 2 ;
    inOutputFormat.mBitsPerChannel  = 16 ;
    inOutputFormat.mBytesPerFrame = 2 ;
    inOutputFormat.mBytesPerPacket = 2 ;
    inOutputFormat.mFramesPerPacket = 1 ;
    inOutputFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical ;   
    inOutputFormat.mReserved = 0 ;



    CheckError(AudioUnitSetProperty(m_audCapUnit,
                                    kAudioUnitProperty_StreamFormat,
                                    kAudioUnitScope_Output,
                                    inputBus, 
                                    &inOutputFormat, 
                                    ui32PropSize),
               "Couldn't set AUHAL Unit Output Format") ;

//.......

在这种情况下,程序运行良好,直到我的程序调用AudioUnitRender回调函数中的 它无法使用文档中AudioUnitRender的错误代码-10876调用 kAudioUnitErr_NoConnection。错误代码让我很困惑,所以我用谷歌搜索了它,但找不到任何有用的信息。有人可以告诉我错误的实际含义吗?

这还没有结束,我通过这段代码再次更改了格式:

//.....
    inOutputFormat.mSampleRate = 8000.  ;
    inOutputFormat.mFormatID = kAudioFormatLinearPCM ;
    inOutputFormat.mChannelsPerFrame = 2 ;
    inOutputFormat.mBitsPerChannel  = 32 ;
    inOutputFormat.mBytesPerFrame = 4 ;
    inOutputFormat.mBytesPerPacket = 4 ;
    inOutputFormat.mFramesPerPacket = 1 ;
    inOutputFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical ;   
    inOutputFormat.mReserved = 0 ;



    CheckError(AudioUnitSetProperty(m_audCapUnit,
                                    kAudioUnitProperty_StreamFormat,
                                    kAudioUnitScope_Output,
                                    inputBus, 
                                    &inOutputFormat, 
                                    ui32PropSize),
               "Couldn't set AUHAL Unit Output Format") ;
//........

在这种情况下,程序AudioUnitRender再次调用失败并返回另一个错误代码-10863(kAudioUnitErr_CannotDoInCurrentContext)。我用谷歌搜索了它,但我发现 了一些有用的东西。阅读那里的信息后,我猜我在 AUHAL 上设置的采样率或格式可能不受硬件支持。

所以我写了一些代码来检查默认输入设备上的可用采样率:

//..........
    UInt32 propertySize = sizeof(AudioDeviceID) ;
    Boolean isWritable = false ;

    CheckError(AudioDeviceGetPropertyInfo(inDeviceID,       //the inDeviceID is the default input device
                                          0,
                                          true,
                                          kAudioDevicePropertyAvailableNominalSampleRates,
                                          &propertySize, 
                                          &isWritable), 
               "Get the Available Sample Rate Count Failed") ;

    m_valueCount = propertySize / sizeof(AudioValueRange) ;
    printf("Available %d Sample Rate\n",m_valueCount) ;

    CheckError(AudioDeviceGetProperty(inDeviceID,
                                      0,
                                      false,
                                      kAudioDevicePropertyAvailableNominalSampleRates, 
                                      &propertySize, 
                                      m_valueTabe), 
               "Get the Available Sample Rate Count Failed") ;


    for(UInt32 i = 0 ; i < m_valueCount ; ++i)
    {
        printf("Available Sample Rate value : %ld\n",(long)m_valueTabe[i].mMinimum) ;
    }
//..............

然后我发现可用的采样率是 8000、16000、32000、44100、48000、88200 和 96000。

8000的采样率是我刚才设置的,但是调用得到错误码AudioUnitRender,我只想说,为什么?

google了这么多,也看了很多文档,都没有得到答案,有没有人能解决我遇到的这个问题?</p>

换句话说; 如何在仅输入的 AUHAL 上更改采样率或格式?</p>

4

3 回答 3

4

最后我昨天自己解决了这个问题。

这是我的解决方案:

  1. 首先,我使用AudioDeviceGetProperty在我的默认输入设备上获取可用格式列表,然后我发现可用格式列表包含:(8khz, 16khz, 32khz, 44.1khz, 48khz, 88.2khz,96khz我只是在这里列出了采样率字段,但列表中还有其他字段)。
  2. 然后我选择在第一步中获得的可用格式之一。以我的程序为例, 我选择格式(8khz,32bits/Channel)并用于AudioDeviceSetProperty 在默认设备上设置它,而不是在 AUHAL 上,这是我的程序在 AUHAL(OutputScope,inputBus)上设置格式后正常工作的关键。
  3. 最后一步,我使用AudioUnitSetProperty设置我想要的格式,程序运行正常。

通过这个问题和解决方案,我想如果我想在仅输入的 AUHAL 上设置格式,格式必须匹配或者可以转换为输入设备正在使用的可用格式。所以我需要做的是首先在输入设备上设置格式,然后在仅输入的 AUHAL 上设置格式。

于 2013-08-10T02:17:58.120 回答
2

根据我的经验,使用 44.1kHz 和 16 位音频以外的设置会导致各种奇怪的错误。一些通用建议可能会让您走上正确的道路:

  • 试试 Novocaine ( https://github.com/alexbw/novocaine )。它确实消除了使用 AudioUnits 的痛苦。
  • 尝试让您的应用程序使用 44.1kHz,然后自己对音频进行下采样。
  • 您设置的比特率可能与所需的采样率不兼容。
于 2013-08-09T15:08:32.427 回答
1

你的回答对我很有帮助。但是,AudioDeviceGetProperty 的使用已被贬低。以下清单可能有助于使事情保持最新。例如,采样率设置为 32 kHz。

 // Get the available sample rates of the default input device.
defaultDeviceProperty.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;


CheckError    (AudioObjectGetPropertyDataSize(defaultDevice,
                                   &defaultDeviceProperty,
                                   0,
                                   NULL,
                                   &propertySize),
            "Couldn't get sample rate count");
int m_valueCount = propertySize / sizeof(AudioValueRange) ;

printf("Available %d Sample Rates\n",m_valueCount) ;

AudioValueRange m_valueTabe[m_valueCount];

CheckError    (AudioObjectGetPropertyData(defaultDevice,
                                          &defaultDeviceProperty,
                                          0,
                                          NULL,
                                          &propertySize,
                                          m_valueTabe),
               "Couldn't get available sample rates");


for(UInt32 i = 0 ; i < m_valueCount ; ++i)
{
    printf("Available Sample Rate value : %f\n", m_valueTabe[i].mMinimum) ;
}

// Set the sample rate to one of the available values.
AudioValueRange inputSampleRate;
inputSampleRate.mMinimum = 32000;
inputSampleRate.mMaximum = 32000;
defaultDeviceProperty.mSelector = kAudioDevicePropertyNominalSampleRate;
CheckError    (AudioObjectSetPropertyData(defaultDevice,
                                          &defaultDeviceProperty,
                                          0,
                                          NULL,
                                          sizeof(inputSampleRate),
                                          &inputSampleRate),
               "Couldn't get available sample rates");
于 2015-01-29T16:31:53.370 回答