2014-12-04 52 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