* soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet)
@ 2012-03-03 0:54 Guido Trentalancia
2012-03-03 9:50 ` walter harms
0 siblings, 1 reply; 9+ messages in thread
From: Guido Trentalancia @ 2012-03-03 0:54 UTC (permalink / raw)
To: linux-hams; +Cc: t.sailer
Hello !
Although the soundmodem code has been removed from the kernel and moved
to userspace, there was a report still open about a bug for 300 baud
AFSK on the linux-hams list, so I am also carbon-copying the list...
I have created a patch for the AFSK modulator so that it is made to work
at 300 baud and later on I am possibly going to create a supplemental
one for the AFSK demodulator (as it appears still a bit buggy in my
setup).
This patch modifies the AFSK modulator in version 0.16 of the soundmodem
application as it appears to be problematic in particular at 300 baud
(in general, it might be buggy for bitrates lower than 1200 baud,
although I have not done any testing at other bitrates).
It is meant to be a temporary patch for further revision or for users
that cannot use 300 baud AFSK at all as it needs further testing and
improvement especially because, at least in my setup, it does not
entirely fix the demodulation at 300 baud AFSK (reception).
First, the patch modifies the AFSK modulator so that it always uses at
least a (pre-defined) minimum sampling rate of 11.025kHz (instead of
always using a supposedly variable sampling rate calculated from the
bitrate). This should make the code work on most soundcards (at the
expense of a few extra CPU cycles), including some buggy ones which
might not deal well with the low sampling rates that are the theoretical
minimum for low bitrates (such as 300 baud). Also, the modified code
makes sure that the sampling rate is always the same for both the
modulator and the demodulator (provided that they operate at the same
bitrate) and it introduces a different (supposedly better) method of
determining the optimal sampling rate.
Then, the patch removes the probably buggy code that always selects a
bitrate of 1200 baud for the modulator during the initial internal
configuration, so that the AFSK modem effectively honours the bitrate
selected by the user in the configuration file.
Finally, the patch removes the buggy code that changes the AFSK tone
frequencies if they are greater than four times the bitrate, thus
honouring the AFSK tone frequencies selected in the configuration file.
I have also introduced optional windowing functions (other than the
Hamming one) for experimentation but at the moment they are completely
untested and they can only be selected during compilation.
After applying this patch, the AFSK modulator should work normally for
300 baud (or in general bitrates different/less than 1200 baud) and the
user should be able to select any AFSK tone frequencies.
In other words, this patch should fix the AFSK modulator for the problem
reported, for example, here:
- http://he.fi/archive/linux-hams/200608/0005.html
- http://marc.info/?l=linux-hams&m=129059468102018&w=2
I shall note that the trick suggested there of using the original
soundmodem code with tones below 1200 Hz for 300 baud, did not work for
me.
As already explained this patch is for testing mainly, so please do not
apply it directly to new releases. Although the fixes described above for
the AFSK modulator have also been applied to the AFSK demodulator, the
latter needs further modifications and the whole patch needs to be tested,
reviewed and eventually improved so that it is stable on most setups.
I suppose the RX filters, or at least their parameters, should be
double-checked and eventually optimized for 300 baud demodulation (at the
moment I am doing some testing with increased values for RXFILTLEN and/or
RXFILTOVERBITS but so far I am still missing the optimal results that I
would like to achieve).
In the meanwhile, I would be grateful if somebody could test this on
other setups and then report.
Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com>
---
afsk/modem.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 176 insertions(+), 34 deletions(-)
--- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100
+++ soundmodem-0.16/afsk/modem.c 2012-03-03 01:08:17.728744850 +0100
@@ -32,8 +32,58 @@
#include "modem.h"
#include "costab.h"
+/*
+ * IZ6RDB 29/02/2012: always use a minimum samplerate
+ * otherwise some sound cards, might not work well
+ * especially at bitrates lower than 1200 baud (such
+ * as 300 baud for HF).
+ *
+ * The value is defined in Hz and it should never be
+ * less than 9600 Hz to avoid problems, although the
+ * recommended value is 11025 Hz for most soundcards.
+ *
+ * Some cards, might even require that only their
+ * maximum allowed sampling rate of 48kHz is used
+ * (for example, according to online reports some
+ * embedded SiS 701x AC'97 controllers).
+ */
+#define MINIMUM_SAMPLERATE 11025
+
+/*
+ * IZ6RDB 01/03/2012: define different possible
+ * window types for the FIR filters and choose
+ * one of the available types:
+ *
+ * - NONE
+ * - HAMMING (window used up to version 0.16)
+ * - HANNING
+ * - BLACKMAN
+ * - WELCH
+ */
+#define FIR_WINDOW HAMMING
+
+/*
+ * IZ6RDB 01/03/2012: introduce a parameter
+ * called "bandwidth expansion factor", which
+ * is a real positive number slightly greater
+ * than unity (up to 2.0) that accounts for
+ * guard-bands and non-ideal filtering.
+ *
+ * This value is only used for estimating the
+ * required sampling rate.
+ *
+ * Values are usually between 1.125 and 1.4.
+ *
+ * The recommended value is 1.36.
+ */
+#define BANDWIDTH_EXPANSION_FACTOR 1.36
+
/* --------------------------------------------------------------------- */
+#ifndef BANDWIDTH_EXPANSION_FACTOR
+#define BANDWIDTH_EXPANSION_FACTOR 1.36
+#endif
+
struct modstate {
struct modemchannel *chan;
unsigned int bps, f0, f1, notdiff, maxbitlen;
@@ -53,6 +103,9 @@ static const struct modemparams modparam
static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[])
{
struct modstate *s;
+ unsigned int bandwidth, expanded_bandwidth;
+ unsigned int min_samplerate, optimized_samplerate;
+ unsigned int f_carrier;
if (!(s = malloc(sizeof(struct modstate))))
logprintf(MLOG_FATAL, "out of memory\n");
@@ -63,22 +116,45 @@ static void *modconfig(struct modemchann
s->bps = 100;
if (s->bps > 9600)
s->bps= 9600;
- } else
- s->bps = 1200;
- if (params[1]) {
+ }
+ if (params[1])
s->f0 = strtoul(params[1], NULL, 0);
- if (s->f0 > s->bps * 4)
- s->f0 = s->bps * 4;
- } else
- s->f0 = 1200;
- if (params[2]) {
+ if (params[2])
s->f1 = strtoul(params[2], NULL, 0);
- if (s->f1 > s->bps * 4)
- s->f1 = s->bps * 4;
- } else
- s->f1 = 2200;
s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0;
- *samplerate = 8 * s->bps;
+
+ /*
+ * Calculate the bandwidth of the baseband (audio) signal:
+ * basically this is the highest frequency of the two
+ * possible tones.
+ */
+ bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1;
+
+ /*
+ * Calculate the expanded bandwidth (with guard-bands)
+ * to get a better estimate.
+ */
+ expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth;
+
+ /* Nyquist criteria (minimum sampling rate) */
+ min_samplerate = 2 * expanded_bandwidth;
+
+ /* Calculate the (audio) carrier frequency */
+ f_carrier = (s->f0 + s->f1)/2;
+
+ /* Calculate intermediate operating point sampling rate */
+ optimized_samplerate = 4 * f_carrier;
+ if (optimized_samplerate > min_samplerate)
+ min_samplerate = optimized_samplerate;
+
+ /*
+ * Make sure that the minimum recommended sampling
+ * rate for the soundcard is exceeded.
+ */
+ if (min_samplerate < MINIMUM_SAMPLERATE)
+ min_samplerate = MINIMUM_SAMPLERATE;
+
+ *samplerate = min_samplerate;
return s;
}
@@ -202,7 +278,9 @@ static const struct modemparams demodpar
static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[])
{
struct demodstate *s;
- unsigned int f;
+ unsigned int bandwidth, expanded_bandwidth;
+ unsigned int min_samplerate, optimized_samplerate;
+ unsigned int f_carrier;
if (!(s = malloc(sizeof(struct demodstate))))
logprintf(MLOG_FATAL, "out of memory\n");
@@ -213,27 +291,45 @@ static void *demodconfig(struct modemcha
s->bps = 100;
if (s->bps > 9600)
s->bps= 9600;
- } else
- s->bps = 1200;
- if (params[1]) {
+ }
+ if (params[1])
s->f0 = strtoul(params[1], NULL, 0);
- if (s->f0 > s->bps * 4)
- s->f0 = s->bps * 4;
- } else
- s->f0 = 1200;
- if (params[2]) {
+ if (params[2])
s->f1 = strtoul(params[2], NULL, 0);
- if (s->f1 > s->bps * 4)
- s->f1 = s->bps * 4;
- } else
- s->f1 = 2200;
s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0;
- f = s->f0;
- if (s->f1 > f)
- f = s->f1;
- f += s->bps/2;
- f = (2*f) + (f >> 1);
- *samplerate = f;
+
+ /*
+ * Calculate the bandwidth of the baseband (audio) signal:
+ * basically this is the highest frequency of the two
+ * possible tones.
+ */
+ bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1;
+
+ /*
+ * Calculate the expanded bandwidth (with guard-bands)
+ * to get a better estimate.
+ */
+ expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth;
+
+ /* Nyquist criteria (minimum sampling rate) */
+ min_samplerate = 2 * expanded_bandwidth;
+
+ /* Calculate the (audio) carrier frequency */
+ f_carrier = (s->f0 + s->f1)/2;
+
+ /* Calculate intermediate operating point sampling rate */
+ optimized_samplerate = 4 * f_carrier;
+ if (optimized_samplerate > min_samplerate)
+ min_samplerate = optimized_samplerate;
+
+ /*
+ * Make sure that the minimum recommended sampling
+ * rate for the soundcard is exceeded.
+ */
+ if (min_samplerate < MINIMUM_SAMPLERATE)
+ min_samplerate = MINIMUM_SAMPLERATE;
+
+ *samplerate = min_samplerate;
return s;
}
@@ -364,11 +460,41 @@ static inline double sinc(double x)
return sin(arg) / arg;
}
-static inline double hamming(double x)
+/*
+ * The Hamming window is the original one (used
+ * exclusively up to version 0.16).
+ * Later versions introduced other optional
+ * windows, so that they can be changed before
+ * compilation and tested in order to try
+ * achieving reduced passband ripples at the
+ * expense of slower passband to stopband
+ * roll-off.
+ */
+static inline double no_window(double x)
+{
+ return 1;
+}
+
+static inline double hamming_window(double x)
{
return 0.54-0.46*cos((2*M_PI)*x);
}
+static inline double hanning_window(double x)
+{
+ return 0.5-0.5*cos((2*M_PI)*x);
+}
+
+static inline double blackman_window(double x)
+{
+ return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x);
+}
+
+static inline double welch_window(double x)
+{
+ return 1.0-pow((2*x-1),2);
+}
+
static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate)
{
struct demodstate *s = (struct demodstate *)state;
@@ -388,7 +514,23 @@ static void demodinit(void *state, unsig
if (w > 1)
w = 0;
else
- w = hamming(w);
+#ifdef FIR_WINDOW
+#if (FIR_WINDOW == NONE)
+ w = no_window(w);
+#elif (FIR_WINDOW == HAMMING)
+ w = hamming_window(w);
+#elif (FIR_WINDOW == HANNING)
+ w = hanning_window(w);
+#elif (FIR_WINDOW == BLACKMAN)
+ w = blackman_window(w);
+#elif (FIR_WINDOW == WELCH)
+ w = welch_window(w);
+#else
+#error "Unknown FIR Window selected !"
+#endif
+#else // default to Hamming window
+ w = hamming_window(w);
+#endif
f0r[i] = w * cos(ph0 * i);
f0i[i] = w * sin(ph0 * i);
f1r[i] = w * cos(ph1 * i);
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) 2012-03-03 0:54 soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) Guido Trentalancia @ 2012-03-03 9:50 ` walter harms 2012-03-03 14:47 ` Guido Trentalancia 2012-03-03 18:48 ` soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) Guido Trentalancia 0 siblings, 2 replies; 9+ messages in thread From: walter harms @ 2012-03-03 9:50 UTC (permalink / raw) To: Guido Trentalancia; +Cc: linux-hams, t.sailer Am 03.03.2012 01:54, schrieb Guido Trentalancia: > Hello ! > > Although the soundmodem code has been removed from the kernel and moved > to userspace, there was a report still open about a bug for 300 baud > AFSK on the linux-hams list, so I am also carbon-copying the list... > > I have created a patch for the AFSK modulator so that it is made to work > at 300 baud and later on I am possibly going to create a supplemental > one for the AFSK demodulator (as it appears still a bit buggy in my > setup). > > This patch modifies the AFSK modulator in version 0.16 of the soundmodem > application as it appears to be problematic in particular at 300 baud > (in general, it might be buggy for bitrates lower than 1200 baud, > although I have not done any testing at other bitrates). > > It is meant to be a temporary patch for further revision or for users > that cannot use 300 baud AFSK at all as it needs further testing and > improvement especially because, at least in my setup, it does not > entirely fix the demodulation at 300 baud AFSK (reception). > > First, the patch modifies the AFSK modulator so that it always uses at > least a (pre-defined) minimum sampling rate of 11.025kHz (instead of > always using a supposedly variable sampling rate calculated from the > bitrate). This should make the code work on most soundcards (at the > expense of a few extra CPU cycles), including some buggy ones which > might not deal well with the low sampling rates that are the theoretical > minimum for low bitrates (such as 300 baud). Also, the modified code > makes sure that the sampling rate is always the same for both the > modulator and the demodulator (provided that they operate at the same > bitrate) and it introduces a different (supposedly better) method of > determining the optimal sampling rate. > > Then, the patch removes the probably buggy code that always selects a > bitrate of 1200 baud for the modulator during the initial internal > configuration, so that the AFSK modem effectively honours the bitrate > selected by the user in the configuration file. > > Finally, the patch removes the buggy code that changes the AFSK tone > frequencies if they are greater than four times the bitrate, thus > honouring the AFSK tone frequencies selected in the configuration file. > > I have also introduced optional windowing functions (other than the > Hamming one) for experimentation but at the moment they are completely > untested and they can only be selected during compilation. > > After applying this patch, the AFSK modulator should work normally for > 300 baud (or in general bitrates different/less than 1200 baud) and the > user should be able to select any AFSK tone frequencies. > > In other words, this patch should fix the AFSK modulator for the problem > reported, for example, here: > > - http://he.fi/archive/linux-hams/200608/0005.html > - http://marc.info/?l=linux-hams&m=129059468102018&w=2 > > I shall note that the trick suggested there of using the original > soundmodem code with tones below 1200 Hz for 300 baud, did not work for > me. > > As already explained this patch is for testing mainly, so please do not > apply it directly to new releases. Although the fixes described above for > the AFSK modulator have also been applied to the AFSK demodulator, the > latter needs further modifications and the whole patch needs to be tested, > reviewed and eventually improved so that it is stable on most setups. > I suppose the RX filters, or at least their parameters, should be > double-checked and eventually optimized for 300 baud demodulation (at the > moment I am doing some testing with increased values for RXFILTLEN and/or > RXFILTOVERBITS but so far I am still missing the optimal results that I > would like to achieve). > > In the meanwhile, I would be grateful if somebody could test this on > other setups and then report. > > Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com> > --- > afsk/modem.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++---------- > 1 file changed, 176 insertions(+), 34 deletions(-) > > --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 > +++ soundmodem-0.16/afsk/modem.c 2012-03-03 01:08:17.728744850 +0100 > @@ -32,8 +32,58 @@ > #include "modem.h" > #include "costab.h" > > +/* > + * IZ6RDB 29/02/2012: always use a minimum samplerate > + * otherwise some sound cards, might not work well > + * especially at bitrates lower than 1200 baud (such > + * as 300 baud for HF). > + * > + * The value is defined in Hz and it should never be > + * less than 9600 Hz to avoid problems, although the > + * recommended value is 11025 Hz for most soundcards. > + * > + * Some cards, might even require that only their > + * maximum allowed sampling rate of 48kHz is used > + * (for example, according to online reports some > + * embedded SiS 701x AC'97 controllers). > + */ > +#define MINIMUM_SAMPLERATE 11025 > + > +/* > + * IZ6RDB 01/03/2012: define different possible > + * window types for the FIR filters and choose > + * one of the available types: > + * > + * - NONE > + * - HAMMING (window used up to version 0.16) > + * - HANNING > + * - BLACKMAN > + * - WELCH > + */ > +#define FIR_WINDOW HAMMING > + > +/* > + * IZ6RDB 01/03/2012: introduce a parameter > + * called "bandwidth expansion factor", which > + * is a real positive number slightly greater > + * than unity (up to 2.0) that accounts for > + * guard-bands and non-ideal filtering. > + * > + * This value is only used for estimating the > + * required sampling rate. > + * > + * Values are usually between 1.125 and 1.4. > + * > + * The recommended value is 1.36. > + */ > +#define BANDWIDTH_EXPANSION_FACTOR 1.36 > + > /* --------------------------------------------------------------------- */ > > +#ifndef BANDWIDTH_EXPANSION_FACTOR > +#define BANDWIDTH_EXPANSION_FACTOR 1.36 > +#endif > + I do not see the distance between the #define BANDWIDTH_EXPANSION_FACTOR and the #ifndef BANDWIDTH_EXPANSION_FACTOR but i would suggest to remove the first one or the check. You are setting it to default values either way that is confusing. > struct modstate { > struct modemchannel *chan; > unsigned int bps, f0, f1, notdiff, maxbitlen; > @@ -53,6 +103,9 @@ static const struct modemparams modparam > static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > { > struct modstate *s; > + unsigned int bandwidth, expanded_bandwidth; > + unsigned int min_samplerate, optimized_samplerate; > + unsigned int f_carrier; > > if (!(s = malloc(sizeof(struct modstate)))) > logprintf(MLOG_FATAL, "out of memory\n"); It is a good habbit to do this in two lines: s = malloc(sizeof(struct modstate)); if (!s) > @@ -63,22 +116,45 @@ static void *modconfig(struct modemchann > s->bps = 100; > if (s->bps > 9600) > s->bps= 9600; > - } else > - s->bps = 1200; > - if (params[1]) { > + } > + if (params[1]) > s->f0 = strtoul(params[1], NULL, 0); > - if (s->f0 > s->bps * 4) > - s->f0 = s->bps * 4; > - } else > - s->f0 = 1200; > - if (params[2]) { > + if (params[2]) > s->f1 = strtoul(params[2], NULL, 0); > - if (s->f1 > s->bps * 4) > - s->f1 = s->bps * 4; > - } else > - s->f1 = 2200; > s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > - *samplerate = 8 * s->bps; > + > + /* > + * Calculate the bandwidth of the baseband (audio) signal: > + * basically this is the highest frequency of the two > + * possible tones. > + */ > + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > + > + /* > + * Calculate the expanded bandwidth (with guard-bands) > + * to get a better estimate. > + */ > + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > + > + /* Nyquist criteria (minimum sampling rate) */ > + min_samplerate = 2 * expanded_bandwidth; > + > + /* Calculate the (audio) carrier frequency */ > + f_carrier = (s->f0 + s->f1)/2; > + > + /* Calculate intermediate operating point sampling rate */ > + optimized_samplerate = 4 * f_carrier; > + if (optimized_samplerate > min_samplerate) > + min_samplerate = optimized_samplerate; > + > + /* > + * Make sure that the minimum recommended sampling > + * rate for the soundcard is exceeded. > + */ > + if (min_samplerate < MINIMUM_SAMPLERATE) > + min_samplerate = MINIMUM_SAMPLERATE; > + > + *samplerate = min_samplerate; > return s; > } > > @@ -202,7 +278,9 @@ static const struct modemparams demodpar > static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > { > struct demodstate *s; > - unsigned int f; > + unsigned int bandwidth, expanded_bandwidth; > + unsigned int min_samplerate, optimized_samplerate; > + unsigned int f_carrier; > > if (!(s = malloc(sizeof(struct demodstate)))) > logprintf(MLOG_FATAL, "out of memory\n"); see above > @@ -213,27 +291,45 @@ static void *demodconfig(struct modemcha > s->bps = 100; > if (s->bps > 9600) > s->bps= 9600; > - } else > - s->bps = 1200; > - if (params[1]) { > + } > + if (params[1]) > s->f0 = strtoul(params[1], NULL, 0); > - if (s->f0 > s->bps * 4) > - s->f0 = s->bps * 4; > - } else > - s->f0 = 1200; > - if (params[2]) { > + if (params[2]) > s->f1 = strtoul(params[2], NULL, 0); > - if (s->f1 > s->bps * 4) > - s->f1 = s->bps * 4; > - } else > - s->f1 = 2200; > s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > - f = s->f0; > - if (s->f1 > f) > - f = s->f1; > - f += s->bps/2; > - f = (2*f) + (f >> 1); > - *samplerate = f; > + > + /* > + * Calculate the bandwidth of the baseband (audio) signal: > + * basically this is the highest frequency of the two > + * possible tones. > + */ > + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > + > + /* > + * Calculate the expanded bandwidth (with guard-bands) > + * to get a better estimate. > + */ > + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > + > + /* Nyquist criteria (minimum sampling rate) */ > + min_samplerate = 2 * expanded_bandwidth; > + > + /* Calculate the (audio) carrier frequency */ > + f_carrier = (s->f0 + s->f1)/2; > + > + /* Calculate intermediate operating point sampling rate */ > + optimized_samplerate = 4 * f_carrier; > + if (optimized_samplerate > min_samplerate) > + min_samplerate = optimized_samplerate; > + > + /* > + * Make sure that the minimum recommended sampling > + * rate for the soundcard is exceeded. > + */ > + if (min_samplerate < MINIMUM_SAMPLERATE) > + min_samplerate = MINIMUM_SAMPLERATE; > + > + *samplerate = min_samplerate; > return s; > } > > @@ -364,11 +460,41 @@ static inline double sinc(double x) > return sin(arg) / arg; > } > > -static inline double hamming(double x) > +/* > + * The Hamming window is the original one (used > + * exclusively up to version 0.16). > + * Later versions introduced other optional > + * windows, so that they can be changed before > + * compilation and tested in order to try > + * achieving reduced passband ripples at the > + * expense of slower passband to stopband > + * roll-off. > + */ > +static inline double no_window(double x) > +{ > + return 1; > +} > + > +static inline double hamming_window(double x) > { > return 0.54-0.46*cos((2*M_PI)*x); > } > > +static inline double hanning_window(double x) > +{ > + return 0.5-0.5*cos((2*M_PI)*x); > +} > + > +static inline double blackman_window(double x) > +{ > + return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x); > +} > + > +static inline double welch_window(double x) > +{ > + return 1.0-pow((2*x-1),2); > +} > + > static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate) > { > struct demodstate *s = (struct demodstate *)state; > @@ -388,7 +514,23 @@ static void demodinit(void *state, unsig > if (w > 1) > w = 0; > else > - w = hamming(w); > +#ifdef FIR_WINDOW > +#if (FIR_WINDOW == NONE) > + w = no_window(w); > +#elif (FIR_WINDOW == HAMMING) > + w = hamming_window(w); > +#elif (FIR_WINDOW == HANNING) > + w = hanning_window(w); > +#elif (FIR_WINDOW == BLACKMAN) > + w = blackman_window(w); > +#elif (FIR_WINDOW == WELCH) > + w = welch_window(w); > +#else > +#error "Unknown FIR Window selected !" > +#endif > +#else // default to Hamming window > + w = hamming_window(w); > +#endif you could do that at start an reduce the forest here like: #ifdef FIR_WINDOW #if (FIR_WINDOW == NONE) # define WINDOW_FKT(x) no_window(w) #elif (FIR_WINDOW == HAMMING) and later: w=WINDOW_FKT(w); in the next step you can add a jump table add make this selectable parameter > f0r[i] = w * cos(ph0 * i); > f0i[i] = w * sin(ph0 * i); there is a sincos() function, maybe usefull here ? > f1r[i] = w * cos(ph1 * i); > hope that helps, just my 2 cents re, wh > -- > To unsubscribe from this list: send the line "unsubscribe linux-hams" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) 2012-03-03 9:50 ` walter harms @ 2012-03-03 14:47 ` Guido Trentalancia 2012-03-04 14:33 ` walter harms 2012-03-03 18:48 ` soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) Guido Trentalancia 1 sibling, 1 reply; 9+ messages in thread From: Guido Trentalancia @ 2012-03-03 14:47 UTC (permalink / raw) To: linux-hams; +Cc: t.sailer, wharms Hello Walter ! Thanks for your comments. On Sat, 2012-03-03 at 10:50 +0100, walter harms wrote: > > Am 03.03.2012 01:54, schrieb Guido Trentalancia: > > Hello ! [cut] > > As already explained this patch is for testing mainly, so please do not > > apply it directly to new releases. Although the fixes described above for > > the AFSK modulator have also been applied to the AFSK demodulator, the > > latter needs further modifications and the whole patch needs to be tested, > > reviewed and eventually improved so that it is stable on most setups. > > I suppose the RX filters, or at least their parameters, should be > > double-checked and eventually optimized for 300 baud demodulation (at the > > moment I am doing some testing with increased values for RXFILTLEN and/or > > RXFILTOVERBITS but so far I am still missing the optimal results that I > > would like to achieve). > > > > In the meanwhile, I would be grateful if somebody could test this on > > other setups and then report. > > > > Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com> > > --- > > afsk/modem.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++---------- > > 1 file changed, 176 insertions(+), 34 deletions(-) > > > > --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 > > +++ soundmodem-0.16/afsk/modem.c 2012-03-03 01:08:17.728744850 +0100 > > @@ -32,8 +32,58 @@ > > #include "modem.h" > > #include "costab.h" > > > > +/* > > + * IZ6RDB 29/02/2012: always use a minimum samplerate > > + * otherwise some sound cards, might not work well > > + * especially at bitrates lower than 1200 baud (such > > + * as 300 baud for HF). > > + * > > + * The value is defined in Hz and it should never be > > + * less than 9600 Hz to avoid problems, although the > > + * recommended value is 11025 Hz for most soundcards. > > + * > > + * Some cards, might even require that only their > > + * maximum allowed sampling rate of 48kHz is used > > + * (for example, according to online reports some > > + * embedded SiS 701x AC'97 controllers). > > + */ > > +#define MINIMUM_SAMPLERATE 11025 > > + > > +/* > > + * IZ6RDB 01/03/2012: define different possible > > + * window types for the FIR filters and choose > > + * one of the available types: > > + * > > + * - NONE > > + * - HAMMING (window used up to version 0.16) > > + * - HANNING > > + * - BLACKMAN > > + * - WELCH > > + */ > > +#define FIR_WINDOW HAMMING > > + > > +/* > > + * IZ6RDB 01/03/2012: introduce a parameter > > + * called "bandwidth expansion factor", which > > + * is a real positive number slightly greater > > + * than unity (up to 2.0) that accounts for > > + * guard-bands and non-ideal filtering. > > + * > > + * This value is only used for estimating the > > + * required sampling rate. > > + * > > + * Values are usually between 1.125 and 1.4. > > + * > > + * The recommended value is 1.36. > > + */ > > +#define BANDWIDTH_EXPANSION_FACTOR 1.36 > > + > > /* --------------------------------------------------------------------- */ > > > > +#ifndef BANDWIDTH_EXPANSION_FACTOR > > +#define BANDWIDTH_EXPANSION_FACTOR 1.36 > > +#endif > > + > > I do not see the distance between the #define BANDWIDTH_EXPANSION_FACTOR and the #ifndef BANDWIDTH_EXPANSION_FACTOR > but i would suggest to remove the first one or the check. You are setting it to default values either way > that is confusing. Yes, you are right. If that sort of method is kept in a final patch, it's better to remove that useless check since the constant value is already defined and hopefully well commented within the same source file. I might well improve that method later on, but at a first sight, for the range 300-2400 baud which is most meaningful for AFSK operation and considering that the lower threshold should probably prevail, at least from 300 baud to 1200 baud, it seems to produce consistent values overall. I have only managed to quickly check that on another soundcard, 1200 baud operation is still working fine after patching. But, it would be nice to check 2400 baud too... > > struct modstate { > > struct modemchannel *chan; > > unsigned int bps, f0, f1, notdiff, maxbitlen; > > @@ -53,6 +103,9 @@ static const struct modemparams modparam > > static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > > { > > struct modstate *s; > > + unsigned int bandwidth, expanded_bandwidth; > > + unsigned int min_samplerate, optimized_samplerate; > > + unsigned int f_carrier; > > > > if (!(s = malloc(sizeof(struct modstate)))) > > logprintf(MLOG_FATAL, "out of memory\n"); > > It is a good habbit to do this in two lines: That's the original code. It's not related to the problem with 300 baud operation and it's just a stylistic, so I would say we'd better leave as it is to avoid complicating things for the time being. > s = malloc(sizeof(struct modstate)); > if (!s) > > > @@ -63,22 +116,45 @@ static void *modconfig(struct modemchann > > s->bps = 100; > > if (s->bps > 9600) > > s->bps= 9600; > > - } else > > - s->bps = 1200; > > - if (params[1]) { > > + } > > + if (params[1]) > > s->f0 = strtoul(params[1], NULL, 0); > > - if (s->f0 > s->bps * 4) > > - s->f0 = s->bps * 4; > > - } else > > - s->f0 = 1200; > > - if (params[2]) { > > + if (params[2]) > > s->f1 = strtoul(params[2], NULL, 0); > > - if (s->f1 > s->bps * 4) > > - s->f1 = s->bps * 4; > > - } else > > - s->f1 = 2200; > > s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > > - *samplerate = 8 * s->bps; > > + > > + /* > > + * Calculate the bandwidth of the baseband (audio) signal: > > + * basically this is the highest frequency of the two > > + * possible tones. > > + */ > > + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > > + > > + /* > > + * Calculate the expanded bandwidth (with guard-bands) > > + * to get a better estimate. > > + */ > > + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > > + > > + /* Nyquist criteria (minimum sampling rate) */ > > + min_samplerate = 2 * expanded_bandwidth; > > + > > + /* Calculate the (audio) carrier frequency */ > > + f_carrier = (s->f0 + s->f1)/2; > > + > > + /* Calculate intermediate operating point sampling rate */ > > + optimized_samplerate = 4 * f_carrier; > > + if (optimized_samplerate > min_samplerate) > > + min_samplerate = optimized_samplerate; > > + > > + /* > > + * Make sure that the minimum recommended sampling > > + * rate for the soundcard is exceeded. > > + */ > > + if (min_samplerate < MINIMUM_SAMPLERATE) > > + min_samplerate = MINIMUM_SAMPLERATE; > > + > > + *samplerate = min_samplerate; > > return s; > > } > > > > @@ -202,7 +278,9 @@ static const struct modemparams demodpar > > static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > > { > > struct demodstate *s; > > - unsigned int f; > > + unsigned int bandwidth, expanded_bandwidth; > > + unsigned int min_samplerate, optimized_samplerate; > > + unsigned int f_carrier; > > > > if (!(s = malloc(sizeof(struct demodstate)))) > > logprintf(MLOG_FATAL, "out of memory\n"); > > > see above > > > > @@ -213,27 +291,45 @@ static void *demodconfig(struct modemcha > > s->bps = 100; > > if (s->bps > 9600) > > s->bps= 9600; > > - } else > > - s->bps = 1200; > > - if (params[1]) { > > + } > > + if (params[1]) > > s->f0 = strtoul(params[1], NULL, 0); > > - if (s->f0 > s->bps * 4) > > - s->f0 = s->bps * 4; > > - } else > > - s->f0 = 1200; > > - if (params[2]) { > > + if (params[2]) > > s->f1 = strtoul(params[2], NULL, 0); > > - if (s->f1 > s->bps * 4) > > - s->f1 = s->bps * 4; > > - } else > > - s->f1 = 2200; > > s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > > - f = s->f0; > > - if (s->f1 > f) > > - f = s->f1; > > - f += s->bps/2; > > - f = (2*f) + (f >> 1); > > - *samplerate = f; > > + > > + /* > > + * Calculate the bandwidth of the baseband (audio) signal: > > + * basically this is the highest frequency of the two > > + * possible tones. > > + */ > > + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > > + > > + /* > > + * Calculate the expanded bandwidth (with guard-bands) > > + * to get a better estimate. > > + */ > > + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > > + > > + /* Nyquist criteria (minimum sampling rate) */ > > + min_samplerate = 2 * expanded_bandwidth; > > + > > + /* Calculate the (audio) carrier frequency */ > > + f_carrier = (s->f0 + s->f1)/2; > > + > > + /* Calculate intermediate operating point sampling rate */ > > + optimized_samplerate = 4 * f_carrier; > > + if (optimized_samplerate > min_samplerate) > > + min_samplerate = optimized_samplerate; > > + > > + /* > > + * Make sure that the minimum recommended sampling > > + * rate for the soundcard is exceeded. > > + */ > > + if (min_samplerate < MINIMUM_SAMPLERATE) > > + min_samplerate = MINIMUM_SAMPLERATE; > > + > > + *samplerate = min_samplerate; > > return s; > > } > > > > @@ -364,11 +460,41 @@ static inline double sinc(double x) > > return sin(arg) / arg; > > } > > > > -static inline double hamming(double x) > > +/* > > + * The Hamming window is the original one (used > > + * exclusively up to version 0.16). > > + * Later versions introduced other optional > > + * windows, so that they can be changed before > > + * compilation and tested in order to try > > + * achieving reduced passband ripples at the > > + * expense of slower passband to stopband > > + * roll-off. > > + */ > > +static inline double no_window(double x) > > +{ > > + return 1; > > +} > > + > > +static inline double hamming_window(double x) > > { > > return 0.54-0.46*cos((2*M_PI)*x); > > } > > > > +static inline double hanning_window(double x) > > +{ > > + return 0.5-0.5*cos((2*M_PI)*x); > > +} > > + > > +static inline double blackman_window(double x) > > +{ > > + return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x); > > +} > > + > > +static inline double welch_window(double x) > > +{ > > + return 1.0-pow((2*x-1),2); > > +} > > + > > static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate) > > { > > struct demodstate *s = (struct demodstate *)state; > > @@ -388,7 +514,23 @@ static void demodinit(void *state, unsig > > if (w > 1) > > w = 0; > > else > > - w = hamming(w); > > +#ifdef FIR_WINDOW > > +#if (FIR_WINDOW == NONE) > > + w = no_window(w); > > +#elif (FIR_WINDOW == HAMMING) > > + w = hamming_window(w); > > +#elif (FIR_WINDOW == HANNING) > > + w = hanning_window(w); > > +#elif (FIR_WINDOW == BLACKMAN) > > + w = blackman_window(w); > > +#elif (FIR_WINDOW == WELCH) > > + w = welch_window(w); > > +#else > > +#error "Unknown FIR Window selected !" > > +#endif > > +#else // default to Hamming window > > + w = hamming_window(w); > > +#endif > > you could do that at start an reduce the forest here like: > > #ifdef FIR_WINDOW > #if (FIR_WINDOW == NONE) > # define WINDOW_FKT(x) no_window(w) > #elif (FIR_WINDOW == HAMMING) > > and later: > w=WINDOW_FKT(w); Since it's very provisional and temporary, I just wrote down the shortest to type... The window selection is not strictly required to sort out the problem with 300 baud operation, so it shouldn't be there in the first place but I was coincidentally experimenting with it and I did sort of forgot to remove it from the posted patch... > in the next step you can add a jump table add make this selectable parameter If you mean selectable at run-time from the graphical config app or from the configuration file, I suppose it's well beyond the scope of my patch. Also, I'd first prefer to invest further (lacking) time to investigate on the poor performance of the demodulator at 300 baud. If the original author believes that window selection can be a desired feature, he might improve that at any later time... > > f0r[i] = w * cos(ph0 * i); > > f0i[i] = w * sin(ph0 * i); > > there is a sincos() function, maybe usefull here ? If you mean the costab table, I did not even look at that, as it is probably meant to just speed-up calculations and it does not change the behaviour I suppose... > > f1r[i] = w * cos(ph1 * i); > > > > hope that helps, just my 2 cents Yes, sure, every little helps. But did raising the sampling rate above a threshold and removing that couple of buggy conditions on the tones and bitrate sort out the issue for you ? In my case, I have at least a working modulator now and I can eventually start checking a bit more carefully the demodulator which suffers poor performance (although I must admit I started doing 300 baud operations just a few days ago, I have no test equipment at all and my antenna is really crap due to lack of space). I believe the code was not originally meant to work at bitrates lower than 1200 baud, that's why, despite it was accepting values lower than 1200, it was not handling them properly. It was perhaps derived from an earlier piece of software called "multimon" by the same author ?? He might eventually shed some light on this, I don't know the whole story... > re, > wh > And by the way, are you also experiencing poor performance with demodulation at 300 baud ? If yes, have you had any closer look at the relative code ? It should be doing some sort of FIR filtering, but I need to look at it more carefully. Another piece of software that I found on the net was instead employing IIR filtering and doing a very good demodulation job at that rate, although it was not as feature-rich and it was limited to very low bitrates. Thanks. Guido ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) 2012-03-03 14:47 ` Guido Trentalancia @ 2012-03-04 14:33 ` walter harms 2012-03-04 20:16 ` Guido Trentalancia 0 siblings, 1 reply; 9+ messages in thread From: walter harms @ 2012-03-04 14:33 UTC (permalink / raw) To: Guido Trentalancia; +Cc: linux-hams, t.sailer Am 03.03.2012 15:47, schrieb Guido Trentalancia: > Hello Walter ! > > Thanks for your comments. > > On Sat, 2012-03-03 at 10:50 +0100, walter harms wrote: >> >> Am 03.03.2012 01:54, schrieb Guido Trentalancia: >>> Hello ! > > [cut] > >>> As already explained this patch is for testing mainly, so please do not >>> apply it directly to new releases. Although the fixes described above for >>> the AFSK modulator have also been applied to the AFSK demodulator, the >>> latter needs further modifications and the whole patch needs to be tested, >>> reviewed and eventually improved so that it is stable on most setups. >>> I suppose the RX filters, or at least their parameters, should be >>> double-checked and eventually optimized for 300 baud demodulation (at the >>> moment I am doing some testing with increased values for RXFILTLEN and/or >>> RXFILTOVERBITS but so far I am still missing the optimal results that I >>> would like to achieve). >>> >>> In the meanwhile, I would be grateful if somebody could test this on >>> other setups and then report. >>> >>> Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com> >>> --- >>> afsk/modem.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++---------- >>> 1 file changed, 176 insertions(+), 34 deletions(-) >>> >>> --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 >>> +++ soundmodem-0.16/afsk/modem.c 2012-03-03 01:08:17.728744850 +0100 >>> @@ -32,8 +32,58 @@ >>> #include "modem.h" >>> #include "costab.h" >>> >>> +/* >>> + * IZ6RDB 29/02/2012: always use a minimum samplerate >>> + * otherwise some sound cards, might not work well >>> + * especially at bitrates lower than 1200 baud (such >>> + * as 300 baud for HF). >>> + * >>> + * The value is defined in Hz and it should never be >>> + * less than 9600 Hz to avoid problems, although the >>> + * recommended value is 11025 Hz for most soundcards. >>> + * >>> + * Some cards, might even require that only their >>> + * maximum allowed sampling rate of 48kHz is used >>> + * (for example, according to online reports some >>> + * embedded SiS 701x AC'97 controllers). >>> + */ >>> +#define MINIMUM_SAMPLERATE 11025 >>> + >>> +/* >>> + * IZ6RDB 01/03/2012: define different possible >>> + * window types for the FIR filters and choose >>> + * one of the available types: >>> + * >>> + * - NONE >>> + * - HAMMING (window used up to version 0.16) >>> + * - HANNING >>> + * - BLACKMAN >>> + * - WELCH >>> + */ >>> +#define FIR_WINDOW HAMMING >>> + >>> +/* >>> + * IZ6RDB 01/03/2012: introduce a parameter >>> + * called "bandwidth expansion factor", which >>> + * is a real positive number slightly greater >>> + * than unity (up to 2.0) that accounts for >>> + * guard-bands and non-ideal filtering. >>> + * >>> + * This value is only used for estimating the >>> + * required sampling rate. >>> + * >>> + * Values are usually between 1.125 and 1.4. >>> + * >>> + * The recommended value is 1.36. >>> + */ >>> +#define BANDWIDTH_EXPANSION_FACTOR 1.36 >>> + >>> /* --------------------------------------------------------------------- */ >>> >>> +#ifndef BANDWIDTH_EXPANSION_FACTOR >>> +#define BANDWIDTH_EXPANSION_FACTOR 1.36 >>> +#endif >>> + >> >> I do not see the distance between the #define BANDWIDTH_EXPANSION_FACTOR and the #ifndef BANDWIDTH_EXPANSION_FACTOR >> but i would suggest to remove the first one or the check. You are setting it to default values either way >> that is confusing. > > Yes, you are right. If that sort of method is kept in a final patch, > it's better to remove that useless check since the constant value is > already defined and hopefully well commented within the same source > file. > > I might well improve that method later on, but at a first sight, for the > range 300-2400 baud which is most meaningful for AFSK operation and > considering that the lower threshold should probably prevail, at least > from 300 baud to 1200 baud, it seems to produce consistent values > overall. I have only managed to quickly check that on another soundcard, > 1200 baud operation is still working fine after patching. But, it would > be nice to check 2400 baud too... > >>> struct modstate { >>> struct modemchannel *chan; >>> unsigned int bps, f0, f1, notdiff, maxbitlen; >>> @@ -53,6 +103,9 @@ static const struct modemparams modparam >>> static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) >>> { >>> struct modstate *s; >>> + unsigned int bandwidth, expanded_bandwidth; >>> + unsigned int min_samplerate, optimized_samplerate; >>> + unsigned int f_carrier; >>> >>> if (!(s = malloc(sizeof(struct modstate)))) >>> logprintf(MLOG_FATAL, "out of memory\n"); >> >> It is a good habbit to do this in two lines: > > That's the original code. It's not related to the problem with 300 baud > operation and it's just a stylistic, so I would say we'd better leave as > it is to avoid complicating things for the time being. I just want to mention it, when you are ready with the current patch you may like to fix thinks like this. > >> s = malloc(sizeof(struct modstate)); >> if (!s) >> >>> @@ -63,22 +116,45 @@ static void *modconfig(struct modemchann >>> s->bps = 100; >>> if (s->bps > 9600) >>> s->bps= 9600; >>> - } else >>> - s->bps = 1200; >>> - if (params[1]) { >>> + } >>> + if (params[1]) >>> s->f0 = strtoul(params[1], NULL, 0); >>> - if (s->f0 > s->bps * 4) >>> - s->f0 = s->bps * 4; >>> - } else >>> - s->f0 = 1200; >>> - if (params[2]) { >>> + if (params[2]) >>> s->f1 = strtoul(params[2], NULL, 0); >>> - if (s->f1 > s->bps * 4) >>> - s->f1 = s->bps * 4; >>> - } else >>> - s->f1 = 2200; >>> s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; >>> - *samplerate = 8 * s->bps; >>> + >>> + /* >>> + * Calculate the bandwidth of the baseband (audio) signal: >>> + * basically this is the highest frequency of the two >>> + * possible tones. >>> + */ >>> + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; >>> + >>> + /* >>> + * Calculate the expanded bandwidth (with guard-bands) >>> + * to get a better estimate. >>> + */ >>> + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; >>> + >>> + /* Nyquist criteria (minimum sampling rate) */ >>> + min_samplerate = 2 * expanded_bandwidth; >>> + >>> + /* Calculate the (audio) carrier frequency */ >>> + f_carrier = (s->f0 + s->f1)/2; >>> + >>> + /* Calculate intermediate operating point sampling rate */ >>> + optimized_samplerate = 4 * f_carrier; >>> + if (optimized_samplerate > min_samplerate) >>> + min_samplerate = optimized_samplerate; >>> + >>> + /* >>> + * Make sure that the minimum recommended sampling >>> + * rate for the soundcard is exceeded. >>> + */ >>> + if (min_samplerate < MINIMUM_SAMPLERATE) >>> + min_samplerate = MINIMUM_SAMPLERATE; >>> + >>> + *samplerate = min_samplerate; >>> return s; >>> } >>> >>> @@ -202,7 +278,9 @@ static const struct modemparams demodpar >>> static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) >>> { >>> struct demodstate *s; >>> - unsigned int f; >>> + unsigned int bandwidth, expanded_bandwidth; >>> + unsigned int min_samplerate, optimized_samplerate; >>> + unsigned int f_carrier; >>> >>> if (!(s = malloc(sizeof(struct demodstate)))) >>> logprintf(MLOG_FATAL, "out of memory\n"); >> >> >> see above >> >> >>> @@ -213,27 +291,45 @@ static void *demodconfig(struct modemcha >>> s->bps = 100; >>> if (s->bps > 9600) >>> s->bps= 9600; >>> - } else >>> - s->bps = 1200; >>> - if (params[1]) { >>> + } >>> + if (params[1]) >>> s->f0 = strtoul(params[1], NULL, 0); >>> - if (s->f0 > s->bps * 4) >>> - s->f0 = s->bps * 4; >>> - } else >>> - s->f0 = 1200; >>> - if (params[2]) { >>> + if (params[2]) >>> s->f1 = strtoul(params[2], NULL, 0); >>> - if (s->f1 > s->bps * 4) >>> - s->f1 = s->bps * 4; >>> - } else >>> - s->f1 = 2200; >>> s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; >>> - f = s->f0; >>> - if (s->f1 > f) >>> - f = s->f1; >>> - f += s->bps/2; >>> - f = (2*f) + (f >> 1); >>> - *samplerate = f; >>> + >>> + /* >>> + * Calculate the bandwidth of the baseband (audio) signal: >>> + * basically this is the highest frequency of the two >>> + * possible tones. >>> + */ >>> + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; >>> + >>> + /* >>> + * Calculate the expanded bandwidth (with guard-bands) >>> + * to get a better estimate. >>> + */ >>> + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; >>> + >>> + /* Nyquist criteria (minimum sampling rate) */ >>> + min_samplerate = 2 * expanded_bandwidth; >>> + >>> + /* Calculate the (audio) carrier frequency */ >>> + f_carrier = (s->f0 + s->f1)/2; >>> + >>> + /* Calculate intermediate operating point sampling rate */ >>> + optimized_samplerate = 4 * f_carrier; >>> + if (optimized_samplerate > min_samplerate) >>> + min_samplerate = optimized_samplerate; >>> + >>> + /* >>> + * Make sure that the minimum recommended sampling >>> + * rate for the soundcard is exceeded. >>> + */ >>> + if (min_samplerate < MINIMUM_SAMPLERATE) >>> + min_samplerate = MINIMUM_SAMPLERATE; >>> + >>> + *samplerate = min_samplerate; >>> return s; >>> } >>> >>> @@ -364,11 +460,41 @@ static inline double sinc(double x) >>> return sin(arg) / arg; >>> } >>> >>> -static inline double hamming(double x) >>> +/* >>> + * The Hamming window is the original one (used >>> + * exclusively up to version 0.16). >>> + * Later versions introduced other optional >>> + * windows, so that they can be changed before >>> + * compilation and tested in order to try >>> + * achieving reduced passband ripples at the >>> + * expense of slower passband to stopband >>> + * roll-off. >>> + */ >>> +static inline double no_window(double x) >>> +{ >>> + return 1; >>> +} >>> + >>> +static inline double hamming_window(double x) >>> { >>> return 0.54-0.46*cos((2*M_PI)*x); >>> } >>> >>> +static inline double hanning_window(double x) >>> +{ >>> + return 0.5-0.5*cos((2*M_PI)*x); >>> +} >>> + >>> +static inline double blackman_window(double x) >>> +{ >>> + return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x); >>> +} >>> + >>> +static inline double welch_window(double x) >>> +{ >>> + return 1.0-pow((2*x-1),2); >>> +} >>> + >>> static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate) >>> { >>> struct demodstate *s = (struct demodstate *)state; >>> @@ -388,7 +514,23 @@ static void demodinit(void *state, unsig >>> if (w > 1) >>> w = 0; >>> else >>> - w = hamming(w); >>> +#ifdef FIR_WINDOW >>> +#if (FIR_WINDOW == NONE) >>> + w = no_window(w); >>> +#elif (FIR_WINDOW == HAMMING) >>> + w = hamming_window(w); >>> +#elif (FIR_WINDOW == HANNING) >>> + w = hanning_window(w); >>> +#elif (FIR_WINDOW == BLACKMAN) >>> + w = blackman_window(w); >>> +#elif (FIR_WINDOW == WELCH) >>> + w = welch_window(w); >>> +#else >>> +#error "Unknown FIR Window selected !" >>> +#endif >>> +#else // default to Hamming window >>> + w = hamming_window(w); >>> +#endif >> >> you could do that at start an reduce the forest here like: >> >> #ifdef FIR_WINDOW >> #if (FIR_WINDOW == NONE) >> # define WINDOW_FKT(x) no_window(w) >> #elif (FIR_WINDOW == HAMMING) >> >> and later: >> w=WINDOW_FKT(w); > > Since it's very provisional and temporary, I just wrote down the > shortest to type... The window selection is not strictly required to > sort out the problem with 300 baud operation, so it shouldn't be there > in the first place but I was coincidentally experimenting with it and I > did sort of forgot to remove it from the posted patch... > if it not nessassery please remove it, my impression was that you would like to try some different windowing technics. >> in the next step you can add a jump table add make this selectable parameter > > If you mean selectable at run-time from the graphical config app or from > the configuration file, I suppose it's well beyond the scope of my > patch. Also, I'd first prefer to invest further (lacking) time to > investigate on the poor performance of the demodulator at 300 baud. If > the original author believes that window selection can be a desired > feature, he might improve that at any later time... no proplem with me i had the wrong impression ntl it may be an interessing feature but in this case clearly next round. > >>> f0r[i] = w * cos(ph0 * i); >>> f0i[i] = w * sin(ph0 * i); >> >> there is a sincos() function, maybe usefull here ? > > If you mean the costab table, I did not even look at that, as it is > probably meant to just speed-up calculations and it does not change the > behaviour I suppose... > i noticed it by chance sincos() is a function returning sin+cos in one call. my idea here was simply to point this out, you can take it or leave it like you wish. >>> f1r[i] = w * cos(ph1 * i); >>> >> >> hope that helps, just my 2 cents > > Yes, sure, every little helps. But did raising the sampling rate above a > threshold and removing that couple of buggy conditions on the tones and > bitrate sort out the issue for you ? > i am sorry i did a pure "look at the code" i do not have the required hardware. re, wh > In my case, I have at least a working modulator now and I can eventually > start checking a bit more carefully the demodulator which suffers poor > performance (although I must admit I started doing 300 baud operations > just a few days ago, I have no test equipment at all and my antenna is > really crap due to lack of space). > > I believe the code was not originally meant to work at bitrates lower > than 1200 baud, that's why, despite it was accepting values lower than > 1200, it was not handling them properly. It was perhaps derived from an > earlier piece of software called "multimon" by the same author ?? He > might eventually shed some light on this, I don't know the whole > story... > >> re, >> wh >> > > And by the way, are you also experiencing poor performance with > demodulation at 300 baud ? If yes, have you had any closer look at the > relative code ? It should be doing some sort of FIR filtering, but I > need to look at it more carefully. Another piece of software that I > found on the net was instead employing IIR filtering and doing a very > good demodulation job at that rate, although it was not as feature-rich > and it was limited to very low bitrates. > > Thanks. > > Guido > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) 2012-03-04 14:33 ` walter harms @ 2012-03-04 20:16 ` Guido Trentalancia [not found] ` <4F776E14.7090104@trinnet.net> 0 siblings, 1 reply; 9+ messages in thread From: Guido Trentalancia @ 2012-03-04 20:16 UTC (permalink / raw) To: wharms; +Cc: linux-hams Hello Walter ! On Sun, 2012-03-04 at 15:33 +0100, walter harms wrote: > > Am 03.03.2012 15:47, schrieb Guido Trentalancia: > > Hello Walter ! > > > > Thanks for your comments. [cut] > >>> struct modstate { > >>> struct modemchannel *chan; > >>> unsigned int bps, f0, f1, notdiff, maxbitlen; > >>> @@ -53,6 +103,9 @@ static const struct modemparams modparam > >>> static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > >>> { > >>> struct modstate *s; > >>> + unsigned int bandwidth, expanded_bandwidth; > >>> + unsigned int min_samplerate, optimized_samplerate; > >>> + unsigned int f_carrier; > >>> > >>> if (!(s = malloc(sizeof(struct modstate)))) > >>> logprintf(MLOG_FATAL, "out of memory\n"); > >> > >> It is a good habbit to do this in two lines: > > > > That's the original code. It's not related to the problem with 300 baud > > operation and it's just a stylistic, so I would say we'd better leave as > > it is to avoid complicating things for the time being. > > > I just want to mention it, when you are ready with the current patch > you may like to fix thinks like this. Unfortunately at the moment I have no time available to get further involved into maintanance and style issues. My urge was to just get the AFSK modulator quick-fixed for 300 baud operation. In my setup it works nicely now, so I am satisfied with it for the time being. Ham-radio is an hobby, I can't spend too much time on it... Also, given that the AFSK modulator is doing definitely better now at 300 baud, I would rather prefer to invest time in a better installation for my antenna at this point... > >> s = malloc(sizeof(struct modstate)); > >> if (!s) > >> > >>> @@ -63,22 +116,45 @@ static void *modconfig(struct modemchann > >>> s->bps = 100; > >>> if (s->bps > 9600) > >>> s->bps= 9600; > >>> - } else > >>> - s->bps = 1200; > >>> - if (params[1]) { > >>> + } > >>> + if (params[1]) > >>> s->f0 = strtoul(params[1], NULL, 0); > >>> - if (s->f0 > s->bps * 4) > >>> - s->f0 = s->bps * 4; > >>> - } else > >>> - s->f0 = 1200; > >>> - if (params[2]) { > >>> + if (params[2]) > >>> s->f1 = strtoul(params[2], NULL, 0); > >>> - if (s->f1 > s->bps * 4) > >>> - s->f1 = s->bps * 4; > >>> - } else > >>> - s->f1 = 2200; > >>> s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > >>> - *samplerate = 8 * s->bps; > >>> + > >>> + /* > >>> + * Calculate the bandwidth of the baseband (audio) signal: > >>> + * basically this is the highest frequency of the two > >>> + * possible tones. > >>> + */ > >>> + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > >>> + > >>> + /* > >>> + * Calculate the expanded bandwidth (with guard-bands) > >>> + * to get a better estimate. > >>> + */ > >>> + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > >>> + > >>> + /* Nyquist criteria (minimum sampling rate) */ > >>> + min_samplerate = 2 * expanded_bandwidth; > >>> + > >>> + /* Calculate the (audio) carrier frequency */ > >>> + f_carrier = (s->f0 + s->f1)/2; > >>> + > >>> + /* Calculate intermediate operating point sampling rate */ > >>> + optimized_samplerate = 4 * f_carrier; > >>> + if (optimized_samplerate > min_samplerate) > >>> + min_samplerate = optimized_samplerate; > >>> + > >>> + /* > >>> + * Make sure that the minimum recommended sampling > >>> + * rate for the soundcard is exceeded. > >>> + */ > >>> + if (min_samplerate < MINIMUM_SAMPLERATE) > >>> + min_samplerate = MINIMUM_SAMPLERATE; > >>> + > >>> + *samplerate = min_samplerate; > >>> return s; > >>> } > >>> > >>> @@ -202,7 +278,9 @@ static const struct modemparams demodpar > >>> static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) > >>> { > >>> struct demodstate *s; > >>> - unsigned int f; > >>> + unsigned int bandwidth, expanded_bandwidth; > >>> + unsigned int min_samplerate, optimized_samplerate; > >>> + unsigned int f_carrier; > >>> > >>> if (!(s = malloc(sizeof(struct demodstate)))) > >>> logprintf(MLOG_FATAL, "out of memory\n"); > >> > >> > >> see above > >> > >> > >>> @@ -213,27 +291,45 @@ static void *demodconfig(struct modemcha > >>> s->bps = 100; > >>> if (s->bps > 9600) > >>> s->bps= 9600; > >>> - } else > >>> - s->bps = 1200; > >>> - if (params[1]) { > >>> + } > >>> + if (params[1]) > >>> s->f0 = strtoul(params[1], NULL, 0); > >>> - if (s->f0 > s->bps * 4) > >>> - s->f0 = s->bps * 4; > >>> - } else > >>> - s->f0 = 1200; > >>> - if (params[2]) { > >>> + if (params[2]) > >>> s->f1 = strtoul(params[2], NULL, 0); > >>> - if (s->f1 > s->bps * 4) > >>> - s->f1 = s->bps * 4; > >>> - } else > >>> - s->f1 = 2200; > >>> s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; > >>> - f = s->f0; > >>> - if (s->f1 > f) > >>> - f = s->f1; > >>> - f += s->bps/2; > >>> - f = (2*f) + (f >> 1); > >>> - *samplerate = f; > >>> + > >>> + /* > >>> + * Calculate the bandwidth of the baseband (audio) signal: > >>> + * basically this is the highest frequency of the two > >>> + * possible tones. > >>> + */ > >>> + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; > >>> + > >>> + /* > >>> + * Calculate the expanded bandwidth (with guard-bands) > >>> + * to get a better estimate. > >>> + */ > >>> + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; > >>> + > >>> + /* Nyquist criteria (minimum sampling rate) */ > >>> + min_samplerate = 2 * expanded_bandwidth; > >>> + > >>> + /* Calculate the (audio) carrier frequency */ > >>> + f_carrier = (s->f0 + s->f1)/2; > >>> + > >>> + /* Calculate intermediate operating point sampling rate */ > >>> + optimized_samplerate = 4 * f_carrier; > >>> + if (optimized_samplerate > min_samplerate) > >>> + min_samplerate = optimized_samplerate; > >>> + > >>> + /* > >>> + * Make sure that the minimum recommended sampling > >>> + * rate for the soundcard is exceeded. > >>> + */ > >>> + if (min_samplerate < MINIMUM_SAMPLERATE) > >>> + min_samplerate = MINIMUM_SAMPLERATE; > >>> + > >>> + *samplerate = min_samplerate; > >>> return s; > >>> } > >>> > >>> @@ -364,11 +460,41 @@ static inline double sinc(double x) > >>> return sin(arg) / arg; > >>> } > >>> > >>> -static inline double hamming(double x) > >>> +/* > >>> + * The Hamming window is the original one (used > >>> + * exclusively up to version 0.16). > >>> + * Later versions introduced other optional > >>> + * windows, so that they can be changed before > >>> + * compilation and tested in order to try > >>> + * achieving reduced passband ripples at the > >>> + * expense of slower passband to stopband > >>> + * roll-off. > >>> + */ > >>> +static inline double no_window(double x) > >>> +{ > >>> + return 1; > >>> +} > >>> + > >>> +static inline double hamming_window(double x) > >>> { > >>> return 0.54-0.46*cos((2*M_PI)*x); > >>> } > >>> > >>> +static inline double hanning_window(double x) > >>> +{ > >>> + return 0.5-0.5*cos((2*M_PI)*x); > >>> +} > >>> + > >>> +static inline double blackman_window(double x) > >>> +{ > >>> + return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x); > >>> +} > >>> + > >>> +static inline double welch_window(double x) > >>> +{ > >>> + return 1.0-pow((2*x-1),2); > >>> +} > >>> + > >>> static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate) > >>> { > >>> struct demodstate *s = (struct demodstate *)state; > >>> @@ -388,7 +514,23 @@ static void demodinit(void *state, unsig > >>> if (w > 1) > >>> w = 0; > >>> else > >>> - w = hamming(w); > >>> +#ifdef FIR_WINDOW > >>> +#if (FIR_WINDOW == NONE) > >>> + w = no_window(w); > >>> +#elif (FIR_WINDOW == HAMMING) > >>> + w = hamming_window(w); > >>> +#elif (FIR_WINDOW == HANNING) > >>> + w = hanning_window(w); > >>> +#elif (FIR_WINDOW == BLACKMAN) > >>> + w = blackman_window(w); > >>> +#elif (FIR_WINDOW == WELCH) > >>> + w = welch_window(w); > >>> +#else > >>> +#error "Unknown FIR Window selected !" > >>> +#endif > >>> +#else // default to Hamming window > >>> + w = hamming_window(w); > >>> +#endif > >> > >> you could do that at start an reduce the forest here like: > >> > >> #ifdef FIR_WINDOW > >> #if (FIR_WINDOW == NONE) > >> # define WINDOW_FKT(x) no_window(w) > >> #elif (FIR_WINDOW == HAMMING) > >> > >> and later: > >> w=WINDOW_FKT(w); > > > > Since it's very provisional and temporary, I just wrote down the > > shortest to type... The window selection is not strictly required to > > sort out the problem with 300 baud operation, so it shouldn't be there > > in the first place but I was coincidentally experimenting with it and I > > did sort of forgot to remove it from the posted patch... > > > > if it not nessassery please remove it, my impression was that you would > like to try some different windowing technics. Yes, the possibility to try different windows is not bad. However, the main problem was the sampling rate and some wrong logic there... > >> in the next step you can add a jump table add make this selectable parameter > > > > If you mean selectable at run-time from the graphical config app or from > > the configuration file, I suppose it's well beyond the scope of my > > patch. Also, I'd first prefer to invest further (lacking) time to > > investigate on the poor performance of the demodulator at 300 baud. If > > the original author believes that window selection can be a desired > > feature, he might improve that at any later time... > > no proplem with me i had the wrong impression ntl it may be an interessing > feature but in this case clearly next round. Unfortunately, I do not have enough time at this precise moment to bring that selection out in the GUI of the configuration application. One thing that is probably worth mentioning is that the is an hard-coded value of 5000Hz sampling rate somewhere else in the main source files (under soundcard directory as far as I remember). I believe this is no longer going to be used by AFSK (at least after patching), but it might be picked up by other modulation schemes, so if somebody is also experiencing problems with other modulations, then that is probably a good candidate for places to look at. > > > >>> f0r[i] = w * cos(ph0 * i); > >>> f0i[i] = w * sin(ph0 * i); > >> > >> there is a sincos() function, maybe usefull here ? > > > > If you mean the costab table, I did not even look at that, as it is > > probably meant to just speed-up calculations and it does not change the > > behaviour I suppose... > > > i noticed it by chance sincos() is a function returning sin+cos in one call. > my idea here was simply to point this out, you can take it or leave it like > you wish. At the moment, I would rather prefer to hear back from people about the original problem with 300 bauds and possibly get a fix into a new release if the author wishes... Also, the list is not specifically and exclusively devoted to this application, so I'd rather prefer not to monopolize it too much for just one minor problem with a feature of an application, even though it's one of the very few ones available for the purpose... > >>> f1r[i] = w * cos(ph1 * i); > >>> > >> > >> hope that helps, just my 2 cents > > > > Yes, sure, every little helps. But did raising the sampling rate above a > > threshold and removing that couple of buggy conditions on the tones and > > bitrate sort out the issue for you ? > > > > i am sorry i did a pure "look at the code" i do not have the required hardware. No problem at all and thanks again for your time, but what is missing next is people that can test on real hardware, as I am very much limited in that sense. > re, > wh Regards, Guido ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <4F776E14.7090104@trinnet.net>]
[parent not found: <1333379832.2112.15.camel@vortex>]
[parent not found: <4F7B199F.3050104@trinnet.net>]
[parent not found: <1333647291.2605.34.camel@vortex>]
[parent not found: <1333741818.4064.20.camel@vortex>]
[parent not found: <4F7F7A2C.2030500@trinnet.net>]
[parent not found: <1333809855.2433.10.camel@vortex>]
* Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation [not found] ` <1333809855.2433.10.camel@vortex> @ 2012-04-07 23:14 ` David Ranch 2012-04-08 15:23 ` Guido Trentalancia 2012-04-09 21:37 ` Curt, WE7U 0 siblings, 2 replies; 9+ messages in thread From: David Ranch @ 2012-04-07 23:14 UTC (permalink / raw) To: Guido Trentalancia, t.sailer, Linux Hams Hello Guido, Thomas, fellow Linux HAMs: I've CCed the Linuxhams group as I'm curious if any of you have any thoughts on why Soundmodem would be shutting down all USB-based keyboard and mouse functionality until the process is killed! In all my years of Linux, I've never need something like this. Very strange and any/all comments would be very much appreciated! Few points: 1) I've recently noticed a change on my system that when I run soundmodemconfig (patched or unpatched), and I go into the spectrum scope view, my USB keyboard and mouse stop responding! Though the spectrum scope continues to update, I can't type nor mouse around until I kill soundmodem via an out of band SSH connection! How weird! This Gateway NV57 laptop system is Centos6 (linux 2.6.32) running PulseAudio and Soundmodem using a USB soundcard (US Interface Navigator) which is configured to use ALSA natively (not OSS). - If I configure soundmodemconfig to use the on-motherboard soundcard, the keyboard and mouse continue to function when the spectrum scope is running! This makes me think this is a USB / kernel issue with soundmodem - I moved all my various USB devices to different port locations but there wasn't any improvement - I tried disconnecting and re-connecting the USB to kb+mouse adapter after the spectrum scope is running but that didn't help - The KB+mouse are actually PS/2 style devices connecting through a PS2 to USB adapter - I've unconfigured the PTT port in soundmodemconfig to reduce variables but that didn't have any change to the behavior - I'm not running a KVM or Xen enabled kernel - I've tried soundmodemconfig -S and that didn't allow the soundsystem to be found. Options -R and -M don't seem to be legal in soundmodemconfig though the man page says they are. - When I start soundmodem and try to show the spectrum display, I see the following on STDOUT: [root@hampacket2 dranch]# soundmodemconfig on_configtree_selection_changed config_select: cfg: hampacket chan: - selection: cfg: hampacket chan: - on_configtree_selection_changed config_deselect: cfg: hampacket chan: - selection: cfg: hampacket chan: Channel 0 Modulator: afsk Demodulator: afsk Modulator: parameter bps value 300 Modulator: parameter f0 value 1600 Modulator: parameter f1 value 1800 Modulator: parameter diffenc value 1 Demodulator: parameter bps value 300 Demodulator: parameter f0 value 1600 Demodulator: parameter f1 value 1800 Demodulator: parameter diffdec value 1 Minimum sampling rate: 11025 Audio IO: type alsa ALSA: Using sample rate 11025, sample format 2, significant bits 16, buffer size 5513, period size 165 ALSA: Using sample rate 11025, sample format 2, significant bits 16, buffer size 5513, period size 165 sm[3644]: audio: starting "plughw:1,0" Real sampling rate: 11025 sm[3644]: Opening PTT device "/dev/USI_PTT" -- - As a test, I tried using "padsp" to try things under OSS emulation but the /dev/dsp device isn't getting created. It looks like maybe soundmodem as asking for something that PulseAudio cannot support (according to an strace): -- write(2, "utils/padsp.c: SNDCTL_DSP_CAPS\n", 31utils/padsp.c: SNDCTL_DSP_CAPS) = 31 write(2, "sm[4098]: ", 10sm[4098]: ) = 10 write(2, "audio: forcing half duplex mode\n", 32audio: forcing half duplex mode) = 32 write(2, "utils/padsp.c: SNDCTL_DSP_SETFRA"..., 50utils/padsp.c: SNDCTL_DSP_SETFRAGMENT: 0xffff0008) = 50 futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 write(2, "utils/padsp.c: SNDCTL_DSP_SETFMT"..., 37utils/padsp.c: SNDCTL_DSP_SETFMT: 16) = 37 futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 write(2, "utils/padsp.c: SNDCTL_DSP_STEREO"..., 36utils/padsp.c: SNDCTL_DSP_STEREO: 0) = 36 write(2, "utils/padsp.c: SNDCTL_DSP_SPEED:"..., 39utils/padsp.c: SNDCTL_DSP_SPEED: 11025) = 39 futex(0x817160, FUTEX_LOCK_PI_PRIVATE, 1) = 0 write(2, "utils/padsp.c: ss: s16le 1ch 110"..., 37utils/padsp.c: ss: s16le 1ch 11025Hz) = 37 futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 write(2, "utils/padsp.c: unknown ioctl 0x0"..., 40utils/padsp.c: unknown ioctl 0x0000500e) = 40 write(2, "sm[4098]: ", 10sm[4098]: ) = 10 write(2, "audio: Error, cannot set nonbloc"..., 42audio: Error, cannot set nonblocking mode) = 42 <------------------------------------- write(2, "utils/padsp.c: freeing fd info ("..., 38utils/padsp.c: freeing fd info (fd=4)) = 38 write(2, "utils/padsp.c: Draining.\n", 25utils/padsp.c: Draining. -- I want to say soundmodem used to work on this specific machine with Pulse/Alsa on plughw1,0. I even tried starting up an older kernel but that didn't help. I don't see anything helpful in /var/log/messages, /var/log/Xorg.0.log, dmesg, etc. 2) I'm trying the newer soundmodem-0.16 patch iz6rdb submitted to Thomas for better 300BAUD performance but I thought you said you reverted one of these patches. I assume means I only need ONE of the patches. Which one should I NOT apply? Sampling rate fix: http://iz6rdb.trentalancia.com/en/soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch Longer filters (I think it's this one you don't recommend now): http://iz6rdb.trentalancia.com/en/soundmodem-0.16-increase-rx-filters-parameters.patch 3) With the unpatched soundmodemconfig spectrum view, there isn't any waveforms in column #1 but I do see all spectrum filling in columns 2-8. With your patches applied, I see the upper frequencies of column 1 filled (50%) all the way through column 4. Columns 5-8 are completely empty. It's as if all the spectrum has been compressed into the first four columns with your patch. Is that expected? It seems to be due to the soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch patch 4) With your patched soundmodem code running with a config of 1600/1800 mark/space, if I hit the PTT button say in the spectrum screen, I get one primary tone at 1700hz (according to the soundmodemconfig spectrum scope) and two very large harmonics on each side of it (1390hz, 1550, 1850, 1990). With the original soundmodem-0.16 code, I get one single tone at 1200hz and no harmonics 5) In soundmodemconfig under channel 0, do you know what the "differential encoding" option is for? 6) It seems I must apply the soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch FIRST and if I don't, the other patch will fail to apply. Might be worth mentioning the order dependency on your website 7) - Your patch files are assuming unique directories (soundmodem-0.16-orig). You should probably make them be more generic and relative: --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 +++ soundmodem-0.16/afsk/modem.c 2012-03-03 19:14:07.696345582 +0100 to say --- afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 +++ afsk/modem.c 2012-03-03 19:14:07.696345582 +0100 Sorry for the long email but lots of interesting stuff and I think including all the details always helps to come to a complete picture of the problem(s). 73s! --David KI6ZHD ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation 2012-04-07 23:14 ` Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation David Ranch @ 2012-04-08 15:23 ` Guido Trentalancia 2012-04-09 21:37 ` Curt, WE7U 1 sibling, 0 replies; 9+ messages in thread From: Guido Trentalancia @ 2012-04-08 15:23 UTC (permalink / raw) To: David Ranch; +Cc: Linux Hams Hello David. On Sat, 2012-04-07 at 16:14 -0700, David Ranch wrote: > Hello Guido, Thomas, fellow Linux HAMs: > > I've CCed the Linuxhams group as I'm curious if any of you have any > thoughts on why Soundmodem would be shutting down all USB-based keyboard > and mouse functionality until the process is killed! In all my years of > Linux, I've never need something like this. Very strange and any/all > comments would be very much appreciated! Soundmodem should be accessing USB through ALSA/Pulseaudio not anything lower level than that, so I doubt the problem with USB is being caused by soundmodem itself. You should perhaps cross-check if the problem persists with other audio applications and then report it for as example as a kernel or Pulseaudio issue, but I don't know... > Few points: > > 1) I've recently noticed a change on my system that when I run > soundmodemconfig (patched or unpatched), and I go into the spectrum > scope view, my USB keyboard and mouse stop responding! Though the > spectrum scope continues to update, I can't type nor mouse around until > I kill soundmodem via an out of band SSH connection! How weird! > > This Gateway NV57 laptop system is Centos6 (linux 2.6.32) running > PulseAudio and Soundmodem using a USB soundcard (US Interface Navigator) > which is configured to use ALSA natively (not OSS). > > - If I configure soundmodemconfig to use the on-motherboard > soundcard, the keyboard and mouse continue to function when the spectrum > scope is running! This makes me think this is a USB / kernel issue with > soundmodem > > - I moved all my various USB devices to different port locations > but there wasn't any improvement > - I tried disconnecting and re-connecting the USB to kb+mouse > adapter after the spectrum scope is running but that didn't help > - The KB+mouse are actually PS/2 style devices connecting through a > PS2 to USB adapter > - I've unconfigured the PTT port in soundmodemconfig to reduce > variables but that didn't have any change to the behavior > - I'm not running a KVM or Xen enabled kernel > - I've tried soundmodemconfig -S and that didn't allow the > soundsystem to be found. Options -R and -M don't seem to be legal in > soundmodemconfig though the man page says they are. > > - When I start soundmodem and try to show the spectrum display, I > see the following on STDOUT: > > [root@hampacket2 dranch]# soundmodemconfig > on_configtree_selection_changed > config_select: cfg: hampacket chan: - > selection: cfg: hampacket chan: - > on_configtree_selection_changed > config_deselect: cfg: hampacket chan: - > selection: cfg: hampacket chan: Channel 0 > Modulator: afsk Demodulator: afsk > Modulator: parameter bps value 300 > Modulator: parameter f0 value 1600 > Modulator: parameter f1 value 1800 > Modulator: parameter diffenc value 1 > Demodulator: parameter bps value 300 > Demodulator: parameter f0 value 1600 > Demodulator: parameter f1 value 1800 > Demodulator: parameter diffdec value 1 > Minimum sampling rate: 11025 > Audio IO: type alsa > ALSA: Using sample rate 11025, sample format 2, significant bits 16, > buffer size 5513, period size 165 > ALSA: Using sample rate 11025, sample format 2, significant bits 16, > buffer size 5513, period size 165 > sm[3644]: audio: starting "plughw:1,0" > Real sampling rate: 11025 > sm[3644]: Opening PTT device "/dev/USI_PTT" > -- > > - As a test, I tried using "padsp" to try things under OSS > emulation but the /dev/dsp device isn't getting created. It looks like > maybe soundmodem as asking for something that PulseAudio cannot support > (according to an strace): > -- > write(2, "utils/padsp.c: SNDCTL_DSP_CAPS\n", 31utils/padsp.c: > SNDCTL_DSP_CAPS) = 31 > write(2, "sm[4098]: ", 10sm[4098]: ) = 10 > write(2, "audio: forcing half duplex mode\n", 32audio: forcing half > duplex mode) = 32 > write(2, "utils/padsp.c: SNDCTL_DSP_SETFRA"..., 50utils/padsp.c: > SNDCTL_DSP_SETFRAGMENT: 0xffff0008) = 50 > futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 > write(2, "utils/padsp.c: SNDCTL_DSP_SETFMT"..., 37utils/padsp.c: > SNDCTL_DSP_SETFMT: 16) = 37 > futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 > write(2, "utils/padsp.c: SNDCTL_DSP_STEREO"..., 36utils/padsp.c: > SNDCTL_DSP_STEREO: 0) = 36 > write(2, "utils/padsp.c: SNDCTL_DSP_SPEED:"..., 39utils/padsp.c: > SNDCTL_DSP_SPEED: 11025) = 39 > futex(0x817160, FUTEX_LOCK_PI_PRIVATE, 1) = 0 > write(2, "utils/padsp.c: ss: s16le 1ch 110"..., 37utils/padsp.c: ss: > s16le 1ch 11025Hz) = 37 > futex(0x817160, FUTEX_UNLOCK_PI_PRIVATE, 0) = 0 > write(2, "utils/padsp.c: unknown ioctl 0x0"..., 40utils/padsp.c: unknown > ioctl 0x0000500e) = 40 > write(2, "sm[4098]: ", 10sm[4098]: ) = 10 > write(2, "audio: Error, cannot set nonbloc"..., 42audio: Error, cannot > set nonblocking mode) = 42 <------------------------------------- > write(2, "utils/padsp.c: freeing fd info ("..., 38utils/padsp.c: freeing > fd info (fd=4)) = 38 > write(2, "utils/padsp.c: Draining.\n", 25utils/padsp.c: Draining. > -- So, pulseaudio is having problems... Unless you are certain that soundmodem is using pulseaudio improperly, then you'd better narrow down to a pulseaudio problem. > I want to say soundmodem used to work on this specific machine with > Pulse/Alsa on plughw1,0. If you are using the configuration file that I did send to you, you should adapt it to suit your needs and configuration, it's just an example, since you did ask... If you just plugged in my configuration file, then that might be the problem, as for example, it uses /dev/dsp directly (device="/dev/dsp") and not alsa. The configuration file was mainly intended to give a hint on tone frequencies, differential enconding and decoding that need to be enabled, half-duplex that needs to be enabled, but the rest, you need to adapt it to your setup. > I even tried starting up an older kernel but > that didn't help. I don't see anything helpful in /var/log/messages, > /var/log/Xorg.0.log, dmesg, etc. > > 2) I'm trying the newer soundmodem-0.16 patch iz6rdb submitted to Thomas > for better 300BAUD performance but I thought you said you reverted one > of these patches. I assume means I only need ONE of the patches. Which > one should I NOT apply? > > Sampling rate fix: > http://iz6rdb.trentalancia.com/en/soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch > Longer filters (I think it's this one you don't recommend now): > http://iz6rdb.trentalancia.com/en/soundmodem-0.16-increase-rx-filters-parameters.patch As I told you already off-list, you will probably need both of them. Or at least I do need both of them, but I couldn't test on different setups or carry out any further optimization. > 3) With the unpatched soundmodemconfig spectrum view, there isn't any > waveforms in column #1 but I do see all spectrum filling in columns > 2-8. With your patches applied, I see the upper frequencies of column 1 > filled (50%) all the way through column 4. Columns 5-8 are completely > empty. It's as if all the spectrum has been compressed into the first > four columns with your patch. Is that expected? It seems to be due to > the soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch patch > > 4) With your patched soundmodem code running with a config of 1600/1800 > mark/space, if I hit the PTT button say in the spectrum screen, I get > one primary tone at 1700hz (according to the soundmodemconfig spectrum > scope) and two very large harmonics on each side of it (1390hz, 1550, > 1850, 1990). With the original soundmodem-0.16 code, I get one single > tone at 1200hz and no harmonics > > 5) In soundmodemconfig under channel 0, do you know what the > "differential encoding" option is for? You need that. Online resources such as Wikipedia will explain you what that it for. > 6) It seems I must apply the > soundmodem-0.16-use-a-minimum-samplerate-for-afsk-v5.patch FIRST and if > I don't, the other patch will fail to apply. Yes, the first patch is mandatory until at least a new release of soundmodem will accommodate 300 baud AFSK properly. The second patch just makes the RX filter better. I do need the second patch for successful decoding, however it might not be optimized. It just works for me. > Might be worth mentioning > the order dependency on your website It's explained in the patch. And they are listed orderly. Also with only two patches, there are very few possible combinations ;-) > 7) - Your patch files are assuming unique directories > (soundmodem-0.16-orig). You should probably make them be more generic > and relative: > > --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 > +++ soundmodem-0.16/afsk/modem.c 2012-03-03 19:14:07.696345582 +0100 > > to say > > --- afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 > +++ afsk/modem.c 2012-03-03 19:14:07.696345582 +0100 patch -p1: kernel standard options for diff. > Sorry for the long email but lots of interesting stuff and I think > including all the details always helps to come to a complete picture of > the problem(s). Yes indeed, interesting stuff. One day I'd also like to have more configurable options (such as IIR filters), but it all takes time, you know... > 73s! > > --David > KI6ZHD Summing up, I really doubt the USB conflict problem is due to soundmodem itself. Double-check your configuration file rather than just dumb-copying the one I did supply to you. If the problem with USB persists, then you either need to do a bit of debugging yourself or try reporting it to pulseaudio for example. Another option is to try posting your configuration file on here for others to check it. Hope it helps. 73 Guido IZ6RDB -- This email and any attachments are intended only for the person to which this email is addressed and may contain confidential and/or privileged information. If you received this email in error, please do not disclose the contents to anyone, but notify the sender immediately and delete this email (and any attachments) from your system. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation 2012-04-07 23:14 ` Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation David Ranch 2012-04-08 15:23 ` Guido Trentalancia @ 2012-04-09 21:37 ` Curt, WE7U 1 sibling, 0 replies; 9+ messages in thread From: Curt, WE7U @ 2012-04-09 21:37 UTC (permalink / raw) To: David Ranch; +Cc: Guido Trentalancia, t.sailer, Linux Hams On Sat, 7 Apr 2012, David Ranch wrote: > I've CCed the Linuxhams group as I'm curious if any of you have any thoughts > on why Soundmodem would be shutting down all USB-based keyboard and mouse > functionality until the process is killed! In all my years of Linux, I've > never need something like this. Very strange and any/all comments would be > very much appreciated! I've seen something kind of like it on my motherboard at home that has an NVidia 8200 chipset integrated in. If I plug in _any_ USB 1.x devices, the whole Linux USB stack crashes and I lose keyboard/mouse (if they're USB). It's a known problem with the NVidia chipset and the USB 1.x controller they integrated into it. Their USB 2.x controller doesn't have the problem. My fix: Plug in a USB smart hub, plug the USB 1.x devices into that: The motherboard only sees USB 2.x protocol and everything works great. The device that caused it in my case: A USB SignaLink box that I use to do digital modes on HF. -- Curt, WE7U. http://www.eskimo.com/~archer APRS Wiki: http://info.aprs.net/ ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) 2012-03-03 9:50 ` walter harms 2012-03-03 14:47 ` Guido Trentalancia @ 2012-03-03 18:48 ` Guido Trentalancia 1 sibling, 0 replies; 9+ messages in thread From: Guido Trentalancia @ 2012-03-03 18:48 UTC (permalink / raw) To: wharms; +Cc: linux-hams, t.sailer Summing things up... I am now doing perfectly well both modulation and demodulation with the combination of the following two patches. This [1/2] patch modifies the AFSK modulator in version 0.16 of the soundmodem application as it appears to be problematic in particular at 300 baud (in general, it might be buggy for bitrates lower than 1200 baud, although I have not done any testing at other bitrates). In other words, this patch should fix the AFSK modulator for the problem reported, for example, here: - http://he.fi/archive/linux-hams/200608/0005.html - http://marc.info/?l=linux-hams&m=129059468102018&w=2 I have also introduced optional windowing functions (other than the Hamming one) for experimentation but at the moment they are completely untested and they can only be selected during compilation. After applying this patch, the AFSK modulator should work normally for 300 baud (or in general bitrates different/less than 1200 baud) and the user should be able to select any AFSK tone frequencies from the configuration file. Similar fixes are also introduced by this patch for the AFSK demodulator, although for successful reception at 300 baud it might also need longer RX filters that are eventually more robust against overflows. Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com> --- afsk/modem.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 193 insertions(+), 37 deletions(-) --- soundmodem-0.16-orig/afsk/modem.c 2012-02-29 20:31:24.356287000 +0100 +++ soundmodem-0.16/afsk/modem.c 2012-03-03 19:14:07.696345582 +0100 @@ -32,8 +32,71 @@ #include "modem.h" #include "costab.h" +/* + * IZ6RDB 29/02/2012: always use a minimum samplerate + * otherwise some sound cards, might not work well + * especially at bitrates lower than 1200 baud (such + * as 300 baud for HF). + * + * The value is defined in Hz and it should never be + * less than 9600 Hz to avoid problems, although the + * recommended value is 11025 Hz for most soundcards. + * + * Some cards, might even require that only their + * maximum allowed sampling rate of 48kHz is used + * (for example, according to online reports some + * embedded SiS 701x AC'97 controllers). + */ +#define MINIMUM_SAMPLERATE 11025 + +/* + * IZ6RDB 01/03/2012: define different possible + * window types for the FIR filters and choose + * one of the available types: + * - NONE + * - HAMMING (window used up to version 0.16) + * - HANNING + * - BLACKMAN + * - WELCH (for weak signals) + */ +#define FIR_WINDOW HAMMING + +/* + * IZ6RDB 01/03/2012: introduce a parameter + * called "bandwidth expansion factor", which + * is a real positive number slightly greater + * than unity (up to 2.0) that accounts for + * guard-bands and non-ideal filtering. + * + * This value is only used for estimating the + * required sampling rate. + * + * Values are usually between 1.125 and 1.4. + * + * The recommended value is 1.36. + */ +#define BANDWIDTH_EXPANSION_FACTOR 1.36 + /* --------------------------------------------------------------------- */ +#ifdef FIR_WINDOW +#if (FIR_WINDOW == NONE) +#define WINDOW_FUNCTION(x) no_window(x) +#elif (FIR_WINDOW == HAMMING) +#define WINDOW_FUNCTION(x) hamming_window(x) +#elif (FIR_WINDOW == HANNING) +#define WINDOW_FUNCTION(x) hanning_window(x) +#elif (FIR_WINDOW == BLACKMAN) +#define WINDOW_FUNCTION(x) blackman_window(x) +#elif (FIR_WINDOW == WELCH) +#define WINDOW_FUNCTION(x) welch_window(x) +#else +#error "A valid FIR Window must be selected !" +#endif +#else // default to Hamming window +#define WINDOW_FUNCTION(x) hamming_window(x) +#endif + struct modstate { struct modemchannel *chan; unsigned int bps, f0, f1, notdiff, maxbitlen; @@ -53,6 +116,9 @@ static const struct modemparams modparam static void *modconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) { struct modstate *s; + unsigned int bandwidth, expanded_bandwidth; + unsigned int min_samplerate, optimized_samplerate; + unsigned int f_carrier; if (!(s = malloc(sizeof(struct modstate)))) logprintf(MLOG_FATAL, "out of memory\n"); @@ -63,22 +129,45 @@ static void *modconfig(struct modemchann s->bps = 100; if (s->bps > 9600) s->bps= 9600; - } else - s->bps = 1200; - if (params[1]) { + } + if (params[1]) s->f0 = strtoul(params[1], NULL, 0); - if (s->f0 > s->bps * 4) - s->f0 = s->bps * 4; - } else - s->f0 = 1200; - if (params[2]) { + if (params[2]) s->f1 = strtoul(params[2], NULL, 0); - if (s->f1 > s->bps * 4) - s->f1 = s->bps * 4; - } else - s->f1 = 2200; s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; - *samplerate = 8 * s->bps; + + /* + * Calculate the bandwidth of the baseband (audio) signal: + * basically this is the highest frequency of the two + * possible tones. + */ + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; + + /* + * Calculate the expanded bandwidth (with guard-bands) + * to get a better estimate. + */ + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; + + /* Nyquist criteria (minimum sampling rate) */ + min_samplerate = 2 * expanded_bandwidth; + + /* Calculate the (audio) carrier frequency */ + f_carrier = (s->f0 + s->f1)/2; + + /* Calculate intermediate operating point sampling rate */ + optimized_samplerate = 4 * f_carrier; + if (optimized_samplerate > min_samplerate) + min_samplerate = optimized_samplerate; + + /* + * Make sure that the minimum recommended sampling + * rate for the soundcard is exceeded. + */ + if (min_samplerate < MINIMUM_SAMPLERATE) + min_samplerate = MINIMUM_SAMPLERATE; + + *samplerate = min_samplerate; return s; } @@ -147,10 +236,28 @@ struct modulator afskmodulator = { #define max(a, b) (((a) > (b)) ? (a) : (b)) -/* RxFilter */ +/* Rx FIR Filter parameters */ + +/* + * Rx FIR Filter window expansion parameter + * is normally equal to 1.5. + */ #define WINDOWEXPAND 1.5 + +/* + * Rx FIR Filter length is normally equal + * to 16. + */ #define RXFILTLEN 16 -#define RXFILTOVERBITS 3 + +/* + * Rx FIR Filter length is normally equal + * to 16. This parameter should represent + * the minimum wordlength to avoid + * overflow. + */ +#define RXFILTOVERBITS 3 + #define RXFILTOVER (1<<(RXFILTOVERBITS)) #define RXFILTFIDX(x) (((x)>>(16-(RXFILTOVERBITS)))&(RXFILTOVER-1)) #define RXFILTFSAMP(x) ((x)>>16) @@ -202,7 +309,9 @@ static const struct modemparams demodpar static void *demodconfig(struct modemchannel *chan, unsigned int *samplerate, const char *params[]) { struct demodstate *s; - unsigned int f; + unsigned int bandwidth, expanded_bandwidth; + unsigned int min_samplerate, optimized_samplerate; + unsigned int f_carrier; if (!(s = malloc(sizeof(struct demodstate)))) logprintf(MLOG_FATAL, "out of memory\n"); @@ -213,27 +322,45 @@ static void *demodconfig(struct modemcha s->bps = 100; if (s->bps > 9600) s->bps= 9600; - } else - s->bps = 1200; - if (params[1]) { + } + if (params[1]) s->f0 = strtoul(params[1], NULL, 0); - if (s->f0 > s->bps * 4) - s->f0 = s->bps * 4; - } else - s->f0 = 1200; - if (params[2]) { + if (params[2]) s->f1 = strtoul(params[2], NULL, 0); - if (s->f1 > s->bps * 4) - s->f1 = s->bps * 4; - } else - s->f1 = 2200; s->notdiff = params[3] ? !strtoul(params[3], NULL, 0) : 0; - f = s->f0; - if (s->f1 > f) - f = s->f1; - f += s->bps/2; - f = (2*f) + (f >> 1); - *samplerate = f; + + /* + * Calculate the bandwidth of the baseband (audio) signal: + * basically this is the highest frequency of the two + * possible tones. + */ + bandwidth = (s->f0 > s->f1) ? s->f0 : s->f1; + + /* + * Calculate the expanded bandwidth (with guard-bands) + * to get a better estimate. + */ + expanded_bandwidth = BANDWIDTH_EXPANSION_FACTOR * bandwidth; + + /* Nyquist criteria (minimum sampling rate) */ + min_samplerate = 2 * expanded_bandwidth; + + /* Calculate the (audio) carrier frequency */ + f_carrier = (s->f0 + s->f1)/2; + + /* Calculate intermediate operating point sampling rate */ + optimized_samplerate = 4 * f_carrier; + if (optimized_samplerate > min_samplerate) + min_samplerate = optimized_samplerate; + + /* + * Make sure that the minimum recommended sampling + * rate for the soundcard is exceeded. + */ + if (min_samplerate < MINIMUM_SAMPLERATE) + min_samplerate = MINIMUM_SAMPLERATE; + + *samplerate = min_samplerate; return s; } @@ -317,7 +444,6 @@ static void demod8bits(struct demodstate s->rxphase += phase; } - static void demoddemodulate(void *state) { struct demodstate *s = (struct demodstate *)state; @@ -364,11 +490,41 @@ static inline double sinc(double x) return sin(arg) / arg; } -static inline double hamming(double x) +/* + * The Hamming window is the original one (used + * exclusively up to version 0.16). + * From version 0.17 optional windows different + * from the Hamming window have been introduced, + * so that they can be changed and tested in + * order to try achieving reduced passband + * ripples at the expense of slower passband to + * stopband roll-off. + */ +static inline double no_window(double x) +{ + return 1; +} + +static inline double hamming_window(double x) { return 0.54-0.46*cos((2*M_PI)*x); } +static inline double hanning_window(double x) +{ + return 0.5-0.5*cos((2*M_PI)*x); +} + +static inline double blackman_window(double x) +{ + return 0.42-0.5*cos((2*M_PI)*x)+0.08*cos((4*M_PI)*x); +} + +static inline double welch_window(double x) +{ + return 1.0-pow((2*x-1),2); +} + static void demodinit(void *state, unsigned int samplerate, unsigned int *bitrate) { struct demodstate *s = (struct demodstate *)state; @@ -388,7 +544,7 @@ static void demodinit(void *state, unsig if (w > 1) w = 0; else - w = hamming(w); + w = WINDOW_FUNCTION(w); f0r[i] = w * cos(ph0 * i); f0i[i] = w * sin(ph0 * i); f1r[i] = w * cos(ph1 * i); This [2/2] patch might be useful for successful reception at 300 baud. It uses longer RX filters and it also makes them supposedly more robust against overflows. It hasn't been extensively tested and setups are all different, but it has helped me considerably in using soundmodem at 300 baud. Signed-off-by: Guido Trentalancia <iz6rdb@trentalancia.com> --- afsk/modem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- soundmodem-0.16-fix-samplerate/afsk/modem.c 2012-03-03 19:14:53.748535161 +0100 +++ soundmodem-0.16-fix-samplerate-and-rxfilters/afsk/modem.c 2012-03-03 19:16:34.066638207 +0100 @@ -59,7 +59,7 @@ * - BLACKMAN * - WELCH (for weak signals) */ -#define FIR_WINDOW HAMMING +#define FIR_WINDOW WELCH /* * IZ6RDB 01/03/2012: introduce a parameter @@ -248,7 +248,7 @@ struct modulator afskmodulator = { * Rx FIR Filter length is normally equal * to 16. */ -#define RXFILTLEN 16 +#define RXFILTLEN 48 /* * Rx FIR Filter length is normally equal @@ -256,7 +256,7 @@ struct modulator afskmodulator = { * the minimum wordlength to avoid * overflow. */ -#define RXFILTOVERBITS 3 +#define RXFILTOVERBITS 5 #define RXFILTOVER (1<<(RXFILTOVERBITS)) #define RXFILTFIDX(x) (((x)>>(16-(RXFILTOVERBITS)))&(RXFILTOVER-1)) In the first patch I have also considered a few kind comments from Walter Harms to improve the style a little bit when defining the optional window selection. I cannot spend much time in further revisions and also I am now perfectly happy with the performance that I am achieving, but feel free to introduce further improvements and/or apply bits or the whole thing directly into new releases if you feel doing the right thing. I just hope it helps quickly sorting out the issue for other people that were also experiencing problems with using soundmodem at 300 baud... Regards, Guido IZ6RDB ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-04-09 21:37 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-03 0:54 soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) Guido Trentalancia
2012-03-03 9:50 ` walter harms
2012-03-03 14:47 ` Guido Trentalancia
2012-03-04 14:33 ` walter harms
2012-03-04 20:16 ` Guido Trentalancia
[not found] ` <4F776E14.7090104@trinnet.net>
[not found] ` <1333379832.2112.15.camel@vortex>
[not found] ` <4F7B199F.3050104@trinnet.net>
[not found] ` <1333647291.2605.34.camel@vortex>
[not found] ` <1333741818.4064.20.camel@vortex>
[not found] ` <4F7F7A2C.2030500@trinnet.net>
[not found] ` <1333809855.2433.10.camel@vortex>
2012-04-07 23:14 ` Soundmodem hangs all USB keyboard or mouse input -- and soundmodem 0.16: fix the AFSK modulator for 300 baud operation David Ranch
2012-04-08 15:23 ` Guido Trentalancia
2012-04-09 21:37 ` Curt, WE7U
2012-03-03 18:48 ` soundmodem 0.16: fix the AFSK modulator for 300 baud operation (was: RE: 300bps Packet) Guido Trentalancia
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox