/[svn]/linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceCoreAudio.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceCoreAudio.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1829 - (hide annotations) (download)
Fri Jan 30 19:22:36 2009 UTC (15 years, 2 months ago) by iliev
File size: 17228 byte(s)
* added (experimental) CoreAudio driver

1 iliev 1829 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2009 Grigor Iliev *
6     * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23     #include "AudioOutputDeviceCoreAudio.h"
24    
25     #include "../../common/global_private.h"
26    
27     namespace LinuxSampler {
28    
29     void AudioOutputDeviceCoreAudio::HandleOutputBuffer (
30     void *aqData,
31     AudioQueueRef inAQ,
32     AudioQueueBufferRef inBuffer
33     ) {
34     AQPlayerState* pAqData = (AQPlayerState*) aqData;
35     if (atomic_read(&(pAqData->mIsRunning)) == 0) {
36     AudioQueueFlush(pAqData->mQueue);
37     AudioQueueStop (pAqData->mQueue, true);
38     return;
39     }
40     uint bufferSize = pAqData->pDevice->uiBufferSize;
41    
42     // let all connected engines render 'fragmentSize' sample points
43     pAqData->pDevice->RenderAudio(bufferSize);
44    
45     int16_t* pDataBuf = (int16_t*)(inBuffer->mAudioData);
46    
47     uint uiCoreAudioChannels = pAqData->pDevice->uiCoreAudioChannels;
48     // convert from DSP value range (-1.0..+1.0) to 16 bit integer value
49     // range (-32768..+32767), check clipping and copy to Alsa output buffer
50     for (int c = 0; c < uiCoreAudioChannels; c++) {
51     float* in = pAqData->pDevice->Channels[c]->Buffer();
52     for (int i = 0, o = c; i < bufferSize; i++ , o += uiCoreAudioChannels) {
53     float sample_point = in[i] * 32768.0f;
54     if (sample_point < -32768.0) sample_point = -32768.0;
55     if (sample_point > 32767.0) sample_point = 32767.0;
56     pDataBuf[o] = (int16_t) sample_point;
57     }
58     }
59    
60     inBuffer->mAudioDataByteSize = (uiCoreAudioChannels * 2) * bufferSize;
61    
62     OSStatus res = AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL);
63     if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl;
64     }
65    
66     AudioOutputDeviceCoreAudio::DeviceInfo* AudioOutputDeviceCoreAudio::pDeviceInfo = NULL;
67    
68     AudioOutputDeviceCoreAudio::DeviceInfo* AudioOutputDeviceCoreAudio::GetDeviceInfo() {
69     if(pDeviceInfo == NULL) {
70     pDeviceInfo = new DeviceInfo;
71    
72     pDeviceInfo->uiSamplerate = 44100;
73     pDeviceInfo->uiChannelNumber = 2;
74    
75     AudioStreamBasicDescription dataFormat;
76     SetAudioDataFormat(&dataFormat);
77     AudioQueueRef pQueue = NULL;
78    
79     OSStatus res = AudioQueueNewOutput (
80     &dataFormat, NULL, NULL, NULL, NULL, 0, &pQueue
81     );
82    
83     if(res) {
84     std::cerr << "Failed to retrieve device info: " << res << std::endl;
85     return pDeviceInfo;
86     }
87    
88     UInt32 chns = pDeviceInfo->uiChannelNumber;
89     UInt32 size = sizeof(chns);
90     res = AudioQueueGetProperty (
91     pQueue,
92     kAudioQueueDeviceProperty_NumberChannels,
93     &chns, &size
94     );
95    
96     if(res) std::cerr << "Failed to retrieve channel number: " << res << std::endl;
97     else pDeviceInfo->uiChannelNumber = chns;
98    
99     Float64 sRate = pDeviceInfo->uiSamplerate;
100     size = sizeof(sRate);
101     res = AudioQueueGetProperty (
102     pQueue,
103     kAudioQueueDeviceProperty_SampleRate,
104     &sRate, &size
105     );
106    
107     if(res) std::cerr << "Failed to retrieve samplerate: " << res << std::endl;
108     else pDeviceInfo->uiSamplerate = (uint)sRate;
109    
110     AudioQueueDispose(pQueue, true);
111     }
112    
113     return pDeviceInfo;
114     }
115    
116     AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio (
117     std::map<String,DeviceCreationParameter*> Parameters
118     ) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) {
119    
120     dmsg(2,("AudioOutputDeviceCoreAudio::AudioOutputDeviceCoreAudio()\n"));
121     atomic_set(&pausedNew, 0);
122     pausedOld = 0;
123    
124     uiCoreAudioChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
125     uint samplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
126     uiBufferNumber = ((DeviceCreationParameterInt*)Parameters["BUFFERS"])->ValueAsInt();
127     uiBufferSize = ((DeviceCreationParameterInt*)Parameters["BUFFERSIZE"])->ValueAsInt();
128    
129     aqPlayerState.mDataFormat.mSampleRate = samplerate;
130     aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM;
131    
132     aqPlayerState.mDataFormat.mFormatFlags =
133     kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
134    
135     aqPlayerState.mDataFormat.mBytesPerPacket = uiCoreAudioChannels * 2;
136     aqPlayerState.mDataFormat.mFramesPerPacket = 1;
137     aqPlayerState.mDataFormat.mBytesPerFrame = uiCoreAudioChannels * 2;
138     aqPlayerState.mDataFormat.mChannelsPerFrame = uiCoreAudioChannels;
139     aqPlayerState.mDataFormat.mBitsPerChannel = 16;
140    
141     aqPlayerState.mBuffers = new AudioQueueBufferRef[uiBufferNumber];
142    
143     aqPlayerState.bufferByteSize =
144     MaxSamplesPerCycle() * aqPlayerState.mDataFormat.mBytesPerFrame;
145    
146     aqPlayerState.mNumPacketsToRead = MaxSamplesPerCycle();
147    
148     aqPlayerState.pDevice = this;
149     aqPlayerState.mQueue = NULL;
150    
151     uint fragmentSize = MaxSamplesPerCycle();
152     // create audio channels for this audio device to which the sampler engines can write to
153     for (int i = 0; i < uiCoreAudioChannels; i++) {
154     this->Channels.push_back(new AudioChannel(i, fragmentSize));
155     }
156    
157     StartThread();
158    
159     if (!((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
160     Stop();
161     }
162     }
163    
164     AudioOutputDeviceCoreAudio::~AudioOutputDevice() {
165     atomic_set(&(aqPlayerState.mIsRunning), 0);
166     destroyMutex.Lock();
167     AudioQueueDispose(aqPlayerState.mQueue, true);
168     destroyMutex.Unlock();
169     delete [] aqPlayerState.mBuffers;
170     }
171    
172     void AudioOutputDeviceCoreAudio::SetAudioDataFormat(AudioStreamBasicDescription* pDataFormat) {
173     pDataFormat->mSampleRate = 44100;
174     pDataFormat->mFormatID = kAudioFormatLinearPCM;
175    
176     pDataFormat->mFormatFlags =
177     kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
178    
179     pDataFormat->mBytesPerPacket = 4;
180     pDataFormat->mFramesPerPacket = 1;
181     pDataFormat->mBytesPerFrame = 4;
182     pDataFormat->mChannelsPerFrame = 2;
183     pDataFormat->mBitsPerChannel = 16;
184     }
185    
186     String AudioOutputDeviceCoreAudio::Name() {
187     return "COREAUDIO";
188     }
189    
190     String AudioOutputDeviceCoreAudio::Description() {
191     return "Apple CoreAudio";
192     }
193    
194     String AudioOutputDeviceCoreAudio::Version() {
195     String s = "$Revision: 1.1 $";
196     return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
197     }
198    
199     void AudioOutputDeviceCoreAudio::Play() {
200     atomic_set(&pausedNew, 0);
201     }
202    
203     bool AudioOutputDeviceCoreAudio::IsPlaying() {
204     return !atomic_read(&pausedNew);
205     }
206    
207     void AudioOutputDeviceCoreAudio::Stop() {
208     atomic_set(&pausedNew, 1);
209     }
210    
211     uint AudioOutputDeviceCoreAudio::MaxSamplesPerCycle() {
212     return uiBufferSize;
213     }
214    
215     uint AudioOutputDeviceCoreAudio::SampleRate() {
216     return aqPlayerState.mDataFormat.mSampleRate;
217     }
218    
219     String AudioOutputDeviceCoreAudio::Driver() {
220     return Name();
221     }
222    
223     AudioChannel* AudioOutputDeviceCoreAudio::CreateChannel(uint ChannelNr) {
224     // just create a mix channel
225     return new AudioChannel(ChannelNr, Channel(ChannelNr % uiCoreAudioChannels));
226     }
227    
228     /**
229     * Entry point for the thread.
230     */
231     int AudioOutputDeviceCoreAudio::Main() {
232     dmsg(2,("CoreAudio thread started\n"));
233    
234     bool initialized = aqPlayerState.mQueue != NULL;
235     if(!initialized) {
236     /*
237     * Initializing the audio queue
238     * Need to be run from this thread because of CFRunLoopGetCurrent()
239     * which returns the CFRunLoop object for the current thread.
240     */
241     OSStatus res = AudioQueueNewOutput (
242     &aqPlayerState.mDataFormat,
243     HandleOutputBuffer,
244     &aqPlayerState,
245     CFRunLoopGetCurrent(),
246     kCFRunLoopCommonModes,
247     0,
248     &aqPlayerState.mQueue
249     );
250    
251     if(res) {
252     String s = String("AudioQueueNewOutput: Error ") + ToString(res);
253     throw Exception(s);
254     }
255    
256     for (int i = 0; i < uiBufferNumber; ++i) {
257     OSStatus res = AudioQueueAllocateBuffer (
258     aqPlayerState.mQueue,
259     aqPlayerState.bufferByteSize,
260     &aqPlayerState.mBuffers[i]
261     );
262    
263     if(res) {
264     String s = String("AudioQueueAllocateBuffer: Error ");
265     throw Exception(s + ToString(res));
266     }
267     }
268     }
269    
270     for (int i = 0; i < uiBufferNumber; ++i) {
271     HandleOutputBuffer (
272     &aqPlayerState,
273     aqPlayerState.mQueue,
274     aqPlayerState.mBuffers[i]
275     );
276     }
277    
278     Float32 gain = 1.0;
279    
280     OSStatus res = AudioQueueSetParameter (
281     aqPlayerState.mQueue,
282     kAudioQueueParam_Volume,
283     gain
284     );
285    
286     if(res) std::cerr << "AudioQueueSetParameter: Error " << res << std::endl;
287    
288     atomic_set(&(aqPlayerState.mIsRunning), 1);
289    
290     if(!initialized) {
291     res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL);
292     if(res) {
293     String s = String("AudioQueuePrime: Error ") + ToString(res);
294     throw Exception(s);
295     }
296     }
297    
298     res = AudioQueueStart(aqPlayerState.mQueue, NULL);
299     if(res) {
300     String s = String("AudioQueueStart: Error ") + ToString(res);
301     throw Exception(s);
302     }
303    
304     destroyMutex.Lock();
305     do {
306     if(atomic_read(&pausedNew) != pausedOld) {
307     pausedOld = atomic_read(&pausedNew);
308    
309     if(pausedOld) {
310     res = AudioQueuePause(aqPlayerState.mQueue);
311     if(res) std::cerr << "AudioQueuePause: Error " << res << std::endl;
312     } else {
313     res = AudioQueuePrime(aqPlayerState.mQueue, 0, NULL);
314     if(res) std::cerr << "AudioQueuePrime: Error " << res << std::endl;
315     res = AudioQueueStart(aqPlayerState.mQueue, NULL);
316     if(res) std::cerr << "AudioQueueStart: Error " << res << std::endl;
317     }
318     }
319    
320     CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.2, false);
321     } while (atomic_read(&(aqPlayerState.mIsRunning)));
322     destroyMutex.Unlock();
323    
324     dmsg(2,("CoreAudio thread stopped\n"));
325    
326     return 0;
327     }
328    
329    
330     // *************** ParameterSampleRate ***************
331     // *
332    
333     AudioOutputDeviceCoreAudio::ParameterSampleRate::ParameterSampleRate() :
334     AudioOutputDevice::ParameterSampleRate::ParameterSampleRate() {
335    
336     }
337    
338     AudioOutputDeviceCoreAudio::ParameterSampleRate::ParameterSampleRate(String s) :
339     AudioOutputDevice::ParameterSampleRate::ParameterSampleRate(s) {
340    
341     }
342    
343     optional<int>
344     AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt(std::map<String,String> Parameters) {
345     dmsg(2,("AudioOutputDeviceCoreAudio::ParameterSampleRate::DefaultAsInt()\n"));
346     return GetDeviceInfo()->uiSamplerate;
347     }
348    
349    
350     // *************** ParameterChannels ***************
351     // *
352    
353     AudioOutputDeviceCoreAudio::ParameterChannels::ParameterChannels() :
354     AudioOutputDevice::ParameterChannels::ParameterChannels() {
355    
356     }
357    
358     AudioOutputDeviceCoreAudio::ParameterChannels::ParameterChannels(String s) :
359     AudioOutputDevice::ParameterChannels::ParameterChannels(s) {
360    
361     }
362    
363     optional<int>
364     AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt(std::map<String,String> Parameters) {
365     dmsg(2,("AudioOutputDeviceCoreAudio::ParameterChannels::DefaultAsInt()\n"));
366     return GetDeviceInfo()->uiChannelNumber;
367     }
368    
369     // *************** ParameterBuffers ***************
370     // *
371    
372     AudioOutputDeviceCoreAudio::ParameterBuffers::ParameterBuffers() : DeviceCreationParameterInt() {
373     InitWithDefault();
374     }
375    
376     AudioOutputDeviceCoreAudio::ParameterBuffers::ParameterBuffers(String s)
377     throw (Exception) : DeviceCreationParameterInt(s) {
378     }
379    
380     String AudioOutputDeviceCoreAudio::ParameterBuffers::Description() {
381     return "Number of audio buffer";
382     }
383    
384     bool AudioOutputDeviceCoreAudio::ParameterBuffers::Fix() {
385     return true;
386     }
387    
388     bool AudioOutputDeviceCoreAudio::ParameterBuffers::Mandatory() {
389     return false;
390     }
391    
392     std::map<String,DeviceCreationParameter*>
393     AudioOutputDeviceCoreAudio::ParameterBuffers::DependsAsParameters() {
394     return std::map<String,DeviceCreationParameter*>();
395     }
396    
397     optional<int>
398     AudioOutputDeviceCoreAudio::ParameterBuffers::DefaultAsInt(std::map<String,String> Parameters) {
399     return 3;
400     }
401    
402     optional<int>
403     AudioOutputDeviceCoreAudio::ParameterBuffers::RangeMinAsInt(std::map<String,String> Parameters) {
404     return 2;
405     }
406    
407     optional<int>
408     AudioOutputDeviceCoreAudio::ParameterBuffers::RangeMaxAsInt(std::map<String,String> Parameters) {
409     return 16;
410     }
411    
412     std::vector<int>
413     AudioOutputDeviceCoreAudio::ParameterBuffers::PossibilitiesAsInt(std::map<String,String> Parameters) {
414     return std::vector<int>();
415     }
416    
417     void AudioOutputDeviceCoreAudio::ParameterBuffers::OnSetValue(int i) throw (Exception) {
418     // not posssible, as parameter is fix
419     }
420    
421     String AudioOutputDeviceCoreAudio::ParameterBuffers::Name() {
422     return "BUFFERS";
423     }
424    
425     // *************** ParameterBufferSize ***************
426     // *
427    
428     AudioOutputDeviceCoreAudio::ParameterBufferSize::ParameterBufferSize() : DeviceCreationParameterInt() {
429     InitWithDefault();
430     }
431    
432     AudioOutputDeviceCoreAudio::ParameterBufferSize::ParameterBufferSize(String s)
433     throw (Exception) : DeviceCreationParameterInt(s) {
434     }
435    
436     String AudioOutputDeviceCoreAudio::ParameterBufferSize::Description() {
437     return "Size of the audio buffer in sample frames";
438     }
439    
440     bool AudioOutputDeviceCoreAudio::ParameterBufferSize::Fix() {
441     return true;
442     }
443    
444     bool AudioOutputDeviceCoreAudio::ParameterBufferSize::Mandatory() {
445     return false;
446     }
447    
448     std::map<String,DeviceCreationParameter*>
449     AudioOutputDeviceCoreAudio::ParameterBufferSize::DependsAsParameters() {
450     return std::map<String,DeviceCreationParameter*>();
451     }
452    
453     optional<int>
454     AudioOutputDeviceCoreAudio::ParameterBufferSize::DefaultAsInt(std::map<String,String> Parameters) {
455     return 128;
456     }
457    
458     optional<int>
459     AudioOutputDeviceCoreAudio::ParameterBufferSize::RangeMinAsInt(std::map<String,String> Parameters) {
460     return 32;
461     }
462    
463     optional<int>
464     AudioOutputDeviceCoreAudio::ParameterBufferSize::RangeMaxAsInt(std::map<String,String> Parameters) {
465     return 4096;
466     }
467    
468     std::vector<int>
469     AudioOutputDeviceCoreAudio::ParameterBufferSize::PossibilitiesAsInt(std::map<String,String> Parameters) {
470     return std::vector<int>();
471     }
472    
473     void AudioOutputDeviceCoreAudio::ParameterBufferSize::OnSetValue(int i) throw (Exception) {
474     // not posssible, as parameter is fix
475     }
476    
477     String AudioOutputDeviceCoreAudio::ParameterBufferSize::Name() {
478     return "BUFFERSIZE";
479     }
480     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC