本文介绍了数据到音频并返回。采用源代码进行调制/解调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个二进制数据流,想将其转换成原始的波形声音数据,我可以发送给演讲者。



这是老学校调制解调器为了通过电话线传输二进制数据(产生典型的调制解调器声音)。它被称为调制。



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



我发现了一种特殊的方式来做到这一点 - 。问题是我找不到任何源代码。



你可以指出任何语言的FSK的实现吗?或者提供可用的源代码的任何替代编码二进制声音?



谢谢!

解决方案

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



这里非常酷/有趣的应用是编码/解码作为莫尔斯码,看看你可以走多快。



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



高级调制方案,如有利于获得给定带宽和信噪比的最高比特率,但是实现起来更复杂。需要模拟电话调制解调器来处理一定的带宽(例如3Khz)和噪声限制。如果您需要获得最高可能的比特率,那么给出带宽和噪声限制就可以了。



对于高级调制方案的实际代码示例,我将调查应用笔记DSP厂商(例如和)作为是DSP的常见应用程序。









另一个非常简单而不是很有效的方法是使用DTMF。那些是由电话键盘产生的音调,其中每个符号是两个频率的组合。如果你在Google上找到很多源代码。根据您的应用/要求,这可能是一个简单的解决方案。



让我们来看一些简单的方案实现细节,就像前面提到的莫尔斯代码一样。我们可以使用dot为0,将dash用作1。一个类似莫斯的方案的优点在于它也解决了框架问题,因为您可以在每个空间之后重新同步采样,为简单起见,我们选择载波频率在11KHz,假设您的波形输出为44Khz,16位,单声道,我们还将使用一个方波,它将产生谐波,但我们不太在意,如果11KHz超出麦克风的频率响应,那么只需将所有频率除以2例如,我们将选择一些任意级别10000,因此我们的on波形如下所示:

  {10000,10000,0 ,0,10000,10000,0,0,10000,0,0,...} // 4个样本= 11Khz期间

和我们的关闭波形只是全零,我将这部分的代码作为一个excersize留给读者。



所以我们有一些东西:

  const int dot_samples = 400; //〜10ms  - 加快速度
const int space_samples = 400; //〜10m s
const int dash_samples = 800; //〜20ms

void encode(uint8_t * source,int length,int16_t * target)//假设目标空间足够
{
for(int i = 0; i<对于(int j = 0; j< 8; j ++)
{
if((source [i]>> j)& ; 1)//如果数据位为1,我们将编码一个点
{
generate_on(& target,dash_samples); //为n个样本生成ON波,并更新目标ptr
}
else //否则一个破折号
{
generate_on(& target,dot_samples); //为n个样本生成ON波,并更新目标ptr
}
generate_off(& target,space_samples); //生成零
}
}
}

解码器有点复杂,但这里有一个大纲:


  1. 可选带通滤波采样信号约11Khz。这将提高嘈杂环境中的表现。 FIR滤镜非常简单,有几个在线设计小程序可以为您生成滤镜。

  2. 对信号进行阈值。每1/2个最大振幅值都为1,每个值低于0。这假设您已对整个信号进行采样。如果这是实时的,您可以选择一个固定的阈值或进行某种自动增益控制,您可以在一段时间内跟踪最大信号电平。

  3. 扫描点或破折号的开始。您可能希望在您的点周期中至少看到一个1的值,以便将样本视为一个点。然后继续扫描,看看这是否是破折号。不要指望一个完美的信号 - 你会在你的1中间看到几个0,在0的中间有几个1。如果没有什么噪音,那么区分开时间段与关时段应该是相当容易的。

  4. 然后反转上述过程。如果您看到破折号将1位缓冲区推送到缓冲区,如果点推零。


I have a stream of binary data and want to convert it to raw waveform sound data, which I can send to the speakers.

This is what the old school modems did in order to transfer binary data over the phone line (producing the typical modemish sound). It is called modulation.

Then I need a reverse process - from the raw waveform samples, I want to obtain the exact binary data. This is called demodulation.

I found one particular way to do this - Frequency shift keying. The problem is I can't find any source code.

Can you point me to an implementation of FSK in any language? Or offer any alternative encoding binary<->sound with available source code?

Thank you!

解决方案

The simplest modulation scheme would be amplitude modulation (technically for the digital realm this would be called Amplitude Shift Keying). Take a fixed frequency (let's say 10Khz), your "carrier wave", and use the bits in your binary data to turn it on and off. If your data rate is 10 bits per second you will be toggling the 10KHz signal on and off at that rate. The demodulation would be an (optional) 10KHz filter followed by comparing with a threshold. This is a fairly simple scheme to implement. Generally the higher the signal frequency and your available bandwidth, the faster you can switch that signal on and off.

A very cool/fun application here would be to encode/decode as morse code and see how fast you can go.

FSK, shifting between two frequencies is more efficient in bandwidth and more immune to noise but will make the demodulator more complex as you need to distinguish between the two frequencies.

Advanced modulation scheme such as Phase Shift Keying are good at getting the highest bit rate for a given bandwidth and signal to noise ratio but they are more complicated to implement. Analog phone modems needed to deal with certain bandwidth (e.g. as little as 3Khz) and noise limitations. If you need to get the highest possible bitrate given bandwidth and noise limitations then is the way to go.

For actual code samples of advanced modulation schemes I would investigate application notes from DSP vendors (such as TI and Analog Devices) as those were common applications for DSPs.

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

Another very simple and not so efficient method is to use DTMF. Those are the tones generated by phone keypads where each symbol is a combination of two frequencies. If you Google you'll find a lot of source code. Depending on your application/requirements this may be a simple solution.

Let's dive in to some simple scheme implementation details, something like the morse code I mentioned earlier. We can use "dot" for 0 and "dash' for 1. An advantage of a morse like scheme is that it also solves the framing problem as you can resynchronize your sampling after every space. For simplicity let's pick the "Carrier Wave" frequency at 11KHz and assume your wave output is 44Khz, 16 bit, mono. We'll also use a square wave which will create harmonics but we don't really care. If 11KHz is beyond your microphone's frequency response then just divide all frequencies by 2 e.g. We'll pick some arbitrary level 10000 and so our "on" waveform looks like this:

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

and our "off" waveform is just all zeros. I leave the coding of this part as an excersize to the reader.

And so we have something like:

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

The decoder is a bit more complicated but here's an outline:

  1. Optionally band-pass filter the sampled signal around 11Khz. This will improve performance in a noisy enviornment. FIR filters are pretty simple and there are a few online design applets that will generate the filter for you.
  2. Threshold the signal. Every value above 1/2 maximum amplitude is 1 every value below is 0. This assumes you have sampled the entire signal. If this is in real time you either pick a fixed threshold or do some sort of automatic gain control where you track the maximum signal level over some time.
  3. Scan for start of dot or dash. You probably want to see at least a certain number of 1's in your dot period to consider the samples a dot. Then keep scanning to see if this is a dash. Don't expect a perfect signal - you'll see a few 0's in the middle of your 1's and a few 1's in the middle of your 0's. If there's little noise then differentiating the "on" periods from the "off" periods should be fairly easy.
  4. Then reverse the above process. If you see dash push a 1 bit to your buffer, if a dot push a zero.

这篇关于数据到音频并返回。采用源代码进行调制/解调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-26 21:54