如何在Java中生成声音效果?

我正在寻找可用于在运行时生成声音的Java代码 – 不播放现有的声音文件。

例如,在440 Hz持续2毫秒产生锯齿波形的最佳代码是什么? 源代码赞赏!

我记得我的Commodore 128有一个简单的声音命令,它将声音,频率,波形和持续时间作为参数来定义声音。 这在很多简单的案例(快速和肮脏的游戏,声音实验等)中都很有效。

我正在寻找特殊的声音效果,如音乐,而不是音乐或MIDI( JFugue图书馆非常清楚)。

您可以使用Java轻松生成采样的声音数据,并在不使用本机代码的情况下进行播放。 如果你正在谈论MIDI的事情可能会变得棘手,但我还没有涉足那个领域。

要生成采样声音数据,您必须向后处理该过程。 我们将像A-to-D一样行动并随着时间的推移采样连续声音function。 您的声卡通过麦克风或线路为音频做同样的事情。

首先,选择采样率(不是我们产生的音调的频率)。 让我们用44100赫兹,因为这可能是声卡播放速率(因此没有采样率转换,除非硬件这样做,否则这不容易)。

// in hz, number of samples in one second sampleRate = 44100 // this is the time BETWEEN Samples samplePeriod = 1.0 / sampleRate // 2ms duration = 0.002; durationInSamples = Math.ceil(duration * sampleRate); time = 0; for(int i = 0; i < durationInSamples; i++) { // sample a sine wave at 440 hertz at each time tick // substitute a function that generates a sawtooth as a function of time / freq // rawOutput[i] = function_of_time(other_relevant_info, time); rawOutput[i] = Math.sin(2 * Math.PI * 440 * time); time += samplePeriod; } // now you can playback the rawOutput // streaming this may be trickier 

