SwiftとAudioUnitで音を鳴らす

# ※こっちの記事のほうが新しいです
http://qiita.com/naokitomita/items/85160e1b354f1281309c

# はじめに
iPhoneで録音した音声ファイルをまったく同時に再生したいと思ったのですが、AVAudioPlayerではうまくいきませんでした。
どうすればいいか調べたのですが、どうやらAudioUnitを使わないと完全に同時に再生することはできないようです。
なので、まずはAudioUnitを使って音を鳴らすところからはじめることにします。

Swiftや音声処理については全くの素人なので、間違っているところやわからなかったところが多々あります。ご存知の方にツッコミを入れていただきたく思い、公開させていただきました。
よろしくお願いします。


# 音を出す
Swift初心者なもので、どうやっていいか、さっぱりわかりませんでしたが、とりあえず動くものができました。

## とりあえず動くもの
下記コードをどっかのファイルにコピーして、`SoundPlayer#Play()`とやればラの音(440Hz)の音が出るはずです。
iOSシミュレータではノイズが乗りまくりました。
実機ではうまくいくんですが・・・。

``` Swift
func RenderCallback (
    inRefCon: UnsafeMutablePointer<Void>,
    ioActionFlags: UnsafeMutablePointer<AudioUnitRenderActionFlags>,
    inTimeStamp: UnsafePointer<AudioTimeStamp>,
    inBusNumber: UInt32,
    inNumberFrames: UInt32,
    ioData: UnsafeMutablePointer<AudioBufferList>) -> (OSStatus)
{
    let tmp: UnsafeMutablePointer<SoundPlayerData> = UnsafeMutablePointer<SoundPlayerData>(inRefCon);
    let data: SoundPlayerData = tmp.memory;
    let buf: AudioBufferList = ioData.memory;
    var datas: UnsafeMutablePointer<Float> = UnsafeMutablePointer<Float>(buf.mBuffers.mData);

    let sineWaveFreq: Float = 440.0;
    let samplingRate: Float = 44100.0;
    let freq: Float = sineWaveFreq * 2.0 * Float(M_PI) / samplingRate;

    for(var i: UInt32 = 0; i < inNumberFrames; i++)
    {
        var tmpVal: Float = sin(data.time);
        memcpy(datas, &tmpVal, sizeof(Float));
        datas++;
        data.time += freq;
    }

    return noErr;
}

class SoundPlayerData
{
    var time: Float = 0.0;
}

class SoundPlayer
{
    var audioUnit: AudioUnit?;
    var acd: AudioComponentDescription?;
    var ac: AudioComponent?;
    var data: SoundPlayerData = SoundPlayerData();
    var isPlaying: Bool = false;

    func play()
    {   
        // AudioUnitの準備
        audioUnit = AudioUnit();

        // AudioComponentDescriptionの準備
        acd = AudioComponentDescription();
        acd?.componentType = kAudioUnitType_Output;
        acd?.componentSubType = kAudioUnitSubType_RemoteIO;
        acd?.componentManufacturer = kAudioUnitManufacturer_Apple;
        acd?.componentFlags = 0;
        acd?.componentFlagsMask = 0;
        
        // AudioComponentの生成
        ac = AudioComponentFindNext(nil, &acd!);

        // AudioUnitとAudioComponentとの関連づけ
        AudioComponentInstanceNew(ac!, &audioUnit!);
        
        // 音声処理のコールバックメソッドを準備
        // メソッドとメソッドに渡すデータを用意しておきます。
        var input = AURenderCallbackStruct(inputProc: RenderCallback, inputProcRefCon: &data);
        
        // AudioUnitとコールバックメソッドの関連づけ
        AudioUnitSetProperty(audioUnit!, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, UInt32(sizeofValue(input)));
        
        // AudioUnitの初期化
        AudioUnitInitialize(audioUnit!);

        // 音声再生実行開始
        AudioOutputUnitStart(audioUnit!);
        isPlaying = true;
    }
    
    func stop()
    {
        if(audioUnit == nil || isPlaying == false)
        {
            return;
        }
        
        AudioOutputUnitStop(audioUnit!);
        audioUnit = nil;
    }
}
```
## ソースコードの解説
音がどうやって出ているかについては参考の第三回あたりを読むと良いでしょう。
音は空気の振動であり、44.1kHzでサンプリングされた音は、1秒間に44100回の振動データを保存しているということになります。
逆に再生する時には44100回、スピーカーに波の信号を送っているということになります。

