2
2
3
3
import android .support .annotation .NonNull ;
4
4
5
+ import java .io .ByteArrayOutputStream ;
6
+ import java .io .IOException ;
7
+
5
8
/**
6
9
* Represents BLE MIDI Output Device
7
10
*
@@ -11,6 +14,8 @@ public abstract class MidiOutputDevice {
11
14
12
15
public static final int MAX_TIMESTAMP = 8192 ;
13
16
17
+ final ByteArrayOutputStream transferDataStream = new ByteArrayOutputStream ();
18
+
14
19
/**
15
20
* Transfer data
16
21
*
@@ -40,16 +45,67 @@ public final String toString() {
40
45
return getDeviceName ();
41
46
}
42
47
48
+ volatile boolean transferDataThreadAlive ;
49
+ final Thread transferDataThread = new Thread (new Runnable () {
50
+ @ Override
51
+ public void run () {
52
+ transferDataThreadAlive = true ;
53
+
54
+ while (transferDataThreadAlive ) {
55
+ synchronized (transferDataStream ) {
56
+ if (writtenDataCount > 0 ) {
57
+ transferData (transferDataStream .toByteArray ());
58
+ transferDataStream .reset ();
59
+ writtenDataCount = 0 ;
60
+ }
61
+ }
62
+
63
+ try {
64
+ Thread .sleep (10 );
65
+ } catch (InterruptedException ignored ) {
66
+ }
67
+ }
68
+ }
69
+ });
70
+
71
+ protected MidiOutputDevice () {
72
+ transferDataThread .start ();
73
+ }
74
+
75
+ /**
76
+ * Stops transfer thread
77
+ */
78
+ public void stop () {
79
+ transferDataThreadAlive = false ;
80
+ }
81
+
82
+ transient int writtenDataCount ;
83
+ private void storeTransferData (byte [] data ) {
84
+ synchronized (transferDataStream ) {
85
+ long timestamp = System .currentTimeMillis () % MAX_TIMESTAMP ;
86
+ if (writtenDataCount == 0 ) {
87
+ // Store timestamp high
88
+ transferDataStream .write ((byte ) (0x80 | ((timestamp >> 7 ) & 0x3f )));
89
+ writtenDataCount ++;
90
+ }
91
+ // timestamp low
92
+ transferDataStream .write ((byte ) (0x80 | (timestamp & 0x7f )));
93
+ writtenDataCount ++;
94
+ try {
95
+ transferDataStream .write (data );
96
+ writtenDataCount += data .length ;
97
+ } catch (IOException ignored ) {
98
+ }
99
+ }
100
+ }
101
+
43
102
/**
44
103
* Sends MIDI message to output device.
45
104
*
46
105
* @param byte1 the first byte
47
106
*/
48
107
private void sendMidiMessage (int byte1 ) {
49
- long timestamp = System .currentTimeMillis () % MAX_TIMESTAMP ;
50
- byte [] writeBuffer = new byte [] { (byte ) (0x80 | ((timestamp >> 7 ) & 0x3f )), (byte ) (0x80 | (timestamp & 0x7f )), (byte ) byte1 };
51
-
52
- transferData (writeBuffer );
108
+ storeTransferData (new byte [] { (byte ) byte1 });
53
109
}
54
110
55
111
/**
@@ -59,15 +115,7 @@ private void sendMidiMessage(int byte1) {
59
115
* @param byte2 the second byte
60
116
*/
61
117
private void sendMidiMessage (int byte1 , int byte2 ) {
62
- byte [] writeBuffer = new byte [4 ];
63
- long timestamp = System .currentTimeMillis () % MAX_TIMESTAMP ;
64
-
65
- writeBuffer [0 ] = (byte ) (0x80 | ((timestamp >> 7 ) & 0x3f ));
66
- writeBuffer [1 ] = (byte ) (0x80 | (timestamp & 0x7f ));
67
- writeBuffer [2 ] = (byte ) byte1 ;
68
- writeBuffer [3 ] = (byte ) byte2 ;
69
-
70
- transferData (writeBuffer );
118
+ storeTransferData (new byte [] { (byte ) byte1 , (byte ) byte2 });
71
119
}
72
120
73
121
/**
@@ -78,16 +126,7 @@ private void sendMidiMessage(int byte1, int byte2) {
78
126
* @param byte3 the third byte
79
127
*/
80
128
private void sendMidiMessage (int byte1 , int byte2 , int byte3 ) {
81
- byte [] writeBuffer = new byte [5 ];
82
- long timestamp = System .currentTimeMillis () % MAX_TIMESTAMP ;
83
-
84
- writeBuffer [0 ] = (byte ) (0x80 | ((timestamp >> 7 ) & 0x3f ));
85
- writeBuffer [1 ] = (byte ) (0x80 | (timestamp & 0x7f ));
86
- writeBuffer [2 ] = (byte ) byte1 ;
87
- writeBuffer [3 ] = (byte ) byte2 ;
88
- writeBuffer [4 ] = (byte ) byte3 ;
89
-
90
- transferData (writeBuffer );
129
+ storeTransferData (new byte [] { (byte ) byte1 , (byte ) byte2 , (byte ) byte3 });
91
130
}
92
131
93
132
/**
@@ -124,6 +163,7 @@ public final void sendMidiSystemExclusive(@NonNull byte[] systemExclusive) {
124
163
// timestamp MSB
125
164
writeBuffer [0 ] = (byte ) (0x80 | ((timestamp >> 7 ) & 0x3f ));
126
165
166
+ // immediately transfer data
127
167
transferData (writeBuffer );
128
168
129
169
timestamp = System .currentTimeMillis () % MAX_TIMESTAMP ;
0 commit comments