[未解決]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)上徹底沒有噪聲。示波器顯示的圖像也明顯更乾淨一些。

有沒有哪位大神能幫我解釋一下這個問題,或者幫我改改代碼。謝謝你們。

相關文章
相關標籤/搜索