AVFoundation bugs, No sound when I run audioPlayer.play() - swift

I have a little problem with AVFoundation, when I launch a sound there is nothing that comes out. On the other hand it is enough to add a timer that displays the currentTime of the sound in question and everything works correctly. could you help me? Thanks.
code that does not work:
do {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = URL(fileURLWithPath: path)
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.volume = 1.0
audioPlayer.play()
} catch {
assertionFailure("Failed crating audio player: \(error).")
return
}
just add the timer and everything will work:
do {
let path = Bundle.main.path(forResource: "sound1", ofType: "mp3")!
let url = URL(fileURLWithPath: path)
let audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer.volume = 1.0
audioPlayer.play()
print("le son est en cours de lecture !")
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
print(audioPlayer.currentTime)
}
} catch {
assertionFailure("Failed crating audio player: \(error).")
return
}

This worked for me
instead of
let audioPlayer = try AVAudioPlayer(contentsOf: url)
change to
audioPlayer = try AVAudioPlayer(contentsOf: url)

Related

Swift5 Play aac file AvAudioPlayer

I currently play a wav file with the code below. But now i have compressed the files to aac-files and i can't figure out how to play them? I tried to change the withExtension to "aac" instead but no sound. Any ideas?
guard let url = Bundle.main.url(forResource: fileName, withExtension: "aac") else { return }
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
try AVAudioSession.sharedInstance().setActive(true)
let audioPlayer = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.ac3.rawValue)
audioPlayer.volume = currentVolume
newAudioPlayer.audioPlayer.play()
} catch let error {
print(error.localizedDescription)
}
If you need to play AAC files you can use AVAudioEngine audio player node:
import UIKit
import AVFoundation
class ViewController: UIViewController {
let audioEngine = AVAudioEngine()
let player = AVAudioPlayerNode()
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "audio_name", withExtension: "aac")!
do {
let audioFile = try AVAudioFile(forReading: url)
guard let buffer = AVAudioPCMBuffer(pcmFormat: audioFile.processingFormat, frameCapacity: .init(audioFile.length)) else { return }
try audioFile.read(into: buffer)
audioEngine.attach(player)
audioEngine.connect(player, to: audioEngine.mainMixerNode, format: buffer.format)
try audioEngine.start()
player.play()
player.scheduleBuffer(buffer, at: nil, options: .loops)
} catch {
print(error)
}
}
}

play multiple AVAudioPlayer at the same time asynchronously?

I have a background AVAudioPlayer who normally works just fine. Now I have some event that triggers an asynchron action with a delay, here I want to play another sound while the other should keep playing. So I make a new one:
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
guard let urlStr = Bundle.main.path(forResource: "File1", ofType: ".mp3") else { fatalError() }
self.player = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: urlStr), fileTypeHint: "mp3")
self.player?.play()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
guard let urlStr = Bundle.main.path(forResource: "File2", ofType: ".mp3") else { fatalError() }
let p = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: urlStr), fileTypeHint: "mp3")
p?.play()
}
So the first one runs normally (Dispatch only to show that it's working also async). The second one runs as well, meaning no error. However, I only hear the first one...
Why do you create a new player inside you async call? I had similar problems and it should work if you declare a new var outside your immediate async-scope.

Can not play sound file Swift4

I'm trying play simple .wav file in my application.
Here is the code:
func alarmSound() {
var player: AVAudioPlayer?
guard let path = Bundle.main.path(forResource: "emergency021", ofType: "wav") else {
print("Can't find audio file")
return
}
let url = URL(fileURLWithPath: path)
do {
player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.wav.rawValue)
if let prepare = player?.prepareToPlay() {
print("Player prepared: \(prepare)")
}
player?.volume = 1.0
player?.play()
} catch {
print("Playing sound error: \(error)")
}
}
Everything ok, file in the bundle, url is ok, player prepared, but.. there is no any sound. I have tried .mp3 file - same result.
Any ideas, why?
Issue was declaring player: AVAudioPlayer locally in function body, when I moved it up to ViewController all works.

Swift 3: AVAudioPlayer not playing sound

I have a struct with my audio player in it:
struct MT_Audio {
func playAudio(_ fileName:String, _ fileExtension:String, _ atVolume:Float) {
var audioPlayer = AVAudioPlayer()
if let audioPath = Bundle.main.path(forResource: fileName, ofType: fileExtension) {
let audioURL = URL(string:audioPath)
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioURL!)
audioPlayer.volume = atVolume
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print(error)
}
}
}
}
//I'm calling it in viewDidLoad like this:
guard let fileURL = Bundle.main.url(forResource:"heartbeat-01a", withExtension: "mp3")
else {
print("can't find file")
return
}
let myAudioPlayer = MT_Audio() //<--RESOLVED THE ISSUE BY MAKING THIS A PROPERTY OF THE VIEWCONTROLLER
myAudioPlayer.playAudio("heartbeat-01a", "mp3", 1.0)
Since it doesn't crash and burn on the guard I know the file is there. I've also put a break point in after the try and I am getting to the audio player. When I go to the actual file and click on it in Xcode it plays. This fails on both the sim and device. Any help would be appreciated.
Looks like your audioPlayer is only stored within your playAudio function.
Try to keep the audioPlayer as an variable inside your class like this:
struct MT_Audio {
var audioPlayer: AVAudioPlayer?
mutating func playAudio(_ fileName:String, _ fileExtension:String, _ atVolume:Float) {
// is now member of your struct -> var audioPlayer = AVAudioPlayer()
if let audioPath = Bundle.main.path(forResource: fileName, ofType: fileExtension) {
let audioURL = URL(string:audioPath)
do {
let audioPlayer = try AVAudioPlayer(contentsOf: audioURL!)
audioPlayer.volume = atVolume
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print(error)
}
}
}
}

Create a function from code

How do I create a function from this code in swift3?
I have a button which is pressed then plays this sound "push"
How can it be simplified when there are lots of buttons? I don't want to add all codes to every button.
var myAudio = AVAudioPlayer()
// Add sound
do {
try myAudio = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath:
Bundle.main.path(forResource: "push", ofType: "mp3")!) as URL)
} catch {
NSLog("No file!")
}
//call the sound
myAudio.play()
I made this change
func play(name : String){
do {
try myAudio = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath:
Bundle.main.path(forResource: name, ofType: "mp3")!) as URL)
} catch {
NSLog("No file!")
}
}
#IBAction func buttonFirst(_ sender: UIButton) {
play(name: "push")
myAudio.play()
}
#IBAction func buttonSecond(_ sender: UIButton) {
play(name: "second")
myAudio.play()
}
I got this output:
2017-07-25 16:13:23.270349+0100 sound[1728:933024] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
Is that a problem?
I think you forgot the prepare
var audioPlayer = AVAudioPlayer()
let sound = URL(fileURLWithPath: Bundle.main.path(forResource: "sound", ofType: "mp3")!)
try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try! AVAudioSession.sharedInstance().setActive(true)
try! audioPlayer = AVAudioPlayer(contentsOf: sound)
audioPlayer.prepareToPlay()
audioPlayer.play()
You can use it in the following way
var myAudio : AVAudioPlayer?
func playSound(){
let path = Bundle.main.path(forResource: "push", ofType:"mp3")!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
self.myAudio = sound
sound.numberOfLoops = 1
sound.prepareToPlay()
sound.play()
} catch {
print("error loading file")
// couldn't load file :(
}
}
Furthermore you can use SwiftySound that lets you play sounds easily in Swift 3.
for example
Sound.play(file: "push.mp3")