Custom sound with NSTimer - ios

I have a timer that counts down based on input. I want it to play a boxing (round end) sound when it hits 0.
I searched around and found this
// Load
let soundURL = NSBundle.mainBundle().URLForResource(mysoundname, withExtension: "wav")
var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL, &mySound)
// Play
AudioServicesPlaySystemSound(mySound);
I have the following questions:
where do you put the load section? Anywhere specific or it doesn't matter?
are these sounds already preloaded/stored somewhere? How does one get a custom sound?
Thanks in advance,
Ace

My code:
// Load Sound
soundlocation = NSBundle.mainBundle().URLForResource("BoxingBellStart", withExtension: "wav")!
player = AVAudioPlayer(contentsOfURL: soundlocation, error: &Error)
player.volume = 1
// Play Sound
player.play()
BoxingBellStart is a .wav file located in my project

Related

AVAudioPlayerNode keeps repeating sound

I am currently in the process of creating a music application, and will allow the user to change the pitch and speed at which the sound is being played. I am using buttons as the sound initiators, and every time a button is pressed, the corresponding sound will start playing.
This is my current code :
audioPlayer.stop()
engine.stop()
pitchControl.pitch = 0.0
engine = AVAudioEngine()
audioPlayer.volume = 1.0
let precursor = audioFiles[audioFileLinks[sender.tag]]
let path = Bundle.main.path(forResource: precursor, ofType: "mp3")!
let url = NSURL.fileURL(withPath: path)
let file = try? AVAudioFile(forReading: url)
let buffer = AVAudioPCMBuffer(pcmFormat: file!.processingFormat, frameCapacity: AVAudioFrameCount(file!.length))
do {
try file!.read(into: buffer!)
} catch _ {}
engine.attach(audioPlayer)
engine.attach(pitchControl)
engine.attach(speedControl)
engine.connect(audioPlayer, to: speedControl, format: buffer?.format)
engine.connect(speedControl, to: pitchControl, format: buffer?.format)
engine.connect(pitchControl, to: engine.mainMixerNode, format: buffer?.format)        
engine.prepare()
do {
try engine.start()
} catch _ {}
audioPlayer.play()
The point of this code is to get which audio track to play based on the tag of the button pressed by the user. The issue that I am having is that every time I press a button, it will play the sound but it keeps playing the sound indefinitely, even though the actual .mp3 file is only 2 seconds long. I am not sure what I am doing wrong. I do not think I am doing anything wrong, I feel that I am just not setting some value correctly.
All help is appreciated! Thank You in advance!

Limit audio duration when played

I'm trying to build an iOS application using Swift 4 that would play different sounds. Part of what I need to do is to limit the duration of the sound file played depending on some settings.
What I'd like to know is if it's possible to set the duration of the sound prior to playing it so it can stop after the set duration. If so, how?
I'm currently using Swift's AVAudioPlayer but I don't know if it can do it. My current code is shown below:
// resName set depending on settings
url = Bundle.main.url(forResource: resName, withExtension: "mp3")
do{
audioPlayer = try AVAudioPlayer(contentsOf: url!)
audioPlayer.prepareToPlay()
audioPlayer.currentTime = 0
} catch let error as NSError{
print(error.debugDescription)
}
audioPlayer.play()
Thanks in advance for the help :)
Well, since you are in control of playing the sounds, one way how to deal with it would be running a Timer when you start playing that would after the given time period stop playing:
let timeLimit = 1.6 // get it from settings
player.play()
Timer.scheduledTimer(withTimeInterval: timeLimit, repeats: false) { (timer) in
player.stop()
}
And in case you need to cancel it, you can keep a reference to the timer and cancel it using timer.invalidate().
As an audio engineer, I recommend editing your audio to be exactly how you want it to avoid any unwanted artifacts that can happen from coding.

How can I repeat a song in iOS?

