iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
録音したデータを再生しようとしたが、上手くいかなかったので、アプリケーション内部で生成したサイン波の再生から、一歩ずつ進める事にした。
再生部を検討していて、録音部で使用したAudio Unit Processing Graph Servicesの使用方法は見直した方が良さそうだったので、再生部はAudio Unitを直接生成した。ヘッダーの内容は以下のとおり。
再生はAudioUnitを直接生成した。
@interface AudioUnitViewController : UIViewController
:
@property (nonatomic, assign) AudioUnit audioUnit;
@property (nonatomic, assign) double phase;
@property (nonatomic, assign) Float64 sampleRate;
@property (nonatomic, assign) BOOL isPlaying;
:
@end
Audio Unitの生成メソッドだ。
- (void)prepareAudioUnit
{
AudioComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_RemoteIO;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
AudioComponent component = AudioComponentFindNext(NULL, &cd);
AudioComponentInstanceNew(component, &__audioUnit);
AudioUnitInitialize(self.audioUnit);
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = MyPlayAURenderCallack;
callbackStruct.inputProcRefCon = self;
AudioUnitSetProperty(self.audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackStruct, sizeof(AURenderCallbackStruct));
self.phase = 0.0;
self.sampleRate = 44100.0;
AudioStreamBasicDescription audioFormat = [self auCanonicalASBDSampleRate:self.sampleRate channel:2];
AudioUnitSetProperty(self.audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &audioFormat, sizeof(AudioStreamBasicDescription));
}
再生のコールバック関数。サイン波を設定している。
static OSStatus MyPlayAURenderCallack (
void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData
)
{
AudioUnitViewController *viewController = (AudioUnitViewController *)inRefCon;
float freq = 440 * 2.0 * M_PI / viewController.sampleRate;
double phase = viewController.phase;
AudioUnitSampleType *outL = ioData->mBuffers[0].mData;
AudioUnitSampleType *outR = ioData->mBuffers[1].mData;
for (int i = 0; i < inNumberFrames; i++) {
float wave = sin(phase);
AudioUnitSampleType sample = wave * (1 << kAudioUnitSampleFractionBits);
*outL++ = sample;
*outR++ = sample;
phase = phase + freq;
}
viewController.phase = phase;
return noErr;
}
色々、デバッグ出力を入れている為か、スムーズでないか、鳴るようになった。