你如何创建一个音调发生器,其音调可以“实时”操作或在Java中动态操作?

时间:2012-04-27 21:07:15

标签: java signal-processing audio

我想在java中制作一个基本的音调生成器,可以实时操作(只需开始调试)。

我想从简单开始,然后添加更复杂的音调生成和效果,最终得到某种基本的合成器。

我发现a helpful post on this site在applet Beeper.java中有一些示例代码。

它生成了一个音调并将其保存到剪辑中。然后它会在需要时将该剪辑播放回循环。相关音调生成位:

/** Generates a tone, and assigns it to the Clip. */
public void generateTone()
    throws LineUnavailableException {
    if ( clip!=null ) {
        clip.stop();
        clip.close();
    } else {
        clip = AudioSystem.getClip();
    }
    boolean addHarmonic = harmonic.isSelected();

    int intSR = ((Integer)sampleRate.getSelectedItem()).intValue();
    int intFPW = framesPerWavelength.getValue();

    float sampleRate = (float)intSR;

    // oddly, the sound does not loop well for less than
    // around 5 or so, wavelengths
    int wavelengths = 20;
    byte[] buf = new byte[2*intFPW*wavelengths];
    AudioFormat af = new AudioFormat(
        sampleRate,
        8,  // sample size in bits
        2,  // channels
        true,  // signed
        false  // bigendian
        );

    int maxVol = 127;
    for(int i=0; i<intFPW*wavelengths; i++){
        double angle = ((float)(i*2)/((float)intFPW))*(Math.PI);
        buf[i*2]=getByteValue(angle);
        if(addHarmonic) {
            buf[(i*2)+1]=getByteValue(2*angle);
        } else {
            buf[(i*2)+1] = buf[i*2];
        }
    }

    try {
        byte[] b = buf;
        AudioInputStream ais = new AudioInputStream(
            new ByteArrayInputStream(b),
            af,
            buf.length/2 );

        clip.open( ais );
    } catch(Exception e) {
        e.printStackTrace();
    }
}

循环位:

/** Loops the current Clip until a commence false is passed. */
public void loopSound(boolean commence) {
    if ( commence ) {
        clip.setFramePosition(0);
        clip.loop( Clip.LOOP_CONTINUOUSLY );
    } else {
        clip.stop();
    }
}

我试图纠缠这个,以便我在后台创建另一个剪辑,当我想改变音高时快速更换另一个剪辑但当然有一个明显的点击,因为一个剪辑开始而另一个停止。

所以我猜我需要某种聪明的缓冲才能做到这一点,以便与另一波无缝地匹配另一波的结束?

或者是否只能使用预先生成的剪辑?如果是这样我该怎么办呢?

除此之外,软件合成器如何工作?他们会不断产生所有的声音和效果,还是会像“Beeper.java”那样预先生成“剪辑”并循环播放?

谢谢!

1 个答案:

答案 0 :(得分:1)

听起来你想在Java中实现一个用阶段累加器实现的numerically controlled oscillator (NCO)

基本上,您需要找出所需频率的delta相位,然后继续将此模2pi加到累加器中。累加器的值用作sin()的值以生成样本值。

如果要更改频率,请更新增量阶段。这确保了样品的连续性(波中没有突然的中断)。我怀疑这是导致点击的原因。如果您想要更好的更改,那么您需要逐渐更改一堆样本的delta阶段。