私は新しいAVAudioEngineに本当に興奮しています。オーディオユニットの優れたAPIラッパーのようです。残念ながら、ドキュメントは今のところ存在せず、単純なグラフを機能させるのに問題があります。
次の簡単なコードを使用してオーディオエンジングラフを設定すると、タップブロックが呼び出されることはありません。これは、Webに浮かんでいるサンプルコードの一部を模倣していますが、それらも機能しませんでした。
let inputNode = audioEngine.inputNode
var error: NSError?
let bus = 0
inputNode.installTapOnBus(bus, bufferSize: 2048, format: inputNode.inputFormatForBus(bus)) {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
println("sfdljk")
}
audioEngine.prepare()
if audioEngine.startAndReturnError(&error) {
println("started audio")
} else {
if let engineStartError = error {
println("error starting audio: \(engineStartError.localizedDescription)")
}
}
私が探しているのは、分析用の生のpcmバッファーだけです。エフェクトや出力は必要ありません。 WWDCの講演「502AudioEngine in Practice」によると、このセットアップは機能するはずです。
ここで、入力ノードからデータをキャプチャする場合は、ノードタップをインストールできます。これについては説明しました。
しかし、この特定の例で興味深いのは、入力ノードだけで作業したい場合、たとえばマイクからデータをキャプチャして調べたり、リアルタイムで分析したり、ファイルに書き込んだりする場合は、直接インストールできます。入力ノードをタップします。
そして、タップは、データの入力ノードをプルし、それをバッファーに詰めて、それをアプリケーションに戻す作業を行います。
そのデータを取得したら、それを使って必要なことは何でもできます。
これが私が試したいくつかのリンクです:
編集:これは、ThorstenKarrerの提案に基づく実装です。残念ながら動作しません。
class AudioProcessor {
let audioEngine = AVAudioEngine()
init(){
let inputNode = audioEngine.inputNode
let bus = 0
var error: NSError?
inputNode.installTapOnBus(bus, bufferSize: 2048, format:inputNode.inputFormatForBus(bus)) {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
println("sfdljk")
}
audioEngine.prepare()
audioEngine.startAndReturnError(nil)
println("started audio")
}
}
AVAudioEngineがスコープ外になり、ARCによってリリースされる場合があります(「気に入った場合は、保持する必要があります...」)。
次のコード(エンジンがivarに移動されたため、固執します)がタップを起動します。
class AppDelegate: NSObject, NSApplicationDelegate {
let audioEngine = AVAudioEngine()
func applicationDidFinishLaunching(aNotification: NSNotification) {
let inputNode = audioEngine.inputNode
let bus = 0
inputNode.installTapOnBus(bus, bufferSize: 2048, format: inputNode.inputFormatForBus(bus)) {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
println("sfdljk")
}
audioEngine.prepare()
audioEngine.startAndReturnError(nil)
}
}
(簡潔にするためにエラー処理を削除しました)
更新:マイク入力を録音し、実行時にいくつかのエフェクト(リバーブ、ディレイ、ディストーション)を適用し、これらすべてのエフェクトを出力ファイルに保存する完全な実例を実装しました。
var engine = AVAudioEngine()
var distortion = AVAudioUnitDistortion()
var reverb = AVAudioUnitReverb()
var audioBuffer = AVAudioPCMBuffer()
var outputFile = AVAudioFile()
var delay = AVAudioUnitDelay()
//オーディオエンジンを初期化します
func initializeAudioEngine() {
engine.stop()
engine.reset()
engine = AVAudioEngine()
isRealTime = true
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
let ioBufferDuration = 128.0 / 44100.0
try AVAudioSession.sharedInstance().setPreferredIOBufferDuration(ioBufferDuration)
} catch {
assertionFailure("AVAudioSession setup error: \(error)")
}
let fileUrl = URLFor("/NewRecording.caf")
print(fileUrl)
do {
try outputFile = AVAudioFile(forWriting: fileUrl!, settings: engine.mainMixerNode.outputFormatForBus(0).settings)
}
catch {
}
let input = engine.inputNode!
let format = input.inputFormatForBus(0)
//settings for reverb
reverb.loadFactoryPreset(.MediumChamber)
reverb.wetDryMix = 40 //0-100 range
engine.attachNode(reverb)
delay.delayTime = 0.2 // 0-2 range
engine.attachNode(delay)
//settings for distortion
distortion.loadFactoryPreset(.DrumsBitBrush)
distortion.wetDryMix = 20 //0-100 range
engine.attachNode(distortion)
engine.connect(input, to: reverb, format: format)
engine.connect(reverb, to: distortion, format: format)
engine.connect(distortion, to: delay, format: format)
engine.connect(delay, to: engine.mainMixerNode, format: format)
assert(engine.inputNode != nil)
isReverbOn = false
try! engine.start()
}
//これで録音機能:
func startRecording() {
let mixer = engine.mainMixerNode
let format = mixer.outputFormatForBus(0)
mixer.installTapOnBus(0, bufferSize: 1024, format: format, block:
{ (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
print(NSString(string: "writing"))
do{
try self.outputFile.writeFromBuffer(buffer)
}
catch {
print(NSString(string: "Write failed"));
}
})
}
func stopRecording() {
engine.mainMixerNode.removeTapOnBus(0)
engine.stop()
}
これがお役に立てば幸いです。ありがとう!
上記の答えは私にはうまくいきませんでしたが、次の答えはうまくいきました。ミキサーノードにタップを取り付けています。
mMixerNode?.installTapOnBus(0, bufferSize: 4096, format: mMixerNode?.outputFormatForBus(0),
{
(buffer: AVAudioPCMBuffer!, time:AVAudioTime!) -> Void in
NSLog("tapped")
}
)
いいトピック
こんにちはブロドニー
あなたのトピックで私は私の解決策を見つけます。ここに同様のトピックがあります AVAudioRecorderでAVAudioPCMBufferを生成します
講義を参照Wwdc2014 502-AVAudioEngine inPracticeキャプチャマイク=> 20分でタップコードを使用してバッファを作成=> 21.50で
ここにSwift 3コード
@IBAction func button01Pressed(_ sender: Any) {
let inputNode = audioEngine.inputNode
let bus = 0
inputNode?.installTap(onBus: bus, bufferSize: 2048, format: inputNode?.inputFormat(forBus: bus)) {
(buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in
var theLength = Int(buffer.frameLength)
print("theLength = \(theLength)")
var samplesAsDoubles:[Double] = []
for i in 0 ..< Int(buffer.frameLength)
{
var theSample = Double((buffer.floatChannelData?.pointee[i])!)
samplesAsDoubles.append( theSample )
}
print("samplesAsDoubles.count = \(samplesAsDoubles.count)")
}
audioEngine.prepare()
try! audioEngine.start()
}
オーディオを停止するには
func stopAudio()
{
let inputNode = audioEngine.inputNode
let bus = 0
inputNode?.removeTap(onBus: bus)
self.audioEngine.stop()
}