diff options
Diffstat (limited to 'src/client/kotlin/space/autistic/radio/client/fmsim/FmFullConstants.kt')
-rw-r--r-- | src/client/kotlin/space/autistic/radio/client/fmsim/FmFullConstants.kt | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/src/client/kotlin/space/autistic/radio/client/fmsim/FmFullConstants.kt b/src/client/kotlin/space/autistic/radio/client/fmsim/FmFullConstants.kt new file mode 100644 index 0000000..f5a49ce --- /dev/null +++ b/src/client/kotlin/space/autistic/radio/client/fmsim/FmFullConstants.kt @@ -0,0 +1,114 @@ +package space.autistic.radio.client.fmsim + +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.sin + +object FmFullConstants { + // tau = 75us, fh = 20396.25Hz + const val FM_PREEMPAHSIS_B0_48K = 6.7639647f + const val FM_PREEMPHASIS_B1_48K = -4.975628f + + /* const val FM_PREEMPHASIS_A0_48K = 1f */ + const val FM_PREEMPHASIS_A1_48K = 0.78833646f + + const val FM_DEEMPAHSIS_B0_48K = 1f / FM_PREEMPAHSIS_B0_48K + const val FM_DEEMPHASIS_B1_48K = FM_PREEMPHASIS_A1_48K / FM_PREEMPAHSIS_B0_48K + + /* const val FM_DEEMPHASIS_A0_48K = 1f */ + const val FM_DEEMPHASIS_A1_48K = FM_PREEMPHASIS_B1_48K / FM_PREEMPAHSIS_B0_48K + + val FIR_LPF_48K_15K_3K1 = floatArrayOf( + -0.0010006913216784596f, + 0.001505308784544468f, + -2.625857350794219e-18f, + -0.002777613466605544f, + 0.0030173989944159985f, + 0.002290070755407214f, + -0.008225799538195133f, + 0.004239063244313002f, + 0.010359899140894413f, + -0.017650796100497246f, + 1.510757873119297e-17f, + 0.029305754229426384f, + -0.02889496460556984f, + -0.020366130396723747f, + 0.07103750854730606f, + -0.03811456635594368f, + -0.10945471376180649f, + 0.29212409257888794f, + 0.6252123713493347f, + 0.29212409257888794f, + -0.10945471376180649f, + -0.03811456635594368f, + 0.07103750854730606f, + -0.020366130396723747f, + -0.02889496460556984f, + 0.029305754229426384f, + 1.510757873119297e-17f, + -0.017650796100497246f, + 0.010359899140894413f, + 0.004239063244313002f, + -0.008225799538195133f, + 0.002290070755407214f, + 0.0030173989944159985f, + -0.002777613466605544f, + -2.625857350794219e-18f, + 0.001505308784544468f, + -0.0010006913216784596f, + ) + + // chosen such that we can easily do 38kHz mixing in frequency (1500*38k/300k = shift of 95 bins, where 1500 comes + // from the 4/25 ratio 48k/300k i.e. 240*25/4) + // (the theoretical optimum, as per above, would be around 180) + // (we could have fudged the carrier frequency a bit but we chose not to) + // NOTE: latency = (data block size / 48000) seconds (84 -> 1.75 ms) + const val FFT_SIZE_LPF_48K_15K_3K1 = 2 * 120 + const val FFT_OVERLAP_LPF_48K_15K_3K1 = 36 + const val FFT_DATA_BLOCK_SIZE_LPF_48K_15K_3K1 = FFT_SIZE_LPF_48K_15K_3K1 - FFT_OVERLAP_LPF_48K_15K_3K1 + + init { + assert(FFT_OVERLAP_LPF_48K_15K_3K1 >= FIR_LPF_48K_15K_3K1.size - 1) + } + + const val DECIMATION_48K_300K = 4 + const val INTERPOLATION_48K_300K = 25 + + const val FFT_SIZE_48K_300K = FFT_SIZE_LPF_48K_15K_3K1 * INTERPOLATION_48K_300K / DECIMATION_48K_300K + const val FFT_OVERLAP_48K_300K = FFT_OVERLAP_LPF_48K_15K_3K1 * INTERPOLATION_48K_300K / DECIMATION_48K_300K + const val FFT_DATA_BLOCK_SIZE_48K_300K = FFT_SIZE_48K_300K - FFT_OVERLAP_48K_300K + + // how many bins to shift for 38kHz mixing + // assuming FFT_SIZE_LPF_48K_15K_3K1 *bins* (complex) + // 19 / 150 is the ratio between 38k/300k + const val FREQUENCY_MIXING_BINS_38K = + FFT_SIZE_LPF_48K_15K_3K1 * INTERPOLATION_48K_300K / DECIMATION_48K_300K * 19 / 150 + + // a single cycle of a 19kHz signal takes (1/19k)/(1/300k) or 300k/19k samples. + // since that number isn't exact, buffer an entire 19 cycles. + const val BUFFER_SIZE_19K_300K = 300 + + // using cosine is nicer + val BUFFER_19K_300K = FloatArray(BUFFER_SIZE_19K_300K) { + 0.1f * cos(2 * PI * 19000.0 * it.toDouble() / 300000.0).toFloat() + } + + // we want a carrier deviation of +-75kHz, at a sampling rate of 300kHz + const val CORRECTION_FACTOR = (75000.0 / (300000.0 / (2.0 * PI))).toFloat() + const val INVERSE_CORRECTION_FACTOR = 1 / CORRECTION_FACTOR + + // these are used for "low/high" mixing + const val CBUFFER_SIZE_100K_300K = 3 + + val CBUFFER_100K_300K = FloatArray(2 * CBUFFER_SIZE_100K_300K) { + val index = it / 2 + if (it and 1 == 0) { + 1f * sin(2 * PI * 100000.0 * index.toDouble() / 300000.0).toFloat() + } else { + 1f * cos(2 * PI * 100000.0 * index.toDouble() / 300000.0).toFloat() + } + } + + const val STEREO = true + const val MONO = false +} \ No newline at end of file |