1

我正在编写一个从一个频率线性转换到另一个频率的 java 声音应用程序。

当我输入一个恒定频率(也就是第一个和最后一个频率相同)时,会播放正确的频率。

但是,只要两个频率之间的差异大于零,播放的频率就会从正确的值开始,但会以两倍的速率递增,并以差异的两倍结束。(例如,我输入 500 和 1000;频率从 500 开始,到 1500 结束)。

我最初认为我只是错误地增加了频率,但是当我打印频率值时,它会打印出我想要的值(例如我输入 500 和 1000;打印输出从 500 开始到 1000 结束)。

我通过记录输出声音并在频谱图上查看其频率来检查可听频率的值。这是我的代码的相关简化部分:

import java.lang.Math;
import javax.sound.sampled.*;

public class MainSpeech {

    public static void main(String[] args) throws LineUnavailableException {

        double freq; //  frequency in Hz
        int volume = 30;
        int time = 1; // in seconds
        float sampleRate = 8000.0f; // in Hz
        int numSamples = (int)(sampleRate * time); // # of samples within given time
        byte stream[] = new byte[(int)(sampleRate*1)]; // waveform values

        freq = 700;
        for (int i = 0; i < numSamples; i++) {
            freq += 0.1;
            stream[i] = (byte) (Math.sin(2*Math.PI*i*freq/sampleRate)*volume);
        }

        AudioFormat af = new AudioFormat(sampleRate, 8, 1, true, false);
        SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
        sdl.open(af);
        sdl.start();
        sdl.write(stream, 0, stream.length); // play sound
        sdl.drain();
        sdl.close();
    }
}

在这个简化的片段中,频率应该从 700 开始,然后增加 8000 倍 0.1,以 1500 的频率结束,打印输出正确显示。然而,可听频率实际上在 2300 处结束。

4

1 回答 1

3

你在这里有一个错误:

2*Math.PI*i*freq/sampleRate

在这里使用 i 或 freq,但不能同时使用它们。你所拥有的不是频率的线性变化,而是二次的。如果您希望它的行为如下所述,请使用

2*Math.PI*freq/sampleRate
于 2013-01-09T10:42:31.457 回答