diff --git a/src/client.cpp b/src/client.cpp
index 57ee15c5..7f95e05f 100755
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -210,11 +210,6 @@ void CClient::run()
PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
}
-
-// TEST
-//Sleep(300);
-//wait(3000);
-
// copy data from one stereo buffer in two separate buffers
iInCnt = 0;
for ( i = 0; i < iSndCrdBlockSizeSam; i++ )
diff --git a/src/clientsettingsdlgbase.ui b/src/clientsettingsdlgbase.ui
index 81e6e3e6..199eabb2 100755
--- a/src/clientsettingsdlgbase.ui
+++ b/src/clientsettingsdlgbase.ui
@@ -19,24 +19,42 @@
true
-
- 9
-
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
Jitter Buffer
-
- 9
-
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
@@ -58,12 +76,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -120,18 +147,25 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
- 0
- 0
+
0
0
@@ -153,9 +187,7 @@
-
-
- 0
- 0
+
0
0
@@ -185,12 +217,21 @@
Block Size
-
- 9
-
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
@@ -212,12 +253,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -274,12 +324,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -356,34 +415,59 @@
Sndcard Buffers
-
- 9
-
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
- 3
- 1
+
0
0
@@ -407,12 +491,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -458,18 +551,25 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
- 3
- 1
+
0
0
@@ -493,12 +593,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -547,7 +656,7 @@
-
- In / Out:
+ Out / In:
Qt::AlignCenter
@@ -559,18 +668,25 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
+
-
- 0
- 0
+
0
0
@@ -590,11 +706,9 @@
-
-
+
-
- 0
- 0
+
0
0
@@ -624,20 +738,38 @@
Debug
-
- 9
-
6
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
+ 9
+
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -662,12 +794,21 @@
-
-
- 0
-
6
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
@@ -681,9 +822,7 @@
-
-
- 0
- 0
+
0
0
diff --git a/windows/sound.cpp b/windows/sound.cpp
index 1580056a..ad5aa82d 100755
--- a/windows/sound.cpp
+++ b/windows/sound.cpp
@@ -49,7 +49,8 @@ ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output b
ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS];
bool bASIOPostOutput;
ASIOCallbacks asioCallbacks;
-int iBufferSize;
+int iBufferSizeMono;
+int iBufferSizeStereo;
// event
HANDLE m_ASIOEvent;
@@ -81,8 +82,8 @@ bool CSound::Read ( CVector& psData )
// check if device must be opened or reinitialized
if ( bChangParamIn )
{
- // Reinit sound interface
- InitRecordingAndPlayback ( iBufferSize );
+ // Reinit sound interface (init recording requires stereo buffer size)
+ InitRecordingAndPlayback ( iBufferSizeStereo );
// Reset flag
bChangParamIn = false;
@@ -108,7 +109,7 @@ bool CSound::Read ( CVector& psData )
ASIOMutex.lock(); // get mutex lock
{
// copy data from sound card in output buffer
- for ( i = 0; i < iBufferSize; i++ )
+ for ( i = 0; i < iBufferSizeStereo; i++ )
{
psData[i] = psSoundcardBuffer[0][i];
}
@@ -116,7 +117,7 @@ bool CSound::Read ( CVector& psData )
// move all other data in buffer
for ( j = 0; j < iInCurBlockToWrite - 1; j++ )
{
- for ( i = 0; i < iBufferSize; i++ )
+ for ( i = 0; i < iBufferSizeStereo; i++ )
{
psSoundcardBuffer[j][i] = psSoundcardBuffer[j + 1][i];
}
@@ -161,8 +162,8 @@ bool CSound::Write ( CVector& psData )
// check if device must be opened or reinitialized
if ( bChangParamOut )
{
- // reinit sound interface
- InitRecordingAndPlayback ( iBufferSize );
+ // reinit sound interface (init recording requires stereo buffer size)
+ InitRecordingAndPlayback ( iBufferSizeStereo );
// reset flag
bChangParamOut = false;
@@ -174,7 +175,7 @@ bool CSound::Write ( CVector& psData )
if ( iOutCurBlockToWrite < iCurNumSndBufOut )
{
// copy stereo data from input in soundcard buffer
- for ( int i = 0; i < iBufferSize; i++ )
+ for ( int i = 0; i < iBufferSizeStereo; i++ )
{
psPlaybackBuffer[iOutCurBlockToWrite][i] = psData[i];
}
@@ -222,17 +223,20 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
ASIOMutex.lock(); // get mutex lock
{
+ // we need mono buffer size but get stereo buffer size
+ const int iNewBufferSizeMono = iNewBufferSize / 2;
+
// calculate "nearest" buffer size and set internal parameter accordingly
// first check minimum and maximum values
- if ( iNewBufferSize < HWBufferInfo.lMinSize )
+ if ( iNewBufferSizeMono < HWBufferInfo.lMinSize )
{
- iBufferSize = HWBufferInfo.lMinSize;
+ iBufferSizeMono = HWBufferInfo.lMinSize;
}
else
{
- if ( iNewBufferSize > HWBufferInfo.lMaxSize )
+ if ( iNewBufferSizeMono > HWBufferInfo.lMaxSize )
{
- iBufferSize = HWBufferInfo.lMaxSize;
+ iBufferSizeMono = HWBufferInfo.lMaxSize;
}
else
{
@@ -244,17 +248,17 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
// test loop
while ( ( iTrialBufSize <= HWBufferInfo.lMaxSize ) && ( !bSizeFound ) )
{
- if ( iTrialBufSize > iNewBufferSize )
+ if ( iTrialBufSize > iNewBufferSizeMono )
{
// test which buffer size fits better: the old one or the
// current one
- if ( ( iTrialBufSize - iNewBufferSize ) < ( iNewBufferSize - iLastTrialBufSize ) )
+ if ( ( iTrialBufSize - iNewBufferSizeMono ) < ( iNewBufferSizeMono - iLastTrialBufSize ) )
{
- iBufferSize = iTrialBufSize;
+ iBufferSizeMono = iTrialBufSize;
}
else
{
- iBufferSize = iLastTrialBufSize;
+ iBufferSizeMono = iLastTrialBufSize;
}
// exit while loop
@@ -278,9 +282,19 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
}
}
- // create and activate ASIO buffers
+ // calculate stereo buffer size
+ iBufferSizeStereo = 2 * iBufferSizeMono;
+
+ // TEST test if requested buffer size is supported by the audio hardware, if not, fire error
+if ( iNewBufferSize != iBufferSizeStereo )
+{
+ throw CGenErr ( "Required sound card buffer size not allowed by the audio hardware." );
+}
+
+
+ // create and activate ASIO buffers (buffer size in samples)
ASIOCreateBuffers ( bufferInfos, 2 * NUM_IN_OUT_CHANNELS,
- iBufferSize * BYTES_PER_SAMPLE, &asioCallbacks );
+ iBufferSizeMono, &asioCallbacks );
// now set all the buffer details
for ( i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ )
@@ -309,7 +323,7 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
delete[] psSoundcardBuffer[i];
}
- psSoundcardBuffer[i] = new short[iBufferSize];
+ psSoundcardBuffer[i] = new short[iBufferSizeStereo];
}
// initialize write block pointer out
@@ -323,10 +337,10 @@ void CSound::InitRecordingAndPlayback ( int iNewBufferSize )
delete[] psPlaybackBuffer[j];
}
- psPlaybackBuffer[j] = new short[iBufferSize];
+ psPlaybackBuffer[j] = new short[iBufferSizeStereo];
// clear new buffer
- for ( i = 0; i < iBufferSize; i++ )
+ for ( i = 0; i < iBufferSizeStereo; i++ )
{
psPlaybackBuffer[j][i] = 0;
}
@@ -352,6 +366,10 @@ void CSound::Close()
// wait for the thread to terminate
Sleep ( 500 );
+ // stop audio and dispose ASIO buffers
+ ASIOStop();
+ ASIODisposeBuffers();
+
// set flag to open devices the next time it is initialized
bChangParamIn = true;
bChangParamOut = true;
@@ -540,55 +558,67 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
{
if ( bufferInfos[i].isInput == false )
{
- // PLAYBACK --------------------------------------------------------
+ // PLAYBACK ----------------------------------------------------
if ( iOutCurBlockToWrite > 0 )
{
// copy data from sound card in output buffer
- for ( iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
+ for ( iCurSample = 0; iCurSample < iBufferSizeMono; iCurSample++ )
{
- ((short*) bufferInfos[i].buffers[index])[iCurSample] =
- psSoundcardBuffer[0][iCurSample];
+ // copy interleaved stereo data in mono sound card buffer
+ ((short*) bufferInfos[i].buffers[index])[iCurSample] =
+ psSoundcardBuffer[0][2 * iCurSample + bufferInfos[i].channelNum];
}
-
- // 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
{
- // CAPTURE ---------------------------------------------------------
+ // CAPTURE -----------------------------------------------------
// first check if buffer is available
if ( iInCurBlockToWrite < iCurNumSndBufIn )
{
// copy new captured block in thread transfer buffer
- for ( iCurSample = 0; iCurSample < iBufferSize; iCurSample++ )
+ for ( iCurSample = 0; iCurSample < iBufferSizeMono; iCurSample++ )
{
- psSoundcardBuffer[iInCurBlockToWrite][iCurSample] =
+ // copy mono data interleaved in stereo buffer
+ psSoundcardBuffer[iInCurBlockToWrite][2 * iCurSample + bufferInfos[i].channelNum] =
((short*) bufferInfos[i].buffers[index])[iCurSample];
}
-
- iInCurBlockToWrite++;
- }
- else
- {
- // TODO: buffer overrun, inform user somehow...?
}
}
}
+
+
+ // Manage thread interface buffers for input and output ----------------
+ // capture
+ if ( iInCurBlockToWrite < iCurNumSndBufIn )
+ {
+ iInCurBlockToWrite++;
+ }
+ else
+ {
+ // TODO: buffer overrun, inform user somehow...?
+ }
+
+ // playback
+ if ( iOutCurBlockToWrite > 0 )
+ {
+ // move all other data in playback buffer
+ for ( int j = 0; j < iOutCurBlockToWrite - 1; j++ )
+ {
+ for ( iCurSample = 0; iCurSample < iBufferSizeStereo; iCurSample++ )
+ {
+ psPlaybackBuffer[j][iCurSample] =
+ psPlaybackBuffer[j + 1][iCurSample];
+ }
+ }
+
+ // adjust "current block to write" pointer
+ iOutCurBlockToWrite--;
+ }
+ else
+ {
+ // TODO: buffer underrun, inform user somehow...?
+ }
}
ASIOMutex.unlock();