javax.sound.sampled-尝试反复启动音频采样不会';行不通
我正在编程一个小型鼓序列器,一个罗兰tr808仿制品,有16个步骤/测量和16个仪器(=鼓样本)。用户有一个gui,可以在其中创建16x16模式 但是,如果一个样本连续快速播放多次,它通常只播放一次。比如说,我在第1、5、9和13步得到了一个低音鼓和tempo的130 bpm,它有时只在第1和9步播放bd,有时也在第5和/或13步播放bd。如果样本很短或节奏很慢,则模式中的每一步都正确弹奏的可能性更高。因此,我假设音频线不喜欢它,当我尝试再次播放尚未完成的示例时 但实际上我认为我在代码中已经考虑到了这一点。如果有人告诉我我的代码出了什么问题,我会非常感激 这是我的完整代码,由Andrew Thompson建议,经过修改,从互联网上获取了一些示例。不过,加载它们需要一些时间。导致问题的部分可能是Instrument类中的play()方法:javax.sound.sampled-尝试反复启动音频采样不会';行不通,java,audio,javasound,javax.sound.sampled,Java,Audio,Javasound,Javax.sound.sampled,我正在编程一个小型鼓序列器,一个罗兰tr808仿制品,有16个步骤/测量和16个仪器(=鼓样本)。用户有一个gui,可以在其中创建16x16模式 但是,如果一个样本连续快速播放多次,它通常只播放一次。比如说,我在第1、5、9和13步得到了一个低音鼓和tempo的130 bpm,它有时只在第1和9步播放bd,有时也在第5和/或13步播放bd。如果样本很短或节奏很慢,则模式中的每一步都正确弹奏的可能性更高。因此,我假设音频线不喜欢它,当我尝试再次播放尚未完成的示例时 但实际上我认为我在代码中已经考虑
package testbox;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.sound.sampled.*;
public class boomboxtest {
public static void main(String[] args) {
Sequencer seq = new Sequencer();
//bassdrum
seq.toggleInstrument(0,0);
seq.toggleInstrument(0,4);
seq.toggleInstrument(0,8);
seq.toggleInstrument(0,12);
//snare
seq.toggleInstrument(1,4);
seq.toggleInstrument(1,12);
//Hihat
seq.toggleInstrument(2, 2);
seq.toggleInstrument(2, 6);
seq.toggleInstrument(2, 10);
//Bongo
seq.toggleInstrument(3, 6);
seq.toggleInstrument(3, 10);
seq.setTempo(130);
seq.play();
}
}
class Sequencer {
private Mixer mixer;
private List<SequencerListener> listeners = new ArrayList<SequencerListener>();
public static final int INSTR_COUNT = 4;
private int tempo_bpm = 120;
private ExecutorService executor;
private int current_step = 0;
private int current_max_step = 16;
private boolean[][] pattern = new boolean[32][INSTR_COUNT];
private ArrayList<Instrument> instruments;
Line[] lines = new Line[16];
private SequencerEngine seq;
private String[] filenames = {"http://www.canadianmusicartists.com/sample/kick_02.wav", "http://www.canadianmusicartists.com/sample/snare01.wav", "http://www.canadianmusicartists.com/sample/H_closedhat_01.wav", "http://www.canadianmusicartists.com/sample/bongo01.wav"};
public Sequencer() {
seq = new SequencerEngine();
try{
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
mixer = AudioSystem.getMixer(mixerInfo[0]);
} catch (Exception e) {e.printStackTrace();}
instruments = new ArrayList<Instrument>(INSTR_COUNT);
for (int i = 0; i < INSTR_COUNT; i++) {
System.out.println("Loading instrument " + i);
Instrument instr = new Instrument(filenames[i], mixer);
instruments.add(instr);
lines[i] = instr.getLine();
}
syncMixer();
executor = Executors.newCachedThreadPool();
executor.submit(seq);
}
public void syncMixer() {
if (mixer.isSynchronizationSupported(lines, false)) {
mixer.synchronize(lines, false);
} else {
System.out.println("No hay synchronisado");
}
}
public boolean isPlaying() {
return seq.getRunning();
}
public boolean toggleInstrument (int instrument, int beat) {
pattern[beat][instrument] = !pattern[beat][instrument];
return pattern[beat][instrument];
}
public void play() {
seq.toggleRun(true);
}
public void pause() {
seq.toggleRun(false);
}
public void stop() {
pause();
setCurrent_step(0);
}
public int getTempo() {
return tempo_bpm;
}
public void setTempo(int tempo) {
if (tempo < 30) {
tempo = 30;
} else if (tempo > 200) {
tempo = 200;
} else {
this.tempo_bpm = tempo;
}
}
public int getCurrent_step() {
return current_step;
}
public void setCurrent_step(int current_step) {
this.current_step = current_step;
}
public boolean[][] getPattern() {
return pattern;
}
public void kill() {
seq.kill();
executor.shutdownNow();
}
public void addListener(SequencerListener toAdd) {
listeners.add(toAdd);
}
public class SequencerEngine implements Runnable{
private boolean running;
private boolean alive = true;
public void run() {
while( getAlive()) {
while (getRunning()) {
if (current_step >= current_max_step) {
current_step = 0;
}
for (; current_step < current_max_step ; current_step++) {
stepListen();
if(!getRunning()) {
break;
}
long time = System.currentTimeMillis();
long steptime = 60000/(4*tempo_bpm);
for (int k = 0; k < INSTR_COUNT; k++) {
if (pattern[current_step][k]) {
instruments.get(k).play();
}
}
while((System.currentTimeMillis()-time) < steptime) {}
}
}
}
}
public void stepListen() {
for (SequencerListener sl : listeners) {
sl.stepEvent(current_step);
}
}
public boolean getRunning() {
return running;
}
public boolean getAlive() {
return alive;
}
public void toggleRun(boolean toggle) {
running = toggle;
}
public void kill() {
alive = false;
}
}
}
class Instrument {
private String name;
private File soundFile;
private AudioInputStream stream;
private AudioFormat format;
private DataLine.Info info;
private Clip clip;
private Mixer mixer;
public Instrument(String filename, Mixer mixer ) {
this.name = filename;
try {
//soundFile = new File("sounds/" + filename);
URL url = new URL(filename);
this.mixer = mixer;
//stream = AudioSystem.getAudioInputStream(soundFile);
stream = AudioSystem.getAudioInputStream(url);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) mixer.getLine(info);
clip.open(stream);
}
catch (Exception e) {
e.printStackTrace();
}
}
public void play() {
clip.stop();
clip.setFramePosition(0);
clip.start();
}
public Line getLine() {
return clip;
}
}
interface SequencerListener {
void stepEvent(int current_step);
}
封装测试盒;
导入java.io.File;
导入java.net.URL;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入javax.sound.sampled.*;
公共类测试{
公共静态void main(字符串[]args){
Sequencer seq=新的Sequencer();
//低音鼓
顺序切换仪表(0,0);
顺序切换仪表(0,4);
顺序切换仪表(0,8);
顺序切换仪表(0,12);
//圈套
顺序切换仪表(1,4);
顺序切换仪表(1,12);
//Hihat
顺序切换仪表(2,2);
顺序切换仪表(2,6);
顺序切换仪表(2,10);
//邦戈
顺序切换仪表(3,6);
顺序切换仪表(3,10);
seq.setTempo(130);
seq.play();
}
}
类序列器{
专用混音器;
私有列表侦听器=新的ArrayList();
公共静态最终仪表计数=4;
私人节奏=120;
私人遗嘱执行人;
专用int电流_步长=0;
专用int电流_最大_步长=16;
私有布尔[][]模式=新布尔[32][INSTR_COUNT];
私人ArrayList文书;
第[]行=新行[16];
私有序列工程顺序;
私有字符串[]文件名={”http://www.canadianmusicartists.com/sample/kick_02.wav", "http://www.canadianmusicartists.com/sample/snare01.wav", "http://www.canadianmusicartists.com/sample/H_closedhat_01.wav", "http://www.canadianmusicartists.com/sample/bongo01.wav"};
公共音序器(){
seq=新序列工程();
试试{
Mixer.Info[]mixerInfo=AudioSystem.getMixerInfo();
mixer=AudioSystem.getMixer(mixerInfo[0]);
}catch(异常e){e.printStackTrace();}
仪器=新阵列列表(仪器计数);
对于(int i=0;i200){
节奏=200;
}否则{
this.tempo_bpm=节奏;
}
}
public int getCurrent_步骤(){
返回电流步进;
}
公共无效设置当前步骤(int当前步骤){
此.current\u step=current\u step;
}
公共布尔值[][]getPattern(){
回报模式;
}
公共空杀(){
seq.kill();
执行者。关机现在();
}
public void addListener(SequencerListener to添加){
添加(toAdd);
}
公共类SequencerEngine实现Runnable{
私有布尔运行;
private boolean alive=true;
公开募捐{
while(getAlive()){
while(getRunning()){
如果(当前步数>=当前最大步数){
当前步进=0;
}
对于(;当前步长<当前最大步长;当前步长++){
stepListen();
如果(!getRunning()){
打破
}
长时间=System.currentTimeMillis();
长步长=60000/(4*tempo_bpm);
对于(int k=0;k