如何指定AVAudioEngine Mic-Input的格式?

时间:2015-11-02 18:10:55

标签: ios avfoundation core-audio avaudioengine

我想使用AVAudioEngine和用户麦克风录制一些音频。我已经有了一个工作样本,但是我们无法弄清楚如何指定我想要的输出格式...

我的要求是我需要AVAudioPCMBuffer正如我所说的那样...

我是否需要添加一个进行转码的单独节点?我找不到关于这个问题的文档/样本......

对于Audio-Stuff而言,我也是一个菜鸟。我知道我希望NSData包含PCM-16bit,最大采样率为16000(8000会更好)

这是我的工作样本:

private var audioEngine = AVAudioEngine()

func startRecording() {

  let format = audioEngine.inputNode!.inputFormatForBus(bus)

  audioEngine.inputNode!.installTapOnBus(bus, bufferSize: 1024, format: format) { (buffer: AVAudioPCMBuffer, time:AVAudioTime) -> Void in

     let audioFormat = PCMBuffer.format
     print("\(audioFormat)")
  }

  audioEngine.prepare()
  do {
     try audioEngine.start()
  } catch { /* Imagine some super awesome error handling here */ }
}

如果我将格式更改为“'说

let format = AVAudioFormat(commonFormat: AVAudioCommonFormat.PCMFormatInt16, sampleRate: 8000.0, channels: 1, interleaved: false)

然后如果会产生错误,说明采样率需要与hwInput相同......

非常感谢任何帮助!!!

编辑:我刚刚找到AVAudioConverter但我需要兼容iOS8 ......

5 个答案:

答案 0 :(得分:11)

您无法直接在输入节点或输出节点上更改音频格式。在麦克风的情况下,格式将始终是44KHz,1通道,32位。为此,您需要在两者之间插入一台调音台。然后当你连接inputNode> changeformatMixer> mainEngineMixer,您可以指定所需格式的详细信息。

类似的东西:

var inputNode = audioEngine.inputNode
var downMixer = AVAudioMixerNode()

//I think you the engine's I/O nodes are already attached to itself by default, so we attach only the downMixer here:
audioEngine.attachNode(downMixer)

//You can tap the downMixer to intercept the audio and do something with it:
downMixer.installTapOnBus(0, bufferSize: 2048, format: downMixer.outputFormatForBus(0), block:  //originally 1024
            { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
                print(NSString(string: "downMixer Tap"))
                do{
                    print("Downmixer Tap Format: "+self.downMixer.outputFormatForBus(0).description)//buffer.audioBufferList.debugDescription)

        })

//let's get the input audio format right as it is
let format = inputNode.inputFormatForBus(0)
//I initialize a 16KHz format I need:
let format16KHzMono = AVAudioFormat.init(commonFormat: AVAudioCommonFormat.PCMFormatInt16, sampleRate: 11050.0, channels: 1, interleaved: true)

//connect the nodes inside the engine:
//INPUT NODE --format-> downMixer --16Kformat--> mainMixer
//as you can see I m downsampling the default 44khz we get in the input to the 16Khz I want 
audioEngine.connect(inputNode, to: downMixer, format: format)//use default input format
audioEngine.connect(downMixer, to: audioEngine.outputNode, format: format16KHzMono)//use new audio format
//run the engine
audioEngine.prepare()
try! audioEngine.start()

我建议使用开放式框架,例如EZAudio,而不是。

答案 1 :(得分:0)

您无法更改输入节点的配置,尝试使用所需格式创建混合器节点,将其附加到引擎,然后将其连接到输入节点,然后将mainMixer连接到刚刚创建的节点。现在,您可以在此节点上安装tap以获取PCM数据。

请注意,由于一些奇怪的原因,您没有多少选择采样率!至少在iOS 9.1上没有,使用标准11025,22050或44100.任何其他采样率都将失败!

答案 2 :(得分:0)

我发现唯一可以改变采样率的东西是

AVAudioSettings.sharedInstance().setPreferredSampleRate(...)

您可以点击engine.inputNode并使用输入节点的输出格式:

engine.inputNode.installTap(onBus: 0, bufferSize: 2048,
                            format: engine.inputNode.outputFormat(forBus: 0))

不幸的是,尽管似乎8000、12000、16000、22050、44100都可以正常工作,但不能保证将获得所需的采样率。

以下内容无效:

  1. 通过点击engine.inputNode设置我的自定义格式。 (例外)
  2. 添加具有我的自定义格式的混音器,然后点击它。 (例外)
  3. 添加一个混音器,将其与inputNode的格式连接,使用我的自定义格式将混音器连接至主混音器,然后移除outputNode的输入,以免将音频发送到扬声器并获得即时反馈。 (有效,但全为零)
  4. 在AVAudioEngine中根本不使用我的自定义格式,而在单击时使用AVAudioConverter从硬件速率转换。 (未设置缓冲区的长度,无法判断结果是否正确)

这是iOS 12.3.1。

答案 3 :(得分:0)

如果只需要更改采样率和通道,建议使用行级API。您无需使用混频器或转换器。在这里,您可以找到有关低级录音的Apple文档。如果需要,您将能够转换为Objective-C类并添加协议。

Audio Queue Services Programming Guide

答案 4 :(得分:0)

为了改变输入节点的采样率,你必须先将输入节点连接到一个混频器节点,并在参数中指定一个新的格式。

let input = avAudioEngine.inputNode
let mainMixer = avAudioEngine.mainMixerNode
let newAudioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)
avAudioEngine.connect(input, to: mainMixer, format: newAudioFormat)

现在您可以使用 newAudioFormat 在输入节点上调用 installTap 函数。

还有一点我想指出的是,自从iPhone12新推出以来,输入节点的默认采样率已经不再是44100了。已升级至 48000。