游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1672|回复: 0

在MIDP应用程序中播放声音1 wxh zt

[复制链接]

1367

主题

1993

帖子

2118

积分

金牌会员

Rank: 6Rank: 6

积分
2118
发表于 2006-4-20 15:55:00 | 显示全部楼层 |阅读模式
副标题:
作者:未知 文章来源:nec
■ 前言
  在上一讲中我们讲述的是如何制作JAVA手机多媒体功能中的动画,本讲中我们将介绍如何制作JAVA手机的另一个多媒体功能——声音,即N800的音乐播放功能。若是在动画上再配以音乐播放功能,就能制作出具有丰富表现力的应用程序了。

■ 音乐播放
  现在我们利用MIDP应用程序播放音乐。但是, MIDP标准API不支持声音播放功能。机种不同,则声音播放方法也不同,所以每个厂商都会使用他们各自扩展的API 。N800使用NEC扩展的API,所以能用MIDP应用程序播放声音。

■ N800的音乐播放功能
  N800只能播放SMF(format 0)格式的音乐数据,最大文件尺寸为10Kbyte。SMF格式即Standard MIDI File 的缩略语,就是为了能实现互换性而设定的文件形式,互换性是指在不同的应用程序中也具有能处理数据的特性。SMF分为format0和format1两种格式。N800所采用的是format0格式。这两种格式具有以下不同特点。(表 1)

format0  Midi的16频声音收录在1个磁道上的形式
format1
  不限制磁道数量的形式

表 1

■ 播放音乐
接下来我们实际操作读取文件播放音乐的功能。

  ● 音乐数据的读取
  利用扩展API上的Media类的static方法读取音乐数据。自变量中记述了音乐数据文件的通过。AudioClip audio = Media.getAudioClip(“/test.mid”);

  另外,能够从web上获得音乐数,并且能够从RMS中得到音乐数据。但,由于形式相同,这里就不特别讲述了。详细情况请参考扩展API文档。

  ● 播放
  播放读取的音乐数据。使用AudioClip例子(在这称为audio)play方法播放。
  audio.play();

  而且也能同时播放两个以上的音乐数据。此时,使用AudioClip例子(在这称为audio1、audio2)play方法播放。
  audio1.play();
  audio2.play();
  上述情况下能够同时播放audio1,audio2。

  ● 停止
  能够暂停音乐的播放。使用AudioClip例子的stop方法能够停止。
  audio.stop();

  ● 其他功能
  AudioClip定义了读取其他音乐数据信息的方法和决定反复播放次数的方法。(表 2)
getChannel()  取得音乐数据的频数
getLapsedTime()
  以MS为单位取得所演奏的音乐数据的播放时间
getTempo()
  取得音乐数据的速度
getTime()
  取得音乐数据的播放时间
setLoopCount(int count)
  设定演奏的音乐数据的反复播放次数


表 2

■ 音频事件
音频演奏过程中,演奏开始时、停止时、结束时都会发生音频事件,能定义此时的处理。要定义音频事件发生时的处理,有必要安装AudioListener接口和记述audioAction方法内的处理。
然后,使用AudioClip对象的addAudioListener方法进入AudioListener。

public class AudioTest implements AudioListener {

 /**
  * 构造函数
  **/

 public AudioTest() {
  AudioClip audio = Media.getAudioClip("/test.mid");// 读取音乐数据
   audio.addAudioListener(this);// 注册audio事务监听器
 }

 /**
  * 音频事件的处理
  **/

 public void audioAction(AudioClip sound, int event, int param) {
    //记述处理
      •
      •
 }
}

ex. 1
记述处理的audioAction方法的自变量如下所示。
AudioClip sound  传递事件发生来源的对象
int event
  传递事件的种类
int param
  传递事件的参数。由于事件不同,则参数的意思也不同。不包含参数的事件的情况下,只传递0


表 3
此外,事件的种类(audioAction方法的自变量、事件)在AudioListener接口文件夹中定义如下。(表 4)
static int AUDIO_COMPLETE  表示音乐播放结束
static int AUDIO_STARTED  表示音乐播放开始
static int AUDIO_COMPLETE  表示音乐播放停止


表 4

以下展示的是只播放音频数据的简单范例。

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
/**
* 音乐播放的简单范例
*/
public class Audio extends MIDlet {

  Display display;
  AudioCanvas canvas;

  /**
   * 构造函数
   */
  public Audio() {
    canvas = new AudioCanvas();
    display = Display.getDisplay(this);
  }

  protected void startApp() throws MIDletStateChangeException {
    display.setCurrent(canvas);
  }

  protected void pauseApp() {}
  protected void destroyApp(boolean arg0) throws MIDletStateChangeException {}
}

import javax.microedition.lcdui.*;
import com.nec.media.*;

