Быстрое создание и воспроизведение звука

104

Итак, что я хочу сделать, так это создать и быстро воспроизвести звук, который будет воспроизводиться, когда я нажимаю кнопку, я знаю, как это сделать в Objective-C, но кто-нибудь знает, как это сделать в Swift?

Для Objective-C это будет примерно так:

NSURL *soundURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"mysoundname" ofType:@"wav"]];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &mySound);

А потом, чтобы поиграть, я бы сделал:

AudioServicesPlaySystemSound(Explosion);

Кто-нибудь знает, как я мог это сделать?

Джейкоб Бэнкс
источник
2
Корень этого вопроса в том, как вызывать функции C из swift. Мне это тоже интересно.
67cherries 04
эта строка может создать звуковой URL: var url :NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mysoundname", ofType: "wav"))
Коннор
@connor Спасибо, что работает, но как насчет AudioServicesCreateSystemSoundID
Джейкоб Бэнкс,
Я не уверен в этом. Мне удалось вызвать только API objective-c из Swift.
Коннор

Ответы:

84

Вот небольшой код, который я добавил во FlappySwift, который работает:

import SpriteKit
import AVFoundation

class GameScene: SKScene {

    // Grab the path, make sure to add it to your project!
    var coinSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "coin", ofType: "wav")!)
    var audioPlayer = AVAudioPlayer()

    // Initial setup
    override func didMoveToView(view: SKView) {
        audioPlayer = AVAudioPlayer(contentsOfURL: coinSound, error: nil)
        audioPlayer.prepareToPlay()
    }

    // Trigger the sound effect when the player grabs the coin
    func didBeginContact(contact: SKPhysicsContact!) {
        audioPlayer.play()
    }

}
Бауэрпауэр
источник
Казалось бы, вы могли бы просто объявить audioPlayer прямо перед его использованием, но у меня это не сработало в симуляторе. Я должен был объявить это наверху, как и вы.
Adam Loving
@Adam Loving, вы можете объявить audioPlayer прямо перед его использованием, но убедитесь, что вы вызываете play () в той же функции, которую вы его объявили (в отличие от хорошего ответа). Кроме того, я бы объявил coinSoundи audioPlayerwith letвместо, varпоскольку вы не хотите измените эти объекты позже.
fat32
3
В Swift 2 не забудьте запустить его таким образом, do { (player object) } catch _ { }иначе вы получите ошибку! :)
ParisNakitaKejser
1
Но внимание! Это приостановит фоновую музыку из плеера. Чтобы проиграть короткий звук, мы должны использовать ответ ниже
Никита Прончик
Голос против
119

Это похоже на некоторые другие ответы, но, возможно, немного больше "Swifty":

// Load "mysoundname.wav"
if let soundURL = Bundle.main.url(forResource: "mysoundname", withExtension: "wav") {
    var mySound: SystemSoundID = 0
    AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
    // Play
    AudioServicesPlaySystemSound(mySound);
}

Обратите внимание, что это тривиальный пример, воспроизводящий эффект кода в вопросе. Вам нужно обязательно это сделать import AudioToolbox, плюс общий шаблон для этого типа кода будет заключаться в том, чтобы загружать ваши звуки при запуске вашего приложения, сохранять их SystemSoundIDгде-то в переменных экземпляра, использовать их во всем приложении, а затем вызывать, AudioServicesDisposeSystemSoundIDкогда вы закончите с ними.

Мэтт Гибсон
источник
1
Вам также необходимо импортировать AudioToolbox
Броди Робертсон
Вам нужно позвонить, AudioServicesDisposeSystemSoundID(mySound)чтобы в дальнейшем освободить память? если вы сделаете это сразу, звук в основном не воспроизводится (очищается мгновенно), поэтому я сделал это dispatch_afterи очистил его через 10 секунд.
owenfi
@owenfi Фрагмент кода в моем ответе - это просто Swift-эквивалент фрагмента кода в вопросе. Общий шаблон для AudioServices состоит в том, чтобы загружать ваши звуки при запуске вашего приложения, использовать их во всем приложении и удалять их при закрытии приложения, но каждое приложение будет отличаться.
Мэтт Гибсон
@ozgur Почему вы используете устаревшую версию Xcode? Нам нужно знать, что означает «не работает», и вам, вероятно, будет лучше задать новый вопрос, если у вас есть конкретные проблемы.
Мэтт Гибсон
на самом деле это единственный способ воспроизвести файл wav. AVPlayer не работает.
Хайтао
18

