1

So I have been struggling to get AVAudioEngine to repeat a sound for me. I need it to play a track (about 26 seconds) over and over again. It needs to be using AVAudioEngine, not AVAudioPlayer, because I need to be able to change it's tone. I've found examples of changing tone, and forcing the sound to repeat, but only for sine waves, links below.

My old code (before trying to implement the problem) is below. It will play the sound through once when the button is pushed, but doesn't do it again.

import UIKit
import AVFoundation
class aboutViewController: UIViewController {

    var audioUrl = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("chimes", ofType: "wav")!)
    var audioEngine = AVAudioEngine()
    var myPlayer = AVAudioPlayerNode()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        audioEngine.attachNode(myPlayer)
        var audioFile = AVAudioFile(forReading: audioUrl, error: nil)
        var audioError: NSError?
        audioEngine.connect(myPlayer, to: audioEngine.mainMixerNode, format: audioFile.processingFormat)
        myPlayer.scheduleFile(audioFile, atTime: nil, completionHandler: nil)
        audioEngine.startAndReturnError(&audioError)


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func toggleSideMenu(sender: AnyObject) {
    toggleSideMenuView()
    }

    @IBAction func testSound(sender: AnyObject) {
    myPlayer.play()
    }
}

My code attempt to implement the repeating is below, and this doesn't do anything (doesn't crash).

import UIKit
import AVFoundation
class aboutViewController: UIViewController {

    var audioUrl = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("chimes", ofType: "wav")!)
    var audioEngine = AVAudioEngine()
    var myPlayer = AVAudioPlayerNode()
    var audioError: NSError?

    override func viewDidLoad() {
        super.viewDidLoad()

    // Do any additional setup after loading the view.

        audioEngine.attachNode(myPlayer)

        var buffer = AVAudioPCMBuffer(PCMFormat: myPlayer.outputFormatForBus(0),frameCapacity:100)
        buffer.frameLength = 100
        var mixer = audioEngine.mainMixerNode
        var audioFile = AVAudioFile(forReading: audioUrl, error: nil)

        audioEngine.connect(myPlayer, to: audioEngine.mainMixerNode, format: audioFile.processingFormat)

        audioEngine.startAndReturnError(&audioError)
        myPlayer.play()
        myPlayer.scheduleBuffer(buffer, atTime: nil, options:.Loops , completionHandler: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }


    @IBAction func testSound(sender: AnyObject) {

    }

}

So what I am asking is this: Can you put together an example that plays an audio file over and over, and have a variable at the top (ex: let tone:Int = 100), that sets the tone that the audio file will be repetitively played at.

Thanks for your help!

Links:

Example of a repeating sine wave: http://www.tmroyal.com/playing-sounds-in-swift-audioengine.html

Example of change in tone: Using sound effects with AudioEngine

Community
  • 1
  • 1
CarveDrone
  • 915
  • 1
  • 9
  • 23
  • Does your audio already repeat? What happens when you try to attach a `AVAudioUnitTimePitch` to your `audioEngine`? – Ian MacDonald Nov 10 '14 at 19:23
  • No, at the moment nothing happens, it doesn't repeat. I think I understand how to do the pitch changing, it's the repeating thats giving me trouble. @IanMacDonald – CarveDrone Nov 10 '14 at 19:24
  • It looks like you never load your `audioFile` into your `buffer`. Try using `audioFile.readIntoBuffer(..)`. – Ian MacDonald Nov 10 '14 at 19:29
  • Aright, with the line `audioFile.readIntoBuffer(buffer, error: audioError)` I get the error: `Missing argument for parameter 'frameCount' in call` @IanMacDonald – CarveDrone Nov 10 '14 at 19:33
  • What happens if you add `frameCount:100` (the capacity that you created your buffer with) to your call? Actually, it looks like you might just be missing an `&` before `audioError`. – Ian MacDonald Nov 10 '14 at 19:39
  • Alright, this did something. Now when I open the view, it plays a pitch! So how can I make it play my audioURL? Oh, and I updated the question, adding old code. Thanks for your help so far! @IanMacDonald – CarveDrone Nov 10 '14 at 19:44
  • If you would like an example project I can put one together @IanMacDonald – CarveDrone Nov 10 '14 at 19:54

0 Answers0