您的位置:首页 > 移动开发 > Android开发

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

2016-04-14 22:16 441 查看
我在Stackoverflow发表了相同的提问->点击跳转到StackOverFlow

最近在研究Java和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是信号频率。

通过SourceDataLine是可以每个byte即时写入的。不用生成完整的buffer再一次写入sourceDataLine中。

Android:

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是播放进行/停止的标记。

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

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

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

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

有没有哪位大神能帮我解释一下这个问题,或者帮我改改代码。谢谢大家。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息