int coreaudio_object_open(struct audio_object *object, enum audio_object_format format, uint32_t rate, uint8_t channels) { struct coreaudio_object *self = to_coreaudio_object(object); OSStatus err = noErr; if (self->initialized) return noErr; memset(&(self->format), 0, sizeof(AudioStreamBasicDescription)); (self->format).mSampleRate = rate; (self->format).mChannelsPerFrame = channels; (self->format).mFramesPerPacket = 1; switch (format) { case AUDIO_OBJECT_FORMAT_S16LE: (self->format).mFormatID = kAudioFormatLinearPCM; (self->format).mBitsPerChannel = 16; (self->format).mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; break; default: return -1; } // guess the remaining of the AudioBasicStreamDescription structure UInt32 procSize = sizeof(AudioStreamBasicDescription); err = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &procSize, &(self->format)); if(err != noErr) { goto cleanup; } // Find default output AudioComponentDescription outputcd = {0,}; outputcd.componentType = kAudioUnitType_Output; outputcd.componentSubType = kAudioUnitSubType_DefaultOutput; outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; // Create a component AudioComponent outputComponent = AudioComponentFindNext(NULL, &outputcd); err = AudioComponentInstanceNew(outputComponent, &(self->outputUnit)); if(err != noErr) { goto cleanup; } // set render callback AURenderCallbackStruct callbackStruct; callbackStruct.inputProcRefCon = self; callbackStruct.inputProc = graphRenderProc; size_t propSize = sizeof(AURenderCallbackStruct); err = AudioUnitSetProperty(self->outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Output, 0, &callbackStruct, propSize); if(err != noErr) { goto cleanup; } // set output unit input format propSize = sizeof(AudioStreamBasicDescription); err = AudioUnitSetProperty(self->outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &(self->format), propSize); if(err != noErr) { goto cleanup; } err = AudioUnitInitialize(self->outputUnit); if(err != noErr) { goto cleanup; } // create a circular buffer to produce and consume audio TPCircularBufferInit(&(self->circularBuffer), COREAUDIO_BUFFER_SIZE); self->initialized = TRUE; return noErr; cleanup: if(self->outputUnit) { AudioUnitUninitialize(self->outputUnit); AudioComponentInstanceDispose(self->outputUnit); } return err; }
int CoreAudioDrv_PCM_Init(int * mixrate, int * numchannels, int * samplebits, void * initdata) { OSStatus result = noErr; AudioComponentDescription desc; AudioStreamBasicDescription requestedDesc; if (Initialised) { CoreAudioDrv_PCM_Shutdown(); } if (pthread_mutex_init(&mutex, 0) < 0) { ErrorCode = CAErr_Mutex; return CAErr_Error; } // Setup a AudioStreamBasicDescription with the requested format requestedDesc.mFormatID = kAudioFormatLinearPCM; requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; requestedDesc.mChannelsPerFrame = *numchannels; requestedDesc.mSampleRate = *mixrate; requestedDesc.mBitsPerChannel = *samplebits; if (*samplebits == 16) { requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; } requestedDesc.mFramesPerPacket = 1; requestedDesc.mBytesPerFrame = requestedDesc.mBitsPerChannel * requestedDesc.mChannelsPerFrame / 8; requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame * requestedDesc.mFramesPerPacket; // Locate the default output audio unit desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; comp = AudioComponentFindNext(NULL, &desc); if (comp == NULL) { ErrorCode = CAErr_FindNextComponent; pthread_mutex_destroy(&mutex); return CAErr_Error; } // Open & initialize the default output audio unit result = AudioComponentInstanceNew(comp, &output_audio_unit); if (result != noErr) { ErrorCode = CAErr_OpenAComponent; //CloseComponent(output_audio_unit); pthread_mutex_destroy(&mutex); return CAErr_Error; } result = AudioUnitInitialize(output_audio_unit); if (result != noErr) { ErrorCode = CAErr_AudioUnitInitialize; //CloseComponent(output_audio_unit); pthread_mutex_destroy(&mutex); return CAErr_Error; } // Set the input format of the audio unit. result = AudioUnitSetProperty(output_audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &requestedDesc, sizeof(requestedDesc)); if (result != noErr) { ErrorCode = CAErr_AudioUnitSetProperty; //CloseComponent(output_audio_unit); pthread_mutex_destroy(&mutex); return CAErr_Error; } // Set the audio callback setMixerCallback(); Initialised = 1; return CAErr_Ok; }
static void *coreaudio_init(const char *device, unsigned rate, unsigned latency) { (void)device; coreaudio_t *dev = (coreaudio_t*)calloc(1, sizeof(*dev)); if (!dev) return NULL; pthread_mutex_init(&dev->lock, NULL); pthread_cond_init(&dev->cond, NULL); #ifdef IOS static bool session_initialized = false; if (!session_initialized) { session_initialized = true; AudioSessionInitialize(0, 0, coreaudio_interrupt_listener, 0); AudioSessionSetActive(true); } #endif // Create AudioComponent AudioComponentDescription desc = {0}; desc.componentType = kAudioUnitType_Output; #ifdef IOS desc.componentSubType = kAudioUnitSubType_RemoteIO; #else desc.componentSubType = kAudioUnitSubType_HALOutput; #endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; AudioComponent comp = AudioComponentFindNext(NULL, &desc); if (comp == NULL) goto error; if (AudioComponentInstanceNew(comp, &dev->dev) != noErr) goto error; #ifdef OSX if (device) choose_output_device(dev, device); #endif dev->dev_alive = true; // Set audio format AudioStreamBasicDescription stream_desc = {0}; AudioStreamBasicDescription real_desc; stream_desc.mSampleRate = rate; stream_desc.mBitsPerChannel = sizeof(float) * CHAR_BIT; stream_desc.mChannelsPerFrame = 2; stream_desc.mBytesPerPacket = 2 * sizeof(float); stream_desc.mBytesPerFrame = 2 * sizeof(float); stream_desc.mFramesPerPacket = 1; stream_desc.mFormatID = kAudioFormatLinearPCM; stream_desc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | (is_little_endian() ? 0 : kAudioFormatFlagIsBigEndian); if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc)) != noErr) goto error; // Check returned audio format UInt32 i_size = sizeof(real_desc);; if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr) goto error; if (real_desc.mChannelsPerFrame != stream_desc.mChannelsPerFrame) goto error; if (real_desc.mBitsPerChannel != stream_desc.mBitsPerChannel) goto error; if (real_desc.mFormatFlags != stream_desc.mFormatFlags) goto error; if (real_desc.mFormatID != stream_desc.mFormatID) goto error; RARCH_LOG("[CoreAudio]: Using output sample rate of %.1f Hz\n", (float)real_desc.mSampleRate); g_settings.audio.out_rate = real_desc.mSampleRate; // Set channel layout (fails on iOS) #ifndef IOS AudioChannelLayout layout = {0}; layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof(layout)) != noErr) goto error; #endif // Set callbacks and finish up AURenderCallbackStruct cb = {0}; cb.inputProc = audio_write_cb; cb.inputProcRefCon = dev; if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &cb, sizeof(cb)) != noErr) goto error; if (AudioUnitInitialize(dev->dev) != noErr) goto error; size_t fifo_size; fifo_size = (latency * g_settings.audio.out_rate) / 1000; fifo_size *= 2 * sizeof(float); dev->buffer_size = fifo_size; dev->buffer = fifo_new(fifo_size); if (!dev->buffer) goto error; RARCH_LOG("[CoreAudio]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)fifo_size, latency); if (AudioOutputUnitStart(dev->dev) != noErr) goto error; return dev; error: RARCH_ERR("[CoreAudio]: Failed to initialize driver ...\n"); coreaudio_free(dev); return NULL; }
int sound_open_AudioUnit(int rate, int bits, int stereo){ Float64 sampleRate = 48000.0; if( soundInit == 1 ) { sound_close_AudioUnit(); } if(rate==44100) sampleRate = 44100.0; if(rate==32000) sampleRate = 32000.0; else if(rate==22050) sampleRate = 22050.0; else if(rate==11025) sampleRate = 11025.0; //audioBufferSize = (rate / 60) * 2 * (stereo==1 ? 2 : 1) ; OSStatus status; // Describe audio component AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentFlags = 0; desc.componentFlagsMask = 0; desc.componentManufacturer = kAudioUnitManufacturer_Apple; // Get component AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc); // Get audio units status = AudioComponentInstanceNew(inputComponent, &audioUnit); checkStatus(status); UInt32 flag = 1; // Enable IO for playback status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); checkStatus(status); AudioStreamBasicDescription audioFormat; memset (&audioFormat, 0, sizeof (audioFormat)); audioFormat.mSampleRate = sampleRate; audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioFormat.mBytesPerPacket = (stereo == 1 ? 4 : 2 ); audioFormat.mFramesPerPacket = 1; audioFormat.mBytesPerFrame = (stereo == 1? 4 : 2); audioFormat.mChannelsPerFrame = (stereo == 1 ? 2 : 1); audioFormat.mBitsPerChannel = 16; status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat)); checkStatus(status); struct AURenderCallbackStruct callbackStruct; // Set output callback callbackStruct.inputProc = playbackCallback; callbackStruct.inputProcRefCon = NULL; status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &callbackStruct, sizeof(callbackStruct)); checkStatus(status); status = AudioUnitInitialize(audioUnit); checkStatus(status); //ARRANCAR soundInit = 1; status = AudioOutputUnitStart(audioUnit); checkStatus(status); return 1; }
static int prepare_audiounit(_THIS, const char *devname, int iscapture, const AudioStreamBasicDescription * strdesc) { OSStatus result = noErr; AURenderCallbackStruct callback; #if MACOSX_COREAUDIO ComponentDescription desc; Component comp = NULL; #else AudioComponentDescription desc; AudioComponent comp = NULL; #endif const AudioUnitElement output_bus = 0; const AudioUnitElement input_bus = 1; const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : kAudioUnitScope_Input); #if MACOSX_COREAUDIO if (!find_device_by_name(this, devname, iscapture)) { SDL_SetError("Couldn't find requested CoreAudio device"); return 0; } #endif SDL_zero(desc); desc.componentType = kAudioUnitType_Output; desc.componentManufacturer = kAudioUnitManufacturer_Apple; #if MACOSX_COREAUDIO if (!iscapture) { desc.componentSubType = kAudioUnitSubType_DefaultOutput; } else { desc.componentSubType = kAudioUnitSubType_HALOutput; } comp = FindNextComponent(NULL, &desc); #else desc.componentSubType = kAudioUnitSubType_RemoteIO; comp = AudioComponentFindNext(NULL, &desc); #endif if (comp == NULL) { SDL_SetError("Couldn't find requested CoreAudio component"); return 0; } /* Open & initialize the audio unit */ #if MACOSX_COREAUDIO result = OpenAComponent(comp, &this->hidden->audioUnit); CHECK_RESULT("OpenAComponent"); #else /* AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6 We can't use OpenAComponent on iPhone because it is not present */ result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit); CHECK_RESULT("AudioComponentInstanceNew"); #endif this->hidden->audioUnitOpened = 1; #if MACOSX_COREAUDIO if (iscapture) { UInt32 enableIO = 1; result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, input_bus, &enableIO, sizeof(enableIO)); CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_EnableIO 1)"); enableIO = 0; result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, output_bus, &enableIO, sizeof(enableIO)); CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_EnableIO 0)"); result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 1, &this->hidden->deviceID, sizeof(AudioDeviceID)); CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); } else { result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &this->hidden->deviceID, sizeof(AudioDeviceID)); CHECK_RESULT ("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); } #endif /* Set the data format of the audio unit. */ result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, strdesc, sizeof(*strdesc)); CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)"); /* Set the audio callback */ SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct)); callback.inputProc = ((iscapture) ? inputCallback : outputCallback); callback.inputProcRefCon = this; if (!iscapture) { result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioUnitProperty_SetRenderCallback, scope, bus, &callback, sizeof(callback)); CHECK_RESULT ("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)"); } else { result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, bus, &callback, sizeof(callback)); CHECK_RESULT ("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); } /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(&this->spec); /* Allocate a sample buffer */ this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size; this->hidden->buffer = SDL_malloc(this->hidden->bufferSize); if (iscapture) { this->hidden->bufferOffset = 0; } result = AudioUnitInitialize(this->hidden->audioUnit); CHECK_RESULT("AudioUnitInitialize"); /* Finally, start processing of the audio unit */ result = AudioOutputUnitStart(this->hidden->audioUnit); CHECK_RESULT("AudioOutputUnitStart"); /* We're running! */ return 1; }
static int prepare_audiounit(_THIS, const char *devname, int iscapture, const AudioStreamBasicDescription * strdesc) { OSStatus result = noErr; AURenderCallbackStruct callback; AudioComponentDescription desc; AudioComponent comp = NULL; UInt32 enableIO = 0; const AudioUnitElement output_bus = 0; const AudioUnitElement input_bus = 1; const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : kAudioUnitScope_Input); SDL_memset(&desc, '\0', sizeof(AudioComponentDescription)); desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; comp = AudioComponentFindNext(NULL, &desc); if (comp == NULL) { SDL_SetError("Couldn't find requested CoreAudio component"); return 0; } /* Open & initialize the audio unit */ /* AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6 We can't use OpenAComponent on iPhone because it is not present */ result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit); CHECK_RESULT("AudioComponentInstanceNew"); this->hidden->audioUnitOpened = 1; // !!! FIXME: this is wrong? enableIO = ((iscapture) ? 1 : 0); result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, input_bus, &enableIO, sizeof(enableIO)); CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO input)"); // !!! FIXME: this is wrong? enableIO = ((iscapture) ? 0 : 1); result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, output_bus, &enableIO, sizeof(enableIO)); CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO output)"); /*result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &this->hidden->deviceID, sizeof(AudioDeviceID)); CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); */ /* Set the data format of the audio unit. */ result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioUnitProperty_StreamFormat, scope, bus, strdesc, sizeof(*strdesc)); CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)"); /* Set the audio callback */ SDL_memset(&callback, '\0', sizeof(AURenderCallbackStruct)); callback.inputProc = ((iscapture) ? inputCallback : outputCallback); callback.inputProcRefCon = this; result = AudioUnitSetProperty(this->hidden->audioUnit, kAudioUnitProperty_SetRenderCallback, scope, bus, &callback, sizeof(callback)); CHECK_RESULT ("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); /* Calculate the final parameters for this audio specification */ SDL_CalculateAudioSpec(&this->spec); /* Allocate a sample buffer */ this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size; this->hidden->buffer = SDL_malloc(this->hidden->bufferSize); result = AudioUnitInitialize(this->hidden->audioUnit); CHECK_RESULT("AudioUnitInitialize"); /* Finally, start processing of the audio unit */ result = AudioOutputUnitStart(this->hidden->audioUnit); CHECK_RESULT("AudioOutputUnitStart"); /* We're running! */ return 1; }
/* *Setup RemoteIO Audio Unit. * (TODO) provide dynamic configuration options here. */ int MUEAudioIO::setupIO() { try { // Open the output unit AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); AudioComponentInstanceNew(comp, &rioUnit); UInt32 one = 1; AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof(one)); // Setup Callbacks-------------------------------------------------- printf("setupIO: Initializing Callbacks\n"); AURenderCallbackStruct inProc; inProc.inputProc = MUEinputCallback; inProc.inputProcRefCon = this; AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, AUDIO_INPUT_BUS, &inProc, sizeof(inProc)); inProc.inputProc = MUEoutputCallback; inProc.inputProcRefCon = this; AudioUnitSetProperty(rioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, AUDIO_OUTPUT_BUS, &inProc, sizeof(inProc)); //----------------------------------------------------------------- // Enable Input and Output------------------------------------------ // Enable Output.... UInt32 flag = 1; OSStatus status = AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, AUDIO_OUTPUT_BUS, &flag, sizeof(flag)); if (status != noErr) { printf("MUEAudioIO::setupIO: Enable Output failed: status = %d\n", status); } // Enable Input.... status = AudioUnitSetProperty(rioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, AUDIO_INPUT_BUS, &flag, sizeof(flag)); if (status != noErr) { printf("MUEAudioIO::setupIO: Enable Input failed: status = %d\n", status); } //----------------------------------------------------------------- // Set up audio I/0 format, data type whatever. Describe the stream. // AudioStreamBasicDescription streamDesc; // This next function is built into Core Audio FillOutASBDForLPCM(m_streamDesc, AUDIO_SAMPLE_RATE, AUDIO_NUM_CHANNELS, AUDIO_BIT_DEPTH, AUDIO_BIT_DEPTH, false, false, AUDIO_FORMAT_IS_NONINTERLEAVED); // XThrowIfError(AudioUnitGetProperty(rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &m_streamDesc, sizeof(m_streamDesc) ), "couldn't get the remote I/O unit's output client format"); // TODO: why is scope input associated with output bus? and vice versa? AudioUnitSetProperty(rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, AUDIO_OUTPUT_BUS, &m_streamDesc, sizeof(m_streamDesc)); AudioUnitSetProperty(rioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, AUDIO_INPUT_BUS, &m_streamDesc, sizeof(m_streamDesc)); /* // Prints audio configuration settings, why wont this print? printf(" m_streamDesc initialized with AUDIO_SAMPLE_RATE : %f", AUDIO_SAMPLE_RATE); printf(" AUDIO_NUM_CHANNELS : %d", AUDIO_NUM_CHANNELS); printf(" AUDIO_BIT_DEPTH : %d", AUDIO_BIT_DEPTH); */ AudioUnitInitialize(rioUnit); } catch (...) { printf("An unknown error occurred\n"); return 1; } return 0; }
Error AudioDriverCoreAudio::init() { mutex = Mutex::create(); AudioComponentDescription desc; zeromem(&desc, sizeof(desc)); desc.componentType = kAudioUnitType_Output; #ifdef OSX_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; #endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; AudioComponent comp = AudioComponentFindNext(NULL, &desc); ERR_FAIL_COND_V(comp == NULL, FAILED); OSStatus result = AudioComponentInstanceNew(comp, &audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); #ifdef OSX_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mElement = kAudioObjectPropertyElementMaster; result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this); ERR_FAIL_COND_V(result != noErr, FAILED); #endif AudioStreamBasicDescription strdesc; zeromem(&strdesc, sizeof(strdesc)); UInt32 size = sizeof(strdesc); result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kOutputBus, &strdesc, &size); ERR_FAIL_COND_V(result != noErr, FAILED); switch (strdesc.mChannelsPerFrame) { case 2: // Stereo case 4: // Surround 3.1 case 6: // Surround 5.1 case 8: // Surround 7.1 channels = strdesc.mChannelsPerFrame; break; default: // Unknown number of channels, default to stereo channels = 2; break; } mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); zeromem(&strdesc, sizeof(strdesc)); strdesc.mFormatID = kAudioFormatLinearPCM; strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; strdesc.mChannelsPerFrame = channels; strdesc.mSampleRate = mix_rate; strdesc.mFramesPerPacket = 1; strdesc.mBitsPerChannel = 16; strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); #ifdef OSX_ENABLED result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32)); ERR_FAIL_COND_V(result != noErr, FAILED); #endif unsigned int buffer_size = buffer_frames * channels; samples_in.resize(buffer_size); input_buf.resize(buffer_size); input_buffer.resize(buffer_size * 8); input_position = 0; input_size = 0; print_verbose("CoreAudio: detected " + itos(channels) + " channels"); print_verbose("CoreAudio: audio buffer frames: " + itos(buffer_frames) + " calculated latency: " + itos(buffer_frames * 1000 / mix_rate) + "ms"); AURenderCallbackStruct callback; zeromem(&callback, sizeof(AURenderCallbackStruct)); callback.inputProc = &AudioDriverCoreAudio::output_callback; callback.inputProcRefCon = this; result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); result = AudioUnitInitialize(audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); return capture_init(); }
Error AudioDriverCoreAudio::capture_init() { AudioComponentDescription desc; zeromem(&desc, sizeof(desc)); desc.componentType = kAudioUnitType_Output; #ifdef OSX_ENABLED desc.componentSubType = kAudioUnitSubType_HALOutput; #else desc.componentSubType = kAudioUnitSubType_RemoteIO; #endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; AudioComponent comp = AudioComponentFindNext(NULL, &desc); ERR_FAIL_COND_V(comp == NULL, FAILED); OSStatus result = AudioComponentInstanceNew(comp, &input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); #ifdef OSX_ENABLED AudioObjectPropertyAddress prop; prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mElement = kAudioObjectPropertyElementMaster; result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); ERR_FAIL_COND_V(result != noErr, FAILED); #endif UInt32 flag = 1; result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); ERR_FAIL_COND_V(result != noErr, FAILED); flag = 0; result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); ERR_FAIL_COND_V(result != noErr, FAILED); UInt32 size; #ifdef OSX_ENABLED AudioDeviceID deviceId; size = sizeof(AudioDeviceID); AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId); ERR_FAIL_COND_V(result != noErr, FAILED); result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND_V(result != noErr, FAILED); #endif AudioStreamBasicDescription strdesc; zeromem(&strdesc, sizeof(strdesc)); size = sizeof(strdesc); result = AudioUnitGetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); ERR_FAIL_COND_V(result != noErr, FAILED); switch (strdesc.mChannelsPerFrame) { case 1: // Mono capture_channels = 1; break; case 2: // Stereo capture_channels = 2; break; default: // Unknown number of channels, default to stereo capture_channels = 2; break; } mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); zeromem(&strdesc, sizeof(strdesc)); strdesc.mFormatID = kAudioFormatLinearPCM; strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; strdesc.mChannelsPerFrame = capture_channels; strdesc.mSampleRate = mix_rate; strdesc.mFramesPerPacket = 1; strdesc.mBitsPerChannel = 16; strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); AURenderCallbackStruct callback; zeromem(&callback, sizeof(AURenderCallbackStruct)); callback.inputProc = &AudioDriverCoreAudio::input_callback; callback.inputProcRefCon = this; result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); result = AudioUnitInitialize(input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); return OK; }