I am trying to repeat a song in my app. However, it just plays it until the end, then it stops altogether. How can I put in a loop feature for this?
This is my code in my viewDidLoad:
do
{
let audioPath = Bundle.main.path(forResource: "APP4", ofType: "mp3")
try player = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
}
catch
{
//catch error
}
let session = AVAudioSession.sharedInstance()
do
{
try session.setCategory(AVAudioSessionCategoryPlayback)
}
catch
{
}
player.play()
I'm using Xcode 8.
Use AVAudioPlayer's numberOfLoops property for getting the repeat feature.
From the Apple doc's Discussion section:
A value of 0, which is the default, means to play the sound once. Set a positive integer value to specify the number of times to return to the start and play again. For example, specifying a value of 1 results in a total of two plays of the sound. Set any negative integer value to loop the sound indefinitely until you call the
stop() method.
So use:
player.numberOfLoops = n - 1 // here n (positive integer) denotes how many times you want to play the sound
Or, to avail the infinite loop use:
player.numberOfLoops = -1
// But somewhere in your code, you need to stop this
To stop the playing:
player.stop()
You need to set the numberOfLoops
player.numberOfLoops = 2 // or whatever
From Apple doc:
var numberOfLoops: Int
The number of times a sound will return to the beginning, upon
reaching the end, to repeat playback.
For repeat song you can set the Property numberOfLoops to -1 .It will work as infinity loop
player.numberOfLoops = -1
With SwiftySound, you can do it with a single line of code. All you have to do is pass -1 value for numberOfLoops parameter.
Sound.play(file: "dog", fileExtension: "wav", numberOfLoops: -1)
You can find SwiftySound on GitHub.

AudioServicesCreateSystemSoundID only once in application and play sound from anywhere

I am doing following stuff to play a sound on button tap. But here, I guess it loads sound file every time I tap on button.
if let soundURL = NSBundle.mainBundle().URLForResource("notification", withExtension: "mp3") {
var mySound: SystemSoundID = 0;
AudioServicesCreateSystemSoundID(soundURL, &mySound);
AudioServicesPlaySystemSound(mySound);
}
What I am trying to do is to load above code once in AppDelegate and call below code from any other VC :
let systemSoundID: SystemSoundID = 0;
AudioServicesPlaySystemSound(systemSoundID);
each time I want a sound.
But it causes an error in console showing
Failure to setup sound, err = -50.
Any Solution?
Rather than add to AppDelegate, it may be neater to add a separate class. This works for me:
import AudioToolbox
class PlaySound {
static private var mySound:SystemSoundID = {
// Do it like this so mySound is initialised only when it is first used
var aSound:SystemSoundID = 1000 // a default sound in case we forget the sound file
if let soundURL = NSBundle.mainBundle().URLForResource("Detection", withExtension: "wav") {
AudioServicesCreateSystemSoundID(soundURL, &aSound)
print("Initialised aSound:\(aSound)")
} else {
print("You have forgotten to add your sound file to the app.")
}
return aSound // this value is put into mySound when mySound is first used.
}()
static func play() { AudioServicesPlaySystemSound(mySound) } // play the sound
static func prepare() -> SystemSoundID { return mySound } // call this to preload sound to avoid any delay on first use, if you want
}
Then whenever I need the sound, I write
PlaySound.play()
and that only sets up the sound once, the first time it is used. The print above shows just when, and how many times, it is initialized. If you want to avoid any possibility of delay in setting up the sound when it is first used, you can call
PlaySound.prepare()
in AppDelegate when the app is launched.

Playing Audio From Parse.com

I am trying to play an audio file i saved on parse. I am getting the url from the PFFile from the object i saved to parse. When i run the app the avplayer produces no audio. I tested to see if the avplayer was playing by the first code snippet below and it prints out "Playing" which means the player is playing but no audio. I also tried setting the volume for avplayer and that didn't help. Don't understand why it won't play if anyone would like to help me out.
Audio File URL: http://files.parsetfss.com/292b6f11-5fee-4be7-b317-16fd494dfa3d/tfss-ccc3a843-967b-4773-b92e-1cf2e8f3c1c6-testfile.wav
This Code stops avplayer if it is playing:
if (player.rate > 0) && (player.error == nil) {
// player is playing
println("Playing")
} else {
println("Not Playing")
}
AVPlayer Code:
let objectAudio: PFObject = object as PFObject
let parseAudio: PFFile = objectAudio.valueForKey("audioFileParse") as PFFile
let audioPath: String = parseAudio.url
let urlParse: NSURL = NSURL(fileURLWithPath: audioPath)!
player = AVPlayer(URL: urlParse)
println(player) //prints out <AVPlayer: 0x79e863c0>
player.volume = 1.0
player.play()
You are using the wrong method to get a NSURL here, you try to create a local file URL from an URL that points to a resource on a remote server.
Instead of NSURL(fileURLWithPath: audioPath) you should use the initalizer that accepts an URL string as the input (see here https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/#//apple_ref/occ/instm/NSURL/initWithString:)
Your current code would point to a local resource which does not exist on the local filesystem whereas it should point to the file on the Parse server.
Just as a reference, the difference between URLWithString and fileURLWithPath What is difference between URLWithString and fileURLWithPath of NSURL?

Resources