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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1500 - (hide annotations) (download)
Wed Nov 21 00:52:09 2007 UTC (16 years, 5 months ago) by senoner
File size: 39686 byte(s)
* win32 port, work in progress:
 - added ASIO low latency audio output driver
* MME MIDI input driver:
 - fixed number of PORTS to 1 as the win32 MME MIDI API
 allows to connect to only one MIDI port at time,

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

  ViewVC Help
Powered by ViewVC