2

I have to play three types of wav file one at a time. When I click on the Play button in Enter region it plays a sound named "EnterRegion.wav" and clicking on Exit Region play button plays "ExitRegion.wav" audio file.

But for the play button of the Immediate, it plays a sound repeatedly until I press the Stop button.

Both first and second Play buttons are working perfectly for me but when I click on play button in Immediate, it plays sound for the first time but when I click on other play buttons and come back to Immediate play button again, the application throws exceptions. This happens the same when I press stop button and come back to the play button of immediate section. My sample app screenshot and code sample which is in Swift 4 is as below.

enter image description here

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()
    }
}    

}

I am unable to locate why this is happening and could you please help me to fix the issue or any suggestions.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Simant
  • 3,142
  • 4
  • 32
  • 61
  • 1
    What is the exception and where is it thrown? – Gary Makin Apr 19 '18 at 08:36
  • @GaryMakin When I click on Play button of Immediate it work perfectly for the first time but when I hit the Play button second time it throws exception. The exception is "AURemoteIO::IOThread (19): EXC_ARITHMETIC (code=EXC_I386_DIV, s" which is coming from library. I am unable to find out why I am getting this error. – Simant Apr 19 '18 at 10:34

1 Answers1

1

code for playing the sound

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)
        }
        }
  • In my case I have to play different audio for differently like play one time, play repeatedly and play an audio with pitch shifting and for that I should go for AVAudioEngine and AVAudioPlayerNode. I don't have problem playing normal audio file but the problem is to repeatedly playing the file. Could you please look into my implementation? Thanks. – Simant Apr 19 '18 at 09:33
  • I will sir , wait –  Apr 19 '18 at 09:40