[未解决]Android/Java播放正弦波模拟信号时出现噪音
2016-04-14 22:16
441 查看
我在Stackoverflow发表了相同的提问->点击跳转到StackOverFlow
最近在研究Java和Android声音信号生成的问题。在网上搜索了很长时间关于正弦波信号编码方式,基本上都是通过正弦函数
来生成符合采样率的波形信号。代码大同小异,在Java上通过SourceDataLine来播放,在Android通过AudioTrack来播放。
Java:
msecs是播放秒数,frequency是信号频率。
通过SourceDataLine是可以每个byte即时写入的。不用生成完整的buffer再一次写入sourceDataLine中。
Android:
flag是播放进行/停止的标记。
经过测试发现。audioTrack没办法像sourceDataLine那样一次写入一个byte的数据(我也不知道为啥,就是播不出来。求大神给解答一下)。所以我选择了一次生成1秒的数据(就是采样率数量的样本)然后多次写入audioTrack。至于为啥生成一秒……因为生成多了慢,用户等待时间就长,生成少了不到一个采样周期,音频不完整。
但是问题来了,通过这些代码生成的正弦波信号是有问题的。
不稳定。设定相同的频率,比如14 kHz,播放的频率是不稳定的,听起来就是有时候声调高有时候声调低。这个问题在Java和Android代码中都有出现过。而且有时候在播放开始后,听到的声音明显带有颤动。需要关闭程序再重新开始几次才能有一个稳定的播放结果。
噪音,噪音问题非常严重。这样播放出来的正弦波信号掺杂着不同频率的噪声。有时甚至调到22 kHz(理论上人耳不可听到),还能听到很大的嗡嗡声。在示波器上显示的FFT图像,也可以明显的看到有很大的噪音干扰。不知道是Java的问题还是代码的问题,我的师兄用Matlab编写的代码用相同的公式在同型号电脑(MBA)上完全没有噪声。示波器显示的图像也明显更干净一些。
有没有哪位大神能帮我解释一下这个问题,或者帮我改改代码。谢谢大家。
最近在研究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)上完全没有噪声。示波器显示的图像也明显更干净一些。
有没有哪位大神能帮我解释一下这个问题,或者帮我改改代码。谢谢大家。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法