FSK Demodulation - Japan EWS Data Analysis

【This is not a duplicate. Similar questions apply to scenarios in which people control the source data. I dont know.】

In Japan, there is something called the “Emergency Warning Broadcasting System”. When activated, it looks like this: http://www.youtube.com/watch?v=9hjlYvp9Pxs

In the above video, at about 2:37, an FSK modulated signal is sent. I want to parse this signal; that is, given the WAV file that contains the signal, I want to get a StringBuilder that contains 0 and 1 for further processing. I have a specification for binary data and everything, but the problem is that I don't know anything about sound programming. :(

This is only for the hobby of the project, but I became connected. Televisions and radios can pick up this signal and make their devices do something in response to this, so it can't be that hard, can it ?: (

Signal Facts:

  • The marking mark is 1024 Hz, and the stop signal is 640 Hz
  • Each tone lasts 15.625 m.
  • 2-second pause before and after the signal (possibly for detection purposes)

What i have done so far:

  • Write a simple RIFF parser that accepts 8-bit mono-WAV files and allows me to get samples from them. I tested it and it works.
  • A cycle that takes 15.625 ms samples and:
    • Using RMS to find two seconds of silence.
    • Uses the Goertzel algorithm to determine if a signal is 1024 Hz or 640 Hz

The problems that I have are:

  • 0s and 1s are swallowed during the cycle depending on the test data.
    • Given the clarity of the signal (playback on YouTube-MP3), this should not be.
    • If I create a repeating sequence 01 in Audacity 30 times, my program will collect about 10 from pairs 01 instead of 30
  • Sometimes 0s and 1s change places (side effect higher?)
  • If I configure the code to work with one test sound file, the other test sound files stop working.

My questions:

  • Can someone give me a high level review on how FSK decoding will work correctly in software?
  • Do I need to apply some kind of filter that limits the signal to 640 Hz + 1024 Hz and turns off everything else?
  • What is the best approach for choosing the right time? Maybe I'm doing it wrong?
  • Any links to budding literature on this type of sound processing? I would really like to study and get this job.

Code that reads samples (simplified):

StringBuilder ews_bits = new StringBuilder(); double[] samples = new double[(int)(samplesPerMs * 16.625D)]; int index = 0, readTo = /* current offset + RIFF subChunk2Size */; BinaryReader br = /* at start of PCM data */; while (br.BaseStream.Position < readTo) { switch (bitsPerSample / 8) { case 1: // 8bit samples[index++] = ((double)br.ReadByte() - 127.5D) / 256D; break; case 2: // 16bit samples[index++] = (double)br.ReadInt16() / 32768D; break; } if (index != samples.Length) continue; /****** The sample buffer is full and we must process it. ******/ if (AudioProcessor.IsSilence(ref samples)) { silence_count++; if (state == ParserState.Decoding && silence_count > 150) { // End of EWS broadcast reached. EwsSignalParser.Parse(ews_bits.ToString()); /* ... reset state; go back looking for silence... */ } goto Done; } /****** The signal was not silence. ******/ if (silence_count > 120 && state == ParserState.SearchingSilence) state = ParserState.Decoding; if (state == ParserState.Decoding) { AudioProcessor.Decode(ref samples, sampleRate, ref ews_bits); bool continue_decoding = /* check first 20 bits for signature */; if (continue_decoding) goto Done; // If we get here, we were decoding a junk signal. state = ParserState.SearchingSilence; } /* Not enough silence yet */ silence_count = 0; Done: index = 0; } 

An audio processor is just a class with:

 public static void Decode(ref double[] samples, int sampleRate, ref StringBuilder bitHolder) { double freq_640 = GoertzelMagnitude(ref samples, 640, sampleRate); double freq_1024 = GoertzelMagnitude(ref samples, 1024, sampleRate); if (freq_640 > freq_1024) bitHolder.Append("0"); else bitHolder.Append("1"); } public static bool IsSilence(ref double[] samples) { // power_RMS = sqrt(sum(x^2) / N) double sum = 0; for (int i = 0; i < samples.Length; i++) sum += samples[i] * samples[i]; double power_RMS = Math.Sqrt(sum / samples.Length); return power_RMS < 0.01; } /// <remarks>http://www.embedded.com/design/embedded/4024443/The-Goertzel-Algorithm</remarks> private static double GoertzelMagnitude(ref double[] samples, double targetFrequency, int sampleRate) { double n = samples.Length; int k = (int)(0.5D + ((double)n * targetFrequency) / (double)sampleRate); double w = (2.0D * Math.PI / n) * k; double cosine = Math.Cos(w); double sine = Math.Sin(w); double coeff = 2.0D * cosine; double q0 = 0, q1 = 0, q2 = 0; for (int i = 0; i < samples.Length; i++) { double sample = samples[i]; q0 = coeff * q1 - q2 + sample; q2 = q1; q1 = q0; } double magnitude = Math.Sqrt(q1 * q1 + q2 * q2 - q1 * q2 * coeff); return magnitude; } 

Thanks for reading. I hope you help me.

+8
c # algorithm audio signal-processing
source share
2 answers

Here is how I did it (high level description)

  • Run your signal through FFT
  • find stable peaks at about 640 Hz + 1024 Hz (I would say at least +/- 10 Hz).
  • if the signal is stable for about 10 ms (at a stable value, about 95% of the samples are in the same range of 640 Hz +/- 10 Hz (or 1024 Hz +/- 10 Hz) take it as tone detection. detection also synchronizes your timer, which tells you when to expect the next tone.
+2
source share

I got about 90% of the work after overwriting the parsing cycle and detecting silence. There were two main problems in my implementation. The first was that the silence detector was excessive, so I changed it to process every millisecond of samples for every half million second of samples. This led me exactly to the start of the FSK data.

The next problem was that I thought then that I could naively allow the demodulator to watch 15.625 ms of samples, since it itself works through a WAV file. It turns out that although this works fine for the first 90 bits or so, the tones eventually get a little longer or shorter than expected, and the demodulator fails. The current code finds and corrects 13 bits with this synchronization mismatch. Particularly vulnerable to this are places where the signal changes from label to space and vice versa.

Guess why the word "analogue" contains "anal." It. I would love to know more about signal theory and digital signal processing. :(

As I discovered all this: I imported MP3 and trimmed it to the FSK part using Audacity. Then I created Audacity to create shortcuts for each bit. After that, I looked at the bits on the labels.

+1
source share

All Articles