https://github.com/tkzic/audiograph
見よう見まねで作っていってシンセサイザーはできたのですが、
ファイルを読み込んで再生という所でエラーが出て再生できません。
色々調べてみたのですが、結局原因は分かりませんでした。
どうすれば上手く再生できるようになるでしょうか。
現在のコードは以下のようになっております。
//AUGraph関係
AUGraph m_AUGraph;
//AudioUnit
AudioUnit remoteIOAudioUnit;
AudioUnit multiChannelMixerAudioUnit;
AudioUnit audioFilePlayerUnit;
//Node
AUNode remoteIONode;
AUNode multiChannelMixerNode;
AUNode audioFilePlayerNode;
AudioFileID filePlayerFile;
-(id)init{
if(self = [super init]){
OSStatus err = noErr;
Float64 sampleRate = 44100.0;
UInt32 maximumFramesPerSlice = 4096;
UInt32 busCount = WAVE_NUM + 2;
//UInt32 samplerBus = WAVE_NUM;
UInt32 audioFilePlayerBus = WAVE_NUM + 1;
//AUGraphをインスタンス化
err = NewAUGraph(&m_AUGraph);
if(err){
NSLog(@"err = %ld", err);
}
err = AUGraphOpen(m_AUGraph);
if(err){
NSLog(@"err = %ld", err);
}
//RemoteIO AudioUnitのAudioComponatDescriptionを作成
AudioComponentDescription cd;
cd.componentType = kAudioUnitType_Output;
cd.componentSubType = kAudioUnitSubType_RemoteIO;
cd.componentManufacturer = kAudioUnitManufacturer_Apple;
cd.componentFlags = 0;
cd.componentFlagsMask = 0;
//AUGraphにRemoteIOのノードを追加
err = AUGraphAddNode(m_AUGraph, &cd, &remoteIONode);
if(err){
NSLog(@"AUGraphAddNode failed (remoteIONode) err = %ld", err);
}
//MultiChannelMixerのAudioComponentDescriptionを用意する
cd.componentType = kAudioUnitType_Mixer;
cd.componentSubType = kAudioUnitSubType_MultiChannelMixer;
//AUGraphにMultiChannelMixerのノードを追加
err = AUGraphAddNode(m_AUGraph, &cd, &multiChannelMixerNode);
if(err){
NSLog(@"AUGraphAddNode failed (multiChannelMixerNode) err = %ld", err);
}
//audioFilePlayerUnitのAudioComponatDescriptionを作成
cd.componentType = kAudioUnitType_Generator;
cd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
//AUGraphにaudioFilePlayerのノードを追加
err = AUGraphAddNode(m_AUGraph, &cd, &audioFilePlayerNode);
if(err){
NSLog(@"AUGraphAddNode failed (audioFilePlayerNode) err = %ld", err);
}
//それぞれのAudioUnitを取得
err = AUGraphNodeInfo(m_AUGraph, remoteIONode, NULL, &remoteIOAudioUnit);
if(err){
NSLog(@"AUGraphNodeInfo failed (remoteIONode) err = %ld", err);
}
err = AUGraphNodeInfo(m_AUGraph, multiChannelMixerNode, NULL, &multiChannelMixerAudioUnit);
if(err){
NSLog(@"AUGraphNodeInfo failed (multiChannelMixerNode) err = %ld", err);
}
err = AUGraphNodeInfo(m_AUGraph, audioFilePlayerNode, NULL, &audioFilePlayerUnit);
if(err){
NSLog(@"AUGraphNodeInfo failed (audioFilePlayerNode) err = %ld", err);
}
//RemoteIO ← MultiChannelMixer ← AudioFilePlayer
//audioFilePlayerNodeからmultiChannelMixerNodeに繫ぐ
err = AUGraphConnectNodeInput(m_AUGraph, audioFilePlayerNode, 0, multiChannelMixerNode, audioFilePlayerBus);
if(err){
NSLog(@"AUGraphConnectNodeInput failed (audioFilePlayerNode 0 to multiChannelMixerNode 9) err = %ld", err);
}
//multiChannelMixerNodeからremoteIONodeに繫ぐ
err = AUGraphConnectNodeInput(m_AUGraph, multiChannelMixerNode, 0, remoteIONode, 0);
if(err){
NSLog(@"AUGraphConnectNodeInput failed (multiChannelMixerNode 0 to remoteIONode 0) err = %ld", err);
}
//MultiChannelMixerのコールバックを設定
for(int i=0; i<WAVE_NUM; i++){
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = synthRenderCallback;//呼び出すコールバック関数の設定
callbackStruct.inputProcRefCon = &m_tWaveDef[i];//コールバック内の参照データのポインタ
//コールバック関数の設定
err = AUGraphSetNodeInputCallback(m_AUGraph,
multiChannelMixerNode,
i,
&callbackStruct);
if(err){
NSLog(@"AUGraphSetNodeInputCallback failed (multiChannelMixerNode bus %d) err = %ld", i, err);
}
}
//AudioUnit正準形
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = sampleRate;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = 41;
audioFormat.mChannelsPerFrame = channel;
audioFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
audioFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
audioFormat.mFramesPerPacket = 1;
audioFormat.mBitsPerChannel = 8 * sizeof(AudioUnitSampleType);
audioFormat.mReserved = 0;
//RemoteIO
//remoteIOAudioUnitにASBDを設定
err = AudioUnitSetProperty(remoteIOAudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audioFormat,
sizeof(audioFormat));
if(err){
NSLog(@"AudioUnitSetProperty failed (remoteIOAudioUnit kAudioUnitProperty_StreamFormat kAudioUnitScope_Input) err = %ld", err);
}
//MultiChannelMixer
//multiChannelMixerAudioUnitにASBDを設定
err = AudioUnitSetProperty(multiChannelMixerAudioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&audioFormat,
sizeof(audioFormat));
if(err){
NSLog(@"AudioUnitSetProperty failed (multiChannelMixerAudioUnit kAudioUnitProperty_StreamFormat kAudioUnitScope_Output) err = %ld", err);
}
//maximumFramesPerSliceを設定
err = AudioUnitSetProperty (multiChannelMixerAudioUnit,
kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global,
0,
&maximumFramesPerSlice,
sizeof (maximumFramesPerSlice)
);
if(err){
NSLog(@"AudioUnitSetProperty failed (multiChannelMixerAudioUnit kAudioUnitProperty_MaximumFramesPerSlice kAudioUnitScope_Global) err = %ld", err);
}
err = AudioUnitSetProperty (multiChannelMixerAudioUnit,
kAudioUnitProperty_ElementCount,
kAudioUnitScope_Input,
0,
&busCount,
sizeof (busCount));
if(err){
NSLog(@"AudioUnitSetProperty failed (multiChannelMixerAudioUnit kAudioUnitProperty_ElementCount kAudioUnitScope_Input) err = %ld", err);
}
//AudioFilePlayer
//ASBDを設定
err = AudioUnitSetProperty(audioFilePlayerUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&audioFormat,
sizeof(audioFormat));
if(err){
NSLog(@"AudioUnitSetProperty failed (audioFilePlayerUnit kAudioUnitProperty_StreamFormat kAudioUnitScope_Output) err = %ld", err);
}
//AudioFilePlayerの設定
err = [self setUPAudioFilePlayer: @"A3" :@"m4a"];
if(err){
NSLog(@"setUPAudioFilePlayer failed err = %ld", err);
}
CAShow(m_AUGraph);
//AUGraphを初期化
err = AUGraphInitialize(m_AUGraph);
if(err){
NSLog(@"AUGraphInitialize failed err = %ld", err);
}
}
return self;
}
//AudioFilePlayerの設定
-(OSStatus)setUPAudioFilePlayer :(NSString*)pathForResource :(NSString*)ofType{
OSStatus err = noErr;
NSString *filePath = [[NSBundle mainBundle] pathForResource:pathForResource ofType:ofType];
CFURLRef audioURL = ( CFURLRef) [NSURL fileURLWithPath:filePath];
//ファイルオープン
err = AudioFileOpenURL(audioURL, kAudioFileReadPermission, 0, &filePlayerFile);
if(err){
NSLog(@"AudioFileOpenURL failed err = %ld", err);
}
//audioFilePlayerUnitにオーディオファイルをぶっ込む
err = AudioUnitSetProperty(audioFilePlayerUnit,
kAudioUnitProperty_ScheduledFileIDs,
kAudioUnitScope_Global,
0,
&filePlayerFile,
sizeof(filePlayerFile));
if(err){
NSLog(@"AudioUnitSetProperty failed (audioFilePlayerUnit kAudioUnitProperty_ScheduledFileIDs kAudioUnitScope_Global) err = %ld", err);
}
UInt64 nPackets;
UInt32 propsize = sizeof(nPackets);
err = AudioFileGetProperty(filePlayerFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets);
if(err){
NSLog(@"AudioFileGetProperty failed (kAudioFilePropertyAudioDataPacketCount) err = %ld", err);
}
//ファイルのASBDを取得
AudioStreamBasicDescription fileASBD;
UInt32 fileASBDPropSize = sizeof(fileASBD);
err = AudioFileGetProperty(filePlayerFile, kAudioFilePropertyDataFormat, &fileASBDPropSize, &fileASBD);
if(err){
NSLog(@"couldn't get file's data format err = %ld", err);
}
ScheduledAudioFileRegion rgn;
memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
rgn.mTimeStamp.mSampleTime = 0;
rgn.mCompletionProc = NULL;
rgn.mCompletionProcUserData = NULL;
rgn.mAudioFile = filePlayerFile;
rgn.mLoopCount = INT_MAX;
rgn.mStartFrame = 0;
rgn.mFramesToPlay = nPackets * fileASBD.mFramesPerPacket;
//ここでエラーが発生します errの値は-10867
err = AudioUnitSetProperty(audioFilePlayerUnit, kAudioUnitProperty_ScheduledFileRegion, kAudioUnitScope_Global, 0, &rgn, sizeof(rgn));
if(err){
NSLog(@"AudioUnitSetProperty failed (audioFilePlayerUnit kAudioUnitProperty_ScheduledFileRegion kAudioUnitScope_Global) err = %ld", err);
}
UInt32 defaultVal = 0;
//ここでもエラーが発生します errの値は-10867
err = AudioUnitSetProperty(audioFilePlayerUnit, kAudioUnitProperty_ScheduledFilePrime, kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal));
if(err){
NSLog(@"AudioUnitSetProperty failed (audioFilePlayerUnit kAudioUnitProperty_ScheduledFilePrime kAudioUnitScope_Global) err = %ld", err);
}
//StartTimeを-1にすることによってループ再生になるらしい
AudioTimeStamp startTime;
memset (&startTime, 0, sizeof(startTime));
startTime.mFlags = kAudioTimeStampSampleTimeValid;
startTime.mSampleTime = rgn.mFramesToPlay;
err = AudioUnitSetProperty(audioFilePlayerUnit, kAudioUnitProperty_ScheduleStartTimeStamp, kAudioUnitScope_Global, 0, &startTime, sizeof(startTime));
if(err){
NSLog(@"AudioUnitSetProperty failed (audioFilePlayerUnit kAudioUnitProperty_ScheduleStartTimeStamp kAudioUnitScope_Global) err = %ld", err);
}
return noErr;
}