2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "SC_CoreAudio.h"
24 #include "SC_SequencedCommand.h"
25 #include "SC_Prototypes.h"
26 #include "SC_HiddenWorld.h"
27 #include "SC_WorldOptions.h"
28 #include "SC_Endian.h"
29 #include "SC_Lib_Cintf.h"
46 #include "SC_Win32Utils.h"
49 int64 gStartupOSCTime
= -1;
51 void sc_SetDenormalFlags();
53 void set_real_time_priority(pthread_t thread
);
55 double gSampleRate
, gSampleDur
;
57 // =====================================================================
60 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIO || SC_AUDIO_API == SC_AUDIO_API_AUDIOUNITS
64 int32
server_timeseed()
66 static int32 count
= 0;
67 int64 time
= AudioGetCurrentHostTime();
68 return (int32
)(time
>> 32) ^ (int32
)time
^ count
--;
71 inline int64
CoreAudioHostTimeToOSC(int64 hostTime
)
73 return (int64
)((double)AudioConvertHostTimeToNanos(hostTime
) * kNanosToOSCunits
) + gOSCoffset
;
78 return CoreAudioHostTimeToOSC(AudioGetCurrentHostTime());
81 static void syncOSCOffsetWithTimeOfDay()
83 // generate a value gOSCoffset such that
84 // (gOSCOffset + systemTimeInOSCunits)
85 // is equal to gettimeofday time in OSCunits.
86 // Then if this machine is synced via NTP, we are synced with the world.
87 // more accurate way to do this??
91 int64 systemTimeBefore
, systemTimeAfter
, diff
;
92 int64 minDiff
= 0x7fffFFFFffffFFFFLL
;
94 // take best of several tries
95 const int numberOfTries
= 5;
96 int64 newOffset
= gOSCoffset
;
97 for (int i
=0; i
<numberOfTries
; ++i
) {
98 systemTimeBefore
= AudioGetCurrentHostTime();
100 systemTimeAfter
= AudioGetCurrentHostTime();
102 diff
= systemTimeAfter
- systemTimeBefore
;
103 if (diff
< minDiff
) {
105 // assume that gettimeofday happens halfway between AudioGetCurrentHostTime calls
106 int64 systemTimeBetween
= systemTimeBefore
+ diff
/2;
107 int64 systemTimeInOSCunits
= (int64
)((double)AudioConvertHostTimeToNanos(systemTimeBetween
) * kNanosToOSCunits
);
108 int64 timeOfDayInOSCunits
= ((int64
)(tv
.tv_sec
+ kSECONDS_FROM_1900_to_1970
) << 32)
109 + (int64
)(tv
.tv_usec
* kMicrosToOSCunits
);
110 newOffset
= timeOfDayInOSCunits
- systemTimeInOSCunits
;
114 gOSCoffset
= newOffset
;
115 //scprintf("gOSCoffset %016llX\n", gOSCoffset);
118 void* resyncThreadFunc(void* arg
);
119 void* resyncThreadFunc(void* /*arg*/)
123 syncOSCOffsetWithTimeOfDay();
128 void initializeScheduler()
130 syncOSCOffsetWithTimeOfDay();
132 pthread_t resyncThread
;
133 pthread_create (&resyncThread
, NULL
, resyncThreadFunc
, (void*)0);
134 set_real_time_priority(resyncThread
);
136 #endif // SC_AUDIO_API_COREAUDIO
139 // =====================================================================
140 // Timing (CoreAudioIPHONE)
142 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIOIPHONE
144 int64 gOSCoffset
= 0;
146 static inline int64
GetMicroseconds()
149 gettimeofday(&tv
, 0);
150 return (int64
) tv
.tv_sec
* 1000000 + tv
.tv_usec
;
153 static inline int64
GetCurrentOSCTime()
157 gettimeofday(&tv
, 0);
158 s
= (uint64
)tv
.tv_sec
+ (uint64
)kSECONDS_FROM_1900_to_1970
;
159 f
= (uint64
)((double)tv
.tv_usec
* kMicrosToOSCunits
);
161 return (s
<< 32) + f
;
164 int32
server_timeseed()
166 int64 time
= GetCurrentOSCTime();
167 return Hash((int32
)(time
>> 32) + Hash((int32
)time
));
172 return GetCurrentOSCTime();
175 void initializeScheduler()
177 gOSCoffset
= GetCurrentOSCTime();
179 #endif // SC_AUDIO_API_COREAUDIO
184 // =====================================================================
185 // Timing (PortAudio)
187 #if SC_AUDIO_API == SC_AUDIO_API_PORTAUDIO
189 int64 gOSCoffset
= 0;
191 static inline int64
GetCurrentOSCTime()
195 gettimeofday(&tv
, 0);
196 s
= (uint64
)tv
.tv_sec
+ (uint64
)kSECONDS_FROM_1900_to_1970
;
197 f
= (uint64
)((double)tv
.tv_usec
* kMicrosToOSCunits
);
199 return (s
<< 32) + f
;
202 int32
server_timeseed()
204 int64 time
= GetCurrentOSCTime();
205 return Hash((int32
)(time
>> 32) + Hash((int32
)time
));
210 return GetCurrentOSCTime();
213 int64
PaStreamTimeToOSC(PaTime pa_time
) {
216 f
= (uint64
)((pa_time
- s
) * 1000000 * kMicrosToOSCunits
);
218 return (s
<< 32) + f
;
221 void initializeScheduler()
223 gOSCoffset
= GetCurrentOSCTime();
225 #endif // SC_AUDIO_API_PORTAUDIO
228 // =====================================================================
231 bool ProcessOSCPacket(World
*inWorld
, OSC_Packet
*inPacket
);
232 void PerformOSCBundle(World
*inWorld
, OSC_Packet
*inPacket
);
233 int PerformOSCMessage(World
*inWorld
, int inSize
, char *inData
, ReplyAddress
*inReply
);
234 PacketStatus
PerformOSCPacket(World
*world
, OSC_Packet
*packet
, SC_ScheduledEvent::PacketFreeFunc
);
236 void Perform_ToEngine_Msg(FifoMsg
*inMsg
);
237 void FreeOSCPacket(FifoMsg
*inMsg
);
241 IsBundle() { str4cpy(s
, "#bundle"); }
242 bool checkIsBundle(int32
*in
) { return in
[0] == s
[0] && in
[1] == s
[1]; }
247 bool ProcessOSCPacket(World
*inWorld
, OSC_Packet
*inPacket
)
249 //scprintf("ProcessOSCPacket %d, '%s'\n", inPacket->mSize, inPacket->mData);
250 if (!inPacket
) return false;
252 inWorld
->mDriverLock
->Lock();
253 SC_AudioDriver
*driver
= AudioDriver(inWorld
);
255 inWorld
->mDriverLock
->Unlock();
258 inPacket
->mIsBundle
= gIsBundle
.checkIsBundle((int32
*)inPacket
->mData
);
260 fifoMsg
.Set(inWorld
, Perform_ToEngine_Msg
, FreeOSCPacket
, (void*)inPacket
);
261 result
= driver
->SendOscPacketMsgToEngine(fifoMsg
);
262 inWorld
->mDriverLock
->Unlock();
266 int PerformOSCMessage(World
*inWorld
, int inSize
, char *inData
, ReplyAddress
*inReply
)
268 // scprintf("->PerformOSCMessage %d\n", inData[0]);
271 if (inData
[0] == 0) {
273 uint32 index
= inData
[3];
274 if (index
>= NUMBER_OF_COMMANDS
) cmdObj
= 0;
275 else cmdObj
= gCmdArray
[index
];
277 cmdNameLen
= OSCstrlen(inData
);
278 cmdObj
= gCmdLib
->Get((int32
*)inData
);
281 CallSendFailureCommand(inWorld
, inData
, "Command not found", inReply
);
282 scprintf("FAILURE IN SERVER: %s Command not found\n", inData
);
283 return kSCErr_NoSuchCommand
;
286 int err
= cmdObj
->Perform(inWorld
, inSize
- cmdNameLen
, inData
+ cmdNameLen
, inReply
);
287 //scprintf("<-PerformOSCMessage %d\n", inData[0]);
291 void PerformOSCBundle(World
*inWorld
, OSC_Packet
*inPacket
)
293 //scprintf("->PerformOSCBundle %d\n", inPacket->mSize);
294 char *data
= inPacket
->mData
+ 16;
295 char* dataEnd
= inPacket
->mData
+ inPacket
->mSize
;
297 while (data
< dataEnd
) {
298 int32 msgSize
= ntohl(*(int32
*)data
);
299 data
+= sizeof(int32
);
300 //scprintf("msgSize %d\n", msgSize);
301 PerformOSCMessage(inWorld
, msgSize
, data
, &inPacket
->mReplyAddr
);
305 // reset so next command uses permanent error notification status
306 inWorld
->mLocalErrorNotification
= 0;
308 // // 0 is a temporary change, so reset the local error flag
309 // if(!inWorld->mLocalErrorNotification) {
310 // inWorld->mLocalErrorNotification = inWorld->mErrorNotification;
313 //scprintf("<-PerformOSCBundle %d\n", inPacket->mSize);
316 PacketStatus
PerformOSCPacket(World
*world
, OSC_Packet
*packet
, SC_ScheduledEvent::PacketFreeFunc freeFunc
)
318 SC_AudioDriver
*driver
= world
->hw
->mAudioDriver
;
320 if (!packet
->mIsBundle
) {
321 PerformOSCMessage(world
, packet
->mSize
, packet
->mData
, &packet
->mReplyAddr
);
322 world
->mLocalErrorNotification
= 0;
323 // if(!world->mLocalErrorNotification) {
324 // world->mLocalErrorNotification = world->mErrorNotification;
326 return PacketPerformed
;
328 // in real time engine, schedule the packet
329 int64 time
= OSCtime(packet
->mData
+ 8);
330 if (time
== 0 || time
== 1) {
331 PerformOSCBundle(world
, packet
);
332 return PacketPerformed
;
334 if ((time
< driver
->mOSCbuftime
) && (world
->mVerbosity
>= 0)) {
335 double seconds
= (driver
->mOSCbuftime
- time
)*kOSCtoSecs
;
336 scprintf("late %.9f\n", seconds
);
339 //ReportLateness(packet->mReply, seconds)
343 //scprintf("scheduled in %.6f at time %.6f\n",
344 // (time-driver->mOSCbuftime)*kOSCtoSecs,
345 // (time-gStartupOSCTime)*kOSCtoSecs);
347 SC_ScheduledEvent
event(world
, time
, packet
, freeFunc
);
348 driver
->AddEvent(event
);
349 return PacketScheduled
;
354 ////////////////////////////////////////////////////////////////////////////
356 void Perform_ToEngine_Msg(FifoMsg
*inMsg
)
358 World
*world
= inMsg
->mWorld
;
359 OSC_Packet
*packet
= (OSC_Packet
*)inMsg
->mData
;
362 PacketStatus status
= PerformOSCPacket(world
, packet
, SC_ScheduledEvent::FreeInNRT
);
363 if (status
== PacketScheduled
) {
364 // Transfer ownership
366 inMsg
->mFreeFunc
= 0;
370 PacketStatus
PerformCompletionMsg(World
*inWorld
, const OSC_Packet
& inPacket
)
372 OSC_Packet
* packet
= (OSC_Packet
*)World_Alloc(inWorld
, sizeof(OSC_Packet
));
374 packet
->mIsBundle
= gIsBundle
.checkIsBundle((int32
*)packet
->mData
);
375 PacketStatus status
= PerformOSCPacket(inWorld
, packet
, SC_ScheduledEvent::FreeInRT
);
376 if (status
== PacketPerformed
) {
377 World_Free(inWorld
, packet
);
382 void FreeOSCPacket(FifoMsg
*inMsg
)
384 OSC_Packet
*packet
= (OSC_Packet
*)inMsg
->mData
;
388 #pragma message("$$$todo fixme hack for the 'uninitialized packet->mData ptr when using MSVC 7.1 debug")
389 if (packet
->mData
!= reinterpret_cast<char*>(0xcdcdcdcd))
391 #else //#ifdef _WIN32
393 #endif //#ifdef _WIN32
398 void Free_FromEngine_Msg(FifoMsg
*inMsg
);
399 void Free_FromEngine_Msg(FifoMsg
*inMsg
)
401 World_Free(inMsg
->mWorld
, inMsg
->mData
);
404 // =====================================================================
405 // Audio driver (Common)
407 SC_AudioDriver::SC_AudioDriver(struct World
*inWorld
)
410 , mNumSamplesPerCallback(0)
415 SC_AudioDriver::~SC_AudioDriver()
417 mRunThreadFlag
= false;
419 pthread_join(mThread
, 0);
422 void* audio_driver_thread_func(void* arg
);
423 void* audio_driver_thread_func(void* arg
)
425 SC_AudioDriver
*ca
= (SC_AudioDriver
*)arg
;
426 void* result
= ca
->RunThread();
430 void* SC_AudioDriver::RunThread()
432 TriggersFifo
*trigfifo
= &mWorld
->hw
->mTriggers
;
433 NodeReplyFifo
*nodereplyfifo
= &mWorld
->hw
->mNodeMsgs
;
434 NodeEndsFifo
*nodeendfifo
= &mWorld
->hw
->mNodeEnds
;
435 DeleteGraphDefsFifo
*deletegraphfifo
= &mWorld
->hw
->mDeleteGraphDefs
;
437 while (mRunThreadFlag
) {
439 mAudioSync
.WaitNext();
441 mWorld
->mNRTLock
->Lock();
446 // send node reply messages
447 nodereplyfifo
->Perform();
449 // send node status messages
450 nodeendfifo
->Perform();
453 deletegraphfifo
->Perform();
456 mFromEngine
.Perform();
458 mWorld
->mNRTLock
->Unlock();
463 bool SC_AudioDriver::SendMsgFromEngine(FifoMsg
& inMsg
)
465 return mFromEngine
.Write(inMsg
);
469 bool SC_AudioDriver::SendMsgToEngine(FifoMsg
& inMsg
)
472 return mToEngine
.Write(inMsg
);
475 bool SC_AudioDriver::SendOscPacketMsgToEngine(FifoMsg
& inMsg
)
477 mOscPacketsToEngine
.Free();
478 return mOscPacketsToEngine
.Write(inMsg
);
481 void SC_ScheduledEvent::FreeInRT(struct World
* world
, OSC_Packet
* packet
)
483 World_Free(world
, packet
->mData
);
484 World_Free(world
, packet
);
487 void SC_ScheduledEvent::FreeInNRT(struct World
* world
, OSC_Packet
* packet
)
490 msg
.Set(world
, FreeOSCPacket
, 0, (void*)packet
);
491 world
->hw
->mAudioDriver
->SendMsgFromEngine(msg
);
494 void SC_ScheduledEvent::Perform()
496 PerformOSCBundle(mWorld
, mPacket
);
497 (*mPacketFreeFunc
)(mWorld
, mPacket
);
500 bool SC_AudioDriver::Setup()
502 mRunThreadFlag
= true;
503 pthread_create (&mThread
, NULL
, audio_driver_thread_func
, (void*)this);
504 set_real_time_priority(mThread
);
509 if (!DriverSetup(&numSamples
, &sampleRate
)) return false;
511 mNumSamplesPerCallback
= numSamples
;
512 //scprintf("mNumSamplesPerCallback %d\n", mNumSamplesPerCallback);
513 //scprintf("mHardwareBufferSize %lu\n", mHardwareBufferSize);
515 // compute a per sample increment to the OpenSoundControl Time
516 mOSCincrementNumerator
= (double)mWorld
->mBufLength
* pow(2.,32.);
517 mOSCincrement
= (int64
)(mOSCincrementNumerator
/ sampleRate
);
518 mOSCtoSamples
= sampleRate
/ pow(2.,32.);
520 World_SetSampleRate(mWorld
, sampleRate
);
521 mSampleRate
= mSmoothSampleRate
= sampleRate
;
522 mBuffersPerSecond
= sampleRate
/ mNumSamplesPerCallback
;
523 mMaxPeakCounter
= (int)mBuffersPerSecond
;
525 if(mWorld
->mVerbosity
>= 0){
526 scprintf("SC_AudioDriver: sample rate = %f, driver's block size = %d\n", sampleRate
, mNumSamplesPerCallback
);
532 bool SC_AudioDriver::Start()
540 mStartSampleTime
= 0.;
541 mPrevSampleTime
= 0.;
545 gStartupOSCTime
= oscTimeNow();
547 return DriverStart();
550 bool SC_AudioDriver::Stop()
552 if (!DriverStop()) return false;
557 // =====================================================================
558 // Audio driver (CoreAudio)
559 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIO
561 SC_AudioDriver
* SC_NewAudioDriver(struct World
*inWorld
)
563 return new SC_CoreAudioDriver(inWorld
);
568 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIO || SC_AUDIO_API == SC_AUDIO_API_AUDIOUNITS
570 SC_CoreAudioDriver::SC_CoreAudioDriver(struct World
*inWorld
)
571 : SC_AudioDriver(inWorld
)
576 SC_CoreAudioDriver::~SC_CoreAudioDriver()
581 for (i
=0; i
<mInputBufList
->mNumberBuffers
; i
++)
583 free(mInputBufList
->mBuffers
[i
].mData
);
589 bool SC_CoreAudioDriver::DriverSetup(int* outNumSamplesPerCallback
, double* outSampleRate
)
591 OSStatus err
= kAudioHardwareNoError
;
593 mOutputDevice
= kAudioDeviceUnknown
;
594 mInputDevice
= kAudioDeviceUnknown
;
595 AudioObjectPropertyAddress propertyAddress
;
597 propertyAddress
.mSelector
= kAudioHardwarePropertyDevices
;
598 propertyAddress
.mScope
= kAudioObjectPropertyScopeGlobal
;
599 propertyAddress
.mElement
= kAudioObjectPropertyElementMaster
;
601 //scprintf("SC_CoreAudioDriver::Setup world %p\n", mWorld);
603 ////////////////////////////////////////////////////////////////////////////////////////////////
606 // err = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices, &count, 0);
608 propertyAddress
.mSelector
= kAudioHardwarePropertyDevices
;
610 err
= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
);
613 scprintf("get kAudioHardwarePropertyDevices error %4.4s\n", (char*)&err
);
617 AudioDeviceID
*devices
= (AudioDeviceID
*)malloc(count
);
619 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &count, devices);
621 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
, devices
);
623 if (err
!= kAudioHardwareNoError
) {
624 scprintf("get kAudioHardwarePropertyDevices error %4.4s\n", (char*)&err
);
629 int numdevices
= count
/ sizeof(AudioDeviceID
);
630 if(mWorld
->mVerbosity
>= 0){
631 scprintf("Number of Devices: %d\n", numdevices
);
633 for (int i
= 0; i
< numdevices
; ++i
) {
634 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
636 // err = AudioDeviceGetPropertyInfo(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, 0);
638 err
= AudioObjectGetPropertyDataSize(devices
[i
], &propertyAddress
, 0, NULL
, &count
);
640 if (err
!= kAudioHardwareNoError
) {
641 scprintf("info kAudioDevicePropertyDeviceName error %4.4s A %d %p\n", (char*)&err
, i
, devices
[i
]);
645 char *name
= (char*)malloc(count
);
646 // err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, name);
648 err
= AudioObjectGetPropertyData(devices
[i
], &propertyAddress
, 0, NULL
, &count
, name
);
650 if (err
!= kAudioHardwareNoError
) {
651 scprintf("get kAudioDevicePropertyDeviceName error %4.4s A %d %p\n", (char*)&err
, i
, devices
[i
]);
655 if(mWorld
->mVerbosity
>= 0){
656 scprintf(" %d : \"%s\"\n", i
, name
);
661 if(mWorld
->mVerbosity
>= 0){
666 if (mWorld
->hw
->mInDeviceName
|| mWorld
->hw
->mOutDeviceName
) {
667 propertyAddress
.mSelector
= kAudioHardwarePropertyDevices
;
669 // err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &count, 0);
671 err
= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
);
673 if (err
!= kAudioHardwareNoError
) {
674 scprintf("info kAudioHardwarePropertyDevices error %4.4s\n", (char*)&err
);
678 AudioDeviceID
*devices
= (AudioDeviceID
*)malloc(count
);
680 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &count, devices);
681 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
, devices
);
683 if (err
!= kAudioHardwareNoError
) {
684 scprintf("get kAudioHardwarePropertyDevices error %4.4s\n", (char*)&err
);
688 int numdevices
= count
/ sizeof(AudioDeviceID
);
689 for (int i
= 0; i
< numdevices
; ++i
) {
691 // err = AudioDeviceGetPropertyInfo(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, 0);
692 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
693 err
= AudioObjectGetPropertyDataSize(devices
[i
], &propertyAddress
, 0, NULL
, &count
);
695 if (err
!= kAudioHardwareNoError
) {
696 scprintf("info kAudioDevicePropertyDeviceName error %4.4s B %d %p\n", (char*)&err
, i
, devices
[i
]);
700 char *name
= (char*)malloc(count
);
702 // err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, name);
704 err
= AudioObjectGetPropertyData(devices
[i
], &propertyAddress
, 0, NULL
, &count
, name
);
706 if (err
!= kAudioHardwareNoError
) {
707 scprintf("get kAudioDevicePropertyDeviceName error %4.4s B %d %p\n", (char*)&err
, i
, devices
[i
]);
710 if (strcmp(name
, mWorld
->hw
->mInDeviceName
) == 0) {
711 mInputDevice
= devices
[i
];
713 if (strcmp(name
, mWorld
->hw
->mOutDeviceName
) == 0) {
714 mOutputDevice
= devices
[i
];
717 if (mInputDevice
!=kAudioDeviceUnknown
&& mOutputDevice
!=kAudioDeviceUnknown
) break;
720 if (mOutputDevice
==kAudioDeviceUnknown
|| mInputDevice
==kAudioDeviceUnknown
) goto getDefault
;
724 // get the default output device for the HAL
725 if (mOutputDevice
==kAudioDeviceUnknown
)
727 count
= sizeof(mOutputDevice
);
728 //get the output device:
729 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) & mOutputDevice);
731 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultOutputDevice
;
733 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
, (void*) & mOutputDevice
);
735 if (err
!= kAudioHardwareNoError
) {
736 scprintf("get kAudioHardwarePropertyDefaultOutputDevice error %4.4s\n", (char*)&err
);
741 //get the input device
742 if (mInputDevice
==kAudioDeviceUnknown
)
744 count
= sizeof(mInputDevice
);
745 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &count, (void *) & mInputDevice);
747 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultInputDevice
;
749 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &count
, (void*) & mInputDevice
);
752 //get the input device:
753 if (err
!= kAudioHardwareNoError
) {
754 scprintf("get kAudioHardwarePropertyDefaultInputDevice error %4.4s\n", (char*)&err
);
760 ////////////////////////////////////////////////////////////////////////////////////////////////
763 now
.mFlags
= kAudioTimeStampHostTimeValid
;
764 now
.mHostTime
= AudioGetCurrentHostTime();
765 if (mPreferredHardwareBufferFrameSize
)
768 count
= sizeof(UInt32
);
769 // err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &mPreferredHardwareBufferFrameSize);
771 propertyAddress
.mSelector
= kAudioDevicePropertyBufferFrameSize
;
772 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
774 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, count
, &mPreferredHardwareBufferFrameSize
);
776 if (err
!= kAudioHardwareNoError
) {
777 scprintf("set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err
);
782 count
= sizeof(UInt32
);
783 //err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &mPreferredHardwareBufferFrameSize);
785 propertyAddress
.mSelector
= kAudioDevicePropertyBufferFrameSize
;
786 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
788 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, count
, &mPreferredHardwareBufferFrameSize
);
790 if (err
!= kAudioHardwareNoError
) {
791 scprintf("set kAudioDevicePropertyNominalSampleRate error %4.4s\n", (char*)&err
);
796 if (mPreferredSampleRate
)
798 Float64 sampleRate
= mPreferredSampleRate
;
799 count
= sizeof(Float64
);
800 //err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &sampleRate);
802 propertyAddress
.mSelector
= kAudioDevicePropertyNominalSampleRate
;
803 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
805 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, count
, &sampleRate
);
807 if (err
!= kAudioHardwareNoError
) {
808 scprintf("set kAudioDevicePropertyNominalSampleRate error %4.4s\n", (char*)&err
);
813 count
= sizeof(Float64
);
814 //err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &sampleRate);
815 propertyAddress
.mSelector
= kAudioDevicePropertyNominalSampleRate
;
816 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
818 err
= AudioObjectSetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, count
, &sampleRate
);
819 if (err
!= kAudioHardwareNoError
) {
820 scprintf("set kAudioDevicePropertyNominalSampleRate error %4.4s\n", (char*)&err
);
826 // get the buffersize for the out device
827 count
= sizeof(mHardwareBufferSize
);
828 // err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferSize, &count, &mHardwareBufferSize);
829 propertyAddress
.mSelector
= kAudioDevicePropertyBufferSize
;
830 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
832 err
= AudioObjectGetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
, &mHardwareBufferSize
);
834 if (err
!= kAudioHardwareNoError
) {
835 scprintf("get kAudioDevicePropertyBufferSize error %4.4s\n", (char*)&err
);
838 //scprintf("mHardwareBufferSize = %ld\n", mHardwareBufferSize);
840 // get a description of the data format used by the output device
841 count
= sizeof(AudioStreamBasicDescription
);
842 // err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDesc);
843 propertyAddress
.mSelector
= kAudioDevicePropertyStreamFormat
;
844 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
846 err
= AudioObjectGetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
, &outputStreamDesc
);
848 if (err
!= kAudioHardwareNoError
) {
849 scprintf("get kAudioDevicePropertyStreamFormat error %4.4s\n", (char*)&err
);
853 if (mInputDevice
!= kAudioDeviceUnknown
) {
854 // get a description of the data format used by the input device
855 count
= sizeof(AudioStreamBasicDescription
);
856 // err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDesc);
857 propertyAddress
.mSelector
= kAudioDevicePropertyStreamFormat
;
858 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
860 err
= AudioObjectGetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, &count
, &inputStreamDesc
);
862 if (err
!= kAudioHardwareNoError
) {
863 scprintf("get kAudioDevicePropertyStreamFormat error on input %4.4s\n", (char*)&err
);
867 if (inputStreamDesc
.mSampleRate
!= outputStreamDesc
.mSampleRate
) {
868 scprintf("input and output sample rates do not match. %g != %g\n", inputStreamDesc
.mSampleRate
, outputStreamDesc
.mSampleRate
);
872 ////////////////////////////////////////////////////////////////////////////////////////////////
876 // err = AudioDeviceGetPropertyInfo(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, 0);
877 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
878 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
880 err
= AudioObjectGetPropertyDataSize(mInputDevice
, &propertyAddress
, 0, NULL
, &count
);
882 if (err
!= kAudioHardwareNoError
) {
883 scprintf("info kAudioDevicePropertyDeviceName error %4.4s C %p\n", (char*)&err
, mInputDevice
);
887 char *name
= (char*)malloc(count
);
888 //err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, name);
890 err
= AudioObjectGetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, &count
, name
);
892 if (err
!= kAudioHardwareNoError
) {
893 scprintf("get kAudioDevicePropertyDeviceName error %4.4s C %p\n", (char*)&err
, mInputDevice
);
898 if(mWorld
->mVerbosity
>= 0){
899 scprintf("\"%s\" Input Device\n", name
);
905 // err = AudioDeviceGetPropertyInfo(mInputDevice, 0, 1, kAudioDevicePropertyStreamConfiguration, &count, &writeable);
906 propertyAddress
.mSelector
= kAudioDevicePropertyStreamConfiguration
;
907 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
909 err
= AudioObjectIsPropertySettable(mInputDevice
, &propertyAddress
, &writeable
);
911 if (err
!= kAudioHardwareNoError
) {
912 scprintf("info kAudioDevicePropertyStreamConfiguration settable error %4.4s\n", (char*)&err
);
916 err
= AudioObjectGetPropertyDataSize(mInputDevice
, &propertyAddress
, 0, NULL
, &count
);
918 if (err
!= kAudioHardwareNoError
) {
919 scprintf("info kAudioDevicePropertyStreamConfiguration size error %4.4s\n", (char*)&err
);
923 AudioBufferList
*bufList
= (AudioBufferList
*)malloc(count
);
924 // err = AudioDeviceGetProperty(mInputDevice, 0, 1, kAudioDevicePropertyStreamConfiguration, &count, bufList);
925 propertyAddress
.mSelector
= kAudioDevicePropertyStreamConfiguration
;
926 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
928 err
= AudioObjectGetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, &count
, bufList
);
930 if (err
!= kAudioHardwareNoError
) {
931 scprintf("get kAudioDevicePropertyStreamConfiguration error %4.4s\n", (char*)&err
);
936 if(mWorld
->mVerbosity
>= 0){
937 scprintf(" Streams: %d\n", bufList
->mNumberBuffers
);
938 for (unsigned int j
= 0; j
< bufList
->mNumberBuffers
; ++j
) {
939 scprintf(" %d channels %d\n", j
, bufList
->mBuffers
[j
].mNumberChannels
);
945 if(mWorld
->mVerbosity
>= 0){
948 ////////////////////////////////////////////////////////////////////////////////////////////////
951 // err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, 0);
952 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
953 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
955 err
= AudioObjectGetPropertyDataSize(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
);
957 char *name
= (char*)malloc(count
);
958 // err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, name);
959 err
= AudioObjectGetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
, name
);
960 if (err
!= kAudioHardwareNoError
) {
961 scprintf("get kAudioDevicePropertyDeviceName error %4.4s\n", (char*)&err
);
966 if(mWorld
->mVerbosity
>= 0){
967 scprintf("\"%s\" Output Device\n", name
);
972 // err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, 0, kAudioDevicePropertyStreamConfiguration, &count, &writeable);
974 propertyAddress
.mSelector
= kAudioDevicePropertyStreamConfiguration
;
975 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
977 err
= AudioObjectIsPropertySettable(mOutputDevice
, &propertyAddress
, &writeable
);
979 if (err
!= kAudioHardwareNoError
) {
980 scprintf("info kAudioDevicePropertyStreamConfiguration settable error %4.4s\n", (char*)&err
);
984 err
= AudioObjectGetPropertyDataSize(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
);
986 if (err
!= kAudioHardwareNoError
) {
987 scprintf("info kAudioDevicePropertyStreamConfiguration size error %4.4s\n", (char*)&err
);
991 AudioBufferList
*bufList
= (AudioBufferList
*)malloc(count
);
992 // err = AudioDeviceGetProperty(mOutputDevice, 0, 0, kAudioDevicePropertyStreamConfiguration, &count, bufList);
994 propertyAddress
.mSelector
= kAudioDevicePropertyStreamConfiguration
;
995 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
997 err
= AudioObjectGetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
, bufList
);
998 if (err
!= kAudioHardwareNoError
) {
999 scprintf("get kAudioDevicePropertyStreamConfiguration error %4.4s\n", (char*)&err
);
1003 if(mWorld
->mVerbosity
>= 0){
1004 scprintf(" Streams: %d\n", bufList
->mNumberBuffers
);
1005 for (unsigned int j
= 0; j
< bufList
->mNumberBuffers
; ++j
) {
1006 scprintf(" %d channels %d\n", j
, bufList
->mBuffers
[j
].mNumberChannels
);
1011 if(mWorld
->mVerbosity
>= 0){
1014 ////////////////////////////////////////////////////////////////////////////////////////////////
1017 if (UseSeparateIO()) {
1018 count
= sizeof(UInt32
);
1019 //err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertySafetyOffset, &count, &mSafetyOffset);
1020 propertyAddress
.mSelector
= kAudioDevicePropertySafetyOffset
;
1021 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
1023 err
= AudioObjectGetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, &count
, &mSafetyOffset
);
1025 if (err
!= kAudioHardwareNoError
) {
1026 scprintf("get kAudioDevicePropertySafetyOffset error %4.4s\n", (char*)&err
);
1029 if(mWorld
->mVerbosity
>= 1){
1030 scprintf("mSafetyOffset %lu\n", mSafetyOffset
);
1034 // err = AudioDeviceGetPropertyInfo(mInputDevice, 0, true, kAudioDevicePropertyStreamConfiguration, &count, &writeable);
1036 propertyAddress
.mSelector
= kAudioDevicePropertyStreamConfiguration
;
1037 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
1039 err
= AudioObjectIsPropertySettable(mInputDevice
, &propertyAddress
, &writeable
);
1041 if (err
!= kAudioHardwareNoError
) {
1042 scprintf("get kAudioDevicePropertyStreamConfiguration writeable error %4.4s\n", (char*)&err
);
1046 err
= AudioObjectGetPropertyDataSize(mInputDevice
, &propertyAddress
, 0, NULL
, &count
);
1048 if (err
!= kAudioHardwareNoError
) {
1049 scprintf("get kAudioDevicePropertyStreamConfiguration size error %4.4s\n", (char*)&err
);
1053 mInputBufList
= (AudioBufferList
*)malloc(count
);
1055 //err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamConfiguration, &count, mInputBufList);
1057 err
= AudioObjectGetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, &count
, mInputBufList
);
1059 if (err
!= kAudioHardwareNoError
) {
1060 scprintf("get kAudioDevicePropertyStreamConfiguration error %4.4s\n", (char*)&err
);
1064 if(mWorld
->mVerbosity
>= 1){
1065 scprintf("mNumberBuffers %lu\n", mInputBufList
->mNumberBuffers
);
1067 for (uint32 i
=0; i
<mInputBufList
->mNumberBuffers
; ++i
) {
1068 if(mWorld
->mVerbosity
>= 1){
1069 scprintf(" mDataByteSize %d %lu\n", i
, mInputBufList
->mBuffers
[i
].mDataByteSize
);
1071 mInputBufList
->mBuffers
[i
].mData
= zalloc(1, mInputBufList
->mBuffers
[i
].mDataByteSize
);
1076 now.mFlags = kAudioTimeStampHostTimeValid;
1077 now.mHostTime = AudioGetCurrentHostTime();
1080 err = AudioDeviceSetProperty(mInputDevice, &now, 0, true, kAudioDevicePropertyRegisterBufferList, count, mInputBufList);
1081 if (err != kAudioHardwareNoError) {
1082 scprintf("get kAudioDevicePropertyRegisterBufferList error %4.4s\n", (char*)&err);
1088 *outNumSamplesPerCallback
= mHardwareBufferSize
/ outputStreamDesc
.mBytesPerFrame
;
1089 *outSampleRate
= outputStreamDesc
.mSampleRate
;
1091 if(mWorld
->mVerbosity
>= 1){
1092 scprintf("<-SC_CoreAudioDriver::Setup world %p\n", mWorld
);
1097 //check if using built-in output, and thus whether there could be headphone plug/un-plug issues
1098 //our assumption otherwise is that we don't respond, and SC will stay with the pre-arranged or default device, and not restart just because headphones switched
1100 // err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, 0);
1102 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
1103 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
1105 err
= AudioObjectGetPropertyDataSize(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
);
1107 if (err
!= kAudioHardwareNoError
) {
1108 scprintf("info kAudioDevicePropertyDeviceName error %4.4s %p\n", (char*)&err
, mOutputDevice
);
1112 char *outputname
= (char*)malloc(count
);
1113 const char *testname
= "Built-in Output";
1115 // err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &count, outputname);
1116 err
= AudioObjectGetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, &count
, outputname
);
1118 if (err
!= kAudioHardwareNoError
) {
1119 scprintf("get kAudioDevicePropertyDeviceName error %4.4s %p\n", (char*)&err
, mOutputDevice
);
1122 builtinoutputflag_
= 0;
1124 if (strcmp(testname
, outputname
) == 0) {
1125 builtinoutputflag_
= 1;
1129 // //check for an Aggregate Devices with a subdevice which is Built-in Output
1130 // //http://lists.apple.com/archives/coreaudio-api/2009/Oct/msg00182.html
1142 OSStatus appIOProc2 (AudioDeviceID inDevice, const AudioTimeStamp* inNow,
1143 const AudioBufferList* inInputData,
1144 const AudioTimeStamp* inInputTime,
1145 AudioBufferList* outOutputData,
1146 const AudioTimeStamp* inOutputTime,
1148 OSStatus appIOProc2 (AudioDeviceID inDevice, const AudioTimeStamp* inNow,
1149 const AudioBufferList* inInputData,
1150 const AudioTimeStamp* inInputTime,
1151 AudioBufferList* outOutputData,
1152 const AudioTimeStamp* inOutputTime,
1155 SC_CoreAudioDriver* def = (SC_CoreAudioDriver*)defptr;
1157 int64 oscTime = CoreAudioHostTimeToOSC(inOutputTime->mHostTime);
1159 AudioTimeStamp readTime;
1160 readTime.mSampleTime = inNow->mSampleTime - def->SafetyOffset() - def->NumSamplesPerCallback();
1161 readTime.mFlags = kAudioTimeStampSampleTimeValid;
1163 AudioDeviceRead(def->InputDevice(), &readTime, def->GetInputBufferList());
1165 def->Run(def->GetInputBufferList(), outOutputData, oscTime);
1167 return kAudioHardwareNoError;
1172 OSStatus
appIOProcSeparateIn (AudioDeviceID device
, const AudioTimeStamp
* inNow
,
1173 const AudioBufferList
* inInputData
,
1174 const AudioTimeStamp
* inInputTime
,
1175 AudioBufferList
* outOutputData
,
1176 const AudioTimeStamp
* inOutputTime
,
1179 SC_CoreAudioDriver
* def
= (SC_CoreAudioDriver
*)defptr
;
1181 // copy input data to driver's private buffer list
1183 for (i
=0; i
<inInputData
->mNumberBuffers
; i
++)
1185 memcpy(def
->mInputBufList
->mBuffers
[i
].mData
, inInputData
->mBuffers
[i
].mData
, inInputData
->mBuffers
[i
].mDataByteSize
);
1188 return kAudioHardwareNoError
;
1191 OSStatus
appIOProc (AudioDeviceID device
, const AudioTimeStamp
* inNow
,
1192 const AudioBufferList
* inInputData
,
1193 const AudioTimeStamp
* inInputTime
,
1194 AudioBufferList
* outOutputData
,
1195 const AudioTimeStamp
* inOutputTime
,
1198 SC_CoreAudioDriver
* def
= (SC_CoreAudioDriver
*)defptr
;
1199 int64 oscTime
= CoreAudioHostTimeToOSC(inOutputTime
->mHostTime
);
1201 double hostSecs
= (double)AudioConvertHostTimeToNanos(inOutputTime
->mHostTime
) * 1e-9;
1202 double sampleTime
= inOutputTime
->mSampleTime
;
1203 if (def
->mStartHostSecs
== 0) {
1204 def
->mStartHostSecs
= hostSecs
;
1205 def
->mStartSampleTime
= sampleTime
;
1207 double instSampleRate
= (sampleTime
- def
->mPrevSampleTime
)/(hostSecs
- def
->mPrevHostSecs
);
1208 double smoothSampleRate
= def
->mSmoothSampleRate
;
1209 smoothSampleRate
= smoothSampleRate
+ 0.002 * (instSampleRate
- smoothSampleRate
);
1210 def
->mOSCincrement
= (int64
)(def
->mOSCincrementNumerator
/ smoothSampleRate
);
1211 def
->mSmoothSampleRate
= smoothSampleRate
;
1214 double avgSampleRate
= (sampleTime
- def
->mStartSampleTime
)/(hostSecs
- def
->mStartHostSecs
);
1215 double jitter
= (smoothSampleRate
* (hostSecs
- def
->mPrevHostSecs
)) - (sampleTime
- def
->mPrevSampleTime
);
1216 double drift
= (smoothSampleRate
- def
->mSampleRate
) * (hostSecs
- def
->mStartHostSecs
);
1217 //if (fabs(jitter) > 0.01) {
1218 scprintf("avgSR %.6f smoothSR %.6f instSR %.6f jitter %.6f drift %.6f inc %lld\n",
1219 avgSampleRate
, smoothSampleRate
, instSampleRate
, jitter
, drift
, def
->mOSCincrement
);
1223 def
->mPrevHostSecs
= hostSecs
;
1224 def
->mPrevSampleTime
= sampleTime
;
1226 if (!def
->UseSeparateIO())
1228 def
->Run(inInputData
, outOutputData
, oscTime
);
1229 return kAudioHardwareNoError
;
1233 def
->Run(def
->mInputBufList
, outOutputData
, oscTime
);
1234 return kAudioHardwareNoError
;
1237 void SC_CoreAudioDriver::Run(const AudioBufferList
* inInputData
,
1238 AudioBufferList
* outOutputData
, int64 oscTime
)
1240 int64 systemTimeBefore
= AudioGetCurrentHostTime();
1241 World
*world
= mWorld
;
1244 int numSamplesPerCallback
= NumSamplesPerCallback();
1245 mOSCbuftime
= oscTime
;
1248 sc_SetDenormalFlags();
1252 /*if (mToEngine.HasData()) {
1253 scprintf("oscTime %.9f %.9f\n", oscTime*kOSCtoSecs, CoreAudioHostTimeToOSC(AudioGetCurrentHostTime())*kOSCtoSecs);
1255 mToEngine
.Perform();
1256 mOscPacketsToEngine
.Perform();
1258 int bufFrames
= world
->mBufLength
;
1259 int numBufs
= numSamplesPerCallback
/ bufFrames
;
1261 int numInputBuses
= world
->mNumInputs
;
1262 int numOutputBuses
= world
->mNumOutputs
;
1263 float* inputBuses
= world
->mAudioBus
+ world
->mNumOutputs
* bufFrames
;
1264 float* outputBuses
= world
->mAudioBus
;
1265 int32
* inputTouched
= world
->mAudioBusTouched
+ world
->mNumOutputs
;
1266 int32
* outputTouched
= world
->mAudioBusTouched
;
1267 int numInputStreams
= inInputData
? inInputData
->mNumberBuffers
: 0;
1268 int numOutputStreams
= outOutputData
? outOutputData
->mNumberBuffers
: 0;
1270 //static int go = 0;
1272 int64 oscInc
= mOSCincrement
;
1273 double oscToSamples
= mOSCtoSamples
;
1275 int bufFramePos
= 0;
1277 for (int i
= 0; i
< numBufs
; ++i
, world
->mBufCounter
++, bufFramePos
+= bufFrames
) {
1278 int32 bufCounter
= world
->mBufCounter
;
1280 // de-interleave input
1282 const AudioBuffer
* inInputDataBuffers
= inInputData
->mBuffers
;
1283 for (int s
= 0, b
= 0; b
<numInputBuses
&& s
< numInputStreams
; s
++) {
1284 const AudioBuffer
* buf
= inInputDataBuffers
+ s
;
1285 int nchan
= buf
->mNumberChannels
;
1287 float *busdata
= inputBuses
+ b
* bufFrames
;
1288 float *bufdata
= (float*)buf
->mData
+ bufFramePos
* nchan
;
1290 for (int k
=0; k
<bufFrames
; ++k
) {
1291 busdata
[k
] = bufdata
[k
];
1293 inputTouched
[b
] = bufCounter
;
1295 int minchan
= sc_min(nchan
, numInputBuses
- b
);
1296 for (int j
=0; j
<minchan
; ++j
, busdata
+= bufFrames
) {
1297 for (int k
=0, m
=j
; k
<bufFrames
; ++k
, m
+= nchan
) {
1298 busdata
[k
] = bufdata
[m
];
1300 inputTouched
[b
+j
] = bufCounter
;
1310 int64 nextTime
= oscTime
+ oscInc
;
1312 /*if (mScheduler.Ready(nextTime)) {
1313 double diff = (mScheduler.NextTime() - mOSCbuftime)*kOSCtoSecs;
1314 scprintf("rdy %.9f %.9f %.9f\n", (mScheduler.NextTime()-gStartupOSCTime) * kOSCtoSecs, (mOSCbuftime-gStartupOSCTime)*kOSCtoSecs, diff);
1317 while ((schedTime
= mScheduler
.NextTime()) <= nextTime
) {
1318 float diffTime
= (float)(schedTime
- oscTime
) * oscToSamples
+ 0.5;
1319 float diffTimeFloor
= floor(diffTime
);
1320 world
->mSampleOffset
= (int)diffTimeFloor
;
1321 world
->mSubsampleOffset
= diffTime
- diffTimeFloor
;
1323 if (world
->mSampleOffset
< 0) world
->mSampleOffset
= 0;
1324 else if (world
->mSampleOffset
>= world
->mBufLength
) world
->mSampleOffset
= world
->mBufLength
-1;
1326 SC_ScheduledEvent event
= mScheduler
.Remove();
1329 world
->mSampleOffset
= 0;
1330 world
->mSubsampleOffset
= 0.f
;
1334 // interleave output
1335 AudioBuffer
* outOutputDataBuffers
= outOutputData
->mBuffers
;
1336 for (int s
= 0, b
= 0; b
<numOutputBuses
&& s
< numOutputStreams
; s
++) {
1337 AudioBuffer
* buf
= outOutputDataBuffers
+ s
;
1338 int nchan
= buf
->mNumberChannels
;
1340 float *busdata
= outputBuses
+ b
* bufFrames
;
1341 float *bufdata
= (float*)buf
->mData
+ bufFramePos
* nchan
;
1343 if (outputTouched
[b
] == bufCounter
) {
1344 for (int k
=0; k
<bufFrames
; ++k
) {
1345 bufdata
[k
] = busdata
[k
];
1349 int minchan
= sc_min(nchan
, numOutputBuses
- b
);
1350 for (int j
=0; j
<minchan
; ++j
, busdata
+= bufFrames
) {
1351 if (outputTouched
[b
+j
] == bufCounter
) {
1352 for (int k
=0, m
=j
; k
<bufFrames
; ++k
, m
+= nchan
) {
1353 bufdata
[m
] = busdata
[k
];
1361 oscTime
= mOSCbuftime
= nextTime
;
1363 } catch (std::exception
& exc
) {
1364 scprintf("exception in real time: %s\n", exc
.what());
1366 scprintf("unknown exception in real time\n");
1368 int64 systemTimeAfter
= AudioGetCurrentHostTime();
1369 double calcTime
= (double)AudioConvertHostTimeToNanos(systemTimeAfter
- systemTimeBefore
) * 1e-9;
1370 double cpuUsage
= calcTime
* mBuffersPerSecond
* 100.;
1371 mAvgCPU
= mAvgCPU
+ 0.1 * (cpuUsage
- mAvgCPU
);
1372 if (cpuUsage
> mPeakCPU
|| --mPeakCounter
<= 0)
1374 mPeakCPU
= cpuUsage
;
1375 mPeakCounter
= mMaxPeakCounter
;
1378 mAudioSync
.Signal();
1384 //////////////////////////////////////////////////////////////////////////////////////////
1385 //////////////////////////////////////////////////////////////////////////////////////////
1386 //////////////////////////////////////////////////////////////////////////////////////////
1387 // These are not linked in yet, but we'll need to listen for the properties and stop/restart synthesis
1388 // if sample-rate, format, or device change.
1390 OSStatus
hardwareListenerProc ( AudioHardwarePropertyID inPropertyID
,
1393 OSStatus err
= noErr
;
1396 Boolean outWritable
;
1397 AudioDeviceID deviceID
;
1399 AudioObjectPropertyAddress propertyAddress
;
1401 propertyAddress
.mSelector
= kAudioHardwarePropertyDevices
;
1402 propertyAddress
.mScope
= kAudioObjectPropertyScopeGlobal
;
1403 propertyAddress
.mElement
= kAudioObjectPropertyElementMaster
;
1405 switch(inPropertyID
)
1407 case kAudioHardwarePropertyDefaultOutputDevice
:
1408 scprintf("%s\n", "***** HARDWARE NOTIFICATION - kAudioHardwarePropertyDefaultOutputDevice\r");
1410 //err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDefaultOutputDevice, &outSize, &outWritable);
1412 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultOutputDevice
;
1414 err
= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
);
1418 err
= AudioObjectIsPropertySettable(kAudioObjectSystemObject
, &propertyAddress
, &outWritable
);
1422 //err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &outSize, &deviceID);
1424 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
, &deviceID
);
1427 // err = AudioDeviceGetPropertyInfo(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, &outWritable);
1429 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
1431 err
= AudioObjectGetPropertyDataSize(deviceID
, &propertyAddress
, 0, NULL
, &outSize
);
1435 err
= AudioObjectIsPropertySettable(deviceID
, &propertyAddress
, &outWritable
);
1439 //err = AudioDeviceGetProperty(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, cStr);
1441 err
= AudioObjectGetPropertyData(deviceID
, &propertyAddress
, 0, NULL
, &outSize
, cStr
);
1449 case kAudioHardwarePropertyDefaultInputDevice
:
1450 scprintf("%s\n", "***** HARDWARE NOTIFICATION - kAudioHardwarePropertyDefaultInputDevice\r");
1451 // err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDefaultInputDevice, &outSize, &outWritable);
1453 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultInputDevice
;
1455 err
= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
);
1459 err
= AudioObjectIsPropertySettable(kAudioObjectSystemObject
, &propertyAddress
, &outWritable
);
1463 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &outSize, &deviceID);
1465 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
, &deviceID
);
1469 // err = AudioDeviceGetPropertyInfo(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, &outWritable);
1472 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
1474 err
= AudioObjectGetPropertyDataSize(deviceID
, &propertyAddress
, 0, NULL
, &outSize
);
1478 err
= AudioObjectIsPropertySettable(deviceID
, &propertyAddress
, &outWritable
);
1482 // err = AudioDeviceGetProperty(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, cStr);
1485 err
= AudioObjectGetPropertyData(deviceID
, &propertyAddress
, 0, NULL
, &outSize
, cStr
);
1493 case kAudioHardwarePropertyDefaultSystemOutputDevice
:
1494 scprintf("%s\n", "***** HARDWARE NOTIFICATION - kAudioHardwarePropertyDefaultSystemOutputDevice\r");
1495 //err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDefaultSystemOutputDevice, &outSize, &outWritable);
1497 propertyAddress
.mSelector
= kAudioHardwarePropertyDefaultSystemOutputDevice
;
1499 err
= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
);
1503 err
= AudioObjectIsPropertySettable(kAudioObjectSystemObject
, &propertyAddress
, &outWritable
);
1507 // err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, &outSize, &deviceID);
1509 err
= AudioObjectGetPropertyData(kAudioObjectSystemObject
, &propertyAddress
, 0, NULL
, &outSize
, &deviceID
);
1513 // err = AudioDeviceGetPropertyInfo(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, &outWritable);
1515 propertyAddress
.mSelector
= kAudioDevicePropertyDeviceName
;
1517 err
= AudioObjectGetPropertyDataSize(deviceID
, &propertyAddress
, 0, NULL
, &outSize
);
1521 err
= AudioObjectIsPropertySettable(deviceID
, &propertyAddress
, &outWritable
);
1525 // err = AudioDeviceGetProperty(deviceID, 0, false, kAudioDevicePropertyDeviceName, &outSize, cStr);
1527 err
= AudioObjectGetPropertyData(deviceID
, &propertyAddress
, 0, NULL
, &outSize
, cStr
);
1535 case kAudioHardwarePropertyDevices
:
1537 scprintf("%s\n", "***** HARDWARE NOTIFICATION - kAudioHardwarePropertyDevices\r");
1541 scprintf("%s\n", "***** HARDWARE NOTIFICATION - %4.4s\r", &inPropertyID
);
1551 OSStatus
AddDeviceListeners(AudioDeviceID inDevice
, void *inClientData
);
1553 OSStatus
AddHardwareListeners(void* inClientData
);
1554 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1555 OSStatus
AddHardwareListeners(void* inClientData
)
1557 OSStatus err
= noErr
;
1559 //non deprecated but requires AudiObject, bleargh
1560 //err= AudioObjectAddPropertyListener(AudioObject, kAudioHardwarePropertyDefaultOutputDevice, hardwareListenerProc, inClientData);
1562 err
= AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultOutputDevice
, hardwareListenerProc
, inClientData
);
1564 if (err
) return err
;
1566 err
= AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultInputDevice
, hardwareListenerProc
, inClientData
);
1567 if (err
) return err
;
1569 //doesn't matter? Only default looked at by SC?
1570 err
= AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultSystemOutputDevice
, hardwareListenerProc
, inClientData
);
1571 if (err
) return err
;
1573 err
= AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices
, hardwareListenerProc
, inClientData
);
1574 if (err
) return err
;
1579 bool SC_CoreAudioDriver::DriverStart()
1581 if(mWorld
->mVerbosity
>= 1){
1582 scprintf("->SC_CoreAudioDriver::DriverStart\n");
1584 OSStatus err
= kAudioHardwareNoError
;
1585 // AudioTimeStamp now;
1586 UInt32 propertySize
;
1588 AudioObjectPropertyAddress propertyAddress
;
1590 propertyAddress
.mSelector
= kAudioHardwarePropertyDevices
;
1591 propertyAddress
.mScope
= kAudioObjectPropertyScopeGlobal
;
1592 propertyAddress
.mElement
= kAudioObjectPropertyElementMaster
;
1594 if(mWorld
->mVerbosity
>= 1){
1595 scprintf("start UseSeparateIO?: %d\n", UseSeparateIO());
1599 if (UseSeparateIO()) {
1600 // err = AudioDeviceAddIOProc(mOutputDevice, appIOProc, (void *) this); // setup Out device with an IO proc
1602 err
= AudioDeviceCreateIOProcID(mOutputDevice
, appIOProc
, (void*) this, &mOutputID
);
1603 if (err
!= kAudioHardwareNoError
) {
1604 scprintf("AudioDeviceAddIOProc failed %s %d\n", &err
, (int)err
);
1607 // err = AudioDeviceAddIOProc(mInputDevice, appIOProcSeparateIn, (void *) this); // setup In device with an IO proc
1608 err
= AudioDeviceCreateIOProcID(mInputDevice
, appIOProcSeparateIn
, (void *)this, &mInputID
);
1610 if (err
!= kAudioHardwareNoError
) {
1611 scprintf("AudioDeviceAddIOProc failed %s %d\n", &err
, (int)err
);
1616 if (mWorld
->hw
->mInputStreamsEnabled
) {
1617 //err = AudioDeviceGetPropertyInfo(mInputDevice, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
1618 propertyAddress
.mSelector
= kAudioDevicePropertyIOProcStreamUsage
;
1619 propertyAddress
.mScope
= kAudioDevicePropertyScopeInput
;
1621 err
= AudioObjectGetPropertyDataSize(mInputDevice
, 0, NULL
, &propertyAddress
, &propertySize
);
1622 err
= AudioObjectIsPropertySettable(mInputDevice
, &propertyAddress
, &writable
);
1624 AudioHardwareIOProcStreamUsage
*su
= (AudioHardwareIOProcStreamUsage
*)malloc(propertySize
);
1625 su
->mIOProc
= (void*)appIOProcSeparateIn
;
1626 // err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, su);
1627 err
= AudioObjectGetPropertyData(mInputDevice
, 0, NULL
, &propertyAddress
, &propertySize
, su
);
1629 int len
= std::min(su
->mNumberStreams
, (UInt32
)strlen(mWorld
->hw
->mInputStreamsEnabled
));
1630 for (int i
=0; i
<len
; ++i
) {
1631 su
->mStreamIsOn
[i
] = mWorld
->hw
->mInputStreamsEnabled
[i
] == '1';
1633 // err = AudioDeviceSetProperty(mInputDevice, &now, 0, true, kAudioDevicePropertyIOProcStreamUsage, propertySize, su);
1635 err
= AudioObjectSetPropertyData(mInputDevice
, &propertyAddress
, 0, NULL
, propertySize
, su
);
1638 if (mWorld
->hw
->mOutputStreamsEnabled
) {
1639 //err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
1641 propertyAddress
.mSelector
= kAudioDevicePropertyIOProcStreamUsage
;
1642 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
1644 err
= AudioObjectGetPropertyDataSize(mInputDevice
, 0, NULL
, &propertyAddress
, &propertySize
);
1645 err
= AudioObjectIsPropertySettable(mInputDevice
, &propertyAddress
, &writable
);
1647 AudioHardwareIOProcStreamUsage
*su
= (AudioHardwareIOProcStreamUsage
*)malloc(propertySize
);
1648 su
->mIOProc
= (void*)appIOProc
;
1649 // err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, su);
1650 err
= AudioObjectGetPropertyData(mOutputDevice
, 0, NULL
, &propertyAddress
, &propertySize
, su
);
1652 int len
= std::min(su
->mNumberStreams
, (UInt32
)strlen(mWorld
->hw
->mOutputStreamsEnabled
));
1653 for (int i
=0; i
<len
; ++i
) {
1654 su
->mStreamIsOn
[i
] = mWorld
->hw
->mOutputStreamsEnabled
[i
] == '1';
1656 // err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyIOProcStreamUsage, propertySize, su);
1658 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, propertySize
, su
);
1661 err
= AudioDeviceStart(mInputDevice
, appIOProcSeparateIn
); // start playing sound through the device
1662 if (err
!= kAudioHardwareNoError
) {
1663 scprintf("AudioDeviceStart failed %d\n", (int)err
);
1667 err
= AudioDeviceStart(mOutputDevice
, appIOProc
); // start playing sound through the device
1668 if (err
!= kAudioHardwareNoError
) {
1669 scprintf("AudioDeviceStart failed %d\n", (int)err
);
1670 err
= AudioDeviceStop(mInputDevice
, appIOProcSeparateIn
); // stop playing sound through the device
1674 // err = AudioDeviceAddIOProc(mOutputDevice, appIOProc, (void *) this); // setup our device with an IO proc
1675 err
= AudioDeviceCreateIOProcID(mOutputDevice
, appIOProc
, (void *) this, &mOutputID
);
1677 if (err
!= kAudioHardwareNoError
) {
1678 scprintf("AudioDeviceAddIOProc failed %d\n", (int)err
);
1682 if (mWorld
->hw
->mInputStreamsEnabled
) {
1683 //err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
1684 propertyAddress
.mSelector
= kAudioDevicePropertyIOProcStreamUsage
;
1685 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
1687 err
= AudioObjectGetPropertyDataSize(mOutputDevice
, 0, NULL
, &propertyAddress
, &propertySize
);
1688 err
= AudioObjectIsPropertySettable(mOutputDevice
, &propertyAddress
, &writable
);
1690 AudioHardwareIOProcStreamUsage
*su
= (AudioHardwareIOProcStreamUsage
*)malloc(propertySize
);
1691 su
->mIOProc
= (void*)appIOProc
;
1692 //err = AudioDeviceGetProperty(mOutputDevice, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, su);
1693 err
= AudioObjectGetPropertyData(mOutputDevice
, 0, NULL
, &propertyAddress
, &propertySize
, su
);
1695 int len
= std::min(su
->mNumberStreams
, (UInt32
)strlen(mWorld
->hw
->mInputStreamsEnabled
));
1696 for (int i
=0; i
<len
; ++i
) {
1697 su
->mStreamIsOn
[i
] = mWorld
->hw
->mInputStreamsEnabled
[i
] == '1';
1699 //err = AudioDeviceSetProperty(mOutputDevice, &now, 0, true, kAudioDevicePropertyIOProcStreamUsage, propertySize, su);
1701 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, propertySize
, su
);
1704 if (mWorld
->hw
->mOutputStreamsEnabled
) {
1705 // err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
1706 propertyAddress
.mSelector
= kAudioDevicePropertyIOProcStreamUsage
;
1707 propertyAddress
.mScope
= kAudioDevicePropertyScopeOutput
;
1709 err
= AudioObjectGetPropertyDataSize(mOutputDevice
, 0, NULL
, &propertyAddress
, &propertySize
);
1710 err
= AudioObjectIsPropertySettable(mOutputDevice
, &propertyAddress
, &writable
);
1712 AudioHardwareIOProcStreamUsage
*su
= (AudioHardwareIOProcStreamUsage
*)malloc(propertySize
);
1713 su
->mIOProc
= (void*)appIOProc
;
1714 //err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, su);
1715 err
= AudioObjectGetPropertyData(mOutputDevice
, 0, NULL
, &propertyAddress
, &propertySize
, su
);
1717 int len
= std::min(su
->mNumberStreams
, (UInt32
)strlen(mWorld
->hw
->mOutputStreamsEnabled
));
1718 for (int i
=0; i
<len
; ++i
) {
1719 su
->mStreamIsOn
[i
] = mWorld
->hw
->mOutputStreamsEnabled
[i
] == '1';
1721 //err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyIOProcStreamUsage, propertySize, su);
1723 err
= AudioObjectSetPropertyData(mOutputDevice
, &propertyAddress
, 0, NULL
, propertySize
, su
);
1726 err
= AudioDeviceStart(mOutputDevice
, appIOProc
); // start playing sound through the device
1727 if (err
!= kAudioHardwareNoError
) {
1728 scprintf("AudioDeviceStart failed %d\n", (int)err
);
1733 scprintf("exception in SC_CoreAudioDriver::DriverStart\n");
1735 if(mWorld
->mVerbosity
>= 1){
1736 scprintf("<-SC_CoreAudioDriver::DriverStart\n");
1740 //http://lists.apple.com/archives/coreaudio-api/2010/Aug/msg00114.html
1741 CFRunLoopRef theRunLoop
= NULL
;
1742 AudioObjectPropertyAddress theAddress
= { kAudioHardwarePropertyRunLoop
, kAudioObjectPropertyScopeGlobal
, kAudioObjectPropertyElementMaster
};
1743 AudioObjectSetPropertyData(kAudioObjectSystemObject
, &theAddress
, 0, NULL
, sizeof(CFRunLoopRef
), &theRunLoop
);
1745 //for now no spotting of hardware changes, assumption is that ServerOptions inviolate. However, if a device was unplugged, could react to loss of that device
1746 //by switching to system default?
1747 //AddHardwareListeners(NULL);
1748 //note that the number of listeners is stripped down to only one for now, to react to headphone swaps in the case of Built-in Output
1749 AddDeviceListeners(mOutputDevice
, this);
1755 bool SC_CoreAudioDriver::StopStart() {
1757 bool test
= DriverStop();
1759 bool test2
= DriverStart();
1760 return test
&& test2
;
1764 bool SC_CoreAudioDriver::DriverStop()
1766 if(mWorld
->mVerbosity
>= 1){
1767 scprintf("->SC_CoreAudioDriver::DriverStop\n");
1769 OSStatus err
= kAudioHardwareNoError
;
1771 if (UseSeparateIO()) {
1772 err
= AudioDeviceStop(mOutputDevice
, appIOProc
);
1773 if (err
!= kAudioHardwareNoError
) {
1774 scprintf("AudioDeviceStop A failed %p\n", err
);
1777 // err = AudioDeviceRemoveIOProc(mOutputDevice, appIOProc);
1778 err
= AudioDeviceDestroyIOProcID(mOutputDevice
, mOutputID
);
1779 if (err
!= kAudioHardwareNoError
) {
1780 scprintf("AudioDeviceRemoveIOProc A failed %p\n", err
);
1784 err
= AudioDeviceStop(mInputDevice
, appIOProcSeparateIn
);
1785 if (err
!= kAudioHardwareNoError
) {
1786 scprintf("AudioDeviceStop A failed %p\n", err
);
1790 // err = AudioDeviceRemoveIOProc(mInputDevice, appIOProcSeparateIn);
1791 err
= AudioDeviceDestroyIOProcID(mOutputDevice
, mInputID
);
1793 if (err
!= kAudioHardwareNoError
) {
1794 scprintf("AudioDeviceRemoveIOProc A failed %p\n", err
);
1798 err
= AudioDeviceStop(mOutputDevice
, appIOProc
);
1799 if (err
!= kAudioHardwareNoError
) {
1800 scprintf("AudioDeviceStop B failed %p\n", err
);
1804 // err = AudioDeviceRemoveIOProc(mOutputDevice, appIOProc);
1805 err
= AudioDeviceDestroyIOProcID(mOutputDevice
, mOutputID
);
1807 if (err
!= kAudioHardwareNoError
) {
1808 scprintf("AudioDeviceRemoveIOProc B failed %p\n", err
);
1812 if(mWorld
->mVerbosity
>= 1){
1813 scprintf("<-SC_CoreAudioDriver::DriverStop\n");
1819 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1820 // Listen for Device Properties and update interface and globals
1821 OSStatus
deviceListenerProc ( AudioDeviceID inDevice
,
1824 AudioDevicePropertyID inPropertyID
,
1827 OSStatus err
= noErr
;
1829 SC_CoreAudioDriver
* coredriver
= (SC_CoreAudioDriver
*) inClientData
;
1831 switch(inPropertyID
)
1833 // case kAudioDevicePropertyBufferSize:
1834 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyBufferSize\r");
1835 // outSize = sizeof(UInt32);
1836 // err = AudioDeviceGetProperty(inDevice, 0, 0, kAudioDevicePropertyBufferSize, &outSize, &theUIntData);
1840 // case kAudioDevicePropertyBufferFrameSize:
1841 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyBufferFrameSize\r");
1842 // outSize = sizeof(UInt32);
1843 // err = AudioDeviceGetProperty(inDevice, 0, 0, kAudioDevicePropertyBufferFrameSize, &outSize, &theUIntData);
1847 // case kAudioDevicePropertyBufferSizeRange:
1849 // AudioValueRange range;
1851 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyBufferSizeRange\r");
1852 // outSize = sizeof(AudioValueRange);
1853 // err = AudioDeviceGetProperty(inDevice, 0, isInput, kAudioDevicePropertyBufferSizeRange, &outSize, &range);
1857 // case kAudioDevicePropertyStreamFormat:
1858 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyStreamFormat\r");
1861 // case kAudioDevicePropertyDeviceIsRunning:
1862 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyDeviceIsRunning\r");
1863 // outSize = sizeof(UInt32);
1864 // err = AudioDeviceGetProperty(inDevice, inLine, isInput, kAudioDevicePropertyDeviceIsRunning, &outSize, &theUIntData);
1866 // //when change device get up to four messages:
1867 // //isInput ==NO or YES theUIntData= 0 or 1 from old and possibly new device (ieheadphone swap)
1873 // case kAudioDevicePropertyVolumeScalar:
1874 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyVolumeScalar\r");
1875 // outSize = sizeof(Float32);
1876 // err = AudioDeviceGetProperty(inDevice, inLine, isInput, kAudioDevicePropertyVolumeScalar, &outSize, &vol);
1879 // case kAudioDevicePropertyMute:
1880 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyMute\r");
1881 // outSize = sizeof(UInt32);
1882 // err = AudioDeviceGetProperty(inDevice, inLine, isInput, kAudioDevicePropertyMute, &outSize, &mute);
1885 // case kAudioDevicePropertyPlayThru:
1886 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyPlayThru\r");
1887 // outSize = sizeof(UInt32);
1888 // err = AudioDeviceGetProperty(inDevice, inLine, isInput, kAudioDevicePropertyPlayThru, &outSize, &playThru);
1892 // case kAudioDevicePropertyDeviceIsAlive:
1893 // scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyDeviceIsAlive\r");
1894 // outSize = sizeof(UInt32);
1895 // err = AudioDeviceGetProperty(inDevice, 0, false, kAudioDevicePropertyDeviceIsAlive, &outSize, &tLong);
1899 case kAudioDevicePropertyDataSource
:
1900 //Don't print anything
1901 //scprintf("%s\n", "***** DEVICE NOTIFICATION - kAudioDevicePropertyDataSource\r");
1903 // match the source to one of the available sources and return the index of that source
1904 //SetControlValue(control, (chan->vol) * 100);
1906 //will get this message anyway even if don't have built-in output seleected.
1907 //so need to react based on whether current output IS built-in output. Annoyingly, headphone unplugging/plugging also sends default and system output + default input change hardware messages
1908 //swapping to new driver
1909 if (coredriver
->builtinoutputflag_
==1)
1910 coredriver
->StopStart();
1916 // scprintf("%s\n", "***** DEVICE NOTIFICATION - %4.4s\r", &inPropertyID);
1923 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1924 OSStatus
streamListenerProc ( AudioStreamID inStream
,
1926 AudioDevicePropertyID inPropertyID
,
1929 OSStatus err
= noErr
;
1931 switch(inPropertyID
)
1933 case kAudioStreamPropertyPhysicalFormat
:
1934 scprintf("%s\n", "***** STREAM NOTIFICATION - kAudioStreamPropertyPhysicalFormat\r");
1937 case kAudioDevicePropertyStreamFormat
:
1938 scprintf("%s\n", "***** STREAM NOTIFICATION - kAudioDevicePropertyStreamFormat\r");
1950 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1951 OSStatus
AddStreamListeners (AudioDeviceID inDevice
, AudioDevicePropertyID inPropertyID
, Boolean isInput
, void *inClientData
);
1953 OSStatus
AddDeviceListeners(AudioDeviceID inDevice
, void *inClientData
)
1955 OSStatus err
= noErr
;
1957 //ONLY REACTING TO HEADPHONE SWAPS FOR NOW
1961 // // kAudioDevicePropertyBufferSize
1962 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyBufferSize, deviceListenerProc, inClientData);
1963 // if (err) return err;
1965 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyBufferSize, deviceListenerProc, inClientData);
1966 // if (err) return err;
1969 // // kAudioDevicePropertyBufferFrameSize
1970 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyBufferFrameSize, deviceListenerProc, inClientData);
1971 // if (err) return err;
1973 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyBufferFrameSize, deviceListenerProc, inClientData);
1974 // if (err) return err;
1976 // // kAudioDevicePropertyDeviceIsRunning
1977 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyDeviceIsRunning, deviceListenerProc, inClientData);
1978 // if (err) return err;
1980 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyDeviceIsRunning, deviceListenerProc, inClientData);
1981 // if (err) return err;
1984 // for (i = 0; i <= deviceInfo->totalOutputChannels; i++)
1986 // // kAudioDevicePropertyVolumeScalar output
1987 // err = AudioDeviceAddPropertyListener(inDevice, i, false, kAudioDevicePropertyVolumeScalar, deviceListenerProc, inClientData);
1988 // if (err) return err;
1990 // // kAudioDevicePropertyVolumeMute output
1991 // err = AudioDeviceAddPropertyListener(inDevice, i, false, kAudioDevicePropertyMute, deviceListenerProc, inClientData);
1992 // if (err) return err;
1995 // for (i = 0; i <= deviceInfo->totalInputChannels; i++)
1997 // // kAudioDevicePropertyVolumeScalar input
1998 // err = AudioDeviceAddPropertyListener(inDevice, i, true, kAudioDevicePropertyVolumeScalar, deviceListenerProc, inClientData);
1999 // if (err) return err;
2001 // // kAudioDevicePropertyVolumeMute input
2002 // err = AudioDeviceAddPropertyListener(inDevice, i, true, kAudioDevicePropertyMute, deviceListenerProc, inClientData);
2003 // if (err) return err;
2005 // // kAudioDevicePropertyPlayThru input
2006 // err = AudioDeviceAddPropertyListener(inDevice, i, true, kAudioDevicePropertyPlayThru, deviceListenerProc, inClientData);
2007 // if (err) return err;
2011 // // kAudioDevicePropertyDeviceIsAlive
2012 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyDeviceIsAlive, deviceListenerProc, inClientData);
2013 // if (err) return err;
2015 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyDeviceIsAlive, deviceListenerProc, inClientData);
2016 // if (err) return err;
2019 // // kAudioDevicePropertyStreamFormat
2020 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyStreamFormat, deviceListenerProc, inClientData);
2021 // if (err) return err;
2023 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyStreamFormat, deviceListenerProc, inClientData);
2024 // if (err) return err;
2026 // // kAudioDevicePropertyBufferSizeRange
2027 // err = AudioDeviceAddPropertyListener(inDevice, 0, false, kAudioDevicePropertyBufferSizeRange, deviceListenerProc, inClientData);
2028 // if (err) return err;
2030 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyBufferSizeRange, deviceListenerProc, inClientData);
2031 // if (err) return err;
2033 //kAudioDevicePropertyDataSource
2034 err
= AudioDeviceAddPropertyListener(inDevice
, 0, false, kAudioDevicePropertyDataSource
, deviceListenerProc
, inClientData
);
2035 if (err
) return err
;
2037 // err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyDataSource, deviceListenerProc, inClientData);
2038 // if (err) return err;
2041 //AddStreamListeners (inDevice, kAudioStreamPropertyPhysicalFormat, false, inClientData);
2043 //AddStreamListeners (inDevice, kAudioStreamPropertyPhysicalFormat, true, inClientData);
2050 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2051 OSStatus
AddStreamListeners (AudioDeviceID inDevice
, AudioDevicePropertyID inPropertyID
, Boolean isInput
, void *inClientData
)
2053 OSStatus err
= noErr
;
2056 Boolean outWritable
;
2057 AudioStreamID
*streamList
= nil
;
2059 err
= AudioDeviceGetPropertyInfo(inDevice
, 0, isInput
, kAudioDevicePropertyStreams
, &outSize
, &outWritable
);
2062 streamList
= (AudioStreamID
*)malloc(outSize
);
2063 err
= AudioDeviceGetProperty(inDevice
, 0, isInput
, kAudioDevicePropertyStreams
, &outSize
, streamList
);
2066 for (count
= 0; count
< (outSize
/ sizeof(AudioStreamID
)); count
++)
2068 err
= AudioStreamAddPropertyListener(streamList
[count
], 0, inPropertyID
, streamListenerProc
, inClientData
);
2069 if (err
) return err
;
2072 if (streamList
!= nil
)
2082 #endif // SC_AUDIO_API_COREAUDIO
2087 // =====================================================================
2088 // Audio driver (CoreAudioIPHONE)
2090 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIOIPHONE
2091 SC_iCoreAudioDriver::SC_iCoreAudioDriver(struct World
*inWorld
)
2092 : SC_AudioDriver(inWorld
)
2097 SC_iCoreAudioDriver::~SC_iCoreAudioDriver()
2102 OSStatus appIOProc2 (AudioDeviceID inDevice, const AudioTimeStamp* inNow,
2103 const AudioBufferList* inInputData,
2104 const AudioTimeStamp* inInputTime,
2105 AudioBufferList* outOutputData,
2106 const AudioTimeStamp* inOutputTime,
2108 OSStatus appIOProc2 (AudioDeviceID inDevice, const AudioTimeStamp* inNow,
2109 const AudioBufferList* inInputData,
2110 const AudioTimeStamp* inInputTime,
2111 AudioBufferList* outOutputData,
2112 const AudioTimeStamp* inOutputTime,
2115 SC_CoreAudioDriver* def = (SC_CoreAudioDriver*)defptr;
2117 int64 oscTime = CoreAudioHostTimeToOSC(inOutputTime->mHostTime);
2119 AudioTimeStamp readTime;
2120 readTime.mSampleTime = inNow->mSampleTime - def->SafetyOffset() - def->NumSamplesPerCallback();
2121 readTime.mFlags = kAudioTimeStampSampleTimeValid;
2123 AudioDeviceRead(def->InputDevice(), &readTime, def->GetInputBufferList());
2125 def->Run(def->GetInputBufferList(), outOutputData, oscTime);
2127 return kAudioHardwareNoError;
2132 OSStatus
InputCallback(void *inRefCon
, AudioUnitRenderActionFlags
*ioActionFlags
, const AudioTimeStamp
*inTimeStamp
, UInt32 inBusNumber
, UInt32 inNumberFrames
, AudioBufferList
*ioData
)
2134 SC_iCoreAudioDriver
*driver
= (SC_iCoreAudioDriver
*) inRefCon
;
2136 if (driver
->receivedIn
)
2138 //printf("exit input with no data \n");
2142 OSStatus ret
= AudioUnitRender(driver
->inputUnit
, ioActionFlags
, inTimeStamp
, inBusNumber
, inNumberFrames
, driver
->buflist
);
2145 //printf("no input !\n");
2148 driver
->receivedIn
= 1;
2153 OSStatus
RenderCallback(void *inRefCon
, AudioUnitRenderActionFlags
*ioActionFlags
, const AudioTimeStamp
*inTimeStamp
, UInt32 inBusNumber
, UInt32 inNumberFrames
, AudioBufferList
*ioData
)
2155 SC_iCoreAudioDriver
*driver
= (SC_iCoreAudioDriver
*) inRefCon
;
2158 if (!driver
->receivedIn
)
2160 //printf("exit output with no data \n");
2165 //float *fbuffer = (float *) driver->converter_buffer;
2168 for (i
=0; i
<inNumberFrames
; i
++)
2170 signed short s
= ((signed short *)driver
->buflist
->mBuffers
[0].mData
)[i
];
2171 int k
= s
+ 0x43c00000;
2172 float f
= *((float *) &k
);
2173 ((float *)driver
->floatInputList
->mBuffers
[0].mData
)[i
] = f
- 384.0f
;
2176 int64 oscTime
= GetCurrentOSCTime();
2177 //driver->Run(driver->floatInputList, driver->floatOutputList, oscTime);
2178 driver
->Run(driver
->floatInputList
, ioData
, oscTime
);
2180 for (i
=0; i
<inNumberFrames
; i
++)
2182 float f1
= ((float *)ioData
->mBuffers
[0].mData
)[i
];
2183 float f2
= ((float *)ioData
->mBuffers
[1].mData
)[i
];
2184 ((int *) ioData
->mBuffers
[0].mData
)[i
] = (int) (f1
*16777216);
2185 ((int *) ioData
->mBuffers
[1].mData
)[i
] = (int) (f2
*16777216);
2190 unsigned long size = 2*1024*sizeof(unsigned long);
2191 OSStatus ret = AudioConverterConvertBuffer(driver->converter_in_to_F32, driver->buflist->mBuffers[0].mDataByteSize, driver->buflist->mBuffers[0].mData, &size, driver->converter_buffer);
2194 printf("couldn't convert !\n");
2199 for (i=0; i<inNumberFrames; i++)
2201 ((int *)ioData->mBuffers[0].mData)[i] = ((int *)ioData->mBuffers[1].mData)[i] = driver->converter_buffer[2*i];
2204 driver
->receivedIn
= 0;
2210 void SC_iCoreAudioDriver::Run(const AudioBufferList
* inInputData
,
2211 AudioBufferList
* outOutputData
, int64 oscTime
)
2213 int64 systemTimeBefore
= GetMicroseconds();
2215 World
*world
= mWorld
;
2218 int numSamplesPerCallback
= NumSamplesPerCallback();
2219 mOSCbuftime
= oscTime
;
2222 sc_SetDenormalFlags();
2227 mToEngine
.Perform();
2228 mOscPacketsToEngine
.Perform();
2229 //printf("mOscPacketsToEngine : %d micros\n", (int) (GetMicroseconds()-systemTimeBefore));
2231 int bufFrames
= world
->mBufLength
;
2232 int numBufs
= numSamplesPerCallback
/ bufFrames
;
2234 int numInputBuses
= world
->mNumInputs
;
2235 int numOutputBuses
= world
->mNumOutputs
;
2236 float* inputBuses
= world
->mAudioBus
+ world
->mNumOutputs
* bufFrames
;
2237 float* outputBuses
= world
->mAudioBus
;
2238 int32
* inputTouched
= world
->mAudioBusTouched
+ world
->mNumOutputs
;
2239 int32
* outputTouched
= world
->mAudioBusTouched
;
2240 int numInputStreams
= inInputData
? inInputData
->mNumberBuffers
: 0;
2241 int numOutputStreams
= outOutputData
? outOutputData
->mNumberBuffers
: 0;
2243 //static int go = 0;
2245 int64 oscInc
= mOSCincrement
;
2246 double oscToSamples
= mOSCtoSamples
;
2248 int bufFramePos
= 0;
2250 for (int i
= 0; i
< numBufs
; ++i
, world
->mBufCounter
++, bufFramePos
+= bufFrames
) {
2251 int32 bufCounter
= world
->mBufCounter
;
2253 // de-interleave input
2255 const AudioBuffer
* inInputDataBuffers
= inInputData
->mBuffers
;
2256 for (int s
= 0, b
= 0; b
<numInputBuses
&& s
< numInputStreams
; s
++) {
2257 const AudioBuffer
* buf
= inInputDataBuffers
+ s
;
2258 int nchan
= buf
->mNumberChannels
;
2260 float *busdata
= inputBuses
+ b
* bufFrames
;
2261 float *bufdata
= (float*)buf
->mData
+ bufFramePos
* nchan
;
2265 vcopy(busdata
, bufdata
, bufFrames
);
2267 for (int k
=0; k
<bufFrames
; ++k
)
2269 busdata
[k
] = bufdata
[k
];
2272 inputTouched
[b
] = bufCounter
;
2274 int minchan
= sc_min(nchan
, numInputBuses
- b
);
2275 for (int j
=0; j
<minchan
; ++j
, busdata
+= bufFrames
) {
2276 for (int k
=0, m
=j
; k
<bufFrames
; ++k
, m
+= nchan
) {
2277 busdata
[k
] = bufdata
[m
];
2279 inputTouched
[b
+j
] = bufCounter
;
2289 int64 nextTime
= oscTime
+ oscInc
;
2291 while ((schedTime
= mScheduler
.NextTime()) <= nextTime
) {
2292 float diffTime
= (float)(schedTime
- oscTime
) * oscToSamples
+ 0.5;
2293 float diffTimeFloor
= floor(diffTime
);
2294 world
->mSampleOffset
= (int)diffTimeFloor
;
2295 world
->mSubsampleOffset
= diffTime
- diffTimeFloor
;
2297 if (world
->mSampleOffset
< 0) world
->mSampleOffset
= 0;
2298 else if (world
->mSampleOffset
>= world
->mBufLength
) world
->mSampleOffset
= world
->mBufLength
-1;
2300 SC_ScheduledEvent event
= mScheduler
.Remove();
2303 world
->mSampleOffset
= 0;
2304 world
->mSubsampleOffset
= 0.f
;
2306 //int64 now = GetMicroseconds();
2310 //printf("world run : %fms\n", (float) (GetMicroseconds()-now)/1000);
2313 // interleave output
2314 AudioBuffer
* outOutputDataBuffers
= outOutputData
->mBuffers
;
2315 for (int s
= 0, b
= 0; b
<numOutputBuses
&& s
< numOutputStreams
; s
++) {
2316 AudioBuffer
* buf
= outOutputDataBuffers
+ s
;
2317 int nchan
= buf
->mNumberChannels
;
2319 float *busdata
= outputBuses
+ b
* bufFrames
;
2320 float *bufdata
= (float*)buf
->mData
+ bufFramePos
* nchan
;
2323 if (outputTouched
[b
] == bufCounter
)
2326 vcopy(bufdata
, busdata
, bufFrames
);
2328 for (int k
=0; k
<bufFrames
; ++k
)
2330 bufdata
[k
] = busdata
[k
];
2335 int minchan
= sc_min(nchan
, numOutputBuses
- b
);
2336 for (int j
=0; j
<minchan
; ++j
, busdata
+= bufFrames
) {
2337 if (outputTouched
[b
+j
] == bufCounter
) {
2338 for (int k
=0, m
=j
; k
<bufFrames
; ++k
, m
+= nchan
) {
2339 bufdata
[m
] = busdata
[k
];
2347 oscTime
= mOSCbuftime
= nextTime
;
2349 } catch (std::exception
& exc
) {
2350 scprintf("exception in real time: %s\n", exc
.what());
2352 scprintf("unknown exception in real time\n");
2355 int64 systemTimeAfter
= GetMicroseconds();
2356 double calcTime
= (double)(systemTimeAfter
- systemTimeBefore
) * 1e-6;
2357 double cpuUsage
= calcTime
* mBuffersPerSecond
* 100.;
2358 mAvgCPU
= mAvgCPU
+ 0.1 * (cpuUsage
- mAvgCPU
);
2359 if (cpuUsage
> mPeakCPU
|| --mPeakCounter
<= 0)
2361 mPeakCPU
= cpuUsage
;
2362 mPeakCounter
= mMaxPeakCounter
;
2365 mAudioSync
.Signal();
2372 OSStatus appIOProc (AudioDeviceID device, const AudioTimeStamp* inNow,
2373 const AudioBufferList* inInputData,
2374 const AudioTimeStamp* inInputTime,
2375 AudioBufferList* outOutputData,
2376 const AudioTimeStamp* inOutputTime,
2379 SC_CoreAudioDriver* def = (SC_CoreAudioDriver*)defptr;
2380 int64 oscTime = CoreAudioHostTimeToOSC(inOutputTime->mHostTime);
2382 double hostSecs = (double)AudioConvertHostTimeToNanos(inOutputTime->mHostTime) * 1e-9;
2383 double sampleTime = inOutputTime->mSampleTime;
2384 if (def->mStartHostSecs == 0) {
2385 def->mStartHostSecs = hostSecs;
2386 def->mStartSampleTime = sampleTime;
2388 double instSampleRate = (sampleTime - def->mPrevSampleTime)/(hostSecs - def->mPrevHostSecs);
2389 double smoothSampleRate = def->mSmoothSampleRate;
2390 smoothSampleRate = smoothSampleRate + 0.002 * (instSampleRate - smoothSampleRate);
2391 def->mOSCincrement = (int64)(def->mOSCincrementNumerator / smoothSampleRate);
2392 def->mSmoothSampleRate = smoothSampleRate;
2395 double avgSampleRate = (sampleTime - def->mStartSampleTime)/(hostSecs - def->mStartHostSecs);
2396 double jitter = (smoothSampleRate * (hostSecs - def->mPrevHostSecs)) - (sampleTime - def->mPrevSampleTime);
2397 double drift = (smoothSampleRate - def->mSampleRate) * (hostSecs - def->mStartHostSecs);
2398 //if (fabs(jitter) > 0.01) {
2399 scprintf("avgSR %.6f smoothSR %.6f instSR %.6f jitter %.6f drift %.6f inc %lld\n",
2400 avgSampleRate, smoothSampleRate, instSampleRate, jitter, drift, def->mOSCincrement);
2404 def->mPrevHostSecs = hostSecs;
2405 def->mPrevSampleTime = sampleTime;
2407 if (!def->UseSeparateIO())
2409 def->Run(inInputData, outOutputData, oscTime);
2410 return kAudioHardwareNoError;
2414 def->Run(lastInputData, outOutputData, oscTime);
2417 return kAudioHardwareNoError;
2422 void AudioSessionInterruptionCbk(void *inClientData
, UInt32 inInterruptionState
)
2427 bool SC_iCoreAudioDriver::DriverSetup(int* outNumSamplesPerCallback
, double* outSampleRate
)
2429 AudioSessionInitialize(0, 0, AudioSessionInterruptionCbk
, 0);
2430 unsigned long category
= kAudioSessionCategory_PlayAndRecord
;
2432 UInt32 micInput
, micInputSize
= sizeof(&micInput
);
2433 AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable
, &micInputSize
, &micInput
);
2435 category
= kAudioSessionCategory_MediaPlayback
;
2436 scprintf("SC_IPHONE: WARNING - no audio input available\n");
2439 AudioSessionSetProperty(kAudioSessionProperty_AudioCategory
, sizeof(category
), &category
);
2441 if (mPreferredHardwareBufferFrameSize
)
2443 Float32 preferredBufferSize
= (float) mPreferredHardwareBufferFrameSize
/44100.f
;
2444 AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration
, sizeof(preferredBufferSize
), &preferredBufferSize
);
2447 AudioSessionSetActive(true);
2449 float actualBufferDuration
;
2450 UInt32 size
= sizeof(actualBufferDuration
);
2451 AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration
, &size
, &actualBufferDuration
);
2453 *outNumSamplesPerCallback
= (int) (actualBufferDuration
*44100.f
+0.5f
);
2454 *outSampleRate
= 44100;
2456 AudioComponentDescription desc
;
2457 desc
.componentType
= kAudioUnitType_Output
;
2458 desc
.componentSubType
= kAudioUnitSubType_RemoteIO
;
2459 desc
.componentManufacturer
= kAudioUnitManufacturer_Apple
;
2464 OSStatus ret
= AUGraphAddNode(graph
, &desc
, &node
);
2465 //printf("node : %d\n", node);
2468 ret
= AUGraphNodeInfo(graph
, node
, &desc
, &unit
);
2469 //printf("%d\n", unit);
2473 AudioComponent remoteIOComp
= AudioComponentFindNext(0, &desc
);
2474 if (AudioComponentInstanceNew(remoteIOComp
, &inputUnit
)!=noErr
)
2476 //printf("error instantiating RemoteIO\n");
2479 //printf("instantiated : %d\n", inputUnit);
2482 ret
= AudioUnitSetProperty(inputUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Input
, 1, &enableIO
, sizeof(enableIO
));
2485 //printf("can't set input : %d\n", ret);
2489 ret
= AudioUnitSetProperty(inputUnit
, kAudioOutputUnitProperty_EnableIO
, kAudioUnitScope_Output
, 0, &enableIO
, sizeof(enableIO
));
2492 //printf("can't set output : %d\n", ret);
2496 AudioUnitInitialize(inputUnit
);
2498 unsigned long bufferSizeBytes
= 1024 * sizeof(unsigned long);
2499 buflist
= (AudioBufferList
*) malloc(sizeof(AudioBufferList
));
2500 buflist
->mNumberBuffers
= 1;
2501 buflist
->mBuffers
[0].mDataByteSize
= bufferSizeBytes
;
2502 buflist
->mBuffers
[0].mData
= malloc(bufferSizeBytes
);
2503 buflist
->mBuffers
[0].mNumberChannels
= 1;
2505 floatInputList
= (AudioBufferList
*) malloc(sizeof(AudioBufferList
));
2506 floatInputList
->mNumberBuffers
= 1;
2507 floatInputList
->mBuffers
[0].mDataByteSize
= bufferSizeBytes
;
2508 floatInputList
->mBuffers
[0].mData
= malloc(bufferSizeBytes
);
2509 floatInputList
->mBuffers
[0].mNumberChannels
= 1;
2512 floatOutputList = (AudioBufferList *) malloc(sizeof(AudioBufferList)+sizeof(AudioBuffer));
2513 floatOutputList->mNumberBuffers = 2;
2514 floatOutputList->mBuffers[0].mDataByteSize = bufferSizeBytes;
2515 floatOutputList->mBuffers[0].mData = malloc(bufferSizeBytes);
2516 floatOutputList->mBuffers[0].mNumberChannels = 1;
2517 floatOutputList->mBuffers[1].mDataByteSize = bufferSizeBytes;
2518 floatOutputList->mBuffers[1].mData = malloc(bufferSizeBytes);
2519 floatOutputList->mBuffers[1].mNumberChannels = 1;
2522 AURenderCallbackStruct inputStruct
;
2523 inputStruct
.inputProc
= InputCallback
;
2524 inputStruct
.inputProcRefCon
= this;
2525 ret
= AudioUnitSetProperty(inputUnit
, kAudioOutputUnitProperty_SetInputCallback
, kAudioUnitScope_Input
, 0, &inputStruct
, sizeof(inputStruct
));
2527 AURenderCallbackStruct renderStruct
;
2528 renderStruct
.inputProc
= RenderCallback
;
2529 renderStruct
.inputProcRefCon
= this;
2530 ret
= AudioUnitSetProperty(unit
, kAudioUnitProperty_SetRenderCallback
, kAudioUnitScope_Input
, 0, &renderStruct
, sizeof(renderStruct
));
2532 AudioStreamBasicDescription streamFormat
;
2533 streamFormat
.mFormatID
= kAudioFormatLinearPCM
;
2534 streamFormat
.mFormatFlags
=
2535 kAudioFormatFlagIsSignedInteger
2536 | kAudioFormatFlagsNativeEndian
2537 | kLinearPCMFormatFlagIsNonInterleaved
2538 | (24 << kLinearPCMFormatFlagsSampleFractionShift
);
2539 streamFormat
.mSampleRate
= 44100;
2540 streamFormat
.mBitsPerChannel
= 32;
2541 streamFormat
.mChannelsPerFrame
= 2;
2542 streamFormat
.mFramesPerPacket
= 1;
2543 streamFormat
.mBytesPerFrame
= ( streamFormat
.mBitsPerChannel
/ 8 );
2544 streamFormat
.mBytesPerPacket
= streamFormat
.mBytesPerFrame
*
2545 streamFormat
.mFramesPerPacket
;
2547 ret
= AudioUnitSetProperty(unit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Input
, 0, &streamFormat
, sizeof(streamFormat
));
2550 AudioStreamBasicDescription audioFormat
;
2551 audioFormat
.mSampleRate
= 44100.00;
2552 audioFormat
.mFormatID
= kAudioFormatLinearPCM
;
2553 audioFormat
.mFormatFlags
= kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagIsPacked
;
2554 audioFormat
.mFramesPerPacket
= 1;
2555 audioFormat
.mChannelsPerFrame
= 1;
2556 audioFormat
.mBitsPerChannel
= 16;
2557 audioFormat
.mBytesPerPacket
= 2;
2558 audioFormat
.mBytesPerFrame
= 2;
2559 ret
= AudioUnitSetProperty(inputUnit
, kAudioUnitProperty_StreamFormat
, kAudioUnitScope_Output
, 1, &audioFormat
, sizeof(audioFormat
));
2563 AudioStreamBasicDescription d;
2565 ret = AudioUnitGetProperty(unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &d, &size);
2567 AudioStreamBasicDescription inputFormat;
2568 AudioStreamBasicDescription outputFormat;
2569 AudioStreamBasicDescription f32Format;
2571 size = sizeof(AudioStreamBasicDescription);
2572 ret = AudioUnitGetProperty(inputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &inputFormat, &size);
2573 ret = AudioUnitGetProperty(inputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &inputFormat, &size);
2574 ret = AudioUnitGetProperty(inputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &outputFormat, &size);
2575 ret = AudioUnitGetProperty(inputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &outputFormat, &size);
2577 outputFormat.mChannelsPerFrame = 1;
2579 f32Format.mSampleRate = inputFormat.mSampleRate;
2580 f32Format.mFormatID = inputFormat.mFormatID;
2581 f32Format.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
2582 f32Format.mBytesPerPacket = 4;
2583 f32Format.mFramesPerPacket = 1;
2584 f32Format.mBytesPerFrame = 4;
2585 f32Format.mChannelsPerFrame = 1;
2586 f32Format.mBitsPerChannel = 32;
2587 f32Format.mReserved = 0;
2589 ret = AudioConverterNew(&inputFormat, &f32Format, &converter_in_to_F32);
2590 ret = AudioConverterNew(&f32Format, &outputFormat, &converter_F32_to_out);
2591 ret = AudioConverterNew(&inputFormat, &outputFormat, &converter_in_to_out);
2593 AUGraphInitialize(graph
);
2595 if(mWorld
->mVerbosity
>= 0){
2596 scprintf("<-SC_CoreAudioDriver::Setup world %p\n", mWorld
);
2601 bool SC_iCoreAudioDriver::DriverStart()
2603 if(mWorld
->mVerbosity
>= 0){
2604 scprintf("->SC_CoreAudioDriver::DriverStart\n");
2609 OSStatus ret
= AUGraphStart(graph
);
2610 AudioOutputUnitStart(inputUnit
);
2612 scprintf("exception in SC_CoreAudioDriver::DriverStart\n");
2614 if(mWorld
->mVerbosity
>= 0){
2615 scprintf("<-SC_CoreAudioDriver::DriverStart\n");
2620 bool SC_iCoreAudioDriver::DriverStop()
2622 if(mWorld
->mVerbosity
>= 0){
2623 scprintf("->SC_CoreAudioDriver::DriverStop\n");
2627 AudioOutputUnitStop(inputUnit
);
2629 if(mWorld
->mVerbosity
>= 0){
2630 scprintf("<-SC_CoreAudioDriver::DriverStop\n");
2635 #endif // SC_AUDIO_API_COREAUDIOIPHONE
2640 // =====================================================================
2641 // Audio driver (PortAudio)
2643 #if SC_AUDIO_API == SC_AUDIO_API_PORTAUDIO
2645 // =====================================================================
2646 // SC_PortAudioDriver (PortAudio)
2648 #define PRINT_PORTAUDIO_ERROR( function, errorcode )\
2649 scprintf( "SC_PortAudioDriver: PortAudio failed at %s with error: '%s'\n",\
2650 #function, Pa_GetErrorText( errorcode ) )
2652 SC_PortAudioDriver::SC_PortAudioDriver(struct World
*inWorld
)
2653 : SC_AudioDriver(inWorld
)
2656 PaError paerror
= Pa_Initialize();
2657 if( paerror
!= paNoError
)
2658 PRINT_PORTAUDIO_ERROR( Pa_Initialize
, paerror
);
2661 SC_PortAudioDriver::~SC_PortAudioDriver()
2664 PaError paerror
= Pa_CloseStream( mStream
);
2665 if( paerror
!= paNoError
)
2666 PRINT_PORTAUDIO_ERROR( Pa_CloseStream
, paerror
);
2671 static int SC_PortAudioStreamCallback( const void *input
, void *output
,
2672 unsigned long frameCount
, const PaStreamCallbackTimeInfo
* timeInfo
,
2673 PaStreamCallbackFlags statusFlags
, void *userData
)
2675 SC_PortAudioDriver
*driver
= (SC_PortAudioDriver
*)userData
;
2677 return driver
->PortAudioCallback( input
, output
, frameCount
, timeInfo
, statusFlags
);
2680 int SC_PortAudioDriver::PortAudioCallback( const void *input
, void *output
,
2681 unsigned long frameCount
, const PaStreamCallbackTimeInfo
* timeInfo
,
2682 PaStreamCallbackFlags statusFlags
)
2684 World
*world
= mWorld
;
2685 (void) frameCount
, timeInfo
, statusFlags
; // suppress unused parameter warnings
2688 // synchronise against the output buffer - timeInfo->currentTime is 0.0 bug in PA?
2689 if (mPaStreamStartupTime
==0 && mPaStreamStartupTimeOSC
==0) {
2690 mPaStreamStartupTimeOSC
= GetCurrentOSCTime();
2691 mPaStreamStartupTime
= timeInfo
->outputBufferDacTime
;
2693 mOSCbuftime
= PaStreamTimeToOSC(timeInfo
->outputBufferDacTime
- mPaStreamStartupTime
) + mPaStreamStartupTimeOSC
;
2696 mToEngine
.Perform();
2697 mOscPacketsToEngine
.Perform();
2699 int numInputs
= mInputChannelCount
;
2700 int numOutputs
= mOutputChannelCount
;
2701 const float **inBuffers
= (const float**)input
;
2702 float **outBuffers
= (float**)output
;
2704 int numSamples
= NumSamplesPerCallback();
2705 int bufFrames
= mWorld
->mBufLength
;
2706 int numBufs
= numSamples
/ bufFrames
;
2708 float *inBuses
= mWorld
->mAudioBus
+ mWorld
->mNumOutputs
* bufFrames
;
2709 float *outBuses
= mWorld
->mAudioBus
;
2710 int32
*inTouched
= mWorld
->mAudioBusTouched
+ mWorld
->mNumOutputs
;
2711 int32
*outTouched
= mWorld
->mAudioBusTouched
;
2713 int minInputs
= std::min
<size_t>(numInputs
, mWorld
->mNumInputs
);
2714 int minOutputs
= std::min
<size_t>(numOutputs
, mWorld
->mNumOutputs
);
2716 int bufFramePos
= 0;
2718 int64 oscTime
= mOSCbuftime
;
2719 int64 oscInc
= mOSCincrement
;
2720 double oscToSamples
= mOSCtoSamples
;
2723 for (int i
= 0; i
< numBufs
; ++i
, mWorld
->mBufCounter
++, bufFramePos
+= bufFrames
)
2725 int32 bufCounter
= mWorld
->mBufCounter
;
2728 // copy+touch inputs
2730 for (int k
= 0; k
< minInputs
; ++k
)
2732 const float *src
= inBuffers
[k
] + bufFramePos
;
2733 float *dst
= inBuses
+ k
* bufFrames
;
2734 for (int n
= 0; n
< bufFrames
; ++n
) *dst
++ = *src
++;
2735 *tch
++ = bufCounter
;
2740 int64 nextTime
= oscTime
+ oscInc
;
2743 if (mScheduler.Ready(nextTime)) {
2744 double diff = (mScheduler.NextTime() - mOSCbuftime)*kOSCtoSecs;
2745 scprintf("rdy %.6f %.6f %.6f %.6f \n", (mScheduler.NextTime()-gStartupOSCTime) * kOSCtoSecs, (mOSCbuftime-gStartupOSCTime)*kOSCtoSecs, diff, (nextTime-gStartupOSCTime)*kOSCtoSecs);
2748 while ((schedTime
= mScheduler
.NextTime()) <= nextTime
) {
2749 float diffTime
= (float)(schedTime
- oscTime
) * oscToSamples
+ 0.5;
2750 float diffTimeFloor
= floor(diffTime
);
2751 world
->mSampleOffset
= (int)diffTimeFloor
;
2752 world
->mSubsampleOffset
= diffTime
- diffTimeFloor
;
2754 if (world
->mSampleOffset
< 0) world
->mSampleOffset
= 0;
2755 else if (world
->mSampleOffset
>= world
->mBufLength
) world
->mSampleOffset
= world
->mBufLength
-1;
2757 SC_ScheduledEvent event
= mScheduler
.Remove();
2760 world
->mSampleOffset
= 0;
2761 world
->mSubsampleOffset
= 0.f
;
2765 // copy touched outputs
2767 for (int k
= 0; k
< minOutputs
; ++k
) {
2768 float *dst
= outBuffers
[k
] + bufFramePos
;
2769 if (*tch
++ == bufCounter
) {
2770 float *src
= outBuses
+ k
* bufFrames
;
2771 for (int n
= 0; n
< bufFrames
; ++n
) *dst
++ = *src
++;
2773 for (int n
= 0; n
< bufFrames
; ++n
) *dst
++ = 0.0f
;
2777 // update buffer time
2778 oscTime
= mOSCbuftime
= nextTime
;
2780 } catch (std::exception
& exc
) {
2781 scprintf("SC_PortAudioDriver: exception in real time: %s\n", exc
.what());
2783 scprintf("SC_PortAudioDriver: unknown exception in real time\n");
2786 double cpuUsage
= (double)Pa_GetStreamCpuLoad(mStream
);
2787 mAvgCPU
= mAvgCPU
+ 0.1 * (cpuUsage
- mAvgCPU
);
2788 if (cpuUsage
> mPeakCPU
|| --mPeakCounter
<= 0)
2790 mPeakCPU
= cpuUsage
;
2791 mPeakCounter
= mMaxPeakCounter
;
2794 mAudioSync
.Signal();
2799 void SC_PortAudioDriver::GetPaDeviceFromName(const char* device
, int* mInOut
) {
2801 const PaDeviceInfo
*pdi
;
2802 const PaHostApiInfo
*apiInfo
;
2803 char devString
[256];
2804 PaDeviceIndex numDevices
= Pa_GetDeviceCount();
2805 mInOut
[0] = paNoDevice
;
2806 mInOut
[1] = paNoDevice
;
2808 // This tries to find one or two devices that match the given name (substring)
2809 // might cause problems for some names...
2810 for( int i
=0; i
<numDevices
; i
++ ) {
2811 pdi
= Pa_GetDeviceInfo( i
);
2812 apiInfo
= Pa_GetHostApiInfo(pdi
->hostApi
);
2813 strcpy(devString
, apiInfo
->name
);
2814 strcat(devString
, " : ");
2815 strcat(devString
, pdi
->name
);
2816 if (strstr(devString
, device
)) {
2817 if (pdi
->maxInputChannels
> 0) mInOut
[0] = i
;
2818 if (pdi
->maxOutputChannels
> 0) mInOut
[1] = i
;
2823 // ====================================================================
2826 bool SC_PortAudioDriver::DriverSetup(int* outNumSamples
, double* outSampleRate
)
2828 int mDeviceInOut
[2];
2830 const PaDeviceInfo
*pdi
;
2831 const PaHostApiInfo
*apiInfo
;
2832 const PaStreamInfo
*psi
;
2833 PaTime suggestedLatencyIn
, suggestedLatencyOut
;
2834 PaDeviceIndex numDevices
= Pa_GetDeviceCount();
2836 // print out all options:
2837 fprintf(stdout
, "\nDevice options:\n");
2838 for( int i
=0; i
<numDevices
; i
++ ) {
2839 pdi
= Pa_GetDeviceInfo( i
);
2840 apiInfo
= Pa_GetHostApiInfo(pdi
->hostApi
);
2841 fprintf(stdout
, " - %s : %s (device #%d with %d ins %d outs)\n",apiInfo
->name
,pdi
->name
, i
, pdi
->maxInputChannels
, pdi
->maxOutputChannels
);
2844 mDeviceInOut
[0] = paNoDevice
;
2845 mDeviceInOut
[1] = paNoDevice
;
2846 if (mWorld
->hw
->mInDeviceName
)
2847 GetPaDeviceFromName(mWorld
->hw
->mInDeviceName
, mDeviceInOut
);
2848 if (mDeviceInOut
[0] == paNoDevice
) mDeviceInOut
[0] = Pa_GetDefaultInputDevice();
2849 if (mDeviceInOut
[1] == paNoDevice
) mDeviceInOut
[1] = Pa_GetDefaultOutputDevice();
2851 *outNumSamples
= mWorld
->mBufLength
;
2852 if (mPreferredSampleRate
)
2853 *outSampleRate
= mPreferredSampleRate
;
2855 *outSampleRate
= 44100.;
2858 if (mDeviceInOut
[0]!=paNoDevice
&& mDeviceInOut
[1]!=paNoDevice
) {
2860 if (mPreferredHardwareBufferFrameSize
)
2861 // controls the suggested latency by hardwareBufferSize switch -Z
2862 suggestedLatencyIn
= suggestedLatencyOut
= mPreferredHardwareBufferFrameSize
/ (*outSampleRate
);
2864 suggestedLatencyIn
= Pa_GetDeviceInfo( mDeviceInOut
[0] )->defaultLowInputLatency
;
2865 suggestedLatencyOut
= Pa_GetDeviceInfo( mDeviceInOut
[1] )->defaultLowOutputLatency
;
2868 PaSampleFormat fmt
= paFloat32
| paNonInterleaved
;
2869 mInputChannelCount
= Pa_GetDeviceInfo( mDeviceInOut
[0] )->maxInputChannels
;
2870 mOutputChannelCount
= Pa_GetDeviceInfo( mDeviceInOut
[1] )->maxOutputChannels
;
2871 fprintf(stdout
, "\nBooting with:\n In: %s : %s \n",
2872 Pa_GetHostApiInfo(Pa_GetDeviceInfo( mDeviceInOut
[0] )->hostApi
)->name
,
2873 Pa_GetDeviceInfo( mDeviceInOut
[0] )->name
);
2874 fprintf(stdout
, " Out: %s : %s \n",
2875 Pa_GetHostApiInfo(Pa_GetDeviceInfo( mDeviceInOut
[1] )->hostApi
)->name
,
2876 Pa_GetDeviceInfo( mDeviceInOut
[1] )->name
);
2878 PaStreamParameters inStreamParams
;
2879 inStreamParams
.device
= mDeviceInOut
[0];
2880 inStreamParams
.channelCount
= mInputChannelCount
;
2881 inStreamParams
.sampleFormat
= fmt
;
2882 inStreamParams
.suggestedLatency
= suggestedLatencyIn
;
2883 inStreamParams
.hostApiSpecificStreamInfo
= NULL
;
2885 PaStreamParameters outStreamParams
;
2886 outStreamParams
.device
= mDeviceInOut
[1];
2887 outStreamParams
.channelCount
= mOutputChannelCount
;
2888 outStreamParams
.sampleFormat
= fmt
;
2889 outStreamParams
.suggestedLatency
= suggestedLatencyOut
;
2890 outStreamParams
.hostApiSpecificStreamInfo
= NULL
;
2892 paerror
= Pa_OpenStream(&mStream
, &inStreamParams
, &outStreamParams
, *outSampleRate
, *outNumSamples
, paNoFlag
, SC_PortAudioStreamCallback
, this );
2893 if( paerror
!= paNoError
)
2894 PRINT_PORTAUDIO_ERROR( Pa_OpenStream
, paerror
);
2896 psi
= Pa_GetStreamInfo(mStream
);
2898 fprintf(stdout
," Could not obtain further info from portaudio stream\n");
2900 fprintf(stdout
," Sample rate: %.3f\n", psi
->sampleRate
);
2901 fprintf(stdout
," Latency (in/out): %.3f / %.3f sec\n", psi
->inputLatency
, psi
->outputLatency
);
2904 return paerror
== paNoError
;
2907 // should not be necessary, but a last try with OpenDefaultStream...
2908 paerror
= Pa_OpenDefaultStream( &mStream
, 2, 2,
2909 paFloat32
| paNonInterleaved
, *outSampleRate
, *outNumSamples
, SC_PortAudioStreamCallback
, this );
2910 if( paerror
!= paNoError
)
2911 PRINT_PORTAUDIO_ERROR( Pa_OpenDefaultStream
, paerror
);
2912 return paerror
== paNoError
;
2915 bool SC_PortAudioDriver::DriverStart()
2920 PaError paerror
= Pa_StartStream( mStream
);
2921 if( paerror
!= paNoError
)
2922 PRINT_PORTAUDIO_ERROR( Pa_StartStream
, paerror
);
2925 mPaStreamStartupTimeOSC
= 0;
2926 mPaStreamStartupTime
= 0;
2927 // it would be better to do the sync here, but the timeInfo in the callback is incomplete
2928 //mPaStreamStartupTimeOSC = GetCurrentOSCTime();
2929 //mPaStreamStartupTime = Pa_GetStreamTime(mStream);
2931 return paerror
== paNoError
;
2934 bool SC_PortAudioDriver::DriverStop()
2939 PaError paerror
= Pa_StopStream(mStream
);
2940 if( paerror
!= paNoError
)
2941 PRINT_PORTAUDIO_ERROR( Pa_StopStream
, paerror
);
2943 return paerror
== paNoError
;
2946 #endif // SC_AUDIO_API_PORTAUDIO