Can't stop AVFoundation song - ios

I'm making a game with level selection in Swift 3.0, and I'm using AVFoundation to play background music. I'd like to play a different song for every level, however when I try to stop the song and play a new one after I've beaten the level, instead of stopping it it just replays it. Here's my code, seriously been working on this for hours and gotten no where.
import UIKit
import AVFoundation
class LevelSelect: UIViewController {
var AudioPlayer0 = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let AssortedMusics0 = NSURL(fileURLWithPath: Bundle.main.path(forResource: "Background", ofType: "mp3")!)
AudioPlayer0 = try! AVAudioPlayer(contentsOf: AssortedMusics0 as URL)
AudioPlayer0.prepareToPlay()
AudioPlayer0.numberOfLoops = -1
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func Level0Button(_ sender: Any) {
AudioPlayer0.stop()
AudioPlayer0.play()
}
}
Thanks for the help!

Related

Playing sound effect in Xcode

I have created a button in Xcode that plays a short sound effect. I am not able to retrigger the button/sound, while it's playing. Therefore I have to wait until the sound has faded to repeat the effect. My intention is that every time I press the button, the sound effect starts to play, even if it is still fading out. Does anybody know how to achieve this? I am using XCode 11.6. My code is below. Many thanks in advance.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "1", ofType: "mp3")!))
audioPlayer.prepareToPlay()
} catch {
print(error)
}
}
#IBAction func Play(_ sender: Any) {
audioPlayer.play()
}
}
You could just initialize the audioPlayer in Play method instead of viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func Play(_ sender: Any) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "1", ofType: "mp3")!))
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print(error)
}
}
if I understand correctly you want to prevent play again when sound is playing and just play sound when it finished already so
you can make condition according sound is playing or not
(try it in your button action):
if audioPlayer.isPlaying(){
// your statement when sound is playing in other word nothing to do
}else{
// your statement when sound is not playing and you want to start play
audioPlayer.play()
}
https://developer.apple.com/documentation/avfoundation/avaudioplayer/1390139-isplaying

Play multiple songs in iOS

I wrote this code for iOS to play a song, however I'm not sure how to write the code to play multiple songs.
This is the line of code for a song:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player:AVAudioPlayer = AVAudioPlayer()
#IBAction func play(_ sender: AnyObject)
{
player.play()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
do
{
let audioPath = Bundle.main.path(forResource: "Ken", ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//ERROR
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You actually can play it with just two instances of the AVAudioPlayer resp. every sound file needs it's own AVAudioPlayer if you want to play them simultaneously.
I already wrote an answer, so I will post even there is already a correct answer. What palme said is correct. You could use multiple AVAudioPlayer instances to play multiple sounds simultaneously:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let paths = ["a","b"]
var sounds = [AVAudioPlayer]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for path in paths {
do
{
let audioPath = Bundle.main.path(forResource: path, ofType: "mp3")
let player = try AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
sounds.append(player)
}
catch
{
//ERROR
}
}
for sound in sounds {
sound.play()
}
}
}

Swift 3 - AVAudioPlayer is not playing sound

I have a simple program which has one button and its only function is to trigger an sound output.
The app works perfectly when tested on an iOS simulator, but when I test it on an iPhone, the app is not playing any sound. I have tested this on two iPhones.
This was working once upon a time. I don't know if updating to iOS 10 has caused the issue.
Here is my code:
//Code
import UIKit
import AVFoundation
var audioPlayer = AVAudioPlayer()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
}
catch{
print(error)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playSound(_ sender: UIButton) {
audioPlayer.play()
}
}
Would be grateful for any answers.
Thanks.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let music = Bundle.main.path(forResource: "sound", ofType: "wav")
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: music! ))
audioPlayer.delegate = self
audioPlayer.preparedToPlay()
}
catch{
print(error)
}
}
import UIKit
import AVFoundation
class ViewController: UIViewController {
var btnSound: AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
//locate resource
let path = Bundle.main.path(forResource: "sound", ofType: "wav")
let music = URL(fileURLWithPath: path!)
do{
try btnSound = AVAudioPlayer(contentsOf: music)
btnSound.prepareToPlay()
} catch let err as NSError{
print(err.debugDescription)
}
}
}
func playSound(){
if btnSound.isPlaying{
//stop playing sound file if already playing
btnSound.stop()
}
//play sound
btnSound.play()
}
#IBAction func playSound(sender: UIButton){
//call playSound function on pressing the button you attach this function to
playSound()
}

Create a random audio sound generator

Thanks for replying.
I am trying to make a program when I press a button once, two random sounds will play. I can get the random sounds to play if I press the button, but I am looking that if I press the button, the random sound will play differently each time.
I can paste the sounds together to hear them in the sequence I want them, but I would like swift to generate the sounds.
I thought of the AVqueplayer to make it as a playlist. I was thinking this can be like a pair of dice in an analogy. For example, if I were to throw the dice down, the random sounds will occur.
I am still a newbie, and tried to figure this out on my own, because it seemed so simple, but I am out of options now.
Here is what I got so far. This will play a random sound when I press the button each time.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
var sounds = ["sound1", "sound2", "sound3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if event!.subtype == UIEventSubtype.motionShake {
let randomNumber = Int(arc4random_uniform(UInt32(sounds.count)))
let fileLocation = Bundle.main.path(forResource: sounds[randomNumber], ofType: "mp3")
var error: NSError? = nil
do { try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation!))
player.play()
} catch {}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Using the same code, and adding a second random number with matching file location will allow the sounds to play back to back, both being random:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer = AVAudioPlayer()
var sounds = ["sound1", "sound2", "sound3"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if event!.subtype == UIEventSubtype.motionShake {
let randomNumber1 = Int(arc4random_uniform(UInt32(sounds.count)))
let randomNumber2 = Int(arc4random_uniform(UInt32(sounds.count)))
let fileLocation1 = Bundle.main.path(forResource: sounds[randomNumber1], ofType: "mp3")
let fileLocation2 = Bundle.main.path(forResource: sounds[randomNumber2], ofType: "mp3")
//var error: NSError? = nil
do {
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation1!))
player.play()
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileLocation2!))
player.play()
} catch {}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Changing the tone of a repetitive sound using AVAudioEngine

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

Resources