OSCCdata(rx.osc.gen, i));
}
- /* filtering, metering, & AGC */
+ /* filtering, metering, squelch, & AGC */
if (rx.mode != SPEC) {
if (rx.tick == 0) reset_OvSv(rx.filt.ovsv);
filter_OvSv(rx.filt.ovsv);
CXBhave(rx.buf.o) = CXBhave(rx.buf.i);
- if (uni.meter.flag) do_meter(CXBbase(rx.buf.o), uni.buflen);
+ if (uni.meter.flag) do_meter(CXBbase(rx.buf.o), uni.buflen);
+ if (should_do_rx_squelch()) do_squelch();
if (rx.agc.flag) DigitalAgc(rx.agc.gen, rx.tick);
} else if (uni.meter.flag)
do_meter(CXBbase(rx.buf.o), uni.buflen);
do_rx(), rx.tick++;
for (i = 0; i < n; i++)
- bufl[i] = (float)CXBimag(rx.buf.o, i), bufr[i] = (float)CXBreal(rx.buf.o, i);
+ bufl[i] = (float) CXBimag(rx.buf.o, i), bufr[i] = (float) CXBreal(rx.buf.o, i);
CXBhave(rx.buf.o) = n;
break;
do_tx(), tx.tick++;
for (i = 0; i < n; i++)
- bufl[i] = (float)CXBimag(tx.buf.o, i), bufr[i] = (float)CXBreal(tx.buf.o, i);
+ bufl[i] = (float) CXBimag(tx.buf.o, i), bufr[i] = (float) CXBreal(tx.buf.o, i);
CXBhave(tx.buf.o) = n;
break;
}
-/* speechproc.c
+/* speechproc.h
This file is part of a program that implements a Software-Defined Radio.
-Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
+Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY, Phil Harman, VK6APH
+Based on Visual Basic code for SDR by Phil Harman
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
void
delSpeechProc(SpeechProc sp) {
if (sp) {
+ delRLB(sp->CG);
delCXB(sp->SpeechProcessorBuffer);
safefree((char *) sp);
}
SpeechProcessor(SpeechProc sp) {
int i;
REAL r = 0.0, Mag;
+
+ // K was 0.4 in VB version, this value is better, perhaps due to filters that follow?
for (i = 0; i < sp->size; i++)
- r = max(r, Cmag(CXBdata(sp->SpeechProcessorBuffer, i)));
- Mag = Cmag(CXBdata(sp->SpeechProcessorBuffer, 0));
- if (Mag > 0.0) {
- RLBdata(sp->CG, 0) = sp->LastCG * (1.0 - sp->K) + (sp->K * r / Mag);
- if (RLBdata(sp->CG, 0) > sp->MaxGain)
- RLBdata(sp->CG, 0) = sp->MaxGain;
- } else
- RLBdata(sp->CG, 0) = 1.0;
- for (i = 1; i < sp->size; i++) {
- Mag = Cmag(CXBdata(sp->SpeechProcessorBuffer, i));
- if (Mag > 0.0) {
- RLBdata(sp->CG, i) =
- RLBdata(sp->CG, i - 1) * (1 - sp->K) + (sp->K * r / Mag);
+ r = max(r, Cmag(CXBdata(sp->SpeechProcessorBuffer, i))); // find the peak magnitude value in the sample buffer
+ RLBdata(sp->CG, 0) = sp->LastCG; // restore from last time
+ for (i = 1; i <= sp->size ; i++) {
+ Mag = Cmag(CXBdata(sp->SpeechProcessorBuffer, i - 1));
+ if (Mag != 0.0) {
+ RLBdata(sp->CG, i) = RLBdata(sp->CG, i - 1) * (1 - sp->K) + (sp->K * r / Mag); // Frerking's formula
if (RLBdata(sp->CG, i) > sp->MaxGain)
RLBdata(sp->CG, i) = sp->MaxGain;
} else
- RLBdata(sp->CG, i) = 1.0;
+ RLBdata(sp->CG, i) = sp->MaxGain;
}
- sp->LastCG = RLBdata(sp->CG, sp->size - 1);
- for (i = 0; i < sp->size; i++)
- CXBdata(sp->SpeechProcessorBuffer, i) =
- Cscl(CXBdata(sp->SpeechProcessorBuffer, i), RLBdata(sp->CG, i));
+ sp->LastCG = RLBdata(sp->CG, sp->size); // save for next time
+
+ for (i = 0; i < sp->size; i++) // multiply each sample by its gain constant
+ CXBdata(sp->SpeechProcessorBuffer, i) = Cscl(CXBdata(sp->SpeechProcessorBuffer, i),
+ RLBdata(sp->CG, i));
}
+