aboutsummaryrefslogtreecommitdiff
path: root/demo
diff options
context:
space:
mode:
authorAuthor Name <[email protected]>2023-07-07 12:20:59 +0930
committerDavid Rowe <[email protected]>2023-07-07 12:29:06 +0930
commitac7c48b4dee99d4c772f133d70d8d1b38262fcd2 (patch)
treea2d0ace57a9c0e2e5b611c4987f6fed1b38b81e7 /demo
shallow zip-file copy from codec2 e9d726bf20
Diffstat (limited to 'demo')
-rw-r--r--demo/CMakeLists.txt17
-rw-r--r--demo/c2demo.c77
-rw-r--r--demo/freedv_700d_rx.c55
-rwxr-xr-xdemo/freedv_700d_rx.py49
-rw-r--r--demo/freedv_700d_tx.c66
-rw-r--r--demo/freedv_datac0c1_rx.c128
-rw-r--r--demo/freedv_datac0c1_tx.c107
-rw-r--r--demo/freedv_datac1_rx.c64
-rw-r--r--demo/freedv_datac1_tx.c96
9 files changed, 659 insertions, 0 deletions
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
new file mode 100644
index 0000000..fb902a5
--- /dev/null
+++ b/demo/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_definitions(-DFLOATING_POINT -DVAR_ARRAYS)
+include_directories(../src)
+
+add_executable(c2demo c2demo.c)
+target_link_libraries(c2demo codec2)
+add_executable(freedv_700d_tx freedv_700d_tx.c)
+target_link_libraries(freedv_700d_tx codec2)
+add_executable(freedv_700d_rx freedv_700d_rx.c)
+target_link_libraries(freedv_700d_rx codec2)
+add_executable(freedv_datac1_tx freedv_datac1_tx.c)
+target_link_libraries(freedv_datac1_tx codec2)
+add_executable(freedv_datac1_rx freedv_datac1_rx.c)
+target_link_libraries(freedv_datac1_rx codec2)
+add_executable(freedv_datac0c1_tx freedv_datac0c1_tx.c)
+target_link_libraries(freedv_datac0c1_tx codec2)
+add_executable(freedv_datac0c1_rx freedv_datac0c1_rx.c)
+target_link_libraries(freedv_datac0c1_rx codec2)
diff --git a/demo/c2demo.c b/demo/c2demo.c
new file mode 100644
index 0000000..08322ff
--- /dev/null
+++ b/demo/c2demo.c
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: c2demo.c
+ AUTHOR......: David Rowe
+ DATE CREATED: 15/11/2010
+
+ Encodes and decodes a file of raw speech samples using Codec 2.
+ Demonstrates use of Codec 2 function API.
+
+ cd codec2/build_linux
+ ./demo/c2demo ../raw/hts1a.raw his1a_out.raw
+ aplay -f S16_LE hts1a_out.raw
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2010 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "codec2.h"
+
+int main(int argc, char *argv[])
+{
+ struct CODEC2 *codec2;
+ FILE *fin;
+ FILE *fout;
+
+ if (argc != 3) {
+ printf("usage: %s InputRawSpeechFile OutputRawSpeechFile\n", argv[0]);
+ exit(1);
+ }
+
+ if ( (fin = fopen(argv[1],"rb")) == NULL ) {
+ fprintf(stderr, "Error opening input speech file: %s\n", argv[1]);
+ exit(1);
+ }
+
+ if ( (fout = fopen(argv[2],"wb")) == NULL ) {
+ fprintf(stderr, "Error opening output speech file: %s\n", argv[2]);
+ exit(1);
+ }
+
+ /* Note only one set of Codec 2 states is required for an encoder
+ and decoder pair. */
+ codec2 = codec2_create(CODEC2_MODE_1300);
+ size_t nsam = codec2_samples_per_frame(codec2);
+ short speech_samples[nsam];
+ /* Bits from the encoder are packed into bytes */
+ unsigned char compressed_bytes[codec2_bytes_per_frame(codec2)];
+
+ while(fread(speech_samples, sizeof(short), nsam, fin) == nsam) {
+ codec2_encode(codec2, compressed_bytes, speech_samples);
+ codec2_decode(codec2, speech_samples, compressed_bytes);
+ fwrite(speech_samples, sizeof(short), nsam, fout);
+ }
+
+ codec2_destroy(codec2);
+ fclose(fin);
+ fclose(fout);
+
+ return 0;
+}
diff --git a/demo/freedv_700d_rx.c b/demo/freedv_700d_rx.c
new file mode 100644
index 0000000..9d99c77
--- /dev/null
+++ b/demo/freedv_700d_rx.c
@@ -0,0 +1,55 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_700d_rx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: April 2021
+
+ Demo receive program for FreeDV API (700D mode), see freedv_700d_tx.c for
+ instructions.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "freedv_api.h"
+
+int main(int argc, char *argv[]) {
+ struct freedv *freedv;
+
+ freedv = freedv_open(FREEDV_MODE_700D);
+ assert(freedv != NULL);
+
+ /* note API functions to tell us how big our buffers need to be */
+ short speech_out[freedv_get_n_max_speech_samples(freedv)];
+ short demod_in[freedv_get_n_max_modem_samples(freedv)];
+
+ size_t nin,nout;
+ nin = freedv_nin(freedv);
+ while(fread(demod_in, sizeof(short), nin, stdin) == nin) {
+ nout = freedv_rx(freedv, speech_out, demod_in);
+ nin = freedv_nin(freedv); /* call me on every loop! */
+ fwrite(speech_out, sizeof(short), nout, stdout);
+ }
+
+ freedv_close(freedv);
+ return 0;
+}
diff --git a/demo/freedv_700d_rx.py b/demo/freedv_700d_rx.py
new file mode 100755
index 0000000..5962a73
--- /dev/null
+++ b/demo/freedv_700d_rx.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+'''
+ Demo receive program for FreeDV API 700D mode.
+
+ cd ~/codec2/build_linux
+ cat ../raw/ve9qrp_10s.raw | ./demo/freedv_700d_tx | ../demo/freedv_700d_rx.py | aplay -f S16_LE
+
+ Credits: Thanks DJ2LS, xssfox, VK5QI
+'''
+
+import ctypes
+from ctypes import *
+import sys
+import pathlib
+import platform
+
+if platform.system() == 'Darwin':
+ libname = pathlib.Path().absolute() / "src/libcodec2.dylib"
+else:
+ libname = pathlib.Path().absolute() / "src/libcodec2.so"
+
+# See: https://docs.python.org/3/library/ctypes.html
+
+c_lib = ctypes.CDLL(libname)
+
+c_lib.freedv_open.argype = [c_int]
+c_lib.freedv_open.restype = c_void_p
+
+c_lib.freedv_get_n_max_speech_samples.argtype = [c_void_p]
+c_lib.freedv_get_n_max_speech_samples.restype = c_int
+
+c_lib.freedv_nin.argtype = [c_void_p]
+c_lib.freedv_nin.restype = c_int
+
+c_lib.freedv_rx.argtype = [c_void_p, c_char_p, c_char_p]
+c_lib.freedv_rx.restype = c_int
+
+FREEDV_MODE_700D = 7 # from freedv_api.h
+freedv = cast(c_lib.freedv_open(FREEDV_MODE_700D), c_void_p)
+
+n_max_speech_samples = c_lib.freedv_get_n_max_speech_samples(freedv)
+speech_out = create_string_buffer(2*n_max_speech_samples)
+
+while True:
+ nin = c_lib.freedv_nin(freedv)
+ demod_in = sys.stdin.buffer.read(nin*2)
+ if len(demod_in) == 0: quit()
+ nout = c_lib.freedv_rx(freedv, speech_out, demod_in)
+ sys.stdout.buffer.write(speech_out[:nout*2])
diff --git a/demo/freedv_700d_tx.c b/demo/freedv_700d_tx.c
new file mode 100644
index 0000000..d678905
--- /dev/null
+++ b/demo/freedv_700d_tx.c
@@ -0,0 +1,66 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_700d_tx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: April 2021
+
+ Demo transmit program using the FreeDV API (700D mode).
+
+ usage:
+
+ cd ~/codec2/build_linux
+ cat ../raw/ve9qrp_10s.raw | ./demo/freedv_700d_tx | ./demo/freedv_700d_rx | aplay -f S16_LE
+
+ Listen to the modulated Tx signal:
+
+ cat ../raw/ve9qrp_10s.raw | ./demo/freedv_700d_tx | aplay -f S16_LE
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "freedv_api.h"
+
+int main(int argc, char *argv[]) {
+ struct freedv *freedv;
+
+ freedv = freedv_open(FREEDV_MODE_700D);
+ assert(freedv != NULL);
+
+ /* handy functions to set buffer sizes */
+ int n_speech_samples = freedv_get_n_speech_samples(freedv);
+ short speech_in[n_speech_samples];
+ int n_nom_modem_samples = freedv_get_n_nom_modem_samples(freedv);
+ short mod_out[n_nom_modem_samples];
+
+ /* OK main loop --------------------------------------- */
+
+ while(fread(speech_in, sizeof(short), n_speech_samples, stdin) == n_speech_samples) {
+ freedv_tx(freedv, mod_out, speech_in);
+ fwrite(mod_out, sizeof(short), n_nom_modem_samples, stdout);
+ }
+
+ freedv_close(freedv);
+
+ return 0;
+}
diff --git a/demo/freedv_datac0c1_rx.c b/demo/freedv_datac0c1_rx.c
new file mode 100644
index 0000000..cfbef14
--- /dev/null
+++ b/demo/freedv_datac0c1_rx.c
@@ -0,0 +1,128 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_datac0c1_rx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: Dec 2021
+
+ Demonstrates receiving frames of raw data bytes using the FreeDV
+ API. Two parallel receivers are running, so we can receive either
+ DATAC0 or DATAC1 frames. Demonstrates a common use case for HF data
+ - the ability to receive signalling as well as payload data frames.
+
+ usage:
+
+ cd codec2/build_linux
+ ./demo/freedv_datacc01_tx | ./demo/freedv_datac0c1_rx
+
+ Give it a hard time with some channel noise, frequency offset, and sample
+ clock offsets:
+
+ ./demo/freedv_datac0c1_tx | ./src/cohpsk_ch - - -24 -f 20 --Fs 8000 |
+ sox -t .s16 -c 1 -r 8000 - -t .s16 -c 1 -r 8008 - |
+ ./demo/freedv_datac0c1_rx
+
+ Replace the final line with "aplay -f S16" to listen to the
+ simulated Rx signal.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "freedv_api.h"
+
+#define NBUF 160
+
+int run_receiver(struct freedv *freedv, short buf[], short demod_in[], int *pn, uint8_t bytes_out[]);
+
+int main(int argc, char *argv[]) {
+
+ // set up DATAC0 Rx
+ struct freedv *freedv_c0 = freedv_open(FREEDV_MODE_DATAC0);
+ assert(freedv_c0 != NULL);
+ freedv_set_frames_per_burst(freedv_c0, 1);
+ freedv_set_verbose(freedv_c0, 0);
+ int bytes_per_modem_frame_c0 = freedv_get_bits_per_modem_frame(freedv_c0)/8;
+ uint8_t bytes_out_c0[bytes_per_modem_frame_c0];
+ short demod_in_c0[freedv_get_n_max_modem_samples(freedv_c0)];
+
+ // set up DATAC1 Rx
+ struct freedv *freedv_c1 = freedv_open(FREEDV_MODE_DATAC1);
+ assert(freedv_c1 != NULL);
+ freedv_set_frames_per_burst(freedv_c1, 1);
+ freedv_set_verbose(freedv_c1, 0);
+ int bytes_per_modem_frame_c1 = freedv_get_bits_per_modem_frame(freedv_c1)/8;
+ uint8_t bytes_out_c1[bytes_per_modem_frame_c1];
+ short demod_in_c1[freedv_get_n_max_modem_samples(freedv_c1)];
+
+ // number of samples in demod_in buffer for each Rx
+ int n_c0 = 0;
+ int n_c1 = 0;
+ // number of frames received in each mode
+ int c0_frames = 0;
+ int c1_frames = 0;
+
+ short buf[NBUF];
+
+ // read a fixed buffer from stdin, use that to fill c0 and c1 demod_in buffers
+ while(fread(buf, sizeof(short), NBUF, stdin) == NBUF) {
+
+ if (run_receiver(freedv_c0, buf, demod_in_c0, &n_c0, bytes_out_c0)) {
+ fprintf(stderr, "DATAC0 frame received!\n");
+ c0_frames++;
+ }
+ if (run_receiver(freedv_c1, buf, demod_in_c1, &n_c1, bytes_out_c1)) {
+ fprintf(stderr, "DATAC1 frame received!\n");
+ c1_frames++;
+ }
+
+ }
+
+ fprintf(stderr, "DATAC0 Frames: %d DATAC1 Frames: %d\n", c0_frames, c1_frames);
+
+ freedv_close(freedv_c0);
+ freedv_close(freedv_c1);
+
+ return 0;
+}
+
+int run_receiver(struct freedv *freedv, short buf[], short demod_in[], int *pn, uint8_t bytes_out[]) {
+ int n = *pn;
+ int nbytes_out = 0;
+ int nin;
+
+ // NBUF new samples into DATAC1 Rx
+ memcpy(&demod_in[n], buf, sizeof(short)*NBUF);
+ n += NBUF; assert(n <= freedv_get_n_max_modem_samples(freedv));
+ nin = freedv_nin(freedv);
+ while (n > nin) {
+ nbytes_out = freedv_rawdatarx(freedv, bytes_out, demod_in);
+ // nin samples were read
+ n -= nin; assert(n >= 0);
+ memmove(demod_in, &demod_in[nin], sizeof(short)*n);
+ nin = freedv_nin(freedv);
+ }
+
+ *pn = n;
+ return nbytes_out;
+}
diff --git a/demo/freedv_datac0c1_tx.c b/demo/freedv_datac0c1_tx.c
new file mode 100644
index 0000000..ddbe2a0
--- /dev/null
+++ b/demo/freedv_datac0c1_tx.c
@@ -0,0 +1,107 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_datac0c1_tx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: Dec 2021
+
+ Transmitting alternate frames of two different raw data modes. See
+ freedv_datac0c1_rx.c
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "freedv_api.h"
+#include "ofdm_internal.h"
+
+#define FRAMES 10
+
+void send_burst(struct freedv *freedv);
+
+int main(void) {
+ struct freedv *freedv_c0, *freedv_c1;
+
+ freedv_c0 = freedv_open(FREEDV_MODE_DATAC0); assert(freedv_c0 != NULL);
+ freedv_c1 = freedv_open(FREEDV_MODE_DATAC1); assert(freedv_c1 != NULL);
+
+ // send frames in different modes in random order
+ int c0_frames = 0;
+ int c1_frames = 0;
+ while ((c0_frames < FRAMES) || (c1_frames < FRAMES)) {
+ if (rand() & 1) {
+ if (c0_frames < FRAMES) {
+ send_burst(freedv_c0);
+ c0_frames++;
+ }
+ } else {
+ if (c1_frames < FRAMES) {
+ send_burst(freedv_c1);
+ c1_frames++;
+ }
+ }
+ }
+
+ freedv_close(freedv_c0);
+ freedv_close(freedv_c1);
+
+ return 0;
+}
+
+
+void send_burst(struct freedv *freedv) {
+ size_t bits_per_frame = freedv_get_bits_per_modem_frame(freedv);
+ size_t bytes_per_modem_frame = bits_per_frame/8;
+ size_t payload_bytes_per_modem_frame = bytes_per_modem_frame - 2; /* 16 bits used for the CRC */
+ size_t n_mod_out = freedv_get_n_tx_modem_samples(freedv);
+ uint8_t bytes_in[bytes_per_modem_frame];
+ short mod_out_short[n_mod_out];
+
+ /* generate a test frame */
+ uint8_t testframe_bits[bits_per_frame];
+ ofdm_generate_payload_data_bits(testframe_bits, bits_per_frame);
+ freedv_pack(bytes_in, testframe_bits, bits_per_frame);
+
+ /* send preamble */
+ int n_preamble = freedv_rawdatapreambletx(freedv, mod_out_short);
+ fwrite(mod_out_short, sizeof(short), n_preamble, stdout);
+
+ /* The raw data modes require a CRC in the last two bytes */
+ uint16_t crc16 = freedv_gen_crc16(bytes_in, payload_bytes_per_modem_frame);
+ bytes_in[bytes_per_modem_frame-2] = crc16 >> 8;
+ bytes_in[bytes_per_modem_frame-1] = crc16 & 0xff;
+
+ /* modulate and send a data frame */
+ freedv_rawdatatx(freedv, mod_out_short, bytes_in);
+ fwrite(mod_out_short, sizeof(short), n_mod_out, stdout);
+
+ /* send postamble */
+ int n_postamble = freedv_rawdatapostambletx(freedv, mod_out_short);
+ fwrite(mod_out_short, sizeof(short), n_postamble, stdout);
+
+ /* create some silence between bursts */
+ int inter_burst_delay_ms = 200;
+ int samples_delay = FREEDV_FS_8000*inter_burst_delay_ms/1000;
+ short sil_short[samples_delay];
+ for(int i=0; i<samples_delay; i++) sil_short[i] = 0;
+ fwrite(sil_short, sizeof(short), samples_delay, stdout);
+}
diff --git a/demo/freedv_datac1_rx.c b/demo/freedv_datac1_rx.c
new file mode 100644
index 0000000..d758c96
--- /dev/null
+++ b/demo/freedv_datac1_rx.c
@@ -0,0 +1,64 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_datac1_rx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: April 2021
+
+ Demonstrates receiving frames of raw data bytes using the FreeDV API.
+
+ See freedv_datac1_tx.c for instructions.
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "freedv_api.h"
+
+int main(int argc, char *argv[]) {
+ struct freedv *freedv;
+
+ freedv = freedv_open(FREEDV_MODE_DATAC1);
+ assert(freedv != NULL);
+ freedv_set_frames_per_burst(freedv, 1);
+ freedv_set_verbose(freedv, 2);
+
+ int bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv)/8;
+ uint8_t bytes_out[bytes_per_modem_frame];
+ short demod_in[freedv_get_n_max_modem_samples(freedv)];
+
+ size_t nin, nbytes_out;
+ nin = freedv_nin(freedv);
+ while(fread(demod_in, sizeof(short), nin, stdin) == nin) {
+
+ nbytes_out = freedv_rawdatarx(freedv, bytes_out, demod_in);
+ nin = freedv_nin(freedv); /* must call this every loop */
+ if (nbytes_out) {
+ /* don't output CRC */
+ fwrite(bytes_out, sizeof(uint8_t), nbytes_out-2, stdout);
+ }
+ }
+
+ freedv_close(freedv);
+
+ return 0;
+}
diff --git a/demo/freedv_datac1_tx.c b/demo/freedv_datac1_tx.c
new file mode 100644
index 0000000..616eec8
--- /dev/null
+++ b/demo/freedv_datac1_tx.c
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------------*\
+
+ FILE........: freedv_datac1_tx.c
+ AUTHOR......: David Rowe
+ DATE CREATED: April 2021
+
+ Demonstrates transmitting frames of raw data bytes using the FreeDV API datac1
+ mode. The data on stdin is transmitted as a sequence of modulated bursts.
+
+ Format of each burst: ...|preamble|data frame|postamble|silence|....
+
+ There is just one data frame per burst in this demo.
+
+ usage:
+
+ cd codec2/build_linux
+ head -c $((510*10)) </dev/urandom > binaryIn.bin
+ cat binaryIn.bin | ./demo/freedv_datac1_tx | ./demo/freedv_datac1_rx > binaryOut.bin
+ diff binaryIn.bin binaryOut.bin
+
+ Listen to the modulated Tx signal:
+
+ cat binaryIn.bin | ./demo/freedv_datac1_tx | aplay -f S16_LE
+
+\*---------------------------------------------------------------------------*/
+
+/*
+ Copyright (C) 2021 David Rowe
+
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License version 2.1, as
+ published by the Free Software Foundation. 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 Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "freedv_api.h"
+
+int main(int argc, char *argv[]) {
+ struct freedv *freedv;
+
+ freedv = freedv_open(FREEDV_MODE_DATAC1);
+ assert(freedv != NULL);
+
+ size_t bytes_per_modem_frame = freedv_get_bits_per_modem_frame(freedv)/8;
+ size_t payload_bytes_per_modem_frame = bytes_per_modem_frame - 2; /* 16 bits used for the CRC */
+ size_t n_mod_out = freedv_get_n_tx_modem_samples(freedv);
+ uint8_t bytes_in[bytes_per_modem_frame];
+ short mod_out_short[n_mod_out];
+
+ for(int b=0; b<10; b++) {
+ /* send preamble */
+ int n_preamble = freedv_rawdatapreambletx(freedv, mod_out_short);
+ fwrite(mod_out_short, sizeof(short), n_preamble, stdout);
+
+ /* read our input data frame from stdin */
+ size_t nread = fread(bytes_in, sizeof(uint8_t), payload_bytes_per_modem_frame, stdin);
+ if (nread != payload_bytes_per_modem_frame) break;
+
+ /* The raw data modes require a CRC in the last two bytes */
+ uint16_t crc16 = freedv_gen_crc16(bytes_in, payload_bytes_per_modem_frame);
+ bytes_in[bytes_per_modem_frame-2] = crc16 >> 8;
+ bytes_in[bytes_per_modem_frame-1] = crc16 & 0xff;
+
+ /* modulate and send a data frame */
+ freedv_rawdatatx(freedv, mod_out_short, bytes_in);
+ fwrite(mod_out_short, sizeof(short), n_mod_out, stdout);
+
+ /* send postamble */
+ int n_postamble = freedv_rawdatapostambletx(freedv, mod_out_short);
+ fwrite(mod_out_short, sizeof(short), n_postamble, stdout);
+
+ /* create some silence between bursts */
+ int inter_burst_delay_ms = 200;
+ int samples_delay = FREEDV_FS_8000*inter_burst_delay_ms/1000;
+ short sil_short[samples_delay];
+ for(int i=0; i<samples_delay; i++) sil_short[i] = 0;
+ fwrite(sil_short, sizeof(short), samples_delay, stdout);
+ }
+
+ freedv_close(freedv);
+
+ return 0;
+}