Java鼓律序列器:如何从复选框状态中集成实时序列?

huangapple 未分类评论50阅读模式
标题翻译

Java Drum Sequencer: How to integrate live sequencing from checkBox states?

问题

我是初学者,正在基于《Head First Java》第13章的代码开发一个小型鼓机项目。

目前,该代码根据我在复选框网格上的输入创建一个序列,并将其绘制到GUI上。

然而,我希望程序能够像真正的鼓机一样运行,即我可以在序列播放时添加或减少击打。

我的想法是默认情况下让所有通道在序列的每个节拍上都播放,并在特定节拍处取消通道的静音复选框。然而,我很难弄清楚如何实现这一点。

这是否可行?是否有更简单或更好的方法可以实现我所追求的目标?

英文翻译

I'm a beginner working on a little drum machine project based off of Head First Java's code in Chapter 13.

At present, the code creates a sequence based on my input on the checkbox grid that the code draws to the GUI.

However I want the program to function like a real drum machine where I can add or subtract hits while the sequence plays.

My idea was to have all channels play on every tick of the sequence per default, and have the checkboxes unmute the channel at that specific tick. However I'm having a hard time figuring out how to implement that.

Is it possible? Is there an easier or better method that I'm not seeing to achieve what I'm aiming for?

import java.awt.*;
import javax.swing.*;
import javax.sound.midi.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.util.*;
import java.awt.event.*;

public class BeatBox {

    JPanel mainPanel;
    ArrayList<JCheckBox> checkboxList;
    Sequencer sequencer;
    Sequence sequence;
    Track track;
    JFrame theFrame;

    String[] instrumentNames = {"Bass Drum", "Closed Hi-Hat", "Open Hi-Hat","Acoustic Snare",
        "Crash Cymbal", "Hand Clap", "High Tom", "Hi Bongo", "Maracas", "Whistle", "Low Conga", "Cowbell",
            "Vibraslap", "Low-mid Tom", "High Agogo", "Open Hi Conga" };

    int[]instruments={35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};

        public static void main(String[]args){
            new BeatBox().buildGUI();
        }


        public void buildGUI(){
                theFrame=new JFrame("Cyber BeatBox");
                theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                BorderLayout layout=new BorderLayout();
                JPanel background=new JPanel(layout);
                background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

                //Build tempo slider
                JSlider slider = new JSlider();
                slider.setOrientation(JSlider.HORIZONTAL);
                slider.setMinimum(50);
                slider.setMaximum(200);
                slider.setPaintTicks(true);
                slider.setPaintLabels(true);
                slider.setMajorTickSpacing(10);
                slider.setMinorTickSpacing(1);
                slider.setValue(120);

                JLabel label = new JLabel();
                label.setText("Tempo: " + slider.getValue());


                slider.addChangeListener(e -> {
                    JSlider source = (JSlider) e.getSource();
                    //float tempoFactor=sequencer.getTempoFactor();
                    sequencer.setTempoFactor((float)source.getValue()/100);
                    label.setText("Tempo: " + String.valueOf(source.getValue()));
                });


                checkboxList=new ArrayList<JCheckBox>();
                Box buttonBox=new Box(BoxLayout.X_AXIS);

                JButton start=new JButton("Start");
                start.addActionListener(new MyStartListener());
                buttonBox.add(start);

                JButton stop=new JButton("Stop");
                stop.addActionListener(new MyStopListener());
                buttonBox.add(stop);


                JButton resetButton = new JButton("Reset Patch");
                resetButton.addActionListener(new MyResetListener());
                buttonBox.add(resetButton);

                Box nameBox=new Box(BoxLayout.Y_AXIS);
                for(int i=0;i< 16;i++){
                        nameBox.add(new Label(instrumentNames[i]));
                        }

                background.add(BorderLayout.NORTH,buttonBox);
                background.add(BorderLayout.WEST,nameBox);
                theFrame.getContentPane().add(background);

                background.add(BorderLayout.SOUTH, slider);
                buttonBox.add(BorderLayout.EAST, label);

                GridLayout grid=new GridLayout(16,16);grid.setVgap(1);
                grid.setHgap(2);

                mainPanel=new JPanel(grid);
                background.add(BorderLayout.CENTER,mainPanel);

                for(int i=0;i< 256;i++){
                        JCheckBox c=new JCheckBox();
                        c.setSelected(false);
                        checkboxList.add(c);
                        mainPanel.add(c);
                        } // end loop
                setUpMidi();

                theFrame.setBounds(50,50,300,300);
                theFrame.pack();
                theFrame.setVisible(true);
                } // close method

        public void setUpMidi(){
                try{
                        sequencer=MidiSystem.getSequencer();
                        sequencer.open();
                        sequence=new Sequence(Sequence.PPQ,4);
                        track=sequence.createTrack();
                        sequencer.setTempoInBPM(120);

                }catch(Exception e){ e.printStackTrace(); }
        } // close method

        public void buildTrackAndStart(){

        int[]trackList=null;
        sequence.deleteTrack(track);
        track=sequence.createTrack();
        sequencer.setTickPosition(0);

        for(int i=0;i<16;i++){
                trackList=new int[16];
                int key=instruments[i];
                for(int j=0;j<16;j++){
                        JCheckBox jc=(JCheckBox)checkboxList.get(j+(16*i));
                        if(!jc.isSelected()){
                        trackList[j]=key;
                        } /*else{
                                trackList[j]=0;
                        }*/
                } // close inner loop

                makeTracks(trackList);
                track.add(makeEvent(176,1,127,0,16));


        } // close outer

        track.add(makeEvent(192,9,1,0,15));

        try{
                sequencer.setSequence(sequence);
                sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
                sequencer.setMasterSyncMode(Sequencer.SyncMode.MIDI_SYNC);
                sequencer.start();
                sequencer.setTempoInBPM(120);
        }catch(Exception e){
                e.printStackTrace();
        }
        } // close buildTrackAndStart method


        //Inner Classes
        public class MyStartListener implements ActionListener{
                public void actionPerformed(ActionEvent a){
                        buildTrackAndStart(); }
        } // close inner class

        public class MyStopListener implements ActionListener{
                public void actionPerformed(ActionEvent a){
                sequencer.stop();
                sequencer.setTickPosition(0);}
        } // close inner class

        public class MyUpTempoListener implements ActionListener{
                public void actionPerformed(ActionEvent a){
                float tempoFactor=sequencer.getTempoFactor();
                sequencer.setTempoFactor((float)(tempoFactor*1.03));
                }
        } // close inner class

        public class MyDownTempoListener implements ActionListener{
                public void actionPerformed(ActionEvent a){
                float tempoFactor=sequencer.getTempoFactor();
                sequencer.setTempoFactor((float)(tempoFactor*.97));
                }
        } // close inner class

        public class MyResetListener implements ActionListener{
            public  void actionPerformed(ActionEvent a){
                for(int i = 0; i<256; i++){
                    JCheckBox loopBox = checkboxList.get(i);
                    loopBox.setSelected(false);
                }
            }
        } // close inner class



        //Makers

        public void makeTracks(int[]list){

                for(int i=0;i<16;i++){
                int key=list[i];
                if(key!=0){
                        track.add(makeEvent(144,9,key,100,i));
                        track.add(makeEvent(128,9,key,100,i+1));
                        }
                }
        }

        public MidiEvent makeEvent(int comd,int chan,int one,int two,int tick){

                MidiEvent event=null;
                try{
                ShortMessage a=new ShortMessage();
                a.setMessage(comd,chan,one,two);
                event=new MidiEvent(a,tick);
                }catch(Exception e){
                        e.printStackTrace();}
                return event;
                }
}

huangapple
  • 本文由 发表于 2020年5月30日 17:34:23
  • 转载请务必保留本文链接:https://java.coder-hub.com/62100546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定