gpt4 book ai didi

algorithm - 数据到音频并返回。使用源代码进行调制/解调

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:17:08 24 4
gpt4 key购买 nike

我有一个二进制数据流,想将其转换为原始波形声音数据,然后将其发送到扬声器。

这就是老式调制解调器所做的,以便通过电话线传输二进制数据(产生典型的现代声音)。它被称为调制。

然后我需要一个反向过程 - 从原始波形样本中,我想获得确切的二进制数据。这称为解调。

  • 任何比特率都可以作为开始。
  • 声音使用计算机扬声器播放并使用麦克风进行采样。
  • 带宽会很低(低质量麦克风)。
  • 有一些背景噪音,但不多。

  • 我找到了一种特殊的方法来做到这一点 - Frequency shift keying .问题是我找不到任何源代码。

    你能指点我用任何语言实现 FSK 吗?
    或者使用可用的源代码提供任何替代编码二进制<->声音?

    最佳答案

    最简单的调制方案是 amplitude modulation (从技术上讲,对于数字领域,这将称为幅移键控)。取一个固定频率(比如 10Khz),你的“载波”,并使用二进制数据中的位来打开和关闭它。如果您的数据速率为每秒 10 位,您将以该速率打开和关闭 10KHz 信号。解调将是一个(可选)10KHz 滤波器,然后与阈值进行比较。这是一个相当简单的实现方案。通常,信号频率和可用带宽越高,打开和关闭信号的速度就越快。

    这里一个非常酷/有趣的应用程序是将编码/解码为莫尔斯电码,看看你能走多快。

    FSK,两个频率之间的转换在带宽上更有效,对噪声更免疫,但会使解调器更复杂,因为您需要区分两个频率。

    高级调制方案,例如 Phase Shift Keying擅长在给定带宽和信噪比下获得最高比特率,但实现起来更复杂。模拟电话调制解调器需要处理特定带宽(例如低至 3Khz)和噪声限制。如果您需要在给定带宽和噪声限制的情况下获得尽可能高的比特率,那么这就是您要走的路。

    对于高级调制方案的实际代码示例,我会研究来自 DSP 供应商的应用笔记(例如 TIAnalog Devices),因为它们是 DSP 的常见应用。

    Implementing a PI/4 Shift D-QPSK Baseband Modem Using the TMS320C50

    QPSK modulation demystified

    V.34 Transmitter and Receiver Implementation on the TMS320C50 DSP

    另一种非常简单但效率不高的方法是使用 DTMF。这些是由电话键盘产生的音调,其中每个符号都是两个频率的组合。如果你谷歌你会发现很多源代码。根据您的应用程序/要求,这可能是一个简单的解决方案。

    让我们深入研究一些简单的方案实现细节,比如我之前提到的莫尔斯电码。我们可以使用 "dot"表示 0 和 "dash"表示 1。莫尔斯式方案的一个优点是它还解决了框架问题,因为您可以在每个空间后重新同步采样。为了简单起见,让我们选择“载波”频率在 11KHz 并假设您的波形输出是 44Khz,16 位,单声道。我们还将使用方波,它会产生谐波,但我们并不在乎。如果 11KHz 超出您麦克风的频率响应,那么只需将所有频率除以 2例如,我们将选择一些任意级别 10000,因此我们的“开启”波形如下所示:

    {10000, 10000, 0, 0, 10000, 10000, 0, 0, 10000, 0, 0, ...} // 4 samples = 11Khz period

    我们的“关闭”波形全为零。我将这部分的编码留给读者作为练习。

    所以我们有类似的东西:
    const int dot_samples = 400; // ~10ms - speed up later
    const int space_samples = 400; // ~10ms
    const int dash_samples = 800; // ~20ms

    void encode( uint8_t* source, int length, int16_t* target ) // assumes enough room in target
    {
    for(int i=0; i<length; i++)
    {
    for(int j=0; j<8; j++)
    {
    if((source[i]>>j) & 1) // If data bit is 1 we'll encode a dot
    {
    generate_on(&target, dash_samples); // Generate ON wave for n samples and update target ptr
    }
    else // otherwise a dash
    {
    generate_on(&target, dot_samples); // Generate ON wave for n samples and update target ptr
    }
    generate_off(&target, space_samples); // Generate zeros
    }
    }
    }

    解码器有点复杂,但这里有一个大纲:
  • 可选择带通滤波器对 11Khz 左右的采样信号进行滤波。这将提高嘈杂环境中的性能。 FIR 滤波器非常简单,有一些在线设计小程序可以为您生成滤波器。
  • 阈值信号。每个高于 1/2 最大振幅的值都是 1,每个低于 0 的值都是如此。这假设您已经对整个信号进行了采样。如果这是实时的,您要么选择一个固定的阈值,要么进行某种自动增益控制,在一段时间内跟踪最大信号电平。
  • 扫描点或破折号的开头。您可能希望在您的点周期中至少看到一定数量的 1,以将样本视为一个点。然后继续扫描,看看这是否是一个破折号。不要指望一个完美的信号 - 您会在 1 的中间看到几个 0,在 0 的中间看到几个 1。如果噪音很小,那么区分“开”时段和“关”时段应该相当容易。
  • 然后将上述过程反过来。如果您看到破折号将 1 位插入您的缓冲区,如果一个点插入一个零。
  • 关于algorithm - 数据到音频并返回。使用源代码进行调制/解调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4976213/

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