FileDocCategorySizeDatePackage
Groove.javaAPI DocExample15594Wed Aug 08 15:13:52 BST 2001None

Groove

public class Groove extends JPanel implements ControlContext, ActionListener, MetaEventListener
Rhythm Groove Box. Program any beat you like, click on a cell. Channel 10 (the rhythm channel) supports the 47 instrument sounds. These sounds are the result of a program change to instrument 1. Beat Pattern 1 | 1 sec | 2 sec 1 e + a 2 e + a 3 e + a 4 e + a hh x x x x x x x x sn x x kk x x x x 0 1 2 3 4 5 6 7 8 9 1011 12131415 Hi-hat on-off : 0-1, 2-3, 4-5, 6-7, 8-9, 10-11, 12-13, 14-15 snare : on-off : 4-5, 12-13 bass : on-off : 0-1, 3-4, 6-7, 8-9
version
@(#)Groove.java 1.16 99/11/03
author
Brian Lichtenwalter

Fields Summary
final int
PROGRAM
final int
NOTEON
final int
NOTEOFF
int
velocity
TempoDial
tempoDial
Sequencer
sequencer
Track
track
TableModel
dataModel
JTable
table
int
row
int
col
JButton
loopB
JButton
startB
JComboBox
combo
String[]
instruments
Vector
data
Constructors Summary
public Groove()



      
        setLayout(new BorderLayout(5,0));
        EmptyBorder eb = new EmptyBorder(5,5,5,5);
        setBorder(eb);

        for (int i = 0, id = 35; i < instruments.length; i++, id++) {
            data.add(new Data(instruments[i], id));
        }

        final String[] names = { "Instrument", 
                                 "1", "e", "+", "a",
                                 "2", "e", "+", "a", 
                                 "3", "e", "+", "a", 
                                 "4", "e", "+", "a"};

        dataModel = new AbstractTableModel() {
            public int getColumnCount() { return names.length; }
            public int getRowCount() { return data.size();}
            public Object getValueAt(int row, int col) { 
                if (col == 0) {
                    return ((Data) data.get(row)).name;
                } else {
                    return ((Data) data.get(row)).staff[col-1];
                }
            }
            public String getColumnName(int col) { return names[col]; }
            public Class getColumnClass(int c) {
                return getValueAt(0, c).getClass();
            }
            public boolean isCellEditable(int row, int col) {
                return col == 0 ? false : true;
            }
            public void setValueAt(Object aValue, int row, int col) {
                if (col == 0) {
                    ((Data) data.get(row)).name = (String) aValue;
                } else {
                    ((Data) data.get(row)).staff[col-1] = (Color) aValue;
                }
            }
        };

        DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
            public void setValue(Object value) {
                setBackground((Color) value);
            }
        };

        table = new JTable(dataModel);
        table.getColumn(names[0]).setMinWidth(120);
        TableColumnModel tcm = table.getColumnModel();
        for (int i = 1; i < names.length; i++) {
            TableColumn col = tcm.getColumn(i);
            col.setCellRenderer(renderer);
        }

        // Listener for row changes
        ListSelectionModel lsm = table.getSelectionModel();
        lsm.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                ListSelectionModel sm = (ListSelectionModel) e.getSource();
                if (!sm.isSelectionEmpty()) {
                    row = sm.getMinSelectionIndex();
                }
            }
        });

        // Listener for column changes
        lsm = table.getColumnModel().getSelectionModel();
        lsm.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                ListSelectionModel sm = (ListSelectionModel) e.getSource();
                if (!sm.isSelectionEmpty()) {
                    col = sm.getMinSelectionIndex();
                }
                if (col != 0) {
                    Color c = ((Data) data.get(row)).staff[col-1];
                    if (c.equals(Color.white)) {
                        ((Data) data.get(row)).staff[col-1] = Color.black;
                    } else {
                        ((Data) data.get(row)).staff[col-1] = Color.white;
                    }
                    table.tableChanged(new TableModelEvent(dataModel));
                }
            }
        });
        
        JPanel p1 = new JPanel();
        p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
        SoftBevelBorder sbb = new SoftBevelBorder(BevelBorder.RAISED);
        p1.setBorder(new CompoundBorder(sbb, eb));
        p1.add(tempoDial);
        p1.add(Box.createVerticalStrut(10));

        JPanel p2 = new JPanel(new GridLayout(0,1,2,10));
        p2.add(startB = makeButton("Start", getBackground()));
        p2.add(loopB = makeButton("Loop", getBackground()));
        p2.add(makeButton("Clear Table", getBackground()));

        combo = new JComboBox();
        combo.addActionListener(this);
        combo.addItem("Rock Beat 1");
        combo.addItem("Rock Beat 2");
        combo.addItem("Rock Beat 3");
        p2.add(combo);

        p1.add(p2);
        p1.add(Box.createVerticalStrut(120));
        add("West", p1);

        add("Center", new JScrollPane(table));
    
Methods Summary
public voidactionPerformed(java.awt.event.ActionEvent e)

        Object object = e.getSource();
        if (object instanceof JComboBox) {
            presetTracks(((JComboBox) object).getSelectedIndex());
            if (startB.getText().startsWith("Stop")) {
                sequencer.stop();
                buildTrackThenStartSequencer();
            }
        } else if (object instanceof JButton) {
            JButton b = (JButton) object;
            if (b.equals(startB)) {
                if (b.getText().startsWith("Start")) {
                    buildTrackThenStartSequencer();
                    b.setText("Stop");
                } else {
                    sequencer.stop();
                    b.setText("Start");
                }
            } else if (b.equals(loopB)) {
                b.setSelected(!b.isSelected());
                if (loopB.getBackground().equals(Color.gray)) {
                    loopB.setBackground(getBackground());
                } else {
                    loopB.setBackground(Color.gray);
                }
            } else if (b.getText().startsWith("Clear")) {
                clearTable();
                table.tableChanged(new TableModelEvent(dataModel));
            }
        }
    
