/[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 2494 - (show annotations) (download)
Wed Jan 1 17:48:01 2014 UTC (10 years, 3 months ago) by schoenebeck
File size: 41121 byte(s)
* Enabled automatic svn "Revision" macro expansion on certain files.
* Bumped version to 1.0.0.svn24.

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

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC