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

Contents of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceAsio.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1895 - (show annotations) (download)
Sun May 3 12:15:40 2009 UTC (14 years, 11 months ago) by persson
File size: 41836 byte(s)
* fixes for using large audio device buffers
* VST: added support for sample rate and buffer size changes
* VST: close editor (Fantasia) when the VST is removed
* minor fix in configure for mmsystem.h detection on MinGW
* removed warnings from gcc 4.4 and valgrind

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2008 Christian Schoenebeck *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "AudioOutputDeviceAsio.h"
25 #include "AudioOutputDeviceFactory.h"
26
27 #define kMaxInputChannels 32
28 #define kMaxOutputChannels 32
29 #define ASIO_MAX_DEVICE_INFO 32
30
31 #define NUM_STANDARDSAMPLINGRATES 3 /* 11.025, 22.05, 44.1 */
32 #define NUM_CUSTOMSAMPLINGRATES 9 /* must be the same number of elements as in the array below */
33 #define MAX_NUMSAMPLINGRATES (NUM_STANDARDSAMPLINGRATES+NUM_CUSTOMSAMPLINGRATES)
34
35 // internal data storage
36 typedef struct DriverInfo
37 {
38 // ASIOInit()
39 ASIODriverInfo driverInfo;
40
41 // ASIOGetChannels()
42 long numInputChannels;
43 long numOutputChannels;
44
45 // ASIOGetBufferSize()
46 long minBufSize;
47 long maxBufSize;
48 long preferredBufSize;
49 long bufGranularity;
50 long chosenBufSize;
51
52 // ASIOGetSampleRate()
53 ASIOSampleRate sampleRate;
54 int numSampleRates;
55 std::vector<int> sampleRates;
56
57 // ASIOOutputReady()
58 bool ASIOOutputReadySupported;
59
60 // ASIOGetLatencies ()
61 long inputLatency;
62 long outputLatency;
63
64 // ASIOCreateBuffers ()
65 long numInputBuffers; // becomes number of actual created input buffers
66 long numOutputBuffers; // becomes number of actual created output buffers
67 ASIOBufferInfo bufferInfos[kMaxInputChannels + kMaxOutputChannels]; // buffer info's
68
69 // ASIOGetChannelInfo()
70 ASIOChannelInfo channelInfos[kMaxInputChannels + kMaxOutputChannels]; // channel info's
71 // The above two arrays share the same indexing, as the data in them are linked together
72
73 // Information from ASIOGetSamplePosition()
74 // data is converted to double floats for easier use, however 64 bit integer can be used, too
75 double nanoSeconds;
76 double samples;
77 double tcSamples; // time code samples
78
79 // bufferSwitchTimeInfo()
80 ASIOTime tInfo; // time info state
81 unsigned long sysRefTime; // system reference time, when bufferSwitch() was called
82
83 // Signal the end of processing in this example
84 bool stopped;
85 } DriverInfo;
86
87 extern AsioDrivers* asioDrivers;
88 extern bool loadAsioDriver(char *name);
89 static ASIODriverInfo MyAsioDriverInfo;
90 static DriverInfo asioDriverInfo = {0};
91
92 static bool asioDriverOpened = false;
93 static bool AudioOutputDeviceAsioInstantiated = false;
94 static String currentAsioDriverName;
95 static std::vector<String> asioDriverList;
96 static bool asioDriverListLoaded = false;
97
98 namespace LinuxSampler {
99
100 // callback prototypes
101
102 ASIOCallbacks asioCallbacks;
103 ASIOBufferInfo bufferInfos[2];
104 AudioOutputDeviceAsio *GlobalAudioOutputDeviceAsioThisPtr;
105
106 template<int bitres>
107 static void floatToASIOSTInt32LSBXX(float *in, void *dest, int numSamples) {
108 double pos_max_value = (1 << bitres) -1.0;
109 double neg_max_value = -pos_max_value;
110 int32_t *out = (int32_t *)dest;
111 for(int i=0; i < numSamples ; i++) {
112 double sample_point = in[i] * pos_max_value;
113 if (sample_point < neg_max_value) sample_point = neg_max_value;
114 if (sample_point > pos_max_value) sample_point = pos_max_value;
115 out[i] = (int16_t)sample_point;
116 }
117 }
118
119 static void floatToASIOSTInt16LSB(float *in, void *dest, int numSamples) {
120 int16_t *out = (int16_t *)dest;
121 for(int i=0; i < numSamples ; i++) {
122 float sample_point = in[i] * 32768.0f;
123 if (sample_point < -32768.0) sample_point = -32768.0;
124 if (sample_point > 32767.0) sample_point = 32767.0;
125 out[i] = (int16_t)sample_point;
126 }
127 }
128
129 static void floatToASIOSTInt32LSB(float *in, void *dest, int numSamples) {
130 int32_t *out = (int32_t *)dest;
131 for(int i=0; i < numSamples ; i++) {
132 double sample_point = in[i] * 2147483648.0;
133 if (sample_point < - 2147483648.0) sample_point = -2147483648.0;
134 if (sample_point > 2147483647.0) sample_point = 2147483647.0;
135 out[i] = (int32_t)(sample_point);
136 }
137 }
138
139 std::vector<String> getAsioDriverNames();
140
141 static bool ASIO_loadAsioDriver(const char *name)
142 {
143 dmsg(2,("ASIO_loadAsioDriver: trying to load '%s'\n",name));
144 #ifdef WINDOWS
145 CoInitialize(0);
146 #endif
147 return loadAsioDriver(const_cast<char*>(name));
148 }
149
150 int ASIO_OpenAndQueryDeviceInfo(char *driverName, DriverInfo *driverInfo, ASIODriverInfo *asioDriverInfo)
151 {
152 ASIOSampleRate possibleSampleRates[]
153 = {8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0};
154
155 ASIOChannelInfo channelInfos;
156 ASIOError asioError;
157
158 // call this function in order to fill the internal vector containing the list of ASIO cards
159 // since the reading of the list is performed only one time subsequent calls to this function will be automatically ignored
160 // calling getAsioDriverNames() is needed in the case of a LinuxSampler client application first creating an ASIO device
161 // which calls ASIO_OpenAndQueryDeviceInfo() and afterwards retrieve the list of available ASIO cards
162 // since getAsioDriverNames() unloads the current driver and loads the driver 'dummy' this would cause
163 // the audio stopping and forcing the create the audio output device again
164 getAsioDriverNames();
165
166 dmsg(2,("ASIO_OpenAndQueryDeviceInfo driverName='%s' current='%s'\n",driverName, currentAsioDriverName.c_str() ));
167 if(!strcmp(driverName, currentAsioDriverName.c_str() )) {
168 // if the given ASIO driver name == current ASIO driver name and the driver
169 // was already opened then do nothing
170 if(asioDriverOpened) {
171 dmsg(2,("asioDriver ALREADY OPENED, DOING NOTHING !\n"));
172 return 0;
173 }
174 }
175 else {
176 dmsg(2,("driverName != currentAsioDriverName , new asio driver specified, opening device ....\n"));
177 // if a new ASIO driver name was specified then first check if we need to close
178 // the old one
179 if(asioDriverOpened) {
180 dmsg(2,("different asioDriver ALREADY OPENED, closing old one !\n"));
181 asioDriverOpened = false;
182 ASIOExit(); // close the old ASIO driver
183 }
184 }
185 currentAsioDriverName = driverName;
186
187 memset((void *)asioDriverInfo,0,sizeof(ASIODriverInfo));
188 asioDriverInfo->asioVersion=1;
189 asioDriverInfo->sysRef = NULL;
190
191 /* MUST BE CHECKED : to force fragments loading on Mac */
192 //ASIO_loadAsioDriver("dummy");
193
194 dmsg(2,("Before ASIO_loadAsioDriver('%s')\n",driverName));
195 if ( !ASIO_loadAsioDriver(driverName) ) {
196 dmsg(2,("ASIO_OpenAndQueryDeviceInfo could not loadAsioDriver %s\n", driverName));
197 return -1;
198 }
199 dmsg(2,("Before ASIOInit()\n"));
200 if( (asioError = ASIOInit(asioDriverInfo)) != ASE_OK ) {
201 dmsg(2,("ASIO_OpenAndQueryDeviceInfo: ASIOInit returned %d for %s\n", asioError, driverName));
202 return asioError;
203 }
204 dmsg(2,("Before ASIOGetChannels()\n"));
205 if( (asioError = ASIOGetChannels(&driverInfo->numInputChannels, &driverInfo->numOutputChannels) != ASE_OK)) {
206 dmsg(2,("ASIO_OpenAndQueryDeviceInfo could not ASIOGetChannels for %s\n", driverName));
207 return asioError;
208 }
209
210 dmsg(2,("Before ASIOGetBufferSize()\n"));
211 if( (asioError = ASIOGetBufferSize(&driverInfo->minBufSize,&driverInfo->maxBufSize,&driverInfo->preferredBufSize,&driverInfo->bufGranularity) != ASE_OK)) {
212 dmsg(2,("ASIO_OpenAndQueryDeviceInfo could not ASIOGetBufferSize for %s\n", driverName));
213 return asioError;
214 }
215
216 dmsg(2,("ASIO_OpenAndQueryDeviceInfo: InputChannels = %d\n", driverInfo->numInputChannels ));
217 dmsg(2,("ASIO_OpenAndQueryDeviceInfo: OutputChannels = %d\n", driverInfo->numOutputChannels ));
218
219 /* Loop through the possible sampling rates and check each to see if the device supports it. */
220 driverInfo->numSampleRates = 0;
221 driverInfo->sampleRates.clear();
222 for (int index = 0; index < MAX_NUMSAMPLINGRATES; index++) {
223 if (ASIOCanSampleRate(possibleSampleRates[index]) != ASE_NoClock) {
224 dmsg(2,("ASIOCanSampleRate: possible sample rate = %d\n", (long)possibleSampleRates[index]));
225 driverInfo->sampleRates.push_back( (int)possibleSampleRates[index] );
226 driverInfo->numSampleRates++;
227 }
228 }
229
230 /* get the channel infos for each output channel (including sample format) */
231 for(int i=0 ; i < driverInfo->numOutputChannels ; i++) {
232 driverInfo->channelInfos[i].channel = i;
233 driverInfo->channelInfos[i].isInput = ASIOFalse;
234 ASIOGetChannelInfo(&driverInfo->channelInfos[i]);
235 dmsg(2,("channelInfos[%d].type (sampleformat) = %d\n", i, driverInfo->channelInfos[i].type));
236 }
237
238 dmsg(2,("ASIO_OpenAndQueryDeviceInfo: driver opened.\n"));
239 asioDriverOpened = true;
240 return ASE_OK;
241 }
242
243
244 std::vector<String> getAsioDriverNames() {
245
246 char* names[ASIO_MAX_DEVICE_INFO];
247 int numDrivers;
248
249 if(asioDriverListLoaded) {
250 dmsg(2,("getAsioDriverNames: ASIO driver list already loaded, doing returning cached list.\n"));
251 return asioDriverList;
252 }
253
254 /* MUST BE CHECKED : to force fragments loading on Mac */
255 ASIO_loadAsioDriver("dummy");
256
257 #if MAC
258 numDrivers = asioDrivers->getNumFragments();
259 #elif WINDOWS
260 numDrivers = asioDrivers->asioGetNumDev();
261 #endif
262
263 for (int i = 0 ; i < ASIO_MAX_DEVICE_INFO ; i++) {
264 names[i] = new char[32];
265 memset(names[i],0,32);
266 }
267
268 /* Get names of all available ASIO drivers */
269 asioDrivers->getDriverNames(names,ASIO_MAX_DEVICE_INFO);
270 dmsg(2,("getAsioDriverNames: numDrivers=%d\n",numDrivers));
271
272 for (int i = 0 ; i < numDrivers ; i++) {
273 dmsg(2,("ASIO DRIVERLIST: i=%d name='%s'\n",i,names[i]));
274
275 #if 1
276 asioDriverList.push_back(names[i]);
277 #else
278 int asioError;
279 // FIXME: we currently try what is the best methode to exclude not connected devices or not working drivers
280 // the code below is for testing only, it tried to load each ASIO driver and if it gives an error it is not included
281 // in the list of available drivers (asioDriverList)
282 if ( ASIO_loadAsioDriver(names[i]) ) {
283 if( (asioError = ASIOInit(&MyAsioDriverInfo)) == ASE_OK ) {
284 asioDriverList.push_back(names[i]);
285 }
286 else {
287 dmsg(2,("getDriverList: ASIOInit of driver %s gave Error %d ! ignoring it.\n", names[i],asioError));
288 }
289 }
290 else {
291 dmsg(2,("getDriverList: load driver %s failed! ignoring it.\n", names[i]));
292 }
293 // FIXME: we need to check this ASIOExit is needed (gave a crash on a ASIO ADSP24(WDM) card so we commented it out)
294 //ASIOExit();
295 #endif
296 //currentAsioDriverName="";
297
298 }
299
300 for (int i = 0 ; i < ASIO_MAX_DEVICE_INFO ; i++) {
301 delete[] names[i];
302 }
303
304 dmsg(2,("getAsioDriverNames: returing from function. asioDriverList.size()=%d\n", asioDriverList.size() ));
305 asioDriverListLoaded = true;
306 return asioDriverList;
307 }
308
309 unsigned long get_sys_reference_time()
310 {
311 // get the system reference time
312 #if WINDOWS
313 return timeGetTime();
314 #elif MAC
315 static const double twoRaisedTo32 = 4294967296.;
316 UnsignedWide ys;
317 Microseconds(&ys);
318 double r = ((double)ys.hi * twoRaisedTo32 + (double)ys.lo);
319 return (unsigned long)(r / 1000.);
320 #endif
321 }
322
323
324 //----------------------------------------------------------------------------------
325 // conversion from 64 bit ASIOSample/ASIOTimeStamp to double float
326 #if NATIVE_INT64
327 #define ASIO64toDouble(a) (a)
328 #else
329 const double twoRaisedTo32 = 4294967296.;
330 #define ASIO64toDouble(a) ((a).lo + (a).hi * twoRaisedTo32)
331 #endif
332
333
334 ASIOTime* AudioOutputDeviceAsio::bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool processNow)
335 {
336
337 static long processedSamples = 0;
338 // store the timeInfo for later use
339 asioDriverInfo.tInfo = *timeInfo;
340
341 // get the time stamp of the buffer, not necessary if no
342 // synchronization to other media is required
343 if (timeInfo->timeInfo.flags & kSystemTimeValid)
344 asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime);
345 else
346 asioDriverInfo.nanoSeconds = 0;
347
348 if (timeInfo->timeInfo.flags & kSamplePositionValid)
349 asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition);
350 else
351 asioDriverInfo.samples = 0;
352
353 if (timeInfo->timeCode.flags & kTcValid)
354 asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples);
355 else
356 asioDriverInfo.tcSamples = 0;
357
358 // TODO: ignore for now. get the system reference time
359 // asioDriverInfo.sysRefTime = get_sys_reference_time();
360
361 // buffer size in samples
362 long buffSize = asioDriverInfo.chosenBufSize;
363 int32_t *p;
364
365 // tell LinuxSampler to render a fragment of buffSize samples
366 GlobalAudioOutputDeviceAsioThisPtr->RenderAudio(buffSize);
367
368 // now write and convert the samples to the ASIO buffer
369 for (int i = 0; i < asioDriverInfo.numOutputBuffers; i++)
370 {
371 // do processing for the outputs only
372 switch (asioDriverInfo.channelInfos[i].type)
373 {
374 case ASIOSTInt16LSB:
375 floatToASIOSTInt16LSB(GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
376 (int16_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
377 break;
378 case ASIOSTInt24LSB: // used for 20 bits as well
379 memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3);
380 break;
381 case ASIOSTInt32LSB:
382 floatToASIOSTInt32LSB(GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
383 (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
384 break;
385 case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
386 throw AudioOutputException(String("ASIO Error: ASIOSTFloat32LSB not yet supported! report to LinuxSampler developers.") );
387 break;
388 case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
389 throw AudioOutputException(String("ASIO Error: ASIOSTFloat64LSB not yet supported! report to LinuxSampler developers.") );
390 break;
391
392 // these are used for 32 bit data buffer, with different alignment of the data inside
393 // 32 bit PCI bus systems can more easily used with these
394 case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment
395 floatToASIOSTInt32LSBXX<16>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
396 (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
397 break;
398 case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
399 floatToASIOSTInt32LSBXX<18>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
400 (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
401 break;
402 case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
403 floatToASIOSTInt32LSBXX<20>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
404 (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
405 break;
406 case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
407 floatToASIOSTInt32LSBXX<24>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(),
408 (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize);
409 break;
410 case ASIOSTInt16MSB:
411 throw AudioOutputException(String("ASIO Error: ASIOSTInt16MSB not yet supported! report to LinuxSampler developers.") );
412 break;
413 case ASIOSTInt24MSB: // used for 20 bits as well
414 throw AudioOutputException(String("ASIO Error: ASIOSTInt24MSB not yet supported! report to LinuxSampler developers.") );
415 break;
416 case ASIOSTInt32MSB:
417 throw AudioOutputException(String("ASIO Error: ASIOSTInt32MSB not yet supported! report to LinuxSampler developers.") );
418 break;
419 case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on bigendian architecture
420 throw AudioOutputException(String("ASIO Error: ASIOSTFloat32MSB not yet supported! report to LinuxSampler developers.") );
421 break;
422 case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on bigendian architecture
423 throw AudioOutputException(String("ASIO Error: ASIOSTFloat64MSB not yet supported! report to LinuxSampler developers.") );
424 break;
425
426 // these are used for 32 bit data buffer, with different alignment of the data inside
427 // 32 bit PCI bus systems can more easily used with these
428 case ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment
429 throw AudioOutputException(String("ASIO Error: ASIOSTInt32MSB16 not yet supported! report to LinuxSampler developers.") );
430 break;
431 case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
432 throw AudioOutputException(String("ASIO Error: ASIOSTInt32MSB18 not yet supported! report to LinuxSampler developers.") );
433 break;
434 case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
435 throw AudioOutputException(String("ASIO Error: ASIOSTInt32MSB20 not yet supported! report to LinuxSampler developers.") );
436 break;
437 case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
438 throw AudioOutputException(String("ASIO Error: ASIOSTInt32MSB24 not yet supported! report to LinuxSampler developers.") );
439 break;
440 default:
441 throw AudioOutputException(String("ASIO Error: unknown ASIOST sample format. report error.") );
442 break;
443 }
444 }
445
446 // finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place
447 if (asioDriverInfo.ASIOOutputReadySupported)
448 ASIOOutputReady();
449
450 processedSamples += buffSize;
451 return 0L;
452 }
453
454 void AudioOutputDeviceAsio::bufferSwitch(long index, ASIOBool processNow)
455 {
456 // the actual processing callback.
457 // as this is a "back door" into the bufferSwitchTimeInfo a timeInfo needs to be created
458 // though it will only set the timeInfo.samplePosition and timeInfo.systemTime fields and the according flags
459 ASIOTime timeInfo;
460 memset (&timeInfo, 0, sizeof (timeInfo));
461
462 // get the time stamp of the buffer, not necessary if no
463 // synchronization to other media is required
464 if(ASIOGetSamplePosition(&timeInfo.timeInfo.samplePosition, &timeInfo.timeInfo.systemTime) == ASE_OK)
465 timeInfo.timeInfo.flags = kSystemTimeValid | kSamplePositionValid;
466
467 bufferSwitchTimeInfo (&timeInfo, index, processNow);
468 }
469
470 void sampleRateChanged(ASIOSampleRate sRate)
471 {
472 // do whatever you need to do if the sample rate changed
473 // usually this only happens during external sync.
474 // Audio processing is not stopped by the driver, actual sample rate
475 // might not have even changed, maybe only the sample rate status of an
476 // AES/EBU or S/PDIF digital input at the audio device.
477 // You might have to update time/sample related conversion routines, etc.
478 }
479
480 long asioMessages(long selector, long value, void* message, double* opt)
481 {
482 dmsg(2,("asioMessages selector=%d value=%d\n",selector,value));
483 // currently the parameters "value", "message" and "opt" are not used.
484 long ret = 0;
485 switch(selector)
486 {
487 case kAsioSelectorSupported:
488 if(value == kAsioResetRequest
489 || value == kAsioEngineVersion
490 || value == kAsioResyncRequest
491 || value == kAsioLatenciesChanged
492 // the following three were added for ASIO 2.0, we don't necessarily have to support them
493 || value == kAsioSupportsTimeInfo
494 || value == kAsioSupportsTimeCode
495 || value == kAsioSupportsInputMonitor)
496 ret = 1L;
497 break;
498 case kAsioResetRequest:
499 // defer the task and perform the reset of the driver during the next "safe" situation
500 // You cannot reset the driver right now, as this code is called from the driver.
501 // Reset the driver is done by completely destruct is. I.e. ASIOStop(), ASIODisposeBuffers(), Destruction
502 // Afterwards you initialize the driver again.
503 //GlobalAudioOutputDeviceAsioThisPtr->asioDriverInfo.stopped; // In this sample the processing will just stop
504 ret = 1L;
505 break;
506 case kAsioResyncRequest:
507 // This informs the application, that the driver encountered some non fatal data loss.
508 // It is used for synchronization purposes of different media.
509 // Added mainly to work around the Win16Mutex problems in Windows 95/98 with the
510 // Windows Multimedia system, which could loose data because the Mutex was hold too long
511 // by another thread.
512 // However a driver can issue it in other situations, too.
513 ret = 1L;
514 break;
515 case kAsioLatenciesChanged:
516 // This will inform the host application that the drivers were latencies changed.
517 // Beware, it this does not mean that the buffer sizes have changed!
518 // You might need to update internal delay data.
519 ret = 1L;
520 break;
521 case kAsioEngineVersion:
522 // return the supported ASIO version of the host application
523 // If a host applications does not implement this selector, ASIO 1.0 is assumed
524 // by the driver
525 ret = 2L;
526 break;
527 case kAsioSupportsTimeInfo:
528 // informs the driver wether the asioCallbacks.bufferSwitchTimeInfo() callback
529 // is supported.
530 // For compatibility with ASIO 1.0 drivers the host application should always support
531 // the "old" bufferSwitch method, too.
532 ret = 1;
533 break;
534 case kAsioSupportsTimeCode:
535 // informs the driver wether application is interested in time code info.
536 // If an application does not need to know about time code, the driver has less work
537 // to do.
538 ret = 0;
539 break;
540 }
541 return ret;
542 }
543
544
545 // *************** ParameterCard ***************
546 // *
547
548 AudioOutputDeviceAsio::ParameterCard::ParameterCard() : DeviceCreationParameterString() {
549 InitWithDefault(); // use default card
550 }
551
552 AudioOutputDeviceAsio::ParameterCard::ParameterCard(String s) throw (Exception) : DeviceCreationParameterString(s) {
553 }
554
555 String AudioOutputDeviceAsio::ParameterCard::Description() {
556 return "Sound card to be used";
557 }
558
559 bool AudioOutputDeviceAsio::ParameterCard::Fix() {
560 return true;
561 }
562
563 bool AudioOutputDeviceAsio::ParameterCard::Mandatory() {
564 return false;
565 }
566
567 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAsio::ParameterCard::DependsAsParameters() {
568 return std::map<String,DeviceCreationParameter*>(); // no dependencies
569 }
570
571 optional<String> AudioOutputDeviceAsio::ParameterCard::DefaultAsString(std::map<String,String> Parameters) {
572
573 std::vector<String> cards = PossibilitiesAsString(Parameters);
574 if (cards.empty()) throw Exception("AudioOutputDeviceAsio: Can't find any card");
575 dmsg(2,("AudioOutputDeviceAsio::ParameterCard::DefaultAsString='%s'\n",cards[0].c_str() ));
576
577 // if currentAsioDriverName is empty then return the first card
578 // otherwise return the currentAsioDriverName. this avoids closing the current ASIO driver
579 // when the LSCP client calls commands like GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO ASIO CARD
580 // which would load the default card (without this check it would always be the same which would cause the above problem)
581 if( currentAsioDriverName == "" ) {
582 return cards[0]; // first card by default
583 }
584 else {
585 return currentAsioDriverName;
586 }
587
588 }
589
590 std::vector<String> AudioOutputDeviceAsio::ParameterCard::PossibilitiesAsString(std::map<String,String> Parameters) {
591 dmsg(2,("AudioOutputDeviceAsio::ParameterCard::PossibilitiesAsString:\n"));
592 return getAsioDriverNames();
593 }
594
595 void AudioOutputDeviceAsio::ParameterCard::OnSetValue(String s) throw (Exception) {
596 // not posssible, as parameter is fix
597 }
598
599 String AudioOutputDeviceAsio::ParameterCard::Name() {
600 return "CARD";
601 }
602
603
604
605 // *************** ParameterSampleRate ***************
606 // *
607
608 AudioOutputDeviceAsio::ParameterSampleRate::ParameterSampleRate() : AudioOutputDevice::ParameterSampleRate::ParameterSampleRate() {
609 }
610
611 AudioOutputDeviceAsio::ParameterSampleRate::ParameterSampleRate(String s) : AudioOutputDevice::ParameterSampleRate::ParameterSampleRate(s) {
612 }
613
614 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAsio::ParameterSampleRate::DependsAsParameters() {
615 static ParameterCard card;
616 std::map<String,DeviceCreationParameter*> dependencies;
617 dependencies[card.Name()] = &card;
618 return dependencies;
619 }
620
621 optional<int> AudioOutputDeviceAsio::ParameterSampleRate::DefaultAsInt(std::map<String,String> Parameters) {
622 if (!Parameters.count("CARD")) {
623 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::DefaultAsInt returning optional<int>::nothing (parameter CARD not supplied)\n"));
624 return optional<int>::nothing;
625 }
626
627 // return the default samplerate. first try 44100 then 48000, then the first samplerate found in the list
628 ParameterCard card(Parameters["CARD"]);
629 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
630 throw AudioOutputException(String("Error: ASIO Initalization Error") );
631 }
632 for(int i = 0 ; i < asioDriverInfo.sampleRates.size() ; i++) {
633 if(asioDriverInfo.sampleRates[i] == 44100) {
634 return 44100;
635 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::DefaultAsInt returning 44100\n"));
636 }
637 if(asioDriverInfo.sampleRates[i] == 48000) {
638 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::DefaultAsInt returning 48000\n"));
639 return 48000;
640 }
641 }
642 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::DefaultAsInt returning %d\n",asioDriverInfo.sampleRates[0]));
643 return asioDriverInfo.sampleRates[0];
644 }
645
646 std::vector<int> AudioOutputDeviceAsio::ParameterSampleRate::PossibilitiesAsInt(std::map<String,String> Parameters) {
647 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::PossibilitiesAsInt\n"));
648 if (!Parameters.count("CARD")) {
649 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::PossibilitiesAsInt returning empty vector (parameter CARD not supplied)\n"));
650 return std::vector<int>();
651 }
652
653 ParameterCard card(Parameters["CARD"]);
654 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
655 throw AudioOutputException(String("Error: ASIO Initalization Error") );
656 }
657
658 for(int i=0;i<asioDriverInfo.sampleRates.size();i++) {
659 dmsg(2,("AudioOutputDeviceAsio::ParameterSampleRate::PossibilitiesAsInt samplerate[%d]=%d\n",i,asioDriverInfo.sampleRates[i]));
660 }
661
662 return asioDriverInfo.sampleRates;
663 }
664
665
666
667 // *************** ParameterChannels ***************
668 // *
669
670 AudioOutputDeviceAsio::ParameterChannels::ParameterChannels() : AudioOutputDevice::ParameterChannels::ParameterChannels() {
671 //InitWithDefault();
672 // could not determine default value? ...
673 //if (ValueAsInt() == 0) SetValue(2); // ... then (try) a common value
674 }
675
676 AudioOutputDeviceAsio::ParameterChannels::ParameterChannels(String s) : AudioOutputDevice::ParameterChannels::ParameterChannels(s) {
677 }
678
679 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAsio::ParameterChannels::DependsAsParameters() {
680 static ParameterCard card;
681 std::map<String,DeviceCreationParameter*> dependencies;
682 dependencies[card.Name()] = &card;
683 return dependencies;
684 }
685
686 optional<int> AudioOutputDeviceAsio::ParameterChannels::DefaultAsInt(std::map<String,String> Parameters) {
687 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::DefaultAsInt\n"));
688 if (!Parameters.count("CARD")) {
689 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::DefaultAsInt returning optional<int>::nothing (CARD parameter not supplied)\n"));
690 return optional<int>::nothing;
691 }
692
693 ParameterCard card(Parameters["CARD"]);
694 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
695 throw AudioOutputException(String("Error: ASIO Initialization Error") );
696 }
697 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::DefaultAsInt returning %d\n",asioDriverInfo.numOutputChannels));
698 return asioDriverInfo.numOutputChannels;
699 }
700
701 optional<int> AudioOutputDeviceAsio::ParameterChannels::RangeMinAsInt(std::map<String,String> Parameters) {
702 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMinAsInt!\n"));
703 if (!Parameters.count("CARD")) {
704 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMinAsInt returning optional<int>::nothing (CARD parameter not supplied)\n"));
705 return optional<int>::nothing;
706 }
707 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMinAsInt returning 1\n"));
708 return 1;
709 }
710
711 optional<int> AudioOutputDeviceAsio::ParameterChannels::RangeMaxAsInt(std::map<String,String> Parameters) {
712 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMaxAsInt!\n"));
713 if (!Parameters.count("CARD")) {
714 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMaxAsInt returning optional<int>::nothing (CARD parameter not supplied)\n"));
715 return optional<int>::nothing;
716 }
717
718 ParameterCard card(Parameters["CARD"]);
719 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
720 throw AudioOutputException(String("Error: ASIO Init Error") );
721 }
722 dmsg(2,("AudioOutputDeviceAsio::ParameterChannels::RangeMaxAsInt returning %d\n",asioDriverInfo.numOutputChannels));
723 return asioDriverInfo.numOutputChannels;
724 }
725
726
727
728 // *************** ParameterFragmentSize ***************
729 // *
730
731 AudioOutputDeviceAsio::ParameterFragmentSize::ParameterFragmentSize() : DeviceCreationParameterInt() {
732 InitWithDefault();
733 }
734
735 AudioOutputDeviceAsio::ParameterFragmentSize::ParameterFragmentSize(String s) throw (Exception) : DeviceCreationParameterInt(s) {
736 }
737
738 String AudioOutputDeviceAsio::ParameterFragmentSize::Description() {
739 return "Size of each buffer fragment";
740 }
741
742 bool AudioOutputDeviceAsio::ParameterFragmentSize::Fix() {
743 return true;
744 }
745
746 bool AudioOutputDeviceAsio::ParameterFragmentSize::Mandatory() {
747 return false;
748 }
749
750 std::map<String,DeviceCreationParameter*> AudioOutputDeviceAsio::ParameterFragmentSize::DependsAsParameters() {
751 static ParameterCard card;
752 std::map<String,DeviceCreationParameter*> dependencies;
753 dependencies[card.Name()] = &card;
754 return dependencies;
755 }
756
757 optional<int> AudioOutputDeviceAsio::ParameterFragmentSize::DefaultAsInt(std::map<String,String> Parameters) {
758 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::DefaultAsInt!\n"));
759 if (!Parameters.count("CARD")) {
760 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::DefaultAsInt returning optional<int>::nothing (no CARD parameter supplied\n"));
761 return optional<int>::nothing;
762 }
763
764 ParameterCard card(Parameters["CARD"]);
765 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
766 throw AudioOutputException(String("Error: ASIO Initialization Error") );
767 }
768 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::DefaultAsInt returning %d\n",asioDriverInfo.preferredBufSize));
769 return asioDriverInfo.preferredBufSize;
770 }
771
772 optional<int> AudioOutputDeviceAsio::ParameterFragmentSize::RangeMinAsInt(std::map<String,String> Parameters) {
773 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMinAsInt!\n"));
774 if (!Parameters.count("CARD")) {
775 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMinAsInt returning optional<int>::nothing (no CARD parameter supplied\n"));
776 return optional<int>::nothing;
777 }
778
779 ParameterCard card(Parameters["CARD"]);
780 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
781 throw AudioOutputException(String("Error: ASIO Initalization Error") );
782 }
783 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMinAsInt returning %d\n",asioDriverInfo.minBufSize));
784 return asioDriverInfo.minBufSize;
785 }
786
787 optional<int> AudioOutputDeviceAsio::ParameterFragmentSize::RangeMaxAsInt(std::map<String,String> Parameters) {
788 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMaxAsInt!\n"));
789 if (!Parameters.count("CARD")) {
790 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMaxAsInt returning optional<int>::nothing (no CARD parameter supplied\n"));
791 return optional<int>::nothing;
792 }
793
794 ParameterCard card(Parameters["CARD"]);
795 if( ASIO_OpenAndQueryDeviceInfo((char *)card.ValueAsString().c_str(), &asioDriverInfo, &MyAsioDriverInfo) != ASE_OK) {
796 throw AudioOutputException(String("Error: ASIO Initialization Error") );
797 }
798 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::RangeMaxAsInt returning %d\n",asioDriverInfo.maxBufSize));
799 return asioDriverInfo.maxBufSize;
800 }
801
802 std::vector<int> AudioOutputDeviceAsio::ParameterFragmentSize::PossibilitiesAsInt(std::map<String,String> Parameters) {
803 dmsg(2,("AudioOutputDeviceAsio::ParameterFragmentSize::PossibilitiesAsInt!\n"));
804 return std::vector<int>();
805 }
806
807 void AudioOutputDeviceAsio::ParameterFragmentSize::OnSetValue(int i) throw (Exception) {
808 // not posssible, as parameter is fix
809 }
810
811 String AudioOutputDeviceAsio::ParameterFragmentSize::Name() {
812 return "FRAGMENTSIZE";
813 }
814
815
816
817 // *************** AudioOutputDeviceAsio ***************
818 // *
819
820 /**
821 * Create and initialize Asio audio output device with given parameters.
822 *
823 * @param Parameters - optional parameters
824 * @throws AudioOutputException if output device cannot be opened
825 */
826 AudioOutputDeviceAsio::AudioOutputDeviceAsio(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters) {
827 if(AudioOutputDeviceAsioInstantiated) throw Exception("AudioOutputDeviceAsio: Sorry, only one ASIO card at time can be opened");
828 AudioOutputDeviceAsioInstantiated = true;
829 asioDriverOpened = false;
830 this->uiAsioChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt();
831 this->uiSamplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt();
832 this->FragmentSize = ((DeviceCreationParameterInt*)Parameters["FRAGMENTSIZE"])->ValueAsInt();
833 String Card = ((DeviceCreationParameterString*)Parameters["CARD"])->ValueAsString();
834
835
836 dmsg(2,("AudioOutputDeviceAsio::AudioOutputDeviceAsio constructor\n"));
837
838 asioIsPlaying = false;
839
840 ASIO_OpenAndQueryDeviceInfo((char *)Card.c_str(), &asioDriverInfo, &MyAsioDriverInfo);
841 dmsg(2,("AudioOutputDeviceAsio::AudioOutputDeviceAsio: after ASIO_OpenAndQueryDeviceInfo\n"));
842
843 if( ASIOSetSampleRate(uiSamplerate) != ASE_OK ) {
844 throw AudioOutputException(String("Error: ASIOSetSampleRate: cannot set samplerate. ") );
845 }
846 dmsg(2,("AudioOutputDeviceAsio::AudioOutputDeviceAsio: after ASIOSetSampleRate\n"));
847
848 if(ASIOOutputReady() == ASE_OK) asioDriverInfo.ASIOOutputReadySupported = true;
849 else asioDriverInfo.ASIOOutputReadySupported = false;
850 dmsg(2,("AudioOutputDeviceAsio::AudioOutputDeviceAsio: after ASIOOutputReady\n"));
851
852 asioDriverInfo.numInputBuffers = 0;
853 asioDriverInfo.numOutputBuffers = uiAsioChannels;
854 asioDriverInfo.chosenBufSize = FragmentSize;
855
856 for( int i = 0 ; i < uiAsioChannels ; i++) {
857 asioDriverInfo.bufferInfos[i].isInput = ASIOFalse;
858 asioDriverInfo.bufferInfos[i].channelNum = i;
859 }
860
861 asioCallbacks.bufferSwitch = &bufferSwitch;
862 asioCallbacks.sampleRateDidChange = &sampleRateChanged;
863 asioCallbacks.asioMessage = &asioMessages;
864 asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo;
865
866 if ( ASIOCreateBuffers(asioDriverInfo.bufferInfos, asioDriverInfo.numOutputBuffers, asioDriverInfo.chosenBufSize = FragmentSize, &asioCallbacks) != ASE_OK ){
867 throw AudioOutputException(String("AudioOutputDeviceAsio: Error: ASIOCreateBuffers failed.") );
868 }
869 dmsg(2,("AudioOutputDeviceAsio::AudioOutputDeviceAsio: after ASIOCreateBuffers\n"));
870
871 // create audio channels for this audio device to which the sampler engines can write to
872 for (int i = 0; i < uiAsioChannels; i++) this->Channels.push_back(new AudioChannel(i, FragmentSize));
873
874 // FIXME: temporary global variable used to store the this pointer for the ASIO callbacks wanting to access the AudioOutputDeviceAsio methods
875 GlobalAudioOutputDeviceAsioThisPtr = this;
876
877 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
878 Play();
879 }
880 }
881
882 AudioOutputDeviceAsio::~AudioOutputDeviceAsio() {
883 ASIOExit();
884 asioDriverOpened = false;
885 AudioOutputDeviceAsioInstantiated = false;
886 }
887
888 void AudioOutputDeviceAsio::Play() {
889 dmsg(2,("AudioOutputDeviceAsio::Play() !\n"));
890 if ( ASIOStart() != ASE_OK ){
891 asioIsPlaying = false;
892 throw AudioOutputException(String("AudioOutputDeviceAsio: Error: ASIOStart failed.") );
893 }
894 else asioIsPlaying = true;
895 }
896
897 bool AudioOutputDeviceAsio::IsPlaying() {
898 return asioIsPlaying;
899 }
900
901 void AudioOutputDeviceAsio::Stop() {
902 dmsg(2,("AudioOutputDeviceAsio::Stop() !\n"));
903 ASIOStop();
904 asioIsPlaying = false;
905 }
906
907 AudioChannel* AudioOutputDeviceAsio::CreateChannel(uint ChannelNr) {
908 dmsg(2,("AudioOutputDeviceAsio::CreateChannel value=%d uiAsioChannels=%d\n",ChannelNr,uiAsioChannels));
909 // just create a mix channel
910 return new AudioChannel(ChannelNr, Channel(ChannelNr % uiAsioChannels));
911 }
912
913 uint AudioOutputDeviceAsio::MaxSamplesPerCycle() {
914 dmsg(2,("AudioOutputDeviceAsio::MaxSamplesPerCycle value=%d\n",FragmentSize));
915 return FragmentSize;
916 }
917
918 uint AudioOutputDeviceAsio::SampleRate() {
919 dmsg(2,("AudioOutputDeviceAsio::SampleRate value=%d\n",uiSamplerate)); fflush(stdout);
920 return uiSamplerate;
921 }
922
923 String AudioOutputDeviceAsio::Name() {
924 return "ASIO";
925 }
926
927 String AudioOutputDeviceAsio::Driver() {
928 return Name();
929 }
930
931 String AudioOutputDeviceAsio::Description() {
932 return "Audio Streaming Input Output 2.2";
933 }
934
935 String AudioOutputDeviceAsio::Version() {
936 String s = "$Revision: 1.4 $";
937 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
938 }
939
940 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC