Wave recording and playback now uses multi channels
This commit is contained in:
@@ -60,7 +60,9 @@ const char *write_tx_wave = NULL;
|
|||||||
const char *read_rx_wave = NULL;
|
const char *read_rx_wave = NULL;
|
||||||
static const char *sdr_args = "";
|
static const char *sdr_args = "";
|
||||||
double sdr_rx_gain = 0, sdr_tx_gain = 0;
|
double sdr_rx_gain = 0, sdr_tx_gain = 0;
|
||||||
|
const char *write_iq_rx_wave = NULL;
|
||||||
|
const char *write_iq_tx_wave = NULL;
|
||||||
|
const char *read_iq_rx_wave = NULL;
|
||||||
void print_help_common(const char *arg0, const char *ext_usage)
|
void print_help_common(const char *arg0, const char *ext_usage)
|
||||||
{
|
{
|
||||||
printf("Usage: %s -k <kanal/channel> %s[options] [station-id]\n", arg0, ext_usage);
|
printf("Usage: %s -k <kanal/channel> %s[options] [station-id]\n", arg0, ext_usage);
|
||||||
@@ -111,18 +113,25 @@ void print_help_common(const char *arg0, const char *ext_usage)
|
|||||||
printf(" -r --realtime <prio>\n");
|
printf(" -r --realtime <prio>\n");
|
||||||
printf(" Set prio: 0 to diable, 99 for maximum (default = %d)\n", rt_prio);
|
printf(" Set prio: 0 to diable, 99 for maximum (default = %d)\n", rt_prio);
|
||||||
printf(" --write-rx-wave <file>\n");
|
printf(" --write-rx-wave <file>\n");
|
||||||
printf(" Write received audio to given wav audio file.\n");
|
printf(" Write received audio to given wave file.\n");
|
||||||
printf(" --write-tx-wave <file>\n");
|
printf(" --write-tx-wave <file>\n");
|
||||||
printf(" Write transmitted audio to given wav audio file.\n");
|
printf(" Write transmitted audio to given wave file.\n");
|
||||||
printf(" --read-rx-wave <file>\n");
|
printf(" --read-rx-wave <file>\n");
|
||||||
printf(" Replace received audio by given wav audio file.\n");
|
printf(" Replace received audio by given wave file.\n");
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
|
printf("\nSDR options:\n");
|
||||||
printf(" --sdr-args <args>\n");
|
printf(" --sdr-args <args>\n");
|
||||||
printf(" Optional SDR device arguments\n");
|
printf(" Optional SDR device arguments\n");
|
||||||
printf(" --sdr-rx-gain <gain>\n");
|
printf(" --sdr-rx-gain <gain>\n");
|
||||||
printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_rx_gain);
|
printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_rx_gain);
|
||||||
printf(" --sdr-tx-gain <gain>\n");
|
printf(" --sdr-tx-gain <gain>\n");
|
||||||
printf(" SDR device's TX gain in dB (default = %.1f)\n", sdr_tx_gain);
|
printf(" SDR device's TX gain in dB (default = %.1f)\n", sdr_tx_gain);
|
||||||
|
printf(" --write-iq-rx-wave <file>\n");
|
||||||
|
printf(" Write received IQ data to given wave file.\n");
|
||||||
|
printf(" --write-iq-tx-wave <file>\n");
|
||||||
|
printf(" Write transmitted IQ data to given wave file.\n");
|
||||||
|
printf(" --read-iq-rx-wave <file>\n");
|
||||||
|
printf(" Replace received IQ data by given wave file.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +147,13 @@ void print_hotkeys_common(void)
|
|||||||
#define OPT_WRITE_RX_WAVE 1001
|
#define OPT_WRITE_RX_WAVE 1001
|
||||||
#define OPT_WRITE_TX_WAVE 1002
|
#define OPT_WRITE_TX_WAVE 1002
|
||||||
#define OPT_READ_RX_WAVE 1003
|
#define OPT_READ_RX_WAVE 1003
|
||||||
#define OPT_SDR_ARGS 1004
|
|
||||||
#define OPT_SDR_RX_GAIN 1005
|
#define OPT_SDR_ARGS 1100
|
||||||
#define OPT_SDR_TX_GAIN 1006
|
#define OPT_SDR_RX_GAIN 1101
|
||||||
|
#define OPT_SDR_TX_GAIN 1102
|
||||||
|
#define OPT_WRITE_IQ_RX_WAVE 1103
|
||||||
|
#define OPT_WRITE_IQ_TX_WAVE 1104
|
||||||
|
#define OPT_READ_IQ_RX_WAVE 1105
|
||||||
|
|
||||||
static struct option long_options_common[] = {
|
static struct option long_options_common[] = {
|
||||||
{"help", 0, 0, 'h'},
|
{"help", 0, 0, 'h'},
|
||||||
@@ -165,6 +178,9 @@ static struct option long_options_common[] = {
|
|||||||
{"sdr-args", 1, 0, OPT_SDR_ARGS},
|
{"sdr-args", 1, 0, OPT_SDR_ARGS},
|
||||||
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
|
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
|
||||||
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
|
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
|
||||||
|
{"write-iq-rx-wave", 1, 0, OPT_WRITE_IQ_RX_WAVE},
|
||||||
|
{"write-iq-tx-wave", 1, 0, OPT_WRITE_IQ_TX_WAVE},
|
||||||
|
{"read-iq-rx-wave", 1, 0, OPT_READ_IQ_RX_WAVE},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -316,6 +332,18 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
|
|||||||
sdr_tx_gain = atof(optarg);
|
sdr_tx_gain = atof(optarg);
|
||||||
*skip_args += 2;
|
*skip_args += 2;
|
||||||
break;
|
break;
|
||||||
|
case OPT_WRITE_IQ_RX_WAVE:
|
||||||
|
write_iq_rx_wave = strdup(optarg);
|
||||||
|
*skip_args += 2;
|
||||||
|
break;
|
||||||
|
case OPT_WRITE_IQ_TX_WAVE:
|
||||||
|
write_iq_tx_wave = strdup(optarg);
|
||||||
|
*skip_args += 2;
|
||||||
|
break;
|
||||||
|
case OPT_READ_IQ_RX_WAVE:
|
||||||
|
read_iq_rx_wave = strdup(optarg);
|
||||||
|
*skip_args += 2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
@@ -50,16 +50,20 @@ typedef struct sdr {
|
|||||||
int channels; /* number of frequencies */
|
int channels; /* number of frequencies */
|
||||||
double samplerate; /* IQ rate */
|
double samplerate; /* IQ rate */
|
||||||
double amplitude; /* amplitude of each carrier */
|
double amplitude; /* amplitude of each carrier */
|
||||||
|
wave_rec_t wave_rx_rec;
|
||||||
|
wave_rec_t wave_tx_rec;
|
||||||
|
wave_play_t wave_rx_play;
|
||||||
} sdr_t;
|
} sdr_t;
|
||||||
|
|
||||||
static const char *sdr_device_args;
|
static const char *sdr_device_args;
|
||||||
static double sdr_rx_gain, sdr_tx_gain;
|
static double sdr_rx_gain, sdr_tx_gain;
|
||||||
|
const char *sdr_write_iq_rx_wave, *sdr_write_iq_tx_wave, *sdr_read_iq_rx_wave;
|
||||||
|
|
||||||
#ifdef FAST_SINE
|
#ifdef FAST_SINE
|
||||||
static float sdr_sine[256];
|
static float sdr_sine[256];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int sdr_init(const char *device_args, double rx_gain, double tx_gain)
|
int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave)
|
||||||
{
|
{
|
||||||
#ifdef FAST_SINE
|
#ifdef FAST_SINE
|
||||||
int i;
|
int i;
|
||||||
@@ -72,6 +76,9 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain)
|
|||||||
sdr_device_args = strdup(device_args);
|
sdr_device_args = strdup(device_args);
|
||||||
sdr_rx_gain = rx_gain;
|
sdr_rx_gain = rx_gain;
|
||||||
sdr_tx_gain = tx_gain;
|
sdr_tx_gain = tx_gain;
|
||||||
|
sdr_write_iq_rx_wave = write_iq_rx_wave;
|
||||||
|
sdr_write_iq_tx_wave = write_iq_tx_wave;
|
||||||
|
sdr_read_iq_rx_wave = read_iq_rx_wave;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -181,6 +188,28 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
|||||||
}
|
}
|
||||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain);
|
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain);
|
||||||
|
|
||||||
|
if (sdr_write_iq_rx_wave) {
|
||||||
|
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sdr_write_iq_tx_wave) {
|
||||||
|
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sdr_read_iq_rx_wave) {
|
||||||
|
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
rc = uhd_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain);
|
rc = uhd_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain);
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -203,6 +232,9 @@ void sdr_close(void *inst)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sdr) {
|
if (sdr) {
|
||||||
|
wave_destroy_record(&sdr->wave_rx_rec);
|
||||||
|
wave_destroy_record(&sdr->wave_tx_rec);
|
||||||
|
wave_destroy_playback(&sdr->wave_rx_play);
|
||||||
free(sdr->chan);
|
free(sdr->chan);
|
||||||
free(sdr);
|
free(sdr);
|
||||||
sdr = NULL;
|
sdr = NULL;
|
||||||
@@ -258,6 +290,27 @@ int sdr_write(void *inst, int16_t **samples, int num, enum paging_signal __attri
|
|||||||
sdr->chan[c].tx_phase = phase;
|
sdr->chan[c].tx_phase = phase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdr->wave_tx_rec.fp) {
|
||||||
|
int16_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
||||||
|
for (s = 0, ss = 0; s < num; s++) {
|
||||||
|
if (buff[ss] >= 1.0)
|
||||||
|
spl[0][s] = 32767;
|
||||||
|
else if (buff[ss] <= -1.0)
|
||||||
|
spl[0][s] = -32767;
|
||||||
|
else
|
||||||
|
spl[0][s] = 32767.0 * buff[ss];
|
||||||
|
ss++;
|
||||||
|
if (buff[ss] >= 1.0)
|
||||||
|
spl[1][s] = 32767;
|
||||||
|
else if (buff[ss] <= -1.0)
|
||||||
|
spl[1][s] = -32767;
|
||||||
|
else
|
||||||
|
spl[1][s] = 32767.0 * buff[ss];
|
||||||
|
ss++;
|
||||||
|
}
|
||||||
|
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
sent = uhd_send(buff, num);
|
sent = uhd_send(buff, num);
|
||||||
#endif
|
#endif
|
||||||
@@ -284,6 +337,34 @@ int sdr_read(void *inst, int16_t **samples, int num, int channels)
|
|||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
|
if (sdr->wave_rx_rec.fp) {
|
||||||
|
int16_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||||
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
|
if (buff[ss] >= 1.0)
|
||||||
|
spl[0][s] = 32767;
|
||||||
|
else if (buff[ss] <= -1.0)
|
||||||
|
spl[0][s] = -32767;
|
||||||
|
else
|
||||||
|
spl[0][s] = 32767.0 * buff[ss];
|
||||||
|
ss++;
|
||||||
|
if (buff[ss] >= 1.0)
|
||||||
|
spl[1][s] = 32767;
|
||||||
|
else if (buff[ss] <= -1.0)
|
||||||
|
spl[1][s] = -32767;
|
||||||
|
else
|
||||||
|
spl[1][s] = 32767.0 * buff[ss];
|
||||||
|
ss++;
|
||||||
|
}
|
||||||
|
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
||||||
|
}
|
||||||
|
if (sdr->wave_rx_play.fp) {
|
||||||
|
int16_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||||
|
wave_read(&sdr->wave_rx_play, spl_list, count);
|
||||||
|
for (s = 0, ss = 0; s < count; s++) {
|
||||||
|
buff[ss++] = (double)spl[0][s] / 32767.0;
|
||||||
|
buff[ss++] = (double)spl[1][s] / 32767.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
display_iq(buff, count);
|
display_iq(buff, count);
|
||||||
|
|
||||||
for (c = 0; c < channels; c++) {
|
for (c = 0; c < channels; c++) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
int sdr_init(const char *device_args, double rx_gain, double tx_gain);
|
int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave);
|
||||||
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation);
|
void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation);
|
||||||
void sdr_close(void *inst);
|
void sdr_close(void *inst);
|
||||||
int sdr_write(void *inst, int16_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels);
|
int sdr_write(void *inst, int16_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels);
|
||||||
|
@@ -50,6 +50,9 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
|
|||||||
sender->loopback = loopback;
|
sender->loopback = loopback;
|
||||||
sender->loss_volume = loss_volume;
|
sender->loss_volume = loss_volume;
|
||||||
sender->paging_signal = paging_signal;
|
sender->paging_signal = paging_signal;
|
||||||
|
sender->write_rx_wave = write_rx_wave;
|
||||||
|
sender->write_tx_wave = write_tx_wave;
|
||||||
|
sender->read_rx_wave = read_rx_wave;
|
||||||
|
|
||||||
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Creating 'Sender' instance\n");
|
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Creating 'Sender' instance\n");
|
||||||
|
|
||||||
@@ -118,28 +121,6 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_rx_wave) {
|
|
||||||
rc = wave_create_record(&sender->wave_rx_rec, write_rx_wave, samplerate);
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (write_tx_wave) {
|
|
||||||
rc = wave_create_record(&sender->wave_tx_rec, write_tx_wave, samplerate);
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (read_rx_wave) {
|
|
||||||
rc = wave_create_playback(&sender->wave_rx_play, read_rx_wave, samplerate);
|
|
||||||
if (rc < 0) {
|
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = init_emphasis(&sender->estate, samplerate, CUT_OFF_EMPHASIS_DEFAULT);
|
rc = init_emphasis(&sender->estate, samplerate, CUT_OFF_EMPHASIS_DEFAULT);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -162,6 +143,7 @@ int sender_open_audio(void)
|
|||||||
int channels;
|
int channels;
|
||||||
double paging_frequency = 0.0;
|
double paging_frequency = 0.0;
|
||||||
int i;
|
int i;
|
||||||
|
int rc;
|
||||||
|
|
||||||
for (master = sender_head; master; master = master->next) {
|
for (master = sender_head; master; master = master->next) {
|
||||||
/* skip audio slaves */
|
/* skip audio slaves */
|
||||||
@@ -184,6 +166,28 @@ int sender_open_audio(void)
|
|||||||
paging_frequency = inst->ruffrequenz;
|
paging_frequency = inst->ruffrequenz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (master->write_rx_wave) {
|
||||||
|
rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (master->write_tx_wave) {
|
||||||
|
rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (master->read_rx_wave) {
|
||||||
|
rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* open device */
|
/* open device */
|
||||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation);
|
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation);
|
||||||
if (!master->audio) {
|
if (!master->audio) {
|
||||||
@@ -278,12 +282,8 @@ cant_recover:
|
|||||||
jitter_load(&inst->dejitter, samples[i], count);
|
jitter_load(&inst->dejitter, samples[i], count);
|
||||||
else
|
else
|
||||||
sender_send(inst, samples[i], count);
|
sender_send(inst, samples[i], count);
|
||||||
if (inst->wave_tx_rec.fp)
|
|
||||||
wave_write(&inst->wave_tx_rec, samples[i], count);
|
|
||||||
/* internal loopback: loop back TX audio to RX */
|
/* internal loopback: loop back TX audio to RX */
|
||||||
if (inst->loopback == 1) {
|
if (inst->loopback == 1) {
|
||||||
if (inst->wave_rx_rec.fp)
|
|
||||||
wave_write(&inst->wave_rx_rec, samples[i], count);
|
|
||||||
display_wave(inst, samples[i], count);
|
display_wave(inst, samples[i], count);
|
||||||
sender_receive(inst, samples[i], count);
|
sender_receive(inst, samples[i], count);
|
||||||
}
|
}
|
||||||
@@ -295,6 +295,9 @@ cant_recover:
|
|||||||
on[i] = sender->paging_on;
|
on[i] = sender->paging_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sender->wave_tx_rec.fp)
|
||||||
|
wave_write(&sender->wave_tx_rec, samples, count);
|
||||||
|
|
||||||
rc = sender->audio_write(sender->audio, samples, count, paging_signal, on, num_chan);
|
rc = sender->audio_write(sender->audio, samples, count, paging_signal, on, num_chan);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
|
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc);
|
||||||
@@ -324,6 +327,11 @@ transmit_later:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
|
if (sender->wave_rx_rec.fp)
|
||||||
|
wave_write(&sender->wave_rx_rec, samples, count);
|
||||||
|
if (sender->wave_rx_play.fp)
|
||||||
|
wave_read(&sender->wave_rx_play, samples, count);
|
||||||
|
|
||||||
/* loop through all channels */
|
/* loop through all channels */
|
||||||
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
||||||
/* rx gain */
|
/* rx gain */
|
||||||
@@ -332,11 +340,7 @@ transmit_later:
|
|||||||
/* do de emphasis from radio (then write_wave/wave_read), receive audio, process echo test */
|
/* do de emphasis from radio (then write_wave/wave_read), receive audio, process echo test */
|
||||||
if (inst->de_emphasis)
|
if (inst->de_emphasis)
|
||||||
de_emphasis(&inst->estate, samples[i], count);
|
de_emphasis(&inst->estate, samples[i], count);
|
||||||
if (inst->wave_rx_play.fp)
|
|
||||||
wave_read(&inst->wave_rx_play, samples[i], count);
|
|
||||||
if (inst->loopback != 1) {
|
if (inst->loopback != 1) {
|
||||||
if (inst->wave_rx_rec.fp)
|
|
||||||
wave_write(&inst->wave_rx_rec, samples[i], count);
|
|
||||||
display_wave(inst, samples[i], count);
|
display_wave(inst, samples[i], count);
|
||||||
sender_receive(inst, samples[i], count);
|
sender_receive(inst, samples[i], count);
|
||||||
}
|
}
|
||||||
|
@@ -53,6 +53,9 @@ typedef struct sender {
|
|||||||
int loopback; /* 0 = off, 1 = internal, 2 = external */
|
int loopback; /* 0 = off, 1 = internal, 2 = external */
|
||||||
|
|
||||||
/* record and playback */
|
/* record and playback */
|
||||||
|
const char *write_rx_wave; /* file name pointers */
|
||||||
|
const char *write_tx_wave;
|
||||||
|
const char *read_rx_wave;
|
||||||
wave_rec_t wave_rx_rec; /* wave recording (from rx) */
|
wave_rec_t wave_rx_rec; /* wave recording (from rx) */
|
||||||
wave_rec_t wave_tx_rec; /* wave recording (from tx) */
|
wave_rec_t wave_tx_rec; /* wave recording (from tx) */
|
||||||
wave_play_t wave_rx_play; /* wave playback (as rx) */
|
wave_play_t wave_rx_play; /* wave playback (as rx) */
|
||||||
|
@@ -33,7 +33,7 @@ struct fmt {
|
|||||||
uint16_t bits_sample; /* bits per sample (one channel) */
|
uint16_t bits_sample; /* bits per sample (one channel) */
|
||||||
};
|
};
|
||||||
|
|
||||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate)
|
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels)
|
||||||
{
|
{
|
||||||
/* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
|
/* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
|
||||||
char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
|
char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
|
||||||
@@ -41,6 +41,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate)
|
|||||||
|
|
||||||
memset(rec, 0, sizeof(*rec));
|
memset(rec, 0, sizeof(*rec));
|
||||||
rec->samplerate = samplerate;
|
rec->samplerate = samplerate;
|
||||||
|
rec->channels = channels;
|
||||||
|
|
||||||
rec->fp = fopen(filename, "w");
|
rec->fp = fopen(filename, "w");
|
||||||
if (!rec->fp) {
|
if (!rec->fp) {
|
||||||
@@ -56,7 +57,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate)
|
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels)
|
||||||
{
|
{
|
||||||
uint8_t buffer[256];
|
uint8_t buffer[256];
|
||||||
struct fmt fmt;
|
struct fmt fmt;
|
||||||
@@ -65,6 +66,7 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate
|
|||||||
int rc = -EINVAL;
|
int rc = -EINVAL;
|
||||||
|
|
||||||
memset(play, 0, sizeof(*play));
|
memset(play, 0, sizeof(*play));
|
||||||
|
play->channels = channels;
|
||||||
|
|
||||||
play->fp = fopen(filename, "r");
|
play->fp = fopen(filename, "r");
|
||||||
if (!play->fp) {
|
if (!play->fp) {
|
||||||
@@ -153,8 +155,8 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate
|
|||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (fmt.channels != 1) {
|
if (fmt.channels !=channels) {
|
||||||
fprintf(stderr, "WAVE error: We support only mono files!\n");
|
fprintf(stderr, "WAVE error: We expect %d cannel(s), but wave file only has %d channel(s)\n", channels, fmt.channels);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -163,13 +165,23 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate
|
|||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if ((int)fmt.data_rate != 2 * channels * samplerate) {
|
||||||
|
fprintf(stderr, "WAVE error: The WAVE file's data rate is only %d bytes per second, but we expect %d bytes per second (2 bytes per sample * channels * samplerate)!\n", fmt.data_rate, 2 * channels * samplerate);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (fmt.bytes_sample != 2 * channels) {
|
||||||
|
fprintf(stderr, "WAVE error: The WAVE file's bytes per sample is only %d, but we expect %d bytes sample (2 bytes per sample * channels)!\n", fmt.bytes_sample, 2 * channels);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (fmt.bits_sample != 16) {
|
if (fmt.bits_sample != 16) {
|
||||||
fprintf(stderr, "WAVE error: We support only 16 bit files!\n");
|
fprintf(stderr, "WAVE error: We support only 16 bit files!\n");
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
play->left = chunk >> 1;
|
play->left = chunk / 2 / channels;
|
||||||
|
|
||||||
printf("*** Replacing received audio by %s.\n", filename);
|
printf("*** Replacing received audio by %s.\n", filename);
|
||||||
|
|
||||||
@@ -181,14 +193,15 @@ error:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wave_read(wave_play_t *play, int16_t *samples, int length)
|
int wave_read(wave_play_t *play, int16_t **samples, int length)
|
||||||
{
|
{
|
||||||
uint8_t *buffer = (uint8_t *)samples;
|
uint8_t buff[2 * length * play->channels];
|
||||||
int __attribute__((__unused__)) len;
|
int __attribute__((__unused__)) len;
|
||||||
int i;
|
int i, j, c;
|
||||||
|
|
||||||
if (length > (int)play->left) {
|
if (length > (int)play->left) {
|
||||||
memset(samples, 0, length << 1);
|
for (c = 0; c < play->channels; c++)
|
||||||
|
memset(samples[c], 0, 2 * length);
|
||||||
length = play->left;
|
length = play->left;
|
||||||
}
|
}
|
||||||
if (!length)
|
if (!length)
|
||||||
@@ -199,28 +212,31 @@ int wave_read(wave_play_t *play, int16_t *samples, int length)
|
|||||||
printf("*** Finished reading WAVE file.\n");
|
printf("*** Finished reading WAVE file.\n");
|
||||||
|
|
||||||
/* read and correct endiness */
|
/* read and correct endiness */
|
||||||
len = fread(samples, 1, length << 1, play->fp);
|
len = fread(buff, 1, 2 * length * play->channels, play->fp);
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0, j = 0; i < length; i++) {
|
||||||
*samples++ = buffer[0] + (buffer[1] << 8);
|
for (c = 0; c < play->channels; c++) {
|
||||||
buffer += 2;
|
samples[c][i] = buff[j] + (buff[j + 1] << 8);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wave_write(wave_rec_t *rec, int16_t *samples, int length)
|
int wave_write(wave_rec_t *rec, int16_t **samples, int length)
|
||||||
{
|
{
|
||||||
uint8_t buffer[length << 1];
|
uint8_t buff[2 * length * rec->channels];
|
||||||
int __attribute__((__unused__)) len;
|
int __attribute__((__unused__)) len;
|
||||||
int i, j;
|
int i, j, c;
|
||||||
|
|
||||||
/* write and correct endiness */
|
/* write and correct endiness */
|
||||||
for (i = 0, j = 0; i < length; i++) {
|
for (i = 0, j = 0; i < length; i++) {
|
||||||
buffer[j++] = *samples;
|
for (c = 0; c < rec->channels; c++) {
|
||||||
buffer[j++] = (*samples) >> 8;
|
buff[j++] = samples[c][i];
|
||||||
samples++;
|
buff[j++] = samples[c][i] >> 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
len = fwrite(buffer, 1, length << 1, rec->fp);
|
len = fwrite(buff, 1, 2 * length * rec->channels, rec->fp);
|
||||||
rec->written += length;
|
rec->written += length;
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
@@ -245,7 +261,7 @@ void wave_destroy_record(wave_rec_t *rec)
|
|||||||
/* go to header */
|
/* go to header */
|
||||||
fseek(rec->fp, 0, SEEK_SET);
|
fseek(rec->fp, 0, SEEK_SET);
|
||||||
|
|
||||||
size = rec->written << 1;
|
size = 2 * rec->written * rec->channels;
|
||||||
wsize = 4 + 8 + sizeof(fmt) + 8 + size + 8 + 4 + 8 + 4;
|
wsize = 4 + 8 + sizeof(fmt) + 8 + size + 8 + 4 + 8 + 4;
|
||||||
|
|
||||||
/* RIFF */
|
/* RIFF */
|
||||||
@@ -257,10 +273,10 @@ void wave_destroy_record(wave_rec_t *rec)
|
|||||||
/* fmt */
|
/* fmt */
|
||||||
fprintf(rec->fp, "fmt %c%c%c%c", (uint8_t)sizeof(fmt), 0, 0, 0);
|
fprintf(rec->fp, "fmt %c%c%c%c", (uint8_t)sizeof(fmt), 0, 0, 0);
|
||||||
fmt.format = 1;
|
fmt.format = 1;
|
||||||
fmt.channels = 1;
|
fmt.channels = rec->channels;
|
||||||
fmt.sample_rate = rec->samplerate; /* samples/sec */
|
fmt.sample_rate = rec->samplerate; /* samples/sec */
|
||||||
fmt.data_rate = rec->samplerate * 2; /* full data rate */
|
fmt.data_rate = rec->samplerate * 2 * rec->channels; /* full data rate */
|
||||||
fmt.bytes_sample = 2; /* all channels */
|
fmt.bytes_sample = 2 * rec->channels; /* all channels */
|
||||||
fmt.bits_sample = 16; /* one channel */
|
fmt.bits_sample = 16; /* one channel */
|
||||||
buffer[0] = fmt.format;
|
buffer[0] = fmt.format;
|
||||||
buffer[1] = fmt.format >> 8;
|
buffer[1] = fmt.format >> 8;
|
||||||
|
@@ -1,19 +1,21 @@
|
|||||||
|
|
||||||
typedef struct wave_rec {
|
typedef struct wave_rec {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
int channels;
|
||||||
int samplerate;
|
int samplerate;
|
||||||
uint32_t written; /* how much samples written */
|
uint32_t written; /* how much samples written */
|
||||||
} wave_rec_t;
|
} wave_rec_t;
|
||||||
|
|
||||||
typedef struct wave_play {
|
typedef struct wave_play {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
int channels;
|
||||||
uint32_t left; /* how much samples left */
|
uint32_t left; /* how much samples left */
|
||||||
} wave_play_t;
|
} wave_play_t;
|
||||||
|
|
||||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate);
|
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels);
|
||||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate);
|
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels);
|
||||||
int wave_read(wave_play_t *play, int16_t *samples, int length);
|
int wave_read(wave_play_t *play, int16_t **samples, int length);
|
||||||
int wave_write(wave_rec_t *rec, int16_t *samples, int length);
|
int wave_write(wave_rec_t *rec, int16_t **samples, int length);
|
||||||
void wave_destroy_record(wave_rec_t *rec);
|
void wave_destroy_record(wave_rec_t *rec);
|
||||||
void wave_destroy_playback(wave_play_t *play);
|
void wave_destroy_playback(wave_play_t *play);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user