Android Open Source - OpenSynth Piano Key






From Project

Back to project page OpenSynth.

License

The source code is released under:

Apache License

If you think the Android project OpenSynth 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

/*
 * Copyright 2011 Google Inc.//www .j a  va 2 s  . c om
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.synthesizer.android.widgets.piano;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.util.Log;

import com.google.synthesizer.core.music.Note;

/**
 * PianoKey is the abstract base class for any key on the piano.
 * It keeps track of whether the key is currently being pressed.
 */
public abstract class PianoKey {
  public PianoKey(PianoView piano) {
    piano_ = piano;
    pressed_ = new boolean[PianoView.FINGERS];
    rect_ = new Rect();

    for (int i = 0; i < pressed_.length; ++i) {
      pressed_[i] = false;
    }

    // Set up some default objects for the key to draw itself with.
    fillPaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);
    strokePaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);
    fillPaint_.setStyle(Paint.Style.FILL);
    strokePaint_.setStyle(Paint.Style.STROKE);
    strokePaint_.setColor(Color.BLACK);

    sideStartRect_ = new Rect();
    topRect_ = new Rect();
    sideEndRect_ = new Rect();

    gradientStartPoint_ = new PointF();
    gradientEndPoint_ = new PointF();

    sideStartPaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);
    sideStartPaint_.setColor(Color.argb(0xff, getSideStartColor(), getSideStartColor(), getSideStartColor()));
    sideStartPaint_.setStrokeJoin(Paint.Join.ROUND);
    sideStartPaint_.setStrokeWidth(SIDE_START_STROKE_WIDTH);
    sideStartPaint_.setStyle(Paint.Style.STROKE);
    sideStartPaint_.setShadowLayer(4.0f, 0.0f, -3.0f, Color.BLACK);

    sideEndPaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);
    sideEndPaint_.setColor(Color.argb(0xff, getSideEndColor(), getSideEndColor(), getSideEndColor()));
    sideEndPaint_.setStrokeJoin(Paint.Join.ROUND);
    sideEndPaint_.setStrokeWidth(SIDE_END_STROKE_WIDTH);
    sideEndPaint_.setStyle(Paint.Style.STROKE);

    topPaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);
    topPaint_.setColor(Color.argb(0xff, getTopColor(), getTopColor(), getTopColor()));
    topPaint_.setStrokeJoin(Paint.Join.ROUND);
    topPaint_.setStrokeWidth(TOP_STROKE_WIDTH);
    topPaint_.setStyle(Paint.Style.FILL_AND_STROKE);

    shaderPaint_ = new Paint(Paint.ANTI_ALIAS_FLAG);

    topPath_ = new Path();
    sideStartPath_ = new Path();
    sideEndPath_ = new Path();
  }

  /**
   * Sets rect_ to the position of this key, based on the drawing rect of the piano it's on.
   * @param drawingRect - the position of the piano itself.
   * @param octaves - the number of octaves visible on the piano keyboard.
   */
  public void layout(Rect drawingRect, int octaves) {
      sideStartPath_.reset();
      sideStartPath_.addRect(new RectF(sideStartRect_), Path.Direction.CW);
 
      sideEndPath_.reset();
      sideEndPath_.addRect(new RectF(sideEndRect_), Path.Direction.CW);
 
      topPath_.reset();
      topPath_.addRect(new RectF(topRect_), Path.Direction.CW);

      LinearGradient shader = new LinearGradient(
              gradientStartPoint_.x, gradientStartPoint_.y,
              gradientEndPoint_.x, gradientEndPoint_.y,
              GRADIENT_COLOR0, GRADIENT_COLOR1, TileMode.CLAMP);
      shaderPaint_.setShader(shader);
  }

  /**
   * Draws the key in the current rect_.
   */
  public void draw(Canvas canvas) {
    canvas.drawPath(topPath_, topPaint_);
    canvas.drawPath(sideStartPath_, sideStartPaint_);
    canvas.drawPath(sideEndPath_, sideEndPaint_);
    if (isPressed()) {
      // When the key is pressed, draw an extra alpha gradient on top.
      canvas.drawRect(topRect_, shaderPaint_);
    }
  }

  /**
   * Called when the key's pressed_ state has changed.
   * @param move - true if the key became pressed because the touch moved onto it.
   */
  abstract protected void onPressedChanged(boolean move);

  /**
   * Returns true if the given co-ordinate is inside the key's current rect_.
   */
  public boolean contains(int x_, int y_) {
    return rect_.contains(x_, y_);
  }

  /**
   * Returns true if any finger is pressing this key.
   */
  public boolean isPressed() {
    for (int i = 0; i < pressed_.length; ++i) {
      if (pressed_[i]) {
        return true;
      }
    }
    return false;
  }

  /**
   * Called when a finger has touched down onto this key.
   * Returns true iff whether the pressed state changed.
   */
  final public boolean onTouchDown(int finger) {
    if (finger >= pressed_.length) {
      Log.e(getClass().getName(),
            "Finger " + finger + " was pressed down, but PianoKey only supports " +
            pressed_.length + " fingers.");
    }
    boolean wasPressed = isPressed();
    pressed_[finger] = true;
    if (!wasPressed) {
      onPressedChanged(false);
      return true;
    }
    return false;
  }

  /**
   * Called on a touch event where this key is not being touched.  It may already be up.
   * Returns true iff whether the pressed state changed.
   */
  final public boolean onTouchUp(int finger) {
    if (finger >= pressed_.length) {
      Log.e(getClass().getName(),
            "Finger " + finger + " was released, but PianoKey only supports " +
            pressed_.length + " fingers.");
    }
    boolean wasPressed = isPressed();
    pressed_[finger] = false;
    boolean isPressed = isPressed();
    if (wasPressed && !isPressed) {
      onPressedChanged(false);
      return true;
    }
    return false;
  }

  /**
   * Called when there's a touch event where the finger was moved onto this key.
   * Returns true iff whether the pressed state changed.
   */
  final public boolean onTouchMoved(int finger) {
    if (finger >= pressed_.length) {
      Log.e(getClass().getName(),
            "Finger " + finger + " was pressed down, but PianoKey only supports " +
            pressed_.length + " fingers.");
    }
    boolean wasPressed = isPressed();
    pressed_[finger] = true;
    if (!wasPressed) {
      onPressedChanged(true);
      return true;
    }
    return false;
  }

  /**
   * Utility function to calculate the width that a standard white key on this keyboard should be.
   */
  protected static int getWhiteKeyWidth(Rect drawingRect, int octaves) {
    // It's +2 to reserve space for the octave-up/down buttons.
    return drawingRect.width() / ((WHITE_KEYS.length * octaves) + 2);
  }
  
  /**
   * Utility function to calculate the height that a standard white key on this keyboard should be.
   */
  protected static int getWhiteKeyHeight(Rect drawingRect) {
    return drawingRect.height();
  }

  protected int getSideStartColor() {
    return 0;
  }

  protected int getSideEndColor() {
    return 0;
  }

  protected int getTopColor() {
    return 0;
  }

  protected void shrinkRect(Rect rect, int pixels) {
      rect.left += pixels;
      rect.top += pixels;
      rect.right -= pixels;
      rect.bottom -= pixels;
  }

  // The piano this key is on.
  protected PianoView piano_;

  // Is each keys currently being pressed?
  protected boolean[] pressed_;

  // The area this key occupies.
  protected Rect rect_;

  // Objects for subclasses to use for painting, just so they don't have to reallocate every time.
  protected Paint fillPaint_;
  protected Paint strokePaint_;

  protected Rect sideStartRect_;
  protected Rect sideEndRect_;
  protected Rect topRect_;

  protected PointF gradientStartPoint_;
  protected PointF gradientEndPoint_;

  private Paint sideStartPaint_;
  private Paint sideEndPaint_;
  private Paint topPaint_;
  private Paint shaderPaint_;

  private Path sideStartPath_;
  private Path sideEndPath_;
  private Path topPath_;

  // Constants to map notes onto the keys.
  protected static final int WHITE_KEYS[] = {
      Note.C, Note.D, Note.E, Note.F, Note.G, Note.A, Note.B };
  protected static final int BLACK_KEYS[] = {
      Note.C_SHARP, Note.E_FLAT, Note.NONE, Note.F_SHARP, Note.A_FLAT, Note.B_FLAT, Note.NONE };

  private static final float SIDE_START_STROKE_WIDTH = 8.0f;
  private static final float SIDE_END_STROKE_WIDTH = 1.0f;
  private static final float TOP_STROKE_WIDTH = 7.0f;

  private static final int GRADIENT_COLOR0 = Color.argb(0xcc, 0x1a, 0x1a, 0x1a);
  private static final int GRADIENT_COLOR1 = Color.argb(0x00, 0x1a, 0x1a, 0x1a);
}




