CoreAudioDriver::CoreAudioDriver( audioProcessCallback processCallback ) : H2Core::AudioOutput( __class_name ) , m_bIsRunning( false ) , mProcessCallback( processCallback ) , m_pOut_L( NULL ) , m_pOut_R( NULL ) { //INFOLOG( "INIT" ); m_nSampleRate = Preferences::get_instance()->m_nSampleRate; //Get the default playback device and store it in m_outputDevice retrieveDefaultDevice(); //Get the buffer size of the previously detected device and store it in m_nBufferSize retrieveBufferSize(); // print some info printStreamInfo(); }
/* initialize default sound device */ boolean adin_mic_standby(int sfreq, void* dummy) { OSStatus status; UInt32 propertySize; struct AudioStreamBasicDescription inDesc; int err; jlog("Stat: adin_darwin: sample rate = %d\n", sfreq); if (CoreAudioInit) return TRUE; #ifdef MAC_OS_X_VERSION_10_6 AudioComponent halout; AudioComponentDescription haloutDesc; #else Component halout; ComponentDescription haloutDesc; #endif haloutDesc.componentType = kAudioUnitType_Output; haloutDesc.componentSubType = kAudioUnitSubType_HALOutput; haloutDesc.componentManufacturer = kAudioUnitManufacturer_Apple; haloutDesc.componentFlags = 0; haloutDesc.componentFlagsMask = 0; halout = FindNextComponent(NULL, &haloutDesc); if(halout == NULL) { jlog("Error: adin_darwin: no HALOutput component found\n"); return FALSE; } OpenAComponent(halout, &InputUnit); UInt32 enableIO; enableIO = 1; status = AudioUnitSetProperty(InputUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); if (status != noErr) { jlog("Error: adin_darwin: cannot set InputUnit's EnableIO(Input)\n"); return FALSE; } enableIO = 0; status = AudioUnitSetProperty(InputUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); if (status != noErr) { jlog("Error: adin_darwin: cannot set InputUnit's EnableIO(Output)\n"); return FALSE; } /* get default input device */ propertySize = sizeof(InputDeviceID); status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &InputDeviceID); if (status != noErr) { jlog("Error: adin_darwin: cannot get default input device\n"); return FALSE; } if (InputDeviceID == kAudioDeviceUnknown) { jlog("Error: adin_darwin: no available input device found\n"); return FALSE; } else { CoreAudioHasInputDevice = TRUE; /* get input device name */ propertySize = sizeof(char) * DEVICE_NAME_LEN; status = AudioDeviceGetProperty(InputDeviceID, 1, 1, kAudioDevicePropertyDeviceName, &propertySize, deviceName); if (status != noErr) { jlog("Error: adin_darwin: cannot get device name\n"); return FALSE; } status = AudioUnitSetProperty(InputUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &InputDeviceID, sizeof(InputDeviceID)); if (status != noErr) { jlog("Error: adin_darwin: cannot bind default input device to AudioUnit\n"); return FALSE; } /* get input device's format */ propertySize = sizeof(inDesc); status = AudioDeviceGetProperty(InputDeviceID, 1, 1, kAudioDevicePropertyStreamFormat, &propertySize, &inDesc); if (status != noErr) { jlog("Error: adin_darwin: cannot get input device's stream format\n"); return FALSE; } /* get input device's buffer frame size */ UInt32 bufferFrameSize; propertySize = sizeof(bufferFrameSize); status = AudioDeviceGetProperty(InputDeviceID, 1, 1, kAudioDevicePropertyBufferFrameSize, &propertySize, &bufferFrameSize); if (status != noErr) { jlog("Error: adin_darwin: cannot get input device's buffer frame size\n"); return FALSE; } jlog("Stat: adin_darwin: using device \"%s\" for input\n", deviceName); jlog("Stat: adin_darwin: sample rate %f\n\t%ld channels\n\t%ld-bit sample\n", inDesc.mSampleRate, inDesc.mChannelsPerFrame, inDesc.mBitsPerChannel); jlog("Stat: adin_darwin: %d buffer frames\n", bufferFrameSize); printStreamInfo(&inDesc); UInt32 formatFlagEndian = inDesc.mFormatFlags & kAudioFormatFlagIsBigEndian; inDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | formatFlagEndian; inDesc.mBytesPerPacket = BytesPerSample; inDesc.mFramesPerPacket = 1; inDesc.mBytesPerFrame = BytesPerSample; inDesc.mChannelsPerFrame = 1; inDesc.mBitsPerChannel = BytesPerSample * BITS_PER_BYTE; printStreamInfo(&inDesc); propertySize = sizeof(inDesc); status = AudioUnitSetProperty(InputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &inDesc, propertySize ); if (status != noErr) { jlog("Error: adin_darwin: cannot set InputUnit's stream format\n"); return FALSE; } InputBytesPerPacket = inDesc.mBytesPerPacket; InputFramesPerPacket = inDesc.mFramesPerPacket; InputSamplesPerPacket = InputBytesPerPacket / BytesPerSample; InputDeviceBufferSamples = bufferFrameSize * InputSamplesPerPacket * InputFramesPerPacket; jlog("Stat: adin_darwin: input device's buffer size (# of samples): %d\n", InputDeviceBufferSamples); AudioStreamBasicDescription outDesc; outDesc.mSampleRate = sfreq; outDesc.mFormatID = kAudioFormatLinearPCM; outDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | formatFlagEndian; outDesc.mBytesPerPacket = BytesPerSample; outDesc.mFramesPerPacket = 1; outDesc.mBytesPerFrame = BytesPerSample; outDesc.mChannelsPerFrame = 1; outDesc.mBitsPerChannel = BytesPerSample * BITS_PER_BYTE; printStreamInfo(&outDesc); OutputBitsPerChannel = outDesc.mBitsPerChannel; OutputBytesPerPacket = outDesc.mBytesPerPacket; OutputSamplesPerPacket = (OutputBitsPerChannel / BITS_PER_BYTE) / OutputBytesPerPacket; status = AudioConverterNew(&inDesc, &outDesc, &Converter); if (status != noErr) { jlog("Error: adin_darwin: cannot create audio converter\n"); return FALSE; } /* UInt32 nChan = inDesc.mChannelsPerFrame; int i; if (inDesc.mFormatFlags & kAudioFormatFlagIsNonInterleaved && nChan > 1) { UInt32 chmap[nChan]; for (i = 0; i < nChan; i++) chmap[i] = 0; status = AudioConverterSetProperty(Converter, kAudioConverterChannelMap, sizeof(chmap), chmap); if (status != noErr){ jlog("cannot set audio converter's channel map\n"); return FALSE; } } */ status = AudioConverterSetProperty(Converter, kAudioConverterSampleRateConverterQuality, sizeof(ConvQuality), &ConvQuality); if (status != noErr) { jlog("Error: adin_darwin: cannot set audio converter quality\n"); return FALSE; } //jlog("Stat: adin_darwin: audio converter generated\n"); /* allocate buffers */ BufList = allocateAudioBufferList(inDesc.mBitsPerChannel / BITS_PER_BYTE, InputDeviceBufferSamples, 1); if (BufList == NULL) return FALSE; BufListBackup.mNumberBuffers = BufList->mNumberBuffers; BufListBackup.mBuffers[0].mNumberChannels = 1; BufListBackup.mBuffers[0].mDataByteSize = BufList->mBuffers[0].mDataByteSize; BufListBackup.mBuffers[0].mData = BufList->mBuffers[0].mData; BufListConverted = allocateAudioBufferList(BytesPerSample, BUF_SAMPLES, 1); if (BufListConverted == NULL) return FALSE; //jlog("Stat: adin_darwin: buffers allocated\n"); err = pthread_mutex_init(&MutexInput, NULL); if (err) { jlog("Error: adin_darwin: cannot init mutex\n"); return FALSE; } err = pthread_cond_init(&CondInput, NULL); if (err) { jlog("Error: adin_darwin: cannot init condition variable\n"); return FALSE; } /* register the callback */ AURenderCallbackStruct input; input.inputProc = InputProc; // an AURenderCallback input.inputProcRefCon = 0; AudioUnitSetProperty(InputUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(input)); status = AudioUnitInitialize(InputUnit); if (status != noErr) { jlog("Error: adin_darwin: InputUnit initialize failed\n"); return FALSE; } } CoreAudioInit = TRUE; jlog("Stat: adin_darwin: CoreAudio: initialized\n"); return TRUE; }