How I can play audio file after downloaded - ios

I have core library to download audio from server and save in local. But it don't have file extension.
When i try to load the audio file from file path URL, it always to get error at catch part.
it only happens when downloading mp3 files. For m4a it's working.
What wrong i do?
Error:
3531: MP4Parser_PacketProvider->GetASBD() failed
101: OpenFromDataSource failed
76: Open failed
The code i used to load audio at bellow
func setupPlayer(url: URL) {
do {
try AVAudioSession.sharedInstance().setCategory(.playback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
if player != nil {
isPlayerConfigured = true
player?.delegate = self
player?.prepareToPlay()
} else {
isPlayerConfigured = false
isPlaying = false
}
} catch(let error) {
isPlayerConfigured = false
isPlaying = false
loge(error.localizedDescription)
}
}
Thanks for your helping.
Try to load audio file at local without extension file

Related

AVAudioPlayer stops playing after playing a lot of audio files: kAudio_TooManyFilesOpenError

I encountered a similar problem mentioned here. From his findings, apparently, there's a limit to how many files you can play per session.
I tried the method the author posted, but I guess his issue was more to do with simultaneous playback.
What I'm trying to achieve is, I have tons of mp3 files (over 450 files), I'm trying to play each file at a time.
here's the code:
internal class NarrationPlayer {
public var player: AVAudioPlayer?
var narrationFile = [URL]()
deinit {
print("deinit NarrationPlayer")
}
internal func initNarration() {
if player != nil {
player = nil
}
}
public func loadNarration(_ filename: String) {
if narrationFile.count >= 1 {
narrationFile.removeLast(1)
}
let url = Bundle.main.url(forResource: filename, withExtension: "mp3")
if (url == nil) {
print("Could not find file: \(filename)")
return
}
do {
narrationFile.append(url!)
var error: NSError? = nil
do {
player = try AVAudioPlayer(contentsOf: narrationFile[narrationFile.count - 1])
} catch let error1 as NSError {
error = error1
player = nil
}
if let player = player {
player.prepareToPlay()
player.volume = 1
player.play()
} else {
print("Could not create audio player: \(error!)")
}
} catch let error as NSError {
print("error retrieving data: \(error)")
}
}
internal func clearNarration() {
print("[clearNarration]")
if let player = player {
player.stop()
}
narrationFile.removeAll()
player = nil
}
}
after a certain number of files, it stops playing with the following error:
Could not create audio player: Error Domain=NSOSStatusErrorDomain Code=-42
AVAudioPlayer works fine until the app hits that threshold of 49 files (or whatever the threshold is), and the problem is not dependent on the actual file, but the total number of files. I've tried SwiftySound as well since the author of that post was using it, but the result was the same.
Is there any way to clean the memory of the loaded files, or can anyone recommend me other ways to load and play a lot of mp3 files?
I tried everything I could find on the internet.
osstatus was a big help. Apparently, the default limit of audio files AVAudioPlayer can handle is 256.
In order to change this, I created a function and called it in AppDelegate, func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
func extendAudioFileLimit() {
var limit:rlimit = rlimit()
getrlimit(RLIMIT_NOFILE, &limit)
// change this value to suit your needs
limit.rlim_cur = 500
setrlimit(RLIMIT_NOFILE, &limit)
getrlimit(RLIMIT_NOFILE, &limit)
}

How to fix problem with AVAudioPlayer: "OpenFromDataSource failed"

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... :)

While I keep my wrist down, how to keep playing audio in iWatch app? - watchOS

