Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //this class takes care of setting up an AudioUnit environment and makes use of RemoteIO and a multiChannelMixer to output 16 bit signed integer 2 channel PCM
- //written by Christian Blomert - use freely for whatever ;)
- ------------
- AudioIO.h
- ------------
- #import <Foundation/Foundation.h>
- #include <AudioToolbox/AudioToolbox.h>
- @interface AudioIO : NSObject
- {
- AUGraph graph;
- AudioUnit masterMixer;
- AudioUnit output;
- }
- @property (nonatomic) AUGraph graph;
- @property (nonatomic) AudioUnit masterMixer;
- @property (nonatomic) AudioUnit output;
- @end
- ------------
- AudioIO.m
- ------------
- #import "AudioIO.h"
- @implementation AudioIO
- @synthesize output;
- @synthesize graph;
- @synthesize masterMixer;
- static OSStatus sampleCallback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData)
- {
- //get a pointer to self
- AudioIO *audio = (AudioIO *)inRefCon;
- //one buffer for SInt32s - 2 if using floats (one for each channel)
- for (int i = 0 ; i < ioData->mNumberBuffers; i++)
- {
- //get the bufferStruct
- AudioBuffer buffer = ioData->mBuffers[i];
- //get the bufferpointer
- UInt32 *frameBuffer = buffer.mData;
- //fill the frames
- for (int j = 0; j < inNumberFrames; j++){
- // getPacket returns a 32 bit value, one frame. - 16bit for each channel
- frameBuffer[j] = [audio getPacket];
- }
- }
- return noErr;
- }
- static OSStatus outputCallback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber,
- UInt32 inNumberFrames,
- AudioBufferList *ioData)
- {
- //get self
- AudioIO *audio = (AudioIO *)inRefCon;
- OSStatus err = 0;
- //render audio using masterMixer unit
- err = AudioUnitRender(audio.masterMixer, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
- if (err != noErr) {
- NSLog(@"erroutputCallback: %ld", err);
- }
- return err;
- }
- void propListener( void * inClientData,
- AudioSessionPropertyID inID,
- UInt32 inDataSize,
- const void * inData)
- {
- printf("property listener\n");
- if (inID == kAudioSessionProperty_AudioRouteChange){
- }
- }
- void rioInterruptionListener(void *inClientData, UInt32 inInterruption)
- {
- printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption");
- if (inInterruption == kAudioSessionEndInterruption) {
- // make sure we are again the active session
- AudioSessionSetActive(true);
- NSLog(@"end of interruption");
- //AudioOutputUnitStart(THIS->audioUnit);
- }
- if (inInterruption == kAudioSessionBeginInterruption) {
- NSLog(@"begin of interruption");
- //AudioOutputUnitStop(THIS->audioUnit);
- }
- }
- //init ------------------------------------------------------------------------ //
- -(id)init {
- self = [super init];
- if (self) {
- [self initAudio];
- }
- return self;
- }
- -(void)initAudio{
- // Initialize and configure the audio session, and add an interuption listener
- AudioSessionInitialize(NULL, NULL, rioInterruptionListener, self);
- //set the audio category
- UInt32 audioCategory = kAudioSessionCategory_LiveAudio;
- AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
- UInt32 getAudioCategory = sizeof(audioCategory);
- AudioSessionGetProperty(kAudioSessionProperty_AudioCategory, &getAudioCategory, &getAudioCategory);
- if(getAudioCategory == kAudioSessionCategory_LiveAudio){
- NSLog(@"kAudioSessionCategory_LiveAudio");
- }
- else{
- NSLog(@"Could not get kAudioSessionCategory_LiveAudio");
- }
- //add a property lisistener
- AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self);
- //set the buffer size as small as w can
- Float32 preferredBufferSize = 128.0/44100.0;
- AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
- UInt32 size = sizeof(preferredBufferSize);
- AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &size,
- &preferredBufferSize);
- NSLog(@"Buffersize: %f", preferredBufferSize*44100);
- //set the audio session active
- AudioSessionSetActive(YES);
- //the descriptions for the components
- AudioComponentDescription masterDescription, outputDescription;
- //the AUNodes
- AUNode masterMixerNode;
- AUNode outputNode;
- //the graph
- OSErr err = noErr;
- err = NewAUGraph(&graph);
- if (err !=noErr) {
- NSLog(@"Error creating graph: %d", err);
- }
- //the output
- outputDescription.componentFlags = 0;
- outputDescription.componentFlagsMask = 0;
- outputDescription.componentType = kAudioUnitType_Output;
- outputDescription.componentSubType = kAudioUnitSubType_RemoteIO;
- outputDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
- err = AUGraphAddNode(graph, &outputDescription, &outputNode);
- if (err !=noErr) {
- NSLog(@"Error creating output node: %d", err);
- }
- //the master mixer
- masterDescription = 0;
- masterDescription = 0;
- masterDescription = kAudioUnitType_Mixer;
- masterDescription = kAudioUnitSubType_MultiChannelMixer;
- masterDescription = kAudioUnitManufacturer_Apple;
- err = AUGraphAddNode(graph, & masterDescription, &masterMixerNode);
- if (err !=noErr) {
- NSLog(@"Error creating mixer node: %d", err);
- }
- err = AUGraphOpen(graph);
- if (err !=noErr) {
- NSLog(@"Error opening graph: %d", err);
- }
- //get the master mixer info
- err = AUGraphNodeInfo(graph, masterMixerNode, &masterDescription, &masterMixer);
- if (err !=noErr) {
- NSLog(@"masterMixer doesnt work!!!");
- }
- t
- err = AUGraphNodeInfo(graph, outputNode, &outputDescription, &output);
- if (err !=noErr) {
- NSLog(@"AHA!!!");
- }
- // set up the rio unit for playback
- UInt32 oneFlag = 1;
- err =
- AudioUnitSetProperty (output,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Output,
- 0,
- &oneFlag,
- sizeof(oneFlag));
- if (err != noErr) {
- NSLog(@"Couldn't enable RIO output : %d", err);
- }
- // enable rio input
- err = AudioUnitSetProperty(output,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Input,
- 1,
- &oneFlag,
- sizeof(oneFlag));
- if (err != noErr) {
- NSLog(@"couldn't enable rio input : %d", err);
- }
- // Set up the mixers input callbacks
- AURenderCallbackStruct sampleCallbackStruct;
- sampleCallbackStruct = sampleCallback;
- sampleCallbackStruct = self;
- AURenderCallbackStruct masterCallbackStruct;
- masterCallbackStruct.inputProc = outputCallback;
- masterCallbackStruct.inputProcRefCon = self;
- //connect nodes to callbacks
- //connect outputNode to masterCallbackStruct
- err = AUGraphSetNodeInputCallback(graph, outputNode, 0, &masterCallbackStruct);
- if (err != noErr) {
- NSLog(@"Couldn't connect outputNode output 0 to rio masterCallbackStruct 0 : %d", err);
- }
- //connect mixer input 1 to callbackStruct
- err = AUGraphSetNodeInputCallback(graph, masterMixerNode, 0, & sampleCallbackStruct);
- if (err != noErr) {
- NSLog(@"Error setting masterMixerNode input sampleCallbackStruct A : %d", err);
- }
- // Describe format
- //SInts
- AudioStreamBasicDescription audioFormat = {0};
- audioFormat.mSampleRate = 44100.00;
- audioFormat.mFormatID = kAudioFormatLinearPCM;
- audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
- audioFormat.mFramesPerPacket = 1;
- audioFormat.mChannelsPerFrame = 2;
- audioFormat.mBitsPerChannel = 16;
- audioFormat.mBytesPerPacket = 4;
- audioFormat.mBytesPerFrame = 4;
- /*
- //Floats:
- audioFormat.mSampleRate = 44100.00;
- audioFormat.mFormatID = kAudioFormatLinearPCM;
- audioFormat.mFormatFlags = kAudioFormatFlagIsNonInterleaved | kAudioFormatFlagIsFloat;
- audioFormat.mFramesPerPacket = 1;
- audioFormat.mChannelsPerFrame = 2;
- audioFormat.mBitsPerChannel = 32;
- audioFormat.mBytesPerPacket = 4;
- audioFormat.mBytesPerFrame = 4;
- */
- //set the rio input properties
- err = AudioUnitSetProperty(output,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0,
- &audioFormat,
- sizeof(audioFormat));
- if (err != noErr) {
- NSLog(@"Error setting RIO input property : %d", err);
- }
- //set the rio output properties
- err = AudioUnitSetProperty(output,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 1,
- &audioFormat,
- sizeof(audioFormat));
- if (err != noErr) {
- NSLog(@"Error setting RIO output property : %d", err);
- }
- //set the master fader output properties
- err = AudioUnitSetProperty(masterMixer,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output,
- 0,
- &audioFormat,
- sizeof(audioFormat));
- if (err != noErr) {
- NSLog(@"Error setting master output property : %d", err);
- }
- //set the master fader input properties
- err = AudioUnitSetProperty(masterMixer,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input,
- 0,
- &audioFormat,
- sizeof(audioFormat));
- if (err != noErr) {
- NSLog(@"Error setting master input1 property : %d", err);
- }
- //initialize Graph
- err = AUGraphInitialize(graph);
- if (err != noErr) {
- NSLog(@"Error initializing graph - error code: %d", err);
- }
- CAShow(graph);
- err = AUGraphStart(graph);
- if (err != noErr) {
- NSLog(@"Error starting graph. - error code: %d", err);
- }
- }
- @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement