Swift - AVAudioPlayer, sound doesn't play correctly
You already provided the correct solution to your problem and that would be #2; to have a class-level audioPlayer
property. Why is this so?
Well, that's because in the code you setup the player, start the playback, show the pop-up and after everything is done, the method exits its scope. The automated memory management (ARC) works so that any local variables get released when you exit the scope of that variable. If you consider that sound playback is asynchronous (eg. it will play without blocking the main thread), you exit the scope before the audio player is finished playing the sound. ARC notices that audioPlayer
is a local variable and releases it at that point, but the sound is not done playing yet.
I hope I was clear enough, if not feel free to ask more!
AVAudioPlayer doesn't play sound when MPMusicPlayerController is playing on iOS
Feeling stupid. The phones were set to silent mode. For some reason, it can play the sounds or the music on silent, but it can't play them both together.
Swift 2 - AVAudioPlayer not playing audio
Here is an example that will work. I am not sure where, in relation to the rest of your code, you have the code that you've shown above. Make sure your device volume is not on silent and is turned up...
//declare these as instance variables
var AudioURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("FileName", ofType: "mp3")!)
var AudioPlayer = AVAudioPlayer()
//inside viewDidLoad establish your AVAudioSession and configure the AudioPlayer with the contents of URL
override func viewDidLoad() {
super.viewDidLoad()
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
//print("AVAudioSession Category Playback OK")
do {
try AVAudioSession.sharedInstance().setActive(true)
//print("AVAudioSession is Active")
} catch let error as NSError {
print(error.localizedDescription)
}
} catch let error as NSError {
print(error.localizedDescription)
}
do {
try AudioPlayer = AVAudioPlayer(contentsOfURL: AudioURL, fileTypeHint: nil)
} catch {
print("errorin do-try-catch")
}
}
//play audio
@IBAction func playAudio(sender: AnyObject){
AudioPlayer.play()
}
AVAudioPlayer doesn't play the first time
Just so this is closed up and anyone who has the same problem knows this was solved. Like Markov said it was fixed by adding this line of code
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers)
The total looks like this
piece of code that loads the sounds
func loadSounds(){
do{
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: AVAudioSessionCategoryOptions.MixWithOthers)
try audioPlayerL = AVAudioPlayer(contentsOfURL: startListening!)
try audioPlayerE = AVAudioPlayer(contentsOfURL: doneListening!)
}
catch{
print("error")
}
audioPlayerL.delegate = self
audioPlayerL.prepareToPlay()
audioPlayerE.delegate = self
audioPlayerE.prepareToPlay()
}
method that is being called to play the sounds
func playSound(){
if(startedListening == true){
audioPlayerL.play()
}
else{
audioPlayerE.play()
}
}
AVAudioPlayer not playing any sound
I found the solution and it's related to something I didn't mention and didn't think about: I'm compiling with Automatic Reference Counting (ARC).
ARC inserts a release call to the audio player, so it's deallocated right after leaving the method where it is created. It has nothing to do with AVAudioPlayer
but with ARC.
In order to solve this issue, I just created an AVAudioPlayer
attribute to the class that deals with sounds so that it is not released anymore by ARC. Well, at least, it's not released until the instance of this class is released.
For more information about ARC, refer to Automatic Reference Counting: Zeroing Weak References with details on why I had this issue.
Why AVAudioPlayer has no sound?
SwiftUI is picky about what you can do in an initializer for a View struct like this. A more reliable option is to move the loading into an ObservableObject:
class AudioManager : ObservableObject {
var audioPlayer : AVAudioPlayer?
func loadAudio(filename: String) {
guard let path = Bundle.main.path(forResource: filename, ofType: "mp3") else {
print("[shark]", filename + "is not found")
return
}
do {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
} catch {
print("[shark], audioPlayer cannot load", path, error)
}
}
func playAudio() {
audioPlayer?.play()
}
}
struct ContentView: View {
var shortname: String = ""
var id: Int = 0
@ObservedObject var audioManager = AudioManager()
var body: some View {
Text("good")
.onAppear {
let fileName = self.shortname.lowercased() + "-" + String(id)
audioManager.loadAudio(filename: fileName)
audioManager.playAudio()
}
}
}
This plays for me on Xcode 12.3 and iOS 14
Related Topics
iOS Charts 3.0 - Align X Labels (Dates) with Plots
Swift: Corelocation Handling Nserror in Didfailwitherror
Simultaneous Gesture Recognition for Specific Gestures
iOS 8 Beta Today Extension Widget Not Showing in a Swift App
How to Limit the Movement of Two Anchored Lines So They Swing Continually Like a Pendulum
Converting Swift Array to Cfarray in Xcode 8 (Swift 3)
Get Build Date and Time in Swift
What Do "_" and "In" Mean in Swift Programming Language
Unsaferawpointer Assumingmemorybound VS. Bindmemory
Does Swift Guarantee the Storage Order of Fields in Classes and Structs
How Do People Deal with Iterating a Swift Struct Value-Type Property
Two Tables on One View in Swift
Does Swift Have a Null Coalescing Operator and If Not, What Is an Example of a Custom Operator
Checking If an Array of Custom Objects Contain a Specific Custom Object
How to Open Your App in Settings iOS 11
Swift Instance Member Cannot Be Used on Type