David Rowe wrote:
I'd like to do some BER tests on it just to be sure, pls send it to me
and I'll try it out with a couple of my sound cards.
svn diff attached
Index: src/fdmdv2_main.cpp
===================================================================
--- src/fdmdv2_main.cpp (revision 1594)
+++ src/fdmdv2_main.cpp (working copy)
@@ -1983,16 +1983,26 @@
m_txRxThread->Wait();
wxLogDebug("thread stopped");
- m_rxPa->stop();
- m_rxPa->streamClose();
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ delete m_rxInPa;
+ if(m_rxOutPa != m_rxInPa) {
+ m_rxOutPa->stop();
+ m_rxOutPa->streamClose();
+ delete m_rxOutPa;
+ }
if (g_nSoundCards == 2) {
- m_txPa->stop();
- m_txPa->streamClose();
- delete m_txPa;
+ m_txInPa->stop();
+ m_txInPa->streamClose();
+ delete m_txInPa;
+ if(m_txInPa != m_txOutPa) {
+ m_txOutPa->stop();
+ m_txOutPa->streamClose();
+ delete m_txOutPa;
+ }
}
- delete m_rxPa;
destroy_fifos();
destroy_src();
deleteEQFilters(g_rxUserdata);
@@ -2028,18 +2038,22 @@
// init input params
pa->setInputDevice(inDevice);
- pa->setInputChannelCount(inputChannels); // stereo input
- pa->setInputSampleFormat(PA_SAMPLE_TYPE);
- pa->setInputLatency(pa->getInputDefaultLowLatency());
- pa->setInputHostApiStreamInfo(NULL);
+ if(inDevice != paNoDevice) {
+ pa->setInputChannelCount(inputChannels); // stereo input
+ pa->setInputSampleFormat(PA_SAMPLE_TYPE);
+ pa->setInputLatency(pa->getInputDefaultLowLatency());
+ pa->setInputHostApiStreamInfo(NULL);
+ }
// init output params
- pa->setOutputDevice(outDevice);
- pa->setOutputChannelCount(2); // stereo output
- pa->setOutputSampleFormat(PA_SAMPLE_TYPE);
- pa->setOutputLatency(pa->getOutputDefaultLowLatency());
- pa->setOutputHostApiStreamInfo(NULL);
+ pa->setOutputDevice(outDevice);
+ if(outDevice != paNoDevice) {
+ pa->setOutputChannelCount(2); // stereo output
+ pa->setOutputSampleFormat(PA_SAMPLE_TYPE);
+ pa->setOutputLatency(pa->getOutputDefaultLowLatency());
+ pa->setOutputHostApiStreamInfo(NULL);
+ }
// init params that affect input and output
@@ -2062,6 +2076,8 @@
int src_error;
const PaDeviceInfo *deviceInfo1 = NULL, *deviceInfo2 = NULL;
int inputChannels1, inputChannels2;
+ bool two_rx=false;
+ bool two_tx=false;
if(!m_RxRunning) {
m_RxRunning = true;
@@ -2071,11 +2087,22 @@
wxMessageBox(wxT("Port Audio failed to initialize"), wxT("Pa_Initialize"), wxOK);
}
- m_rxPa = new PortAudioWrap();
+ m_rxInPa = new PortAudioWrap();
+ if(g_soundCard1InDeviceNum != g_soundCard1OutDeviceNum)
+ two_rx=true;
+ if(g_soundCard2InDeviceNum != g_soundCard2OutDeviceNum)
+ two_tx=true;
+
+ if(two_rx)
+ m_rxOutPa = new PortAudioWrap();
+ else
+ m_rxOutPa = m_rxInPa;
if (g_nSoundCards == 0) {
wxMessageBox(wxT("No Sound Cards configured, use Tools - Audio Config to configure"), wxT("Error"), wxOK);
- delete m_rxPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
m_RxRunning = false;
return;
}
@@ -2083,10 +2110,12 @@
// Init Sound card 1 ----------------------------------------------
// sanity check on sound card device numbers
- if ((m_rxPa->getDeviceCount() <= g_soundCard1InDeviceNum) ||
- (m_rxPa->getDeviceCount() <= g_soundCard1OutDeviceNum)) {
+ if ((m_rxInPa->getDeviceCount() <= g_soundCard1InDeviceNum) ||
+ (m_rxOutPa->getDeviceCount() <= g_soundCard1OutDeviceNum)) {
wxMessageBox(wxT("Sound Card 1 not present"), wxT("Error"), wxOK);
- delete m_rxPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
m_RxRunning = false;
return;
}
@@ -2096,7 +2125,9 @@
deviceInfo1 = Pa_GetDeviceInfo(g_soundCard1InDeviceNum);
if (deviceInfo1 == NULL) {
wxMessageBox(wxT("Couldn't get device info from Port Audio for Sound Card 1"), wxT("Error"), wxOK);
- delete m_rxPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
m_RxRunning = false;
return;
}
@@ -2105,26 +2136,41 @@
else
inputChannels1 = 2;
- initPortAudioDevice(m_rxPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1,
+ if(two_rx) {
+ initPortAudioDevice(m_rxInPa, g_soundCard1InDeviceNum, paNoDevice, 1,
g_soundCard1SampleRate, inputChannels1);
+ initPortAudioDevice(m_rxOutPa, paNoDevice, g_soundCard1OutDeviceNum, 1,
+ g_soundCard1SampleRate, inputChannels1);
+ }
+ else
+ initPortAudioDevice(m_rxInPa, g_soundCard1InDeviceNum, g_soundCard1OutDeviceNum, 1,
+ g_soundCard1SampleRate, inputChannels1);
// Init Sound Card 2 ------------------------------------------------
if (g_nSoundCards == 2) {
- m_txPa = new PortAudioWrap();
+ m_txInPa = new PortAudioWrap();
+ if(two_tx)
+ m_txOutPa = new PortAudioWrap();
+ else
+ m_txOutPa = m_txInPa;
// sanity check on sound card device numbers
- //printf("m_txPa->getDeviceCount(): %d\n", m_txPa->getDeviceCount());
+ //printf("m_txInPa->getDeviceCount(): %d\n", m_txInPa->getDeviceCount());
//printf("g_soundCard2InDeviceNum: %d\n", g_soundCard2InDeviceNum);
//printf("g_soundCard2OutDeviceNum: %d\n", g_soundCard2OutDeviceNum);
- if ((m_txPa->getDeviceCount() <= g_soundCard2InDeviceNum) ||
- (m_txPa->getDeviceCount() <= g_soundCard2OutDeviceNum)) {
+ if ((m_txInPa->getDeviceCount() <= g_soundCard2InDeviceNum) ||
+ (m_txOutPa->getDeviceCount() <= g_soundCard2OutDeviceNum)) {
wxMessageBox(wxT("Sound Card 2 not present"), wxT("Error"), wxOK);
- delete m_rxPa;
- delete m_txPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
m_RxRunning = false;
return;
}
@@ -2132,7 +2178,12 @@
deviceInfo2 = Pa_GetDeviceInfo(g_soundCard2InDeviceNum);
if (deviceInfo2 == NULL) {
wxMessageBox(wxT("Couldn't get device info from Port Audio for Sound Card 1"), wxT("Error"), wxOK);
- delete m_rxPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
m_RxRunning = false;
return;
}
@@ -2141,8 +2192,15 @@
else
inputChannels2 = 2;
- initPortAudioDevice(m_txPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2,
+ if(two_tx) {
+ initPortAudioDevice(m_txInPa, g_soundCard2InDeviceNum, paNoDevice, 2,
g_soundCard2SampleRate, inputChannels2);
+ initPortAudioDevice(m_txOutPa, paNoDevice, g_soundCard2OutDeviceNum, 2,
+ g_soundCard2SampleRate, inputChannels2);
+ }
+ else
+ initPortAudioDevice(m_txInPa, g_soundCard2InDeviceNum, g_soundCard2OutDeviceNum, 2,
+ g_soundCard2SampleRate, inputChannels2);
}
// Init call back data structure ----------------------------------------------
@@ -2182,15 +2240,19 @@
// Start sound card 1 ----------------------------------------------------------
- m_rxPa->setUserData(g_rxUserdata);
- m_rxErr = m_rxPa->setCallback(rxCallback);
+ m_rxInPa->setUserData(g_rxUserdata);
+ m_rxErr = m_rxInPa->setCallback(rxCallback);
- m_rxErr = m_rxPa->streamOpen();
+ m_rxErr = m_rxInPa->streamOpen();
if(m_rxErr != paNoError) {
wxMessageBox(wxT("Sound Card 1 Open/Setup error."), wxT("Error"), wxOK);
- delete m_rxPa;
- delete m_txPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
destroy_fifos();
destroy_src();
deleteEQFilters(g_rxUserdata);
@@ -2199,11 +2261,15 @@
return;
}
- m_rxErr = m_rxPa->streamStart();
+ m_rxErr = m_rxInPa->streamStart();
if(m_rxErr != paNoError) {
wxMessageBox(wxT("Sound Card 1 Stream Start Error."), wxT("Error"), wxOK);
- delete m_rxPa;
- delete m_txPa;
+ delete m_rxInPa;
+ if(two_rx)
+ delete m_rxOutPa;
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
destroy_fifos();
destroy_src();
deleteEQFilters(g_rxUserdata);
@@ -2212,6 +2278,48 @@
return;
}
+ // Start separate output stream if needed
+
+ if(two_rx) {
+ m_rxOutPa->setUserData(g_rxUserdata);
+ m_rxErr = m_rxOutPa->setCallback(rxCallback);
+
+ m_rxErr = m_rxOutPa->streamOpen();
+
+ if(m_rxErr != paNoError) {
+ wxMessageBox(wxT("Sound Card 1 Second Stream Open/Setup error."), wxT("Error"), wxOK);
+ delete m_rxInPa;
+ delete m_rxOutPa;
+ delete m_txOutPa;
+ if(two_tx)
+ delete m_txOutPa;
+ destroy_fifos();
+ destroy_src();
+ deleteEQFilters(g_rxUserdata);
+ delete g_rxUserdata;
+ m_RxRunning = false;
+ return;
+ }
+
+ m_rxErr = m_rxOutPa->streamStart();
+ if(m_rxErr != paNoError) {
+ wxMessageBox(wxT("Sound Card 1 Second Stream Start Error."), wxT("Error"), wxOK);
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ delete m_rxInPa;
+ delete m_rxOutPa;
+ delete m_txOutPa;
+ if(two_tx)
+ delete m_txOutPa;
+ destroy_fifos();
+ destroy_src();
+ deleteEQFilters(g_rxUserdata);
+ delete g_rxUserdata;
+ m_RxRunning = false;
+ return;
+ }
+ }
+
// Start sound card 2 ----------------------------------------------------------
if (g_nSoundCards == 2) {
@@ -2221,16 +2329,24 @@
// chance of them both being called at the same time? We
// could need a mutex ...
- m_txPa->setUserData(g_rxUserdata);
- m_txErr = m_txPa->setCallback(txCallback);
- m_txErr = m_txPa->streamOpen();
+ m_txInPa->setUserData(g_rxUserdata);
+ m_txErr = m_txInPa->setCallback(txCallback);
+ m_txErr = m_txInPa->streamOpen();
if(m_txErr != paNoError) {
+fprintf(stderr, "Err: %d\n", m_txErr);
wxMessageBox(wxT("Sound Card 2 Open/Setup error."), wxT("Error"), wxOK);
- m_rxPa->stop();
- m_rxPa->streamClose();
- delete m_rxPa;
- delete m_txPa;
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ delete m_rxInPa;
+ if(two_rx) {
+ m_rxOutPa->stop();
+ m_rxOutPa->streamClose();
+ delete m_rxOutPa;
+ }
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
destroy_fifos();
destroy_src();
deleteEQFilters(g_rxUserdata);
@@ -2238,13 +2354,20 @@
m_RxRunning = false;
return;
}
- m_txErr = m_txPa->streamStart();
+ m_txErr = m_txInPa->streamStart();
if(m_txErr != paNoError) {
wxMessageBox(wxT("Sound Card 2 Start Error."), wxT("Error"), wxOK);
- m_rxPa->stop();
- m_rxPa->streamClose();
- delete m_rxPa;
- delete m_txPa;
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ delete m_rxInPa;
+ if(two_rx) {
+ m_rxOutPa->stop();
+ m_rxOutPa->streamClose();
+ delete m_rxOutPa;
+ }
+ delete m_txInPa;
+ if(two_tx)
+ delete m_txOutPa;
destroy_fifos();
destroy_src();
deleteEQFilters(g_rxUserdata);
@@ -2252,6 +2375,63 @@
m_RxRunning = false;
return;
}
+ // Start separate output stream if needed
+
+ if (two_tx) {
+
+ // question: can we use same callback data
+ // (g_rxUserdata)or both sound card callbacks? Is there a
+ // chance of them both being called at the same time? We
+ // could need a mutex ...
+
+ m_txOutPa->setUserData(g_rxUserdata);
+ m_txErr = m_txOutPa->setCallback(txCallback);
+ m_txErr = m_txOutPa->streamOpen();
+
+ if(m_txErr != paNoError) {
+ wxMessageBox(wxT("Sound Card 2 Second Stream Open/Setup error."), wxT("Error"), wxOK);
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ delete m_rxInPa;
+ if(two_rx) {
+ m_rxOutPa->stop();
+ m_rxOutPa->streamClose();
+ delete m_rxOutPa;
+ }
+ m_txInPa->stop();
+ m_txInPa->streamClose();
+ delete m_txInPa;
+ delete m_txOutPa;
+ destroy_fifos();
+ destroy_src();
+ deleteEQFilters(g_rxUserdata);
+ delete g_rxUserdata;
+ m_RxRunning = false;
+ return;
+ }
+ m_txErr = m_txOutPa->streamStart();
+ if(m_txErr != paNoError) {
+ wxMessageBox(wxT("Sound Card 2 Second Stream Start Error."), wxT("Error"), wxOK);
+ m_rxInPa->stop();
+ m_rxInPa->streamClose();
+ m_txInPa->stop();
+ m_txInPa->streamClose();
+ delete m_txInPa;
+ if(two_rx) {
+ m_rxOutPa->stop();
+ m_rxOutPa->streamClose();
+ delete m_rxOutPa;
+ }
+ delete m_txInPa;
+ delete m_txOutPa;
+ destroy_fifos();
+ destroy_src();
+ deleteEQFilters(g_rxUserdata);
+ delete g_rxUserdata;
+ m_RxRunning = false;
+ return;
+ }
+ }
}
// start tx/rx processing thread
@@ -2667,35 +2847,39 @@
assert(framesPerBuffer < MAX_FPB);
- for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels1)
- {
- indata[i] = *rptr;
- }
- if (fifo_write(cbData->infifo1, indata, framesPerBuffer)) {
- //wxLogDebug("infifo1 full\n");
- }
+ if(rptr) {
+ for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels1)
+ {
+ indata[i] = *rptr;
+ }
+ if (fifo_write(cbData->infifo1, indata, framesPerBuffer)) {
+ //wxLogDebug("infifo1 full\n");
+ }
+ }
// OK now set up output samples for this callback
- if (fifo_read(cbData->outfifo1, outdata, framesPerBuffer) == 0)
- {
- // write signal to both channels */
- for(i = 0; i < framesPerBuffer; i++, wptr += 2)
- {
- wptr[0] = outdata[i];
- wptr[1] = outdata[i];
- }
- }
- else
- {
- //wxLogDebug("outfifo1 empty\n");
- // zero output if no data available
- for(i = 0; i < framesPerBuffer; i++, wptr += 2)
- {
- wptr[0] = 0;
- wptr[1] = 0;
- }
- }
+ if(wptr) {
+ if (fifo_read(cbData->outfifo1, outdata, framesPerBuffer) == 0)
+ {
+ // write signal to both channels */
+ for(i = 0; i < framesPerBuffer; i++, wptr += 2)
+ {
+ wptr[0] = outdata[i];
+ wptr[1] = outdata[i];
+ }
+ }
+ else
+ {
+ //wxLogDebug("outfifo1 empty\n");
+ // zero output if no data available
+ for(i = 0; i < framesPerBuffer; i++, wptr += 2)
+ {
+ wptr[0] = 0;
+ wptr[1] = 0;
+ }
+ }
+ }
return paContinue;
}
@@ -3210,43 +3394,51 @@
assert(framesPerBuffer < MAX_FPB);
- for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels2)
- {
- indata[i] = *rptr;
- }
+ if(rptr) {
+ for(i = 0; i < framesPerBuffer; i++, rptr += cbData->inputChannels2)
+ {
+ indata[i] = *rptr;
+ }
+ }
//#define SC2_LOOPBACK
#ifdef SC2_LOOPBACK
+ //TODO: This doesn't work unless using the same soundcard!
- for(i = 0; i < framesPerBuffer; i++, wptr += 2)
- {
- wptr[0] = indata[i];
- wptr[1] = indata[i];
- }
+ if(wptr) {
+ for(i = 0; i < framesPerBuffer; i++, wptr += 2)
+ {
+ wptr[0] = indata[i];
+ wptr[1] = indata[i];
+ }
+ }
#else
- fifo_write(cbData->infifo2, indata, framesPerBuffer);
+ if(rptr)
+ fifo_write(cbData->infifo2, indata, framesPerBuffer);
// OK now set up output samples for this callback
- if (fifo_read(cbData->outfifo2, outdata, framesPerBuffer) == 0)
- {
- // write signal to both channels */
- for(i = 0; i < framesPerBuffer; i++, wptr += 2)
- {
- wptr[0] = outdata[i];
- wptr[1] = outdata[i];
- }
- }
- else
- {
- // zero output if no data available
- for(i = 0; i < framesPerBuffer; i++, wptr += 2)
- {
- wptr[0] = 0;
- wptr[1] = 0;
- }
- }
+ if(wptr) {
+ if (fifo_read(cbData->outfifo2, outdata, framesPerBuffer) == 0)
+ {
+ // write signal to both channels */
+ for(i = 0; i < framesPerBuffer; i++, wptr += 2)
+ {
+ wptr[0] = outdata[i];
+ wptr[1] = outdata[i];
+ }
+ }
+ else
+ {
+ // zero output if no data available
+ for(i = 0; i < framesPerBuffer; i++, wptr += 2)
+ {
+ wptr[0] = 0;
+ wptr[1] = 0;
+ }
+ }
+ }
#endif
return paContinue;
}
Index: src/fdmdv2_main.h
===================================================================
--- src/fdmdv2_main.h (revision 1594)
+++ src/fdmdv2_main.h (working copy)
@@ -336,8 +336,10 @@
bool m_RxRunning;
- PortAudioWrap *m_rxPa;
- PortAudioWrap *m_txPa;
+ PortAudioWrap *m_rxInPa;
+ PortAudioWrap *m_rxOutPa;
+ PortAudioWrap *m_txInPa;
+ PortAudioWrap *m_txOutPa;
PaError m_rxErr;
PaError m_txErr;
Index: src/fdmdv2_pa_wrapper.cpp
===================================================================
--- src/fdmdv2_pa_wrapper.cpp (revision 1594)
+++ src/fdmdv2_pa_wrapper.cpp (working copy)
@@ -52,8 +52,8 @@
{
return Pa_OpenStream(
&m_pStream,
- &m_inputBuffer,
- &m_outputBuffer,
+ m_inputBuffer.device == paNoDevice ? NULL : &m_inputBuffer,
+ m_outputBuffer.device == paNoDevice ? NULL : &m_outputBuffer,
m_samplerate,
m_framesPerBuffer,
m_statusFlags,
------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.
Get unparalleled scalability from the best Selenium testing platform available
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
_______________________________________________
Freetel-codec2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freetel-codec2