package com.example.miditest;

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

import org.billthefarmer.mididriver.MidiDriver;

public class MainActivity extends AppCompatActivity implements MidiDriver.OnMidiStartListener,
        View.OnTouchListener, AdapterView.OnItemSelectedListener {

    private MidiDriver midiDriver;
    private byte[] event;
    private int[] config;

    private Button buttonSustain;

    private Button buttonC;
    private Button buttonCsharp;
    private Button buttonD;
    private Button buttonDsharp;
    private Button buttonE;
    private Button buttonF;
    private Button buttonFsharp;
    private Button buttonG;
    private Button buttonGsharp;
    private Button buttonA;
    private Button buttonAsharp;
    private Button buttonB;
    private Button buttonC2;

    private Spinner spinnerInstruments;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set up the buttons.
        buttonSustain = (Button)findViewById(R.id.buttonSustain);
        buttonSustain.setOnTouchListener(this);

        buttonC = (Button)findViewById(R.id.buttonC);
        buttonC.setOnTouchListener(this);
        buttonCsharp = (Button)findViewById(R.id.buttonCsharp);
        buttonCsharp.setOnTouchListener(this);
        buttonD = (Button)findViewById(R.id.buttonD);
        buttonD.setOnTouchListener(this);
        buttonDsharp = (Button)findViewById(R.id.buttonDsharp);
        buttonDsharp.setOnTouchListener(this);
        buttonE = (Button)findViewById(R.id.buttonE);
        buttonE.setOnTouchListener(this);
        buttonF = (Button)findViewById(R.id.buttonF);
        buttonF.setOnTouchListener(this);
        buttonFsharp = (Button)findViewById(R.id.buttonFsharp);
        buttonFsharp.setOnTouchListener(this);
        buttonG = (Button)findViewById(R.id.buttonG);
        buttonG.setOnTouchListener(this);
        buttonGsharp = (Button)findViewById(R.id.buttonGsharp);
        buttonGsharp.setOnTouchListener(this);
        buttonA = (Button)findViewById(R.id.buttonA);
        buttonA.setOnTouchListener(this);
        buttonAsharp = (Button)findViewById(R.id.buttonAsharp);
        buttonAsharp.setOnTouchListener(this);
        buttonB = (Button)findViewById(R.id.buttonB);
        buttonB.setOnTouchListener(this);
        buttonC2 = (Button)findViewById(R.id.buttonC2);
        buttonC2.setOnTouchListener(this);


        // Set up the instruments spinner.
        spinnerInstruments = (Spinner)findViewById(R.id.spinnerInstruments);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
                R.array.instruments_array, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerInstruments.setAdapter(adapter);
        spinnerInstruments.setOnItemSelectedListener(this);

        // Instantiate the driver.
        midiDriver = MidiDriver.getInstance();
        // Set the listener.
        midiDriver.setOnMidiStartListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        midiDriver.start();

        // Get the configuration.
        config = midiDriver.config();

        // Print out the details.
        Log.d(this.getClass().getName(), "maxVoices: " + config[0]);
        Log.d(this.getClass().getName(), "numChannels: " + config[1]);
        Log.d(this.getClass().getName(), "sampleRate: " + config[2]);
        Log.d(this.getClass().getName(), "mixBufferSize: " + config[3]);


    }

    @Override
    protected void onPause() {
        super.onPause();
        midiDriver.stop();
    }

    @Override
    public void onMidiStart() {
        Log.d(this.getClass().getName(), "onMidiStart()");
    }

    private void playNote(int noteNumber) {

        // Construct a note ON message for the note at maximum velocity on channel 1:
        event = new byte[3];
        event[0] = (byte) (0x90 | 0x00);  // 0x90 = note On, 0x00 = channel 1
        event[1] = (byte) noteNumber;
        event[2] = (byte) 0x7F;  // 0x7F = the maximum velocity (127)

        // Send the MIDI event to the synthesizer.
        midiDriver.write(event);

    }

    private void stopNote(int noteNumber, boolean sustainUpEvent) {

        // Stop the note unless the sustain button is currently pressed. Or stop the note if the
        // sustain button was depressed and the note's button is not pressed.
        if (!buttonSustain.isPressed() || sustainUpEvent) {
            // Construct a note OFF message for the note at minimum velocity on channel 1:
            event = new byte[3];
            event[0] = (byte) (0x80 | 0x00);  // 0x80 = note Off, 0x00 = channel 1
            event[1] = (byte) noteNumber;
            event[2] = (byte) 0x00;  // 0x00 = the minimum velocity (0)

            // Send the MIDI event to the synthesizer.
            midiDriver.write(event);
        }
    }

    private void selectInstrument(int instrument) {

        // Construct a program change to select the instrument on channel 1:
        event = new byte[2];
        event[0] = (byte)(0xC0 | 0x00); // 0xC0 = program change, 0x00 = channel 1
        event[1] = (byte)instrument;

        // Send the MIDI event to the synthesizer.
        midiDriver.write(event);

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        Log.d(this.getClass().getName(), "Motion event: " + event);

        if (v.getId() == R.id.buttonSustain && event.getAction() == MotionEvent.ACTION_UP) {
            // Stop any notes whose buttons are not held down.
            if (!buttonC.isPressed()) {
                stopNote(60, true);
            }
            if (!buttonCsharp.isPressed()) {
                stopNote(61, true);
            }
            if (!buttonD.isPressed()) {
                stopNote(62, true);
            }
            if (!buttonDsharp.isPressed()) {
                stopNote(63, true);
            }
            if (!buttonE.isPressed()) {
                stopNote(64, true);
            }
            if (!buttonF.isPressed()) {
                stopNote(65, true);
            }
            if (!buttonFsharp.isPressed()) {
                stopNote(66, true);
            }if (!buttonG.isPressed()) {
                stopNote(67, true);
            }
            if (!buttonGsharp.isPressed()) {
                stopNote(68, true);
            }
            if (!buttonA.isPressed()) {
                stopNote(69, true);
            }
            if (!buttonAsharp.isPressed()) {
                stopNote(70, true);
            }
            if (!buttonB.isPressed()) {
                stopNote(71, true);
            }
            if (!buttonC2.isPressed()) {
                stopNote(72, true);
            }
        }

        int noteNumber;

        switch (v.getId()) {
            case R.id.buttonC:
                noteNumber = 60;
                break;
            case R.id.buttonCsharp:
                noteNumber = 61;
                break;
            case R.id.buttonD:
                noteNumber = 62;
                break;
            case R.id.buttonDsharp:
                noteNumber = 63;
                break;
            case R.id.buttonE:
                noteNumber = 64;
                break;
            case R.id.buttonF:
                noteNumber = 65;
                break;
            case R.id.buttonFsharp:
                noteNumber = 66;
                break;
            case R.id.buttonG:
                noteNumber = 67;
                break;
            case R.id.buttonGsharp:
                noteNumber = 68;
                break;
            case R.id.buttonA:
                noteNumber = 69;
                break;
            case R.id.buttonAsharp:
                noteNumber = 70;
                break;
            case R.id.buttonB:
                noteNumber = 71;
                break;
            case R.id.buttonC2:
                noteNumber = 72;
                break;
            default:
                noteNumber = -1;
        }

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Log.d(this.getClass().getName(), "MotionEvent.ACTION_DOWN");
            playNote(noteNumber);
        }
        if (event.getAction() == MotionEvent.ACTION_UP) {
            Log.d(this.getClass().getName(), "MotionEvent.ACTION_UP");
            stopNote(noteNumber, false);
        }

        return false;
    }

    /**
     * <p>Callback method to be invoked when an item in this view has been
     * selected. This callback is invoked only when the newly selected
     * position is different from the previously selected position or if
     * there was no selected item.</p>
     * <p/>
     * Impelmenters can call getItemAtPosition(position) if they need to access the
     * data associated with the selected item.
     *
     * @param parent   The AdapterView where the selection happened
     * @param view     The view within the AdapterView that was clicked
     * @param position The position of the view in the adapter
     * @param id       The row id of the item that is selected
     */
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        selectInstrument(position);
    }

    /**
     * Callback method to be invoked when the selection disappears from this
     * view. The selection can disappear for instance when touch is activated
     * or when the adapter becomes empty.
     *
     * @param parent The AdapterView that now contains no selected item.
     */
    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.miditest.MainActivity"
    android:orientation="vertical"
    android:background="@android:color/darker_gray">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Sustain"
            android:id="@+id/buttonSustain" />

        <Spinner
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/spinnerInstruments"
            android:layout_gravity="right" />
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:enabled="false"
            android:background="@android:color/darker_gray"
            android:textColor="@color/background_material_light"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="C#"
            android:id="@+id/buttonCsharp"
            android:layout_weight="2"
            android:background="@color/background_material_dark"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="D#"
            android:id="@+id/buttonDsharp"
            android:layout_weight="2"
            android:background="@color/background_material_dark"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:enabled="false"
            android:background="@android:color/darker_gray"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="F#"
            android:id="@+id/buttonFsharp"
            android:layout_weight="2"
            android:background="@color/background_material_dark"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="G#"
            android:id="@+id/buttonGsharp"
            android:layout_weight="2"
            android:background="@color/background_material_dark"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="A#"
            android:id="@+id/buttonAsharp"
            android:layout_weight="2"
            android:background="@color/background_material_dark"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:enabled="false"
            android:background="@android:color/darker_gray"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp"
            android:layout_marginRight="8dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:enabled="false"
            android:background="@android:color/darker_gray"
            android:textColor="@color/background_material_light"
            android:layout_marginLeft="8dp" />

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="C"
            android:id="@+id/buttonC"
            android:layout_column="0"
            android:layout_row="0"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="D"
            android:id="@+id/buttonD"
            android:layout_row="0"
            android:layout_column="1"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="E"
            android:id="@+id/buttonE"
            android:layout_row="0"
            android:layout_column="2"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="F"
            android:id="@+id/buttonF"
            android:layout_row="0"
            android:layout_column="3"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="G"
            android:id="@+id/buttonG"
            android:layout_row="0"
            android:layout_column="4"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="A"
            android:id="@+id/buttonA"
            android:layout_row="0"
            android:layout_column="5"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="B"
            android:id="@+id/buttonB"
            android:layout_row="0"
            android:layout_column="6"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />

        <Button
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:text="C"
            android:id="@+id/buttonC2"
            android:layout_row="0"
            android:layout_column="7"
            android:layout_weight="1"
            android:textColor="@color/background_material_dark"
            android:background="@color/background_material_light"
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp" />
    </LinearLayout>

</LinearLayout>

miditest-GQ-QZQ\app\libs\MidiDriver-1.21.aar

通过网盘分享的文件:MidiDriver-1.21.aar
链接: https://pan.baidu.com/s/1a3wwy0H4OrKJdkTTKAsL9A 提取码: itkg

钢琴apk下载地址:
app-debug-miditest-GQ-QZQ.apk

https://download.csdn.net/download/qq_32257509/91866921

钢琴软件源代码下载地址:
miditest-GQ-QZQ.zip
https://download.csdn.net/download/qq_32257509/91866925

通过网盘分享的文件:app-debug-miditest-GQ-QZQ.apk
链接: https://pan.baidu.com/s/1pqS4GGRTYsplpgWOCv6XGw 提取码: n4fu

通过网盘分享的文件:miditest-GQ-QZQ.zip
链接: https://pan.baidu.com/s/1TRsiUFivW20du5e0axRZRw?pwd=yg4x 提取码: yg4x

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