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

Reply via email to