diff options
author | SoniEx2 <endermoneymod@gmail.com> | 2025-03-07 10:14:43 -0300 |
---|---|---|
committer | SoniEx2 <endermoneymod@gmail.com> | 2025-03-07 10:14:43 -0300 |
commit | 31a76d788d7b2cc4af095d6623cf78228e949b63 (patch) | |
tree | 6457074f5df3c9caa121688b8404dc08afddaca0 /src/main/kotlin/space/autistic/radio/cli | |
parent | 79ff3692b9462fc79d93bd74213ce6904340fc13 (diff) |
Add demodulator
Diffstat (limited to 'src/main/kotlin/space/autistic/radio/cli')
-rw-r--r-- | src/main/kotlin/space/autistic/radio/cli/OfflineSimulator.kt | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/src/main/kotlin/space/autistic/radio/cli/OfflineSimulator.kt b/src/main/kotlin/space/autistic/radio/cli/OfflineSimulator.kt index 517957b..bc16814 100644 --- a/src/main/kotlin/space/autistic/radio/cli/OfflineSimulator.kt +++ b/src/main/kotlin/space/autistic/radio/cli/OfflineSimulator.kt @@ -3,6 +3,7 @@ package space.autistic.radio.cli import org.joml.Vector2f import space.autistic.radio.complex.cmul import space.autistic.radio.fmsim.FmFullConstants +import space.autistic.radio.fmsim.FmFullDemodulator import space.autistic.radio.fmsim.FmFullModulator import java.io.FileInputStream import java.io.FileOutputStream @@ -17,20 +18,24 @@ import kotlin.math.min import kotlin.system.exitProcess fun printUsage() { - println("Usage: OfflineSimulator -o OUTFILE.raw {[-p POWER] [-l|-h] file:///FILE.raw}") + println("Usage: OfflineSimulator <-o|-O> OUTFILE.raw {[-p POWER] [-l|-h] [-m] file:///FILE.raw} [-m]") println(" file:///FILE.raw (or ./FILE.raw - the ./ is required)") - println(" The raw input file. 2x48kHz 32-bit float") + println(" The raw input file. two-channel (even with -m), 48kHz 32-bit float.") println(" -o OUTFILE.raw") - println(" The raw RF stream to output, 2x200kHz 32-bit float") + println(" The raw RF stream to output, 2x300kHz 32-bit float.") + println(" -O OUTFILE.raw") + println(" The raw audio stream to output, 2x48kHz 32-bit float.") println(" -p POWER") - println(" The signal amplitude (power level), e.g. 1.0") + println(" The signal amplitude (power level), e.g. 1.0.") println(" -l") println(" Simulate a partial overlap on the lower half of the tuned-into frequency.") println(" -h") println(" Simulate a partial overlap on the upper half of the tuned-into frequency.") + println(" -m") + println(" Downconvert to mono. As the last option, demodulate as mono.") } -class SimFile(val power: Float, val band: Int, val filename: String) { +class SimFile(val power: Float, val band: Int, val filename: String, val stereo: Boolean) { var closed: Boolean = false val buffer: FloatBuffer = FloatBuffer.allocate(8192) val modulator = FmFullModulator() @@ -45,14 +50,16 @@ fun main(args: Array<String>) { var hasOutput = false var inArg = "" var output = "" + var rfOutput = true var power = 1.0f var band = 2 + var stereo = FmFullConstants.STEREO val files: ArrayList<SimFile> = ArrayList() for (arg in args) { if (!hasOutput) { - if (arg == "-o") { + if (arg == "-o" || arg == "-O") { hasOutput = true - inArg = "-o" + inArg = arg } else { printUsage() exitProcess(1) @@ -61,6 +68,13 @@ fun main(args: Array<String>) { when (inArg) { "-o" -> { output = arg + rfOutput = true + inArg = "" + } + + "-O" -> { + output = arg + rfOutput = false inArg = "" } @@ -75,15 +89,17 @@ fun main(args: Array<String>) { "" -> { if (!arg.startsWith("-")) { - files.add(SimFile(power, band, arg)) + files.add(SimFile(power, band, arg, stereo)) inArg = "" band = 2 power = 1.0f + stereo = FmFullConstants.STEREO } else { when (arg) { "-p" -> inArg = "-p" "-l" -> band = 1 "-h" -> band = 3 + "-m" -> stereo = FmFullConstants.MONO else -> { println("Unknown option") printUsage() @@ -119,14 +135,16 @@ fun main(args: Array<String>) { val buffer = ByteBuffer.allocate(2 * 4 * FmFullConstants.FFT_DATA_BLOCK_SIZE_LPF_48K_15K_3K1) val plus100k = FloatBuffer.wrap(FmFullConstants.CBUFFER_100K_300K) val minus100k = FloatBuffer.wrap(FmFullConstants.CBUFFER_100K_300K) + val demodulator = FmFullDemodulator() + var lastStereoPilot = false while (true) { // initialized to maximum buffer size, trimmed down later var minBuffer = 8192 for (inputFile in files) { val stream = inputFile.stream if (stream == null) { - if (inputFile.buffer.remaining() > 2 * FmFullConstants.IFFT_DATA_BLOCK_SIZE_48K_300K) { - inputFile.modulator.flush(inputFile.power) { + if (inputFile.buffer.remaining() > 2 * FmFullConstants.FFT_DATA_BLOCK_SIZE_48K_300K) { + inputFile.modulator.flush(inputFile.power, inputFile.stereo) { inputFile.buffer.put(it) } } @@ -136,18 +154,18 @@ fun main(args: Array<String>) { stream.close() inputFile.stream = null inputFile.closed = true - inputFile.modulator.flush(inputFile.power) { + inputFile.modulator.flush(inputFile.power, inputFile.stereo) { inputFile.buffer.put(it) } } else { val floats = buffer.slice(0, bytes).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer() var shouldFlush = true - inputFile.modulator.process(floats, inputFile.power) { + inputFile.modulator.process(floats, inputFile.power, inputFile.stereo) { inputFile.buffer.put(it) shouldFlush = false } if (shouldFlush) { - inputFile.modulator.flush(inputFile.power) { + inputFile.modulator.flush(inputFile.power, inputFile.stereo) { inputFile.buffer.put(it) } } @@ -199,7 +217,18 @@ fun main(args: Array<String>) { floatView.put(i, floatView.get(i) + z.x) floatView.put(i, floatView.get(i) + z.y) } - outputStream.write(outputBuffer.array()) + if (rfOutput) { + outputStream.write(outputBuffer.array()) + } else { + demodulator.process(floatView, stereo) { stereoPilot, it -> + if (stereoPilot != lastStereoPilot) { + println(if (stereoPilot) "stereo" else "mono") + } + lastStereoPilot = stereoPilot + buffer.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer().put(0, it.array()) + outputStream.write(buffer.array()) + } + } if (files.all { it.closed }) { break } |