トップ «前の日記(2012-04-04) 最新 次の日記(2012-04-06)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|

2012-04-05 [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プログラミング(永野 哲久 著)
とれも参考にさせていただきました。

トップ «前の日記(2012-04-04) 最新 次の日記(2012-04-06)» 編集