注意:我不想“读取音频文件foo.bar并播放它。”
我想以编程方式动态生成音频文件并播放它们。
Java是否为此构建了库,还是属于依赖于系统的库?
谢谢!
答案 0 :(得分:41)
使用Andrew's approach,这是一个播放equal tempered scale。
的示例import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class Tone {
public static void main(String[] args) throws LineUnavailableException {
final AudioFormat af =
new AudioFormat(Note.SAMPLE_RATE, 8, 1, true, true);
SourceDataLine line = AudioSystem.getSourceDataLine(af);
line.open(af, Note.SAMPLE_RATE);
line.start();
for (Note n : Note.values()) {
play(line, n, 500);
play(line, Note.REST, 10);
}
line.drain();
line.close();
}
private static void play(SourceDataLine line, Note note, int ms) {
ms = Math.min(ms, Note.SECONDS * 1000);
int length = Note.SAMPLE_RATE * ms / 1000;
int count = line.write(note.data(), 0, length);
}
}
enum Note {
REST, A4, A4$, B4, C4, C4$, D4, D4$, E4, F4, F4$, G4, G4$, A5;
public static final int SAMPLE_RATE = 16 * 1024; // ~16KHz
public static final int SECONDS = 2;
private byte[] sin = new byte[SECONDS * SAMPLE_RATE];
Note() {
int n = this.ordinal();
if (n > 0) {
double exp = ((double) n - 1) / 12d;
double f = 440d * Math.pow(2d, exp);
for (int i = 0; i < sin.length; i++) {
double period = (double)SAMPLE_RATE / f;
double angle = 2.0 * Math.PI * i / period;
sin[i] = (byte)(Math.sin(angle) * 127f);
}
}
}
public byte[] data() {
return sin;
}
}
这种低级方法可能适用于较旧,功能较弱的平台。还要考虑javax.sound.midi
;显示了一个完整的示例here,并引用了Synthesizing Sound教程here。
答案 1 :(得分:7)
最简单的方法是使用内置MIDI库中的java:
int channel = 0; // 0 is a piano, 9 is percussion, other channels are for other instruments
int volume = 80; // between 0 et 127
int duration = 200; // in milliseconds
try {
Synthesizer synth = MidiSystem.getSynthesizer();
synth.open();
MidiChannel[] channels = synth.getChannels();
// --------------------------------------
// Play a few notes.
// The two arguments to the noteOn() method are:
// "MIDI note number" (pitch of the note),
// and "velocity" (i.e., volume, or intensity).
// Each of these arguments is between 0 and 127.
channels[channel].noteOn( 60, volume ); // C note
Thread.sleep( duration );
channels[channel].noteOff( 60 );
channels[channel].noteOn( 62, volume ); // D note
Thread.sleep( duration );
channels[channel].noteOff( 62 );
channels[channel].noteOn( 64, volume ); // E note
Thread.sleep( duration );
channels[channel].noteOff( 64 );
Thread.sleep( 500 );
// --------------------------------------
// Play a C major chord.
channels[channel].noteOn( 60, volume ); // C
channels[channel].noteOn( 64, volume ); // E
channels[channel].noteOn( 67, volume ); // G
Thread.sleep( 3000 );
channels[channel].allNotesOff();
Thread.sleep( 500 );
synth.close();
}
catch (Exception e) {
e.printStackTrace();
}
答案 2 :(得分:2)
你看过JSyn了吗?我不认为Java Core库可以做你想做的事。
答案 3 :(得分:1)
请参阅Java Sound API。
再多一点,我还找到了Jass。
答案 4 :(得分:1)
Jcollider是SuperCollider综合服务器的Java接口。如果你想合成音乐,这将使事情变得更容易(它从音调发生器抽象到合成器,处理诸如图形生成之类的事情,从合成图中删除静音合成器直到它们再次被需要,在合成器之间修补信号动态等。)。
答案 5 :(得分:0)
This Sun forum post有一些有趣的代码用于生成sin音调。此外,鉴于WAV文件格式不是太复杂,您可以创建一个表示所需波形的表,然后将其写入文件。有几个例子,例如a raw audio converter和how to write a wav file。