我有一个二进制数据流,想要将其转换为原始波形声音数据,然后可以发送给扬声器。
这就是老式调制解调器为了通过电话线传输二进制数据(产生典型的现代声音)所做的事情。这称为调制。
然后,我需要一个逆过程-从原始波形样本中,我想获得确切的二进制数据。这称为解调。
我找到了一种执行此操作的特殊方法-Frequency shift keying。问题是我找不到任何源代码。
您能指出我用任何一种语言实现的FSK吗?
还是提供带有可用源代码的任何其他编码二进制声音?
最佳答案
最简单的调制方案是amplitude modulation(在数字 Realm 中,技术上称为幅度偏移键控)。采取固定的频率(假设为10Khz),即“载波”,然后使用二进制数据中的位将其打开和关闭。如果数据速率为每秒10位,则将以该速率打开和关闭10KHz信号。解调将是一个(可选)10KHz滤波器,然后与阈值进行比较。这是一个相当简单的实现方案。通常,信号频率和可用带宽越高,则打开和关闭信号的速度就越快。
这里一个非常酷/有趣的应用程序是将代码编码/解码为莫尔斯电码,并查看您可以走多快。
FSK,在两个频率之间切换在带宽上更有效,并且更不受噪声影响,但是由于需要区分两个频率,解调器将变得更加复杂。
诸如Phase Shift Keying之类的高级调制方案擅长在给定的带宽和信噪比下获得最高的比特率,但实现起来较为复杂。模拟电话调制解调器需要处理某些带宽(例如,低至3Khz)和噪声限制。如果您需要在给定的带宽和噪声限制下获得尽可能高的比特率,那么这是可行的方法。
对于高级调制方案的实际代码示例,我将研究DSP供应商的应用笔记(例如TI和Analog 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。这些是电话键盘产生的音调,其中每个符号是两个频率的组合。如果您使用Google,则会发现很多源代码。根据您的应用程序/要求,这可能是一个简单的解决方案。
让我们深入了解一些简单的方案实现细节,例如我之前提到的莫尔斯电码。我们可以将“dot”用于0,将“dash”用于1。摩尔斯式方案的一个优点是它还解决了成帧问题,因为您可以在每个空间之后重新同步采样。为简单起见,我们选择“载波”频率假设您的电波输出为44Khz(16位单声道),频率为11KHz,我们还将使用方波来产生谐波,但我们不在乎。如果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
}
}
}
解码器稍微复杂一点,但这是一个概述:
关于algorithm - 数据转为音频并返回。带有源代码的调制/解调,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4976213/