产生音调跳过cretain频率的功能

以下内容来自Android应用程序:

    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吗? 任何你可以帮助我的东西?


主要问题是您需要将时间段作为浮点数保留,因为8000/789和8000/739会舍入为相同的整数:

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

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

作为一个次要的风格问题,我还建议从下面的行中删除“+1”,而不是要求cx / wide(你应该真的称为“增益”)仅限于[0,1]范围内:

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

你的原代码生成有效样本为因为+1(0,+ 2,0,+ 2,...),然后乘以cx/wide ,但是这会在你的事业上溢short val如果cx/wide大于1/2(因为2 * 32767 * 1/2是短路的最大值)。

更常见的做法是将cx/wide指定为(0,1)(其中0 =最小音量和1 =最大音量)范围内的增益,并且还可以在该函数中强制执行该约束。

第三个问题是您可能只使用输出的一半动态范围。 如果输出应该是16位带符号的采样(查找它),那么您可以将原始采样生成为? -1 : 1 ? -1 : 1而不是0/1。 如果输出流接受16位无符号采样,那么您希望将采样保留为0/1,但将volume更改为65535,并使用int而不是val作为short

链接地址: http://www.djcxy.com/p/62145.html

上一篇: Function to generate tone skipping cretain frequencies

下一篇: alias FIRLS filter order