Удобное расширение Swift:

import AudioToolbox

extension SystemSoundID {
    static func playFileNamed(fileName: String, withExtenstion fileExtension: String) {
        var sound: SystemSoundID = 0
        if let soundURL = NSBundle.mainBundle().URLForResource(fileName, withExtension: fileExtension) {
            AudioServicesCreateSystemSoundID(soundURL, &sound)
            AudioServicesPlaySystemSound(sound)
        }
    }
}

Затем из любого места вашего приложения (не забудьте import AudioToolbox) вы можете позвонить

SystemSoundID.playFileNamed("sound", withExtenstion: "mp3")

проиграть "sound.mp3"

Алейкс Пинарделл
источник
Когда я выполняю это в игре SpriteKit, всегда есть задержка перед воспроизведением звука. Даже если я положу внутрь DispatchQueue.global(qos: .userInitiated).async {}.
Джон Кантнер
NSBundleзаменен на Bundle, используйте Bundle.main.url(forResource: fileName, withExtension: fileExtension)вместо
диаходелический
14

Это создает SystemSoundIDиз файла с именем Cha-Ching.aiff.

import AudioToolbox

let chaChingSound: SystemSoundID = createChaChingSound()

class CashRegisterViewController: UIViewController {
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        AudioServicesPlaySystemSound(chaChingSound)
    }
}

func createChaChingSound() -> SystemSoundID {
    var soundID: SystemSoundID = 0
    let soundURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), "Cha-Ching", "aiff", nil)
    AudioServicesCreateSystemSoundID(soundURL, &soundID)
    CFRelease(soundURL)
    return soundID
}
ma11hew28
источник
Вы пытались скомпилировать код? Я получаю сообщение об ошибке «Невозможно преобразовать тип извлечения« Неуправляемый <CFURL>! » для ввода "CFString" "из этой строки" let soundURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), "Cha-Ching", "aiff", nil) "
bpolat
Да, он компилируется для меня. См github.com/acani/Chats/blob/master/Chats/Chats/...
ma11hew28
2
Это должен быть принятый ответ, учитывая, что предоставленный пример Obj-C основан на AudioToolBox Framework
eharo2
@JochenBedersdorfer, вы, вероятно, получаете сообщение об ошибке из-за того, что объекты Core Foundation автоматически управляются памятью.
XCool
8

С классом и AudioToolbox:

import AudioToolbox

class Sound {

    var soundEffect: SystemSoundID = 0
    init(name: String, type: String) {
        let path  = NSBundle.mainBundle().pathForResource(name, ofType: type)!
        let pathURL = NSURL(fileURLWithPath: path)
        AudioServicesCreateSystemSoundID(pathURL as CFURLRef, &soundEffect)
    }

    func play() {
        AudioServicesPlaySystemSound(soundEffect)
    }
}

Использование:

testSound = Sound(name: "test", type: "caf")
testSound.play()
Каримхоссенбукс
источник
2
Мне нравится этот ответ. Кроме того, поскольку это системный звук, я не получаю системного сообщения, которое AVAudioPlayer выдает в консоль для xcode 8.
TPot
помогите пожалуйста, я делаю то же самое, звук воспроизводится, но громкость слишком низкая. не слышу
веереш кумбар
5
import AVFoundation

var audioPlayer = AVAudioPlayer()

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {

        let soundURL = NSBundle.mainBundle().URLForResource("04", withExtension: "mp3")
        audioPlayer = AVAudioPlayer(contentsOfURL: soundURL, error: nil)
        audioPlayer.play()
    }
}
Майкл Н
источник
Это AVAudioPlayer (contentsOf: soundURL) в современном Swift
штучной упаковке
5

Этот код у меня работает. Используйте Try and Catch для AVAudioPlayer

import UIKit
import AVFoundation
class ViewController: UIViewController {

    //Make sure that sound file is present in your Project.
    var CatSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Meow-sounds.mp3", ofType: "mp3")!)
    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        do {

            audioPlayer = try AVAudioPlayer(contentsOfURL: CatSound)
            audioPlayer.prepareToPlay()

        } catch {

            print("Problem in getting File")

        }      
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func button1Action(sender: AnyObject) {

        audioPlayer.play()
    }
}
Сачин Добария
источник
4
var mySound = NSSound(named:"Morse.aiff")
mySound.play()

