為Java程式中新增播放MIDI音樂功能

vjvj110發表於2022-05-10

Java在多媒體處理方面的確優勢不大,但是我們在程式中有些時候又需要一些音樂做為點綴,如果播放的音樂是wav等波形音訊檔案,又挺大,所以背景音樂最好就是MIDI了,可是網上很多播放MIDI的教程都是簡單的幾句話的例子,並且沒有考慮資源的釋放問題,如果程式長久執行的話,就會出現記憶體越耗越多的情況,以至於最後丟擲一個java.lang.OutOfMemoryError,整個程式就掛了。  在MIDI的播放中,一個類是比較重要的,那就是MidiSystem類,它負責整個MIDI播放裝置等的管理,其實就是Seqencer,它就是一個MIDI播放設定,用於播放MIDI序列的,還有一個類叫Seqence,它就是MIDI的序列,MIDI的序列可以自己由程式生成,也可以從檔案中或者URL中讀取。  下面我們來看一個例子吧: /* * Test5.java * * Created on 2007-9-22, 11:16:22 * * To change this template, choose Tools | Templates * and open the template in the editor. */package test1;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.Hashtable;import java.util.Map;import java.util.logging.Level;import java.util.logging.Logger;import javax.sound.midi.InvalidMidiDataException;import javax.sound.midi.MidiSystem;import javax.sound.midi.MidiUnavailableException;import javax.sound.midi.Sequence;import javax.sound.midi.Sequencer;/** * * @author hadeslee */public class Test5 implements Runnable{ private Sequencer midi; private String[] names={"1.mid","2.mid","3.mid","4.mid","5.mid"}; private int i; private Map map; public Test5(){ initMap(); new Thread(this).start(); } private void initMap(){ try { map = new Hashtable(); midi = MidiSystem.getSequencer(false); midi.open(); for (String s : names) { try { Sequence s1 = MidiSystem.getSequence(new File(s)); map.put(s, s1); } catch (InvalidMidiDataException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } } catch (MidiUnavailableException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } private void createPlayer(String name){ try { Sequence se=map.get(name); midi.setSequence(se); midi.start(); }catch (InvalidMidiDataException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } public void run(){ while(true){ try { System.out.println("換檔案了." ( i)); String name=names[(int)(Math.random()*names.length)]; createPlayer(name); Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } } public static void main(String[] args) { new Test5(); }}  在這裡有很重要的一點,那就是在程式執行的時候,只要一個Seqencer就可以了,我以前在程式裡面每次播放的時候都生成了一個Seqencer,因為那個時候我想,我都呼叫它的close()方法了,它還能被開啟嗎?其實它還可以再度被開啟的,就是這樣一種慣性思維使得程式最終因記憶體溢位而崩潰。  現在按我這種方式播,哪怕10毫秒換一次MIDI都可以,換個幾萬次記憶體一點都沒有加,呵呵,真是防不勝防啊。   檢視關於Java多媒體的更多文件   Java在多媒體處理方面的確優勢不大,但是我們在程式中有些時候又需要一些音樂做為點綴,如果播放的音樂是wav等波形音訊檔案,又挺大,所以背景音樂最好就是MIDI了,可是網上很多播放MIDI的教程都是簡單的幾句話的例子,並且沒有考慮資源的釋放問題,如果程式長久執行的話,就會出現記憶體越耗越多的情況,以至於最後丟擲一個java.lang.OutOfMemoryError,整個程式就掛了。  在MIDI的播放中,一個類是比較重要的,那就是MidiSystem類,它負責整個MIDI播放裝置等的管理,其實就是Seqencer,它就是一個MIDI播放設定,用於播放MIDI序列的,還有一個類叫Seqence,它就是MIDI的序列,MIDI的序列可以自己由程式生成,也可以從檔案中或者URL中讀取。  下面我們來看一個例子吧: /* * Test5.java * * Created on 2007-9-22, 11:16:22 * * To change this template, choose Tools | Templates * and open the template in the editor. */package test1;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.Hashtable;import java.util.Map;import java.util.logging.Level;import java.util.logging.Logger;import javax.sound.midi.InvalidMidiDataException;import javax.sound.midi.MidiSystem;import javax.sound.midi.MidiUnavailableException;import javax.sound.midi.Sequence;import javax.sound.midi.Sequencer;/** * * @author hadeslee */public class Test5 implements Runnable{ private Sequencer midi; private String[] names={"1.mid","2.mid","3.mid","4.mid","5.mid"}; private int i; private Map map; public Test5(){ initMap(); new Thread(this).start(); } private void initMap(){ try { map = new Hashtable(); midi = MidiSystem.getSequencer(false); midi.open(); for (String s : names) { try { Sequence s1 = MidiSystem.getSequence(new File(s)); map.put(s, s1); } catch (InvalidMidiDataException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } } catch (MidiUnavailableException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } private void createPlayer(String name){ try { Sequence se=map.get(name); midi.setSequence(se); midi.start(); }catch (InvalidMidiDataException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } public void run(){ while(true){ try { System.out.println("換檔案了." ( i)); String name=names[(int)(Math.random()*names.length)]; createPlayer(name); Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(Test5.class.getName()).log(Level.SEVERE, null, ex); } } } public static void main(String[] args) { new Test5(); }}  在這裡有很重要的一點,那就是在程式執行的時候,只要一個Seqencer就可以了,我以前在程式裡面每次播放的時候都生成了一個Seqencer,因為那個時候我想,我都呼叫它的close()方法了,它還能被開啟嗎?其實它還可以再度被開啟的,就是這樣一種慣性思維使得程式最終因記憶體溢位而崩潰。  現在按我這種方式播,哪怕10毫秒換一次MIDI都可以,換個幾萬次記憶體一點都沒有加,呵呵,真是防不勝防啊。   檢視關於Java多媒體的更多文件 


為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能為Java程式中新增播放MIDI音樂功能

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31495967/viewspace-2893161/,如需轉載,請註明出處,否則將追究法律責任。

相關文章