From ac7c48b4dee99d4c772f133d70d8d1b38262fcd2 Mon Sep 17 00:00:00 2001 From: Author Name Date: Fri, 7 Jul 2023 12:20:59 +0930 Subject: shallow zip-file copy from codec2 e9d726bf20 --- demo/CMakeLists.txt | 17 ++++++ demo/c2demo.c | 77 ++++++++++++++++++++++++++++ demo/freedv_700d_rx.c | 55 ++++++++++++++++++++ demo/freedv_700d_rx.py | 49 ++++++++++++++++++ demo/freedv_700d_tx.c | 66 ++++++++++++++++++++++++ demo/freedv_datac0c1_rx.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++ demo/freedv_datac0c1_tx.c | 107 ++++++++++++++++++++++++++++++++++++++ demo/freedv_datac1_rx.c | 64 +++++++++++++++++++++++ demo/freedv_datac1_tx.c | 96 ++++++++++++++++++++++++++++++++++ 9 files changed, 659 insertions(+) create mode 100644 demo/CMakeLists.txt create mode 100644 demo/c2demo.c create mode 100644 demo/freedv_700d_rx.c create mode 100755 demo/freedv_700d_rx.py create mode 100644 demo/freedv_700d_tx.c create mode 100644 demo/freedv_datac0c1_rx.c create mode 100644 demo/freedv_datac0c1_tx.c create mode 100644 demo/freedv_datac1_rx.c create mode 100644 demo/freedv_datac1_tx.c (limited to 'demo') 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 . +*/ + +#include +#include +#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 . +*/ + +#include +#include +#include + +#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 . +*/ + +#include +#include +#include +#include + +#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 . +*/ + +#include +#include +#include +#include +#include + +#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 . +*/ + +#include +#include +#include +#include + +#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. +*/ + +#include +#include +#include +#include + +#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)) 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 . +*/ + +#include +#include +#include +#include + +#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