I am trying to build an audio app for apple watch. But the problem is whenever I keep my hands down , audio will stop playing.
I have turned background mode on as well.
Can anyone please help me with this? I am stuck at this part.
Here is the Code I have used for playing audio.
func play(url : URL) {
do {
if #available(watchOSApplicationExtension 4.0, *) {
WKExtension.shared().isFrontmostTimeoutExtended = true
} else {
// Fallback on earlier versions
}
self.player = try AVAudioPlayer(contentsOf: url)
player!.prepareToPlay()
player?.delegate = self
player?.play()
print("-----------------")
print("Playing Audio")
print("*****************\nCurrent Time \(String(describing: self.player?.currentTime))")
} catch let error as NSError {
self.player = nil
print(error.localizedDescription)
} catch {
print("*************************")
print("AVAudioPlayer init failed")
}
}
Make sure you are trying to play with Audio Data, not Audio URL and have added policy: .longFormAudio in your category setup. As per Apple documentation, these two settings have to be set for audio to play in background mode.
// Set up the session.
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(
.playback,
mode: .default,
policy: .longFormAudio
)
} catch let error {
fatalError("*** Unable to set up the audio session: \(error.localizedDescription) ***")
}
// Set up the player.
let player: AVAudioPlayer
do {
player = try AVAudioPlayer(data: audioData)
} catch let error {
print("*** Unable to set up the audio player: \(error.localizedDescription) ***")
// Handle the error here.
return
}
// Activate and request the route.
session.activate(options: []) { (success, error) in
guard error == nil else {
print("*** An error occurred: \(error!.localizedDescription) ***")
// Handle the error here.
return
}
// Play the audio file.
player.play()
}
I have tested this code and its working with only Bluetooth connectivity in Watch application not in watch speaker.
Simply turning on background mode is not enough. You also need to activate the AVAudioSession.
It's all well documented by Apple here: Playing Background Audio.
Configure and Activate the Audio Session
Before you can play audio, you need to set up and activate the audio session.
session.setCategory(AVAudioSession.Category.playback,
mode: .default,
policy: .longForm,
options: [])
Next, activate the session, by calling the activate(options:completionHandler:) method.
session.activate(options: []) { (success, error) in
// Check for an error and play audio.
}
Ref: https://developer.apple.com/documentation/watchkit/playing_background_audio
Example:
var player: AVAudioPlayer?
let session: AVAudioSession = .sharedInstance()
func prepareSession() {
do {
try session.setCategory(AVAudioSession.Category.playback,
mode: .default,
policy: .longForm,
options: [])
}
catch {
print(error)
}
}
func play(url: URL) {
do {
player = try AVAudioPlayer(contentsOf: url)
}
catch {
print(error)
return
}
session.activate(options: []) { (success, error) in
guard error == nil else {
print(error!)
return
}
// Play the audio file
self.player?.play()
}
}
Simple Test:
prepareSession()
if let url = Bundle.main.url(forResource: "test", withExtension: "mp3") {
play(url: url)
}
else {
print("test.mp3 not found in project: put any mp3 file in and name it so")
}

iOS: audio files used in app sound harsher than when played outside the app

The audio files for our iOS app sound much worse when played through the app than when played outside the app. The sounds seem harsher and more "ecohy".
Here's our code for playing audio. Are we somehow altering the playback or natural sound of the audio?
Two of the audio files we're using can be found here:
private func createAudioPlayer(filename: String) -> AVAudioPlayer {
// Define file URL
let path = Bundle.main.path(forResource: filename, ofType: nil)
let url = URL(fileURLWithPath: path!)
// Create player
let audioPlayer: AVAudioPlayer!
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
} catch {
audioPlayer = nil
printError("Error creating audio player for \(url): \(error)")
logEvent("Audio Error", userData: nil)
}
// Print status
print("Created audio player for \(filename)")
// Return player
return audioPlayer
}
func play(file: AudioFileEnum) {
if let player = audioPlayers[file] {
if player.isPlaying {
player.pause()
}
player.currentTime = 0
player.play()
} else {
printError("Error finding audio player for \(file)")
}
}
Have you tried setting the volume on the audioPlayer object to something smaller, like 0.05f, and adjusting from there?

AVAudioPlayer produces lag playing sound effect

I'm using the SKTAudio library given by Ray Wenderlich on his Github. Here's the code I've modified for playing a sound effect that I call everytime I play one:
public func playSoundEffect(_ filename: String) {
let url = Bundle.main.url(forResource: filename, withExtension: nil)
if (url == nil) {
print("Could not find file: \(filename)")
return
}
if !UserDefaults.standard.bool(forKey: "soundOff"){
var error: NSError? = nil
do {
soundEffectPlayer = try AVAudioPlayer(contentsOf: url!)
} catch let error1 as NSError {
error = error1
soundEffectPlayer = nil
}
if let player = soundEffectPlayer {
DispatchQueue.global(qos: .background).async {
player.numberOfLoops = 0
player.prepareToPlay()
player.play()
}
} else {
print("Could not create audio player: \(error!)")
}
}
}
I'm using this because this way I can mute the sound effects easily, since this is using a singleton class method. The thing is, this produces minor lag everytime I play a sound effect. If I mute the game, no lag. I tried making the sound play in a background thread, but the result is the same.
Is there any easy change to this code to make it have NO LAG?
EDIT: This is not a duplicate because none of the other answers on other questions solved my problem.

Resources