程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> UniJa2.1聲音播放問題(MIDI格式)

UniJa2.1聲音播放問題(MIDI格式)

編輯:J2ME
一.線程處理[不推薦]:

<1>使用方法:假設和我們的.Java文件同目錄下有a.mid文件

1 在需要聲音的.Java文件中聲明一個SoundEffects的全局對象snd,比如:

private SoundEffects snd = new SoundEffects();

2 在需要聲音的位置寫

                  new Thread(){

                 public void run(){

                      snd.playMIDI("/a.mid");

                 }

                  }.start();

// 這樣就播放了

3 停止,在需要停止的地方寫

                  if(snd != null)

                 snd.destroy();

// 這樣snd就釋放為null了,如果要再播放,先要

// snd = new SoundEffects();

        <2>優點:可以在一個應用中使用多個SoundEffects對象,即可以使用多個Player對象。程序代碼中可以很清晰的看出不同的Player對象播放不同的聲音文件。(也許這不是優點)

        <3>缺點:開銷大(占用CPU時間),開啟和關閉線程都有很大的開銷(這裡的開銷應該是CPU調度開銷),經測試,采用這種線程處理聲音播放的方式,游戲應用運行5-6個小時後,將出現“死機”現象。

        SoundEffects類源文件見附件。

二.非線程處理[推薦]:

 使用原因:Java雖然支持多線程處理,但使用多線程一直是開發者一個特別慎重的選擇,因為多線程的使用是比較復雜不好控制的,而且會占用大量的系統資源,Java尚且如此UNIJA上的應用就更是如此了,所以如果稍微使用不當或估計不全,就有可能耗盡系統的資源,也正是這個原因,所以在我們的應用中不建義使用多線程處理聲音問題,因為任何優點都會因為用戶使用過程中的“掛掉”而變的毫無意義。在單線程中處理其實是非常簡單的,我只是簡單一提即可,相信你一看就會明白。:)

使用方法:在UniJa應用中MIDI格式的聲音播放功能在同一線程不支持多個Player對象,所以不能實現背景樂和音效同時播放,但允許不同聲音的接續播放,具體方法是播放一個聲音文件後或播放一個聲音期間如果想要改放另一個音效,應先將當前的PLYAER關閉,再將PLAYER對象清空並System.gc()(釋放Player資源),然後再用這個PLAYER對象引用重新生成一個新的聲音文件對象,並播放。(注:這個過程如果頻繁操做也會對系統開銷造成危脅,所以建議,如果使用MID格式的聲音文件最好不要加過多的音效,一兩個為宜,我的經驗是當應用進MENU菜單時可以循環播放背景音樂,當應用進入到游戲之中時則只有音效即可)

三.個人總結:

1.  播放問題:在UniJa應用中MIDI格式的聲音播放功能不支持多個Player對象,必須在播放一個聲音文件後,將對象清空(釋放Player資源),只能在應用中存在一個Player對象,否則將不能播放其他的聲音文件。

2.  開銷問題:強烈推薦采用非線程處理聲音方法

3.  循環問題:在我寫的SoundEffects類的構造函數中,我聲明了一個參數time,用來控制聲音播放次數,如:new SoundEffects(10)就代表這個Player播放對象將循環播放十次;在Player類中,我沒有找到無限循環播放的方法,在我寫的SoundEffects類中,我一般將time設定為100萬次來實現。

四.附件:SoundEffects.Java(修改過的,推薦采用)

import Javax.microedition.media.*;

import Java.io.InputStream;

import Java.io.ByteArrayInputStream;

import Javax.microedition.media.control.*;

import Java.io.*;

/**音效播放類,本類基於MIDP2.0支持的音效包括

 Wave audio files: audio/x-wav

 AU audio files: audio/basic

 MP3 audio files: audio/mpeg

 MIDI files: audio/midi

 Tone sequences: audio/x-tone-seq

 使用方法:先創建對象,然後調用播放功能,當程序退出,或者不再使用音效功能時,記得調用destroy()

 */

public class SoundEffects {

  String filename = null;

  String contentType;

  int time;

  Player player = null;

  InputStream is = null;

  public SoundEffects(int time) {

    this.time = time;

  }

  public void playWAV(String filename) {

    this.contentType = "audio/x-wav";

    playSound(filename);

  }

  public void playAU(String filename) {

    this.contentType = "audio/basic";

    playSound(filename);

  }

  public void playMP3(String filename) {

    this.contentType = "audio/mpeg";

    playSound(filename);

  }

  public void playMIDI(String filename) {

    this.contentType = "audio/midi";

    playSound(filename);

  }

  protected synchronized void playSound(String filename) {

    this.close();

    this.filename = filename;

    playFile();

  }

  protected void close() {

    if (player != null) {

      player.close();

      player = null;

    }

    if (is != null) {

      try {

        is.close();

      }

      catch (Exception e) {}

      is = null;

    }

    filename = null;

  }

  public void destroy() {

    this.close();

  }

  public void startPlay(){

    try{

      player.start();

    }catch(MediaException e){

      e.printStackTrace();

    }

  }

  public void pausePlay(){

    try{

      player.stop();

    }catch(MediaException e){

      e.printStackTrace();

    }

  }

  public int getState(){

    return player.getState();

  }

  public void playFile() {

    player = null;

    if(filename!=null){

      try {

        is = getClass().getResourceAsStream(filename);

        player = Manager.createPlayer(is, contentType);

        //p.prefetch();

        player.realize();

        VolumeControl vc = (VolumeControl) player.getControl("VolumeControl");

        vc.setLevel(100);

        player.setLoopCount(time);

        player.start();

      }

      catch (IOException e) {

        e.printStackTrace();

      }

      catch (Javax.microedition.media.MediaException e) {

        e.printStackTrace();

      }

    }

  }

}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved