Package music.ui.instruments

Source Code of music.ui.instruments.PianoKeyCanvas

/*
*    Musical Skill Coach - An interactive midi device friendly program to help music students improve their skills
*    Copyright (C) 2011  Paul-Emile Gaudet
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package music.ui.instruments;

import java.awt.*;
import java.awt.event.MouseEvent;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.ShortMessage;

public class PianoKeyCanvas extends BasicInstrumentCanvas
{
  /**
   *
   */
  private static final long serialVersionUID = 1L;

  protected static final int [] DRAW_PROFILE =
  { 0, 1, 2, 1, 3, 0, 1, 4, 1, 5, 1, 3 };
  protected static final int [] DRAW_COLOUR =
  { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };

  public static final int KEYBOARD_LAYOUT_88KEYS = 0;
  public static final int KEYBOARD_LAYOUT_61KEYS = 1;
  public static final int KEYBOARD_LAYOUT_41KEYS = 2;

  protected static final double [][] PROFILE_RATIOS =
  {
    { 0.00, 1.0, 0.0, 1.714 }, // C
    { 0.00, 1.0, 0.00, 0.00 }, // C#
    { 0.00, 1.0, -0.286, 1.286 }, // D
    { 0.00, 1.0, -0.714, 1.0 }, // E
    { 0.00, 1.0, -0.286, 1.50 }, // G
    { 0.00, 1.0, -0.50, 1.286 }, // A
   
    { 0.00, 1.0, 0.0, 1.286 }, // A as the left key, for 88 keys
    { 0.00, 1.714, 0.0, 1.714 }, // C as the right key, for 88 keys
    { 0.00, 1.0, -0.5, 1.0 } // E as the right key, for 41 keys
  };

  protected static final int [][] LAYOUT_PROFILES =
  {
  { 88, 9, 6, 7, 21 },
  { 61, 0, -1, 7, 36 },
  { 41, 5, -1, 8, 41 } };

  protected int keys;
  protected int midiLeftNoteKey;
  protected int leftKeyNote;
  protected int leftKeyProfileOverride;
  protected int rightKeyProfileOverride;

  protected int keySplitHeight;
  protected int [] topHalfKeyMarkers;
  protected int [] bottomHalfKeyMarkers;
  protected int [] notes;

  protected int keyPosition;
  protected int clickNote;

  public PianoKeyCanvas()
  {
    super();
    keySplitHeight = 0;
    topHalfKeyMarkers = new int[128];
    bottomHalfKeyMarkers = new int[128];
    notes = new int[128];

    setInstrumentType(KEYBOARD_LAYOUT_61KEYS);
  }

  @Override
  public void setInstrumentType(int instrumentType)
  {
    if ((instrumentType < KEYBOARD_LAYOUT_88KEYS) || (instrumentType > KEYBOARD_LAYOUT_41KEYS))
      return;

    keys = LAYOUT_PROFILES[instrumentType][0];
    leftKeyNote = LAYOUT_PROFILES[instrumentType][1];
    leftKeyProfileOverride = LAYOUT_PROFILES[instrumentType][2];
    rightKeyProfileOverride = LAYOUT_PROFILES[instrumentType][3];
    midiLeftNoteKey = LAYOUT_PROFILES[instrumentType][4];
  }

  public void paint(Graphics g)
  {
    Graphics2D g2 = (Graphics2D) g;

    Dimension d = getSize();

    g2.setBackground(Color.GRAY);

    g2.clearRect(0, 0, d.width, d.height);

    double keySpace = (double) d.width / (double) (keys + 1);

    int keyLeftEdge = 0;
    int profile;
    int drawProfile;
    int topLeft, topRight, bottomLeft, bottomRight;
    int i;

    keySplitHeight = d.height * 2 / 3;

    for (i = 0; i < keys; i++)
    {
      profile = (i + leftKeyNote) % DRAW_PROFILE.length;

      if (i + midiLeftNoteKey == keyPosition)
      {
        g2.setColor(Color.RED);
      }
      else if (notes[i + midiLeftNoteKey] == 1)
      {
        g2.setColor(Color.BLUE);
      }
      else if (i + midiLeftNoteKey == 60)
      {
        g2.setColor(Color.YELLOW);
      }
      else
      {
        switch (DRAW_COLOUR[profile])
        {
          case 0:
            g2.setColor(Color.WHITE);
            break;
          case 1:
            g2.setColor(Color.BLACK);
            break;
        }
      }

      drawProfile = DRAW_PROFILE[profile];

      if ((i == 0) && (leftKeyProfileOverride >= 0))
        drawProfile = leftKeyProfileOverride;

      if ((i == keys - 1) && (rightKeyProfileOverride >= 0))
        drawProfile = rightKeyProfileOverride;

      topLeft = (int) ((double) (keySpace) * PROFILE_RATIOS[drawProfile][0]) + keyLeftEdge;
      topRight = (int) ((double) (keySpace) * PROFILE_RATIOS[drawProfile][1]) + keyLeftEdge;
      bottomLeft = (int) ((double) (keySpace) * PROFILE_RATIOS[drawProfile][2]) + keyLeftEdge;
      bottomRight = (int) ((double) (keySpace) * PROFILE_RATIOS[drawProfile][3]) + keyLeftEdge;

      topHalfKeyMarkers[i] = topLeft;
      bottomHalfKeyMarkers[i] = bottomLeft;

      topLeft++;
      topRight--;
      bottomLeft++;
      bottomRight--;

      if (PROFILE_RATIOS[drawProfile][2] == PROFILE_RATIOS[drawProfile][3])
      {
        g2.fillRect(topLeft, 0, topRight - topLeft, d.height * 2 / 3);
        bottomHalfKeyMarkers[i] = -1;
      }
      else
      {
        g2.fillRect(topLeft, 0, topRight - topLeft, d.height);
        g2.fillRect(bottomLeft, d.height * 2 / 3 + 2, bottomRight - bottomLeft, d.height - (d.height * 2 / 3) - 2);
      }

      keyLeftEdge = (int) ((double) (i + 1) * keySpace);
    }
    for (; i < bottomHalfKeyMarkers.length; i++)
    {
      topHalfKeyMarkers[i] = bottomHalfKeyMarkers[i] = -1;
    }
  }

  protected void locateKey(MouseEvent e)
  {
    Point p = e.getPoint();

    if (p.y < keySplitHeight)
    {
      for (keyPosition = 0; keyPosition < keys; keyPosition++)
      {
        if (p.x < topHalfKeyMarkers[keyPosition])
        {
          if (keyPosition > 0)
            keyPosition--;
          break;
        }
      }
    }
    else
    {
      for (keyPosition = 0; keyPosition < keys; keyPosition++)
      {
        if (p.x < bottomHalfKeyMarkers[keyPosition])
        {
          if (keyPosition > 0)
            keyPosition--;
          while ((keyPosition > 0) && (bottomHalfKeyMarkers[keyPosition] == -1))
            keyPosition--;
          break;
        }
      }
    }

    if (keyPosition >= keys)
      keyPosition = keys - 1;

    keyPosition += midiLeftNoteKey;
  }

  @Override
  public void mouseExited(MouseEvent e)
  {
    keyPosition = -1;
    repaint();
  }

  @Override
  public void mousePressed(MouseEvent e)
  {
    locateKey(e);
   
    if ((keyPosition >= 0) && (keyPosition < notes.length))
    {
      notes[keyPosition] = 1;
      clickNote = keyPosition;
    }
   
    if ((midiTrans != null) && (keyPosition > 0))
    {
      midiTrans.addNote(0, keyPosition, 0x60, 100);
    }

    ShortMessage midiMessage = new ShortMessage();

    if (midiRec != null)
    {
      try
      {
        midiMessage.setMessage(ShortMessage.NOTE_ON, 0, keyPosition, 0x60);
        midiRec.send(midiMessage, 0);
      }
      catch (InvalidMidiDataException e1)
      {
      }
    }
  }

  public void getKeyEvent(int keyCharacter)
  {
  }

  @Override
  public void mouseReleased(MouseEvent e)
  {
    locateKey(e);
   
    if ((clickNote >= 0) && (clickNote < notes.length))
    {
      notes[clickNote] = 0;
    }
   
    clickNote = -1;
  }

  @Override
  public void mouseMoved(MouseEvent e)
  {
    int lastKey = keyPosition;
    locateKey(e);
    if (lastKey != keyPosition)
    {
      // invalidate();
      repaint();
    }
  }

  protected void gotMidiEvent(int midiKey, int pressure)
  {
    keyPosition = midiKey;
   
    if ((keyPosition >= 0) && (keyPosition < notes.length))
    {
      if (pressure == 0)
        notes[keyPosition] = 0;
      else
        notes[keyPosition] = 1;
    }
   
   
    keyPosition = -1;
   
    repaint();
  }
}
TOP

Related Classes of music.ui.instruments.PianoKeyCanvas

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.