Android Open Source - Music-Theory Score View






From Project

Back to project page Music-Theory.

License

The source code is released under:

GNU General Public License

If you think the Android project Music-Theory listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.mt.staff;
/*from  w ww .  j  ava 2  s  .  c  om*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.view.View;

import com.mt.R;
import com.mt.theory.Accidental;
import com.mt.theory.Clef;
import com.mt.theory.KeySignature;
import com.mt.theory.Note;
import com.mt.theory.NoteGroup;
import com.mt.theory.Score;
import com.mt.theory.Tone;
import com.mt.utils.NoteUtil;

public class ScoreView extends View {

  private static Drawable flatDrawable;

  private static Drawable sharpDrawable;
  private static final int STAFF_SPACING = 30;

  private Paint paint;

  private Score score;

  public ScoreView(Context context, Score score) {
    super(context);
    this.score = score;
    this.paint = new Paint();
    paint.setColor(0xFFFFFFFF);

    if (sharpDrawable == null || flatDrawable == null) {
      sharpDrawable = getResources().getDrawable(R.drawable.sharp);
      flatDrawable = getResources().getDrawable(R.drawable.flat);
    }
  }

  private void drawKey(Canvas canvas) {
    if (score.getKeySignature() == null || score.getClef() == null) {
      return;
    }

    Drawable d;

    KeySignature key = score.getKeySignature();
    Accidental aType = key.getAccidentalType();
    Clef clef = score.getClef();
    int verticalCenter = (canvas.getClipBounds().height() / 2);
    int minKeyPosition;
    int maxKeyPosition;

    if (aType.equals(Accidental.FLAT)) {
      d = flatDrawable;
      minKeyPosition = clef.getMinFlatKeyPosition();
      maxKeyPosition = clef.getMaxFlatKeyPosition();
    } else {
      d = sharpDrawable;
      minKeyPosition = clef.getMinSharpKeyPosition();
      maxKeyPosition = clef.getMaxSharpKeyPosition();
    }

    float dRatio = (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight();
    float heightMod = aType.equals(Accidental.FLAT) ? 0.75f : 0.50f;
    int height = (int) (2.25 * STAFF_SPACING);
    int width = (int) (dRatio * height);
    int left = 150;
    int right;
    int top;
    int bottom;

    // Key signatures have a particular order and the symbols don't always
    // stay within a given octave for a particular clef. To solve the min
    // and max positions of the key signature are hard-coded for each
    // supported clef.
    for (Tone tone : key.getAccidentals()) {
      int positionValue = -1;
      int totalOffset;
      int octave = 4;
      while (positionValue < minKeyPosition || positionValue > maxKeyPosition) {
        positionValue = NoteUtil.getPositionValue(octave, tone);
        if (positionValue >= minKeyPosition && positionValue <= maxKeyPosition) {
          // Draw
          totalOffset = NoteUtil.getStepsFromStaffCenter(positionValue, clef);
          top = (int) (verticalCenter + ((totalOffset * (STAFF_SPACING / 2)) * -1) - (heightMod * height));
          bottom = top + height;
          right = left + width;

          d.setBounds(left, top, right, bottom);
          d.draw(canvas);

          left += 25;
        } else if (positionValue < minKeyPosition) {
          octave++;
        } else {
          octave--;
        }
      }
    }
  }

  private void drawNoteGroup(NoteGroup noteGroup, Canvas canvas) {
    Note note = noteGroup.getNotes().get(0);

    Rect bounds = canvas.getClipBounds();
    int verticalCenter = (bounds.height() / 2);

    int totalOffset = NoteUtil.getStepsFromStaffCenter(note, score.getClef());

    // Determine Actual Note
    int noteHeadTop = verticalCenter + ((totalOffset * (STAFF_SPACING / 2)) * -1);
    int noteHeadVerticalCenter = (int) (noteHeadTop + ((.9 * STAFF_SPACING) / 2));

    // Is this note higher / lower than the note at the staff center?
    boolean higherTone = (totalOffset >= 0);

    // Ledger Lines
    int ledgerLineCount = NoteUtil.getLedgerCount(note, score.getClef());
    boolean ledgerLines = ledgerLineCount > 0;

    if (ledgerLines) {
      int ledgerLeft = -10;
      int ledgerRight = 60;
      int offsetShift = higherTone ? STAFF_SPACING * -1 : STAFF_SPACING;
      for (int i = 0; i < ledgerLineCount; i++) {
        int ledgerTop = verticalCenter + (offsetShift * (3 + i));
        canvas.drawLine(ledgerLeft, ledgerTop, ledgerRight, ledgerTop, paint);
      }
    }

    int tempAlpha = paint.getAlpha();
    paint.setStrokeWidth(2.0f);

    // Draw Note Stem
    int stemTop = higherTone ? noteHeadVerticalCenter - 10 : noteHeadVerticalCenter - (3 * STAFF_SPACING) - 10;
    int stemBottom = higherTone ? noteHeadVerticalCenter + (3 * STAFF_SPACING) - 10 : noteHeadVerticalCenter - 10;
    int stemLeft = higherTone ? 5 : 43;

    // If the note shows ledger lines, the stem goes all the way to the
    // staff center
    stemTop = (ledgerLines && !higherTone) ? verticalCenter : stemTop;
    stemBottom = (ledgerLines && higherTone) ? verticalCenter : stemBottom;

    canvas.drawLine(stemLeft, stemTop, stemLeft, stemBottom, paint);

    paint.setStrokeWidth(1.0f);

    // Rotate & Draw Note Head
    canvas.save();
    canvas.translate(0, noteHeadTop - 5);
    canvas.rotate(-20);
    paint.setFlags(Paint.ANTI_ALIAS_FLAG);

    canvas.drawOval(new RectF(new Rect(0, 0, (int) (1.4 * STAFF_SPACING), (int) (0.9 * STAFF_SPACING))), paint);

    paint.setFlags(~Paint.ANTI_ALIAS_FLAG);
    paint.setAlpha(tempAlpha);
    canvas.restore();
  }

  private void drawStave(Canvas canvas, int left, int top, int right, int bottom) {
    // Draw Horizontal Staff Lines
    for (int i = 0; i < 5; i++) {
      int verticalPosition = top + (i * STAFF_SPACING);
      canvas.drawLine(left, verticalPosition, right, verticalPosition, paint);
    }

    // Draw Left Staff Boundry Line
    canvas.drawLine(left, top, left, bottom, paint);

    // Draw Thick Double Bar
    paint.setStrokeWidth(10.0f);
    canvas.drawLine(right - 5, top, right - 5, bottom, paint);
    paint.setStrokeWidth(1.0f);
    canvas.drawLine(right - 15, top, right - 15, bottom, paint);

    // Draw Clef
    Drawable d = getResources().getDrawable(score.getClef().getResourceId());
    float clefRatio = (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth();
    int clefWidth = (int) (2.7 * STAFF_SPACING);
    int clefHeight = (int) (clefRatio * clefWidth);

    int clefLeft = left + 25;
    int clefRight = clefLeft + clefWidth;

    int clefUpperPortionHeight = (int) (score.getClef().getRatioAboveMiddle() * clefHeight);
    int clefTop = bottom - ((bottom - top) / 2) - clefUpperPortionHeight;
    int clefBottom = clefTop + clefHeight;

    d.setBounds(clefLeft, clefTop, clefRight, clefBottom);
    d.draw(canvas);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Staff Bounds
    Rect bounds = canvas.getClipBounds();
    int canvasVerticalCenter = (bounds.height() / 2);
    int canvasHorizontalCenter = (getWidth() / 2);
    int staffTop = (int) (canvasVerticalCenter - (STAFF_SPACING * 2));

    // Draw Staff
    drawStave(canvas, 20, staffTop, bounds.width() - 20, staffTop + STAFF_SPACING * 4);

    // Draw Key Signature
    drawKey(canvas);

    // Draw Notes
    canvas.save();
    canvas.translate(canvasHorizontalCenter - 15, 0);
    for (NoteGroup noteGroup : score.getNoteGroups()) {
      drawNoteGroup(noteGroup, canvas);
    }
    canvas.restore();

    LinearGradient lg = new LinearGradient(0,
      50,
      0,
      canvas.getClipBounds().height() - 50,
      0x00000000,
      0x66000000,
      Shader.TileMode.CLAMP);
    paint.setShader(lg);
    canvas.drawPaint(paint);
    paint.reset();
  }

}




Java Source Code List

com.mt.HomeActivity.java
com.mt.QuizActivity.java
com.mt.audio.MidiTrack.java
com.mt.keys.KeySignatureQuizActivity.java
com.mt.keys.KeySignatureQuizPreferenceActivity.java
com.mt.notes.NoteQuizActivity.java
com.mt.notes.NoteQuizPreferenceActivity.java
com.mt.staff.ScoreView.java
com.mt.theory.Accidental.java
com.mt.theory.Clef.java
com.mt.theory.Duration.java
com.mt.theory.Interval.java
com.mt.theory.KeySignature.java
com.mt.theory.NoteGroup.java
com.mt.theory.Note.java
com.mt.theory.Quality.java
com.mt.theory.Score.java
com.mt.theory.TimeSignature.java
com.mt.theory.Tone.java
com.mt.utils.NoteUtil.java
com.mt.utils.QuizUtil.java