为什么使用java音响系统时,英语频率会升高得太高

为什么使用java音响系统时,英语频率会升高得太高,java,audio,trigonometry,frequency,pitch,Java,Audio,Trigonometry,Frequency,Pitch,我尝试从一个开始音符到一个结束音符(下面的java代码)创建一个glissando(平滑音高上升)。我从开始音符频率线性上升到停止音符频率,如下所示 for (i = 0; i < b1.length; i++) { instantFrequency = startFrequency + (i * deltaFreq / nrOfSamples); b1[i] = (byte) (127 * Math.sin(2 * Math

我尝试从一个开始音符到一个结束音符(下面的java代码)创建一个glissando(平滑音高上升)。我从开始音符频率线性上升到停止音符频率,如下所示

        for (i = 0; i < b1.length; i++) {
            instantFrequency = startFrequency + (i * deltaFreq / nrOfSamples);
            b1[i] = (byte) (127 * Math.sin(2 * Math.PI * instantFrequency * i / sampleRate));
        }

出现问题的原因是每个帧的相邻节距太宽。
instantFrequency
的计算结果很好,但通过将其乘以
i
得出一个值是可疑的。从i到i+1时,前进的距离如下所示:

distance = ((n+1) * instantFrequency[n+1]) - (n * instantFrequency[n]) 
该值大于所需的增量值,该值应等于新的
瞬时频率
值,例如:

distance = ((n+1) * instantFrequency[n]) - (n * instantFrequency[n]) 
下面的代码帮助我解决了这个问题,这让我困惑了好几个小时。只有在熟睡之后,我才能得到上面的简明解释(在编辑中添加)

下面是一个更简单的例子来说明这个问题。因为问题发生在sin函数计算之前,所以我排除了它们以及trig计算之后的所有操作

public class CuriousSeries {

    public static void main(String[] args) {

        double aa = 1;  // analogous to your 220
        double bb = 2;  // analogous to your 440
        
        double delta = bb - aa;
        
        int steps = 10;
        double[] travelVals = new double[steps + 1]; 
        
        // trip aa
        for (int i = 0; i <= 10; i++) {
            travelVals[i] = aa * i;
            System.out.println("aa trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip ab
        for (int i = 0; i <= 10; i++) {
            double instantFreq = aa + (i / 10.0) * delta;
            travelVals[i] = instantFreq * i;
            System.out.println("ab trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip bb
        for (int i = 0; i <= 10; i++) {
            travelVals[i] = bb * i;
            System.out.println("bb trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip cc
        travelVals[0] = 0;
        for (int i = 1; i <= 10; i++) {
            double travelIncrement = aa + (i / 10.0) * delta;
            travelVals[i] = travelVals[i-1] + travelIncrement;
            System.out.println("cc trip. travelVals[" + i + "] = " + travelVals[i]);
        }
    }
}
这一“步”所走的距离接近3,而不是期望的2

在最后一个示例中,tripcc
travelIncrement
的计算与
瞬时频率的计算相同。但在这种情况下,增量只是添加到前一个位置

事实上,为了音频合成的目的(在计算创建波形时),使用加法来最小化cpu成本是有意义的。按照这些思路,我通常会执行以下操作,从内部循环中删除尽可能多的计算:

double cursor = 0;
double prevCursor = 0;
double pitchIncrement = 2 * Math.PI * frequency / sampleRate;

for (int i = 0; i < n; i++) {
    cursor = prevCursor + pitchIncrement;
    audioVal[i] = Math.sin(cursor);
    prevCursor = cursor;
}
双光标=0;
双光标=0;
双纵摇增量=2*Math.PI*频率/采样器;
对于(int i=0;i
奇怪的是,它精确地上升到660赫兹(八度和五度,听它,E高于440)。这可能是个线索。非常感谢!使用delta phase还解决了连接不同部件时的瞬时点击问题,这是我列表中的下一个问题,太棒了!因此,最终,不希望的额外相位增加来自于每次切换到更高的频率,其中波已经是更进一步的相位,通过确保相位差精确,使用delta相位解决了这一问题。另外,感谢你的提示,从内部循环中删除尽可能多的计算!现在,我们有了所有的工具来重新创建传奇的VHX简介,万岁,你离创建一个FM合成器(使用相位调制)不远了,沿着经典的雅马哈DX-7或当前的本地仪器FM8的路线!
public class CuriousSeries {

    public static void main(String[] args) {

        double aa = 1;  // analogous to your 220
        double bb = 2;  // analogous to your 440
        
        double delta = bb - aa;
        
        int steps = 10;
        double[] travelVals = new double[steps + 1]; 
        
        // trip aa
        for (int i = 0; i <= 10; i++) {
            travelVals[i] = aa * i;
            System.out.println("aa trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip ab
        for (int i = 0; i <= 10; i++) {
            double instantFreq = aa + (i / 10.0) * delta;
            travelVals[i] = instantFreq * i;
            System.out.println("ab trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip bb
        for (int i = 0; i <= 10; i++) {
            travelVals[i] = bb * i;
            System.out.println("bb trip. travelVals[" + i + "] = " + travelVals[i]);
        }
        
        // trip cc
        travelVals[0] = 0;
        for (int i = 1; i <= 10; i++) {
            double travelIncrement = aa + (i / 10.0) * delta;
            travelVals[i] = travelVals[i-1] + travelIncrement;
            System.out.println("cc trip. travelVals[" + i + "] = " + travelVals[i]);
        }
    }
}
ab trip. travelSum[9] = 17.099999999999998
ab trip. travelSum[10] = 20.0
double cursor = 0;
double prevCursor = 0;
double pitchIncrement = 2 * Math.PI * frequency / sampleRate;

for (int i = 0; i < n; i++) {
    cursor = prevCursor + pitchIncrement;
    audioVal[i] = Math.sin(cursor);
    prevCursor = cursor;
}