Home | History | Annotate | Download | only in com.example.android.common.midi
      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
     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 
     53         private MidiEvent(int count) {
     54             super(0);
     55             data = new byte[count];
     56         }
     57 
     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
     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      */
     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
    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      */
    115     public MidiReceiver getReceiver() {
    116         return mReceiver;
    117     }
    118 
    119 }
    120