[iOS]Looping Recorderの基礎(Audio Unit (7)) | Cocoa練習帳

[iOS]Looping Recorderの基礎(Audio Unit (7))

一応、録音した音が再生できた。だが、かなり荒いコードだ。そもそも、iPhoneシミュレータでAudio Unitを使用する場合、今のXcodeのバージョンだと問題があるようで、エラーメッセージが表示されていて、意図した動きをしない。自分のバグの可能性もあるが。実機で動作できたが、モノラル/ステレオの扱い等がいい加減なコードだ。でも、第一歩としては、今回はこれでヨシとしよう。




録音したデータをバッファに保存するコードだ。




- (void)write:(UInt32)inNumberFrames data:(AudioBufferList *)ioData
{
    uint32_t    available = self.maxSampleCount - self.startingSampleCount;
    if (available < inNumberFrames) {
        inNumberFrames = available;
    }
    memcpy(self.buffer + self.startingSampleCount, ioData->mBuffers[0].mData, sizeof(AudioUnitSampleType) * inNumberFrames);
    self.startingSampleCount = self.startingSampleCount + inNumberFrames;
    if (self.maxSampleCount <= self.startingSampleCount) {
        [self stop:nil];
    }
}

static OSStatus MyAURenderCallack(void *inRefCon,
                                  AudioUnitRenderActionFlags *ioActionFlags,
                                  const AudioTimeStamp *inTimeStamp,
                                  UInt32 inBusNumber,
                                  UInt32 inNumberFrames,
                                  AudioBufferList *ioData)
{
    AudioUnitViewController *viewController = (AudioUnitViewController *)inRefCon;
    [viewController write:inNumberFrames data:ioData];
    return noErr;
}



ループ再生するコードだ。




- (void)read:(UInt32)inNumberFrames data:(AudioBufferList *)ioData
{
    uint32_t    available = self.maxSampleCount - self.startingSampleCount;
    uint32_t    num = inNumberFrames;
    if (available < num) {
        num = available;
    }
    memcpy(ioData->mBuffers[0].mData, self.buffer + self.startingSampleCount, sizeof(AudioUnitSampleType) * num);
    self.startingSampleCount = self.startingSampleCount + num;
    if (self.maxSampleCount <= self.startingSampleCount)
        self.startingSampleCount = 0;
    if (num < inNumberFrames) {
        num = inNumberFrames - num;
        memcpy(ioData->mBuffers[0].mData, self.buffer + self.startingSampleCount, sizeof(AudioUnitSampleType) * num);
        self.startingSampleCount = self.startingSampleCount + num;
    }
    memcpy(ioData->mBuffers[1].mData, ioData->mBuffers[0].mData, sizeof(AudioUnitSampleType) * inNumberFrames);
}

static OSStatus MyPlayAURenderCallack (
                                       void                        *inRefCon,
                                       AudioUnitRenderActionFlags  *ioActionFlags,
                                       const AudioTimeStamp        *inTimeStamp,
                                       UInt32                      inBusNumber,
                                       UInt32                      inNumberFrames,
                                       AudioBufferList             *ioData
                                       )
{
    AudioUnitViewController *viewController = (AudioUnitViewController *)inRefCon;
    [viewController read:inNumberFrames data:ioData];
    return noErr;
}



例えば、鍵盤楽器のようなアプリケーションを作る場合は、Audio Unitのレスポンスの早さは魅力的だと思う。そうでなければ、ちょっと、面倒かな。




ソースコード

GitHubからどうぞ。

https://github.com/murakami/DemoAudio - GitHub




関連情報

Cocoa Life KOF2011特別編 - Facebook

Cocoa勉強会 関西の会誌。

iPhone Core Audioプログラミング(永野 哲久 著)

とれも参考にさせていただきました。