AVAudioPlayerNode を使用して短いバッファをスケジュールし、タッチ イベント ("Touch Up Inside") ですぐに再生する場合、テスト中に再生時に聞こえるグリッチ/アーティファクトに気付きました。iOS シミュレーターではオーディオにまったく問題はありませんが、実際の iOS デバイスでアプリを実行すると、再生時に歪みが聞こえます。可聴歪みはランダムに発生します (トリガーされたサウンドは、素晴らしいサウンドになることもあれば、歪んだサウンドになることもあります)。
さまざまなオーディオ ファイル、ファイル形式を使用して、prepareWithFrameCount メソッドを使用して再生用のバッファーを準備しようとしましたが、残念ながら結果は常に同じで、何が問題なのか疑問に思っています..
わかりやすくシンプルにするために、コードをグローバルに落としました。どんな助けや洞察も大歓迎です。これは、iOS アプリを開発する最初の試みであり、スタック オーバーフローに投稿された最初の質問です。
let filePath = NSBundle.mainBundle().pathForResource("BD_withSilence", ofType: "caf")!
let fileURL: NSURL = NSURL(fileURLWithPath: filePath)!
var error: NSError?
let file = AVAudioFile(forReading: fileURL, error: &error)
let fileFormat = file.processingFormat
let frameCount = UInt32(file.length)
let buffer = AVAudioPCMBuffer(PCMFormat: fileFormat, frameCapacity: frameCount)
let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
func startEngine() {
var error: NSError?
file.readIntoBuffer(buffer, error: &error)
audioEngine.attachNode(playerNode)
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: buffer.format)
audioEngine.prepare()
func start() {
var error: NSError?
audioEngine.startAndReturnError(&error)
}
start()
}
startEngine()
let frameCapacity = AVAudioFramePosition(buffer.frameCapacity)
let frameLength = buffer.frameLength
let sampleRate: Double = 44100.0
func play() {
func scheduleBuffer() {
playerNode.scheduleBuffer(buffer, atTime: nil, options: AVAudioPlayerNodeBufferOptions.Interrupts, completionHandler: nil)
playerNode.prepareWithFrameCount(frameLength)
}
if playerNode.playing == false {
scheduleBuffer()
let time = AVAudioTime(sampleTime: frameCapacity, atRate: sampleRate)
playerNode.playAtTime(time)
}
else {
scheduleBuffer()
}
}
// triggered by a "Touch Up Inside" event on a UIButton in my ViewController
@IBAction func triggerPlay(sender: AnyObject) {
play()
}
アップデート:
歪みの原因を特定できたと思います。出力時のノードのボリュームが大きすぎて、クリッピングが発生しています。私の startEngine 関数に次の 2 行を追加することで、歪みは発生しなくなりました。
playerNode.volume = 0.8
audioEngine.mainMixerNode.volume = 0.8
ただし、出力を下げる必要がある理由はまだわかりません。オーディオ ファイル自体はクリップしません。AVAudioPlayerNodeBufferOptions.Interrupts が実装されている方法の結果である可能性があると推測しています。バッファが別のバッファを中断すると、中断の結果として出力ボリュームが増加し、出力クリッピングが発生する可能性がありますか? なぜこれが発生するのかについて、私はまだしっかりとした理解を求めています..誰かがこれについて明確にする意思がある/できるなら、それは素晴らしいことです!