麦芽を支える技術

麦芽(ばくが、英語:malt)とは、麦、特に大麦の種子を発芽させたもので、ビール、ウイスキー、水飴の原料となる。(Wikipediaより)

AVAudioEngineで音声にかけられるエフェクトをいろいろ試せるテスターアプリを作った

iOS8からAVAudioEngineを使って、音声に簡単にAudioUnitのエフェクトをかけられるようになりましたが、それらのエフェクトかけると実際にどんな音になるのかちょっと調べる必要があったので、とりあえずその調査の副産物置いときます。(結局調べたいことはわからんかったという...)

ちなみに既に似たようなサンプルは、以下のようにiOS開発者で有名な堤さんが公開してくれている「iOS8-Sampler」とかあるんですが、今回調べたかったのは主にAVAudioUnitTimePitchとかAVAudioUnitVarispeedで、その辺はこれには入って無いようだったので、とりあえず自前で作ってみた、って感じです。

d.hatena.ne.jp

あくまで自分の調査用だったので、レイアウトとか適当です。。。あしからず。

成果物

これ。

github.com

使い方

まず画面は以下の感じ。

  • Play / Pause
    • 全タブ共通で1つの音声(なんかGoogleにあった著作権フリー素材)の再生/一時停止
  • Reset Default Valuse
    • 現在表示中のタブ内の値を初期設定に戻す
  • 各画面のスライダー
    • (お察しの通り)そのプロパティ値をお好みの値に変更

一応各スライダーのMin値/Max値/デフォルト値は、Apple公式リファレンスに記載のものを(だいたい)設定しています。ただ、DelayやDistortionは一旦デフォルトでは無効にしたかったので、wetDryMix初期値は0にしています。

ちなみにReverbとか一部存在しないエフェクトありますが、これはUISliderで設定する類の設定方法ではなかったためです。(あくまで副産物なので、ある程度コピペレベルでつけれる機能までしか手を付けていないという…)

ソースコード解説

ソースコード解説するほどでもないので詳細はGitHub見てもらえればいいですが、端的に言うと以下のように1つのAVAudioEngineにエフェクターをガッツリと繋いで、そのプロパティ値を各ViewControllerからUISliderで設定できるようにしただけのものです。

audioEngine = AVAudioEngine()

// Prepare AVAudioFile
let url = NSURL(string: NSBundle.mainBundle().pathForResource("sample", ofType: "mp3")!)
audioFile = try AVAudioFile(forReading: url!)

// Prepare AVAudioPlayerNode
audioPlayerNode = AVAudioPlayerNode()
audioEngine.attachNode(audioPlayerNode)

// Prepare AVAudioUnitTimePitch
audioUnitTimePitch = AVAudioUnitTimePitch()
audioEngine.attachNode(audioUnitTimePitch)

// Prepare AVAudioUnitVarispeed
audioUnitVarispeed = AVAudioUnitVarispeed()
audioEngine.attachNode(audioUnitVarispeed)

// Prepare AVAudioUnitDelay
audioUnitDelay = AVAudioUnitDelay()
audioEngine.attachNode(audioUnitDelay)
audioUnitDelay.wetDryMix = 0

// Prepare AVAudioUnitDistortion
audioUnitDistortion = AVAudioUnitDistortion()
audioEngine.attachNode(audioUnitDistortion)
audioUnitDistortion.wetDryMix = 0

// Connect Nodes
audioEngine.connect(audioPlayerNode, to: audioUnitTimePitch, format: audioFile.processingFormat)
audioEngine.connect(audioUnitTimePitch, to: audioUnitVarispeed, format: audioFile.processingFormat)
audioEngine.connect(audioUnitVarispeed, to: audioUnitDelay, format: audioFile.processingFormat)
audioEngine.connect(audioUnitDelay, to: audioUnitDistortion, format: audioFile.processingFormat)
audioEngine.connect(audioUnitDistortion, to: audioEngine.mainMixerNode, format: audioFile.processingFormat)

// Start Engine
try audioEngine.start()

まとめ

うまく調整すると、男の声を女の声みたいにするとかボイスチェンジャー的なことも出来そうですね〜