7

iOS 8 で新しい AVAudioEngine を使用しようとしています。

サウンド ファイルの再生が完了する前に、 player.scheduleFile() の completionHandler が呼び出されているようです。

私は 5 秒の長さのサウンド ファイルを使用しています --println()メッセージは、サウンドが終了する約 1 秒前に表示されます。

私は何か間違ったことをしていますか、それともcompletionHandlerの考え方を誤解していますか?

ありがとう!


ここにいくつかのコードがあります:

class SoundHandler {
    let engine:AVAudioEngine
    let player:AVAudioPlayerNode
    let mainMixer:AVAudioMixerNode

    init() {
        engine = AVAudioEngine()
        player = AVAudioPlayerNode()
        engine.attachNode(player)
        mainMixer = engine.mainMixerNode

        var error:NSError?
        if !engine.startAndReturnError(&error) {
            if let e = error {
                println("error \(e.localizedDescription)")
            }
        }

        engine.connect(player, to: mainMixer, format: mainMixer.outputFormatForBus(0))
    }

    func playSound() {
        var soundUrl = NSBundle.mainBundle().URLForResource("Test", withExtension: "m4a")
        var soundFile = AVAudioFile(forReading: soundUrl, error: nil)

        player.scheduleFile(soundFile, atTime: nil, completionHandler: { println("Finished!") })

        player.play()
    }
}
4

7 に答える 7

6

iOS 8 の頃の AVAudioEngine ドキュメントは間違っていたに違いありません。当面の間、回避策として、代わりscheduleBuffer:atTime:options:completionHandler:にコールバックを使用すると、(再生が終了した後に) 期待どおりに起動されることに気付きました。

コード例:

AVAudioFile *file = [[AVAudioFile alloc] initForReading:_fileURL commonFormat:AVAudioPCMFormatFloat32 interleaved:NO error:nil];
AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:file.processingFormat frameCapacity:(AVAudioFrameCount)file.length];
[file readIntoBuffer:buffer error:&error];

[_player scheduleBuffer:buffer atTime:nil options:AVAudioPlayerNodeBufferInterrupts completionHandler:^{
    // reminder: we're not on the main thread in here
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"done playing, as expected!");
    });
}];
于 2015-04-14T14:32:54.880 に答える