0

I am looking for a way to simply play audio files one after another. AVAudioPlayer using an array seems to be the best solution. In fact, I was able to play the first element of the array using Sneak's recommendations found on this page : Here.

But I don't understand where and how to write the second call to AVAudioPlayer in order to play the second file?

The "audioPlayerDidFinishPlaying" function is not reacting. Why?

Thanks for watching.

import Cocoa
import AVFoundation

var action = AVAudioPlayer()
let path = Bundle.main.path(forResource: "test.aif", ofType:nil)!
let url = URL(fileURLWithPath: path)
let path2 = Bundle.main.path(forResource: "test2.aif", ofType:nil)!
let url2 = URL(fileURLWithPath: path2)
let array1 = NSMutableArray(array: [url, url2])

class ViewController: NSViewController
{
    @IBOutlet weak var LanceStop: NSButton!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        do
        {
            action = try AVAudioPlayer(contentsOf: array1[0] as! URL)
            action.numberOfLoops = 0
            action.prepareToPlay()
            action.volume = 1
        }catch{print("error")}
    }
...
@IBAction func Lancer(_ sender: NSButton)
    {
        if action.isPlaying == true
        {
            action.stop()
            action.currentTime = 0.0
            LanceStop.title = "Lancer"
        }
        else
        {
            action.play()
            LanceStop.title = "Stopper"
        }
    }

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
    {
        if flag == true
        {
            LanceStop.title = "Lancer"
        }
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Fredo
  • 153
  • 2
  • 13

2 Answers2

1

But I don't understand where and how to write the second call to
AVAudioPlayer in order to play the second file?

So in order to play the second file, you need to write one method where you will need to initialize the audioplayer and invoke the same method inside audioplayer delegate method audioPlayerDidFinishPlaying like this:-

func playAudioFile(_ index: Int) {
  do
{
  action = try AVAudioPlayer(contentsOf: array1[index] as! URL)
  action.numberOfLoops = 0
  action.prepareToPlay()
  action.volume = 1
 } catch{print("error")
}

 func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
     //This delegate method will called once it finished playing audio file.
    //Here you can invoke your second file. You can declare counter variable 
   //and increment it based on your file and stop playing your file acordingly.
  counter = counter + 1
  playAudioFile(counter)
}

Note:- Set Audioplayer delegate to your ViewController in order to get invoke audioPlayerDidFinishPlaying method like this.

action.delegate = self
Hussain Shabbir
  • 14,801
  • 5
  • 40
  • 56
  • I was able to change my code using your exemple except for the delegate. It gives an "Expected declaration" error. Also I don't know how to make sure the index (Int) variable starts at "0". Should I not declare it? – Fredo Jul 24 '17 at 21:03
  • Have added "AVAudioPlayerDelegate" after "NSViewController,". But still, I don't know where to insert the "action.delegate = self" code, it crashes the app. – Fredo Jul 24 '17 at 21:28
  • I 've found my way out of this puzzle. I 'll have to find another answer because there is an audio gap between each url played. Thanks for letting me understand a little bit better how delegates works. Cheers. – Fredo Jul 24 '17 at 23:13
0

Changed Code...

class ViewController: NSViewController, AVAudioPlayerDelegate
{

    @IBOutlet weak var LanceStop: NSButton!

    override func viewDidLoad()
    {
        super.viewDidLoad()
    }
    override var representedObject: Any?
    {
        didSet
        {
        // Update the view, if already loaded.
        }
    }

    func playAudioFile(_ index: Int)
    {
        do
        {
            action = try AVAudioPlayer(contentsOf: array1[index] as! URL)
            action.delegate = self
            action.numberOfLoops = 0
            action.prepareToPlay()
            action.volume = 1
            action.play()
        }
        catch{print("error")}
    }

    @IBAction func Lancer(_ sender: NSButton)
    {
      playAudioFile(0)
    }


    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
    {
        if flag == true
        {
            playAudioFile(1)
        }
    }

}
Fredo
  • 153
  • 2
  • 13