首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

手把手教你用 Swing + MIDI 打造電子鼓 BeatBox:從 GUI 到音頻合成完整實戰

     編輯:Java 綜合教學

Swing 實戰:構建可視化 MIDI 音樂編排器 BeatBox

本文完整呈現一個基於 Swing 與 Java Sound API 的圖形化節拍器,涵蓋 GUI 佈局、事件監聽、MIDI 序列器編程、音軌構建與播放控制,適合進階 Java 開發者鞏固客戶端開發技能。

1. 核心架構圖解

  • View 層:JFrame + BorderLayout,左側樂器名稱(BoxLayout.Y_AXIS),右側控制按鈕,中間 16×16 JCheckBox 網格(GridLayout)代表 16 條音軌 × 16 拍。
  • Controller 層:四個 ActionListener 內部類處理 Start/Stop/Tempo± 邏輯。
  • Model 層:Sequencer、Sequence、Track、MidiEvent 構建標準 MIDI 序列。

2. 關鍵代碼片段解析

2.1 GUI 構建

public void buildGUI() {
    theFrame = new JFrame("Cyber BeatBox");
    theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel background = new JPanel(new BorderLayout());
    background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

    // 右側按鈕盒
    Box buttonBox = new Box(BoxLayout.Y_AXIS);
    JButton start = new JButton("Start");
    start.addActionListener(new MyStartListener());
    buttonBox.add(start);
    // Stop、Tempo Up/Down 同理...

    // 左側樂器名稱
    Box nameBox = new Box(BoxLayout.Y_AXIS);
    for (String name : instrumentNames) nameBox.add(new Label(name));

    // 中間 16x16 CheckBox 網格
    GridLayout grid = new GridLayout(16, 16);
    grid.setVgap(1); grid.setHgap(2);
    mainJPanel = new JPanel(grid);
    for (int i = 0; i < 256; i++) {
        JCheckBox cb = new JCheckBox();
        cb.setSelected(false);
        checkboxsList.add(cb);
        mainJPanel.add(cb);
    }

    background.add(BorderLayout.EAST, buttonBox);
    background.add(BorderLayout.WEST, nameBox);
    background.add(BorderLayout.CENTER, mainJPanel);

    theFrame.getContentPane().add(background);
    theFrame.pack();
    theFrame.setVisible(true);
}

要點:JFrame 必須用 getContentPane().add() 或 setContentPane(),不能直接 frame.add();pack() 根據子組件優先尺寸自動調整窗口大小。

2.2 MIDI 初始化

public void setUpMidi() {
    try {
        sequencer = MidiSystem.getSequencer();
        sequencer.open();
        sequence = new Sequence(Sequence.PPQ, 4); // 4 ticks per quarter note
        track = sequence.createTrack();
        sequencer.setTempoInBPM(120);
    } catch (Exception e) { e.printStackTrace(); }
}

2.3 根據 CheckBox 狀態構建 Track

public void buildTrackAndStart() {
    sequence.deleteTrack(track);
    track = sequence.createTrack();

    for (int i = 0; i < 16; i++) { // 16 條音軌
        int[] trackList = new int[16];
        int key = instruments[i]; // MIDI note number

        for (int j = 0; j < 16; j++) { // 16 拍
            JCheckBox cb = checkboxsList.get(j + 16 * i);
            trackList[j] = cb.isSelected() ? key : 0;
        }
        makeTracks(trackList); // 將 note on/off 加入 track
        track.add(makeEvent(176, 1, 127, 0, 16)); // Control Change: All Sound Off
    }
    track.add(makeEvent(192, 9, 1, 0, 15)); // Program Change: 結束標記

    sequencer.setSequence(sequence);
    sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
    sequencer.start();
    sequencer.setTempoInBPM(120);
}

2.4 MidiEvent 工廠方法

public MidiEvent makeEvent(int cmd, int chan, int one, int two, int tick) {
    try {
        ShortMessage msg = new ShortMessage();
        msg.setMessage(cmd, chan, one, two);
        return new MidiEvent(msg, tick);
    } catch (Exception e) { e.printStackTrace(); return null; }
}

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));     // Note On
            track.add(makeEvent(128, 9, key, 100, i + 1)); // Note Off
        }
    }
}

cmd 對應 MIDI 狀態字節:144=Note On, 128=Note Off, 176=Control Change, 192=Program Change。Channel 9 為打擊樂專用通道。

2.5 速度控制

// Tempo Up: 每次 +3%
sequencer.setTempoFactor(tempoFactor * 1.03f);
// Tempo Down: 每次 -3%
sequencer.setTempoFactor(tempoFactor * 0.97f);

3. 運行效果

BeatBox 界面截圖

界面呈現 16 行樂器 × 16 列拍子的棋盤,點擊 Start 即可循環播放勾選的節奏型,支持實時調速。

4. 進階擴展方向

  1. 持久化:將 checkboxsList 狀態序列化為 JSON/Properties,下次啟動恢復。
  2. 多音色支援:引入 Soundbank 載入 SF2 音色庫,突破 GM 預設音色。
  3. MIDI 輸出:MidiSystem.write(sequence, 1, file) 導出 .mid 檔案。
  4. 鍵盤映射:鍵盤事件觸發對應 JCheckBox 切換,實現即時演奏。
  5. JavaFX 重寫:使用 MediaPlayer + Canvas 實現現代化 UI 與更低延遲音頻。

5. 避坑提醒

  • JFrame.setDefaultCloseOperation(EXIT_ON_CLOSE) 確保關閉窗口釋放 MIDI 資源。
  • sequencer.open() 後必須 close(),否則佔用獨佔音頻設備導致二次啟動失敗。
  • Linux 無聲音時檢查 alsa-utils、pulseaudio、soundbank.gm 是否安裝。
  • Swing 必須在 EDT 執行:SwingUtilities.invokeLater(() -> new BeatBox().buildGUI())。

完整代碼約 200 行,涵蓋 GUI、事件、MIDI 三大核心知識點,是鞏固 Java 客戶端開發的優秀練手項目。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved