/[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 1948 - (show annotations) (download)
Sun Jul 19 11:12:13 2009 UTC (11 years, 4 months ago) by persson
File size: 40604 byte(s)
* code cleanup of the ASIO driver
* minor Makefile fix for parallel make

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

  ViewVC Help
Powered by ViewVC