Java Source Code List

com.google.synthesizer.android.widgets.piano.BlackPianoKey.java
com.google.synthesizer.android.widgets.piano.NotePianoKey.java
com.google.synthesizer.android.widgets.piano.OctavePianoKey.java
com.google.synthesizer.android.widgets.piano.PianoKey.java
com.google.synthesizer.android.widgets.piano.PianoViewListener.java
com.google.synthesizer.android.widgets.piano.PianoView.java
com.google.synthesizer.android.widgets.piano.WhitePianoKey.java
com.google.synthesizer.core.midi.MidiListener.java
com.google.synthesizer.core.music.Note.java
com.indigo_lab.android.opensynth.OpenSynthActivity.java
com.indigo_lab.android.opensynth.ViewPagerAdapter.java
com.indigo_lab.android.opensynth.view.ArpeggioView.java
com.indigo_lab.android.opensynth.view.ControllerView.java
com.indigo_lab.android.opensynth.view.EnvelopeView.java
com.indigo_lab.android.opensynth.view.FilterEnvelopeView.java
com.indigo_lab.android.opensynth.view.FilterView.java
com.indigo_lab.android.opensynth.view.ImageRadioButton.java
com.indigo_lab.android.opensynth.view.ModulationView.java
com.indigo_lab.android.opensynth.view.OscillatorDetailView.java
com.indigo_lab.android.opensynth.view.OscillatorView.java
com.indigo_lab.android.opensynth.view.RadioButton.java
com.indigo_lab.android.opensynth.view.VolumeEnvelopeView.java
org.thebends.synth.Arpeggio.java
org.thebends.synth.Controller.java
org.thebends.synth.Envelope.java
org.thebends.synth.FilterCutoff.java
org.thebends.synth.Filter.java
org.thebends.synth.FixedParameter.java
org.thebends.synth.KeyStack.java
org.thebends.synth.KeyboardOscillator.java
org.thebends.synth.LFO.java
org.thebends.synth.LagProcessor.java
org.thebends.synth.LowPassFilter.java
org.thebends.synth.MutableParameter.java
org.thebends.synth.Oscillator.java
org.thebends.synth.Parameter.java
org.thebends.synth.ResonantFilter.java
org.thebends.synth.SynthJni.java
org.thebends.synth.SynthTrack.java
org.thebends.synth.Volume.java