, CoreAudio:
#include <CoreFoundation/CoreFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef struct MyAUGraphPlayer
{
AudioStreamBasicDescription streamFormat;
AUGraph graph;
AUNode output;
AUNode mixer;
AUNode sine;
AudioUnit audioUnits[3];
AudioBufferList *inputBuffer;
Float64 firstInputSampleTime;
Float64 firstOutputSampleTime;
Float64 inToOutSampleTimeOffset;
} MyAUGraphPlayer;
OSStatus SineWaveRenderCallback(void * inRefCon,
AudioUnitRenderActionFlags * ioActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
double currentPhase = *((double *)inRefCon);
Float32 * outputBuffer = (Float32 *)ioData->mBuffers[0].mData;
const double frequency = 880.0;
const double phaseStep = (frequency / 44100.) * (M_PI * 2.);
for(int i = 0; i < inNumberFrames; i++) {
outputBuffer[i] = sin(currentPhase);
currentPhase += phaseStep;
}
for(int i = 1; i < ioData->mNumberBuffers; i++) {
memcpy(ioData->mBuffers[i].mData, outputBuffer, ioData->mBuffers[i].mDataByteSize);
}
*((double *)inRefCon) = currentPhase;
return noErr;
}
int main(int argc, const char * argv[])
{
MyAUGraphPlayer *player = {0};
MyAUGraphPlayer p = {0};
player=&p;
NewAUGraph(&player->graph);
OSStatus result = 0;
AudioStreamBasicDescription ASBD = {
.mSampleRate = 44100,
.mFormatID = kAudioFormatLinearPCM,
.mFormatFlags = kAudioFormatFlagsNativeFloatPacked,
.mChannelsPerFrame = 2,
.mFramesPerPacket = 1,
.mBitsPerChannel = sizeof(Float32) * 8,
.mBytesPerPacket = sizeof(Float32),
.mBytesPerFrame = sizeof(Float32)
};
{
AudioComponentDescription description = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_DefaultOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple
};
result = AUGraphAddNode(player->graph, &description, &player->output);
printf("err: %d\n", result);
AudioComponent comp = AudioComponentFindNext(NULL, &description);
result = AudioComponentInstanceNew(comp, &player->audioUnits[0]);
printf("err: %d\n", result);
result = AudioUnitInitialize(player->audioUnits[0]);
printf("err: %d\n", result);
}
{
AudioComponentDescription description = {
.componentType = kAudioUnitType_Mixer,
.componentSubType = kAudioUnitSubType_StereoMixer,
.componentManufacturer = kAudioUnitManufacturer_Apple
};
result = AUGraphAddNode(player->graph, &description, &player->mixer);
printf("err: %d\n", result);
AudioComponent comp = AudioComponentFindNext(NULL, &description);
result = AudioComponentInstanceNew(comp, &player->audioUnits[1]);
printf("err: %d\n", result);
}
{
AudioComponentDescription description = {
.componentType = kAudioUnitType_Generator,
.componentSubType = kAudioUnitSubType_ScheduledSoundPlayer,
.componentManufacturer = kAudioUnitManufacturer_Apple
};
result = AUGraphAddNode(player->graph, &description, &player->sine);
printf("err: %d\n", result);
AudioComponent comp = AudioComponentFindNext(NULL, &description);
result = AudioComponentInstanceNew(comp, &player->audioUnits[2]);
printf("err: %d\n", result);
result = AudioUnitInitialize(player->audioUnits[2]);
printf("err: %d\n", result);
}
result = AUGraphConnectNodeInput(player->graph,
player->sine,
0,
player->mixer,
0);
printf("err: %d\n", result);
result = AUGraphConnectNodeInput(player->graph,
player->mixer,
0,
player->output,
0);
printf("err: %d\n", result);
result = AUGraphOpen(player->graph);
printf("err: %d\n", result);
UInt32 numbuses = 1;
result = AudioUnitSetProperty(player->audioUnits[1], kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, sizeof(numbuses));
printf("err: %d\n", result);
for (UInt32 i = 0; i <= numbuses; ++i) {
AURenderCallbackStruct rcbs;
rcbs.inputProc = &SineWaveRenderCallback;
rcbs.inputProcRefCon = &player;
printf("set AUGraphSetNodeInputCallback\n");
result = AUGraphSetNodeInputCallback(player->graph, player->mixer, i, &rcbs);
printf("AUGraphSetNodeInputCallback err: %d\n", result);
printf("set input bus %d, client kAudioUnitProperty_StreamFormat\n", (unsigned int)i);
result = AudioUnitSetProperty(player->audioUnits[1], kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, &ASBD, sizeof(ASBD));
printf("err: %d\n", result);
}
result = AudioUnitSetProperty(player->audioUnits[1], kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &ASBD, sizeof(ASBD));
printf("err: %d\n", result);
OSStatus status = AUGraphInitialize(player->graph);
printf("err: %d\n", status);
player->firstOutputSampleTime = -1;
AudioOutputUnitStart(player->audioUnits[0]);
AUGraphStart(player->graph);
printf("enter key to stop\n");
getchar();
return 0;
}