Index: linuxsampler/src/drivers/audio/AudioOutputDeviceAsio.cpp =================================================================== RCS file: /var/cvs/linuxsampler/linuxsampler/src/drivers/audio/AudioOutputDeviceAsio.cpp,v retrieving revision 1.2 diff -u -2 -r1.2 AudioOutputDeviceAsio.cpp --- linuxsampler/src/drivers/audio/AudioOutputDeviceAsio.cpp 19 Jan 2008 16:55:03 -0000 1.2 +++ linuxsampler/src/drivers/audio/AudioOutputDeviceAsio.cpp 5 Apr 2009 15:48:16 -0000 @@ -90,5 +90,5 @@ static DriverInfo asioDriverInfo = {0}; -static bool asioDriverOpened; +static bool asioDriverOpened = false; static bool AudioOutputDeviceAsioInstantiated = false; static String currentAsioDriverName; @@ -104,5 +104,18 @@ AudioOutputDeviceAsio *GlobalAudioOutputDeviceAsioThisPtr; -void floatToASIOSTInt16LSB(float *in, void *dest, int numSamples) { +template +static void floatToASIOSTInt32LSBXX(float *in, void *dest, int numSamples) { + double pos_max_value = (1 << bitres) -1.0; + double neg_max_value = -pos_max_value; + int32_t *out = (int32_t *)dest; + for(int i=0; i < numSamples ; i++) { + double sample_point = in[i] * pos_max_value; + if (sample_point < neg_max_value) sample_point = neg_max_value; + if (sample_point > pos_max_value) sample_point = pos_max_value; + out[i] = (int16_t)sample_point; + } +} + +static void floatToASIOSTInt16LSB(float *in, void *dest, int numSamples) { int16_t *out = (int16_t *)dest; for(int i=0; i < numSamples ; i++) { @@ -114,5 +127,5 @@ } -void floatToASIOSTInt32LSB(float *in, void *dest, int numSamples) { +static void floatToASIOSTInt32LSB(float *in, void *dest, int numSamples) { int32_t *out = (int32_t *)dest; for(int i=0; i < numSamples ; i++) { @@ -124,4 +137,6 @@ } +std::vector getAsioDriverNames(); + static bool ASIO_loadAsioDriver(char *name) { @@ -141,4 +156,12 @@ ASIOError asioError; + // call this function in order to fill the internal vector containing the list of ASIO cards + // since the reading of the list is performed only one time subsequent calls to this function will be automatically ignored + // calling getAsioDriverNames() is needed in the case of a LinuxSampler client application first creating an ASIO device + // which calls ASIO_OpenAndQueryDeviceInfo() and afterwards retrieve the list of available ASIO cards + // since getAsioDriverNames() unloads the current driver and loads the driver 'dummy' this would cause + // the audio stopping and forcing the create the audio output device again + getAsioDriverNames(); + dmsg(1,("ASIO_OpenAndQueryDeviceInfo driverName='%s' current='%s'\n",driverName, currentAsioDriverName.c_str() )); if(!strcmp(driverName, currentAsioDriverName.c_str() )) { @@ -271,5 +294,5 @@ //ASIOExit(); #endif - currentAsioDriverName=""; + //currentAsioDriverName=""; } @@ -333,6 +356,6 @@ asioDriverInfo.tcSamples = 0; - // get the system reference time - asioDriverInfo.sysRefTime = get_sys_reference_time(); + // TODO: ignore for now. get the system reference time + // asioDriverInfo.sysRefTime = get_sys_reference_time(); // buffer size in samples @@ -350,5 +373,6 @@ { case ASIOSTInt16LSB: - memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2); + floatToASIOSTInt16LSB(GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int16_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTInt24LSB: // used for 20 bits as well @@ -356,6 +380,6 @@ break; case ASIOSTInt32LSB: - p = (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index]; - floatToASIOSTInt32LSB(GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), p, buffSize); + floatToASIOSTInt32LSB(GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture @@ -368,15 +392,19 @@ // these are used for 32 bit data buffer, with different alignment of the data inside // 32 bit PCI bus systems can more easily used with these - case ASIOSTInt32LSB16: // 32 bit data with 18 bit alignment - throw AudioOutputException(String("ASIO Error: ASIOSTInt32LSB16 not yet supported! report to LinuxSampler developers.") ); + case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment + floatToASIOSTInt32LSBXX<16>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment - throw AudioOutputException(String("ASIO Error: ASIOSTInt32LSB18 not yet supported! report to LinuxSampler developers.") ); + floatToASIOSTInt32LSBXX<18>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment - throw AudioOutputException(String("ASIO Error: ASIOSTInt32LSB20 not yet supported! report to LinuxSampler developers.") ); + floatToASIOSTInt32LSBXX<20>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment - throw AudioOutputException(String("ASIO Error: ASIOSTInt32LSB24 not yet supported! report to LinuxSampler developers.") ); + floatToASIOSTInt32LSBXX<24>( GlobalAudioOutputDeviceAsioThisPtr->Channels[i]->Buffer(), + (int32_t *)asioDriverInfo.bufferInfos[i].buffers[index], buffSize); break; case ASIOSTInt16MSB: @@ -546,5 +574,16 @@ if (cards.empty()) throw Exception("AudioOutputDeviceAsio: Can't find any card"); dmsg(1,("AudioOutputDeviceAsio::ParameterCard::DefaultAsString='%s'\n",cards[0].c_str() )); - return cards[0]; // first card by default + + // if currentAsioDriverName is empty then return the first card + // otherwise return the currentAsioDriverName. this avoids closing the current ASIO driver + // when the LSCP client calls commands like GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO ASIO CARD + // which would load the default card (without this check it would always be the same which would cause the above problem) + if( currentAsioDriverName == "" ) { + return cards[0]; // first card by default + } + else { + return currentAsioDriverName; + } + }