I have a sound called speeding.mp3 and I am trying to make a AVAudioPayer instance with it by doing this in the root of the class:
let speedingAudioPlayer = try! AVAudioPlayer(contentsOfURL: NSBundle.mainBundle().URLForResource("speeding", withExtension: "mp3")!)
Then when I run the app it throws an error but I don't know why this is happening. The speeding.mp3 file is in the Bundle Resources drop down in Build Phases so it should find it fine. If I try to print out the URL in the simulator and paste it into Safari it loads and plays the file like normal. I am importing AVFoundation into the class and the framework into the project.
Use this code snippet to debug your error,
if let URL = NSBundle.mainBundle().URLForResource("speeding", withExtension: "mp3") {
do {
let speedingAudioPlayer = try AVAudioPlayer(contentsOfURL: URL)
} catch let error as NSError {
print(error.localizedDescription)
}
} else {
print("No such file exist")
}
I found another question where the var is placed outside the class because otherwise it would be deallocated by the phone.
AVAudioPlayer Object Sound Not Playing - Swift
import UIKit
import AVFoundation
class CustomAudioPlayer {
var audioPlayer : AVAudioPlayer!
override func viewDidLoad() {
super.viewDidLoad()
playSound("sound_file_name")
}
func playSound(soundName: String)
{
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(soundName, ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOfURL:alertSound)
audioPlayer.prepareToPlay()
audioPlayer.play()
}catch {
print("Error getting the audio file")
}
}
}
Try this code for playing the sound.
Related
The sound file is playing when i add breakpoints inside the below functions. But the sound file is not playing if i run the application without breakpoint.
I am calling this function in button click as Sound().playSounds()
import AVFoundation
class Sound {
private var audioplayer:AVAudioPlayer!
func playSounds()
{
if let path = Bundle.main.path(forResource: "Audio/ring.mp3", ofType: nil)
{
let url = URL(fileURLWithPath: path)
do {
self.audioplayer = try AVAudioPlayer(contentsOf: url)
self.audioplayer.numberOfLoops = 3
self.audioplayer.prepareToPlay()
self.audioplayer.play()
}
catch {
print("Couldn't load file")
}
}
}
}
Your Sound object gets deallocated before it has a chance to play a sound.
Store it where you are calling it from:
var sound = Sound()
// for example to play sound call
func playPressed(){
sound.playSounds()
}
Chane your player into a global variable like this. Otherwise it'll be a deadlock.
var audioplayer:AVAudioPlayer!
Also you may want to change your resource path extracting logic to below,
if let path = Bundle.main.path(forResource: "ring.mp3", ofType: "mp3")
Or you can directly use Bundle.main.url(forResource: withExtention) method.
I'm working on Xcode 10.1 and this is a very basic snippet of an audio playing app.
var audioplayer:AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "ringtone2", withExtension: "mp3")
guard url != nil else{
return
}
do{
audioplayer = try AVAudioPlayer(contentsOf: url!)
audioplayer?.play()
}
catch{
print("error")
}
}
It should play the ringtone tune but the code enters the catch block and the following is printed:
2019-06-20 15:29:11.573735+0530 letsplaymusic[1539:42595] 1410: Problem scanning for packets
2019-06-20 15:29:11.574033+0530 letsplaymusic[1539:42595] 1008: MPEGAudioFile::OpenFromDataSource failed
2019-06-20 15:29:11.574204+0530 letsplaymusic[1539:42595] 101: OpenFromDataSource failed
2019-06-20 15:29:11.574427+0530 letsplaymusic[1539:42595] 76: Open failed
error
You might be placing your audio file at the wrong place. Try placing your file at the same hierarchy level as your ViewController.swift file.
I'm able to play the sound using the same code you posted, however I can't see where you have put the audio file so I'm guessing that must be the issue.
1. Make Sure .Mp3 file copy in Bundle and confirm with Log
2. player.prepareToPlay() - required function to play the resources
func playAudioFile(_ url: URL) {
print("playing \(url)")
do {
self.player = try AVAudioPlayer(contentsOf: url)
player.prepareToPlay()
player.volume = 1.0
player.play()
} catch {
self.player = nil
print(error.localizedDescription)
print("AVAudioPlayer init failed")
}
}
Happy Coding... :)
I'm new in Swift. I am trying to Run this code but got an error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x48) a.
Error appears here:
self.player.play()
Can anyone help in this issue?
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
do {
if let audioPath = Bundle.main.path(forResource: "music", ofType: "mp3") {
try player = AVAudioPlayer(contentsOf: URL(fileURLWithPath: audioPath))
}
} catch {
print("ERROR")
}
self.player.play()
}
What you doing with your code is:
Creating an instance of AVAudioPlayer without any data
Trying to create a new instance with some data from music.mp3 file
Playing it
If the audioPath is not correct, then the player is not correctly created: application will use the one without valid data, leading to a crash during playback.
Your code can be written making the player optional, which helps preventing the crash:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
player = initializePlayer()
player?.play()
}
private func initializePlayer() -> AVAudioPlayer? {
guard let path = Bundle.main.path(forResource: "music", ofType: "mp3") else {
return nil
}
return try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
}
}
Some changes performed to the code:
player is now optional: there is no need to initialize it twice. Plus if the initialization goes well you can use it without problems, otherwise your app won't crash.
The play method is now in an optional chain
I've moved the initialization of the player in a separate private methods, to maintain the code readable. Feel free to change it, it is just a suggestion.
I've got it. The issue is that the file isn't being coping to my app bundle. To fix it:
Click your project
Click your target
Select Build Phases
Expand Copy Bundle Resources
Click '+' and select your file.
Thanks Denis Hennessy
I have a WAV file with tones at around 18kHz. The audio is 16-bit PCM mono.
I am using the following function to play the file:
func playSound(name: String) {
let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let path = documents.appending("/").appending(name)
let url = NSURL.fileURL(withPath: path)
do {
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.prepareToPlay()
player.play()
} catch let error {
print(error.localizedDescription)
}
}
When I play it on my iOS 10.2 device I hear a series of tones between 1000Hz to 10000Hz. I've analyzed the rendered audio by capturing it and a frequency plot shows that the original content at 18kHz is there, but there are also tones present between 1000Hz to 10000Hz. When I play the same WAV file with VLC or any other desktop audio player, I don't hear the tones (which is expected since they're located around 18kHz). I suspect that the code above isn't loading the data correctly or that the player isn't properly initialized, so I need a seasoned iOS veteran who can tell me what I'm doing wrong.
Thank you in advance.
Check the following code it might work for you
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("button-09", ofType: "wav"))
println(alertSound)
// Removed deprecated use of AVAudioSessionDelegate protocol
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
}
For the var testAudio declaration in my iPhone app, I am receiving an error here
"Call can throw, but errors cannot be thrown out of a property initializer"
import UIKit
import AVFoundation
class ViewController: UIViewController {
var testAudio = AVAudioPlayer(contentsOfURL: NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("testAudio", ofType: "wav")!), fileTypeHint:nil)
This happened when I moved to the Xcode 7 beta.
How can I get this audio clip functioning in Swift 2.0?
Swift 2 has a brand new error handling system, you can read more about it here: Swift 2 Error Handling.
In your case, the AVAudioPlayer constructor can throw an error. Swift won't let you use methods that throw errors in property initializers because there is no way to handle them there. Instead, don't initialize the property until the init of the view controller.
var testAudio:AVAudioPlayer;
init() {
do {
try testAudio = AVAudioPlayer(contentsOfURL: NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource("testAudio", ofType: "wav")!), fileTypeHint:nil)
} catch {
//Handle the error
}
}
This gives you a chance to handle any errors that may come up when creating the audio player and will stop Xcode giving you warnings.
If you know an error won't be returned you can add try! beforehand:
testAudio = try! AVAudioPlayer(contentsOfURL: NSURL (fileURLWithPath: NSBundle.mainBundle().pathForResource
Works for me in Swift 2.2
But don't forget to add the fileName.mp3 to the project Build phases->Copy Bundle Resources (right click on the project root)
var player = AVAudioPlayer()
func music()
{
let url:NSURL = NSBundle.mainBundle().URLForResource("fileName", withExtension: "mp3")!
do
{
player = try AVAudioPlayer(contentsOfURL: url, fileTypeHint: nil)
}
catch let error as NSError { print(error.description) }
player.numberOfLoops = 1
player.prepareToPlay()
player.play()
}