I have this file and want to use this file in another class, but this does not work. I assume that this is because I have not initialized the AVAudioPlayer in this file, so I tackled with this, but a message appeared, saying "Call can throw, but it is not marked with 'try' and the error is not handled" My implementation was unsuccessful. I have no idea how to deal with this. Could you point out what is wrong with the initialization and provide me with some code that works. Thanks in advance.
class SoundManager: AVAudioPlayer {
var _Sound: AVAudioPlayer!
override init() {
let url = NSBundle.mainBundle().URLForResource("rain", withExtension: "wav")
super.init(contentsOfURL: url!)
}
func playSound() {
if (url == nil) {
print("Could not find the file \(_Sound)")
}
do {
_Sound = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil)
}
catch let error as NSError { print(error.debugDescription)
}
if _Sound == nil {
print("Could not create audio player")
}
_Sound.prepareToPlay()
_Sound.numberOfLoops = -1
_Sound.play()
}
}
I recommend to use this way init you manager, It does not have to be subclass of AVAudioPlayer.
class SoundManager {
var _Sound: AVAudioPlayer!
var url: NSURL?
/**
init with file name
- parameter fileName: fileName
- returns: SoundManager
*/
init(fileName: String) {
url = NSBundle.mainBundle().URLForResource(fileName, withExtension: "wav")
}
func playSound() {
if (url == nil) {
print("Could not find the file \(_Sound)")
}
do {
_Sound = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil)
}
catch let error as NSError { print(error.debugDescription)
}
if _Sound == nil {
print("Could not create audio player")
}
_Sound.prepareToPlay()
_Sound.numberOfLoops = -1
_Sound.play()
}
}
Use
let manager = SoundManager(fileName: "hello")
manager.playSound()
Related
I'm trying to download a URL from Firebase storage and save it to an AVAudioPlayer
func loadAudio(post: CompPost, completion: #escaping (AVAudioPlayer) -> ())
{
let audioRef = Storage.storage().reference().child("cPosts").child(post.uid).child("Audio").child(post.mp3)
audioRef.downloadURL
{ (url, error) in
print("mp3filename: " + post.mp3)
guard error == nil else
{
print(error!.localizedDescription)
return /**alert**/ }
let audioURL = url
print("url:" + audioURL!.absoluteString)
do
{
try self.audioPlayer = AVAudioPlayer(contentsOf: audioURL!)
completion(self.audioPlayer)
print("THIS HAS LOADED")
}
catch
{
print("COULD NOT ASSIGN URL") /**alert**/
//ERROR here that keeps on happening :(
}
}
}
I know for a fact it's the correct file from storage, and that there's no error getting the url because of my print statements to check, however, for some reason there is an issue setting this URL to the contents of my AVAudioPlayer, audioPlayer
What #jnpdx meant (I think is) - this way you can let iOS stream directly from the remote URL, without handling downloading the file yourself
func loadAudio(post: CompPost, completion: #escaping (AVAudioPlayer) -> ())
{
let audioRef = Storage.storage().reference().child("cPosts").child(post.uid).child("Audio").child(post.mp3)
audioRef.downloadURL
{ (url, error) in
print("mp3filename: " + post.mp3)
guard error == nil else
{
print(error!.localizedDescription)
return /**alert**/ }
let audioURL = url
print("url:" + audioURL!.absoluteString)
do
{
**try self.audioPlayer = AVPlayer(url: audioURL!)**
completion(self.audioPlayer)
print("THIS HAS LOADED")
}
catch
{
print("COULD NOT ASSIGN URL - Error = /(error)") /**alert**/
//ERROR here that keeps on happening :(
}
}
}
instead of:
try self.audioPlayer = AVAudioPlayer(contentsOf: audioURL!)
try using this (note the try position):
do {
self.audioPlayer = try AVAudioPlayer(contentsOf: audioURL!)
completion(self.audioPlayer)
} catch {
print("===> " + error.localizedDescription)
}
you can of course use AVPlayer as well (without the do/catch)
I want to download and play the sound from Google Translate (Text to Speech).
The mp3 file's downloaded successfull. I tried to play it with AVAudioPlayer, but there's no sound on both simulator and my real iPhone
I use XCode 10.2.1, Swift 5. Test on simulator (XSMax) and iPhone XSMax
import UIKit
import AVFoundation
class TextToSpeechGoogleTranslate: AVAudioPlayer, AVAudioPlayerDelegate {
var player: AVAudioPlayer?
func speak() {
let fileURL = URL(string: "https://translate.google.com/translate_tts?ie=UTF-8&total=1&idx=0&client=tw-ob&tl=vi&q=Hello" )!
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
let destinationFileUrl = documentsUrl.appendingPathComponent("voice.mp3")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try? FileManager.default.removeItem(at: destinationFileUrl)
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
print(destinationFileUrl)
do {
self.player = try AVAudioPlayer(contentsOf: destinationFileUrl)
self.player!.delegate = self
self.player!.prepareToPlay()
self.player!.volume = 1.0
self.player!.play()
}
catch let error as NSError {
print("Error: \(error.localizedDescription)")
}
catch {
print("AVAudioPlayer init failed")
}
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription as Any);
}
}
task.resume()
}
}
Output:
Successfully downloaded. Status code: 200
file:///Users/macbook/Library/Developer/CoreSimulator/Devices/F43F9B03-674C-4EE1-8CAD-01B5145868DE/data/Containers/Data/Application/6D1A3310-386D-4706-9F1E-DFF536B2A43F/Documents/voice.mp3
I played that file in Finder. It's OK.
I just tried your code and it seems to work fine. Maybe the problem is in how you create the TextToSpeechGoogleTranslate object and call speak() on it. For example, here is what I tried:
class ViewController: UIViewController {
var test: TextToSpeechGoogleTranslate?
override func viewDidLoad() {
super.viewDidLoad()
test = TextToSpeechGoogleTranslate()
test!.speak()
}
}
If that doesn't help, can you post some code showing how you call this method?
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate {
var audioPlayer = TextToSpeechGoogleTranslate()
override func viewDidLoad() {
super.viewDidLoad()
audioPlayer.delegate = self
audioPlayer!.speak()
}
}
1) create instance of your class
2) Confirm it's delegate
3) call your function after you received your data
4) while testing from device, don't forget to turn off silence mode (volume up)
I am trying to trigger a function when a song finishes playing. Here is my audio player class:
import AVFoundation
public class SKTAudio {
public var backgroundMusicPlayer: AVAudioPlayer?
public func playBackgroundMusic(filename: String) {
let url = Bundle.main.url(forResource: filename, withExtension: nil)
if (url == nil) {
print("Could not find file: \(filename)")
return
}
var error: NSError? = nil
do {
backgroundMusicPlayer = try AVAudioPlayer(contentsOf: url!)
} catch let error1 as NSError {
error = error1
backgroundMusicPlayer = nil
}
if let player = backgroundMusicPlayer {
player.delegate = self
player.prepareToPlay()
player.play()
} else {
print("Could not create audio player: \(error!)")
}
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer,
// Do stuff
}
}
However, the code won't compile, and the line player.delegate = self returns this error:
Cannot assign value of type 'SKTAudio' to type
'AVAudioPlayerDelegate?'
And gives the option to:
Insert ' as! AVAudioPlayerDelegate'
This compiles, but, upon running, crashes and returns the following in console:
Could not cast value of type 'Scene.SKTAudio' (0x102ebf7b0) to
'AVAudioPlayerDelegate'
Where playBackgroundMusic() is called within Scene. I have no clue what to do at this point, I've tried to follow various other posts but nobody seems to face an issue with the player.delegate = self line. Thank you
I have been trying to make a game to teach myself swift, and cant seem to get this code to work. I am extremely new to this, and can't seem to find out why it won't work... XCode doesn't flag any problems, build sucseed, and debugger even prints "Got to Stage 1 & Got to Stage 2... anything help?
I Imported AVFoundation..
class GAME {
class func SuperStartGame(playerwhowon1: SKSpriteNode) {
var player = AVAudioPlayer()
func PlaySound() {
guard let URL = Bundle.main.url(forResource: "PowerUp", withExtension: "mp3")
else {
print("Didn't Find URL")
return
}
do {
print("Got to Stage 1")
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: URL, fileTypeHint: "mp3")
player.prepareToPlay()
player.play()
print("Got to Stage 2")
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
RoundNumber += 1
Round.text = "Round \(RoundNumber)"
if playerwhowon1 == Mine {
MyScore.run(addscoreM) {
PlaySound()
Round.run(NewRoundForRound) {
...
Code keeps going.. thats the only part that is relevant to the sound. I added the sound file to Xcode, and made sure it was added tot he project target... it is in my main bundle.
Make sure that your device isn't muted
mp3 file is copied to bundle
Example VC playing sound:
class ViewController: UIViewController {
var game = Game()
#IBAction func playAction(_ sender: UIButton) {
game.playSound()
}
}
class Game {
var player: AVAudioPlayer?
func playSound() {
guard let URL = Bundle.main.url(forResource: "SampleAudio", withExtension: "mp3") else {
print("Didn't Find URL")
return
}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: URL, fileTypeHint: "mp3")
player?.prepareToPlay()
player?.play()
} catch let error as NSError {
print("\(error.localizedDescription)")
}
}
}
I have been trying to figure out how to deactivate playing a sound. I tried to attached a removeAtionWithKey with a sound action, and it seems to be working fine, but the sound does not stop to play. Is this because I am using action in SpriteKit?
If this problem is solved here instead of importing AVFoundation, then could you give me some examples to stop a sound from being played? Or, if importing AVFoundation is preferred in this case, could you provide me with some code as well.
Here's an example of how to use AVFoundation.
import Foundation
import AVFoundation
var backgroundMusicPlayer: AVAudioPlayer!
func playBackgroundMusic(filename: String) {
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: "mp3")
if (url == nil) {
print("Could not find the file \(filename)")
}
do { backgroundMusicPlayer = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil) } catch let error as NSError { print(error.debugDescription)}
if backgroundMusicPlayer == nil {
print("Could not create audio player")
}
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
}
var Sound: AVAudioPlayer!
func playSound(filename: String) {
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: "wav")
if (url == nil) {
print("Could not find the file \(filename)")
}
do { Sound = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil) } catch let error as NSError { print(error.debugDescription)}
if Sound == nil {
print("Could not create audio player")
}
Sound.prepareToPlay()
Sound.play()
}
And here's what you want to achieve (if I understood well):
#IBAction func MusicButton(sender: UIButton) {
if backgroundMusicPlayer.playing {
backgroundMusicPlayer.stop()
}
else {
playBackgroundMusic("SomeMusicName")
}
}
Stopping the music with AVFoundation is as easy as .stop() ^^!