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