Added frequency markers to waterfall

pull/39/head
Marek Ossowski 2025-08-05 00:14:52 +02:00
rodzic 1a722d5289
commit ba4b8bc4a5
2 zmienionych plików z 23 dodań i 5 usunięć

Wyświetl plik

@ -33,9 +33,11 @@ public class Demodulator {
public int syncPulseOffset;
public float frequencyOffset;
public static final double syncPulseFrequency = 1200;
public static final double blackFrequency = 1500;
public static final double whiteFrequency = 2300;
Demodulator(int sampleRate) {
double blackFrequency = 1500;
double whiteFrequency = 2300;
double scanLineBandwidth = whiteFrequency - blackFrequency;
frequencyModulation = new FrequencyModulation(scanLineBandwidth, sampleRate);
double syncPulse5msSeconds = 0.005;
@ -65,7 +67,6 @@ public class Demodulator {
baseBandLowPass.taps[i] = (float) (kaiser.window(2.0, i, baseBandLowPass.length) * Filter.lowPass(cutoffFrequency, sampleRate, i, baseBandLowPass.length));
double centerFrequency = (lowestFrequency + highestFrequency) / 2;
baseBandOscillator = new Phasor(-centerFrequency, sampleRate);
double syncPulseFrequency = 1200;
syncPulseFrequencyValue = (float) ((syncPulseFrequency - centerFrequency) * 2 / scanLineBandwidth);
syncPulseFrequencyTolerance = (float) (50 * 2 / scanLineBandwidth);
double syncPorchFrequency = 1500;

Wyświetl plik

@ -15,6 +15,7 @@ import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
@ -43,6 +44,7 @@ import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.ShareActionProvider;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.core.graphics.Insets;
import androidx.core.os.LocaleListCompat;
import androidx.core.view.MenuItemCompat;
@ -72,6 +74,7 @@ public class MainActivity extends AppCompatActivity {
private ImageView peakMeterView;
private PixelBuffer imageBuffer;
private ShortTimeFourierTransform stft;
private final int binWidthHz = 10;
private short[] shortBuffer;
private float[] recordBuffer;
private AudioRecord audioRecord;
@ -223,8 +226,22 @@ public class MainActivity extends AppCompatActivity {
double lowest = Math.log(1e-9);
double highest = Math.log(1);
double range = highest - lowest;
int lowestBin = 14;
for (int i = 0; i < stride; ++i)
waterfallPlotBuffer.pixels[line + i] = rainbow((Math.log(stft.power[i + 14]) - lowest) / range);
waterfallPlotBuffer.pixels[line + i] = rainbow((Math.log(stft.power[i + lowestBin]) - lowest) / range);
int[] markerFrequencies = new int[] {
(int)Demodulator.syncPulseFrequency,
(int)Demodulator.blackFrequency,
(int)Demodulator.whiteFrequency,
};
for (int freq: markerFrequencies) {
int marker = freq / binWidthHz - lowestBin;
waterfallPlotBuffer.pixels[line + marker - 1] = Color.BLACK;
waterfallPlotBuffer.pixels[line + marker] = ColorUtils.blendARGB(waterfallPlotBuffer.pixels[line + marker], Color.GREEN, 0.8f);
waterfallPlotBuffer.pixels[line + marker + 1] = Color.BLACK;
}
System.arraycopy(waterfallPlotBuffer.pixels, line, waterfallPlotBuffer.pixels, line + stride * (waterfallPlotBuffer.height / 2), stride);
}
}
@ -315,7 +332,7 @@ public class MainActivity extends AppCompatActivity {
if (rateChanged) {
decoder = new Decoder(scopeBuffer, imageBuffer, getString(R.string.raw_mode), recordRate);
decoder.setMode(currentMode);
stft = new ShortTimeFourierTransform(recordRate / 10, 3);
stft = new ShortTimeFourierTransform(recordRate / binWidthHz, 3);
}
startListening();
} else {