SCDoc: Use proper static string constants instead of comparing string literals.
[supercollider.git] / include / server / SC_CoreAudio.h
blobd8a1238dbae68b639e1f079468a8bda93f9093e2
1 /*
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
22 #ifndef _SC_CoreAudio_
23 #define _SC_CoreAudio_
25 #include "MsgFifo.h"
26 #include "SC_FifoMsg.h"
27 #include "OSC_Packet.h"
28 #include "SC_SyncCondition.h"
29 #include "PriorityQueue.h"
30 #include "SC_Lock.h"
32 #define SC_AUDIO_API_COREAUDIO 1
33 #define SC_AUDIO_API_JACK 2
34 #define SC_AUDIO_API_PORTAUDIO 3
35 #define SC_AUDIO_API_AUDIOUNITS 4
36 #define SC_AUDIO_API_COREAUDIOIPHONE 5
37 #define SC_AUDIO_API_ANDROIDJNI 6
39 #ifdef SC_ANDROID
40 #define SC_AUDIO_API SC_AUDIO_API_ANDROIDJNI
41 #endif
43 #ifdef SC_IPHONE
44 #define SC_AUDIO_API SC_AUDIO_API_COREAUDIOIPHONE
45 #endif
47 #ifndef SC_AUDIO_API
48 # if defined(_WIN32)
49 # define SC_AUDIO_API SC_AUDIO_API_PORTAUDIO
50 # elif defined(__APPLE__)
51 # define SC_AUDIO_API SC_AUDIO_API_COREAUDIO
52 # else
53 # error SC_AUDIO_API undefined, cannot determine audio backend
54 # endif
55 #endif // SC_AUDIO_API
57 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIO || SC_AUDIO_API == SC_AUDIO_API_AUDIOUNITS
58 # include <CoreAudio/AudioHardware.h>
59 # include <CoreAudio/HostTime.h>
60 #endif
62 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIOIPHONE
63 #include <AudioUnit/AudioUnit.h>
64 #include <AudioToolbox/AudioToolbox.h>
65 #include <AudioToolbox/AudioConverter.h>
66 #include <AudioToolbox/AUGraph.h>
67 #endif
70 #if SC_AUDIO_API == SC_AUDIO_API_PORTAUDIO
71 #include "portaudio.h"
72 #endif
74 const double kSecondsToOSCunits = 4294967296.; // pow(2,32)
75 const double kMicrosToOSCunits = 4294.967296; // pow(2,32)/1e6
76 const double kNanosToOSCunits = 4.294967296; // pow(2,32)/1e9
78 const int32 kSECONDS_FROM_1900_to_1970 = (int32)2208988800UL; /* 17 leap years */
79 const double kOSCtoSecs = 2.328306436538696e-10;
81 struct SC_ScheduledEvent
83 /// Callback function responsible for freeing the OSC packet in the correct thread.
84 typedef void (*PacketFreeFunc)(struct World* world, OSC_Packet* packet);
86 /// Frees an OSC packet in the realtime thread (to be used as a PacketFreeFunc).
87 static void FreeInRT(struct World* world, OSC_Packet* packet);
88 /// Frees an OSC packet in the non-realtime thread (to be used as a PacketFreeFunc).
89 static void FreeInNRT(struct World* world, OSC_Packet* packet);
91 SC_ScheduledEvent() : mTime(0), mPacket(0) {}
92 SC_ScheduledEvent(struct World *inWorld, int64 inTime, OSC_Packet *inPacket, PacketFreeFunc freeFunc)
93 : mTime(inTime), mPacket(inPacket), mPacketFreeFunc(freeFunc), mWorld(inWorld) {}
95 int64 Time() { return mTime; }
96 void Perform();
98 int64 mTime;
99 OSC_Packet *mPacket;
100 PacketFreeFunc mPacketFreeFunc;
101 struct World *mWorld;
104 typedef MsgFifo<FifoMsg, 1024> EngineFifo;
106 // Functions to be implemented by the driver backend
107 extern "C" {
108 int32 server_timeseed();
109 int64 oscTimeNow();
112 void initializeScheduler();
114 /** Denotes whether an OSC packet has been performed immediately or has been scheduled for later execution.
116 If the package has been scheduled, memory ownership is transferred from the caller to the scheduler.
118 enum PacketStatus
120 PacketPerformed,
121 PacketScheduled
124 /** Perform a completion message in the realtime thread.
126 The return value denotes whether ownership is transferred to the scheduler or not.
128 PacketStatus PerformCompletionMsg(World *world, const OSC_Packet& packet);
130 class SC_AudioDriver
132 protected:
133 int64 mOSCincrement;
134 struct World *mWorld;
135 double mOSCtoSamples;
136 int mSampleTime;
138 // Common members
139 uint32 mHardwareBufferSize; // bufferSize returned by kAudioDevicePropertyBufferSize
140 EngineFifo mFromEngine, mToEngine;
141 EngineFifo mOscPacketsToEngine;
142 SC_SyncCondition mAudioSync;
143 pthread_t mThread;
144 bool mRunThreadFlag;
145 uint32 mSafetyOffset;
146 PriorityQueueT<SC_ScheduledEvent, 2048> mScheduler;
147 int mNumSamplesPerCallback;
148 uint32 mPreferredHardwareBufferFrameSize;
149 uint32 mPreferredSampleRate;
150 double mBuffersPerSecond;
151 double mAvgCPU, mPeakCPU;
152 int mPeakCounter, mMaxPeakCounter;
153 double mOSCincrementNumerator;
155 double mStartHostSecs;
156 double mPrevHostSecs;
157 double mStartSampleTime;
158 double mPrevSampleTime;
159 double mSmoothSampleRate;
160 double mSampleRate;
162 // Driver interface methods, implemented by subclasses
164 * DriverSetup() should init the driver and write the num of samples per callback
165 * and the sample rate into the two addresses supplied as arguments.
166 * The driver will have access to the "preferred" values of these two args
167 * (mPreferredHardwareBufferFrameSize, mPreferredSampleRate) and ideally should follow them.
168 * This method should open the resources (and return true if successful), but shouldn't
169 * really start the streaming (this is the responsibility of DriverStart()).
171 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate) = 0;
173 * Start the audio streaming. Return true iff successful.
175 virtual bool DriverStart() = 0;
177 * Stop the audio streaming. Return true iff successful.
179 virtual bool DriverStop() = 0;
181 public:
182 // Common methods
183 SC_AudioDriver(struct World *inWorld);
184 virtual ~SC_AudioDriver();
186 int64 mOSCbuftime;
188 bool Setup();
189 bool Start();
190 bool Stop();
192 void ClearSched() { mScheduler.Empty(); }
194 void RunNonRealTime(float *in, float *out, int numSamples, int64 oscTime);
195 void* RunThread();
197 int SafetyOffset() const { return mSafetyOffset; }
198 int NumSamplesPerCallback() const { return mNumSamplesPerCallback; }
199 void SetPreferredHardwareBufferFrameSize(int inSize)
201 mPreferredHardwareBufferFrameSize = inSize;
203 void SetPreferredSampleRate(int inRate)
205 mPreferredSampleRate = inRate;
208 bool SendMsgToEngine(FifoMsg& inMsg); // called by NRT thread
209 bool SendMsgFromEngine(FifoMsg& inMsg);
210 bool SendOscPacketMsgToEngine(FifoMsg& inMsg); // called by OSC socket listener threads, protected by mWorld->mDriverLock
212 void AddEvent(SC_ScheduledEvent& event) { mScheduler.Add(event); }
214 double GetAvgCPU() const { return mAvgCPU; }
215 double GetPeakCPU() const { return mPeakCPU; }
216 double GetSampleRate() const { return mSampleRate; }
217 double GetActualSampleRate() const { return mSmoothSampleRate; }
220 extern SC_AudioDriver* SC_NewAudioDriver(struct World* inWorld);
223 // the following classes should be split out into separate source files.
224 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIO || SC_AUDIO_API == SC_AUDIO_API_AUDIOUNITS
225 class SC_CoreAudioDriver : public SC_AudioDriver
228 AudioBufferList * mInputBufList;
229 AudioDeviceID mInputDevice;
230 AudioDeviceID mOutputDevice;
232 AudioStreamBasicDescription inputStreamDesc; // info about the default device
233 AudioStreamBasicDescription outputStreamDesc; // info about the default device
235 friend OSStatus appIOProc ( AudioDeviceID inDevice,
236 const AudioTimeStamp* inNow,
237 const AudioBufferList* inInputData,
238 const AudioTimeStamp* inInputTime,
239 AudioBufferList* outOutputData,
240 const AudioTimeStamp* inOutputTime,
241 void* defptr);
243 friend OSStatus appIOProcSeparateIn (AudioDeviceID device, const AudioTimeStamp* inNow,
244 const AudioBufferList* inInputData,
245 const AudioTimeStamp* inInputTime,
246 AudioBufferList* outOutputData,
247 const AudioTimeStamp* inOutputTime,
248 void* defptr);
250 protected:
251 // Driver interface methods
252 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
253 virtual bool DriverStart();
254 virtual bool DriverStop();
256 AudioDeviceIOProcID mOutputID;
257 AudioDeviceIOProcID mInputID;
259 public:
260 int builtinoutputflag_;
262 SC_CoreAudioDriver(struct World *inWorld);
263 virtual ~SC_CoreAudioDriver();
265 bool StopStart();
267 void Run(const AudioBufferList* inInputData, AudioBufferList* outOutputData, int64 oscTime);
269 bool UseInput() { return mInputDevice != kAudioDeviceUnknown; }
270 bool UseSeparateIO() { return UseInput() && mInputDevice != mOutputDevice; }
271 AudioDeviceID InputDevice() { return mInputDevice; }
272 AudioDeviceID OutputDevice() { return mOutputDevice; }
274 void SetInputBufferList(AudioBufferList * inBufList) { mInputBufList = inBufList; }
275 AudioBufferList* GetInputBufferList() const { return mInputBufList; }
278 #endif
280 #if SC_AUDIO_API == SC_AUDIO_API_COREAUDIOIPHONE
281 class SC_iCoreAudioDriver : public SC_AudioDriver
283 AUGraph graph;
285 AudioStreamBasicDescription inputStreamDesc; // info about the default device
286 AudioStreamBasicDescription outputStreamDesc; // info about the default device
288 protected:
289 // Driver interface methods
290 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
291 virtual bool DriverStart();
292 virtual bool DriverStop();
294 public:
295 SC_iCoreAudioDriver(struct World *inWorld);
296 virtual ~SC_iCoreAudioDriver();
298 void Run(const AudioBufferList* inInputData, AudioBufferList* outOutputData, int64 oscTime);
300 AudioBufferList * buflist;
301 AudioBufferList * floatInputList;
302 AudioBufferList * floatOutputList;
303 AudioConverterRef converter_in_to_F32;
304 AudioConverterRef converter_F32_to_out;
305 AudioConverterRef converter_in_to_out;
306 int *converter_buffer;
308 int receivedIn;
309 AudioUnit inputUnit;
314 inline SC_AudioDriver* SC_NewAudioDriver(struct World *inWorld)
316 return new SC_iCoreAudioDriver(inWorld);
318 #endif // SC_AUDIO_API_COREAUDIOIPHONE
321 #if SC_AUDIO_API == SC_AUDIO_API_PORTAUDIO
322 class SC_PortAudioDriver : public SC_AudioDriver
325 int mInputChannelCount, mOutputChannelCount;
326 PaStream *mStream;
327 PaTime mPaStreamStartupTime;
328 int64 mPaStreamStartupTimeOSC;
330 protected:
331 // Driver interface methods
332 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
333 virtual bool DriverStart();
334 virtual bool DriverStop();
336 public:
337 SC_PortAudioDriver(struct World *inWorld);
338 virtual ~SC_PortAudioDriver();
340 int PortAudioCallback( const void *input, void *output,
341 unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo,
342 PaStreamCallbackFlags statusFlags );
343 private:
344 void GetPaDeviceFromName(const char* device, int* mInOut);
347 inline SC_AudioDriver* SC_NewAudioDriver(struct World *inWorld)
349 return new SC_PortAudioDriver(inWorld);
351 #endif // SC_AUDIO_API_PORTAUDIO
353 #if SC_AUDIO_API == SC_AUDIO_API_ANDROIDJNI
355 class SC_AndroidJNIAudioDriver : public SC_AudioDriver
358 protected:
360 // Driver interface methods
361 virtual bool DriverSetup(int* outNumSamplesPerCallback, double* outSampleRate);
362 virtual bool DriverStart();
363 virtual bool DriverStop();
365 public:
366 SC_AndroidJNIAudioDriver(struct World *inWorld);
367 virtual ~SC_AndroidJNIAudioDriver();
369 void genaudio(short* arri, int numSamples);
373 inline SC_AudioDriver* SC_NewAudioDriver(struct World *inWorld)
375 return new SC_AndroidJNIAudioDriver(inWorld);
378 #endif // SC_AUDIO_API == SC_AUDIO_API_ANDROIDJNI
380 #endif