00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "midi.h"
00012
00013
00014
00015 namespace media
00016 {
00017
00018
00019
00020
00021
00022 const static int s_DataSize[8] = {
00023 2,
00024 2,
00025 2,
00026 2,
00027 1,
00028 1,
00029 3,
00030 0,
00031 };
00032
00033
00034 static const char * s_EventName[8] = {
00035 "Note Off",
00036 "Note On",
00037 "Note Aftertouch",
00038 "Control Change",
00039 "Program Change",
00040 "Channel Aftertouch",
00041 "Pitch",
00042 "System Exclusive"
00043 };
00044
00045
00046 static const char * s_DataName[8][2] = {
00047 { "Note Number", "Velocity" },
00048 { "Note Number", "Velocity" },
00049 { "Note Number", "Pressure" },
00050 { "Control Number", "Control Value" },
00051 { "Patch", NULL },
00052 { "Pressure Value", NULL },
00053 { "Pitch Bend", NULL },
00054 { NULL, NULL }
00055 };
00056
00057
00058
00059
00060
00061
00062 class MidiEventImpl : public MidiEvent {
00063 public:
00064 void SetStatus(IN byte_t status) throw()
00065 { m_status = status; }
00066 void SetData(IN int index, IN byte_t value) throw()
00067 { m_data[index] = value; }
00068 };
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 bool
00079 MidiEvent::IsValidStatus
00080 (
00081 IN eStatus status
00082 )
00083 throw()
00084 {
00085 switch (status) {
00086 case eNoteOn:
00087 case eNoteOff:
00088 case eNoteAfter:
00089 case eControl:
00090 case eProgram:
00091 case eChannelAfter:
00092 case ePitch:
00093 case eSystem:
00094 return true;
00095
00096 default:
00097 return false;
00098 }
00099 }
00100
00101
00102 int
00103 MidiEvent::GetDataByteCount
00104 (
00105 IN eStatus status
00106 )
00107 throw()
00108 {
00109 int retval;
00110
00111 ASSERT(IsValidStatus(status), "Invalid status");
00112
00113 retval = s_DataSize[status - 8];
00114 if (3 == retval)
00115 retval = 2;
00116
00117 return retval;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 void
00129 ParseMidi
00130 (
00131 IN MidiReceiver * receiver,
00132 IN const byte_t * buffer,
00133 IN long bytes,
00134 OUT long * offset
00135 )
00136 {
00137 MidiEventImpl event;
00138 int count = 0;
00139
00140 ASSERT(receiver, "NULL receiver");
00141 ASSERT(buffer, "NULL buffer");
00142 ASSERT(bytes > 0, "invalid byte count");
00143 ASSERT(offset, "NULL offset pointer");
00144 *offset = 0;
00145
00146 for (;;) {
00147
00148 while (*buffer < 0x80 && bytes > 0) {
00149 DPRINTF("Skipping non-status byte: 0x%02x",
00150 (int) *buffer);
00151 buffer++;
00152 bytes--;
00153 }
00154
00155
00156 if (bytes <= 0) {
00157 ASSERT(0 == bytes, "Invalid remainder");
00158 break;
00159 }
00160
00161
00162 count = *(buffer);
00163 count = (count >> 4) & 0xf;
00164 ASSERT(count >= 8, "Invalid count?");
00165
00166 count -= 8;
00167 ASSERT(count >= 0 && count < 8, "Invalid status?");
00168 count = s_DataSize[count];
00169
00170
00171
00172 if (count >= bytes) {
00173
00174
00175 *offset = bytes;
00176 break;
00177 }
00178
00179
00180 event.SetStatus(*buffer);
00181 buffer++;
00182 bytes--;
00183
00184 if (0 == count) {
00185 DPRINTF("SYSTEM EXCLUSIVE!! Ignoring status = 0x%02x",
00186 event.GetStatus());
00187 continue;
00188 }
00189
00190
00191 if (count > 0) {
00192 event.SetData(0, *buffer);
00193 buffer++;
00194 bytes--;
00195 }
00196
00197
00198 if (count > 1) {
00199 event.SetData(1, *buffer);
00200 buffer++;
00201 bytes--;
00202 }
00203
00204
00205 receiver->NotifyEvent(event);
00206 }
00207 }
00208
00209
00210
00211 void
00212 PrintEvent
00213 (
00214 IN FILE * output,
00215 IN const MidiEvent& event
00216 )
00217 throw()
00218 {
00219 int index;
00220 int count;
00221
00222 ASSERT(output, "NULL output stream");
00223
00224 index = event.GetStatus() - 0x8;
00225 if (index < 0 || index > 7) {
00226 DPRINTF("Invalid status?");
00227 return;
00228 }
00229
00230 fprintf(output, "Event: %s\n", s_EventName[index]);
00231 fprintf(output, " Channel: %d\n", (int) event.GetChannel());
00232
00233 count = s_DataSize[index];
00234 if (1 == count || 2 == count) {
00235 fprintf(output, " %s: %d\n", s_DataName[index][0],
00236 (int) event.GetNote());
00237 }
00238
00239 if (2 == count) {
00240 fprintf(output, " %s: %d\n", s_DataName[index][1],
00241 (int) event.GetVelocity());
00242 }
00243
00244 if (3 == count) {
00245 fprintf(output, " %s: %d\n", s_DataName[index][0],
00246 (int) event.GetPitch());
00247 }
00248 }
00249
00250
00251
00252 };