Audio Unit によるリアルタイム・タイムストレッチ(2. タイムストレッチ)

今回はタイムストレッチの処理を行う実装の説明を行います。
前回の prepareAUGraph 関数を追記/修正することになります。

「2. AUNodeの作成」において、componentSubType が kAudioUnitSubType_AUiPodTimeOther の AUNode を追加することで、タイムストレッチの処理を行うことができます。

「5. Nodeの接続」は以下のようになります。
AUConverter -> AUiPodTimeOther -> Remote IO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
- (OSStatus)prepareAUGraph
{
    // 1. AUGraphの準備
    NewAUGraph(&_graph);
    AUGraphOpen(_graph);
     
    // 2. AUNodeの作成
    AudioComponentDescription cd;
     
    cd.componentType = kAudioUnitType_FormatConverter;
    cd.componentSubType = kAudioUnitSubType_AUConverter;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    AUNode converterNode;
    AUGraphAddNode(_graph, &cd, &converterNode);
    AUGraphNodeInfo(_graph, converterNode, NULL, &_converterUnit);
     
    cd.componentType = kAudioUnitType_FormatConverter;
    cd.componentSubType = kAudioUnitSubType_AUiPodTimeOther;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    AUNode aUiPodTimeNode;
    AUGraphAddNode(_graph, &cd, &aUiPodTimeNode);
    AUGraphNodeInfo(_graph, aUiPodTimeNode, NULL, &_aUiPodTimeUnit);
     
    cd.componentType = kAudioUnitType_Output;
    cd.componentSubType = kAudioUnitSubType_RemoteIO;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;
    AUNode remoteIONode;
    AUGraphAddNode(_graph, &cd, &remoteIONode);
    AUGraphNodeInfo(_graph, remoteIONode, NULL, &_remoteIOUnit);
     
    // 3. Callbackの作成
    AURenderCallbackStruct callbackStruct;
    callbackStruct.inputProc = renderCallback;
    callbackStruct.inputProcRefCon = self;
    AUGraphSetNodeInputCallback(_graph,
                                converterNode,
                                0,  // bus number
                                &callbackStruct);
     
    // 4. 各NodeをつなぐためのASBDの設定
    AudioStreamBasicDescription asbd = {0};
    UInt32 size = sizeof(asbd);
     
    // converter IO
    AudioUnitSetProperty(_converterUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input, 0,
                         &_outputFormat, size);
     
    AudioUnitSetProperty(_converterUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Output, 0,
                         &_outputFormat, size);
     
    // aUiPodTime IO
    AudioUnitSetProperty(_aUiPodTimeUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Output, 0,
                         &_outputFormat, size);
     
    AudioUnitSetProperty(_aUiPodTimeUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input, 0,
                         &_outputFormat, size);
     
    // remoteIO I
    AudioUnitSetProperty(_remoteIOUnit,
                         kAudioUnitProperty_StreamFormat,
                         kAudioUnitScope_Input, 0,
                         &_outputFormat, size);
     
    // 5. Nodeの接続
    // AUConverter -> AUiPodTimeOther
    AUGraphConnectNodeInput(_graph,
                            converterNode, 0,
                            aUiPodTimeNode, 0);
     
    // AUiPodTimeOther -> Remote IO
    AUGraphConnectNodeInput(_graph,
                            aUiPodTimeNode, 0,
                            remoteIONode, 0);
     
    // 6. AUiPodTimeOtherへ設定するためのプロキシオブジェクトを作成
    // (次回に説明するため、今回はコメント)
//  _aUiPodTimeProxy = [[AUiPodTimeProxy alloc] initWithReverbUnit:_aUiPodTimeUnit];
     
    // 7. AUGraphを初期化
    AUGraphInitialize(_graph);
     
    return ret;
}

タイムストレッチの値を変更するための処理は、上記でコメントしている箇所にて行うことになります。説明は次回に行います。

(追記:2015/03/23)
現時点での最新OS(iOS 8)で確認したところ、kAudioUnitSubType_AUiPodTimeOther についてもFloat32型での定義扱いになっているようです。(最初に本記事を書いた頃はそうではなかったのですが)
そのため、上記はそのまま使うと実行時エラーになると思います。
修正方法は、「イコライザーを追加しました(Tune Changer)」を参考にしていただければと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です