added some more modes

This commit is contained in:
Ahmet Inan 2025-07-01 14:27:48 +02:00
commit b10e171e9a
3 changed files with 151 additions and 46 deletions

31
README.md vendored
View file

@ -12,7 +12,7 @@ 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 1500 23 CALLSIGN uncoded.dat
./encode encoded.wav 8000 16 1 1500 5 uncoded.dat
```
Start recording to ```recorded.wav``` audio file and stop after 5 seconds:
@ -41,18 +41,23 @@ diff -s uncoded.dat decoded.dat
### Supported Modes
Ping:
* Mode 0: DBPSK, 2/7-rate code, 1600 Hz bandwidth, 0.36 seconds and no payload
All modes need a bandwidth of 2000 Hz and use a 1/2-rate forward error correction code
Next:
* Mode 23: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 1.80 seconds and 256 bytes
* Mode 24: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 3.24 seconds and 512 bytes
* Mode 25: DQPSK, 1/2-rate code, 1600 Hz bandwidth, 6.12 seconds and 1024 bytes
* Mode 26: QAM16, 1/2-rate code, 1700 Hz bandwidth, 1.08 seconds and 256 bytes
* Mode 27: QAM16, 1/2-rate code, 1700 Hz bandwidth, 1.80 seconds and 512 bytes
* Mode 28: QAM16, 1/2-rate code, 1700 Hz bandwidth, 3.24 seconds and 1024 bytes
* Mode 29: QAM64, 1/2-rate code, 1900 Hz bandwidth, 1.26 seconds and 512 bytes
* Mode 30: QAM64, 1/2-rate code, 1900 Hz bandwidth, 2.16 seconds and 1024 bytes
* Mode 1: QPSK, 1.02 seconds and 128 bytes
* Mode 2: QPSK, 1.70 seconds and 256 bytes
* Mode 3: QPSK, 3.06 seconds and 512 bytes
* Mode 4: QPSK, 5.78 seconds and 1024 bytes
* Mode 5: QAM16, 1.02 seconds and 256 bytes
* Mode 6: QAM16, 1.70 seconds and 512 bytes
* Mode 7: QAM16, 3.06 seconds and 1024 bytes
* Mode 8: QAM16, 5.78 seconds and 2048 bytes
* Mode 9: QAM64, 2.21 seconds and 1024 bytes
* Mode 10: QAM64, 4.08 seconds and 2048 bytes
* Mode 11: QAM64, 7.82 seconds and 4096 bytes
* Mode 12: QAM256, 1.02 seconds and 512 bytes
* Mode 13: QAM256, 1.70 seconds and 1024 bytes
* Mode 14: QAM256, 3.06 seconds and 2048 bytes
* Mode 15: QAM256, 5.78 seconds and 4096 bytes
### Simulating
@ -61,7 +66,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 1500 23 CALLSIGN uncoded.dat | ../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 1500 5 uncoded.dat | ../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

@ -45,11 +45,11 @@ struct Decoder
static const int symbol_len = guard_len * 16;
static const int filter_len = (((21 * rate) / 8000) & ~3) | 1;
static const int extended_len = symbol_len + guard_len;
static const int mod_max = 6;
static const int mod_max = 8;
static const int code_max = 16;
static const int bits_max = 1 << code_max;
static const int data_max = 1024;
static const int symbols_max = 32;
static const int data_max = 4096;
static const int symbols_max = 44;
static const int mls0_poly = 0b1100110001;
static const int mls0_seed = 214;
static const int mls1_poly = 0b100101011;
@ -127,6 +127,8 @@ struct Decoder
return QuadratureAmplitudeModulation<16, cmplx, code_type>::soft(b, c, precision);
case 6:
return QuadratureAmplitudeModulation<64, cmplx, code_type>::soft(b, c, precision);
case 8:
return QuadratureAmplitudeModulation<256, cmplx, code_type>::soft(b, c, precision);
}
}
void shuffle(code_type *dest, const code_type *src)
@ -174,61 +176,110 @@ struct Decoder
void setup(int oper_mode) {
switch (oper_mode) {
case 1:
mod_bits = 2;
symbol_count = 4;
code_order = 11;
data_bits = 1024;
frozen_bits = frozen_2048_1056;
break;
case 2:
mod_bits = 2;
symbol_count = 8;
code_order = 12;
data_bits = 2048;
frozen_bits = frozen_4096_2080;
break;
case 2:
case 3:
mod_bits = 2;
symbol_count = 16;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 3:
case 4:
mod_bits = 2;
symbol_count = 32;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 4:
case 5:
mod_bits = 4;
symbol_count = 4;
code_order = 12;
data_bits = 2048;
frozen_bits = frozen_4096_2080;
break;
case 5:
case 6:
mod_bits = 4;
symbol_count = 8;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 6:
case 7:
mod_bits = 4;
symbol_count = 16;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 7:
mod_bits = 6;
symbol_count = 6;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 8:
mod_bits = 4;
symbol_count = 32;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 9:
mod_bits = 6;
symbol_count = 11;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 10:
mod_bits = 6;
symbol_count = 22;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 11:
mod_bits = 6;
symbol_count = 44;
code_order = 16;
data_bits = 32768;
frozen_bits = frozen_65536_32800;
break;
case 12:
mod_bits = 8;
symbol_count = 4;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 13:
mod_bits = 8;
symbol_count = 8;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 14:
mod_bits = 8;
symbol_count = 16;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 15:
mod_bits = 8;
symbol_count = 32;
code_order = 16;
data_bits = 32768;
frozen_bits = frozen_65536_32800;
break;
default:
return;
}
@ -276,7 +327,7 @@ struct Decoder
for (int i = 0; i < pilot_tones; ++i)
mode[i] = clamp(std::nearbyint(127 * demod_or_erase(tone[i*block_length+pilot_offset], chan[i*block_length+pilot_offset]).real() * nrz(seq1())));
int oper_mode = hadamarddec(mode);
if (oper_mode < 0 || oper_mode > 8) {
if (oper_mode < 0 || oper_mode > 15) {
std::cerr << "operation mode " << oper_mode << " unsupported." << std::endl;
continue;
}
@ -347,9 +398,7 @@ struct Decoder
if (i % block_length == roff)
continue;
int bits = mod_bits;
if (oper_mode == 7 && k % 32 == 30)
bits = 2;
else if (oper_mode == 8 && k % 64 == 60)
if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60)
bits = 4;
demap_bits(perm+k, demod[tone_count*j+i], precision, bits);
k += bits;

View file

@ -30,7 +30,7 @@ struct Encoder
static const int guard_len = rate / 100;
static const int symbol_len = guard_len * 16;
static const int bits_max = 65536;
static const int data_max = 1024;
static const int data_max = 4096;
static const int mls0_poly = 0b1100110001;
static const int mls0_seed = 214;
static const int mls1_poly = 0b100101011;
@ -172,6 +172,8 @@ struct Encoder
return QuadratureAmplitudeModulation<16, cmplx, code_type>::map(b);
case 6:
return QuadratureAmplitudeModulation<64, cmplx, code_type>::map(b);
case 8:
return QuadratureAmplitudeModulation<256, cmplx, code_type>::map(b);
}
return 0;
}
@ -184,6 +186,8 @@ struct Encoder
return QuadratureAmplitudeModulation<16, cmplx, code_type>::DIST;
case 6:
return QuadratureAmplitudeModulation<64, cmplx, code_type>::DIST;
case 8:
return QuadratureAmplitudeModulation<256, cmplx, code_type>::DIST;
}
return 2;
}
@ -228,61 +232,110 @@ struct Encoder
symbol_count = 1;
break;
case 1:
mod_bits = 2;
symbol_count = 4;
code_order = 11;
data_bits = 1024;
frozen_bits = frozen_2048_1056;
break;
case 2:
mod_bits = 2;
symbol_count = 8;
code_order = 12;
data_bits = 2048;
frozen_bits = frozen_4096_2080;
break;
case 2:
case 3:
mod_bits = 2;
symbol_count = 16;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 3:
case 4:
mod_bits = 2;
symbol_count = 32;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 4:
case 5:
mod_bits = 4;
symbol_count = 4;
code_order = 12;
data_bits = 2048;
frozen_bits = frozen_4096_2080;
break;
case 5:
case 6:
mod_bits = 4;
symbol_count = 8;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 6:
case 7:
mod_bits = 4;
symbol_count = 16;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 7:
mod_bits = 6;
symbol_count = 6;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 8:
mod_bits = 4;
symbol_count = 32;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 9:
mod_bits = 6;
symbol_count = 11;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 10:
mod_bits = 6;
symbol_count = 22;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 11:
mod_bits = 6;
symbol_count = 44;
code_order = 16;
data_bits = 32768;
frozen_bits = frozen_65536_32800;
break;
case 12:
mod_bits = 8;
symbol_count = 4;
code_order = 13;
data_bits = 4096;
frozen_bits = frozen_8192_4128;
break;
case 13:
mod_bits = 8;
symbol_count = 8;
code_order = 14;
data_bits = 8192;
frozen_bits = frozen_16384_8224;
break;
case 14:
mod_bits = 8;
symbol_count = 16;
code_order = 15;
data_bits = 16384;
frozen_bits = frozen_32768_16416;
break;
case 15:
mod_bits = 8;
symbol_count = 32;
code_order = 16;
data_bits = 32768;
frozen_bits = frozen_65536_32800;
break;
default:
return;
}
@ -365,9 +418,7 @@ struct Encoder
tone[i] = 0;
} else {
int bits = mod_bits;
if (oper_mode == 7 && k % 32 == 30)
bits = 2;
else if (oper_mode == 8 && k % 64 == 60)
if (oper_mode >= 9 && oper_mode <= 11 && k % 64 == 60)
bits = 4;
tone[i] = map_bits(perm+k, bits);
k += bits;
@ -409,7 +460,7 @@ int main(int argc, char **argv)
std::cerr << "Using operation mode " << oper_mode << " but " << input_count << " input file" << (input_count == 1 ? "" : "s") << " provided." << std::endl;
return 1;
}
if (oper_mode < 0 || oper_mode > 8) {
if (oper_mode < 0 || oper_mode > 15) {
std::cerr << "Unsupported operation mode." << std::endl;
return 1;
}