private voidbuildTrackThenStartSequencer()

        Sequence sequence = null;
        try {
           sequence = new Sequence(Sequence.PPQ, 4);
        } catch (Exception ex) { ex.printStackTrace(); }
        track = sequence.createTrack();
        createEvent(PROGRAM, 9, 1, 0);
        for (int i = 0; i < data.size(); i++) {
            Data d = (Data) data.get(i);
            for (int j = 0; j < d.staff.length; j++) {
                if (d.staff[j].equals(Color.black)) {
                     createEvent(NOTEON, 9, d.id, j); 
                     createEvent(NOTEOFF, 9, d.id, j+1); 
                }
            }
        }
        // so we always have a track from 0 to 15.
        createEvent(PROGRAM, 9, 1, 15);

        // set and start the sequencer.
        try {
            sequencer.setSequence(sequence);
        } catch (Exception ex) { ex.printStackTrace(); }
        sequencer.start();
        sequencer.setTempoInBPM(tempoDial.getTempo());
    
private voidclearTable()

        for (int i = 0; i < data.size(); i++) {
            Data d = (Data) data.get(i);
            for (int j = 0; j < d.staff.length; j++) {
                d.staff[j] = Color.white;
            }
        }
    
public voidclose()

        if (startB.getText().startsWith("Stop")) {
            startB.doClick(0);
        }
        if (sequencer != null) {
            sequencer.close();
        }
        sequencer = null;
    
private voidcreateEvent(int type, int chan, int num, long tick)

        ShortMessage message = new ShortMessage();
        try {
            message.setMessage(type, chan, num, velocity); 
            MidiEvent event = new MidiEvent( message, tick );
            track.add(event);
        } catch (Exception ex) { ex.printStackTrace(); }
    
public static voidmain(java.lang.String[] args)

        final Groove groove = new Groove();
        JFrame f = new JFrame("Rhythm Groove Box");
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}
        });
        f.getContentPane().add("Center", groove);
        f.pack();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int w = 640;
        int h = 440;
        f.setLocation(screenSize.width/2 - w/2, screenSize.height/2 - h/2);
        f.setSize(w, h);
        f.show();
        groove.open();
    
private javax.swing.JButtonmakeButton(java.lang.String bName, java.awt.Color c)

        JButton b = new JButton(bName);
        b.setBackground(c);
        b.addActionListener(this);
        return b;
    
public voidmeta(javax.sound.midi.MetaMessage message)

        if (message.getType() == 47) {  // 47 is end of track
            if (loopB.getBackground().equals(Color.gray)) {
                if (sequencer != null && sequencer.isOpen()) {
                    sequencer.start();
                    sequencer.setTempoInBPM(tempoDial.getTempo());
                }
            } else {
                startB.setText("Start");
            }
        }
    
public voidopen()

        try {
            sequencer = MidiSystem.getSequencer();
            sequencer.open();
        } catch (Exception e) { e.printStackTrace(); }
        tempoDial.setSequencer(sequencer);
        sequencer.addMetaEventListener(this);
    
private voidpresetTracks(int num)


        final int ACOUSTIC_BASS = 35;
        final int ACOUSTIC_SNARE = 38;
        final int HAND_CLAP = 39;
        final int PEDAL_HIHAT = 44;
        final int LO_TOM = 45;
        final int CLOSED_HIHAT = 42;
        final int CRASH_CYMBAL1 = 49;
        final int HI_TOM = 50;
        final int RIDE_BELL = 53;

        clearTable();

        switch (num) {
            case 0 : for (int i = 0; i < 16; i+=2) {
                         setCell(CLOSED_HIHAT, i); 
                     }
                     setCell(ACOUSTIC_SNARE, 4);
                     setCell(ACOUSTIC_SNARE, 12);
                     int bass1[] = { 0, 3, 6, 8 };
                     for (int i = 0; i < bass1.length; i++) {
                         setCell(ACOUSTIC_BASS, bass1[i]); 
                     }
                     break;
            case 1 : for (int i = 0; i < 16; i+=4) {
                         setCell(CRASH_CYMBAL1, i); 
                     }
                     for (int i = 0; i < 16; i+=2) {
                         setCell(PEDAL_HIHAT, i); 
                     }
                     setCell(ACOUSTIC_SNARE, 4);
                     setCell(ACOUSTIC_SNARE, 12);
                     int bass2[] = { 0, 2, 3, 7, 9, 10, 15 };
                     for (int i = 0; i < bass2.length; i++) {
                         setCell(ACOUSTIC_BASS, bass2[i]); 
                     }
                     break;
            case 2 : for (int i = 0; i < 16; i+=4) {
                         setCell(RIDE_BELL, i); 
                     }
                     for (int i = 2; i < 16; i+=4) {
                         setCell(PEDAL_HIHAT, i); 
                     }
                     setCell(HAND_CLAP, 4);
                     setCell(HAND_CLAP, 12);
                     setCell(HI_TOM, 13);
                     setCell(LO_TOM, 14);
                     int bass3[] = { 0, 3, 6, 9, 15 };
                     for (int i = 0; i < bass3.length; i++) {
                         setCell(ACOUSTIC_BASS+1, bass3[i]); 
                     }
                     break;
            default :
        }
        table.tableChanged(new TableModelEvent(dataModel));
    
private voidsetCell(int id, int tick)

        for (int i = 0; i < data.size(); i++) {
            Data d = (Data) data.get(i);
            if (d.id == id) {
                d.staff[tick] = Color.black;
                break;
            }
        }