ReactOS 0.4.17-dev-934-g091855f
midi.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2024 Yuxuan Shui for CodeWeavers
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include "dmusic_midi.h"
20#include "dmime_private.h"
21#include "dmusic_band.h"
22#include "winternl.h"
23
25
26#ifdef WORDS_BIGENDIAN
27#define GET_BE_WORD(x) (x)
28#define GET_BE_DWORD(x) (x)
29#else
30#define GET_BE_WORD(x) RtlUshortByteSwap(x)
31#define GET_BE_DWORD(x) RtlUlongByteSwap(x)
32#endif
33
35{
38 union
39 {
40 struct
41 {
43 };
44 struct
45 {
48 };
49 };
50};
51
53{
54 struct list entry;
56};
57
59{
60 IDirectMusicTrack8 *seqtrack;
63 /* Track the initial note on event generated for a note that is currently on. NULL if the note is off. */
65
66 IDirectMusicTrack *chordtrack;
67 IDirectMusicTrack *bandtrack;
68 IDirectMusicTrack *tempotrack;
72};
73
75{
91};
92
94{
95 HRESULT hr;
96 ULONG read = 0;
97 if (size > *bytes_left) hr = IStream_Read(stream, buffer, *bytes_left, &read);
98 else hr = IStream_Read(stream, buffer, size, &read);
99 if (hr != S_OK) return hr;
100 *bytes_left -= read;
101 if (read < size) return S_FALSE;
102 return S_OK;
103}
104
106{
107 BYTE byte;
108 HRESULT hr = S_OK;
109
110 *out = 0;
111 do
112 {
113 hr = stream_read_at_most(stream, &byte, 1, bytes_left);
114 if (hr != S_OK) return hr;
115 *out = (*out << 7) | (byte & 0x7f);
116 } while (byte & 0x80);
117 return S_OK;
118}
119
120static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *last_status, ULONG *bytes_left)
121{
122 BYTE byte, status_type;
124 BYTE data[3];
126 HRESULT hr = S_OK;
127 DWORD delta_time;
128
129 if ((hr = read_variable_length_number(stream, &delta_time, bytes_left)) != S_OK) return hr;
130 event->delta_time = delta_time;
131
132 if ((hr = stream_read_at_most(stream, &byte, 1, bytes_left)) != S_OK) return hr;
133
134 if (byte & 0x80)
135 {
136 event->status = *last_status = byte;
137 if ((hr = stream_read_at_most(stream, &byte, 1, bytes_left)) != S_OK) return hr;
138 }
139 else event->status = *last_status;
140
141 if (event->status == MIDI_META)
142 {
143 event->meta_type = byte;
144
145 if ((hr = read_variable_length_number(stream, &length, bytes_left)) != S_OK) return hr;
146
147 switch (event->meta_type)
148 {
150 if (length != 3)
151 {
152 ERR("Invalid MIDI meta event length %lu for set tempo event.\n", length);
153 return E_FAIL;
154 }
155 if (FAILED(hr = stream_read_at_most(stream, data, 3, bytes_left))) return hr;
156 event->tempo = (data[0] << 16) | (data[1] << 8) | data[2];
157 break;
158 default:
159 if (*bytes_left < length) return S_FALSE;
160 offset.QuadPart = length;
161 if (FAILED(hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, NULL))) return hr;
162 FIXME("MIDI meta event type %#02x, length %lu, time +%lu. not supported\n",
163 event->meta_type, length, delta_time);
164 *bytes_left -= length;
165 event->tempo = 0;
166 }
167 TRACE("MIDI meta event type %#02x, length %lu, time +%lu\n", event->meta_type, length, delta_time);
168 return S_OK;
169 }
170 else if (event->status == MIDI_SYSEX1 || event->status == MIDI_SYSEX2)
171 {
172 if (byte & 0x80)
173 {
174 if ((hr = read_variable_length_number(stream, &length, bytes_left)) != S_OK) return hr;
175 length = length << 8 | (byte & 0x7f);
176 }
177 else length = byte;
178
179 if (*bytes_left < length) return S_FALSE;
180 offset.QuadPart = length;
181 if (FAILED(hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, NULL))) return hr;
182 *bytes_left -= length;
183 FIXME("MIDI sysex event type %#02x, length %lu, time +%lu. not supported\n", event->status,
184 length, delta_time);
185 return S_OK;
186 }
187
188 status_type = event->status & 0xf0;
189 event->data[0] = byte;
190 if (status_type != MIDI_PROGRAM_CHANGE && status_type != MIDI_CHANNEL_PRESSURE &&
191 (hr = stream_read_at_most(stream, &byte, 1, bytes_left)) != S_OK)
192 return hr;
193 event->data[1] = byte;
194 TRACE("MIDI event status %#02x, data: %#02x, %#02x, time +%lu\n", event->status, event->data[0],
195 event->data[1], delta_time);
196
197 return S_OK;
198}
199
201{
202 DMUS_TEMPO_PARAM tempo;
203 MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division;
204 HRESULT hr;
205
206 if (!parser->tempotrack && FAILED(hr = CoCreateInstance(&CLSID_DirectMusicTempoTrack, NULL, CLSCTX_INPROC_SERVER,
207 &IID_IDirectMusicTrack, (void **)&parser->tempotrack)))
208 return hr;
209
210 tempo.mtTime = dmusic_time;
211 tempo.dblTempo = 60 * 1000000.0 / event->tempo;
212 TRACE("Adding tempo at time %lu, tempo %f\n", dmusic_time, tempo.dblTempo);
213 return IDirectMusicTrack_SetParam(parser->tempotrack, &GUID_TempoParam, dmusic_time, &tempo);
214}
215
217{
218 HRESULT hr;
220 IDirectMusicBand *band;
221 DMUS_BAND_PARAM band_param;
222 MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division;
223 instrument.dwPChannel = event->status & 0xf;
225 instrument.dwPatch = event->data[0];
226 if (FAILED(hr = CoCreateInstance(&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER,
227 &IID_IDirectMusicBand, (void **)&band)))
228 return hr;
230
231 if (SUCCEEDED(hr))
232 {
233 TRACE("Adding band at time %lu\n", dmusic_time);
234 band_param.pBand = band;
235 band_param.mtTimePhysical = dmusic_time;
236 hr = IDirectMusicTrack_SetParam(parser->bandtrack, &GUID_BandParam, dmusic_time, &band_param);
237 }
238 else WARN("Failed to add instrument to band\n");
239
241 return hr;
242}
243
245{
246 BYTE new_velocity = (event->status & 0xf0) == MIDI_NOTE_OFF ? 0 : event->data[1]; /* DirectMusic doesn't have noteoff velocity */
247 BYTE note = event->data[0], channel = event->status & 0xf;
248 DWORD index = (DWORD)channel * 128 + note;
249 MUSIC_TIME dmusic_time;
250 struct midi_seqtrack_item *note_state = parser->note_states[index];
251 DMUS_IO_SEQ_ITEM *seq_item;
252 struct midi_seqtrack_item *item;
253
254 /* Testing shows there are 2 cases to deal with here:
255 *
256 * 1. Got note on when the note is already on, generate a NOTE event with
257 * new velocity and duration 1.
258 * 2. Got note on when the note is off, generate a NOTE event that lasts
259 * until the next note off event, intervening note on event doesn't matter.
260 */
261 if (new_velocity)
262 {
263 TRACE("Adding note event at time %lu, note %u, velocity %u\n", parser->time, note, new_velocity);
264
265 dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division;
266
267 item = calloc(1, sizeof(struct midi_seqtrack_item));
268 if (!item) return E_OUTOFMEMORY;
269
270 seq_item = &item->item;
271 seq_item->mtTime = dmusic_time;
272 seq_item->mtDuration = 1;
273 seq_item->dwPChannel = channel;
274 seq_item->bStatus = MIDI_NOTE_ON;
275 seq_item->bByte1 = note;
276 seq_item->bByte2 = new_velocity;
277 list_add_tail(&parser->seqtrack_items, &item->entry);
278 parser->seqtrack_items_count++;
279
280 if (!note_state) parser->note_states[index] = item;
281 }
282 else if (note_state)
283 {
284 note_state->item.mtDuration = (ULONGLONG)parser->time * DMUS_PPQ / parser->division -
285 note_state->item.mtTime;
286 if (note_state->item.mtDuration == 0) note_state->item.mtDuration = 1;
287
288 TRACE("Note off at time %lu, note %u, duration %ld\n", parser->time, note, note_state->item.mtDuration);
289
290 parser->note_states[index] = NULL;
291 }
292
293 return S_OK;
294}
295
297{
298 struct midi_seqtrack_item *item;
299 DMUS_IO_SEQ_ITEM *seq_item;
300 MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division;
301
302 if ((item = calloc(1, sizeof(struct midi_seqtrack_item))) == NULL) return E_OUTOFMEMORY;
303
304 seq_item = &item->item;
305 seq_item->mtTime = dmusic_time;
306 seq_item->mtDuration = 0;
307 seq_item->dwPChannel = event->status & 0xf;
308 seq_item->bStatus = event->status & 0xf0;
309 seq_item->bByte1 = event->data[0];
310 seq_item->bByte2 = event->data[1];
311 list_add_tail(&parser->seqtrack_items, &item->entry);
312 parser->seqtrack_items_count++;
313
314 return S_OK;
315}
316
317static int midi_seqtrack_item_compare(const void *a, const void *b)
318{
319 const DMUS_IO_SEQ_ITEM *item_a = a, *item_b = b;
320 return item_a->mtTime - item_b->mtTime;
321}
322
323static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment8 *segment)
324{
325 WORD i = 0;
326 HRESULT hr;
327 MUSIC_TIME music_length = 0;
328 DMUS_IO_SEQ_ITEM *seq_items = NULL;
329 struct midi_seqtrack_item *item;
330
331 TRACE("(%p, %p): semi-stub\n", parser, segment);
332
333 for (i = 0;; i++)
334 {
335 BYTE magic[4] = {0}, last_status = 0;
336 DWORD length_be;
338 ULONG read = 0;
339 struct midi_event event = {0};
340
341 TRACE("Start parsing track %u\n", i);
342 if ((hr = IStream_Read(parser->stream, magic, sizeof(magic), &read)) != S_OK) break;
343 if (read < sizeof(magic)) break;
344 if (memcmp(magic, "MTrk", 4) != 0) break;
345
346 if ((hr = IStream_Read(parser->stream, &length_be, sizeof(length_be), &read)) != S_OK)
347 break;
348 if (read < sizeof(length_be)) break;
349 length = GET_BE_DWORD(length_be);
350 TRACE("Track %u, length %lu bytes\n", i, length);
351
352 while ((hr = read_midi_event(parser->stream, &event, &last_status, &length)) == S_OK)
353 {
354 parser->time += event.delta_time;
355 if (event.status == 0xff && event.meta_type == MIDI_META_SET_TEMPO)
357 else
358 {
359 switch (event.status & 0xf0)
360 {
361 case MIDI_NOTE_ON:
362 case MIDI_NOTE_OFF:
364 break;
369 break;
372 break;
373 default:
374 FIXME("Unhandled MIDI event type %#02x at time +%lu\n", event.status, parser->time);
375 break;
376 }
377 }
378 if (FAILED(hr)) break;
379 }
380
381 if (FAILED(hr)) break;
382
383 TRACE("End of track %u\n", i);
384 if (parser->time > music_length) music_length = parser->time;
385 parser->time = 0;
386 memset(parser->note_states, 0, sizeof(parser->note_states));
387 }
388 if (FAILED(hr)) return hr;
389
390 TRACE("End of file\n");
391
392 if ((seq_items = calloc(parser->seqtrack_items_count, sizeof(DMUS_IO_SEQ_ITEM))) == NULL)
393 return E_OUTOFMEMORY;
394
395 i = 0;
396 LIST_FOR_EACH_ENTRY(item, &parser->seqtrack_items, struct midi_seqtrack_item, entry)
397 seq_items[i++] = item->item;
398 sequence_track_set_items(parser->seqtrack, seq_items, parser->seqtrack_items_count);
399 qsort(seq_items, parser->seqtrack_items_count, sizeof(DMUS_IO_SEQ_ITEM), midi_seqtrack_item_compare);
400
401 music_length = (ULONGLONG)music_length * DMUS_PPQ / parser->division + 1;
403 if (SUCCEEDED(hr)) hr = IDirectMusicSegment8_InsertTrack(segment, parser->bandtrack, 0xffff);
404 if (SUCCEEDED(hr)) hr = IDirectMusicSegment8_InsertTrack(segment, parser->chordtrack, 0xffff);
405 if (SUCCEEDED(hr) && parser->tempotrack)
406 hr = IDirectMusicSegment8_InsertTrack(segment, parser->tempotrack, 0xffff);
407 if (SUCCEEDED(hr))
408 hr = IDirectMusicSegment8_InsertTrack(segment, (IDirectMusicTrack *)parser->seqtrack, 0xffff);
409
410 return hr;
411}
412
414{
415 struct midi_seqtrack_item *item, *next_item;
416 IStream_Release(parser->stream);
417 if (parser->bandtrack) IDirectMusicTrack_Release(parser->bandtrack);
418 if (parser->chordtrack) IDirectMusicTrack_Release(parser->chordtrack);
419 if (parser->tempotrack) IDirectMusicTrack_Release(parser->tempotrack);
420 if (parser->seqtrack) IDirectMusicTrack_Release(parser->seqtrack);
421 LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &parser->seqtrack_items, struct midi_seqtrack_item, entry)
422 {
423 list_remove(&item->entry);
424 free(item);
425 }
426 free(parser);
427}
428
429static HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser)
430{
433 HRESULT hr;
434 WORD format, number_of_tracks, division;
435 struct midi_parser *parser;
436
437 *out_parser = NULL;
438
439 /* Skip over the 'MThd' magic number. */
440 offset.QuadPart = 4;
441 if (FAILED(hr = IStream_Seek(stream, offset, STREAM_SEEK_SET, NULL))) return hr;
442
443 if (FAILED(hr = IStream_Read(stream, &length, sizeof(length), NULL))) return hr;
445
446 if (FAILED(hr = IStream_Read(stream, &format, sizeof(format), NULL))) return hr;
448
449 if (FAILED(hr = IStream_Read(stream, &number_of_tracks, sizeof(number_of_tracks), NULL)))
450 return hr;
451
452 number_of_tracks = GET_BE_WORD(number_of_tracks);
453 if (FAILED(hr = IStream_Read(stream, &division, sizeof(division), NULL))) return hr;
455 if (division & 0x8000)
456 {
457 WARN("SMPTE time division not implemented yet\n");
459 }
460
461 TRACE("MIDI format %u, %u tracks, division %u\n", format, number_of_tracks, division);
462
463 parser = calloc(1, sizeof(struct midi_parser));
464 if (!parser) return E_OUTOFMEMORY;
465 list_init(&parser->seqtrack_items);
466 IStream_AddRef(stream);
467 parser->stream = stream;
468 parser->division = division;
469 hr = CoCreateInstance(&CLSID_DirectMusicBandTrack, NULL, CLSCTX_INPROC_SERVER,
470 &IID_IDirectMusicTrack, (void **)&parser->bandtrack);
471 if (SUCCEEDED(hr))
472 hr = CoCreateInstance(&CLSID_DirectMusicChordTrack, NULL, CLSCTX_INPROC_SERVER,
473 &IID_IDirectMusicTrack, (void **)&parser->chordtrack);
474 if (SUCCEEDED(hr))
475 hr = CoCreateInstance(&CLSID_DirectMusicSeqTrack, NULL, CLSCTX_INPROC_SERVER,
476 &IID_IDirectMusicTrack, (void **)&parser->seqtrack);
477
479 else *out_parser = parser;
480 return hr;
481}
482
483HRESULT parse_midi(IStream *stream, IDirectMusicSegment8 *segment)
484{
485 struct midi_parser *parser;
486 HRESULT hr;
487
488 if (FAILED(hr = midi_parser_new(stream, &parser))) return hr;
491 return hr;
492}
#define read
Definition: acwin.h:97
HRESULT band_add_instrument(IDirectMusicBand *iface, DMUS_IO_INSTRUMENT *instrument)
Definition: band.c:531
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
int note(char *format,...)
Definition: util.c:12
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
#define MIDI_CONTROL_CHANGE
Definition: beepmidi.c:63
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
Definition: list.h:39
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
static HRESULT midi_parser_handle_set_tempo(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:200
static HRESULT midi_parser_handle_note_on_off(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:244
static HRESULT stream_read_at_most(IStream *stream, void *buffer, ULONG size, ULONG *bytes_left)
Definition: midi.c:93
static void midi_parser_destroy(struct midi_parser *parser)
Definition: midi.c:413
static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *last_status, ULONG *bytes_left)
Definition: midi.c:120
static HRESULT read_variable_length_number(IStream *stream, DWORD *out, ULONG *bytes_left)
Definition: midi.c:105
static HRESULT midi_parser_handle_program_change(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:216
HRESULT parse_midi(IStream *stream, IDirectMusicSegment8 *segment)
Definition: midi.c:483
static HRESULT midi_parser_handle_control(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:296
static HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser)
Definition: midi.c:429
#define GET_BE_WORD(x)
Definition: midi.c:30
#define GET_BE_DWORD(x)
Definition: midi.c:31
static int midi_seqtrack_item_compare(const void *a, const void *b)
Definition: midi.c:317
static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment8 *segment)
Definition: midi.c:323
meta_event_type
Definition: midi.c:75
@ MIDI_META_TEXT_EVENT
Definition: midi.c:77
@ MIDI_META_END_OF_TRACK
Definition: midi.c:85
@ MIDI_META_LYRIC
Definition: midi.c:81
@ MIDI_META_INSTRUMENT_NAME
Definition: midi.c:80
@ MIDI_META_TIME_SIGNATURE
Definition: midi.c:88
@ MIDI_META_CHANNEL_PREFIX_ASSIGNMENT
Definition: midi.c:84
@ MIDI_META_SET_TEMPO
Definition: midi.c:86
@ MIDI_META_TRACK_NAME
Definition: midi.c:79
@ MIDI_META_KEY_SIGNATURE
Definition: midi.c:89
@ MIDI_META_SEQUENCE_NUMBER
Definition: midi.c:76
@ MIDI_META_COPYRIGHT_NOTICE
Definition: midi.c:78
@ MIDI_META_MARKER
Definition: midi.c:82
@ MIDI_META_CUE_POINT
Definition: midi.c:83
@ MIDI_META_SEQUENCER_SPECIFIC
Definition: midi.c:90
@ MIDI_META_SMPTE_OFFSET
Definition: midi.c:87
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
#define byte(x, n)
Definition: tomcrypt.h:118
#define DMUS_E_UNSUPPORTED_STREAM
Definition: dmerror.h:100
void sequence_track_set_items(IDirectMusicTrack8 *track, DMUS_IO_SEQ_ITEM *items, unsigned int count)
Definition: seqtrack.c:507
#define IDirectMusicTrack_SetParam(p, a, b, c)
Definition: dmplugin.h:233
#define IDirectMusicTrack_Release(p)
Definition: dmplugin.h:226
LONG MUSIC_TIME
Definition: dmplugin.h:95
@ MIDI_PITCH_BEND_CHANGE
Definition: dmusic_midi.h:33
@ MIDI_SYSEX2
Definition: dmusic_midi.h:35
@ MIDI_SYSEX1
Definition: dmusic_midi.h:34
@ MIDI_META
Definition: dmusic_midi.h:37
#define DMUS_IO_INST_PATCH
Definition: dmusicf.h:237
#define DMUS_PPQ
Definition: dmusici.h:314
#define IDirectMusicSegment8_SetLength(p, a)
Definition: dmusici.h:1086
#define IDirectMusicBand_Release(p)
Definition: dmusici.h:815
#define IDirectMusicSegment8_InsertTrack(p, a, b)
Definition: dmusici.h:1093
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLuint index
Definition: glext.h:6031
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define MIDI_PROGRAM_CHANGE
Definition: midi.h:20
#define MIDI_CHANNEL_PRESSURE
Definition: midi.h:21
#define calloc
Definition: rosglue.h:14
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:236
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:242
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
MUSIC_TIME mtTimePhysical
Definition: dmusici.h:783
struct IDirectMusicBand * pBand
Definition: dmusici.h:784
DWORD dwPChannel
Definition: dmusicf.h:434
MUSIC_TIME mtTime
Definition: dmusicf.h:432
MUSIC_TIME mtDuration
Definition: dmusicf.h:433
double dblTempo
Definition: dmusicf.h:477
MUSIC_TIME mtTime
Definition: dmusicf.h:476
Definition: band.c:76
Definition: filter.c:185
BYTE meta_type
Definition: midi.c:46
BYTE status
Definition: midi.c:37
ULONG tempo
Definition: midi.c:47
MUSIC_TIME delta_time
Definition: midi.c:36
struct list seqtrack_items
Definition: midi.c:62
DWORD division
Definition: midi.c:71
struct midi_seqtrack_item * note_states[128 *16]
Definition: midi.c:64
IDirectMusicTrack * tempotrack
Definition: midi.c:68
IStream * stream
Definition: midi.c:70
ULONG seqtrack_items_count
Definition: midi.c:61
IDirectMusicTrack * chordtrack
Definition: midi.c:66
MUSIC_TIME time
Definition: midi.c:69
IDirectMusicTrack * bandtrack
Definition: midi.c:67
IDirectMusicTrack8 * seqtrack
Definition: midi.c:60
struct list entry
Definition: midi.c:54
DMUS_IO_SEQ_ITEM item
Definition: midi.c:55
Definition: import.c:81
Definition: parse.h:23
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG
Definition: typedefs.h:59
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define S_FALSE
Definition: winerror.h:3451
unsigned char BYTE
Definition: xxhash.c:193