2014-12-04 41 views
0

下面是從一個Android應用採取:函數來生成頻調跳過cretain頻率

public void genTone(int freq){ 
     for(int i = 0; i<numSamples; i++){ 
      samples[i] = Math.pow(-1, (float)(i/(sampleRate/freq))); 
     } 
     int idx = 0; 
     int volume = 32767 * cx/wide; 
     for (final double dVal : samples) { 
      final short val = (short) ((dVal+1) * volume); 

      generatedSnd[idx++] = (byte) (val & 0x00ff); 
      generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8); 
      if(isRecording){ 
       toRec.add((byte)(val & 0x00ff)); 
       toRec.add((byte)((val & 0xff00) >>> 8)); 
      } 
     } 
    } 

上面的代碼是在Android的Java函數應用中的產生方波具有指定頻率。頻率由整數'音符'確定,該音符是MotionEvent的最後記錄位置除以屏幕高度的值。頻率爲440 * 2 ^(注/ 12)。我用文本輸出了音符和頻率,並輸出我想要的內容,但是在某些音符處,即使它在文本中輸出不同的頻率,聽起來也完全一樣。 8000是否過低(每秒)sampleRate?這是一個衆所周知的bug嗎?任何你可以幫助我的東西?

+0

是sampleRate一個int或float? – jaket 2014-12-04 22:59:05

+0

@jaket Int:8000,它有什麼區別?無可否認,idk的四捨五入是如何運作的。 – user2649681 2014-12-05 00:30:50

+0

什麼是cx,wide,numSamples和freq在每種情況下,你希望是不同的,但聽起來相同?聞起來像整數溢出給我。除非您生成一些高頻音調,否則8 KHz不是問題。 – 2014-12-05 03:22:53

回答

1

的主要問題是,你需要離開的期間爲float,因爲七百八十九分之八千和七百三十九分之八千否則一輪相同的整數:

float period = (float)sampleRate/(float)freq; 

for(int i = 0; i<numSamples; i++){ 
    samples[i] = ((int)(i/period) % 2)==0 ? 0 : 1; 
} 

作爲次要風格的問題,我也想建議刪除「+1」從以下行,而是要求CX /寬(你應該真的叫「增益」)範圍內的獨家[0,1]:

final short val = (short) ((dVal) * volume); 

你的原代碼由於+1,有效地將樣本生成爲(0,+ 2,0,+ 2,...),然後相乘通過cx/wide,但如果cx/wide大於1/2(因爲2 * 32767 * 1/2是短的最大值),則會導致short val中的溢出。

更常見的做法是指定cx/wide作爲(0,1)(其中0 =最小體積和1 =最大體積)範圍內的增益,並且還在該函數中強制執行該約束。

第三個問題是您可能只使用輸出的一半動態範圍。如果輸出應該是16位帶符號的採樣(查找它),那麼您可以生成原始採樣爲? -1 : 1而不是0/1。如果輸出流接受16位無符號採樣,那麼您希望將採樣保留爲0/1,但將volume更改爲65535,並且對於val,使用int而不是short

+0

您的[其他問題](http://stackoverflow.com/questions/27296929/record-audio-played-on-audiotrack)建議您需要ENCODING_PCM_16BIT,這將是未簽名的。 – 2014-12-05 14:50:12

+0

它不是已經在1,-1之間產生了嗎? 等等,ENCODING_PCM_16BIT是否接受無符號? – user2649681 2014-12-05 14:56:01

+0

你原來的'samples []'應該是-1,1,-1,-1,但是你的'dVal + 1'將它變成0,2,0,2。 – 2014-12-05 14:58:14