watchOS3で追加されたAVFoundataionを使って音を鳴らす&喋らす
はじめに
今回の記事はiOS その3 Advent Calendar 2016の12/19分となります。
watchOS3でAVFoundataionフレームワークが追加されました。watchOS3ではSceneKit/SpriteKitも追加されており、(楽しいかどうかはおいておいて)AppleWatchで遊ぶゲームアプリが作りやすくなりました。
AVAudioEngineで音声ファイルを鳴らす
プロジェクトに音声ファイルを追加する
まずはファイルをプロジェクトに追加します。注意しなければいけないのは WatchKit Extension に追加するということです。WatchKit Appの方ではないので気をつけましょう。
AVAudioEngine、AVAudioPlayerNode、AVAudioFileを使って再生する
使うAVFoundataionのクラスは AVAudioEngine、AVAudioPlayerNode、AVAudioFile の3つです。
まずはコードを。
var audioEngine: AVAudioEngine! var audioPlayerNode: AVAudioPlayerNode! var audioFile: AVAudioFile! override func awake(withContext context: Any?) { super.awake(withContext: context) guard let path = Bundle.main.path(forResource: "se", ofType: "caf") else { return } audioEngine = AVAudioEngine() // (1) audioPlayerNode = AVAudioPlayerNode() // (2) let audioPath = URL(fileURLWithPath: path) audioFile = try! AVAudioFile(forReading: audioPath) // (3) audioEngine.attach(audioPlayerNode) // (4) audioEngine.connect(audioPlayerNode, to: audioEngine.mainMixerNode, format: audioFile.processingFormat) // (5) audioEngine.prepare() // (6) try! audioEngine.start() // (7) } @IBAction func hanldeButton1() { audioPlayerNode.scheduleFile(audioFile, at: nil) { () -> Void in // (8) print("complete") } audioPlayerNode.play() // (9) }
以下の手順で音声ファイルを再生します。
- AVAudioEngineのインスタンスを生成する
- AVAudioPlayerNodeのインスタンスを生成する
- Bundle内の音声ファイルを指定してAVAudioFileのインスタンスを生成する
- AVAudioEngineの
attach(_:)
メソッドでAVAudioPlayerNodeをアタッチする - AVAudioEngineの
connect(_:to:format:)
メソッドでNode同士を接続する - AVAudioEngineの
prepare()
メソッドとstart()
メソッドで処理を開始させる - AVAudioPlayerNodeの
scheduleFile(_:at:completionHandler)
メソッドで音声ファイルの再生をスケジュールする - AVAudioEngineの
start
メソッドで再生する
AudioUnitは使うことができない
なおAPI Diffsの中にAVAudioUnitの文字を見つけて「おっ!」となったのですが、どうやらまだAudioUnitを使うことはできないようです。Preset のクラスはありますが、肝心の本体のクラスがありません。(AVAudioUnitReverbPresetクラスはあるがAVAudioUnitReverbクラスが無い)
残念ながらエフェクトをかけて再生することはできないようです。ただ Preset のクラスが追加されたということは将来的に使えるようになるかもしれませんね。ハードウェアが進化したApple Watch Series3が発売されるときでしょうか?!
AppleWatchに喋らせる
AVSpeechSynthesizer
次にAppleWatchに喋らせる方法です。喋らせるにはAVSpeechSynthesizer
クラスを使います。
まずはコードを。
class InterfaceController: WKInterfaceController { var speechSynthesizer: AVSpeechSynthesizer! override func awake(withContext context: Any?) { super.awake(withContext: context) AVSpeechSynthesisVoice.speechVoices().forEach { print($0.language) } speechSynthesizer = AVSpeechSynthesizer() // (1) speechSynthesizer.delegate = self // (2) } @IBAction func handleButton2() { let speechUtterance = AVSpeechUtterance(string: "おはよう。こんにちは。こんばんは") // (3) speechUtterance.voice = AVSpeechSynthesisVoice(language: "jp-JP") // (4) speechUtterance.rate = AVSpeechUtteranceDefaultSpeechRate speechUtterance.pitchMultiplier = 1.0 // [0.5 - 2] Default = 1 speechSynthesizer.speak(speechUtterance) // (5) } } extension InterfaceController: AVSpeechSynthesizerDelegate { func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) { print("再生開始") } func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { print("再生終了") } }
以下の手順で音声ファイルを再生します。
- AVSpeechSynthesizerのインスタンスを生成する
- AVSpeechSynthesizerの
delegate
を設定する(必須ではない) - 喋らせる文章を指定してAVSpeechUtteranceのインスタンスを生成する
- AVSpeechUtteranceの
voice
プロパティにAVSpeechSynthesisVoice
(言語)を設定する - AVSpeechSynthesizerの
speak
メソッドで喋らせる(再生する)
なお上記のサンプルでは(4)と(5)の間に再生させるスピードrate
と、再生するピッチpitchMultiplier
を指定しています。これらの値を変更することで早く喋らせたり声の高さを変えることができます。
AVSpeechSynthesizerDelegateクラスのメソッドで再生開始や再生終了のタイミングで処理を行うことができます。
喋らせることができる言語
AVSpeechSynthesisVoiceクラスのspeechVoices
メソッドで一覧を取得することができます。
AVSpeechSynthesisVoice.speechVoices().forEach {
print($0.language)
}
上記のコードをwatchOS3.1.1で実行すると以下の結果を以下の言語が利用できることがわかります。今後アップデートで言語が増える可能性はあります。
ar-SA cs-CZ da-DK de-DE el-GR en-AU en-GB en-US es-ES es-MX fi-FI fr-CA fr-FR he-IL hi-IN hu-HU id-ID it-IT ja-JP ko-KR nl-NL no-NO pl-PL pt-BR pt-PT ro-RO ru-RU sk-SK sv-SE th-TH tr-TR zh-CN zh-HK zh-TW
まとめ
AVFoundataionが追加されたことで音声ファイルの再生などできることが増えました。増えましたが・・・そんなにAppleWatchで音を鳴らす機会ってあるんですかね(元も子もない)
元も子もない一環でSprikeKitで作ったFlappyBirdもよければ御覧ください。AppleWatchでFlappyBirdをして楽しいかどうか・・・Starをもらえるとこの無意味な鳥も浮かばれます。
あと、よくよく考えたらwatchOS
の記事なのでiOS Advent Calendar
でよかったのか!?