«Morse.aiff» - это системный звук OSX, но если вы просто нажмете на «named» в XCode, вы сможете увидеть (на панели QuickHelp), где эта функция ищет звуки. Это может быть ваша папка "Вспомогательные файлы".

Филипп
источник
4
Вопрос по iOS.
rmaddy 04
Действительно ... Не удалось сделать это в симуляторе. На сегодняшний день нет доступных документов
philippe
4

Согласно новому Swift 2.0 мы должны использовать do try catch. Код будет выглядеть так:

var badumSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("BadumTss", ofType: "mp3"))
var audioPlayer = AVAudioPlayer()
 do {
     player = try AVAudioPlayer(contentsOfURL: badumSound)
 } catch {
     print("No sound found by URL:\(badumSound)")
 }
 player.prepareToPlay()
Роман Сафин
источник
3

это работает со Swift 4:

if let soundURL = Bundle.main.url(forResource: "note3", withExtension: "wav") {
                var mySound: SystemSoundID = 0
                AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
                // Play
                AudioServicesPlaySystemSound(mySound);
            }
Мохаммад Абоелнаср
источник
2
Пожалуйста, объясните свой код. Только кодовые ответы менее ценны, чем объяснения.
Винсент
@Vincent +1, на самом деле мне интересно, & оператор. Это может быть ссылка между звуком и памятью.
elia
вам нужно добавить импорт AudioToolbox, затем добавить приведенный выше код
Мохаммад Абоелнаср,
2
//Swift 4
import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player : AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func notePressed(_ sender: UIButton) {
        let path = Bundle.main.path(forResource: "note1", ofType: "wav")!
        let url = URL(fileURLWithPath: path)
        do {
            player = try AVAudioPlayer(contentsOf: url)
            player?.play()
        } catch {
            // error message
        }
    }
}
Сома Шарма
источник
2

Давайте посмотрим на более обновленный подход к этому вопросу:

Import AudioToolbox

func noteSelector(noteNumber: String) {

    if let soundURL = Bundle.main.url(forResource: noteNumber, withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
        AudioServicesPlaySystemSound(mySound)
}
Адам Эбербах
источник
1
Код отлично работает на Swift 4, но, очевидно, издаваемый звук не соответствует громкости мультимедиа
Дэвид Варгас
1

Решение Мэтта Гибсона сработало для меня, вот версия быстрой 3.

if let soundURL = Bundle.main.url(forResource: "ringSound", withExtension: "aiff") {
  var mySound: SystemSoundID = 0
  AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
  AudioServicesPlaySystemSound(mySound);
}
Павле Миятович
источник
1

Swift 4

import UIKit
import AudioToolbox

class ViewController: UIViewController{

var sounds : [SystemSoundID] = [1, 2, 3, 4, 5, 6, 7]

override func viewDidLoad() {
    super.viewDidLoad()

    for index in 0...sounds.count-1 {
        let fileName : String = "note\(sounds[index])"

        if let soundURL = Bundle.main.url(forResource: fileName, withExtension: "wav") {
            AudioServicesCreateSystemSoundID(soundURL as CFURL, &sounds[index])
        }
    }
}



@IBAction func notePressed(_ sender: UIButton) {
    switch sender.tag {
    case 1:
        AudioServicesPlaySystemSound(sounds[0])
    case 2:
        AudioServicesPlaySystemSound(sounds[1])
    case 3:
        AudioServicesPlaySystemSound(sounds[2])
    case 4:
        AudioServicesPlaySystemSound(sounds[3])
    case 5:
        AudioServicesPlaySystemSound(sounds[4])
    case 6:
        AudioServicesPlaySystemSound(sounds[5])
    default:
        AudioServicesPlaySystemSound(sounds[6])
    }
}
}

или

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate{

var audioPlayer : AVAudioPlayer!

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func notePressed(_ sender: UIButton) {

    let soundURL = Bundle.main.url(forResource: "note\(sender.tag)", withExtension: "wav")

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
    }
    catch {
        print(error)
    }

    audioPlayer.play()

}
}

источник
1

работает в Xcode 9.2

if let soundURL = Bundle.main.url(forResource: "note1", withExtension: "wav") {
   var mySound: SystemSoundID = 0
   AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
   // Play
    AudioServicesPlaySystemSound(mySound);
 }
Рэй Сойер
источник
1

Пример кода Swift :

import UIKit
import AudioToolbox

