diff --git a/src/buffer.cpp b/src/buffer.cpp index 1b17d018..562bd9dd 100755 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -417,13 +417,8 @@ bool CConvBuf::Put ( const CVector& vecsData ) vecsMemory[iPutPos++] = vecsData[iCurPos++]; } - bool bBufOk = false; - if ( iEnd == iMemSize ) - { - bBufOk = true; - } - - return bBufOk; + // return "buffer is ready for readout" flag + return iEnd == iMemSize; } CVector CConvBuf::Get() diff --git a/windows/sound.cpp b/windows/sound.cpp index c0467c15..bbc08d1a 100755 --- a/windows/sound.cpp +++ b/windows/sound.cpp @@ -1,5 +1,5 @@ /******************************************************************************\ - * Copyright (c) 2004-2008 + * Copyright (c) 2004-2009 * * Author(s): * Volker Fischer @@ -29,7 +29,6 @@ /* Implementation *************************************************************/ -#ifdef USE_ASIO_SND_INTERFACE #include // external references @@ -929,643 +928,3 @@ long CSound::asioMessages ( long selector, long value, void* message, double* op } return ret; } - -#else // USE_ASIO_SND_INTERFACE - -/******************************************************************************\ -* Wave in * -\******************************************************************************/ -bool CSound::Read ( CVector& psData ) -{ - int i; - bool bError; - - // check if device must be opened or reinitialized - if ( bChangParamIn ) - { - OpenInDevice(); - - // Reinit sound interface - InitRecording ( iBufferSizeIn, bBlockingRec ); - - // Reset flag - bChangParamIn = false; - } - - // wait until data is available - if ( ! ( m_WaveInHeader[iWhichBufferIn].dwFlags & WHDR_DONE ) ) - { - if ( bBlockingRec ) - { - WaitForSingleObject ( m_WaveInEvent, INFINITE ); - } - else - { - return false; - } - } - - // check if buffers got lost - int iNumInBufDone = 0; - for ( i = 0; i < iCurNumSndBufIn; i++ ) - { - if ( m_WaveInHeader[i].dwFlags & WHDR_DONE ) - { - iNumInBufDone++; - } - } - - /* If the number of done buffers equals the total number of buffers, it is - very likely that a buffer got lost -> set error flag */ - if ( iNumInBufDone == iCurNumSndBufIn ) - { - bError = true; - } - else - { - bError = false; - } - - // copy data from sound card in output buffer - for ( i = 0; i < iBufferSizeIn; i++ ) - { - psData[i] = psSoundcardBuffer[iWhichBufferIn][i]; - } - - // add the buffer so that it can be filled with new samples - AddInBuffer(); - - // in case more than one buffer was ready, reset event - ResetEvent ( m_WaveInEvent ); - - return bError; -} - -void CSound::AddInBuffer() -{ - // unprepare old wave-header - waveInUnprepareHeader ( - m_WaveIn, &m_WaveInHeader[iWhichBufferIn], sizeof ( WAVEHDR ) ); - - // prepare buffers for sending to sound interface - PrepareInBuffer ( iWhichBufferIn ); - - // send buffer to driver for filling with new data - waveInAddBuffer ( m_WaveIn, &m_WaveInHeader[iWhichBufferIn], sizeof ( WAVEHDR ) ); - - // toggle buffers - iWhichBufferIn++; - if ( iWhichBufferIn == iCurNumSndBufIn ) - { - iWhichBufferIn = 0; - } -} - -void CSound::PrepareInBuffer ( int iBufNum ) -{ - // set struct entries - m_WaveInHeader[iBufNum].lpData = (LPSTR) &psSoundcardBuffer[iBufNum][0]; - m_WaveInHeader[iBufNum].dwBufferLength = iBufferSizeIn * BYTES_PER_SAMPLE; - m_WaveInHeader[iBufNum].dwFlags = 0; - - // prepare wave-header - waveInPrepareHeader ( m_WaveIn, &m_WaveInHeader[iBufNum], sizeof ( WAVEHDR ) ); -} - -void CSound::InitRecording ( int iNewBufferSize, bool bNewBlocking ) -{ - // check if device must be opened or reinitialized - if ( bChangParamIn ) - { - 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 - if ( ( iNewNum >= MAX_SND_BUF_IN ) || ( iNewNum < 1 ) ) - { - iNewNum = NUM_SOUND_BUFFERS_IN; - } - - // change only if parameter is different - if ( iNewNum != iCurNumSndBufIn ) - { - iCurNumSndBufIn = iNewNum; - bChangParamIn = true; - } -} - - -/******************************************************************************\ -* Wave out * -\******************************************************************************/ -bool CSound::Write ( CVector& psData ) -{ - int i, j; - int iCntPrepBuf; - int iIndexDoneBuf; - bool bError; - - // check if device must be opened or reinitialized - if ( bChangParamOut ) - { - OpenOutDevice(); - - // reinit sound interface - InitPlayback ( iBufferSizeOut, bBlockingPlay ); - - // reset flag - bChangParamOut = false; - } - - // get number of "done"-buffers and position of one of them - GetDoneBuffer ( iCntPrepBuf, iIndexDoneBuf ); - - // now check special cases (Buffer is full or empty) - if ( iCntPrepBuf == 0 ) - { - if ( bBlockingPlay ) - { - /* Blocking wave out routine. Always - ensure that the buffer is completely filled to avoid buffer - underruns */ - while ( iCntPrepBuf == 0 ) - { - 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 - } - } - else - { - if ( iCntPrepBuf == iCurNumSndBufOut ) - { - /* ----------------------------------------------------------------- - Buffer is empty -> send as many cleared blocks to the sound- - interface until half of the buffer size is reached */ - // send half of the buffer size blocks to the sound-interface - for ( j = 0; j < iCurNumSndBufOut / 2; j++ ) - { - // first, clear these buffers - for ( i = 0; i < iBufferSizeOut; i++ ) - { - psPlaybackBuffer[j][i] = 0; - } - - // then send them to the interface - AddOutBuffer ( j ); - } - - // set index for done buffer - iIndexDoneBuf = iCurNumSndBufOut / 2; - - bError = true; - } - else - { - bError = false; - } - } - - // copy stereo data from input in soundcard buffer - for ( i = 0; i < iBufferSizeOut; i++ ) - { - psPlaybackBuffer[iIndexDoneBuf][i] = psData[i]; - } - - // now, send the current block - AddOutBuffer ( iIndexDoneBuf ); - - return bError; -} - -void CSound::GetDoneBuffer ( int& iCntPrepBuf, int& iIndexDoneBuf ) -{ - // get number of "done"-buffers and position of one of them - iCntPrepBuf = 0; - for ( int i = 0; i < iCurNumSndBufOut; i++ ) - { - if ( m_WaveOutHeader[i].dwFlags & WHDR_DONE ) - { - iCntPrepBuf++; - iIndexDoneBuf = i; - } - } -} - -void CSound::AddOutBuffer ( int iBufNum ) -{ - // unprepare old wave-header - waveOutUnprepareHeader ( - m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof ( WAVEHDR ) ); - - // prepare buffers for sending to sound interface - PrepareOutBuffer ( iBufNum ); - - // send buffer to driver for filling with new data - waveOutWrite ( m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof ( WAVEHDR ) ); -} - -void CSound::PrepareOutBuffer ( int iBufNum ) -{ - // set Header data - m_WaveOutHeader[iBufNum].lpData = (LPSTR) &psPlaybackBuffer[iBufNum][0]; - m_WaveOutHeader[iBufNum].dwBufferLength = iBufferSizeOut * BYTES_PER_SAMPLE; - m_WaveOutHeader[iBufNum].dwFlags = 0; - - // prepare wave-header - waveOutPrepareHeader ( m_WaveOut, &m_WaveOutHeader[iBufNum], sizeof ( WAVEHDR ) ); -} - -void CSound::InitPlayback ( int iNewBufferSize, bool bNewBlocking ) -{ - int i, j; - - // check if device must be opened or reinitialized - if ( bChangParamOut ) - { - 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 - if ( ( iNewNum >= MAX_SND_BUF_OUT ) || ( iNewNum < 1 ) ) - { - iNewNum = NUM_SOUND_BUFFERS_OUT; - } - - // change only if parameter is different - if ( iNewNum != iCurNumSndBufOut ) - { - iCurNumSndBufOut = iNewNum; - bChangParamOut = true; - } -} - - -/******************************************************************************\ -* Common * -\******************************************************************************/ -void CSound::Close() -{ - int i; - 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." ); - } - } - - // set event to ensure that thread leaves the waiting function - if ( m_WaveInEvent != NULL ) - { - SetEvent(m_WaveInEvent); - } - - // 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; -} - -CSound::CSound() -{ - int i; - - // init number of sound buffers - 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 the number of digital audio devices in this computer, check range - iNumDevs = waveInGetNumDevs(); - - if ( iNumDevs > MAX_NUMBER_SOUND_CARDS ) - { - iNumDevs = MAX_NUMBER_SOUND_CARDS; - } - - // at least one device must exist in the system - if ( iNumDevs == 0 ) - { - throw CGenErr ( "No audio device found." ); - } - - // get info about the devices and store the names - for ( i = 0; i < iNumDevs; i++ ) - { - if ( !waveInGetDevCaps ( i, &m_WaveInDevCaps, sizeof ( WAVEINCAPS ) ) ) - { - pstrDevices[i] = m_WaveInDevCaps.szPname; - } - } - - // we use an event controlled wave-in (wave-out) structure - // create events - 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; - - // delete allocated memory - for ( i = 0; i < iCurNumSndBufIn; i++ ) - { - if ( psSoundcardBuffer[i] != NULL ) - { - delete[] psSoundcardBuffer[i]; - } - } - - for ( i = 0; i < iCurNumSndBufOut; i++ ) - { - if ( psPlaybackBuffer[i] != NULL ) - { - delete[] psPlaybackBuffer[i]; - } - } - - // close the handle for the events - if ( m_WaveInEvent != NULL ) - { - CloseHandle ( m_WaveInEvent ); - } - - if ( m_WaveOutEvent != NULL ) - { - CloseHandle ( m_WaveOutEvent ); - } -} - -#endif // USE_ASIO_SND_INTERFACE diff --git a/windows/sound.h b/windows/sound.h index 6b2ba4d1..7e9b7bb9 100755 --- a/windows/sound.h +++ b/windows/sound.h @@ -1,5 +1,5 @@ /******************************************************************************\ - * Copyright (c) 2004-2008 + * Copyright (c) 2004-2009 * * Author(s): * Volker Fischer @@ -27,23 +27,21 @@ #define AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_ #include -#include #include #include #include "../src/util.h" #include "../src/global.h" +// copy the ASIO SDK in the llcon/windows directory: "llcon/windows/ASIOSDK2" to +// get it work +#include "asiosys.h" +#include "asio.h" +#include "asiodrivers.h" + /* Definitions ****************************************************************/ -// switch here between ASIO (Steinberg) or native Windows(TM) sound interface -//#undef USE_ASIO_SND_INTERFACE -#define USE_ASIO_SND_INTERFACE - - #define NUM_IN_OUT_CHANNELS 2 /* Stereo recording (but we only use one channel for recording) */ -#define BITS_PER_SAMPLE 16 // use all bits of the D/A-converter -#define BYTES_PER_SAMPLE 2 // number of bytes per sample #define MAX_SND_BUF_IN 100 #define MAX_SND_BUF_OUT 100 @@ -53,16 +51,6 @@ /* Classes ********************************************************************/ -#ifdef USE_ASIO_SND_INTERFACE - -// copy the ASIO SDK in the llcon/windows directory: "llcon/windows/ASIOSDK2" to -// get it work - -#include "asiosys.h" -#include "asio.h" -#include "asiodrivers.h" - - class CSound { public: @@ -127,75 +115,4 @@ protected: bool bBlockingPlay; }; -#else // USE_ASIO_SND_INTERFACE - -class CSound -{ -public: - CSound(); - virtual ~CSound(); - - void InitRecording ( int iNewBufferSize, bool bNewBlocking = true ); - void InitPlayback ( int iNewBufferSize, bool bNewBlocking = false ); - bool Read ( CVector& psData ); - bool Write ( CVector& psData ); - - int GetNumDev() { return iNumDevs; } - std::string GetDeviceName ( int iDiD ) { return pstrDevices[iDiD]; } - - // dummy functions - int SetDev ( const int iNewDev ) {} - int GetDev() { return 0; } - - void SetOutDev ( int iNewDev ); - int GetOutDev() { return iCurOutDev; } - void SetInDev ( int iNewDev ); - int GetInDev() { return iCurInDev; } - void SetOutNumBuf ( int iNewNum ); - int GetOutNumBuf() { return iCurNumSndBufOut; } - void SetInNumBuf ( int iNewNum ); - int GetInNumBuf() { return iCurNumSndBufIn; } - - void Close(); - -protected: - void OpenInDevice(); - void OpenOutDevice(); - void PrepareInBuffer ( int iBufNum ); - void PrepareOutBuffer ( int iBufNum ); - void AddInBuffer(); - void AddOutBuffer ( int iBufNum ); - void GetDoneBuffer ( int& iCntPrepBuf, int& iIndexDoneBuf ); - - WAVEFORMATEX sWaveFormatEx; - UINT iNumDevs; - std::string pstrDevices[MAX_NUMBER_SOUND_CARDS]; - UINT iCurInDev; - UINT iCurOutDev; - bool bChangParamIn; - bool bChangParamOut; - int iCurNumSndBufIn; - int iCurNumSndBufOut; - - // wave in - WAVEINCAPS m_WaveInDevCaps; - HWAVEIN m_WaveIn; - HANDLE m_WaveInEvent; - WAVEHDR m_WaveInHeader[MAX_SND_BUF_IN]; - int iBufferSizeIn; - int iWhichBufferIn; - short* psSoundcardBuffer[MAX_SND_BUF_IN]; - bool bBlockingRec; - - // wave out - int iBufferSizeOut; - HWAVEOUT m_WaveOut; - short* psPlaybackBuffer[MAX_SND_BUF_OUT]; - WAVEHDR m_WaveOutHeader[MAX_SND_BUF_OUT]; - HANDLE m_WaveOutEvent; - bool bBlockingPlay; -}; - -#endif // USE_ASIO_SND_INTERFACE - #endif // !defined ( AFX_SOUNDIN_H__9518A621_7F78_11D3_8C0D_EEBF182CF549__INCLUDED_ )