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