java基础06 MidiEvent三种方式实现简单的音乐播放

一、静态makeEvent()方法

package MusicePlayer;

import javax.sound.midi.*;

public class ManiMusicPlayer1 {
    public static void main(String[] args) {
        try {
            //获取音乐播放队列 开启队列
            Sequencer sequencer= MidiSystem.getSequencer();
            sequencer.open();
            //创建队列和轨道
            Sequence sequence=new Sequence(Sequence.PPQ,4);
            Track track=sequence.createTrack();
            //创建一堆连续的音符 利用makeEvent时间 产生信息和事件
            for (int i = 0; i < 61; i+=4) {
                track.add(makeevent(144,1,i,100,i));
                track.add(makeevent(128,1,i,100,i+2));
            }
            //将队列设置到播放队列中
            sequencer.setSequence(sequence);
            //设置播放的模式
            sequencer.setTempoInBPM(220);
            //开始播放
            sequencer.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *
     * @param tick 何时播放
     * @return 返回事件
     */
    public static MidiEvent makeevent(int comd,int chan,
                                      int one,int two,int tick){
        MidiEvent event=null;
        try {
            //利用ShortMessage对象来创建信息
            ShortMessage a=new ShortMessage();
            //设置信息内容
            a.setMessage(comd,chan,one,two);
            //创建事件
            event=new MidiEvent(a,tick);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        return event;
    }
}

二、注册并取得ControllerEvent方法

package MusicePlayer;

import javax.sound.midi.*;
//需要监听 所以需要继承监听类
public class MiniMusicPlayer2 implements ControllerEventListener {
    public static void main(String[] args) {
        MiniMusicPlayer2 mini=new MiniMusicPlayer2();
        mini.go();
    }
    public void go() {
        try {
            //获取音乐播放队列 开启队列
            Sequencer sequencer= MidiSystem.getSequencer();
            sequencer.open();
            //向sequencer注册事件,只需要127事件
            int[] eventsIWant={127};
            sequencer.addControllerEventListener(this,eventsIWant);
            //创建队列和轨道
            Sequence sequence=new Sequence(Sequence.PPQ,4);
            Track track=sequence.createTrack();
            //创建一堆连续的音符 利用makeEvent时间 产生信息和事件
            for (int i = 0; i < 61; i+=4) {
                track.add(makeevent(144,1,i,100,i));
                //插入事件编号为127的自定义ControllerEvent(176)
                //作用是让我们知道有音符被播放
                track.add(makeevent(176,1,127,0,i));
                track.add(makeevent(128,1,i,100,i+2));
            }
            //将队列设置到播放队列中
            sequencer.setSequence(sequence);
            //设置播放的模式
            sequencer.setTempoInBPM(220);
            //开始播放
            sequencer.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //获知事件时 调用该方法
    @Override
    public void controlChange(ShortMessage event) {
        System.out.println("la");
    }

    /**
     *
     * @param tick 何时播放
     * @return 返回事件
     */
    public static MidiEvent makeevent(int comd,int chan,
                                      int one,int two,int tick){
        MidiEvent event=null;
        try {
            //利用ShortMessage对象来创建信息
            ShortMessage a=new ShortMessage();
            //设置信息内容
            a.setMessage(comd,chan,one,two);
            //创建事件
            event=new MidiEvent(a,tick);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        return event;
    }
}

三、与音乐同步输出图形

package MusicePlayer;

import javax.sound.midi.*;
import javax.swing.*;
import java.awt.*;

//需要监听 所以需要继承监听类
public class MiniMusicPlayer3 implements ControllerEventListener {
    //获取Jframe对象 实现图形化界面 同时设置标题 还可以设置图标
    static JFrame f=new JFrame("My First Music Video");
    //声明静态变量 实现画图功能
    static MyDrawPanel m1;
    //主类
    public static void main(String[] args) {
        MiniMusicPlayer3 mini=new MiniMusicPlayer3();
        mini.go();
    }
    //设置画布的属性
    public void setUpGui(){
        //获取画布 并将其放入窗口中
        m1=new MyDrawPanel();
        f.setContentPane(m1);
        f.setBounds(30,30,300,300);
        f.setVisible(true);
    }

    public void go() {
        setUpGui();
        try {
            //获取音乐播放队列 开启队列
            Sequencer sequencer= MidiSystem.getSequencer();
            sequencer.open();
            //向sequencer注册事件,只需要127事件
            int[] eventsIWant={127};
            sequencer.addControllerEventListener(m1,eventsIWant);
            //创建队列和轨道
            Sequence sequence=new Sequence(Sequence.PPQ,4);
            Track track=sequence.createTrack();
            
            int r=0;
            //创建一堆连续的音符 利用makeEvent时间 产生信息和事件
            for (int i = 0; i < 61; i+=4) {
                r = (int) ((Math.random() * 50) + 1);
                track.add(makeevent(144,1,r,100,i));
                //插入事件编号为127的自定义ControllerEvent(176)
                //作用是让我们知道有音符被播放
                track.add(makeevent(176,1,127,0,i));
                track.add(makeevent(128,1,r,100,i+2));
            }
            //将队列设置到播放队列中
            sequencer.setSequence(sequence);
            //设置播放的模式
            sequencer.setTempoInBPM(220);
            //开始播放
            sequencer.start();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //获知事件时 调用该方法


    @Override
    public void controlChange(ShortMessage event) {
        
    }

    /**
     *
     * @param tick 何时播放
     * @return 返回事件
     */
    public static MidiEvent makeevent(int comd,int chan,
                                      int one,int two,int tick){
        MidiEvent event=null;
        try {
            //利用ShortMessage对象来创建信息
            ShortMessage a=new ShortMessage();
            //设置信息内容
            a.setMessage(comd,chan,one,two);
            //创建事件
            event=new MidiEvent(a,tick);
        } catch (InvalidMidiDataException e) {
            e.printStackTrace();
        }
        return event;
    }

    //设置监听类 监听音频的播放事件 当队列中发生变化的时候调用
    class MyDrawPanel extends JPanel implements ControllerEventListener{
        boolean msg=false;
        @Override
        public void controlChange(ShortMessage event) {
            msg=true;
            repaint();
        }
        //重绘的内容
        public void paintComponent(Graphics g){
            if (msg){
                Graphics2D g2= (Graphics2D) g;

                int r= (int) (Math.random()*255);
                int gr= (int) (Math.random()*255);
                int b= (int) (Math.random()*255);
                //生成RGB颜色并设置到画布中
                g.setColor(new Color(r,gr,b));
                //设置画的图形的大小
                int ht= (int) ((Math.random() * 120) + 10);
                int width= (int) ((Math.random() * 120) + 10);
                //设置绘图的位置
                int x= (int) ((Math.random() * 40) + 10);
                int y= (int) ((Math.random() * 40) + 10);

                g.fillRect(x,y,ht,width);
                msg=false;
            }
        }
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值