javax.sound.sampled - 尝试重复启动音频样本并不起作用

时间:2016-04-26 15:11:17

标签: java audio javasound javax.sound.sampled

我正在编写一个小鼓音序器,一个roland tr808仿冒品,16步/测量和16个乐器(=鼓样本)。用户可以创建一个16x16模式。

然而,如果一个样本连续播放不止一次,它通常只播放一次。比如说,我在第1,5,9和13步以及节奏130BPM上得到了一个bassdrum,它有时只在1和9上播放bd,有时也在5和/或13上播放。如果样本非常短或速度很慢,则模式中的每一步都可以正确播放的可能性更高。因此,当我尝试再次播放样本时,我认为音频线并不喜欢它。

但实际上我认为我已经在我的代码中考虑到了这一点。如果有人告诉我我的代码有什么问题,我真的很感激。

这是我安德鲁汤普森建议的完整代码,修改后需要从互联网上获取一些样本。但是加载它们需要一点时间。导致问题的部分可能是Instrument类中的play()方法:

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);
}

样品质量相当可疑,但特别是bassdrum样品说明我的问题非常好。

0 个答案:

没有答案