### `play()`メソッド
`play()`メソッドが音を鳴らすための準備と再生開始のメソッドとなっています。
流れとしては、次のようになります。

1. AudioUnitを生成
2. AudioComponentDescriptionを生成
3. AudioComponentDescriptionからAudioComponentを生成
4. AudioComponentとAudioUnitを関連づける
5. 音を鳴らすための計算を行うコールバック関数を設定する
    * コールバック関数が呼ばれた時に渡されるデータに`self`をセットすることはできませんでした。Mutableなポインタにできないとか言われた気がしますが、なんででしょうか。
6. AudioUnitの初期化
7. 再生開始(コールバックメソッドが呼び出されるようになります。)

### `RenderCallback()`関数
`play()`を実行すると、`RenderCallback()`メソッドが1秒間に86回(だったかな)呼び出されるようになります。
第一引数の`inRefCon`は`play()`メソッド内で設定したコールバック関数に渡されるデータのポインタが入っています。
第五引数の`inNumberFrames`は第六引数であるバッファの箱の数が入っています。バッファは,1/86秒分の音声を保持することができます。
第六引数の`ioData`は音声出力用バッファです。ここに-1.0 ~ 1.0までのデータを連続で入力してあげることで、1/86秒分の音声を出力することができます。

関数の先頭で、引数に渡された`UnsafeMutablePointer`の値をSwiftで扱えるようにキャストしたりしています。やり方がさっぱりわからなかったため、強引にやっています。正しいやり方を教えてください・・・。

次に、440Hzの音声を出力するために必要な定数を計算しています。ここでいちいち計算する必要はないので、無駄な処理ですね。

最後にループ内で、`inNumberFrames`個分のSin波を計算してバッファに詰めています。

#### がんばったところ
* ポインタのキャスト
    * Swiftで扱えるような形にポインタをキャストするのに苦労しました。正しいやり方とは思えませんが・・・。
* 出力用のバッファに値を書き込むところ
    * バッファに値がどうしてもうまく書き込めなかったので、memcpyを使っています。たぶん、もっとスマートな方法があると思います。教えてください。

#### わからないところ
本来であれば、`AudioBufferList`は次のような構造体だそうです。

```c
struct AudioBufferList
{
    UInt32      mNumberBuffers;
    AudioBuffer mBuffers[kVariableLengthArray];
};
typedef struct AudioBufferList  AudioBufferList;

struct AudioBuffer
{
    UInt32  mNumberChannels;
    UInt32  mDataByteSize;
    void*    mData;
};
typedef struct AudioBuffer  AudioBuffer;
```

しかし、Swiftでは次のように定義されていました。

```swift
public struct AudioBufferList {
    public var mNumberBuffers: UInt32
    public var mBuffers: (AudioBuffer) // this is a variable length array of mNumberBuffers elements
    public init()
    public init(mNumberBuffers: UInt32, mBuffers: (AudioBuffer))
}

public struct AudioBuffer {
    public var mNumberChannels: UInt32
    public var mDataByteSize: UInt32
    public var mData: UnsafeMutablePointer<Void>
    public init()
    public init(mNumberChannels: UInt32, mDataByteSize: UInt32, mData: UnsafeMutablePointer<Void>)
}
```

`AudioBufferList#mBuffers`は配列であり、ステレオ出力の場合には`mNumberBuffers`が2となります。Obj-Cのサンプルでは

```
AudioBufferList#mBuffers[0]
AudioBufferList#mBuffers[1]
```

というふうにアクセスして左右の音声を出力していたのですが、Swiftは配列ではないように見えます。

```swift
public var mBuffers: (AudioBuffer) // []で括ってないから配列ではないのでは？
```

コメントには、
> this is a variable length array of mNumberBuffers elements
> これは`mNumberBuffers`個の可変長の変数です。

とあるので、配列なんだと思うのですが、アクセス方法がわかりませんでした。
どなたか、詳しい方、教えてください。


# 参考
[Getting Started With AudioUnit / My Codex Leicester](http://nagano.monalisa-au.org/連載-getting-started-with-audio-unit)