even more ASIO work, audio in and out in first version ready, at least some sound can be heard although it sounds a bit strange :-)
This commit is contained in:
parent
5eb8694134
commit
2cf4e4f285
1 changed files with 89 additions and 123 deletions
|
@ -55,10 +55,11 @@ int iBufferSize;
|
||||||
HANDLE m_ASIOEvent;
|
HANDLE m_ASIOEvent;
|
||||||
|
|
||||||
// wave in
|
// wave in
|
||||||
int iCurBlockToWrite;
|
int iInCurBlockToWrite;
|
||||||
short* psSoundcardBuffer[MAX_SND_BUF_IN];
|
short* psSoundcardBuffer[MAX_SND_BUF_IN];
|
||||||
|
|
||||||
// wave out
|
// wave out
|
||||||
|
int iOutCurBlockToWrite;
|
||||||
short* psPlaybackBuffer[MAX_SND_BUF_OUT];
|
short* psPlaybackBuffer[MAX_SND_BUF_OUT];
|
||||||
|
|
||||||
int iCurNumSndBufIn;
|
int iCurNumSndBufIn;
|
||||||
|
@ -88,7 +89,7 @@ bool CSound::Read ( CVector<short>& psData )
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until data is available
|
// wait until data is available
|
||||||
if ( iCurBlockToWrite == 0 )
|
if ( iInCurBlockToWrite == 0 )
|
||||||
{
|
{
|
||||||
if ( bBlockingRec )
|
if ( bBlockingRec )
|
||||||
{
|
{
|
||||||
|
@ -102,7 +103,7 @@ bool CSound::Read ( CVector<short>& psData )
|
||||||
|
|
||||||
// If the number of done buffers equals the total number of buffers, it is
|
// If the number of done buffers equals the total number of buffers, it is
|
||||||
// very likely that a buffer got lost -> set error flag
|
// very likely that a buffer got lost -> set error flag
|
||||||
bError = ( iCurBlockToWrite == iCurNumSndBufIn );
|
bError = ( iInCurBlockToWrite == iCurNumSndBufIn );
|
||||||
|
|
||||||
ASIOMutex.lock(); // get mutex lock
|
ASIOMutex.lock(); // get mutex lock
|
||||||
{
|
{
|
||||||
|
@ -113,7 +114,7 @@ bool CSound::Read ( CVector<short>& psData )
|
||||||
}
|
}
|
||||||
|
|
||||||
// move all other data in buffer
|
// move all other data in buffer
|
||||||
for ( j = 0; j < iCurBlockToWrite - 1; j++ )
|
for ( j = 0; j < iInCurBlockToWrite - 1; j++ )
|
||||||
{
|
{
|
||||||
for ( i = 0; i < iBufferSize; i++ )
|
for ( i = 0; i < iBufferSize; i++ )
|
||||||
{
|
{
|
||||||
|
@ -122,7 +123,7 @@ bool CSound::Read ( CVector<short>& psData )
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust "current block to write" pointer
|
// adjust "current block to write" pointer
|
||||||
iCurBlockToWrite--;
|
iInCurBlockToWrite--;
|
||||||
}
|
}
|
||||||
ASIOMutex.unlock();
|
ASIOMutex.unlock();
|
||||||
|
|
||||||
|
@ -154,10 +155,8 @@ void CSound::SetInNumBuf ( int iNewNum )
|
||||||
\******************************************************************************/
|
\******************************************************************************/
|
||||||
bool CSound::Write ( CVector<short>& psData )
|
bool CSound::Write ( CVector<short>& psData )
|
||||||
{
|
{
|
||||||
int i, j;
|
// init return state
|
||||||
int iCntPrepBuf;
|
bool bError = false;
|
||||||
int iIndexDoneBuf;
|
|
||||||
bool bError;
|
|
||||||
|
|
||||||
// check if device must be opened or reinitialized
|
// check if device must be opened or reinitialized
|
||||||
if ( bChangParamOut )
|
if ( bChangParamOut )
|
||||||
|
@ -169,73 +168,26 @@ bool CSound::Write ( CVector<short>& psData )
|
||||||
bChangParamOut = false;
|
bChangParamOut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
ASIOMutex.lock(); // get mutex lock
|
||||||
// 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 )
|
|
||||||
{
|
{
|
||||||
// Blocking wave out routine. Needed for transmitter. Always
|
// first check if buffer is available
|
||||||
// ensure that the buffer is completely filled to avoid buffer
|
if ( iOutCurBlockToWrite < iCurNumSndBufOut )
|
||||||
// underruns
|
|
||||||
while ( iCntPrepBuf == 0 )
|
|
||||||
{
|
{
|
||||||
WaitForSingleObject ( m_WaveOutEvent, INFINITE );
|
// copy stereo data from input in soundcard buffer
|
||||||
|
for ( int i = 0; i < iBufferSize; i++ )
|
||||||
|
{
|
||||||
|
psPlaybackBuffer[iOutCurBlockToWrite][i] = psData[i];
|
||||||
|
}
|
||||||
|
|
||||||
GetDoneBuffer ( iCntPrepBuf, iIndexDoneBuf );
|
iOutCurBlockToWrite++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// buffer overrun, return error
|
||||||
|
bError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
ASIOMutex.unlock();
|
||||||
{
|
|
||||||
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 < iBufferSize; 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 < iBufferSize; i++ )
|
|
||||||
{
|
|
||||||
psPlaybackBuffer[iIndexDoneBuf][i] = psData[i];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
// now, send the current block
|
|
||||||
AddOutBuffer ( iIndexDoneBuf );
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// TEST
|
|
||||||
Sleep(10);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
|
||||||
return bError;
|
return bError;
|
||||||
}
|
}
|
||||||
|
@ -264,8 +216,9 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
// first, stop audio
|
// first, stop audio and dispose ASIO buffers
|
||||||
ASIOStop();
|
ASIOStop();
|
||||||
|
ASIODisposeBuffers();
|
||||||
|
|
||||||
ASIOMutex.lock(); // get mutex lock
|
ASIOMutex.lock(); // get mutex lock
|
||||||
{
|
{
|
||||||
|
@ -345,8 +298,8 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
|
||||||
|
|
||||||
|
|
||||||
// our buffer management -----------------------------------------------
|
// our buffer management -----------------------------------------------
|
||||||
// initialize write block pointer
|
// initialize write block pointer in
|
||||||
iCurBlockToWrite = 0;
|
iInCurBlockToWrite = 0;
|
||||||
|
|
||||||
// create memory for sound card buffer
|
// create memory for sound card buffer
|
||||||
for ( i = 0; i < iCurNumSndBufIn; i++ )
|
for ( i = 0; i < iCurNumSndBufIn; i++ )
|
||||||
|
@ -359,37 +312,25 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
|
||||||
psSoundcardBuffer[i] = new short[iBufferSize];
|
psSoundcardBuffer[i] = new short[iBufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize write block pointer out
|
||||||
|
iOutCurBlockToWrite = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// reset interface
|
|
||||||
waveOutReset ( m_WaveOut );
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
for ( j = 0; j < iCurNumSndBufOut; j++ )
|
|
||||||
{
|
|
||||||
// create memory for playback buffer
|
// create memory for playback buffer
|
||||||
if ( psPlaybackBuffer[j] != NULL )
|
for ( j = 0; j < iCurNumSndBufOut; j++ )
|
||||||
{
|
{
|
||||||
delete[] psPlaybackBuffer[j];
|
if ( psPlaybackBuffer[j] != NULL )
|
||||||
}
|
{
|
||||||
|
delete[] psPlaybackBuffer[j];
|
||||||
|
}
|
||||||
|
|
||||||
psPlaybackBuffer[j] = new short[iBufferSize];
|
psPlaybackBuffer[j] = new short[iBufferSize];
|
||||||
|
|
||||||
// clear new buffer
|
// clear new buffer
|
||||||
for ( i = 0; i < iBufferSize; i++ )
|
for ( i = 0; i < iBufferSize; i++ )
|
||||||
{
|
{
|
||||||
psPlaybackBuffer[j][i] = 0;
|
psPlaybackBuffer[j][i] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// prepare buffer for sending to the sound interface
|
|
||||||
PrepareOutBuffer ( j );
|
|
||||||
|
|
||||||
// initially, send all buffers to the interface
|
|
||||||
AddOutBuffer ( j );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// reset event
|
// reset event
|
||||||
ResetEvent ( m_ASIOEvent );
|
ResetEvent ( m_ASIOEvent );
|
||||||
|
@ -405,7 +346,7 @@ void CSound::Close()
|
||||||
// set event to ensure that thread leaves the waiting function
|
// set event to ensure that thread leaves the waiting function
|
||||||
if ( m_ASIOEvent != NULL )
|
if ( m_ASIOEvent != NULL )
|
||||||
{
|
{
|
||||||
SetEvent(m_ASIOEvent);
|
SetEvent ( m_ASIOEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for the thread to terminate
|
// wait for the thread to terminate
|
||||||
|
@ -542,9 +483,9 @@ pstrDevices[0] = driverInfo.name;
|
||||||
// create event
|
// create event
|
||||||
m_ASIOEvent = CreateEvent ( NULL, FALSE, FALSE, NULL );
|
m_ASIOEvent = CreateEvent ( NULL, FALSE, FALSE, NULL );
|
||||||
|
|
||||||
// set flag to open devices
|
// init flag to open devices
|
||||||
bChangParamIn = true;
|
bChangParamIn = false;
|
||||||
bChangParamOut = true;
|
bChangParamOut = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSound::~CSound()
|
CSound::~CSound()
|
||||||
|
@ -590,6 +531,8 @@ ASIOTime* CSound::bufferSwitchTimeInfo ( ASIOTime *timeInfo, long index, ASIOBoo
|
||||||
|
|
||||||
void CSound::bufferSwitch ( long index, ASIOBool processNow )
|
void CSound::bufferSwitch ( long index, ASIOBool processNow )
|
||||||
{
|
{
|
||||||
|
int iCurSample;
|
||||||
|
|
||||||
ASIOMutex.lock(); // get mutex lock
|
ASIOMutex.lock(); // get mutex lock
|
||||||
{
|
{
|
||||||
// perform the processing for input and output
|
// perform the processing for input and output
|
||||||
|
@ -598,43 +541,66 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
|
||||||
if ( bufferInfos[i].isInput == false )
|
if ( bufferInfos[i].isInput == false )
|
||||||
{
|
{
|
||||||
// PLAYBACK --------------------------------------------------------
|
// PLAYBACK --------------------------------------------------------
|
||||||
// TODO the following is just a test code
|
if ( iOutCurBlockToWrite > 0 )
|
||||||
//memset ( bufferInfos[i].buffers[index], 0, buffSize /** 2*/ );
|
{
|
||||||
|
// copy data from sound card in output buffer
|
||||||
|
for ( iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
|
||||||
|
{
|
||||||
|
((short*) bufferInfos[i].buffers[index])[iCurSample] =
|
||||||
|
psSoundcardBuffer[0][iCurSample];
|
||||||
|
}
|
||||||
|
|
||||||
|
// move all other data in buffer
|
||||||
|
for ( int j = 0; j < iOutCurBlockToWrite - 1; j++ )
|
||||||
|
{
|
||||||
|
for ( iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
|
||||||
|
{
|
||||||
|
psPlaybackBuffer[j][iCurSample] =
|
||||||
|
psPlaybackBuffer[j + 1][iCurSample];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust "current block to write" pointer
|
||||||
|
iOutCurBlockToWrite--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: buffer underrun, inform user somehow...?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// CAPTURE ---------------------------------------------------------
|
// CAPTURE ---------------------------------------------------------
|
||||||
// first check if buffer is available
|
// first check if buffer is available
|
||||||
if ( iCurBlockToWrite < iCurNumSndBufIn )
|
if ( iInCurBlockToWrite < iCurNumSndBufIn )
|
||||||
{
|
{
|
||||||
// copy new captured block in thread transfer buffer
|
// copy new captured block in thread transfer buffer
|
||||||
for ( int iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
|
for ( iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
|
||||||
{
|
{
|
||||||
psSoundcardBuffer[iCurBlockToWrite][iCurSample] =
|
psSoundcardBuffer[iInCurBlockToWrite][iCurSample] =
|
||||||
((short*) bufferInfos[i].buffers[index])[iCurSample];
|
((short*) bufferInfos[i].buffers[index])[iCurSample];
|
||||||
}
|
}
|
||||||
|
|
||||||
iCurBlockToWrite++;
|
iInCurBlockToWrite++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO: buffer overrun, inform user somehow...?
|
||||||
// buffer overrun, inform user somehow...?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally if the driver supports the ASIOOutputReady() optimization,
|
|
||||||
// do it here, all data are in place
|
|
||||||
if ( bASIOPostOutput )
|
|
||||||
{
|
|
||||||
ASIOOutputReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set event
|
|
||||||
SetEvent ( m_ASIOEvent );
|
|
||||||
}
|
}
|
||||||
ASIOMutex.unlock();
|
ASIOMutex.unlock();
|
||||||
|
|
||||||
|
// finally if the driver supports the ASIOOutputReady() optimization,
|
||||||
|
// do it here, all data are in place
|
||||||
|
if ( bASIOPostOutput )
|
||||||
|
{
|
||||||
|
ASIOOutputReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
// set event
|
||||||
|
SetEvent ( m_ASIOEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
long CSound::asioMessages ( long selector, long value, void* message, double* opt )
|
long CSound::asioMessages ( long selector, long value, void* message, double* opt )
|
||||||
|
|
Loading…
Reference in a new issue