replaced frequency offset paramter with operation mode

This commit is contained in:
Ahmet Inan 2024-01-03 17:22:12 +01:00
commit 88e8a3ad94
3 changed files with 49 additions and 55 deletions

2
Makefile vendored
View file

@ -14,7 +14,7 @@ CXX = clang++ -stdlib=libc++ -march=native
all: encode decode
test: encode decode
$(QEMU) ./encode encoded.wav 8000 8 1 /dev/urandom
$(QEMU) ./encode encoded.wav 8000 8 1 /dev/urandom 25
$(QEMU) ./decode /dev/null encoded.wav
encode: encode.cc

8
README.md vendored
View file

@ -3,16 +3,16 @@
Quick start:
Create file ```uncoded.dat``` with ```2720``` bits of random data:
Create file ```uncoded.dat``` with ```2048``` bits of random data:
```
dd if=/dev/urandom of=uncoded.dat bs=1 count=340
dd if=/dev/urandom of=uncoded.dat bs=1 count=256
```
Encode file ```uncoded.dat``` to ```encoded.wav``` [WAV](https://en.wikipedia.org/wiki/WAV) audio file with 8000 Hz sample rate, 16 bits and only 1 (real) channel:
```
./encode encoded.wav 8000 16 1 uncoded.dat
./encode encoded.wav 8000 16 1 uncoded.dat 25
```
Start recording to ```recorded.wav``` audio file and stop after 5 seconds:
@ -46,7 +46,7 @@ Prerequisite: [disorders](https://github.com/aicodix/disorders)
Encode ```uncoded.dat``` to [analytic](https://en.wikipedia.org/wiki/Analytic_signal) audio signal, add [multipath](https://en.wikipedia.org/wiki/Multipath_propagation), [CFO, SFO](https://en.wikipedia.org/wiki/Carrier_frequency_offset), [AWGN](https://en.wikipedia.org/wiki/Additive_white_Gaussian_noise), decode and compare:
```
./encode - 8000 16 2 uncoded.dat 2000 | ../disorders/multipath - - ../disorders/multipath.txt 10 | ../disorders/cfo - - 234.567 | ../disorders/sfo - - 147 | ../disorders/awgn - - -30 | ./decode - - | diff -q -s uncoded.dat -
./encode - 8000 16 2 uncoded.dat 25 | ../disorders/multipath - - ../disorders/multipath.txt 10 | ../disorders/cfo - - 234.567 | ../disorders/sfo - - 147 | ../disorders/awgn - - -30 | ./decode - - | diff -q -s uncoded.dat -
```
### Reading

View file

@ -257,7 +257,7 @@ struct Encoder
int reserved_tones = 0;
switch (oper_mode) {
case 0:
cons_cols = 256;
code_cols = 256;
break;
case 23:
mod_bits = 2;
@ -325,11 +325,11 @@ struct Encoder
int offset = (freq_off * symbol_len) / rate;
mls0_off = offset - mls0_len + 1;
mls1_off = offset - mls1_len / 2;
cons_cols = code_cols + comb_cols;
code_off = offset - cons_cols / 2;
if (oper_mode > 0) {
cons_cols = code_cols + comb_cols;
comb_dist = comb_cols ? cons_cols / comb_cols : 1;
comb_off = comb_cols ? comb_dist / 2 : 1;
code_off = offset - cons_cols / 2;
if (reserved_tones) {
value kern_fac = 1 / value(10 * reserved_tones);
for (int i = 0, j = code_off - reserved_tones / 2; i < reserved_tones; ++i, ++j) {
@ -400,8 +400,8 @@ long long int base37_encoder(const char *str)
int main(int argc, char **argv)
{
if (argc < 6 || argc > 8) {
std::cerr << "usage: " << argv[0] << " OUTPUT RATE BITS CHANNELS INPUT [OFFSET] [CALLSIGN]" << std::endl;
if (argc < 7 || argc > 8) {
std::cerr << "usage: " << argv[0] << " OUTPUT RATE BITS CHANNELS INPUT MODE [CALLSIGN]" << std::endl;
return 1;
}
@ -415,9 +415,7 @@ int main(int argc, char **argv)
if (input_name[0] == '-' && input_name[1] == 0)
input_name = "/dev/stdin";
int freq_off = output_chan == 1 ? 1500 : 0;
if (argc >= 7)
freq_off = std::atoi(argv[6]);
int oper_mode = std::atoi(argv[6]);
long long int call_sign = base37_encoder("ANONYMOUS");
if (argc >= 8)
@ -428,21 +426,6 @@ int main(int argc, char **argv)
return 1;
}
const int comb_pilots_max = 16;
const int reserved_tones_max = 15;
const int data_carriers_max = 273;
const int band_width = (25 * (data_carriers_max + comb_pilots_max + reserved_tones_max)) / 4;
if ((output_chan == 1 && freq_off < band_width / 2) || freq_off < band_width / 2 - output_rate / 2 || freq_off > output_rate / 2 - band_width / 2) {
std::cerr << "Unsupported frequency offset." << std::endl;
return 1;
}
if (freq_off % 50) {
std::cerr << "Frequency offset must be divisible by 50." << std::endl;
return 1;
}
typedef float value;
typedef DSP::Complex<value> cmplx;
@ -451,33 +434,44 @@ int main(int argc, char **argv)
std::cerr << "Couldn't open file \"" << input_name << "\" for reading." << std::endl;
return 1;
}
const int data_len = 768;
uint8_t *input_data = new uint8_t[data_len];
for (int i = 0; i < data_len; ++i)
input_data[i] = std::max(input_file.get(), 0);
int oper_mode = 0;
for (int i = 680; i < 768; ++i)
if (!oper_mode && input_data[i])
oper_mode = 28;
for (int i = 384; i < 680; ++i)
if (!oper_mode && input_data[i])
oper_mode = 27;
for (int i = 256; i < 384; ++i)
if (!oper_mode && input_data[i])
oper_mode = 26;
for (int i = 192; i < 256; ++i)
if (!oper_mode && input_data[i])
oper_mode = 25;
for (int i = 128; i < 192; ++i)
if (!oper_mode && input_data[i])
oper_mode = 24;
for (int i = 0; i < 128; ++i)
if (!oper_mode && input_data[i])
oper_mode = 23;
CODE::Xorshift32 scrambler;
for (int i = 0; i < data_len; ++i)
input_data[i] ^= scrambler();
int data_bits;
switch (oper_mode) {
case 0:
data_bits = 0;
break;
case 23:
data_bits = 1024;
break;
case 24:
data_bits = 1536;
break;
case 25:
data_bits = 2048;
break;
case 26:
data_bits = 3072;
break;
case 27:
data_bits = 5440;
break;
case 28:
data_bits = 6144;
break;
default:
std::cerr << "Unsupported operation mode." << std::endl;
return 1;
}
uint8_t *input_data = nullptr;
if (oper_mode) {
int data_len = data_bits / 8;
input_data = new uint8_t[data_len];
for (int i = 0; i < data_len; ++i)
input_data[i] = std::max(input_file.get(), 0);
CODE::Xorshift32 scrambler;
for (int i = 0; i < data_len; ++i)
input_data[i] ^= scrambler();
}
int freq_off = 1500;
DSP::WriteWAV<value> output_file(output_name, output_rate, output_bits, output_chan);
output_file.silence(output_rate);
switch (output_rate) {