Enable concurrent RSID decoding

* Change Sound*::Read methods to float
* Enable RSID upsampling for 8 KHz modems
* Add main.{get,set,toggle}_rsid XML-RPC methods
* Add option to disable RSID decoding on reception
* RSID may be enabled during transmit or tune
pull/2/head
Stelios Bounanos 2009-09-01 01:05:51 +01:00
rodzic 4de96c9b34
commit b09cea25ff
11 zmienionych plików z 288 dodań i 142 usunięć

Wyświetl plik

@ -1945,6 +1945,12 @@ Fl_Check_Button *chkRSidNotifyOnly=(Fl_Check_Button *)0;
static void cb_chkRSidNotifyOnly(Fl_Check_Button* o, void*) {
progdefaults.rsid_notify_only = o->value();
notify_create_rsid_event(progdefaults.rsid_notify_only);
if (progdefaults.rsid_notify_only) {
chkRSidAutoDisable->value(0);
chkRSidAutoDisable->deactivate();
}
else
chkRSidAutoDisable->activate();
progdefaults.changed = true;
}
@ -1955,6 +1961,13 @@ static void cb_chkRSidMark(Fl_Check_Button* o, void*) {
progdefaults.changed = true;
}
Fl_Check_Button *chkRSidAutoDisable=(Fl_Check_Button *)0;
static void cb_chkRSidAutoDisable(Fl_Check_Button* o, void*) {
progdefaults.rsid_auto_disable = o->value();
progdefaults.changed = true;
}
Fl_Group *tabMisc=(Fl_Group *)0;
Fl_Tabs *tabsMisc=(Fl_Tabs *)0;
@ -4272,7 +4285,7 @@ ll with your audio device."));
} // Fl_Value_Slider* sldrCWIDwpm
sld->end();
} // Fl_Group* sld
{ Fl_Group* o = new Fl_Group(5, 218, 490, 94, _("Reed-Solomon ID"));
{ Fl_Group* o = new Fl_Group(5, 218, 490, 120, _("Reed-Solomon ID"));
o->box(FL_ENGRAVED_FRAME);
o->align(FL_ALIGN_TOP_LEFT|FL_ALIGN_INSIDE);
{ Fl_Check_Button* o = chkTransmitRSid = new Fl_Check_Button(15, 246, 165, 20, _("Transmit mode RSID"));
@ -4300,6 +4313,14 @@ d frequency"));
chkRSidMark->callback((Fl_Callback*)cb_chkRSidMark);
chkRSidMark->value(progdefaults.rsid_mark);
} // Fl_Check_Button* chkRSidMark
{ chkRSidAutoDisable = new Fl_Check_Button(15, 306, 200, 20, _("Reception disables detector"));
chkRSidAutoDisable->tooltip(_("Disable further detection when RSID is received"));
chkRSidAutoDisable->down_box(FL_DOWN_BOX);
chkRSidAutoDisable->callback((Fl_Callback*)cb_chkRSidAutoDisable);
if (progdefaults.rsid_notify_only) progdefaults.rsid_auto_disable = false;
chkRSidAutoDisable->value(progdefaults.rsid_auto_disable);
if (progdefaults.rsid_notify_only) chkRSidAutoDisable->deactivate();
} // Fl_Check_Button* chkRSidAutoDisable
o->end();
} // Fl_Group* o
tabID->end();

Wyświetl plik

@ -82,7 +82,7 @@ static const char szBaudRates[] = "300|600|1200|2400|4800|9600|19200|38400|57600
code {} {}
Fl_Window {} {
label {Fldigi configuration} open
xywh {646 121 500 400} type Double color 45 selection_color 51 labelsize 18 align 80 visible
xywh {646 129 500 400} type Double color 45 selection_color 51 labelsize 18 align 80 visible
} {
Fl_Tabs tabsConfigure {open
xywh {0 0 517 372} color 50 selection_color 50
@ -2369,7 +2369,7 @@ progdefaults.changed = true;}
}
Fl_Group {} {
label {Reed-Solomon ID} open
xywh {5 218 490 94} box ENGRAVED_FRAME align 21
xywh {5 218 490 120} box ENGRAVED_FRAME align 21
} {
Fl_Check_Button chkTransmitRSid {
label {Transmit mode RSID}
@ -2390,6 +2390,12 @@ OFF - limit search to +/- 200 Hz} xywh {215 246 270 20} down_box DOWN_BOX
label {Notifications only}
callback {progdefaults.rsid_notify_only = o->value();
notify_create_rsid_event(progdefaults.rsid_notify_only);
if (progdefaults.rsid_notify_only) {
chkRSidAutoDisable->value(0);
chkRSidAutoDisable->deactivate();
}
else
chkRSidAutoDisable->activate();
progdefaults.changed = true;}
tooltip {Check this to be notified when an RSID is received
without changing modem and frequency} xywh {15 276 155 20} down_box DOWN_BOX
@ -2403,6 +2409,15 @@ progdefaults.changed = true;}
changing frequency and modem} xywh {215 276 270 20} down_box DOWN_BOX
code0 {chkRSidMark->value(progdefaults.rsid_mark);}
}
Fl_Check_Button chkRSidAutoDisable {
label {Reception disables detector}
callback {progdefaults.rsid_auto_disable = o->value();
progdefaults.changed = true;}
tooltip {Disable further detection when RSID is received} xywh {15 306 200 20} down_box DOWN_BOX
code0 {if (progdefaults.rsid_notify_only) progdefaults.rsid_auto_disable = false;}
code1 {chkRSidAutoDisable->value(progdefaults.rsid_auto_disable);}
code2 {if (progdefaults.rsid_notify_only) chkRSidAutoDisable->deactivate();}
}
}
}
Fl_Group tabMisc {

Wyświetl plik

@ -1246,21 +1246,9 @@ void cbTune(Fl_Widget *w, void *) {
restoreFocus();
}
void cbRSID(Fl_Widget *w, void *) {
if (trx_state == STATE_TX || trx_state == STATE_TUNE) {
btnRSID->value(0);
return;
}
if (progdefaults.rsid == true) {
progdefaults.rsid = false;
wf->xmtrcv->activate();
btnTune->activate();
} else {
ReedSolomon->reset();
progdefaults.rsid = true;
wf->xmtrcv->deactivate();
btnTune->deactivate();
}
void cbRSID(Fl_Widget *w, void *)
{
progdefaults.rsid = btnRSID->value();
restoreFocus();
}
@ -3410,7 +3398,6 @@ void setReverse(int rev) {
void start_tx()
{
if (progdefaults.rsid == true) return;
trx_transmit();
REQ(&waterfall::set_XmtRcvBtn, wf, true);
}

Wyświetl plik

@ -291,6 +291,7 @@ extern Fl_Check_Button *chkTransmitRSid;
extern Fl_Check_Button *chkRSidWideSearch;
extern Fl_Check_Button *chkRSidNotifyOnly;
extern Fl_Check_Button *chkRSidMark;
extern Fl_Check_Button *chkRSidAutoDisable;
extern Fl_Group *tabMisc;
extern Fl_Tabs *tabsMisc;
extern Fl_Group *tabSweetSpot;

Wyświetl plik

@ -52,6 +52,9 @@
ELEM_(bool, rsid_notify_only, "RSIDNOTIFYONLY", \
"Trigger RSID notifications but do not change modem and frequency", \
false) \
ELEM_(bool, rsid_auto_disable, "RSIDAUTODISABLE", \
"Disable RSID detection when changing modem and/or frequency", \
true) \
\
ELEM_(bool, slowcpu, "SLOWCPU", \
"Disable expensive processing in some decoders", \

Wyświetl plik

@ -2,8 +2,10 @@
//
// rsid.h
//
// Copyright (C) 2006
// Copyright (C) 2008, 2009
// Dave Freese, W1HKJ
// Copyright (C) 2009
// Stelios Bounanos, M0GLD
//
// This file is part of fldigi.
//
@ -40,11 +42,15 @@
#ifndef RSID_H
#define RSID_H
#include <samplerate.h>
#include "ringbuffer.h"
#include "globals.h"
#include "modem.h"
#define RSID_SAMPLE_RATE 11025.0
#define RSID_FFT_SAMPLES 512
#define RSID_FFT_SIZE 1024
#define RSID_ARRAY_SIZE (RSID_FFT_SIZE * 2)
@ -66,7 +72,6 @@ struct RSIDs { unsigned char rs; trx_mode mode; };
class cRsId {
private:
int _samplerate;
// Table of precalculated Reed Solomon symbols
unsigned char *pCodes;
@ -79,7 +84,7 @@ private:
// Span of FFT bins, in which the RSID will be searched for
int nBinLow;
int nBinHigh;
double aInputSamples[RSID_ARRAY_SIZE];
float aInputSamples[RSID_ARRAY_SIZE];
double fftwindow[RSID_ARRAY_SIZE];
double aFFTReal[RSID_ARRAY_SIZE];
double aFFTAmpl[RSID_FFT_SIZE];
@ -98,6 +103,12 @@ private:
int DistanceOut;
int MetricsOut;
// resample
SRC_STATE* src_state;
SRC_DATA src_data;
float* inptr;
static long src_callback(void* cb_data, float** data);
// transmit
double *outbuf;
size_t symlen;
@ -107,12 +118,13 @@ private:
int HammingDistance(int iBucket, unsigned char *p2);
void CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd);
bool search_amp( int &pSymbolOut, int &pBinOut);
void search(void);
void apply (int iSymbol, int iBin);
public:
cRsId();
~cRsId();
void reset();
void search(const double *pSamples, size_t nSamples);
void apply (int iSymbol, int iBin);
void receive(const float* buf, size_t len);
void send(bool postidle);
};

Wyświetl plik

@ -79,7 +79,8 @@ protected:
SNDFILE* ofCapture;
SNDFILE* ifPlayback;
SNDFILE* ofGenerate;
sf_count_t read_file(SNDFILE* file, double* buf, size_t count);
sf_count_t read_file(SNDFILE* file, float* buf, size_t count);
sf_count_t write_file(SNDFILE* file, float* buf, size_t count);
sf_count_t write_file(SNDFILE* file, double* buf, size_t count);
bool format_supported(int format);
void tag_file(SNDFILE *sndfile, const char *title);
@ -97,7 +98,7 @@ public:
virtual void Abort(unsigned dir = UINT_MAX) = 0;
virtual size_t Write(double *, size_t) = 0;
virtual size_t Write_stereo(double *, double *, size_t) = 0;
virtual size_t Read(double *, size_t) = 0;
virtual size_t Read(float *, size_t) = 0;
virtual void flush(unsigned dir = UINT_MAX) = 0;
virtual bool must_close(void) = 0;
#if USE_SNDFILE
@ -148,7 +149,7 @@ public:
void Abort(unsigned dir = UINT_MAX) { Close(dir); }
size_t Write(double *, size_t);
size_t Write_stereo(double *, double *, size_t);
size_t Read(double *, size_t);
size_t Read(float *, size_t);
bool must_close(void) { return true; }
void flush(unsigned dir = UINT_MAX) { wait_till_finished(); }
@ -191,7 +192,7 @@ public:
void Abort(unsigned dir = UINT_MAX);
size_t Write(double *buf, size_t count);
size_t Write_stereo(double *bufleft, double *bufright, size_t count);
size_t Read(double *buf, size_t count);
size_t Read(float *buf, size_t count);
bool must_close(void);
void flush(unsigned dir = UINT_MAX);
@ -274,7 +275,7 @@ public:
void Abort(unsigned dir = UINT_MAX);
size_t Write(double* buf, size_t count);
size_t Write_stereo(double* bufleft, double* bufright, size_t count);
size_t Read(double *buf, size_t count);
size_t Read(float *buf, size_t count);
bool must_close(void) { return false; }
void flush(unsigned dir = UINT_MAX);
@ -320,7 +321,7 @@ public:
void Abort(unsigned) { }
size_t Write(double* buf, size_t count);
size_t Write_stereo(double* bufleft, double* bufright, size_t count);
size_t Read(double *buf, size_t count);
size_t Read(float *buf, size_t count);
bool must_close(void) { return false; }
void flush(unsigned) { }
};

Wyświetl plik

@ -1116,7 +1116,7 @@ public:
Main_toggle_lock()
{
_signature = "b:n";
_help = "Toggles the Reverse Sideband state. Returns the new state.";
_help = "Toggles the Transmit Lock state. Returns the new state.";
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
@ -1128,6 +1128,54 @@ public:
// =============================================================================
class Main_get_rsid : public xmlrpc_c::method
{
public:
Main_get_rsid()
{
_signature = "b:n";
_help = "Returns the RSID state.";
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
*retval = xmlrpc_c::value_boolean(btnRSID->value());
}
};
class Main_set_rsid : public xmlrpc_c::method
{
public:
Main_set_rsid()
{
_signature = "b:b";
_help = "Sets the RSID state. Returns the old state.";
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
bool v = btnRSID->value();
REQ(set_button, btnRSID, params.getBoolean(0));
*retval = xmlrpc_c::value_boolean(v);
}
};
class Main_toggle_rsid : public xmlrpc_c::method
{
public:
Main_toggle_rsid()
{
_signature = "b:n";
_help = "Toggles the RSID state. Returns the new state.";
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
bool v = !btnRSID->value();
REQ(set_button, btnRSID, v);
*retval = xmlrpc_c::value_boolean(v);
}
};
// =============================================================================
class Main_get_trx_status : public xmlrpc_c::method
{
public:
@ -1142,8 +1190,6 @@ public:
*retval = xmlrpc_c::value_string("tune");
else if (wf->xmtrcv->value())
*retval = xmlrpc_c::value_string("tx");
else if (btnRSID->value())
*retval = xmlrpc_c::value_string("rsid");
else
*retval = xmlrpc_c::value_string("rx");
}
@ -1159,11 +1205,8 @@ public:
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
if (!wf->xmtrcv->value()) {
if (btnRSID->value())
REQ(set_button, btnRSID, false);
if (!wf->xmtrcv->value())
REQ(set_button, wf->xmtrcv, true);
}
*retval = xmlrpc_c::value_nil();
}
};
@ -1178,11 +1221,8 @@ public:
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
if (!btnTune->value()) {
if (btnRSID->value())
REQ(set_button, btnRSID, false);
if (!btnTune->value())
REQ(set_button, btnTune, !btnTune->value());
}
*retval = xmlrpc_c::value_nil();
}
};
@ -1199,8 +1239,6 @@ public:
{
if (wf->xmtrcv->value())
REQ(set_button, wf->xmtrcv, false);
else if (btnRSID->value())
REQ(set_button, btnRSID, false);
*retval = xmlrpc_c::value_nil();
}
};
@ -1257,7 +1295,7 @@ public:
Main_rsid()
{
_signature = "n:n";
_help = "Waits for RSID.";
_help = "Deprecated; use main.{get,set,toggle}_rsid instead.";
}
void execute(const xmlrpc_c::paramList& params, xmlrpc_c::value* retval)
{
@ -1946,6 +1984,10 @@ public:
ELEM_(Main_set_lock, "main.set_lock") \
ELEM_(Main_toggle_lock, "main.toggle_lock") \
\
ELEM_(Main_get_rsid, "main.get_rsid") \
ELEM_(Main_set_rsid, "main.set_rsid") \
ELEM_(Main_toggle_rsid, "main.toggle_rsid") \
\
ELEM_(Main_get_trx_status, "main.get_trx_status") \
ELEM_(Main_tx, "main.tx") \
ELEM_(Main_tune, "main.tune") \

Wyświetl plik

@ -1,7 +1,35 @@
// ----------------------------------------------------------------------------
//
// rsid.cxx
//
// Copyright (C) 2008, 2009
// Dave Freese, W1HKJ
// Copyright (C) 2009
// Stelios Bounanos, M0GLD
//
// This file is part of fldigi.
//
// fldigi is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// fldigi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with fldigi; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ----------------------------------------------------------------------------
#include <config.h>
#include <cmath>
#include <cstring>
#include <float.h>
#include <samplerate.h>
#include "rsid.h"
#include "filters.h"
@ -13,6 +41,7 @@
#include "confdialog.h"
#include "qrunner.h"
#include "notify.h"
#include "debug.h"
#include "rsid_fft.cxx"
@ -228,8 +257,16 @@ const int cRsId::indices[] = {
2, 4, 8, 9, 11, 15, 7, 14, 5, 10, 13, 3
};
cRsId :: cRsId()
cRsId::cRsId()
{
int error;
src_state = src_new(progdefaults.sample_converter, 1, &error);
if (error) {
LOG_ERROR("src_new error %d: %s", error, src_strerror(error));
abort();
}
src_data.end_of_input = 0;
reset();
memset(aHashTable1, 255, sizeof(aHashTable1));
@ -256,8 +293,6 @@ cRsId :: cRsId()
nBinLow = RSID_RESOL + 1;
nBinHigh = RSID_FFT_SIZE - 32;
_samplerate = 11025;
outbuf = 0;
symlen = 0;
}
@ -266,6 +301,7 @@ cRsId::~cRsId()
{
delete [] pCodes;
delete [] outbuf;
src_delete(src_state);
}
void cRsId::reset()
@ -277,6 +313,12 @@ void cRsId::reset()
memset(aFFTReal, 0, sizeof(aFFTReal));
memset(aFFTAmpl, 0, sizeof(aFFTAmpl));
memset(aBuckets, 0, sizeof(aBuckets));
int error = src_reset(src_state);
if (error)
LOG_ERROR("src_reset error %d: %s", error, src_strerror(error));
src_data.src_ratio = 0.0;
inptr = aInputSamples + RSID_FFT_SAMPLES;
}
void cRsId::Encode(int code, unsigned char *rsid)
@ -324,8 +366,50 @@ void cRsId::CalculateBuckets(const double *pSpectrum, int iBegin, int iEnd)
}
}
void cRsId::receive(const float* buf, size_t len)
{
double src_ratio = RSID_SAMPLE_RATE / active_modem->get_samplerate();
bool resample = (fabs(src_ratio - 1.0) >= DBL_EPSILON);
size_t ns;
void cRsId::search(const double *pSamples, size_t nSamples)
while (len) {
ns = inptr - aInputSamples;
if (ns >= RSID_FFT_SAMPLES) // inptr points to second half of aInputSamples
ns -= RSID_FFT_SAMPLES;
ns = RSID_FFT_SAMPLES - ns; // number of additional samples we need to call search()
if (resample) {
if (src_data.src_ratio != src_ratio)
src_set_ratio(src_state, src_data.src_ratio = src_ratio);
src_data.data_in = const_cast<float*>(buf);
src_data.input_frames = len;
src_data.data_out = inptr;
src_data.output_frames = ns;
src_data.input_frames_used = 0;
int error = src_process(src_state, &src_data);
if (unlikely(error)) {
LOG_ERROR("src_process error %d: %s", error, src_strerror(error));
return;
}
inptr += src_data.output_frames_gen;
buf += src_data.input_frames_used;
len -= src_data.input_frames_used;
}
else {
ns = MIN(ns, len);
memcpy(inptr, buf, ns * sizeof(*inptr));
inptr += ns;
buf += ns;
len -= ns;
}
ns = inptr - aInputSamples;
if (ns == RSID_FFT_SAMPLES || ns == RSID_FFT_SIZE)
search(); // will reset inptr if at end of input
}
}
void cRsId::search(void)
{
if (progdefaults.rsidWideSearch) {
nBinLow = RSID_RESOL + 1;
@ -343,14 +427,18 @@ void cRsId::search(const double *pSamples, size_t nSamples)
nBinHigh = RSID_FFT_SIZE - nBinLow;
}
size_t ns = nSamples;
if (ns > RSID_ARRAY_SIZE / 4) {
ns = RSID_ARRAY_SIZE / 4;
}
memmove(aInputSamples, aInputSamples + ns, ns * sizeof(double));
memcpy(aInputSamples + ns, pSamples, ns * sizeof(double));
for (int i = 0; i < RSID_FFT_SIZE; i++)
aFFTReal[i] = aInputSamples[i] * fftwindow[i];
if (inptr == aInputSamples + RSID_FFT_SIZE) {
for (int i = 0; i < RSID_FFT_SIZE; i++)
aFFTReal[i] = aInputSamples[i] * fftwindow[i];
inptr = aInputSamples;
}
else { // second half of aInputSamples is older
for (size_t i = RSID_FFT_SAMPLES; i < RSID_FFT_SIZE; i++)
aFFTReal[i - RSID_FFT_SAMPLES] = aInputSamples[i] * fftwindow[i - RSID_FFT_SAMPLES];
for (size_t i = 0; i < RSID_FFT_SAMPLES; i++)
aFFTReal[i + RSID_FFT_SAMPLES] = aInputSamples[i] * fftwindow[i + RSID_FFT_SAMPLES];
}
memset(aFFTReal + RSID_FFT_SIZE, 0, RSID_FFT_SIZE * sizeof(double));
rsrfft(aFFTReal, 11);
@ -387,7 +475,7 @@ void cRsId::apply(int iSymbol, int iBin)
mbin = rsid_ids[n].mode;
break;
}
if (!progdefaults.rsid_notify_only)
if (!progdefaults.rsid_notify_only && progdefaults.rsid_auto_disable)
REQ(toggleRSID);
if (mbin == NUM_MODES) return;

