试图解码在音频上编码的FM信号

时间:2015-12-21 21:54:05

标签: c++ c

我的音频信号上有一种FM编码信号。编码信号使用this Biphase mark coding technique< - 请参阅本页末尾。

此信号是时间码的数字表示,以小时,分钟,秒和帧为单位。它基本上是这样的:

  1. 让我们考虑一下,我们每秒工作25帧;
  2. 我们知道代码每帧传输80位信息(即每帧80位x每秒25帧=每秒2000位);
  3. 以每秒44100个样本采样波。因此,如果我们划分44100/2000,我们会看到每个位使用22,05个样本;
  4. 当信号改变符号时会发生一点。
  5. 如果波在整个比特周期内改变符号并保持其符号,则它是零。如果波在一个比特周期内改变符号两次,那么它就是一个;
  6. 我的代码是这样做的:

    1. 检测到第一个过零点,即时钟开始(to)
    2. 测量to = to + 0.75 * bitPeriod ... 0.75的等级以给出容差。
    3. 如果第二级别不同,我们有1,如果不是,我们有0;
    4. 这是代码:

      // data is a C array of floats representing the audio levels
      
      float bitPeriod = ceil(44100 / 2000);
      int firstZeroCrossIndex = findNextZeroCross(data);
      // firstZeroCrossIndex is the value where the signal changed
      // for example: data[0] = -0.23 and data[1] = 0.5
      // firstZeroCrossIndex will be equal to 1
      
      // if firstZeroCrossIndex is invalid, go away
      if (firstZeroCrossIndex < 0) return 
      
      float firstValue = data[firstZeroCrossIndex];
      int lastSignal = sign(firstValue);
      
      if (lastSignal == 0) return; // invalid, go away
      
      while (YES) {
      
          float newValue = data[firstZeroCrossIndex + 0.75* bitPeriod];
          int newSignal = sign(newValue);
      
          if (lastSignal == newSignal)
            printf("0");
          else 
            printf("1");
      
          firstZeroCrossIndex += bitPeriod;
      
          // I think I must invert the signal here for the next loop interaction
          lastSignal = -newSignal;
      
          if (firstZeroCrossIndex > maximuPossibleIndex)
            break;
      
      }
      

      这段代码对我来说是合乎逻辑的,但是来自它的结果完全是胡说八道。我错过了什么?

      注意:此代码通过实时信号执行,并从循环环形缓冲区读取值。如果值为负,则sign返回-1;如果值为正,则返回1;如果值为零,则返回0。

1 个答案:

答案 0 :(得分:2)

很酷的问题! : - )

代码以两种独立的方式失败:

  1. 您正在搜索第一个(任意)过零点。这很好。但是有50%的可能性,这个转换发生在每个位(01)之前或者此转换是否标记为{ {1}}位。如果你在开始时弄错了,你最终会胡说八道。

  2. 您继续将1(float,22.05)添加到bitPeriod(int)。这意味着您的采样点将慢慢与模拟信号不同相,当采样点接近信号转换时,您将看到奇怪的效果。你至少会定期得到胡说八道。

  3. 解决方案1:您必须首先搜索至少一个firstZeroCrossIndex,以便知道哪个转换仅指示下一位,哪个指示0位。实际上,您需要在每个'0'位重新同步您的采样器。

    解决方案2:不要将1添加到您的采样点。而是像在开始时一样搜索下一个转换。下一个转换要么是“半个”,要么是“完整位”,它可以为您提供所需的信息。在“半个小时”之后,你必须看到另一个'半个'时期。如果没有,则必须重新同步,因为您意外地进行了开始转换的中间转换。这正是我在1中谈论的重新同步。