2

我必须一次播放三种类型的 wav 文件。当我单击 Enter 区域中的 Play 按钮时,它会播放一个名为“EnterRegion.wav”的声音,然后单击 Exit Region 播放按钮会播放“ExitRegion.wav”音频文件。

但是对于立即的播放按钮,它会重复播放声音,直到我按下停止按钮。

第一个和第二个播放按钮对我来说都很完美,但是当我点击立即播放按钮时,它会第一次播放声音,但是当我点击其他播放按钮并再次返回立即播放按钮时,应用程序会抛出异常。当我按下停止按钮并返回立即部分的播放按钮时,也会发生这种情况。我在 Swift 4 中的示例应用程序屏幕截图和代码示例如下。

在此处输入图像描述

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var engine: AVAudioEngine!

    var enterWavFile: AVAudioFile!

    var audioPlayerNode : AVAudioPlayerNode!
    var immediaAudioPlayerNode: AVAudioPlayerNode!


    var exitWavFile: AVAudioFile!

    var flatlineWavFile:AVAudioFile!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        engine = AVAudioEngine()

        enterWavFile = try? AVAudioFile(forReading: NSURL.fileURL(withPath:
            Bundle.main.path(forResource: "EnterRegion", ofType: "wav")!))
        exitWavFile = try? AVAudioFile(forReading: NSURL.fileURL(withPath:
            Bundle.main.path(forResource: "ExitRegion", ofType: "wav")!))

        flatlineWavFile = try? AVAudioFile(forReading: NSURL.fileURL(withPath:
            Bundle.main.path(forResource: "Immediate", ofType: "wav")!))

    }

    @IBAction func playEnterRegionSound(_ sender: UIButton) {
       playSound(audioFile: enterWavFile)
    }

    @IBAction func playExitRegion(_ sender: UIButton) {
       playSound(audioFile: exitWavFile)
    }

    func playSound(audioFile: AVAudioFile)  {
        audioPlayerNode = AVAudioPlayerNode()
        if(audioPlayerNode.isPlaying){
            audioPlayerNode.stop()
        }

        if(engine.isRunning){
            engine.stop()
            engine.reset()
        }

        engine.attach(audioPlayerNode)

    engine.connect(audioPlayerNode, to: engine.mainMixerNode, format: audioFile.processingFormat)
    audioPlayerNode.scheduleFile(audioFile, at: nil, completionHandler: nil)

    // Start the audio engine
    engine.prepare()
    try! engine.start()

    audioPlayerNode.play()
}


@IBAction func playImmediateFlatline(_ sender: UIButton) {
    immediaAudioPlayerNode = AVAudioPlayerNode()
    if(immediaAudioPlayerNode.isPlaying){
        print("immediateAudioPlayerNode Playing")
        immediaAudioPlayerNode.stop()
    }


    if(engine.isRunning){
        print("engine Running")
        engine.stop()
        engine.reset()
    }

    let audioFileBuffer = AVAudioPCMBuffer(pcmFormat: flatlineWavFile.processingFormat, frameCapacity: AVAudioFrameCount( flatlineWavFile.length))!

    try? flatlineWavFile.read(into: audioFileBuffer)

    engine.attach(immediaAudioPlayerNode)

    engine.connect(immediaAudioPlayerNode, to: engine.mainMixerNode, format: flatlineWavFile.processingFormat)
    immediaAudioPlayerNode.scheduleBuffer(audioFileBuffer, at: nil, options: AVAudioPlayerNodeBufferOptions.loops, completionHandler: nil)

    // Start the audio engine
    engine.prepare()
    try! engine.start()

    immediaAudioPlayerNode.play()
}


@IBAction func stopImmediateFlatline(_ sender: UIButton) {
    if (immediaAudioPlayerNode.isPlaying){
        print("immediateAudioPlayerNode playing")
        immediaAudioPlayerNode.pause()
    }

    if(engine.isRunning){
        print("engine Running")
        engine.stop()
        engine.reset()
    }
}    

}

我无法找到发生这种情况的原因,请您帮我解决问题或提供任何建议。

4

1 回答 1

1

播放声音的代码

var player1: AVAudioPlayer?
var player2: AVAudioPlayer?
var player3: AVAudioPlayer?

     func playSound() {
        guard let url = Bundle.main.url(forResource: "Music", withExtension: "wav") else { return }

        do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        /* The following line is required for the player to work on iOS 11. Change the file type accordingly*/
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)

        /* iOS 10 and earlier require the following line:
         player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) */

        guard let player = player else { return }
        // read this line of code for you to play the wav file you wanted to play ang then trigger it using a button.
        player.play()

        } catch let error {
        print(error.localizedDescription)
        }
        }
于 2018-04-19T09:17:29.853 回答