Java中的正弦波声音发生器

在Java中以任何频率生成正弦波声音的最简单方法是什么? 样本大小超过2个字节会有所帮助,但这并不重要。

谢谢

有关自包含示例,请参阅Beeper


也许更简单的事情?

如链接答案顶部所示,51行代码片段(重复低于 – 单行和内插注释的间隔)就像生成音调一样简单(好吧,你可以取5行以上)谐波)。

人们似乎认为它应该是工具包内置的一种方法,以产生纯净的音调。 它不是,并且需要一点计算来制作一个。

 /** 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 

如果您想要一些简单的代码来帮助您入门,这应该会有所帮助

 import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; public class SinSynth { // protected static final int SAMPLE_RATE = 16 * 1024; public static byte[] createSinWaveBuffer(double freq, int ms) { int samples = (int)((ms * SAMPLE_RATE) / 1000); byte[] output = new byte[samples]; // double period = (double)SAMPLE_RATE / freq; for (int i = 0; i < output.length; i++) { double angle = 2.0 * Math.PI * i / period; output[i] = (byte)(Math.sin(angle) * 127f); } return output; } public static void main(String[] args) throws LineUnavailableException { final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true); SourceDataLine line = AudioSystem.getSourceDataLine(af); line.open(af, SAMPLE_RATE); line.start(); boolean forwardNotBack = true; for(double freq = 400; freq <= 800;) { byte [] toneBuffer = createSinWaveBuffer(freq, 50); int count = line.write(toneBuffer, 0, toneBuffer.length); if(forwardNotBack) { freq += 20; forwardNotBack = false; } else { freq -= 10; forwardNotBack = true; } } line.drain(); line.close(); } } 

在第一个I建议创建类Note ,它返回note的频率,并将其转换为字节数组。

然后非常简单地流式传输

  protected static final int SAMPLE_RATE = 8 * 1024; public static void main(String[] args) throws LineUnavailableException { final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true); SourceDataLine line = AudioSystem.getSourceDataLine(af); line.open(af, SAMPLE_RATE); line.start(); // fist argument is duration of playing note byte[] noteDo = Note.DO.getTone(1, SAMPLE_RATE); byte[] noteRe = Note.RE.getTone(0.5, SAMPLE_RATE); byte[] noteMi = Note.MI.getTone(1.5, SAMPLE_RATE); line.write(noteDo, 0, noteDo.length); line.write(noteRe, 0, noteRe.length); line.write(noteMi, 0, noteMi.length); line.drain(); line.close(); } public enum Note { DO(0.0f), DO_DIEZ(1.0f), RE(2.0f), RE_DIEZ(3.0f), MI(4.0f), FA(5.0f), FA_DIEZ(6.0f), SOL(7.0f),SOL_DIEZ(8.0f), LYA(9.0f),LYA_DIEZ(10.0f), SI(11.0f); private final double mPhase; Note(double phase) { mPhase = phase; } public double getNoteFrequencies() { double index = getmPhase()/ 12.0d; return 440 * Math.pow(2, index); } public static Note getNote(double phase) throws Exception { Note findNote = null; for (Note note : Note.values()){ if (note.getmPhase() == phase){ findNote = note; } } if (findNote == null) throw new Exception("Note not found: Ilegal phase " + phase); else return findNote; } public byte[] getTone(double duration, int rate){ double frequencies = getNoteFrequencies(); int maxLength = (int)(duration * rate); byte generatedTone[] = new byte[2 * maxLength]; double[] sample = new double[maxLength]; int idx = 0; for (int x = 0; x < maxLength; x++){ sample[x] = sine(x, frequencies / rate); } for (final double dVal : sample) { final short val = (short) ((dVal * 100f)); // in 16 bit wav PCM, first byte is the low order byte generatedTone[idx++] = (byte) (val & 0x00ff); generatedTone[idx++] = (byte) ((val & 0xff00) >>> 8); } return generatedTone; } private double sine(int x, double frequencies){ return Math.sin( 2*Math.PI * x * frequencies); } public double getmPhase() { return mPhase; } } 

我只想指出,有一种非常有效的生成正弦波的算法。

DSP技巧:正弦音发生器http://www.dspguru.com/dsp/tricks/sine_tone_generator

如果你正在寻找一个叫做哔哔声的课程,那么试试这个:(从Thumbz借来的一些代码)

  package ditdah; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; public class Beep { protected static final int SAMPLE_RATE = 16 * 1024; public void play(double freq, int length) { final AudioFormat af = new AudioFormat(SAMPLE_RATE, 8, 1, true, true); try { SourceDataLine line = AudioSystem.getSourceDataLine(af); line.open(af, SAMPLE_RATE); line.start(); byte[] toneBuffer = this.createSinWaveBuffer(freq, length); say.it(toneBuffer.toString() + " " + toneBuffer.length); int count = line.write(toneBuffer, 0, toneBuffer.length); line.drain(); line.close(); } catch (LineUnavailableException e) { say.it(e.getLocalizedMessage()); } } public byte[] createSinWaveBuffer(double freq, int ms) { int samples = (int) ((ms * SAMPLE_RATE) / 1000); byte[] output = new byte[samples]; // double period = (double) SAMPLE_RATE / freq; for (int i = 0; i < output.length; i++) { double angle = 2.0 * Math.PI * i / period; output[i] = (byte) (Math.sin(angle) * 127f); } return output; } 

}