Lorem ipsum dolor sit amet, consectetur adipiscing elit. Test link

PianoView with Sound in Android

JavaScript


public class PianoView extends View {
    private static final int[] NOTES = {60, 62, 64, 65, 67, 69, 71};
    private Paint mKeyPaint;
    private Paint mBlackKeyPaint;
    private SparseBooleanArray mActivePointers;
    private SoundPool mSoundPool;
    private int[] mSoundIds;

    public PianoView(Context context) {
        super(context);
        init(null, 0);
    }

    public PianoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public PianoView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        mKeyPaint = new Paint();
        mKeyPaint.setColor(Color.WHITE);
        mKeyPaint.setStyle(Paint.Style.FILL);
        mBlackKeyPaint = new Paint();
        mBlackKeyPaint.setColor(Color.BLACK);
        mBlackKeyPaint.setStyle(Paint.Style.FILL);
        mActivePointers = new SparseBooleanArray();
    }

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

        int width = getWidth();
        int height = getHeight();
        int keyWidth = width / NOTES.length;

        for (int i = 0; i < NOTES.length; i++) {
            int note = NOTES[i];
            if (note % 12 == 1 || note % 12 == 4 || note % 12 == 6 || note % 12 == 9 || note % 12 == 11) {
                // Draw black key
                canvas.drawRect(i * keyWidth + keyWidth * 3 / 4, 0, (i + 1) * keyWidth - keyWidth / 4, height / 2, mBlackKeyPaint);
            } else {
                // Draw white key
                canvas.drawRect(i * keyWidth, 0, (i + 1) * keyWidth, height, mKeyPaint);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        int pointerIndex = event.getActionIndex();
        int pointerId = event.getPointerId(pointerIndex);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                mActivePointers.put(pointerId, true);
                int noteIndex = getNoteIndex(event.getX(pointerIndex), event.getY(pointerIndex));
                int note = NOTES[noteIndex];
                playNote(note);
                invalidate();
                break;

            case MotionEvent.ACTION_MOVE:
                for (int i = 0; i < event.getPointerCount(); i++) {
                    int id = event.getPointerId(i);
                    if (mActivePointers.get(id)) {
                        int noteIndex2 = getNoteIndex(event.getX(i), event.getY(i));
                        int note2 = NOTES[noteIndex2];
                        playNote(note2);
                    }
                }
                invalidate();
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
                mActivePointers.put(pointerId, false);
                stopNote();
                invalidate();
                break;
        }
        return true;
    }

    private int getNoteIndex(float x, float y) {
        int width = getWidth();
        int height = getHeight();
        int keyWidth = width / NOTES.length;
        int keyIndex = (int) (x / keyWidth);
        int note = NOTES[keyIndex];
        // Check if the touch event is on a black key
        if (note % 12 == 1 || note % 12 == 4 || note % 12 == 6 || note % 12 == 9 || note % 12 == 11) {
            float blackKeyWidth = keyWidth * 3 / 4;
            float blackKeyHeight = height / 2;
            float blackKeyY = blackKeyHeight;
            if (y < blackKeyHeight) {
                blackKeyY = 0;
            }
            float blackKeyX = keyIndex * keyWidth + keyWidth - blackKeyWidth / 2;
            if (x < blackKeyX - keyWidth / 4 || x > blackKeyX + blackKeyWidth + keyWidth / 4) {
                // Touch event is not on the black key, use the white key instead
                keyIndex++;
                note = NOTES[keyIndex];
            } else {
                return keyIndex;
            }
        }
        return keyIndex;
    }

    private void playNote(int note) {
        if (mSoundPool == null) {
            mSoundPool = new SoundPool(7, AudioManager.STREAM_MUSIC, 0);
            mSoundIds = new int[NOTES.length];
            for (int i = 0; i < NOTES.length; i++) {
                mSoundIds[i] = mSoundPool.load(getContext(), getSoundResourceId(NOTES[i]), 1);
            }
        }
        int index = Arrays.binarySearch(NOTES, note);
        if (index >= 0 && index < mSoundIds.length) {
            mSoundPool.play(mSoundIds[index], 1.0f, 1.0f, 0, 0, 1.0f);
        }
    }

    private void stopNote() {
        if (mSoundPool != null) {
            mSoundPool.release();
            mSoundPool = null;
            mSoundIds = null;
        }
    }

    private int getSoundResourceId(int note) {
        int resourceId = getResources().getIdentifier("note_" + note, "raw", getContext().getPackageName());
        return resourceId;
    }
}

        

Post a Comment