mirror of
https://github.com/romanz/amodem.git
synced 2026-03-17 15:16:00 +08:00
91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
"""Configuration class."""
|
|
|
|
import numpy as np
|
|
|
|
|
|
class Configuration(object):
|
|
Fs = 32000.0 # sampling frequency [Hz]
|
|
Tsym = 0.001 # symbol duration [seconds]
|
|
Npoints = 64
|
|
frequencies = [1e3, 8e3] # use 1..8 kHz carriers
|
|
|
|
# audio config
|
|
bits_per_sample = 16
|
|
latency = 0.1
|
|
|
|
# sender config
|
|
silence_start = 0.25
|
|
silence_stop = 0.25
|
|
|
|
# receiver config
|
|
skip_start = 0.1
|
|
timeout = 60.0
|
|
|
|
def __init__(self, **kwargs):
|
|
self.__dict__.update(**kwargs)
|
|
|
|
self.sample_size = self.bits_per_sample // 8
|
|
assert self.sample_size * 8 == self.bits_per_sample
|
|
|
|
self.Ts = 1.0 / self.Fs
|
|
self.Fsym = 1 / self.Tsym
|
|
self.Nsym = int(self.Tsym / self.Ts)
|
|
self.baud = int(1.0 / self.Tsym)
|
|
assert self.baud * self.Tsym == 1
|
|
|
|
if len(self.frequencies) != 1:
|
|
first, last = self.frequencies
|
|
self.frequencies = np.arange(first, last + self.baud, self.baud)
|
|
|
|
self.Nfreq = len(self.frequencies)
|
|
self.carrier_index = 0
|
|
self.Fc = self.frequencies[self.carrier_index]
|
|
|
|
bits_per_symbol = int(np.log2(self.Npoints))
|
|
assert 2 ** bits_per_symbol == self.Npoints
|
|
self.bits_per_baud = bits_per_symbol * self.Nfreq
|
|
self.modem_bps = self.baud * self.bits_per_baud
|
|
self.carriers = np.array([
|
|
np.exp(2j * np.pi * f * np.arange(0, self.Nsym) * self.Ts)
|
|
for f in self.frequencies
|
|
])
|
|
|
|
# QAM constellation
|
|
Nx = 2 ** int(np.ceil(bits_per_symbol / 2))
|
|
Ny = self.Npoints // Nx
|
|
symbols = [complex(x, y) for x in range(Nx) for y in range(Ny)]
|
|
symbols = np.array(symbols)
|
|
symbols = symbols - symbols[-1]/2
|
|
self.symbols = symbols / np.max(np.abs(symbols))
|
|
|
|
|
|
# MODEM configurations for various bitrates [kbps]
|
|
bitrates = {
|
|
1: Configuration(Fs=8e3, Npoints=2, frequencies=[2e3]),
|
|
2: Configuration(Fs=8e3, Npoints=4, frequencies=[2e3]),
|
|
4: Configuration(Fs=8e3, Npoints=16, frequencies=[2e3]),
|
|
8: Configuration(Fs=8e3, Npoints=16, frequencies=[1e3, 2e3]),
|
|
12: Configuration(Fs=16e3, Npoints=16, frequencies=[3e3, 5e3]),
|
|
16: Configuration(Fs=16e3, Npoints=16, frequencies=[2e3, 5e3]),
|
|
20: Configuration(Fs=16e3, Npoints=16, frequencies=[2e3, 6e3]),
|
|
24: Configuration(Fs=16e3, Npoints=16, frequencies=[1e3, 6e3]),
|
|
28: Configuration(Fs=32e3, Npoints=16, frequencies=[3e3, 9e3]),
|
|
32: Configuration(Fs=32e3, Npoints=16, frequencies=[2e3, 9e3]),
|
|
36: Configuration(Fs=32e3, Npoints=64, frequencies=[4e3, 9e3]),
|
|
42: Configuration(Fs=32e3, Npoints=64, frequencies=[4e3, 10e3]),
|
|
48: Configuration(Fs=32e3, Npoints=64, frequencies=[3e3, 10e3]),
|
|
54: Configuration(Fs=32e3, Npoints=64, frequencies=[2e3, 10e3]),
|
|
60: Configuration(Fs=32e3, Npoints=64, frequencies=[2e3, 11e3]),
|
|
64: Configuration(Fs=32e3, Npoints=256, frequencies=[3e3, 10e3]),
|
|
72: Configuration(Fs=32e3, Npoints=256, frequencies=[2e3, 10e3]),
|
|
80: Configuration(Fs=32e3, Npoints=256, frequencies=[2e3, 11e3]),
|
|
}
|
|
|
|
|
|
def fastest():
|
|
return bitrates[max(bitrates)]
|
|
|
|
|
|
def slowest():
|
|
return bitrates[min(bitrates)]
|