[未解决]Android/Java播放正弦波模拟信号时出现噪音

我在Stackoverflow发表了相同的提问->点击跳转到StackOverFlow
java

最近在研究Java和Android声音信号生成的问题。在网上搜索了很长时间关于正弦波信号编码方式,基本上都是经过正弦函数android

y=sin(x)

来生成符合采样率的波形信号。代码大同小异,在Java上经过SourceDataLine来播放,在Android经过AudioTrack来播放。函数

Java:测试

this.aFormat = new AudioFormat(
    this.sample_Rate,				//SAMPLE_RATE
    this.sample_Size_in_Bits,			//SAMPLE SIZE IN BITS
    this.channels,				//CHANNELS
    this.signed,				//SIGNED
    this.bigEndian);			        //bigEndian
    SourceDataLine sourceDataLine = AudioSystem.getSourceDataLine(aFormat);
    sourceDataLine.open(aFormat);
    sourceDataLine.start();
    byte[] buf = new byte[1];
    for(int i=0;i<msecs*8;i++){
    double angle = (2.0*Math.PI*i)/(sample_Rate/frequency);
    buf[0] = (byte)(Math.sin(angle)*127);
    sourceDataLine.write(buf, 0, 1);
}

msecs是播放秒数,frequency是信号频率。this

经过SourceDataLine是能够每一个byte即时写入的。不用生成完整的buffer再一次写入sourceDataLine中。编码

Android:code

bufferSize = AudioTrack.getMinBufferSize(
    sampleRate,
    channels,
    encodingSize);
audioTrack = new AudioTrack(
    managerType,
    sampleRate,
    channels,
    encodingSize,
    bufferSize,
    trackMode);
audioTrack.setStereoVolume(AudioTrack.getMaxVolume(), AudioTrack.getMaxVolume());
audioTrack.play();
double phase = 0.0;
int amp = 10000;
short[] buffer = new short[bufferSize];
double phaseIncrement = (2 * Math.PI * frequency) / sampleRate;
for (int i = 0; i < bufferSize; i++) {
    buffer[i] = (short) (amp * Math.sin(phase));
    phase += phaseIncrement;
    }
while(flag) {
    audioTrack.write(buffer, 0, buffer.length);
    }

flag是播放进行/中止的标记。orm

通过测试发现。audioTrack没办法像sourceDataLine那样一次写入一个byte的数据(我也不知道为啥,就是播不出来。求大神给解答一下)。因此我选择了一次生成1秒的数据(就是采样率数量的样本)而后屡次写入audioTrack。至于为啥生成一秒……由于生成多了慢,用户等待时间就长,生成少了不到一个采样周期,音频不完整。rem

可是问题来了,经过这些代码生成的正弦波信号是有问题的。get

  1. 不稳定。设定相同的频率,好比14 kHz,播放的频率是不稳定的,听起来就是有时候声调高有时候声调低。这个问题在Java和Android代码中都有出现过。并且有时候在播放开始后,听到的声音明显带有颤动。须要关闭程序再从新开始几回才能有一个稳定的播放结果。

  2. 噪音,噪音问题很是严重。这样播放出来的正弦波信号掺杂着不一样频率的噪声。有时甚至调到22 kHz(理论上人耳不可听到),还能听到很大的嗡嗡声。在示波器上显示的FFT图像,也能够明显的看到有很大的噪音干扰。不知道是Java的问题仍是代码的问题,个人师兄用Matlab编写的代码用相同的公式在同型号电脑(MBA)上彻底没有噪声。示波器显示的图像也明显更干净一些。

有没有哪位大神能帮我解释一下这个问题,或者帮我改改代码。谢谢你们。

相关文章
相关标签/搜索