Home | History | Annotate | Download | only in midi
      1 /*
      2  * Copyright (C) 2014 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.android.internal.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          * Store these bytes in the EventScheduler to be delivered at the specified
     36          * time.
     37          */
     38         @Override
     39         public void onSend(byte[] msg, int offset, int count, long timestamp)
     40                 throws IOException {
     41             MidiEvent event = createScheduledEvent(msg, offset, count, timestamp);
     42             if (event != null) {
     43                 add(event);
     44             }
     45         }
     46 
     47         @Override
     48         public void onFlush() {
     49             MidiEventScheduler.this.flush();
     50         }
     51     }
     52 
     53     public static class MidiEvent extends SchedulableEvent {
     54         public int count = 0;
     55         public byte[] data;
     56 
     57         private MidiEvent(int count) {
     58             super(0);
     59             data = new byte[count];
     60         }
     61 
     62         private MidiEvent(byte[] msg, int offset, int count, long timestamp) {
     63             super(timestamp);
     64             data = new byte[count];
     65             System.arraycopy(msg, offset, data, 0, count);
     66             this.count = count;
     67         }
     68 
     69         @Override
     70         public String toString() {
     71             String text = "Event: ";
     72             for (int i = 0; i < count; i++) {
     73                 text += data[i] + ", ";
     74             }
     75             return text;
     76         }
     77     }
     78 
     79     /**
     80      * Create an event that contains the message.
     81      */
     82     private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
     83             long timestamp) {
     84         MidiEvent event;
     85         if (count > POOL_EVENT_SIZE) {
     86             event = new MidiEvent(msg, offset, count, timestamp);
     87         } else {
     88             event = (MidiEvent) removeEventfromPool();
     89             if (event == null) {
     90                 event = new MidiEvent(POOL_EVENT_SIZE);
     91             }
     92             System.arraycopy(msg, offset, event.data, 0, count);
     93             event.count = count;
     94             event.setTimestamp(timestamp);
     95         }
     96         return event;
     97     }
     98 
     99     /**
    100      * Return events to a pool so they can be reused.
    101      *
    102      * @param event
    103      */
    104     @Override
    105     public void addEventToPool(SchedulableEvent event) {
    106         // Make sure the event is suitable for the pool.
    107         if (event instanceof MidiEvent) {
    108             MidiEvent midiEvent = (MidiEvent) event;
    109             if (midiEvent.data.length == POOL_EVENT_SIZE) {
    110                 super.addEventToPool(event);
    111             }
    112         }
    113     }
    114 
    115     /**
    116      * This MidiReceiver will write date to the scheduling buffer.
    117      * @return the MidiReceiver
    118      */
    119     public MidiReceiver getReceiver() {
    120         return mReceiver;
    121     }
    122 
    123 }
    124