int g_soundCard1OutDeviceNum = 0;
int g_soundCard1SampleRate = 48000;
-int g_soundCard2InDeviceNum = 2;
-int g_soundCard2OutDeviceNum = 2;
+int g_soundCard2InDeviceNum = 1;
+int g_soundCard2OutDeviceNum = 1;
int g_soundCard2SampleRate = 44100;
int cb_cnt, cb1, cb2;
}
}
+#ifdef OLD
inline void short_to_float(float out_float[], short in_short[], int n) {
int i;
for(i=0; i<n; i++)
for(i=0; i<n; i++)
out_short[i] = (short)in_float[i];
}
+#endif
+
+// returns number of output samples generated by resampling
+
+static int resample(SRC_STATE *src,
+ short output_short[],
+ short input_short[],
+ int output_sample_rate,
+ int input_sample_rate,
+ int length_output_short, // maximum output array length in samples
+ int length_input_short
+ )
+{
+ SRC_DATA src_data;
+ float input[N48*2];
+ float output[N48*2];
+
+ assert(src != NULL);
+ assert(length_input_short <= N48*2);
+ assert(length_output_short <= N48*2);
+
+ src_short_to_float_array(input_short, input, length_input_short);
+
+ src_data.data_in = input;
+ src_data.data_out = output;
+ src_data.input_frames = length_input_short;
+ src_data.output_frames = length_output_short;
+ src_data.end_of_input = 0;
+ src_data.src_ratio = (float)output_sample_rate/input_sample_rate;
+
+ src_process(src, &src_data);
+
+ assert(src_data.output_frames_gen <= length_output_short);
+ src_float_to_short_array(output, output_short, src_data.output_frames_gen);
+
+ return src_data.output_frames_gen;
+}
+
//-------------------------------------------------------------------------
// rxCallback()
// temp buffers re-used by tx and rx processing
- short in8k_short[N8];
- float in8k[2*N8];
- float out8k[2*N8];
+ short in8k_short[2*N8];
+ short in48k_short[2*N48];
short out8k_short[2*N8];
- float out48k[2*N48];
short out48k_short[2*N48];
- short in48k_short[2*N48];
- float in48k[2*N48];
short indata[MAX_FPB];
short outdata[MAX_FPB];
- SRC_DATA src_data;
+ int nout;
int ret;
unsigned int i;
-
+
(void) timeInfo;
(void) statusFlags;
//printf("%d cb1 .. %d", cb1++, cb1-cb2);
assert(inputBuffer != NULL);
assert(outputBuffer != NULL);
+
/*
framesPerBuffer is portaudio-speak for number of samples we
actually get from the record side and need to provide to the
play side. On Linux (at least) it was found that
framesPerBuffer may not always be what we ask for in the
framesPerBuffer field of Pa_OpenStream. For example a request
- for 960 sample buffers lead to framesPerBuffer = 1024.
-
- To perform the 48 to 8 kHz conversion we need an integer
- multiple of FDMDV_OS samples. As we can't guarantee the size
- of framesPerBuffer we do a little FIFO buffering to interface
- the different input and output number of sample requirements.
+ for 960 sample buffers may lead to framesPerBuffer = 1024 in
+ this call back.
- We also use FIFOs at the input and output of the rx and tx
- processing to interface between different buffer sizes. For
- example the number of samples rqd for the demod is time
- varying.
-
- It does result in a bunch of code that's a hard to
- understand. So I can't help think there is a better way to do this
- ....
+ So we use a bunch of FIFOs to interface between different
+ buffer sizes required at each processing step, and to
+ communicate between the call backs for the two sound cards.
*/
//
{
indata[i] = *rptr;
}
- ret = fifo_write(cbData->infifo1, indata, framesPerBuffer);
- assert(ret != -1);
+ fifo_write(cbData->infifo1, indata, framesPerBuffer);
// while we have enough input samples available ...
while (fifo_read(cbData->infifo1, in48k_short, N48) == 0)
{
- // note: modifying fdmdv_48_to_8() to have short arrays rather
- // than floats would remove all these float to short
- // conversions
-
-#ifdef OLD
- short_to_float(&in48k1[FDMDV_OS_TAPS], in48k_short, N48);
- fdmdv_48_to_8(out8k, &in48k1[FDMDV_OS_TAPS], N8);
- float_to_short(out8k_short, out8k, N8);
-#endif
-
- src_short_to_float_array(in48k_short, in48k, N48);
-
- src_data.data_in = in48k;
- src_data.data_out = out8k;
- src_data.input_frames = N48;
- src_data.output_frames = N8;
- src_data.end_of_input = 0;
- src_data.src_ratio = (float)FS/g_soundCard1SampleRate;
-
- src_process(cbData->insrc1, &src_data);
- assert(src_data.output_frames_gen <= N8);
-
- src_float_to_short_array(out8k, out8k_short, src_data.output_frames_gen);
-
- fifo_write(cbData->rxinfifo, out8k_short, src_data.output_frames_gen);
+ int n8k;
+
+ n8k = resample(cbData->insrc1, in8k_short, in48k_short, FS, g_soundCard1SampleRate, N8, N48);
+ fifo_write(cbData->rxinfifo, in8k_short, n8k);
per_frame_rx_processing(cbData->rxoutfifo, g_CodecBits, cbData->rxinfifo, &g_nRxIn, &g_State, g_pCodec2);
- // if demod out of sync echo audio at input to demod to
- // headset aid in tuning (ie we hear SSB radio output)
+ // if demod out of sync just pass thru audio so we can hear
+ // SSB radio ouput as an aid to tuning
if (g_State == 0)
- memcpy(in8k, out8k, sizeof(float)*N8);
+ memcpy(out8k_short, in8k_short, sizeof(short)*n8k);
else {
- memset(in8k_short, 0, sizeof(short)*N8);
- fifo_read(cbData->rxoutfifo, in8k_short, N8);
- src_short_to_float_array(in8k_short, in8k, N8);
- //short_to_float(&in8k1[MEM8], in8k_short, N8);
+ memset(out8k_short, 0, sizeof(short)*N8);
+ fifo_read(cbData->rxoutfifo, out8k_short, N8);
}
- //fdmdv_8_to_48(out48k, &in8k1[MEM8], N8);
- //float_to_short(out48k_short, out48k, N48);
- src_data.data_in = in8k;
- src_data.data_out = out48k;
- src_data.input_frames = N8;
- src_data.output_frames = N48;
- src_data.end_of_input = 0;
-
if (g_nSoundCards == 1) {
- src_data.src_ratio = (float)g_soundCard1SampleRate/FS;
- src_process(cbData->outsrc2, &src_data);
- //printf("src_data.output_frames_gen: %d\n", src_data.output_frames_gen);
- src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
- fifo_write(cbData->outfifo1, out48k_short, src_data.output_frames_gen);
+ nout = resample(cbData->outsrc2, out48k_short, out8k_short, g_soundCard1SampleRate, FS, N48, N8);
+ fifo_write(cbData->outfifo1, out48k_short, nout);
}
else {
- src_data.src_ratio = (float)g_soundCard2SampleRate/FS;
- src_process(cbData->outsrc2, &src_data);
- src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
- fifo_write(cbData->outfifo2, out48k_short, src_data.output_frames_gen);
- //printf("after outfifo2 write %d fifo_n: %d\n", src_data.output_frames_gen, fifo_n(cbData->outfifo2));
+ nout = resample(cbData->outsrc2, out48k_short, out8k_short, g_soundCard2SampleRate, FS, N48, N8);
+ fifo_write(cbData->outfifo2, out48k_short, nout);
}
- assert(src_data.output_frames_gen <= N48);
}
//
// 48kHz, so this loop will run 0 or 1 times.
while((unsigned)fifo_n(cbData->outfifo1) < framesPerBuffer) {
- short tx_speech_in[2*N8];
- short tx_mod_out[2*N8];
// number of microphone samples we need at g_soundcards2SampleRate
- int nsam = g_soundCard2SampleRate * (float)codec2_samples_per_frame(g_pCodec2)/FS;
+ int nsam = g_soundCard2SampleRate * (float)codec2_samples_per_frame(g_pCodec2)/FS;
assert(nsam <= 2*N48);
// infifo2 is written to by another sound card so it may
// just result in a short interruption in audio being fed
// to codec2_enc, possibly making a click every now and
// again in the decoded audio at the other end.
-
// zero speech input just in case infifo2 underflows
fifo_read(cbData->infifo2, in48k_short, nsam);
- //if (mute_mic)
- // memset(in48k_short, 0, sizeof(short)*nsam);
-
- src_short_to_float_array(in48k_short, in48k, nsam);
-
- src_data.data_in = in48k;
- src_data.data_out = out8k;
- src_data.input_frames = nsam;
- src_data.output_frames = codec2_samples_per_frame(g_pCodec2);
- src_data.end_of_input = 0;
- src_data.src_ratio = (float)FS/g_soundCard2SampleRate;
-
- src_process(cbData->insrc2, &src_data);
- assert(src_data.output_frames_gen <= codec2_samples_per_frame(g_pCodec2));
-
- src_float_to_short_array(out8k, tx_speech_in, src_data.output_frames_gen);
+ nout = resample(cbData->insrc2, in8k_short, in48k_short, FS, g_soundCard2SampleRate, 2*N8, nsam);
if (write_file) {
- fwrite(tx_speech_in, sizeof(short), 2*N8, g_write_file);
+ fwrite( in8k_short, sizeof(short), nout, g_write_file);
}
if (read_file) {
- int n = fread( tx_speech_in, sizeof(short), 2*N8, g_file);
+ int n = fread( in8k_short , sizeof(short), 2*N8, g_file);
if (n != 2*N8) {
- //printf("rewind\n");
rewind(g_file);
}
}
- assert(codec2_samples_per_frame(g_pCodec2) == (2*N8));
-
- per_frame_tx_processing(tx_mod_out, tx_speech_in, g_pCodec2);
+ per_frame_tx_processing(out8k_short, in8k_short, g_pCodec2);
// output 40ms of modem tone
-#ifdef OLD
-
- short_to_float(&in8k2[MEM8], tx_mod_out, 2*N8);
- fdmdv_8_to_48(out48k, &in8k2[MEM8], 2*N8);
- float_to_short(out48k_short, out48k, 2*N48);
-#endif
- src_short_to_float_array(tx_mod_out, in8k, 2*N8);
-
- src_data.data_in = in8k;
- src_data.data_out = out48k;
- src_data.input_frames = 2*N8;
- src_data.output_frames = 2*N48;
- src_data.end_of_input = 0;
- src_data.src_ratio = (float)g_soundCard1SampleRate/FS;
-
- src_process(cbData->outsrc1, &src_data);
- assert(src_data.output_frames_gen <= 2*N48);
-
- src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
- fifo_write(cbData->outfifo1, out48k_short, src_data.output_frames_gen );
+ nout = resample(cbData->outsrc1, out48k_short, out8k_short, g_soundCard1SampleRate, FS, 2*N48, 2*N8);
+ fifo_write(cbData->outfifo1, out48k_short, nout);
}
}