gpt4 book ai didi

c# - FSK 解调 - 解析日本 EWS 数据

转载 作者:太空狗 更新时间:2023-10-29 19:44:06 24 4
gpt4 key购买 nike

【这不是重复的。类似的问题是关于人们可以控制源数据的场景。我没有。】

在日本有一种叫做“紧急警报广播系统”的东西。激活时看起来像这样:http://www.youtube.com/watch?v=9hjlYvp9Pxs

在上面的视频中,在 2:37 左右,发送了一个 FSK 调制信号。我想解析这个信号;即给定一个包含信号的 WAV 文件,我想以一个包含 0 和 1 的 StringBuilder 结束,以便稍后处理它们。我有二进制数据和所有规范,但问题是我对音频编程一无所知。 :(

这只是一个爱好项目,但我迷上了。电视和 radio 制造商可以接收到这个信号并让他们的设备对其使用react,所以这不会那么难,对吧? :(

关于信号的事实:

  • 标音为1024Hz,停音为640Hz
  • 每个音调长 15.625 毫秒
  • 信号开始前和信号结束后暂停 2 秒(可能用于检测目的)

到目前为止我做了什么:

  1. 编写一个简单的 RIFF 解析器,它接受 8 位单声道 WAV 文件并允许我从中获取样本。我已经对其进行了测试并且有效。
  2. 一个循环,需要 15.625 毫秒的样本,并且:
    1. 使用 RMS 寻找两秒的静音
    2. 使用 Goertzel 算法来确定信号是 1024Hz 还是 640Hz

我遇到的问题:

  • 0s 和 1s 在循环中根据测试数据被吞掉。
    • 考虑到信号的清晰度(YouTube 到 MP3 的翻录),这不应该发生。
    • 如果我在 Audacity 中生成一个重复的 01 序列 30 次,我的程序将选择 01 对中的大约 10 个,而不是 30 个
  • 有时 0 和 1 会交换(上述的副作用?)
  • 如果我调整代码使其适用于一个测试声音文件,其他测试声音文件将停止工作

我的问题:

  • 谁能给我一个关于如何在软件中正确完成 FSK 解码的高级概述?
  • 我是否需要应用某种滤波器将信号限制为 640Hz+1024Hz 并使其他所有信号静音?
  • 保持时机正确的最佳方法是什么?也许我做错了?
  • 有关此类音频处理的初学者文献的任何链接?我真的很想学习并让它发挥作用。

读取样本的代码是(简化):

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;
}

音频处理器只是一个类:

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;
}

感谢阅读。我希望你能帮助我。

最佳答案

这就是我的做法(高级描述)

  1. 通过 FFT 运行信号
  2. 寻找大约 640Hz+1024Hz 的稳定峰值(我会说至少 +/- 10Hz)
  3. 如果信号稳定大约 10 毫秒(我的意思是大约 95% 的样本处于相同范围 640Hz+/-10Hz(或 1024Hz+/-10Hz)),则将其视为对音调的检测。使用此检测还可以同步您的计时器,告诉您何时期待下一个音调。

关于c# - FSK 解调 - 解析日本 EWS 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20418630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com