diff --git a/windows/sound.cpp b/windows/sound.cpp index 4e57d61f..06943201 100755 --- a/windows/sound.cpp +++ b/windows/sound.cpp @@ -47,10 +47,8 @@ bool CSound::Read ( CVector& psData ) // check if device must be opened or reinitialized if ( bChangParamIn == TRUE ) { - OpenInDevice(); - // Reinit sound interface - InitRecording ( iBufferSizeIn, bBlockingRec ); + InitRecordingAndPlayback ( iBufferSize ); // Reset flag bChangParamIn = FALSE; @@ -98,7 +96,7 @@ bool CSound::Read ( CVector& psData ) */ // copy data from sound card in output buffer - for ( i = 0; i < iBufferSizeIn; i++ ) + for ( i = 0; i < iBufferSize; i++ ) { psData[i] = psSoundcardBuffer[iWhichBufferIn][i]; } @@ -147,106 +145,6 @@ void CSound::PrepareInBuffer ( int iBufNum ) */ } -void CSound::InitRecording ( int iNewBufferSize, bool bNewBlocking ) -{ - // check if device must be opened or reinitialized - if ( bChangParamIn == TRUE ) - { - OpenInDevice(); - - // reset flag - bChangParamIn = FALSE; - } - - // set internal parameter - iBufferSizeIn = iNewBufferSize; - bBlockingRec = bNewBlocking; - -/* - // reset interface so that all buffers are returned from the interface - waveInReset ( m_WaveIn ); - waveInStop ( m_WaveIn ); -*/ - - // reset current buffer ID (it is important to do this BEFORE calling - // "AddInBuffer()" - iWhichBufferIn = 0; - - // create memory for sound card buffer - for ( int i = 0; i < iCurNumSndBufIn; i++ ) - { -/* - // Unprepare old wave-header in case that we "re-initialized" this - // module. Calling "waveInUnprepareHeader()" with an unprepared - // buffer (when the module is initialized for the first time) has - // simply no effect - waveInUnprepareHeader ( m_WaveIn, &m_WaveInHeader[i], sizeof ( WAVEHDR ) ); -*/ - - if ( psSoundcardBuffer[i] != NULL ) - { - delete[] psSoundcardBuffer[i]; - } - - psSoundcardBuffer[i] = new short[iBufferSizeIn]; - - - /* Send all buffers to driver for filling the queue ----------------- */ - // prepare buffers before sending them to the sound interface - PrepareInBuffer ( i ); - - AddInBuffer(); - } - -/* - // notify that sound capturing can start now - waveInStart ( m_WaveIn ); -*/ - - // This reset event is very important for initialization, otherwise we will - // get errors! - ResetEvent ( m_WaveInEvent ); -} - -void CSound::OpenInDevice() -{ -/* - // open wave-input and set call-back mechanism to event handle - if ( m_WaveIn != NULL ) - { - waveInReset ( m_WaveIn ); - waveInClose ( m_WaveIn ); - } - - MMRESULT result = waveInOpen ( &m_WaveIn, iCurInDev, &sWaveFormatEx, - (DWORD) m_WaveInEvent, NULL, CALLBACK_EVENT ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface Start, waveInOpen() failed. This error " - "usually occurs if another application blocks the sound in." ); - } -*/ -} - -void CSound::SetInDev ( int iNewDev ) -{ -/* - // set device to wave mapper if iNewDev is invalid - if ( ( iNewDev >= iNumDevs ) || ( iNewDev < 0 ) ) - { - iNewDev = WAVE_MAPPER; - } -*/ - - // change only in case new device id is not already active - if ( iNewDev != iCurInDev ) - { - iCurInDev = iNewDev; - bChangParamIn = TRUE; - } -} - void CSound::SetInNumBuf ( int iNewNum ) { // check new parameter @@ -277,10 +175,8 @@ bool CSound::Write ( CVector& psData ) // check if device must be opened or reinitialized if ( bChangParamOut == TRUE ) { - OpenOutDevice(); - // reinit sound interface - InitPlayback ( iBufferSizeOut, bBlockingPlay ); + InitRecordingAndPlayback ( iBufferSize ); // reset flag bChangParamOut = FALSE; @@ -292,24 +188,14 @@ bool CSound::Write ( CVector& psData ) // now check special cases (Buffer is full or empty) if ( iCntPrepBuf == 0 ) { - if ( bBlockingPlay == TRUE ) + /* Blocking wave out routine. Needed for transmitter. Always + ensure that the buffer is completely filled to avoid buffer + underruns */ + while ( iCntPrepBuf == 0 ) { - /* Blocking wave out routine. Needed for transmitter. Always - ensure that the buffer is completely filled to avoid buffer - underruns */ - while ( iCntPrepBuf == 0 ) - { - WaitForSingleObject ( m_WaveOutEvent, INFINITE ); + WaitForSingleObject ( m_WaveOutEvent, INFINITE ); - GetDoneBuffer ( iCntPrepBuf, iIndexDoneBuf ); - } - } - else - { - /* All buffers are filled, dump new block ----------------------- */ -// It would be better to kill half of the buffer blocks to set the start -// back to the middle: TODO - return TRUE; // an error occurred + GetDoneBuffer ( iCntPrepBuf, iIndexDoneBuf ); } } else @@ -323,7 +209,7 @@ bool CSound::Write ( CVector& psData ) for ( j = 0; j < iCurNumSndBufOut / 2; j++ ) { // first, clear these buffers - for ( i = 0; i < iBufferSizeOut; i++ ) + for ( i = 0; i < iBufferSize; i++ ) { psPlaybackBuffer[j][i] = 0; } @@ -344,7 +230,7 @@ bool CSound::Write ( CVector& psData ) } // copy stereo data from input in soundcard buffer - for ( i = 0; i < iBufferSizeOut; i++ ) + for ( i = 0; i < iBufferSize; i++ ) { psPlaybackBuffer[iIndexDoneBuf][i] = psData[i]; } @@ -399,95 +285,6 @@ void CSound::PrepareOutBuffer ( int iBufNum ) */ } -void CSound::InitPlayback ( int iNewBufferSize, bool bNewBlocking ) -{ - int i, j; - - // check if device must be opened or reinitialized - if ( bChangParamOut == TRUE ) - { - OpenOutDevice(); - - // reset flag - bChangParamOut = FALSE; - } - - // set internal parameters - iBufferSizeOut = iNewBufferSize; - bBlockingPlay = bNewBlocking; - -/* - // reset interface - waveOutReset ( m_WaveOut ); -*/ - - for ( j = 0; j < iCurNumSndBufOut; j++ ) - { -/* - // Unprepare old wave-header (in case header was not prepared before, - // simply nothing happens with this function call - waveOutUnprepareHeader ( m_WaveOut, &m_WaveOutHeader[j], sizeof ( WAVEHDR ) ); -*/ - - // create memory for playback buffer - if ( psPlaybackBuffer[j] != NULL ) - { - delete[] psPlaybackBuffer[j]; - } - - psPlaybackBuffer[j] = new short[iBufferSizeOut]; - - // clear new buffer - for ( i = 0; i < iBufferSizeOut; i++ ) - { - psPlaybackBuffer[j][i] = 0; - } - - // prepare buffer for sending to the sound interface - PrepareOutBuffer ( j ); - - // initially, send all buffers to the interface - AddOutBuffer ( j ); - } -} - -void CSound::OpenOutDevice() -{ -/* - if ( m_WaveOut != NULL ) - { - waveOutReset ( m_WaveOut ); - waveOutClose ( m_WaveOut ); - } - - MMRESULT result = waveOutOpen ( &m_WaveOut, iCurOutDev, &sWaveFormatEx, - (DWORD) m_WaveOutEvent, NULL, CALLBACK_EVENT ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface Start, waveOutOpen() failed." ); - } -*/ -} - -void CSound::SetOutDev ( int iNewDev ) -{ -/* - // set device to wave mapper if iNewDev is invalid - if ( ( iNewDev >= iNumDevs ) || ( iNewDev < 0 ) ) - { - iNewDev = WAVE_MAPPER; - } -*/ - - // change only in case new device id is not already active - if ( iNewDev != iCurOutDev ) - { - iCurOutDev = iNewDev; - bChangParamOut = TRUE; - } -} - void CSound::SetOutNumBuf ( int iNewNum ) { // check new parameter @@ -508,35 +305,128 @@ void CSound::SetOutNumBuf ( int iNewNum ) /******************************************************************************\ * Common * \******************************************************************************/ -void CSound::Close() +void CSound::InitRecordingAndPlayback ( int iNewBufferSize ) { - int i; + int i, j; + + // first, stop audio + ASIOStop(); + + // set internal parameters + iBufferSize = iNewBufferSize; + + /* - MMRESULT result; - - // reset audio driver - if ( m_WaveOut != NULL ) - { - result = waveOutReset ( m_WaveOut ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveOutReset() failed." ); - } - } - - if ( m_WaveIn != NULL ) - { - result = waveInReset ( m_WaveIn ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveInReset() failed." ); - } - } + // reset interface so that all buffers are returned from the interface + waveInReset ( m_WaveIn ); + waveInStop ( m_WaveIn ); */ + // reset current buffer ID (it is important to do this BEFORE calling + // "AddInBuffer()" + iWhichBufferIn = 0; + + // create memory for sound card buffer + for ( i = 0; i < iCurNumSndBufIn; i++ ) + { +/* + // Unprepare old wave-header in case that we "re-initialized" this + // module. Calling "waveInUnprepareHeader()" with an unprepared + // buffer (when the module is initialized for the first time) has + // simply no effect + waveInUnprepareHeader ( m_WaveIn, &m_WaveInHeader[i], sizeof ( WAVEHDR ) ); +*/ + + if ( psSoundcardBuffer[i] != NULL ) + { + delete[] psSoundcardBuffer[i]; + } + + psSoundcardBuffer[i] = new short[iBufferSize]; + + + /* Send all buffers to driver for filling the queue ----------------- */ + // prepare buffers before sending them to the sound interface + PrepareInBuffer ( i ); + + AddInBuffer(); + } + +/* + // notify that sound capturing can start now + waveInStart ( m_WaveIn ); +*/ + + // This reset event is very important for initialization, otherwise we will + // get errors! + ResetEvent ( m_WaveInEvent ); + + + + +// TODO this should be done in the setinoutbuf functions + // create and activate buffers +// ASIOCreateBuffers(bufferInfos, 2 * NUM_IN_OUT_CHANNELS, +// iBufferSizeIn * BYTES_PER_SAMPLE, &asioCallbacks); + ASIOCreateBuffers(bufferInfos, 2 * NUM_IN_OUT_CHANNELS, + iBufferSize * BYTES_PER_SAMPLE, &asioCallbacks); + + // now set all the buffer details + for ( i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) + { + channelInfos[i].channel = NUM_IN_OUT_CHANNELS; + channelInfos[i].isInput = bufferInfos[i].isInput; + ASIOGetChannelInfo ( &channelInfos[i] ); + } + + + + + + + +/* + // reset interface + waveOutReset ( m_WaveOut ); +*/ + + for ( j = 0; j < iCurNumSndBufOut; j++ ) + { +/* + // Unprepare old wave-header (in case header was not prepared before, + // simply nothing happens with this function call + waveOutUnprepareHeader ( m_WaveOut, &m_WaveOutHeader[j], sizeof ( WAVEHDR ) ); +*/ + + // create memory for playback buffer + if ( psPlaybackBuffer[j] != NULL ) + { + delete[] psPlaybackBuffer[j]; + } + + psPlaybackBuffer[j] = new short[iBufferSize]; + + // clear new buffer + for ( i = 0; i < iBufferSize; i++ ) + { + psPlaybackBuffer[j][i] = 0; + } + + // prepare buffer for sending to the sound interface + PrepareOutBuffer ( j ); + + // initially, send all buffers to the interface + AddOutBuffer ( j ); + } + + + // initialization is done, (re)start audio + ASIOStart(); +} + +void CSound::Close() +{ // set event to ensure that thread leaves the waiting function if ( m_WaveInEvent != NULL ) { @@ -546,53 +436,6 @@ void CSound::Close() // wait for the thread to terminate Sleep ( 500 ); -/* - // unprepare wave-headers - if ( m_WaveIn != NULL ) - { - for ( i = 0; i < iCurNumSndBufIn; i++ ) - { - result = waveInUnprepareHeader ( - m_WaveIn, &m_WaveInHeader[i], sizeof ( WAVEHDR ) ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveInUnprepareHeader()" - " failed." ); - } - } - - // close the sound in device - result = waveInClose ( m_WaveIn ); - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveInClose() failed." ); - } - } - - if ( m_WaveOut != NULL ) - { - for ( i = 0; i < iCurNumSndBufOut; i++ ) - { - result = waveOutUnprepareHeader ( - m_WaveOut, &m_WaveOutHeader[i], sizeof ( WAVEHDR ) ); - - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveOutUnprepareHeader()" - " failed." ); - } - } - - // close the sound out device - result = waveOutClose ( m_WaveOut ); - if ( result != MMSYSERR_NOERROR ) - { - throw CGenErr ( "Sound Interface, waveOutClose() failed." ); - } - } -*/ - // set flag to open devices the next time it is initialized bChangParamIn = TRUE; bChangParamOut = TRUE; @@ -606,44 +449,9 @@ CSound::CSound() iCurNumSndBufIn = NUM_SOUND_BUFFERS_IN; iCurNumSndBufOut = NUM_SOUND_BUFFERS_OUT; -/* // should be initialized because an error can occur during init m_WaveInEvent = NULL; m_WaveOutEvent = NULL; - m_WaveIn = NULL; - m_WaveOut = NULL; -*/ - - // init buffer pointer to zero - for ( i = 0; i < MAX_SND_BUF_IN; i++ ) - { -/* - memset ( &m_WaveInHeader[i], 0, sizeof ( WAVEHDR ) ); -*/ - psSoundcardBuffer[i] = NULL; - } - - for ( i = 0; i < MAX_SND_BUF_OUT; i++ ) - { -/* - memset ( &m_WaveOutHeader[i], 0, sizeof ( WAVEHDR ) ); -*/ - psPlaybackBuffer[i] = NULL; - } - -/* - // init wave-format structure - sWaveFormatEx.wFormatTag = WAVE_FORMAT_PCM; - sWaveFormatEx.nChannels = NUM_IN_OUT_CHANNELS; - sWaveFormatEx.wBitsPerSample = BITS_PER_SAMPLE; - sWaveFormatEx.nSamplesPerSec = SND_CRD_SAMPLE_RATE; - sWaveFormatEx.nBlockAlign = sWaveFormatEx.nChannels * - sWaveFormatEx.wBitsPerSample / 8; - sWaveFormatEx.nAvgBytesPerSec = sWaveFormatEx.nBlockAlign * - sWaveFormatEx.nSamplesPerSec; - sWaveFormatEx.cbSize = 0; -*/ - // get available ASIO driver names in system char* cDriverNames[MAX_NUMBER_SOUND_CARDS]; @@ -692,49 +500,94 @@ pstrDevices[0] = driverInfo.name; - -// TEST !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -ASIOExit(); - - - -/* - // get info about the devices and store the names - for ( i = 0; i < iNumDevs; i++ ) + // check the number of available channels + long lNumInChan; + long lNumOutChan; + ASIOGetChannels ( &lNumInChan, &lNumOutChan ); + if ( ( lNumInChan != NUM_IN_OUT_CHANNELS ) || ( lNumOutChan != NUM_IN_OUT_CHANNELS ) ) { - if ( !waveInGetDevCaps ( i, &m_WaveInDevCaps, sizeof ( WAVEINCAPS ) ) ) - { - pstrDevices[i] = m_WaveInDevCaps.szPname; - } + throw CGenErr ( "The audio device does not support required number of channels." ); + } + + // check the usable buffer sizes + long lMinSize; + long lMaxSize; + long lPreferredSize; + long lGranularity; + ASIOGetBufferSize ( &lMinSize, &lMaxSize, &lPreferredSize, &lGranularity ); + + // TODO make use of the information... + + + // set the sample rate and check if sample rate is supported + ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE ); + + ASIOSampleRate sampleRate; + ASIOGetSampleRate ( &sampleRate ); + if ( sampleRate != SND_CRD_SAMPLE_RATE ) + { + throw CGenErr ( "The audio device does not support required sample rate." ); + } + + // check wether the driver requires the ASIOOutputReady() optimization + // (can be used by the driver to reduce output latency by one block) + bASIOPostOutput = ( ASIOOutputReady() == ASE_OK ); + + // set up the asioCallback structure and create the ASIO data buffer + asioCallbacks.bufferSwitch = &bufferSwitch; + asioCallbacks.sampleRateDidChange = &sampleRateChanged; + asioCallbacks.asioMessage = &asioMessages; + asioCallbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfo; + + // prepare input channels + for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ ) + { + bufferInfos[i].isInput = ASIOTrue; + bufferInfos[i].channelNum = i; + bufferInfos[i].buffers[0] = 0; + bufferInfos[i].buffers[1] = 0; + } + + // prepare output channels + for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ ) + { + bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse; + bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i; + bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0; + bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0; + } + + // init buffer pointer to zero + for ( i = 0; i < MAX_SND_BUF_IN; i++ ) + { + psSoundcardBuffer[i] = NULL; + } + + for ( i = 0; i < MAX_SND_BUF_OUT; i++ ) + { + psPlaybackBuffer[i] = NULL; } -*/ // we use an event controlled wave-in (wave-out) structure // create events - m_WaveInEvent = CreateEvent ( NULL, FALSE, FALSE, NULL ); + m_WaveInEvent = CreateEvent ( NULL, FALSE, FALSE, NULL ); m_WaveOutEvent = CreateEvent ( NULL, FALSE, FALSE, NULL ); // set flag to open devices bChangParamIn = TRUE; bChangParamOut = TRUE; - -/* - // default device number, "wave mapper" - iCurInDev = WAVE_MAPPER; - iCurOutDev = WAVE_MAPPER; -*/ - - // non-blocking wave out is default - bBlockingPlay = FALSE; - - // blocking wave in is default - bBlockingRec = TRUE; } CSound::~CSound() { int i; + // cleanup ASIO stuff + ASIOStop(); + ASIODisposeBuffers(); + ASIOExit(); + asioDrivers->removeCurrentDriver(); + // delete allocated memory for ( i = 0; i < iCurNumSndBufIn; i++ ) { @@ -766,6 +619,144 @@ CSound::~CSound() */ } +// ASIO callbacks ------------------------------------------------------------- +ASIOTime* CSound::bufferSwitchTimeInfo ( ASIOTime *timeInfo, long index, ASIOBool processNow ) +{ + + +/* + static long processedSamples = 0; + + // store the timeInfo for later use + asioDriverInfo.tInfo = *timeInfo; + + // get the time stamp of the buffer, not necessary if no + // synchronization to other media is required + if (timeInfo->timeInfo.flags & kSystemTimeValid) + asioDriverInfo.nanoSeconds = ASIO64toDouble(timeInfo->timeInfo.systemTime); + else + asioDriverInfo.nanoSeconds = 0; + + if (timeInfo->timeInfo.flags & kSamplePositionValid) + asioDriverInfo.samples = ASIO64toDouble(timeInfo->timeInfo.samplePosition); + else + asioDriverInfo.samples = 0; + + if (timeInfo->timeCode.flags & kTcValid) + asioDriverInfo.tcSamples = ASIO64toDouble(timeInfo->timeCode.timeCodeSamples); + else + asioDriverInfo.tcSamples = 0; + + // get the system reference time + asioDriverInfo.sysRefTime = get_sys_reference_time(); + +#if WINDOWS && _DEBUG + // a few debug messages for the Windows device driver developer + // tells you the time when driver got its interrupt and the delay until the app receives + // the event notification. + static double last_samples = 0; + char tmp[128]; + sprintf (tmp, "diff: %d / %d ms / %d ms / %d samples \n", asioDriverInfo.sysRefTime - (long)(asioDriverInfo.nanoSeconds / 1000000.0), asioDriverInfo.sysRefTime, (long)(asioDriverInfo.nanoSeconds / 1000000.0), (long)(asioDriverInfo.samples - last_samples)); + OutputDebugString (tmp); + last_samples = asioDriverInfo.samples; +#endif + + // buffer size in samples + long buffSize = asioDriverInfo.preferredSize; + + // perform the processing + for (int i = 0; i < asioDriverInfo.inputBuffers + asioDriverInfo.outputBuffers; i++) + { + if (asioDriverInfo.bufferInfos[i].isInput == false) + { + // OK do processing for the outputs only + switch (asioDriverInfo.channelInfos[i].type) + { + case ASIOSTInt16LSB: + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2); + break; + case ASIOSTInt24LSB: // used for 20 bits as well + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3); + break; + case ASIOSTInt32LSB: + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8); + break; + + // 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 + case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment + case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment + case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + + case ASIOSTInt16MSB: + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 2); + break; + case ASIOSTInt24MSB: // used for 20 bits as well + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 3); + break; + case ASIOSTInt32MSB: + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 8); + break; + + // 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 ASIOSTInt32MSB16: // 32 bit data with 18 bit alignment + case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment + case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment + case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment + memset (asioDriverInfo.bufferInfos[i].buffers[index], 0, buffSize * 4); + break; + } + } + } + + // finally if the driver supports the ASIOOutputReady() optimization, do it here, all data are in place + if (asioDriverInfo.postOutput) + ASIOOutputReady(); + + if (processedSamples >= asioDriverInfo.sampleRate * TEST_RUN_TIME) // roughly measured + asioDriverInfo.stopped = true; + else + processedSamples += buffSize; +*/ + + + return 0L; +} + +void CSound::bufferSwitch( long index, ASIOBool processNow ) +{ + +} + +long CSound::asioMessages ( long selector, long value, void* message, double* opt ) +{ + long ret = 0; + switch(selector) + { + case kAsioEngineVersion: + // return the supported ASIO version of the host application + ret = 2L; + break; + } + return ret; +} + #else // USE_ASIO_SND_INTERFACE /******************************************************************************\ diff --git a/windows/sound.h b/windows/sound.h index 82245114..3a248ffa 100755 --- a/windows/sound.h +++ b/windows/sound.h @@ -71,17 +71,17 @@ public: CSound(); virtual ~CSound(); - void InitRecording ( int iNewBufferSize, bool bNewBlocking = TRUE ); - void InitPlayback ( int iNewBufferSize, bool bNewBlocking = FALSE ); + void InitRecording ( int iNewBufferSize, bool bNewBlocking = TRUE ) { InitRecordingAndPlayback ( iNewBufferSize ); } + void InitPlayback ( int iNewBufferSize, bool bNewBlocking = FALSE ) { InitRecordingAndPlayback ( iNewBufferSize ); } bool Read ( CVector& psData ); bool Write ( CVector& psData ); int GetNumDev() { return iNumDevs; } std::string GetDeviceName ( int iDiD ) { return pstrDevices[iDiD]; } - void SetOutDev ( int iNewDev ); - int GetOutDev() { return iCurOutDev; } - void SetInDev ( int iNewDev ); - int GetInDev() { return iCurInDev; } + void SetOutDev ( int iNewDev ) {} // not supported + int GetOutDev() { return 0; } // not supported + void SetInDev ( int iNewDev ) {} // not supported + int GetInDev() { return 0; } // not supported void SetOutNumBuf ( int iNewNum ); int GetOutNumBuf() { return iCurNumSndBufOut; } void SetInNumBuf ( int iNewNum ); @@ -90,8 +90,7 @@ public: void Close(); protected: - void OpenInDevice(); - void OpenOutDevice(); + void InitRecordingAndPlayback ( int iNewBufferSize ); void PrepareInBuffer ( int iBufNum ); void PrepareOutBuffer ( int iBufNum ); void AddInBuffer(); @@ -100,29 +99,34 @@ protected: // ASIO stuff ASIODriverInfo driverInfo; + ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output buffers -> "2 *" + ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS]; + bool bASIOPostOutput; + ASIOCallbacks asioCallbacks; + // callbacks + static void bufferSwitch ( long index, ASIOBool processNow ); + static ASIOTime* bufferSwitchTimeInfo ( ASIOTime *timeInfo, long index, ASIOBool processNow ); + static void sampleRateChanged ( ASIOSampleRate sRate ) {} + static long asioMessages ( long selector, long value, void* message, double* opt ); int iNumDevs; std::string pstrDevices[MAX_NUMBER_SOUND_CARDS]; - int iCurInDev; - int iCurOutDev; bool bChangParamIn; bool bChangParamOut; int iCurNumSndBufIn; int iCurNumSndBufOut; + int iBufferSize; + // wave in HANDLE m_WaveInEvent; - int iBufferSizeIn; int iWhichBufferIn; short* psSoundcardBuffer[MAX_SND_BUF_IN]; - bool bBlockingRec; // wave out - int iBufferSizeOut; short* psPlaybackBuffer[MAX_SND_BUF_OUT]; HANDLE m_WaveOutEvent; - bool bBlockingPlay; }; #else // USE_ASIO_SND_INTERFACE