class ViewController: UIViewController {  

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func notePressed(_ sender: UIButton) {

    // Load "mysoundname.wav"

    if let soundURL = Bundle.main.url(forResource: "note1", withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
    // Play

        AudioServicesPlaySystemSound(mySound);
    }
}
Павел
источник
Пожалуйста, расскажите подробнее, почему этот код полезен.
Berendschot
1

Вы можете попробовать это в Swift 5.2:

func playSound() {
        let soundURL = Bundle.main.url(forResource: selectedSoundFileName, withExtension: "wav")
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
        }
        catch {
            print(error)
        }
        audioPlayer.play()
    }
Xab Ion
источник
1

swift 4 и iOS 12

var audioPlayer: AVAudioPlayer?

override func viewDidLoad() {
    super.viewDidLoad()



}

@IBAction func notePressed(_ sender: UIButton) {

    // noise while pressing button

    _ = Bundle.main.path(forResource: "note1", ofType: "wav")

    if Bundle.main.path(forResource: "note1", ofType: "wav") != nil {
        print("Continue processing")
    } else {
        print("Error: No file with specified name exists")
    }

    do {
        if let fileURL = Bundle.main.path(forResource: "note1", ofType: "wav") {
            audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileURL))
        } else {
            print("No file with specified name exists")
        }
    } catch let error {
        print("Can't play the audio file failed with an error \(error.localizedDescription)")
    }


    audioPlayer?.play()    }

}

Гулсан Борбхуия
источник
Не просто размещайте код - объясните, что он делает! stackoverflow.com/help/how-to-answer
Нино Филиу
пожалуйста, обратитесь к вопросу этого сообщения. Вы можете найти свой ответ! спасибо @NinoFiliu
Gulsan Borbhuiya
0

Используйте эту функцию для создания звука в Swift (вы можете использовать эту функцию там, где хотите воспроизводить звук.)

Сначала добавьте SpriteKit и AVFoundation Framework.

import SpriteKit
import AVFoundation
 func playEffectSound(filename: String){
   runAction(SKAction.playSoundFileNamed("\(filename)", waitForCompletion: false))
 }// use this function to play sound

playEffectSound("Sound File Name With Extension")
// Example :- playEffectSound("BS_SpiderWeb_CollectEgg_SFX.mp3")
Ракша Шайни
источник
0

Этот код работает для меня:

class ViewController: UIViewController {

    var audioFilePathURL : NSURL!
    var soundSystemServicesId : SystemSoundID = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        audioFilePathURL = NSBundle.mainBundle().URLForResource("MetalBell", withExtension: "wav")

        AudioServicesCreateSystemSoundID( audioFilePathURL, &soundSystemServicesId)


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.


    }


    @IBAction func PlayAlertSound(sender: UIButton) {

         AudioServicesPlayAlertSound(soundSystemServicesId)
    }
}
Джива
источник
0

Для Swift 3 :

extension SystemSoundID {
    static func playFileNamed(_ fileName: String, withExtenstion fileExtension: String) {
        var sound: SystemSoundID = 0
        if let soundURL = Bundle.main.url(forResource: fileName, withExtension: fileExtension) {
            AudioServicesCreateSystemSoundID(soundURL as CFURL, &sound)
            AudioServicesPlaySystemSound(sound)
        }
    }
}
Хэ Ифэй 何 一 非
источник
0

Swift 3 вот как я это делаю.

{

import UIKit
import AVFoundation

        let url = Bundle.main.url(forResource: "yoursoundname", withExtension: "wav")!
        do {

            player = try AVAudioPlayer(contentsOf: url); guard let player = player else { return }

            player.prepareToPlay()
            player.play()
        } catch let error as Error {
            print(error)

        }
    }

источник
0

Не могли бы вы просто import AVFoundationвыбрать аудиоплеер ( var audioPlayer : AVAudioPlayer!) и воспроизвести звук? ( let soundURL = Bundle.main.url(forResource: "sound", withExtension: "wav")

BoeingLikesToDab
источник
0
import UIKit
import AudioToolbox

class ViewController: UIViewController {

    let toneSound : Array =  ["note1","note2","note3","note4","note5","note6"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

    }

    func playSound(theTone : String) {
        if let soundURL = Bundle.main.url(forResource: theTone, withExtension: "wav") {
            var mySound: SystemSoundID = 0
            do {
                AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
                // Play
                AudioServicesPlaySystemSound(mySound);
            }
            catch {
               print(error)
            }
        }
    }

    @IBAction func anypressed(_ sender: UIButton) {
        playSound(theTone: toneSound[sender.tag-1] )
    }    

}
ИсламНазир
источник