Wyświetl plik

@ -81,7 +81,7 @@ SoundBase::SoundBase()
: sample_frequency(0),
txppm(progdefaults.TX_corr), rxppm(progdefaults.RX_corr),
tx_src_state(0), rx_src_state(0),
wrt_buffer(new double [SND_BUF_LEN]),
wrt_buffer(new double[SND_BUF_LEN]),
#if USE_SNDFILE
ofCapture(0), ifPlayback(0), ofGenerate(0),
#endif
@ -129,7 +129,7 @@ void SoundBase::get_file_params(const char* def_fname, const char** fname, int*
*format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
break;
case 1:
*format = SF_FORMAT_AU | SF_FORMAT_DOUBLE | SF_ENDIAN_CPU;
*format = SF_FORMAT_AU | SF_FORMAT_FLOAT | SF_ENDIAN_CPU;
break;
case 2:
*format = SF_FORMAT_FLAC | SF_FORMAT_PCM_16;
@ -231,13 +231,13 @@ int SoundBase::Generate(bool val)
return 1;
}
sf_count_t SoundBase::read_file(SNDFILE* file, double* buf, size_t count)
sf_count_t SoundBase::read_file(SNDFILE* file, float* buf, size_t count)
{
sf_count_t r = sf_readf_double(file, buf, count);
sf_count_t r = sf_readf_float(file, buf, count);
while (r < (sf_count_t)count) {
sf_seek(file, 0, SEEK_SET);
r += sf_readf_double(file, buf + r, count - r);
r += sf_readf_float(file, buf + r, count - r);
if (r == 0)
break;
}
@ -245,17 +245,34 @@ sf_count_t SoundBase::read_file(SNDFILE* file, double* buf, size_t count)
return r;
}
#define WRITE_FILE(type_, file_, buf_, count_) \
if (capture || !progdefaults.EnableMixer) \
return sf_writef_ ## type_(file, buf, count); \
/* generated audio; apply transmit mixer level */ \
size_t nw = count; \
type_* wrtbuf = (type_*)wrt_buffer; \
for (size_t n = MIN(SND_BUF_LEN, count); count; count -= n) { \
for (size_t i = 0; i < n; i++) \
wrtbuf[i] = buf[i] * progStatus.XmtMixer; \
if (sf_writef_ ## type_(file, wrtbuf, n) != n) { \
LOG_ERROR("sf_write error: %s", sf_strerror(file)); \
break; \
} \
} \
return nw - count
sf_count_t SoundBase::write_file(SNDFILE* file, float* buf, size_t count)
{
WRITE_FILE(float, file, buf, count);
}
sf_count_t SoundBase::write_file(SNDFILE* file, double* buf, size_t count)
{
if (capture || !progdefaults.EnableMixer)
return sf_writef_double(file, buf, count);
else {
for (size_t n = 0; n < count; n++)
wrt_buffer[n] = buf[n] * progStatus.XmtMixer;
return sf_write_double(file, wrt_buffer, count);
}
WRITE_FILE(double, file, buf, count);
}
bool SoundBase::format_supported(int format)
{
@ -298,7 +315,7 @@ void SoundBase::tag_file(SNDFILE *sndfile, const char *title)
#if USE_OSS
#define MAXSC 32767.0
#define MAXSC 32767.0f
#define maxsc 32000.0
SoundOSS::SoundOSS(const char *dev ) {
@ -505,7 +522,7 @@ bool SoundOSS::reset_device()
return 1; /* sounddevice has been reset */
}
size_t SoundOSS::Read(double *buffer, size_t buffersize)
size_t SoundOSS::Read(float *buffer, size_t buffersize)
{
short int *ibuff = (short int *)cbuff;
int numread;
@ -952,7 +969,7 @@ void SoundPort::Abort(unsigned dir)
} while (0)
size_t SoundPort::Read(double *buf, size_t count)
size_t SoundPort::Read(float *buf, size_t count)
{
#if USE_SNDFILE
if (playback) {
@ -1018,9 +1035,13 @@ size_t SoundPort::Read(double *buf, size_t count)
sd[0].advance = 0;
}
// convert to double
for (size_t i = 0; i < count; i++)
buf[i] = rbuf[sd[0].params.channelCount * i];
if (sd[0].params.channelCount == 1)
memcpy(buf, rbuf, count * sizeof(float));
else {
// write first channel
for (size_t i = 0; i < count; i++)
buf[i] = rbuf[sd[0].params.channelCount * i];
}
#if USE_SNDFILE
if (capture)
@ -1719,7 +1740,7 @@ long SoundPulse::src_read_cb(void* arg, float** data)
return p->sd[0].blocksize;
}
size_t SoundPulse::Read(double *buf, size_t count)
size_t SoundPulse::Read(float *buf, size_t count)
{
#if USE_SNDFILE
if (playback) {
@ -1744,20 +1765,17 @@ size_t SoundPulse::Read(double *buf, size_t count)
size_t n = 0;
sd[0].blocksize = SCBLOCKSIZE;
while (n < count) {
if ((r = src_callback_read(rx_src_state, sd[0].src_ratio, count - n, fbuf + n)) == 0)
if ((r = src_callback_read(rx_src_state, sd[0].src_ratio, count - n, buf + n)) == 0)
return n;
n += r;
}
}
else {
int err;
if (pa_simple_read(sd[0].stream, fbuf, sizeof(float) * count, &err) == -1)
if (pa_simple_read(sd[0].stream, buf, sizeof(float) * count, &err) == -1)
throw SndPulseException(err);
}
for (size_t i = 0; i < count; i++)
buf[i] = fbuf[i];
#if USE_SNDFILE
if (capture)
write_file(ofCapture, buf, count);
@ -1815,7 +1833,7 @@ size_t SoundNull::Write_stereo(double* bufleft, double* bufright, size_t count)
return count;
}
size_t SoundNull::Read(double *buf, size_t count)
size_t SoundNull::Read(float *buf, size_t count)
{
#if USE_SNDFILE
if (playback) {

Wyświetl plik

@ -73,21 +73,20 @@ static int _trx_tune;
// Ringbuffer for the audio "history". A pointer into this buffer
// is also passed to the waterfall signal drawing routines.
#define NUMMEMBUFS 1024
ringbuffer<double> trxrb(ceil2(NUMMEMBUFS * SCBLOCKSIZE));
static ringbuffer<double> trxrb(ceil2(NUMMEMBUFS * SCBLOCKSIZE));
// Vector used for direct access to the ringbuffer
ringbuffer<double>::vector_type rbvec[2];
static ringbuffer<double>::vector_type rbvec[2];
static float fbuf[SCBLOCKSIZE];
bool bHistory = false;
static bool trxrunning = false;
static bool rsid_detecting = false;
#include "tune.cxx"
//=============================================================================
void trx_trx_receive_loop()
{
int numread;
size_t numread;
int current_samplerate;
assert(powerof2(SCBLOCKSIZE));
@ -126,56 +125,16 @@ void trx_trx_receive_loop()
active_modem->rx_init();
while (1) {
if (progdefaults.rsid == true && rsid_detecting == false) {
rsid_detecting = true;
try {
current_samplerate = RSID_SAMPLE_RATE;
scard->Open(O_RDONLY, current_samplerate);
}
catch (const SndException& e) {
LOG_ERROR("%s", e.what());
put_status(e.what(), 5);
scard->Close();
if (e.error() == EBUSY && progdefaults.btnAudioIOis == SND_IDX_PORT) {
sound_close();
sound_init();
}
MilliSleep(1000);
return;
}
}
if (progdefaults.rsid == false && rsid_detecting == true) {
rsid_detecting = false;
active_modem->rx_init();
try {
current_samplerate = active_modem->get_samplerate();
scard->Open(O_RDONLY, current_samplerate);
}
catch (const SndException& e) {
LOG_ERROR("%s", e.what());
put_status(e.what(), 5);
scard->Close();
if (e.error() == EBUSY && progdefaults.btnAudioIOis == SND_IDX_PORT) {
sound_close();
sound_init();
}
MilliSleep(1000);
return;
}
}
// If we change to an 8000Hz modem while RSID is on we'll never detect anything.
// Toggle rsid_detecting so that the audio device is reopened with the ReedSolomon
// samplerate in the next loop iteration.
if (progdefaults.rsid && rsid_detecting && current_samplerate != RSID_SAMPLE_RATE)
rsid_detecting = false;
try {
numread = 0;
while (numread < SCBLOCKSIZE && trx_state == STATE_RX)
numread += scard->Read(fbuf + numread, SCBLOCKSIZE - numread);
if (trxrb.write_space() == 0) // discard some old data
trxrb.read_advance(SCBLOCKSIZE);
trxrb.get_wv(rbvec);
numread = 0;
while (numread < SCBLOCKSIZE && trx_state == STATE_RX)
numread += scard->Read(rbvec[0].buf + numread, SCBLOCKSIZE - numread);
// convert to double and write to rb
for (size_t i = 0; i < numread; i++)
rbvec[0].buf[i] = fbuf[i];
}
catch (const SndException& e) {
scard->Close();
@ -191,10 +150,9 @@ void trx_trx_receive_loop()
REQ(&waterfall::sig_data, wf, rbvec[0].buf, numread, current_samplerate);
if (!bHistory) {
if (rsid_detecting == true)
ReedSolomon->search(rbvec[0].buf, numread);
else
active_modem->rx_process(rbvec[0].buf, numread);
active_modem->rx_process(rbvec[0].buf, numread);
if (progdefaults.rsid)
ReedSolomon->receive(fbuf, numread);
}
else {
bool afc = progStatus.afconoff;
@ -239,9 +197,9 @@ void trx_trx_transmit_loop()
push2talk->set(true);
active_modem->tx_init(scard);
if (progdefaults.TransmitRSid == true)
if (progdefaults.TransmitRSid)
ReedSolomon->send(true);
while (trx_state == STATE_TX) {
try {
if (active_modem->tx_process() < 0)
@ -256,10 +214,10 @@ void trx_trx_transmit_loop()
}
}
if (progdefaults.TransmitRSid == true)
if (progdefaults.TransmitRSid)
ReedSolomon->send(false);
scard->flush();
scard->flush();
if (scard->must_close())
scard->Close();
} else