1*90c8c64dSAndroid Build Coastguard Worker /* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker 17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.common.midi; 18*90c8c64dSAndroid Build Coastguard Worker 19*90c8c64dSAndroid Build Coastguard Worker import android.media.midi.MidiReceiver; 20*90c8c64dSAndroid Build Coastguard Worker 21*90c8c64dSAndroid Build Coastguard Worker import java.io.IOException; 22*90c8c64dSAndroid Build Coastguard Worker 23*90c8c64dSAndroid Build Coastguard Worker /** 24*90c8c64dSAndroid Build Coastguard Worker * Add MIDI Events to an EventScheduler 25*90c8c64dSAndroid Build Coastguard Worker */ 26*90c8c64dSAndroid Build Coastguard Worker public class MidiEventScheduler extends EventScheduler { 27*90c8c64dSAndroid Build Coastguard Worker private static final String TAG = "MidiEventScheduler"; 28*90c8c64dSAndroid Build Coastguard Worker // Maintain a pool of scheduled events to reduce memory allocation. 29*90c8c64dSAndroid Build Coastguard Worker // This pool increases performance by about 14%. 30*90c8c64dSAndroid Build Coastguard Worker private final static int POOL_EVENT_SIZE = 16; 31*90c8c64dSAndroid Build Coastguard Worker private MidiReceiver mReceiver = new SchedulingReceiver(); 32*90c8c64dSAndroid Build Coastguard Worker 33*90c8c64dSAndroid Build Coastguard Worker private class SchedulingReceiver extends MidiReceiver 34*90c8c64dSAndroid Build Coastguard Worker { 35*90c8c64dSAndroid Build Coastguard Worker /** 36*90c8c64dSAndroid Build Coastguard Worker * Store these bytes in the EventScheduler to be delivered at the specified 37*90c8c64dSAndroid Build Coastguard Worker * time. 38*90c8c64dSAndroid Build Coastguard Worker */ 39*90c8c64dSAndroid Build Coastguard Worker @Override onSend(byte[] msg, int offset, int count, long timestamp)40*90c8c64dSAndroid Build Coastguard Worker public void onSend(byte[] msg, int offset, int count, long timestamp) 41*90c8c64dSAndroid Build Coastguard Worker throws IOException { 42*90c8c64dSAndroid Build Coastguard Worker MidiEvent event = createScheduledEvent(msg, offset, count, timestamp); 43*90c8c64dSAndroid Build Coastguard Worker if (event != null) { 44*90c8c64dSAndroid Build Coastguard Worker add(event); 45*90c8c64dSAndroid Build Coastguard Worker } 46*90c8c64dSAndroid Build Coastguard Worker } 47*90c8c64dSAndroid Build Coastguard Worker } 48*90c8c64dSAndroid Build Coastguard Worker 49*90c8c64dSAndroid Build Coastguard Worker public static class MidiEvent extends SchedulableEvent { 50*90c8c64dSAndroid Build Coastguard Worker public int count = 0; 51*90c8c64dSAndroid Build Coastguard Worker public byte[] data; 52*90c8c64dSAndroid Build Coastguard Worker MidiEvent(int count)53*90c8c64dSAndroid Build Coastguard Worker private MidiEvent(int count) { 54*90c8c64dSAndroid Build Coastguard Worker super(0); 55*90c8c64dSAndroid Build Coastguard Worker data = new byte[count]; 56*90c8c64dSAndroid Build Coastguard Worker } 57*90c8c64dSAndroid Build Coastguard Worker MidiEvent(byte[] msg, int offset, int count, long timestamp)58*90c8c64dSAndroid Build Coastguard Worker private MidiEvent(byte[] msg, int offset, int count, long timestamp) { 59*90c8c64dSAndroid Build Coastguard Worker super(timestamp); 60*90c8c64dSAndroid Build Coastguard Worker data = new byte[count]; 61*90c8c64dSAndroid Build Coastguard Worker System.arraycopy(msg, offset, data, 0, count); 62*90c8c64dSAndroid Build Coastguard Worker this.count = count; 63*90c8c64dSAndroid Build Coastguard Worker } 64*90c8c64dSAndroid Build Coastguard Worker 65*90c8c64dSAndroid Build Coastguard Worker @Override toString()66*90c8c64dSAndroid Build Coastguard Worker public String toString() { 67*90c8c64dSAndroid Build Coastguard Worker String text = "Event: "; 68*90c8c64dSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) { 69*90c8c64dSAndroid Build Coastguard Worker text += data[i] + ", "; 70*90c8c64dSAndroid Build Coastguard Worker } 71*90c8c64dSAndroid Build Coastguard Worker return text; 72*90c8c64dSAndroid Build Coastguard Worker } 73*90c8c64dSAndroid Build Coastguard Worker } 74*90c8c64dSAndroid Build Coastguard Worker 75*90c8c64dSAndroid Build Coastguard Worker /** 76*90c8c64dSAndroid Build Coastguard Worker * Create an event that contains the message. 77*90c8c64dSAndroid Build Coastguard Worker */ createScheduledEvent(byte[] msg, int offset, int count, long timestamp)78*90c8c64dSAndroid Build Coastguard Worker private MidiEvent createScheduledEvent(byte[] msg, int offset, int count, 79*90c8c64dSAndroid Build Coastguard Worker long timestamp) { 80*90c8c64dSAndroid Build Coastguard Worker MidiEvent event; 81*90c8c64dSAndroid Build Coastguard Worker if (count > POOL_EVENT_SIZE) { 82*90c8c64dSAndroid Build Coastguard Worker event = new MidiEvent(msg, offset, count, timestamp); 83*90c8c64dSAndroid Build Coastguard Worker } else { 84*90c8c64dSAndroid Build Coastguard Worker event = (MidiEvent) removeEventfromPool(); 85*90c8c64dSAndroid Build Coastguard Worker if (event == null) { 86*90c8c64dSAndroid Build Coastguard Worker event = new MidiEvent(POOL_EVENT_SIZE); 87*90c8c64dSAndroid Build Coastguard Worker } 88*90c8c64dSAndroid Build Coastguard Worker System.arraycopy(msg, offset, event.data, 0, count); 89*90c8c64dSAndroid Build Coastguard Worker event.count = count; 90*90c8c64dSAndroid Build Coastguard Worker event.setTimestamp(timestamp); 91*90c8c64dSAndroid Build Coastguard Worker } 92*90c8c64dSAndroid Build Coastguard Worker return event; 93*90c8c64dSAndroid Build Coastguard Worker } 94*90c8c64dSAndroid Build Coastguard Worker 95*90c8c64dSAndroid Build Coastguard Worker /** 96*90c8c64dSAndroid Build Coastguard Worker * Return events to a pool so they can be reused. 97*90c8c64dSAndroid Build Coastguard Worker * 98*90c8c64dSAndroid Build Coastguard Worker * @param event 99*90c8c64dSAndroid Build Coastguard Worker */ 100*90c8c64dSAndroid Build Coastguard Worker @Override addEventToPool(SchedulableEvent event)101*90c8c64dSAndroid Build Coastguard Worker public void addEventToPool(SchedulableEvent event) { 102*90c8c64dSAndroid Build Coastguard Worker // Make sure the event is suitable for the pool. 103*90c8c64dSAndroid Build Coastguard Worker if (event instanceof MidiEvent) { 104*90c8c64dSAndroid Build Coastguard Worker MidiEvent midiEvent = (MidiEvent) event; 105*90c8c64dSAndroid Build Coastguard Worker if (midiEvent.data.length == POOL_EVENT_SIZE) { 106*90c8c64dSAndroid Build Coastguard Worker super.addEventToPool(event); 107*90c8c64dSAndroid Build Coastguard Worker } 108*90c8c64dSAndroid Build Coastguard Worker } 109*90c8c64dSAndroid Build Coastguard Worker } 110*90c8c64dSAndroid Build Coastguard Worker 111*90c8c64dSAndroid Build Coastguard Worker /** 112*90c8c64dSAndroid Build Coastguard Worker * This MidiReceiver will write date to the scheduling buffer. 113*90c8c64dSAndroid Build Coastguard Worker * @return the MidiReceiver 114*90c8c64dSAndroid Build Coastguard Worker */ getReceiver()115*90c8c64dSAndroid Build Coastguard Worker public MidiReceiver getReceiver() { 116*90c8c64dSAndroid Build Coastguard Worker return mReceiver; 117*90c8c64dSAndroid Build Coastguard Worker } 118*90c8c64dSAndroid Build Coastguard Worker 119*90c8c64dSAndroid Build Coastguard Worker } 120