web-dev-qa-db-ja.com

AVAudioEngine Mic-Inputのフォーマットを指定するにはどうすればよいですか?

AVAudioEngineとユーザーのマイクを使用してオーディオを録音したいと思います。私はすでに実用的なサンプルを持っていますが、私が望む出力のフォーマットを指定する方法を理解することができません...

私の要件は、私が話しているようにAVAudioPCMBufferが必要であるということです。

トランスコーディングを行う別のノードを追加する必要がありますか?その問題に関するドキュメント/サンプルがあまり見つかりません...

そして、私はオーディオスタッフに関しても初心者です。最大サンプルレートが16000のPCM-16ビットを含むNSDataが必要なことはわかっています(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と同じである必要があるというエラーが生成されます。

どんな助けでも大歓迎です!!!

EDIT:AVAudioConverterを見つけましたが、iOS8とも互換性がある必要があります...

15
Georg

入力ノードと出力ノードでオーディオ形式を直接変更することはできません。マイクの場合、フォーマットは常に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などのオープンフレームワークを使用することをお勧めします。

16
Josh

サンプリングレートを変更するために働いたことがわかったのは、

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を使用してタップのハードウェアレートから変換します。 (バッファの長さが設定されておらず、結果が正しいかどうかを判断する方法がありません)

これはiOS12.3.1でした。

1
prewett

入力ノードの構成を変更することはできません。必要な形式でミキサーノードを作成し、エンジンに接続してから、入力ノードに接続してから、mainMixerを作成したノードに接続してください。これで、このノードにタップをインストールしてPCMデータを取得できます。

いくつかの奇妙な理由で、サンプルレートの選択肢があまりないことに注意してください!少なくともiOS9.1では、標準の11025、22050、または44100を使用してください。他のサンプルレートは失敗します。

0