这是一个可能有用的示例。 这会产生正弦波:

 package notegenerator; import java.io.IOException; /** * Tone generator and player. * * @author Cesar Vezga vcesar@yahoo.com */ public class Main { public static void main(String[] args) throws IOException { Player player = new Player(); player.play(BeachRock.getTack1(),BeachRock.getTack2()); } } 

  package notegenerator; public class BeachRock { // GUITAR static String gs1 = "T332 A4-E4 F#5-C6 E5-A5 T166 G5 A5 F#5 A5 F5 A5 E5-A5 E3 G3 G#3 "; static String gs2 = "A3 A3 A3 G3 E3 E3 G3 G#3 "; static String gs3 = "A3 A3 A3 G3 E3 A3 C4 C#4 "; static String gs4 = gs2 + gs2 + gs2 + gs3; static String gs5 = "D4 D4 D4 C4 A3 A3 C4 D#4 "; static String gs6 = "D4 D4 D4 C4 A3 E3 G3 G#3 "; static String gs7 = gs4 + gs5 + gs6 + gs2 + "A3 A3 A3 G3 E3 B3 D3 D#3 "; static String gs8 = "E4 E4 E4 D4 B3 B3 E4 B3 " + gs6 + gs2; static String gs9 = "x E3-B3 E3-B3 E3-B3 E3-B3 E3 G3 G#3 "; static String gs10 = gs7 + gs8 + gs9; static String gs11 = "A3-D4 X*7 X*16 X*5 E3 G3 G#3 "; static String guitar = gs1 + gs10 + gs11 + gs10 + gs11 + "A3 A3 A3"; // DRUMS static String ds1 = "D2 X D3 D3 X*2 D3 X "; static String ds2 = "D2 X D3 D3 X D3 D3 D3 "; static String ds3 = "D2 D3 D3 D3 D3 T83 D3 D3 T166 D3 "; static String ds4 = ds1 + ds1 + ds1 + ds2; static String ds5 = ds1 + ds1 + ds1 + ds3; static String ds6 = "D2*2 D3 D3 X*2 D3*2 "; static String ds7 = "D2*2 D3 D3 X D3 D3 D3 "; static String ds8 = ds6 + ds6 + ds6 + ds7; static String drums = "V25 T166 X*16 " + ds4 + ds4 + ds5 + ds8 + ds4 + ds4 + ds5 + ds8; public static String getTack1(){ return guitar; } public static String getTack2(){ return drums; } } 

 package notegenerator; import java.util.HashMap; /** * * Physics of Music - Notes * * Frequencies for equal-tempered scale * This table created using A4 = 440 Hz * Speed of sound = 345 m/s = 1130 ft/s = 770 miles/hr * * ("Middle C" is C4 ) * * http://www.phy.mtu.edu/~suits/notefreqs.html * * @author Cesar Vezga  * */ public class Notes { private static final Object[] notes = { "C0",16.35, "C#0/Db0",17.32, "D0",18.35, "D#0/Eb0",19.45, "E0",20.6, "F0",21.83, "F#0/Gb0",23.12, "G0",24.5, "G#0/Ab0",25.96, "A0",27.5, "A#0/Bb0",29.14, "B0",30.87, "C1",32.7, "C#1/Db1",34.65, "D1",36.71, "D#1/Eb1",38.89, "E1",41.2, "F1",43.65, "F#1/Gb1",46.25, "G1",49.00, "G#1/Ab1",51.91, "A1",55.00, "A#1/Bb1",58.27, "B1",61.74, "C2",65.41, "C#2/Db2",69.3, "D2",73.42, "D#2/Eb2",77.78, "E2",82.41, "F2",87.31, "F#2/Gb2",92.5, "G2",98.00, "G#2/Ab2",103.83, "A2",110.00, "A#2/Bb2",116.54, "B2",123.47, "C3",130.81, "C#3/Db3",138.59, "D3",146.83, "D#3/Eb3",155.56, "E3",164.81, "F3",174.61, "F#3/Gb3",185.00, "G3",196.00, "G#3/Ab3",207.65, "A3",220.00, "A#3/Bb3",233.08, "B3",246.94, "C4",261.63, // Middle C "C#4/Db4",277.18, "D4",293.66, "D#4/Eb4",311.13, "E4",329.63, "F4",349.23, "F#4/Gb4",369.99, "G4",392.00, "G#4/Ab4",415.3, "A4",440.00, "A#4/Bb4",466.16, "B4",493.88, "C5",523.25, "C#5/Db5",554.37, "D5",587.33, "D#5/Eb5",622.25, "E5",659.26, "F5",698.46, "F#5/Gb5",739.99, "G5",783.99, "G#5/Ab5",830.61, "A5",880.00, "A#5/Bb5",932.33, "B5",987.77, "C6",1046.5, "C#6/Db6",1108.73, "D6",1174.66, "D#6/Eb6",1244.51, "E6",1318.51, "F6",1396.91, "F#6/Gb6",1479.98, "G6",1567.98, "G#6/Ab6",1661.22, "A6",1760.00, "A#6/Bb6",1864.66, "B6",1975.53, "C7",2093.00, "C#7/Db7",2217.46, "D7",2349.32, "D#7/Eb7",2489.02, "E7",2637.02, "F7",2793.83, "F#7/Gb7",2959.96, "G7",3135.96, "G#7/Ab7",3322.44, "A7",3520.00, "A#7/Bb7",3729.31, "B7",3951.07, "C8",4186.01, "C#8/Db8",4434.92, "D8",4698.64, "D#8/Eb8",4978.03 }; private HashMap noteMap; public Notes(){ noteMap = new HashMap(); for(int i=0; i 

 package notegenerator; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; public class Player { private SourceDataLine line = null; private Notes notes = new Notes(); private long time = 250; private double volumen = 1; public void play(String keys) { byte[] data = parse(keys); start(); line.write(data, 0, data.length); stop(); } public void play(String... track) { byte[] data2 = parseAll(track); if (data2 != null) { start(); line.write(data2, 0, data2.length); stop(); } } private byte[] parseAll(String... track) { byte[] data2 = null; for (String t : track) { byte[] data1 = parse(t); if (data2 == null) { data2 = data1; } else { data2 = notes.addWaves(data1, data2); } } return data2; } private byte[] parse(String song) { time = 250; volumen = 1; ByteArrayOutputStream baos = new ByteArrayOutputStream(); String[] key = song.split(" "); byte[] data = null; for (String k : key) { int mult = 1; if (k.indexOf("*") > -1) { String keyAux = k.split("\\*")[0]; mult = Integer.parseInt(k.split("\\*")[1]); k = keyAux; } else if (k.startsWith("T")) { time = Long.parseLong(k.substring(1)); continue; } else if (k.startsWith("V")) { volumen = Double.parseDouble(k.substring(1)) / 100; if(volumen>1) volumen = 1; if(volumen<0) volumen = 0; continue; } if (k.indexOf("-") > -1) { k = k.replaceAll("-", " ").trim(); data = notes.getCordData(k, time * mult); } else { data = notes.tone(k, time * mult); } volumen(data); try { baos.write(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return baos.toByteArray(); } private void volumen(byte[] data) { for(int i=0; i 

Java媒体框架同时做到了这两点。 您可以播放录制的声音或使用MIDI界面合成您自己的声音和音乐。 它还提供混音器API。

当然,如果您知道要播放的波形的详细信息,则可以定期“采样”该函数,并将生成的样本传递给回放API,就好像它是预先录制的声音文件一样。

Sun并没有积极维护JMF,但各种平台都有function分布。

我的第一台计算机是Commodore 64,我记得因为恐惧之泪“每个人都想要统治世界”,因为它的SID芯片被抽出来了。 我不知道这个纯Java SID仿真器是否是开源的,但它可能会为您提供一些关于实现更高级别的Attack-Decay-Sustain-Release和波形function的指示。

你想要的可能不是一个声音API,而是某种合成器代码,我很确定你需要比Java允许更多的低级声音驱动程序控制(它是一种通常在“沙盒”中运行的解释语言)。

但好消息是,谷歌快速搜索“ java声音合成 ”,发现了一个名为JSyn的插件, 它使用原生C方法(我猜这是一种方法)来产生声音。 它似乎是免费的非商业用途,也可以在商业许可证中使用。 🙂