Created
January 15, 2016 00:41
-
-
Save AlexanderBollbach/3b862db17adf240928f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <AudioToolbox/AudioToolbox.h> | |
typedef struct MyAUGraphPlayer | |
{ | |
AudioStreamBasicDescription streamFormat; | |
AudioUnit inputUnit; | |
AudioBufferList *inputBuffer; | |
ExtAudioFileRef recordFile; | |
SInt64 startingByte; | |
} MyAUGraphPlayer; | |
OSStatus InputRenderProc(void *inRefCon, | |
AudioUnitRenderActionFlags *ioActionFlags, | |
const AudioTimeStamp *inTimeStamp, | |
UInt32 inBusNumber, | |
UInt32 inNumberFrames, | |
AudioBufferList * ioData); | |
#pragma mark - render proc - | |
OSStatus InputRenderProc(void *inRefCon, | |
AudioUnitRenderActionFlags *ioActionFlags, | |
const AudioTimeStamp *inTimeStamp, | |
UInt32 inBusNumber, | |
UInt32 inNumberFrames, | |
AudioBufferList * ioData) | |
{ | |
// printf ("InputRenderProc!\n"); | |
MyAUGraphPlayer *player = (MyAUGraphPlayer*) inRefCon; | |
// render into our buffer | |
OSStatus inputProcErr = noErr; | |
inputProcErr = AudioUnitRender(player->inputUnit, | |
ioActionFlags, | |
inTimeStamp, | |
inBusNumber, | |
inNumberFrames, | |
player->inputBuffer); | |
Float32 someDataL = *(Float32*)(player->inputBuffer->mBuffers[0].mData); | |
printf("L2 input: % 1.7f \n",someDataL); | |
UInt32 numOfBytes = 4096*player->streamFormat.mBytesPerFrame; | |
// ExtAudioFileWriteAsync(player->recordFile, 4096, player->inputBuffer); | |
player->startingByte += numOfBytes; | |
return inputProcErr; | |
} | |
#pragma mark - utility functions - | |
// generic error handler - if err is nonzero, prints error message and exits program. | |
static void CheckError(OSStatus error, const char *operation) | |
{ | |
if (error == noErr) return; | |
char str[20]; | |
// see if it appears to be a 4-char-code | |
*(UInt32 *)(str + 1) = CFSwapInt32HostToBig(error); | |
if (isprint(str[1]) && isprint(str[2]) && isprint(str[3]) && isprint(str[4])) { | |
str[0] = str[5] = '\''; | |
str[6] = '\0'; | |
} else | |
// no, format it as an integer | |
sprintf(str, "%d", (int)error); | |
fprintf(stderr, "Error: %s (%s)\n", operation, str); | |
exit(1); | |
} | |
void CreateInputUnit (MyAUGraphPlayer *player) { | |
// generate description that will match audio HAL | |
AudioComponentDescription inputcd = {0}; | |
inputcd.componentType = kAudioUnitType_Output; | |
inputcd.componentSubType = kAudioUnitSubType_HALOutput; | |
inputcd.componentManufacturer = kAudioUnitManufacturer_Apple; | |
AudioComponent comp = AudioComponentFindNext(NULL, &inputcd); | |
if (comp == NULL) { | |
printf ("can't get output unit"); | |
exit (-1); | |
} | |
CheckError(AudioComponentInstanceNew(comp, &player->inputUnit), "Couldn't open component for inputUnit"); | |
UInt32 disableFlag = 0, enableFlag = 1; | |
AudioUnitScope outputBus = 0, inputBus = 1; | |
CheckError(AudioUnitSetProperty(player->inputUnit, | |
kAudioOutputUnitProperty_EnableIO, | |
kAudioUnitScope_Input, | |
inputBus, | |
&enableFlag, | |
sizeof(enableFlag)), "Couldn't enable input on I/O unit"); | |
CheckError (AudioUnitSetProperty(player->inputUnit, | |
kAudioOutputUnitProperty_EnableIO, | |
kAudioUnitScope_Output, | |
outputBus, | |
&disableFlag, | |
sizeof(enableFlag)), "Couldn't disable output on I/O unit"); | |
AudioDeviceID defaultDevice = kAudioObjectUnknown; | |
UInt32 propertySize = sizeof(defaultDevice); | |
AudioObjectPropertyAddress defaultDeviceProperty; | |
defaultDeviceProperty.mSelector = kAudioHardwarePropertyDefaultInputDevice; | |
defaultDeviceProperty.mScope = kAudioObjectPropertyScopeGlobal; | |
defaultDeviceProperty.mElement = kAudioObjectPropertyElementMaster; | |
CheckError (AudioObjectGetPropertyData(kAudioObjectSystemObject, | |
&defaultDeviceProperty, | |
0, | |
NULL, | |
&propertySize, | |
&defaultDevice), "Couldn't get default input device"); | |
UInt32 bufferProp = 2048; | |
AudioObjectPropertyAddress defaultDeviceProperty2; | |
defaultDeviceProperty2.mSelector = kAudioDevicePropertyBufferFrameSize; | |
defaultDeviceProperty2.mScope = kAudioObjectPropertyScopeGlobal; | |
defaultDeviceProperty2.mElement = kAudioObjectPropertyElementMaster; | |
AudioObjectSetPropertyData(defaultDevice, | |
&defaultDeviceProperty2, | |
NULL, | |
NULL, | |
sizeof(bufferProp), | |
&bufferProp); | |
CheckError(AudioUnitSetProperty(player->inputUnit, | |
kAudioOutputUnitProperty_CurrentDevice, | |
kAudioUnitScope_Global, | |
outputBus, | |
&defaultDevice, | |
sizeof(defaultDevice)),"Couldn't set default device on I/O unit"); | |
propertySize = sizeof (AudioStreamBasicDescription); | |
CheckError(AudioUnitGetProperty(player->inputUnit, | |
kAudioUnitProperty_StreamFormat, | |
kAudioUnitScope_Output, | |
inputBus, | |
&player->streamFormat, | |
&propertySize), "Couldn't get ASBD from input unit"); | |
AudioStreamBasicDescription deviceFormat; | |
CheckError(AudioUnitGetProperty(player->inputUnit, | |
kAudioUnitProperty_StreamFormat, | |
kAudioUnitScope_Input, | |
inputBus, | |
&deviceFormat, | |
&propertySize), "Couldn't get ASBD from input unit"); | |
printf ("Device rate %f, graph rate %f\n", deviceFormat.mSampleRate, player->streamFormat.mSampleRate); | |
player->streamFormat.mSampleRate = deviceFormat.mSampleRate; | |
propertySize = sizeof (AudioStreamBasicDescription); | |
CheckError(AudioUnitSetProperty(player->inputUnit, | |
kAudioUnitProperty_StreamFormat, | |
kAudioUnitScope_Output, | |
inputBus, | |
&player->streamFormat, | |
propertySize), "Couldn't set ASBD on input unit"); | |
UInt32 bufferSizeFrames = 0; | |
propertySize = sizeof(UInt32); | |
CheckError (AudioUnitGetProperty(player->inputUnit, | |
kAudioDevicePropertyBufferFrameSize, | |
kAudioUnitScope_Global, | |
0, | |
&bufferSizeFrames, | |
&propertySize), "Couldn't get buffer frame size from input unit"); | |
UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32); | |
printf("buffer num of frames %i", bufferSizeFrames); | |
if (player->streamFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved) { | |
int offset = offsetof(AudioBufferList, mBuffers[0]); | |
int sizeOfAB = sizeof(AudioBuffer); | |
int chNum = player->streamFormat.mChannelsPerFrame; | |
int inputBufferSize = offset + sizeOfAB * chNum; | |
//malloc buffer lists | |
player->inputBuffer = (AudioBufferList *)malloc(inputBufferSize); | |
player->inputBuffer->mNumberBuffers = chNum; | |
for (UInt32 i = 0; i < chNum ; i++) { | |
player->inputBuffer->mBuffers[i].mNumberChannels = 1; | |
player->inputBuffer->mBuffers[i].mDataByteSize = bufferSizeBytes; | |
player->inputBuffer->mBuffers[i].mData = malloc(bufferSizeBytes); | |
} | |
} | |
AURenderCallbackStruct callbackStruct; | |
callbackStruct.inputProc = InputRenderProc; | |
callbackStruct.inputProcRefCon = player; | |
CheckError(AudioUnitSetProperty(player->inputUnit, | |
kAudioOutputUnitProperty_SetInputCallback, | |
kAudioUnitScope_Global, | |
0, | |
&callbackStruct, | |
sizeof(callbackStruct)), "Couldn't set input callback"); | |
CheckError(AudioUnitInitialize(player->inputUnit), "Couldn't initialize input unit"); | |
} | |
int main(void) { | |
MyAUGraphPlayer player = {0}; | |
player.startingByte = 0; | |
memset (&player, 0, sizeof (player)); | |
CreateInputUnit(&player); | |
CFURLRef myFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("./test23.wav"), kCFURLPOSIXPathStyle, false); | |
CheckError (AudioOutputUnitStart(player.inputUnit), "AudioOutputUnitStart failed"); | |
CheckError(ExtAudioFileCreateWithURL(myFileURL, kAudioFileWAVEType, &player.streamFormat, NULL, kAudioFileFlags_EraseFile, &player.recordFile),"create file"); | |
// UInt32 size = sizeof(AudioStreamBasicDescription); | |
// | |
// CheckError(ExtAudioFileSetProperty(player.recordFile, kExtAudioFileProperty_ClientDataFormat, size, &player.streamFormat), "set prop on file"); | |
// CheckError(ExtAudioFileWriteAsync(player.recordFile, 0, NULL), "audio file write bytes first"); | |
// and wait | |
printf("Capturing, press <return> to stop:\n"); | |
getchar(); | |
CheckError(AudioOutputUnitStop(player.inputUnit), "stop"); | |
ExtAudioFileDispose(player.recordFile); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment