Mar*_*cek 22 algorithm audio encoding signal-processing
我有一个二进制数据流,并希望将其转换为原始波形声音数据,我可以将其发送到扬声器.
这就是老派调制解调器为了通过电话线传输二进制数据所做的事情(产生典型的现代声音).它被称为调制.
然后我需要一个反向过程 - 从原始波形样本,我想获得确切的二进制数据.这称为解调.
我找到了一种特殊的方法 - 频移键控.问题是我找不到任何源代码.
你能指点我用任何语言实现FSK吗?
或者提供任何替代编码二进制< - >声音和可用的源代码?
Guy*_*ton 20
最简单的调制方案是幅度调制(技术上对于数字领域,这将被称为幅移键控).采用固定频率(比如说10Khz),你的"载波",并使用二进制数据中的位来打开和关闭它.如果您的数据速率是每秒10位,您将以该速率打开和关闭10KHz信号.解调将是(可选的)10KHz滤波器,然后与阈值进行比较.这是一个相当简单的实现方案.通常,信号频率和可用带宽越高,开关信号的速度就越快.
这里一个非常酷/有趣的应用程序将编码/解码为莫尔斯代码,看看你能走多快.
FSK在两个频率之间转换,带宽效率更高,对噪声更具免疫力,但由于您需要区分两个频率,因此会使解调器更加复杂.
诸如相移键控之类的高级调制方案擅长于在给定带宽和信噪比下获得最高比特率,但是它们实现起来更复杂.模拟电话调制解调器需要处理某些带宽(例如低至3Khz)和噪声限制.如果您需要在给定带宽和噪声限制的情况下获得尽可能高的比特率,那么就是要走的路.
对于高级调制方案的实际代码示例,我将研究DSP供应商(如TI和ADI公司)的应用笔记,因为这些是DSP的常见应用.
使用TMS320C50实现PI/4移位D-QPSK基带调制解调器
另一种非常简单且不那么有效的方法是使用DTMF.这些是由电话键盘产生的音调,其中每个符号是两个频率的组合.如果你谷歌,你会发现很多源代码.根据您的应用/要求,这可能是一个简单的解决方案.
让我们深入研究一些简单的方案实现细节,比如我前面提到的莫尔斯代码.我们可以使用"dot"代表0和"破折号"代表1.莫尔斯式方案的一个优点是它也解决了框架问题,因为你可以在每个空格后重新同步你的采样.为简单起见,我们选择"载波"频率在11KHz并假设你的波输出是44Khz,16位,单声道.我们也会使用方波产生谐波,但我们并不在意.如果11KHz超出你的麦克风的频率响应那么只需将所有频率除以2例如,我们将选择一些任意级别10000,因此我们的"开启"波形如下所示:
{10000, 10000, 0, 0, 10000, 10000, 0, 0, 10000, 0, 0, ...} // 4 samples = 11Khz period
Run Code Online (Sandbox Code Playgroud)
而我们的"关闭"波形只是全零.我把这部分的编码留给了读者.
所以我们有类似的东西:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
解码器有点复杂,但这是一个大纲: