<< 前 ホーム 次 >>

bakaid: 20131128

music-synthesizer-for-androidなんですけど、こないだ
「素人の自分が感じるようなレイテンシはなかった」って
書きましたけど、旧Nexus7でUSB電源ケーブルを抜くと
CPUパワーが落ちるようで、そうなるとタッチを取り
こぼすことがありました。あと、ごく稀にノイズが出ます。

で、music-synthesizerなんですけど、鍵盤のレイアウト
がちょっと自分の好みと違うんですね。自分は歌メロを
指1本で弾く程度の楽しみ方なんですけど、music-
synthesizerの鍵盤はC4...B3なんですよね。これだと
歌メロを弾くには向いてない。

ということで、レイアウトを変えてみようとソースを
見てみました。AndroidManifest.xmlを見ればわかる
ように、起動時のアクティビティは
com.levien.synthesizer.android.ui.PianoActivity2
なんですね。他にもアクティビティが並んでますけど、
今のところ、UIで切り替えることはできないのかな?

PianoActivity2.javaを見ると、鍵盤は
com.levien.synthesizer.android.widgets.piano.PianoView
になるみたい。ちなみに、PianoActivity2にUSBがらみ
のコードがあって、USB MIDIキーボードがつながるん
じゃないかと。

PianoView.javaを見ると、白鍵、黒鍵、それと左右の
オクターブ変えるキーがnewされています。キー関係の
クラス構成を整理しておくと:

  PianoKey
    |
    +--OctavePianoKey
    |
    +--NotePianoKey
        |
        +--BlackPianoKey
        |
        +--WhitePianoKey

という感じ。PianoKeyはViewじゃありません。PianoKey
の役割は大体:

* 音程
* 描画領域
* 描画
* ヒット判定

といったところ。

で、鍵盤のレイアウトを変えたいわけで、PianoKeyの
生成と描画領域の割り当てが別れているとやりにくい。
PianoKeyの生成はPianoViewでやって、描画領域の割り
当てはPianoKeyにやらせています。これを一ヶ所に
まとめたい。手始めにPianoKeyの生成を別クラスに
移します:

public class PianoKeyboard {
  // Generate the set of keys.  There are 12 music keys per octave, plus the octave change button
  // on either end.
  public PianoKey[] createKeys(PianoView piano, int octaves) {
    ArrayList<PianoKey> keys = createWhiteKeys(piano, octaves);
    keys.addAll(createBlackKeys(piano, octaves));
    keys.addAll(createOctaveChangingKeys(piano));
    PianoKey[] typeArg = {};
    return keys.toArray(typeArg);
  }

  private ArrayList<PianoKey> createWhiteKeys(PianoView piano, int octaves) {
    ArrayList<PianoKey> keys = new ArrayList<PianoKey>();
    for (int octave = 0; octave < octaves; ++octave) {
      for (int note = 0; note < 7; ++note) {
        keys.add(new WhitePianoKey(piano, octave, note));
      }
    }
    return keys;
  }

  private ArrayList<PianoKey> createBlackKeys(PianoView piano, int octaves) {
    ArrayList<PianoKey> keys = new ArrayList<PianoKey>();
    for (int octave = 0; octave < octaves; ++octave) {
      for (int note = 0; note < 7; ++note) {
        if (BlackPianoKey.isValid(note)) {
          keys.add(new BlackPianoKey(piano, octave, note));
        }
      }
    }
    return keys;
  }

  private ArrayList<PianoKey> createOctaveChangingKeys(PianoView piano) {
    ArrayList<PianoKey> keys = new ArrayList<PianoKey>();
    keys.add(new OctavePianoKey(piano, -1));
    keys.add(new OctavePianoKey(piano, 1));
    return keys;
  }

  public void draw(Canvas canvas, Rect drawingRect, PianoKey[] keys, int octaves) {
    layoutKeys(drawingRect, keys, octaves);
    drawKeys(canvas, keys);
  }

  private void layoutKeys(Rect drawingRect, PianoKey[] keys, int octaves) {
    for (int i = 0; i < keys.length; ++i) {
      keys[i].layout(drawingRect, octaves);
    }
  }

  private void drawKeys(Canvas canvas, PianoKey[] keys) {
    for (int i = 0; i < keys.length; ++i) {
      keys[i].draw(canvas);
    }
  }
}

public class PianoView extends View {
  public PianoView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PianoView);
    octaves_ = a.getInteger(R.styleable.PianoView_octaves, 1);
    firstOctave_ = a.getInteger(R.styleable.PianoView_first_octave, 4);
    drawingRect_ = new Rect();
    keys_ = keyboard.createKeys(this, octaves_);
    pianoViewListener_ = null;
  }

  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    getDrawingRect(drawingRect_);
    keyboard.draw(canvas, drawingRect_, keys_, octaves_);
  }
  ...
  private PianoKeyboard keyboard = new PianoKeyboard();
}

本家Permlink

<< 前 ホーム 次 >>


Copyright © 1905 tko at jitu.org

バカが征く on Rails