我正在寻找可用于在运行时生成声音的Java代码 - 不播放现有的声音文件.
例如,在440 Hz持续2毫秒产生锯齿波形的最佳代码是什么?源代码赞赏!
我记得我的Commodore 128有一个简单的声音命令,它将声音,频率,波形和持续时间作为参数来定义声音.这在很多简单的案例(快速和肮脏的游戏,声音实验等)中都很有用.
我正在寻找特殊的声音效果,如声音,而不是音乐或MIDI(JFugue图书馆非常清楚).
这是一个可能有用的示例.这会产生正弦波:
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
2> basszero..:您可以使用Java轻松生成采样声音数据,并在不使用本机代码的情况下播放.如果你正在谈论MIDI的事情可能会变得棘手,但我还没有涉足那个领域.
要生成采样声音数据,您必须向后处理该过程.我们将像A-to-D一样行动并随着时间的推移采样连续声音功能.您的声卡通过麦克风或线路对音频做同样的事情.
首先,选择采样率(不是我们产生的音调的频率).让我们用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
对于像我这样的假人,一旦你生成它,你怎么玩它?