I'm trying to set a background jingle for my game which is supposed to start at the Home scene and then loop continuously even while on the other scenes.
This is what my class looks like:
class AudioPlayer: AVAudioPlayer {
var audioPlayer: AVAudioPlayer? = AVAudioPlayer()
let ost = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("bkg", ofType: "mp3")!)
func playOst() {
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: ost)
}
catch {
audioPlayer = nil
}
audioPlayer?.prepareToPlay()
audioPlayer!.play()
audioPlayer!.numberOfLoops = -1
}
func stopOst() {
audioPlayer!.stop()
}
since I put the play method in the home scene, it will start playing a new track every time I load it, overlaying one track on another making it result in a big mess. How can I prevent it?
Make your audio player class a singleton, or let AppDelegate look after it. This will also allow you to control the music from any scene/screen in your app at any time.
Whenever your home screen loads check to see if music is already playing, if not, call playOst, otherwise do nothing.
Related
I'm using the following code to play a sound file twice. The second sound plays immediately following the first
Is it possible to leave a time gap (1 second) between them? I've tried to find a solution reading the Apple Docs
var letterSound: AVAudioPlayer!
...
#IBAction func speakLetter(sender: AnyObject) {
let soundFile: String = "SoundFile" + String(letterNumber)
let path = Bundle.main.path(forResource: soundFile, ofType:"mp3")!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
letterSound = sound
letterSound.numberOfLoops = 1
letterSound.play()
} catch {
// couldn't load file :(
}
}
One option would be to add some 'white space' or silence at the end of your audio file.
If you don't have an audio editor i'd recommend Audacity, it's free and there are lots of tutorials on how to add silence.
If you want a more code based option you could look in to using the AVAudioPlayerDelegate didFinishPlaying method to detect the end of the first play and then use play(atTime:) to trigger the next loop 1 second from now.
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
player.play(atTime: player.deviceCurrentTime + 1.0)
}
This code is untested and I think it might create an infinite loop so you may need some additional logic here to make sure it only loops once
I want to be able to add a video (called "Logo-Animation4.mp4") into the UI in Swift, just like you can a UIImage in a UIImageView.
Right now, I've tried just putting an AVPlayer on the view, but it comes up with the default iOS AVPlayer, which contains the regular fullscreen, controls, and volume stuff that I don't want. I just want the video to play in the UI without any way to have the user interact with it.
I've thought about animating the video using a regular UIImageView's animation feature, but my video isn't that short, and it would be hard to get every single frame, and input it into the code.
How should I go about doing this?
To achieve what you are asking, you'll need to use AVPlayerLayer
Add a UIView outlet
#IBOutlet weak var videoView: UIView!
Import AVFoundation
Create player variables
var player : AVPlayer!
var avPlayerLayer : AVPlayerLayer!
Add the following code to your viewDidLoad
guard let path = Bundle.main.path(forResource: "Logo-Animation4", ofType:"mp4") else {
debugPrint("Logo-Animation4.mp4 not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
avPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.videoGravity = AVLayerVideoGravity.resize
videoView.layer.addSublayer(avPlayerLayer)
player.play()
Add this method
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
avPlayerLayer.frame = videoView.layer.bounds
}
In SpriteKit (for those unfamiliar with it) there's a way to load and unload scenes, and a transition (visual) between them.
I'm trying to make a sound play between scenes, as they transition... that doesn't stutter.
So far, all the ways I've tried either create no sound, or the sound stutters, even using a sound manager, like this:
import AVFoundation
import SpriteKit
open class SoundManager {
static let soundStart = SKAction.playSoundFileNamed("ActionBeep_AP1.7", waitForCompletion: true)
static var coinSound = NSURL(fileURLWithPath:Bundle.main.path(forResource: "ActionBeep_AP1.7", ofType: "wav")!)
static var audioPlayer = AVAudioPlayer()
open static func playCoinSound(){
guard let soundToPlay = try? AVAudioPlayer(contentsOf: coinSound as URL) else {
fatalError("Failed to initialize the audio player with asset: \(coinSound)")
}
soundToPlay.prepareToPlay()
self.audioPlayer = soundToPlay
self.audioPlayer.play()
}
}
Anyone had any success making scene transition sounds run smoothly? I realise there's a lot going on during a scene transition, and that's probably not helping the sound engine. But think there must be a way to make a clear sound play during a scene transition.
And yes, I've tried with .caf and .mp3 and .wav files, all with different "compression" and raw states. I think it's how I play the sounds that's the problem, not the file type.
As crashoverride777 said, you need to change when you load the sound manager. You could set up a thread in your didMoveToView() function to minimize loading time:
DispatchQueue.global(qos: .userInitiated).async {
// Load your sound stuff
}
Now, you have your sound file loaded for whenever you need it, lag-free.
I am trying to add sound effects to a game app I am making in Xcode 6. Here is the code that I am using to play the sounds:
var jumpSoundPlayer:AVAudioPlayer = AVAudioPlayer()
var jumpAudioPath:String = ""
var jumpSoundError: NSError? = nil
func setUpSoundPlayers(){
jumpAudioPath = NSBundle.mainBundle().pathForResource("Jump", ofType: "mp3")!
jumpSoundError = nil
jumpSoundPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: jumpAudioPath), fileTypeHint: "mp3", error: &jumpSoundError)
}
func playJumpSound(volume:Float = 1){
jumpSoundPlayer.volume = volume
jumpSoundPlayer.play()
}
I can get sounds to play, but it seems as though it will not play a sound until the one currently playing is finished. How can I get it so that multiple sounds can play at once and overlap each other?
Also, every time a sound plays it drops the frame rate down a little bit. Is there a way to fix that?
I believe you have to use
jumpSoundPlayer.prepareToPlay()
before using
jumpSoundPlayer.play()
Also the only solution to drop the frame rate a little less, is to set up all the AVAudioPlayers before using them or at the beginning of the game.
I want to play an intro video for my iPhone app the first time it launches. I have it set up to detect that it's the first launch, but how do I play the video from the app (not a url) using SWIFT? Do I set it up in the first ViewController file or in the AppDelegate? I've tried using MPMoviePlayerController, but I just can't seem to get it to actually play. Thank you for your help!
I had this same trouble. Here's my solution:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.controlStyle = .None
player.prepareToPlay()
player.scalingMode = .AspectFit
self.view.addSubview(player.view)
}
}
Don't forget to import MediaPlayer and declare your variable - var moviePlayer: MPMoviePlayerController?
Then call your function when you want to play it playVideo()
See my question for how to dismiss it - In iOS how do I programmatically add a video view and then remove it after it finishes playing using Swift?
I got a really helpful answer there.
Also notice that I disabled my controllers because I don't want it to be seen.