Hatena::ブログ(Diary)

hidecheckの日記

2009-11-05

AndroidでmidiとかJetCreatorとかで鍵盤アプリとか作成

| 00:58

f:id:hidecheck:20091106005200p:image

Androidmidiを演奏するにはMediaPlayerを使った方法とJetPlayerを使った方法がある。

前者は音楽ファイルとして演奏するのに向いている。

後者は動的な演奏や、効果音などのインタラクティブな音楽の演奏をしたいときに使うのに向いている。

今回はJetPlayerを使った鍵盤アプリを作成する。

JetCreator日本語ドキュメント※誤訳だらけです

JetPlayerAPIリファレンス

midiファイルを再生するまでの流れまとめ

  • 演奏したいmidiデータを用意する
  • JetCreatorを使ってjetファイルを作成する
    • JetPlayerでmidiを演奏するにはJetCreatorを使ってjetファイルを作成する必要がある。つまり、通常のmidiファイルをJetPlayerを使って演奏することは無理
    • jetファイルの作成手順
      • JetCreatorを起動する
      • Segmentにmidiファイルを追加する
      • jetファイルを作成する
  • Androidアプリ内でJetPlayerを使って演奏する
jetでできること

jetで何が出来るのかをまとめる

  • Mute/Un-mute Synchronization ミュート・アンミュートの同期
    • Segmentを使うことによってあたかもmidiトラックを操作するようなことが出来る。
    • 音楽の中のイベントにミュート・アンミュートを同期させることが出来る。
  • Audio Synchronization オーディオ同期
    • オーディオの中のイベントにゲームプレーを同期させることができる
    • オトゲーでいうところの特定のタイミングに合わせた音楽再生的なイメージでおk
  • midiイベントAPIなどの呼び出しはできない
    • 従来のmidishortmessageとかを使ってmidi音源を鳴らすことはできない。
    • それっぽいことをしたいなら以下の手順
      • 同等のmidiファイルを用意
      • JetCreatorを使ってSegmentに追加
      • JetPlayerを実装して、Segmentの再生をする

midiのほうが便利じゃね?


アプリケーション作成手順

jetファイルの作成

midiファイルを用意する

  • 「ド」〜「ソ」の音を再生するmidiファイルを用意する
  • ファイル名:c.mid〜g.mid

■JetCreatorを起動する

JetCreatorを使うには、Python2.5以上、wxPython2.7以上がインストールされている必要がある

JetCreatorはAndroidsdkのインストールディレクトリ以下のtools/Jet/JetCreator/にある「JetCreator.py」から起動する

OpenWomdpw画面起動したら「New」ボタンをクリックし新規jetファイルを作成する

f:id:hidecheck:20091106005159p:image

JetCreatorのMainWindowが表示される

f:id:hidecheck:20091106005303p:image


midiファイルを追加する

「ド」の音を追加する

  • 「Add」ボタンをクリック
  • Revice Segment画面が起動する
  • Segment NameNoteC
  • MIDI File:c.mid
  • Ending M/B/T:2/1/0
  • 「OK」ボタンクリック

同様に「レ〜ソ」の音を追加する

f:id:hidecheck:20091106005341p:image

f:id:hidecheck:20091106010034p:image


■jetファイルを作成する

  • [File]→「Save As」
  • ファイル名:doremi.jtc
    • jtcを作成すると同時にjetファイルが作成される
  • 保存
  • jetファイルが作成されていることを確認する

f:id:hidecheck:20091106005516p:image

f:id:hidecheck:20091106005511p:image


Androidアプリの作成

アプリ概要

  • SampleJetPlayerというプロジェクト名で作成する
  • resフォルダ以下にrawフォルダを追加する
  • rawにdoremi.jetファイルを配置する

f:id:hidecheck:20091106005541p:image

  • 音再生ボタン:ドレミファソの5つのボタンを定義する

f:id:hidecheck:20091106005725p:image


■SampleJetPlayer

  • jetファイルを演奏するJetPlayerオブジェクトを定義する
  • JetPlayerインスタンスを取得する
  • リソースからdoremi.jetファイルを読み込む
  • 各ボタンで対象の音Segmentを指定して再生する
  • SegmentはJetCreaterメインウィンドウの順番で0〜から始まる。
  • Segmentの再生はJetPlayer.queueJetSegmentメソッドを使う
public boolean queueJetSegment (int segmentNum, int libNum, int repeatCount, int transpose, int muteFlags, byte userID) 

Segment再生手順

  • JetPlayer.creatQuereでキューを空にする
  • queueJetSegmentでキュー追加
    • 引数
    • 1 SegmentNo
    • 2 DLSとかのsoundbankを指定する使わない場合は-1
    • 3 リピート回数
    • 4 音程
    • 5 ミュートフラグ
    • 6 多分コールバック的な感じのやつonJetUserIdUpdate(JetPlayer, int, int) とかが関係するらしい
  • キューを再生
jetPlayer.clearQueue();
jetPlayer.queueJetSegment(0, -1, 0, 0, 0, (byte) 0);
jetPlayer.play();

今回のSegment仕様

SegmentNoNote
0C
1D
2E
3F
4G
ソース
package com.example.jet;

import android.app.Activity;
import android.media.JetPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SampleJetPlayer extends Activity {

	private Button btC;
	private Button btD;
	private Button btE;
	private Button btF;
	private Button btG;
	private JetPlayer jetPlayer;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		initButton();
		this.jetPlayer = JetPlayer.getJetPlayer();
		this.jetPlayer.loadJetFile(getResources().openRawResourceFd(R.raw.doremi));

	}

	private void initButton() {
		this.btC = (Button) findViewById(R.id.Button01);
		this.btD = (Button) findViewById(R.id.Button02);
		this.btE = (Button) findViewById(R.id.Button03);
		this.btF = (Button) findViewById(R.id.Button04);
		this.btG = (Button) findViewById(R.id.Button05);
		this.btC.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				jetPlayer.clearQueue();
				jetPlayer.queueJetSegment(0, -1, 0, 0, 0, (byte) 0);
				jetPlayer.play();

			}
		});
		this.btD.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				jetPlayer.clearQueue();
				jetPlayer.queueJetSegment(1, -1, 0, 0, 0, (byte) 0);
				jetPlayer.play();

			}
		});

		this.btE.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				jetPlayer.clearQueue();
				jetPlayer.queueJetSegment(2, -1, 0, 0, 0, (byte) 0);
				jetPlayer.play();

			}
		});
		this.btF.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				jetPlayer.clearQueue();
				jetPlayer.queueJetSegment(3, -1, 0, 0, 0, (byte) 0);
				jetPlayer.play();

			}
		});
		this.btG.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				jetPlayer.clearQueue();
				jetPlayer.queueJetSegment(4, -1, 0, 0, 0, (byte) 0);
				jetPlayer.play();

			}
		});
	}
}

akingaking 2010/05/24 17:24 I am Taiwan developer
Thank you share code.

YALEYADO.........