/**
* 音频 canvas
**/
public class AudioCanvas

  extends Canvas
  implements Runnable, CommandListener, AudioListener {

  Command START = new Command("play", Command.OK, 0);
  Command STOP = new Command("stop", Command.OK, 0);

  AudioClip a;// 音乐数据

  Thread th;

  /**
   * 构造函数
   **/
  public AudioCanvas() {

    a = Media.getAudioClip("/_test.mid");// 读取音乐数据
    a.addAudioListener(this);// 注册 AudioListener

    this.addCommand(START);
    this.addCommand(STOP);
    this.setCommandListener(this);

    th = new Thread(this);
    th.start();
  }

/**
* 音频事件的处理
*/
public void audioAction(AudioClip sound, int event, int param) {

    if (sound == a) {
      if (event == AudioListener.AUDIO_COMPLETE) {
        sound.play();

      }
    }
  }

  /**
   * 描绘处理
   */
  protected void paint(Graphics g) {
    g.setColor(255, 255, 255);
    g.fillRect(0, 0, getHeight(), getWidth());

    g.setColor(0, 0, 0);
    g.drawString("Music Play?", 50, 52, Graphics.TOP | Graphics.LEFT);
    g.drawString(
       "channel=" + a.getChannel(),
       30,
       64,
       Graphics.TOP | Graphics.LEFT);
    g.drawString(
       "lapsed time=" + a.getLapsedTime(),
       30,
       76,
       Graphics.TOP | Graphics.LEFT);
    g.drawString(
       "tempo=" + a.getTempo(),
       30,
       88,
       Graphics.TOP | Graphics.LEFT);
    g.drawString(
       "time=" + a.getTime(),
       30,
    100,
       Graphics.TOP | Graphics.LEFT);
  }

  /**
   * 命令事件的处理
   */
  public void commandAction(Command c, Displayable d) {

    System.out.println("test");
    if (c.equals(START)) {
      a.play();
    } else if (c.equals(STOP)) {
      a.stop();
    }
  }

  /**
   * 线程的处理
   * 刷新查看
   */
  public void run() {

    while (true) {
      repaint();
      try{
        Thread.sleep(500);
      }catch(Exception e){

      }
    }
  }
}


ex. 2
接受表示音乐播放结束的事件后,根据明确的开始播放音乐菜单可以无限循环地播放音乐。下面的演示详细记述了上述例子中的audioAction方法,能够实现无限循环播放。(ex. 3)


  /**
   * 音频事件的处理
   */
  public void audioAction(AudioClip sound, int event, int param) {

    if (sound == a) {
      if (event == AudioListener.AUDIO_COMPLETE) {
        sound.play();
      }
    }
  }


ex. 3



制作应用程序
接下来制作实际的发声应用程序。
本讲中制作的是简单的“泡泡龙”游戏。

■ 游戏方法
移动小棒接住反弹的球使其不掉下去,使上方的彩球逐渐消失的游戏。彩球完全消失并清除后,球再落下则此游戏通过。

■ 准备工作
准备游戏必备的图片和音效。
准备以下图片。


· 背景音乐 ( bgm.mid )
· 球反弹时的音效 ( ball.mid )
· 彩球破碎时的音效 ( block.mid )

■ 设计
以下是状态连接图
本讲中为了简单化,在启动应用程序的同时立刻就启动游戏。形成游戏开始、球落下后游戏结束、全部清除彩球后游戏过关。


Figure 4

■ 制作应用程序
现在我们按照以下顺序制作应用程序。
1.类结构
2.变量、常量的定义
3.查看图片和音效
4.使图片运动
5.球的反弹
6.音乐的播放

1.类结构
 下表内容是类结构。(表 5)

  BlockApplication    泡泡龙游戏的MIDlet
  BlockCanvas    泡泡龙游戏的Canvas
表 5

2. 变量、常量的定义
  将下面的应用变量、定量作为BlockCanvas例子的属性并定义。(ex. 4)

  // 状态设定
  private int state; // 状态
  private final int ACTIVE = 1;
  private final int GAME_OVER = 2;
  private final int CLEAR = 3;

  // 彩球的设定
  private final int BLOCK_H = 7; // 彩球横向的个数
  private final int BLOCK_V = 5; // 彩球纵向的个数
  private final int BLOCK_WIDTH = getWidth() / BLOCK_H;
  private final int BLOCK_HEIGHT = BLOCK_WIDTH / 2;
  private boolean block[][] = new boolean[BLOCK_H][BLOCK_V];
  private int blockCount; // 彩球个数
  // 小棒的设定
  private final int BAR_HEIGHT = 11;
  private final int BAR_WIDTH = 23;
  private int barX = 0;
  private int barY = getHeight() - BAR_HEIGHT;
  private int barMovCode Example = 0;

  // 球的设定
  private final int BALL_HEIGHT = 10;
  private final int BALL_WIDTH = 10;
  private int ballX;
  private int ballY;
  private int ballMovCode Example = 5;
  private int ballMoveY = 5;

  private Thread th;

  // 画面类
  private Image barImg = null;
  private Image ballImg = null;
  private Image blockImg = null;

  // 音效类
  private AudioClip bgm; // Background music
  private AudioClip ballSound; // Sound of bouncing ball
  private AudioClip blockSound; // Sound of destroying blocks
ex. 4
3. 查看图片和音效
  查看准备好的图片和音效。BlockCanvas的构造函数内分别读取小棒、球、彩球的图片。(ex. 5)

    // 读取图片
    try {
      barImg = Image.createImage("/bar.png");
      ballImg = Image.createImage("/ball.png");
      blockImg = Image.createImage("/block.png");
    } catch (Code Exampleception e) {
      e.printStackTrace();
    }



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-24 07:08

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表