我想用java制作一个可以实时操作的基本音调发生器(只是音高开始)。
我想从简单开始,然后添加更复杂的音调生成和效果,最终得到某种基本的合成器。
我在这个站点上发现了一篇有用的帖子,其中包含一个小程序 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 一样预生成“剪辑”和循环?
谢谢!