aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2016-03-25 13:58:16 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2016-03-27 17:56:04 +0200
commit1146537d849c30aa20a4cb742cdd18654f041a8d (patch)
tree9cdc0a47669fc5d4ece4c77972308a7f1de81048 /src
parent0aa749d27b1c95997a6e324694a7e624988faacc (diff)
common code: Add feature to record received audio and replay it
-W <file.wav> writes a wave file of received audio -R <file.wav> reads a wave file to feed into decoder This way you can record a phone and later debug without a phone and radio equipment.
Diffstat (limited to 'src')
-rw-r--r--src/anetz/anetz.c4
-rw-r--r--src/anetz/anetz.h2
-rw-r--r--src/anetz/main.c2
-rw-r--r--src/bnetz/bnetz.c4
-rw-r--r--src/bnetz/bnetz.h2
-rw-r--r--src/bnetz/main.c2
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/main.h2
-rw-r--r--src/common/main_common.c18
-rw-r--r--src/common/sender.c32
-rw-r--r--src/common/sender.h7
-rw-r--r--src/common/wave.c300
-rw-r--r--src/common/wave.h19
-rw-r--r--src/nmt/main.c2
-rw-r--r--src/nmt/nmt.c4
-rw-r--r--src/nmt/nmt.h2
16 files changed, 386 insertions, 17 deletions
diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c
index 5b4d0b3..8d965fe 100644
--- a/src/anetz/anetz.c
+++ b/src/anetz/anetz.c
@@ -137,7 +137,7 @@ static void anetz_timeout(struct timer *timer);
static void anetz_go_idle(anetz_t *anetz);
/* Create transceiver instance and link to a list. */
-int anetz_create(const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume)
+int anetz_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int loopback, double loss_volume)
{
anetz_t *anetz;
int rc;
@@ -156,7 +156,7 @@ int anetz_create(const char *sounddev, int samplerate, int kanal, int loopback,
PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
/* init general part of transceiver */
- rc = sender_create(&anetz->sender, sounddev, samplerate, kanal, loopback, loss_volume, -1);
+ rc = sender_create(&anetz->sender, sounddev, samplerate, write_wave, read_wave, kanal, loopback, loss_volume, -1);
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n");
goto error;
diff --git a/src/anetz/anetz.h b/src/anetz/anetz.h
index 5400016..a8a4382 100644
--- a/src/anetz/anetz.h
+++ b/src/anetz/anetz.h
@@ -41,7 +41,7 @@ typedef struct anetz {
double anetz_kanal2freq(int kanal, int unterband);
int anetz_init(void);
-int anetz_create(const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume);
+int anetz_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int loopback, double loss_volume);
void anetz_destroy(sender_t *sender);
void anetz_loss_indication(anetz_t *anetz);
void anetz_receive_tone(anetz_t *anetz, int bit);
diff --git a/src/anetz/main.c b/src/anetz/main.c
index 59a3f23..fce3df5 100644
--- a/src/anetz/main.c
+++ b/src/anetz/main.c
@@ -142,7 +142,7 @@ int main(int argc, char *argv[])
}
/* create transceiver instance */
- rc = anetz_create(sounddev, samplerate, kanal, loopback, lossdetect / 100.0);
+ rc = anetz_create(sounddev, samplerate, write_wave, read_wave, kanal, loopback, lossdetect / 100.0);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;
diff --git a/src/bnetz/bnetz.c b/src/bnetz/bnetz.c
index 9819211..7829590 100644
--- a/src/bnetz/bnetz.c
+++ b/src/bnetz/bnetz.c
@@ -242,7 +242,7 @@ static void bnetz_timeout(struct timer *timer);
static void bnetz_go_idle(bnetz_t *bnetz);
/* Create transceiver instance and link to a list. */
-int bnetz_create(const char *sounddev, int samplerate, int kanal, int gfs, int loopback, double loss_factor, const char *pilot)
+int bnetz_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int gfs, int loopback, double loss_factor, const char *pilot)
{
bnetz_t *bnetz;
int use_pilot_tone = -1;
@@ -300,7 +300,7 @@ error_pilot:
PDEBUG(DBNETZ, DEBUG_DEBUG, "Creating 'B-Netz' instance for 'Kanal' = %d 'Gruppenfreisignal' = %d (sample rate %d).\n", kanal, gfs, samplerate);
/* init general part of transceiver */
- rc = sender_create(&bnetz->sender, sounddev, samplerate, kanal, loopback, loss_factor, use_pilot_tone);
+ rc = sender_create(&bnetz->sender, sounddev, samplerate, write_wave, read_wave, kanal, loopback, loss_factor, use_pilot_tone);
if (rc < 0) {
PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
goto error;
diff --git a/src/bnetz/bnetz.h b/src/bnetz/bnetz.h
index 3eed7c8..1d9ddd3 100644
--- a/src/bnetz/bnetz.h
+++ b/src/bnetz/bnetz.h
@@ -90,7 +90,7 @@ typedef struct bnetz {
double bnetz_kanal2freq(int kanal, int unterband);
int bnetz_init(void);
-int bnetz_create(const char *sounddev, int samplerate, int kanal, int gfs, int loopback, double loss_volume, const char *pilot);
+int bnetz_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int gfs, int loopback, double loss_volume, const char *pilot);
void bnetz_destroy(sender_t *sender);
void bnetz_loss_indication(bnetz_t *bnetz);
void bnetz_receive_tone(bnetz_t *bnetz, int bit);
diff --git a/src/bnetz/main.c b/src/bnetz/main.c
index a788529..fe0c5b5 100644
--- a/src/bnetz/main.c
+++ b/src/bnetz/main.c
@@ -154,7 +154,7 @@ int main(int argc, char *argv[])
}
/* create transceiver instance */
- rc = bnetz_create(sounddev, samplerate, kanal, gfs, loopback, (double)lossdetect / 100.0, pilot);
+ rc = bnetz_create(sounddev, samplerate, write_wave, read_wave, kanal, gfs, loopback, (double)lossdetect / 100.0, pilot);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index c6a90e9..0d3baa3 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -6,6 +6,7 @@ libcommon_a_SOURCES = \
../common/debug.c \
../common/timer.c \
../common/sound_alsa.c \
+ ../common/wave.c \
../common/goertzel.c \
../common/jitter.c \
../common/loss.c \
diff --git a/src/common/main.h b/src/common/main.h
index 54c4fe3..fc4f01f 100644
--- a/src/common/main.h
+++ b/src/common/main.h
@@ -8,6 +8,8 @@ extern int use_mncc_sock;
extern int send_patterns;
extern int loopback;
extern int rt_prio;
+extern const char *read_wave;
+extern const char *write_wave;
void print_help(const char *arg0);
void print_help_common(const char *arg0, const char *ext_usage);
diff --git a/src/common/main_common.c b/src/common/main_common.c
index 47a3ca3..c634f7e 100644
--- a/src/common/main_common.c
+++ b/src/common/main_common.c
@@ -36,6 +36,8 @@ int use_mncc_sock = 0;
int send_patterns = 1;
int loopback = 0;
int rt_prio = 0;
+const char *read_wave = NULL;
+const char *write_wave = NULL;
void print_help_common(const char *arg0, const char *ext_usage)
{
@@ -64,6 +66,10 @@ void print_help_common(const char *arg0, const char *ext_usage)
printf(" Loopback test: 1 = internal | 2 = external | 3 = echo\n");
printf(" -r --realtime <prio>\n");
printf(" Set prio: 0 to diable, 99 for maximum (default = %d)\n", rt_prio);
+ printf(" -W --write-wave <file>\n");
+ printf(" Write received audio to given wav audio file.\n");
+ printf(" -R --read-wave <file>\n");
+ printf(" Replace received audio by given wav audio file.\n");
}
static struct option long_options_common[] = {
@@ -78,10 +84,12 @@ static struct option long_options_common[] = {
{"send-patterns", 0, 0, 'p'},
{"loopback", 1, 0, 'L'},
{"realtime", 1, 0, 'r'},
+ {"write-wave", 1, 0, 'W'},
+ {"read-wave", 1, 0, 'R'},
{0, 0, 0, 0}
};
-const char *optstring_common = "hD:k:d:s:c:l:mp:L:r:";
+const char *optstring_common = "hD:k:d:s:c:l:mp:L:r:W:R:";
struct option *long_options;
char *optstring;
@@ -151,6 +159,14 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
rt_prio = atoi(optarg);
*skip_args += 2;
break;
+ case 'W':
+ write_wave = strdup(optarg);
+ *skip_args += 2;
+ break;
+ case 'R':
+ read_wave = strdup(optarg);
+ *skip_args += 2;
+ break;
default:
exit (0);
}
diff --git a/src/common/sender.c b/src/common/sender.c
index 97abcdc..5f14a25 100644
--- a/src/common/sender.c
+++ b/src/common/sender.c
@@ -32,7 +32,7 @@ sender_t *sender_head = NULL;
static sender_t **sender_tailp = &sender_head;
/* Init transceiver instance and link to list of transceivers. */
-int sender_create(sender_t *sender, const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume, int use_pilot_signal)
+int sender_create(sender_t *sender, const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int loopback, double loss_volume, int use_pilot_signal)
{
int rc = 0;
@@ -65,6 +65,21 @@ int sender_create(sender_t *sender, const char *sounddev, int samplerate, int ka
goto error;
}
+ if (write_wave) {
+ rc = wave_create_record(&sender->wave_rec, write_wave, samplerate);
+ if (rc < 0) {
+ PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
+ goto error;
+ }
+ }
+ if (read_wave) {
+ rc = wave_create_playback(&sender->wave_play, read_wave, samplerate);
+ if (rc < 0) {
+ PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
+ goto error;
+ }
+ }
+
*sender_tailp = sender;
sender_tailp = &sender->next;
@@ -90,6 +105,9 @@ void sender_destroy(sender_t *sender)
if (sender->sound)
sound_close(sender->sound);
+ wave_destroy_record(&sender->wave_rec);
+ wave_destroy_playback(&sender->wave_play);
+
jitter_destroy(&sender->audio);
}
@@ -167,8 +185,11 @@ void process_sender(sender_t *sender, int latspl)
PDEBUG(DSENDER, DEBUG_ERROR, "Trying to recover!\n");
return;
}
- if (sender->loopback == 1)
+ if (sender->loopback == 1) {
+ if (sender->wave_rec.fp)
+ wave_write(&sender->wave_rec, samples, count);
sender_receive(sender, samples, count);
+ }
}
count = sound_read(sender->sound, samples, latspl);
@@ -180,8 +201,13 @@ void process_sender(sender_t *sender, int latspl)
return;
}
if (count) {
- if (sender->loopback != 1)
+ if (sender->wave_play.fp)
+ wave_read(&sender->wave_play, samples, count);
+ if (sender->loopback != 1) {
+ if (sender->wave_rec.fp)
+ wave_write(&sender->wave_rec, samples, count);
sender_receive(sender, samples, count);
+ }
if (sender->loopback == 3) {
jitter_save(&sender->audio, samples, count);
}
diff --git a/src/common/sender.h b/src/common/sender.h
index e01f97d..795a055 100644
--- a/src/common/sender.h
+++ b/src/common/sender.h
@@ -1,4 +1,5 @@
#include "sound.h"
+#include "wave.h"
#include "samplerate.h"
#include "jitter.h"
#include "loss.h"
@@ -21,6 +22,10 @@ typedef struct sender {
/* loopback test */
int loopback; /* 0 = off, 1 = internal, 2 = external */
+ /* record and playback */
+ wave_rec_t wave_rec; /* wave recording */
+ wave_play_t wave_play; /* wave playback */
+
/* audio buffer for audio to send to transmitter (also used as loopback buffer) */
jitter_t audio;
@@ -42,7 +47,7 @@ typedef struct sender {
/* list of all senders */
extern sender_t *sender_head;
-int sender_create(sender_t *sender, const char *sounddev, int samplerate, int kanal, int loopback, double loss_volume, int use_pilot_signal);
+int sender_create(sender_t *sender, const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int kanal, int loopback, double loss_volume, int use_pilot_signal);
void sender_destroy(sender_t *sender);
void sender_send(sender_t *sender, int16_t *samples, int count);
void sender_receive(sender_t *sender, int16_t *samples, int count);
diff --git a/src/common/wave.c b/src/common/wave.c
new file mode 100644
index 0000000..572f989
--- /dev/null
+++ b/src/common/wave.c
@@ -0,0 +1,300 @@
+/* wave recording and playback functions
+ *
+ * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "wave.h"
+
+struct fmt {
+ uint16_t format; /* 1 = pcm, 2 = adpcm */
+ uint16_t channels; /* number of channels */
+ uint32_t sample_rate; /* sample rate */
+ uint32_t data_rate; /* data rate */
+ uint16_t bytes_sample; /* bytes per sample (all channels) */
+ uint16_t bits_sample; /* bits per sample (one channel) */
+};
+
+int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate)
+{
+ /* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
+ char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
+ int __attribute__((__unused__)) len;
+
+ memset(rec, 0, sizeof(*rec));
+ rec->samplerate = samplerate;
+
+ rec->fp = fopen(filename, "w");
+ if (!rec->fp) {
+ fprintf(stderr, "Failed to open recording file '%s'! (errno %d)\n", filename, errno);
+ return -errno;
+ }
+
+ memset(&dummyheader, 0, sizeof(dummyheader));
+ len = fwrite(dummyheader, 1, sizeof(dummyheader), rec->fp);
+
+ printf("*** Writing received audio to %s.\n", filename);
+
+ return 0;
+}
+
+int wave_create_playback(wave_play_t *play, const char *filename, int samplerate)
+{
+ uint8_t buffer[256];
+ struct fmt fmt;
+ uint32_t size, chunk, len;
+ int gotfmt = 0, gotdata = 0;
+ int rc = -EINVAL;
+
+ memset(play, 0, sizeof(*play));
+
+ play->fp = fopen(filename, "r");
+ if (!play->fp) {
+ fprintf(stderr, "Failed to open playback file '%s'! (errno %d)\n", filename, errno);
+ return -errno;
+ }
+
+ len = fread(buffer, 1, 12, play->fp);
+ if (len != 12) {
+ fprintf(stderr, "Failed to read RIFF header!\n");
+ rc = -EIO;
+ goto error;
+ }
+ if (!!strncmp((char *)buffer, "RIFF", 4)) {
+ fprintf(stderr, "Missing RIFF header, seems that this is no WAVE file!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ size = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24);
+ if (!!strncmp((char *)buffer + 8, "WAVE", 4)) {
+ fprintf(stderr, "Missing WAVE header, seems that this is no WAVE file!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ size -= 4;
+ while (size) {
+ if (size < 8) {
+ fprintf(stderr, "Short read of WAVE file!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ len = fread(buffer, 1, 8, play->fp);
+ if (len != 8) {
+ fprintf(stderr, "Failed to read chunk of WAVE file!\n");
+ rc = -EIO;
+ goto error;
+ }
+ chunk = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24);
+ size -= 8 + chunk;
+ if (size < 0) {
+ fprintf(stderr, "WAVE error: Chunk '%c%c%c%c' overflows file size!\n", buffer[4], buffer[5], buffer[6], buffer[7]);
+ rc = -EIO;
+ goto error;
+ }
+ if (!strncmp((char *)buffer, "fmt ", 4)) {
+ if (chunk < 16 || chunk > sizeof(buffer)) {
+ fprintf(stderr, "WAVE error: Short or corrupt 'fmt' chunk!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ len = fread(buffer, 1, chunk, play->fp);
+ fmt.format = buffer[0] + (buffer[1] << 8);
+ fmt.channels = buffer[2] + (buffer[3] << 8);
+ fmt.sample_rate = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24);
+ fmt.data_rate = buffer[8] + (buffer[9] << 8) + (buffer[10] << 16) + (buffer[11] << 24);
+ fmt.bytes_sample = buffer[12] + (buffer[13] << 8);
+ fmt.bits_sample = buffer[14] + (buffer[15] << 8);
+ gotfmt = 1;
+ } else
+ if (!strncmp((char *)buffer, "data", 4)) {
+ if (!gotfmt) {
+ fprintf(stderr, "WAVE error: 'data' without 'fmt' chunk!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ gotdata = 1;
+ break;
+ } else {
+ while(chunk > sizeof(buffer)) {
+ len = fread(buffer, 1, sizeof(buffer), play->fp);
+ chunk -= sizeof(buffer);
+ }
+ if (chunk)
+ len = fread(buffer, 1, chunk, play->fp);
+ }
+ }
+
+ if (!gotfmt || !gotdata) {
+ fprintf(stderr, "WAVE error: Missing 'data' or 'fmt' chunk!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (fmt.format != 1) {
+ fprintf(stderr, "WAVE error: We support only PCM files!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ if (fmt.channels != 1) {
+ fprintf(stderr, "WAVE error: We support only mono files!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+ if (fmt.sample_rate != samplerate) {
+ fprintf(stderr, "WAVE error: The WAVE file's sample rate (%d) does not match our sample rate (%d)!\n", fmt.sample_rate, samplerate);
+ rc = -EINVAL;
+ goto error;
+ }
+ if (fmt.bits_sample != 16) {
+ fprintf(stderr, "WAVE error: We support only 16 bit files!\n");
+ rc = -EINVAL;
+ goto error;
+ }
+
+ play->left = chunk >> 1;
+
+ printf("*** Replacing received audio by %s.\n", filename);
+
+ return 0;
+
+error:
+ fclose(play->fp);
+ play->fp = NULL;
+ return rc;
+}
+
+int wave_read(wave_play_t *play, int16_t *samples, int length)
+{
+ uint8_t *buffer = (uint8_t *)samples;
+ int __attribute__((__unused__)) len;
+ int i;
+
+ if (length > play->left) {
+ memset(samples, 0, length << 1);
+ length = play->left;
+ }
+ if (!length)
+ return length;
+
+ play->left -= length;
+ if (!play->left)
+ printf("*** Finished reading WAVE file.\n");
+
+ /* read and correct endiness */
+ len = fread(samples, 1, length << 1, play->fp);
+ for (i = 0; i < length; i++) {
+ *samples++ = buffer[0] + (buffer[1] << 8);
+ buffer += 2;
+ }
+
+ return length;
+}
+
+int wave_write(wave_rec_t *rec, int16_t *samples, int length)
+{
+ uint8_t buffer[length << 1];
+ int __attribute__((__unused__)) len;
+ int i, j;
+
+ /* write and correct endiness */
+ for (i = 0, j = 0; i < length; i++) {
+ buffer[j++] = *samples;
+ buffer[j++] = (*samples) >> 8;
+ samples++;
+ }
+ len = fwrite(buffer, 1, length << 1, rec->fp);
+ rec->written += length;
+
+ return length;
+}
+
+void wave_destroy_record(wave_rec_t *rec)
+{
+ uint8_t buffer[256];
+ uint32_t size, wsize;
+ struct fmt fmt;
+ int __attribute__((__unused__)) len;
+
+ if (!rec->fp)
+ return;
+
+ /* cue */
+ fprintf(rec->fp, "cue %c%c%c%c%c%c%c%c", 4, 0, 0, 0, 0,0,0,0);
+
+ /* LIST */
+ fprintf(rec->fp, "LIST%c%c%c%cadtl", 4, 0, 0, 0);
+
+ /* go to header */
+ fseek(rec->fp, 0, SEEK_SET);
+
+ size = rec->written << 1;
+ wsize = 4 + 8 + sizeof(fmt) + 8 + size + 8 + 4 + 8 + 4;
+
+ /* RIFF */
+ fprintf(rec->fp, "RIFF%c%c%c%c", wsize & 0xff, (wsize >> 8) & 0xff, (wsize >> 16) & 0xff, wsize >> 24);
+
+ /* WAVE */
+ fprintf(rec->fp, "WAVE");
+
+ /* fmt */
+ fprintf(rec->fp, "fmt %c%c%c%c", (uint8_t)sizeof(fmt), 0, 0, 0);
+ fmt.format = 1;
+ fmt.channels = 1;
+ fmt.sample_rate = rec->samplerate; /* samples/sec */
+ fmt.data_rate = rec->samplerate * 2; /* full data rate */
+ fmt.bytes_sample = 2; /* all channels */
+ fmt.bits_sample = 16; /* one channel */
+ buffer[0] = fmt.format;
+ buffer[1] = fmt.format >> 8;
+ buffer[2] = fmt.channels;
+ buffer[3] = fmt.channels >> 8;
+ buffer[4] = fmt.sample_rate;
+ buffer[5] = fmt.sample_rate >> 8;
+ buffer[6] = fmt.sample_rate >> 16;
+ buffer[7] = fmt.sample_rate >> 24;
+ buffer[8] = fmt.data_rate;
+ buffer[9] = fmt.data_rate >> 8;
+ buffer[10] = fmt.data_rate >> 16;
+ buffer[11] = fmt.data_rate >> 24;
+ buffer[12] = fmt.bytes_sample;
+ buffer[13] = fmt.bytes_sample >> 8;
+ buffer[14] = fmt.bits_sample;
+ buffer[15] = fmt.bits_sample >> 8;
+ len = fwrite(buffer, 1, sizeof(fmt), rec->fp);
+
+ /* data */
+ fprintf(rec->fp, "data%c%c%c%c", size & 0xff, (size >> 8) & 0xff, (size >> 16) & 0xff, size >> 24);
+
+ fclose(rec->fp);
+ rec->fp = NULL;
+
+ printf("*** Received audio is written to WAVE file.\n");
+}
+
+void wave_destroy_playback(wave_play_t *play)
+{
+ if (!play->fp)
+ return;
+
+ fclose(play->fp);
+ play->fp = NULL;
+}
+
diff --git a/src/common/wave.h b/src/common/wave.h
new file mode 100644
index 0000000..b9575d6
--- /dev/null
+++ b/src/common/wave.h
@@ -0,0 +1,19 @@
+
+typedef struct wave_rec {
+ FILE *fp;
+ int samplerate;
+ uint32_t written; /* how much samples written */
+} wave_rec_t;
+
+typedef struct wave_play {
+ FILE *fp;
+ uint32_t left; /* how much samples left */
+} wave_play_t;
+
+int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate);
+int wave_create_playback(wave_play_t *play, const char *filename, int samplerate);
+int wave_read(wave_play_t *play, 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_playback(wave_play_t *play);
+
diff --git a/src/nmt/main.c b/src/nmt/main.c
index cea0169..0d6a7d4 100644
--- a/src/nmt/main.c
+++ b/src/nmt/main.c
@@ -235,7 +235,7 @@ int main(int argc, char *argv[])
}
/* create transceiver instance */
- rc = nmt_create(sounddev, samplerate, kanal, (loopback) ? CHAN_TYPE_TEST : chan_type, ms_power, nmt_digits2value(traffic_area, 2), area_no, compander, supervisory, loopback);
+ rc = nmt_create(sounddev, samplerate, write_wave, read_wave, kanal, (loopback) ? CHAN_TYPE_TEST : chan_type, ms_power, nmt_digits2value(traffic_area, 2), area_no, compander, supervisory, loopback);
if (rc < 0) {
fprintf(stderr, "Failed to create transceiver instance. Quitting!\n");
goto fail;
diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c
index 1e8166e..22c9295 100644
--- a/src/nmt/nmt.c
+++ b/src/nmt/nmt.c
@@ -283,7 +283,7 @@ static void nmt_timeout(struct timer *timer);
static void nmt_go_idle(nmt_t *nmt);
/* Create transceiver instance and link to a list. */
-int nmt_create(const char *sounddev, int samplerate, int channel, enum nmt_chan_type chan_type, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compander, int supervisory, int loopback)
+int nmt_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int channel, enum nmt_chan_type chan_type, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compander, int supervisory, int loopback)
{
nmt_t *nmt;
int rc;
@@ -324,7 +324,7 @@ int nmt_create(const char *sounddev, int samplerate, int channel, enum nmt_chan_
PDEBUG(DNMT, DEBUG_DEBUG, "Creating 'NMT' instance for channel = %d (sample rate %d).\n", channel, samplerate);
/* init general part of transceiver */
- rc = sender_create(&nmt->sender, sounddev, samplerate, channel, loopback, 0, -1);
+ rc = sender_create(&nmt->sender, sounddev, samplerate, write_wave, read_wave, channel, loopback, 0, -1);
if (rc < 0) {
PDEBUG(DNMT, DEBUG_ERROR, "Failed to init transceiver process!\n");
goto error;
diff --git a/src/nmt/nmt.h b/src/nmt/nmt.h
index 385f4fb..edb1497 100644
--- a/src/nmt/nmt.h
+++ b/src/nmt/nmt.h
@@ -134,7 +134,7 @@ const char *chan_type_long_name(enum nmt_chan_type chan_type);
double nmt_channel2freq(int channel, int uplink);
void nmt_country_list(void);
uint8_t nmt_country_by_short_name(const char *short_name);
-int nmt_create(const char *sounddev, int samplerate, int channel, enum nmt_chan_type chan_type, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compander, int supervisory, int loopback);
+int nmt_create(const char *sounddev, int samplerate, const char *write_wave, const char *read_wave, int channel, enum nmt_chan_type chan_type, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compander, int supervisory, int loopback);
void nmt_destroy(sender_t *sender);
void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double level, double frames_elapsed);
const char *nmt_get_frame(nmt_t *nmt);