40 AudioUnitRenderActionFlags *ioActionFlags,
41 const AudioTimeStamp *inTimeStamp,
43 UInt32 inNumberFrames,
44 AudioBufferList *ioData
48 assert( ioData->mNumberBuffers > 0 && ioData->mNumberBuffers <= 2 );
49 pDriver->
m_pOut_L =
static_cast< float *
>( ioData->mBuffers[ 0 ].mData );
50 pDriver->
m_pOut_R =
static_cast< float *
>( ioData->mBuffers[ 1 ].mData );
67 AudioObjectPropertyAddress propertyAddress = {
68 kAudioDevicePropertyLatency,
69 kAudioDevicePropertyScopeInput,
72 UInt32 nDeviceLatency;
73 nSize =
sizeof( nDeviceLatency );
74 err = AudioObjectGetPropertyData(
m_outputDevice, &propertyAddress, 0, NULL, &nSize, &nDeviceLatency );
76 ERRORLOG(
"Couldn't get device latency" );
81 AudioStreamID streamID;
82 nSize =
sizeof( streamID );
84 kAudioDevicePropertyStreams,
85 kAudioDevicePropertyScopeOutput,
88 err = AudioObjectGetPropertyData(
m_outputDevice, &propertyAddress, 0, NULL, &nSize, &streamID );
90 ERRORLOG(
"Couldn't get stream for output device" );
93 UInt32 nStreamLatency;
94 nSize =
sizeof(nStreamLatency);
96 kAudioStreamPropertyLatency,
97 kAudioObjectPropertyScopeOutput,
100 err = AudioObjectGetPropertyData( streamID, &propertyAddress, 0, NULL, &nSize, &nStreamLatency );
101 if ( err != noErr ) {
102 ERRORLOG( QString(
"Couldn't get stream latency") );
111 CFStringRef deviceNameRef;
112 UInt32 size =
sizeof( deviceNameRef );
113 AudioObjectPropertyAddress propertyAddress = {
114 kAudioDevicePropertyDeviceNameCFString,
115 kAudioDevicePropertyScopeOutput,
118 err = AudioObjectGetPropertyData( deviceID, &propertyAddress, 0, NULL, &size, &deviceNameRef );
119 if ( err != noErr ) {
120 ERRORLOG( QString(
"Couldn't get name for device %1" ).arg( deviceID ) );
123 UInt32 nBufferSize = CFStringGetMaximumSizeForEncoding( CFStringGetLength( deviceNameRef ), kCFStringEncodingUTF8 );
124 char buffer[ nBufferSize + 1 ];
125 CFStringGetCString( deviceNameRef, buffer, nBufferSize + 1, kCFStringEncodingUTF8 );
126 CFRelease( deviceNameRef );
128 return QString( buffer );
141 AudioObjectPropertyAddress propertyAddress = {
142 kAudioHardwarePropertyDevices,
143 kAudioObjectPropertyScopeGlobal,
144 kAudioObjectPropertyElementMaster
147 err = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject,
148 &propertyAddress, 0, NULL, &dataSize );
149 if ( err != noErr ) {
150 ERRORLOG(
"Couldn't get size for devices list" );
154 int nDevices = dataSize /
sizeof( AudioDeviceID );
155 AudioDeviceID deviceIDs[ nDevices ];
157 err = AudioObjectGetPropertyData( kAudioObjectSystemObject,
158 &propertyAddress, 0, NULL, &dataSize, deviceIDs );
159 if ( err != noErr ) {
160 ERRORLOG(
"Couldn't read device IDs" );
166 for (
int i = 0; i < nDevices; i++ ) {
167 UInt32 nBufferListSize = 0;
168 AudioObjectPropertyAddress propertyAddress = {
169 kAudioDevicePropertyStreamConfiguration,
170 kAudioDevicePropertyScopeOutput,
173 err = AudioObjectGetPropertyDataSize( deviceIDs[ i ], &propertyAddress, 0, NULL, &nBufferListSize );
174 if ( err != noErr ) {
175 ERRORLOG(
"Couldn't get device config size" );
178 AudioBufferList *pBufferList = (AudioBufferList *) alloca( nBufferListSize );
179 err = AudioObjectGetPropertyData( deviceIDs[ i ], &propertyAddress, 0, NULL, &nBufferListSize, pBufferList );
182 for (
int nBuffer = 0; nBuffer < pBufferList->mNumberBuffers; nBuffer++ ) {
183 nChannels += pBufferList->mBuffers[ nBuffer ].mNumberChannels;
185 if ( nChannels < 2 ) {
187 if ( nChannels == 1 ) {
188 INFOLOG( QString(
"Skipping mono output device %1" ).arg( deviceIDs[ i ] ) );
214 if ( sPreferredDeviceName.isNull()
215 || QString::compare( sPreferredDeviceName,
"default", Qt::CaseInsensitive ) == 0 ) {
216 INFOLOG(
"Using default device" );
221 if ( QString::compare( sDeviceName, sPreferredDeviceName, Qt::CaseInsensitive ) == 0 ) {
223 INFOLOG( QString(
"Found device '%1' (%2) for preference '%3'" )
224 .arg( sDeviceName ).arg( (
int)device ).arg( sPreferredDeviceName ) );
228 ERRORLOG( QString(
"Couldn't find device '%1', falling back to default" ).arg( sPreferredDeviceName ) );
237 AudioDeviceID device;
239 AudioObjectPropertyAddress propertyAddress = {
240 kAudioHardwarePropertyDefaultOutputDevice,
241 kAudioObjectPropertyScopeGlobal,
242 kAudioObjectPropertyElementMaster
245 dataSize =
sizeof(AudioDeviceID);
246 err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
253 if ( err != noErr ) {
254 ERRORLOG(
"Could not get Default Output Device" );
288 AudioStreamBasicDescription outputStreamBasicDescription;
289 UInt32 propertySize =
sizeof( outputStreamBasicDescription );
292 AudioObjectPropertyAddress propertyAddress = {
293 kAudioDevicePropertyStreamFormat,
294 kAudioObjectPropertyScopeGlobal,
295 kAudioObjectPropertyElementMaster
303 &outputStreamBasicDescription
307 ERRORLOG( QString(
"AudioDeviceGetProperty: returned %1 when getting kAudioDevicePropertyStreamFormat").arg(err) );
310 INFOLOG( QString(
"SampleRate: %1").arg( outputStreamBasicDescription.mSampleRate ) );
311 INFOLOG( QString(
"BytesPerPacket: %1").arg( outputStreamBasicDescription.mBytesPerPacket ) );
312 INFOLOG( QString(
"FramesPerPacket: %1").arg( outputStreamBasicDescription.mFramesPerPacket ) );
313 INFOLOG( QString(
"BytesPerFrame: %1").arg( outputStreamBasicDescription.mBytesPerFrame ) );
314 INFOLOG( QString(
"ChannelsPerFrame: %1").arg( outputStreamBasicDescription.mChannelsPerFrame ) );
315 INFOLOG( QString(
"BitsPerChannel: %1").arg( outputStreamBasicDescription.mBitsPerChannel ) );
350 OSStatus err = noErr;
353 AudioComponent compOutput;
354 AudioComponentDescription descAUHAL;
356 descAUHAL.componentType = kAudioUnitType_Output;
357 descAUHAL.componentSubType = kAudioUnitSubType_HALOutput;
358 descAUHAL.componentManufacturer = kAudioUnitManufacturer_Apple;
359 descAUHAL.componentFlags = 0;
360 descAUHAL.componentFlagsMask = 0;
362 compOutput = AudioComponentFindNext( NULL, &descAUHAL );
363 if ( compOutput == NULL ) {
364 ERRORLOG(
"Error in FindNextComponent" );
368 err = AudioComponentInstanceNew( compOutput, &
m_outputUnit );
369 if ( err != noErr ) {
370 ERRORLOG(
"Error Opening Component" );
377 err = AudioUnitSetProperty(
379 kAudioOutputUnitProperty_CurrentDevice,
380 kAudioUnitScope_Global,
385 if ( err != noErr ) {
386 ERRORLOG(
"Could not set Current Device" );
389 AudioStreamBasicDescription asbdesc;
391 asbdesc.mFormatID = kAudioFormatLinearPCM;
392 asbdesc.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;
393 asbdesc.mBytesPerPacket =
sizeof( Float32 );
394 asbdesc.mFramesPerPacket = 1;
395 asbdesc.mBytesPerFrame =
sizeof( Float32 );
396 asbdesc.mChannelsPerFrame = 2;
397 asbdesc.mBitsPerChannel = 32;
399 err = AudioUnitSetProperty(
401 kAudioUnitProperty_StreamFormat,
402 kAudioUnitScope_Input,
405 sizeof( AudioStreamBasicDescription )
409 AURenderCallbackStruct out;
411 out.inputProcRefCon = (
void * )
this;
413 err = AudioUnitSetProperty(
415 kAudioUnitProperty_SetRenderCallback,
416 kAudioUnitScope_Global,
421 if ( err != noErr ) {
422 ERRORLOG(
"Could not Set Render Callback" );
427 if ( err != noErr ) {
428 ERRORLOG(
"Could not Initialize AudioUnit" );
432 INFOLOG( QString(
"Setting buffer size to %1" ).arg( nBufferSize ) );
433 AudioObjectPropertyAddress propertyAddress = {
434 kAudioDevicePropertyBufferFrameSize,
435 kAudioObjectPropertyScopeGlobal,
436 kAudioObjectPropertyElementMaster
443 sizeof(UInt32), &nBufferSize);
445 if ( err != noErr ) {
446 ERRORLOG( QString(
"Could not set buffer size to %1" ).arg( nBufferSize ) );
static OSStatus renderProc(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
The Render Callback.