ReactOS 0.4.17-dev-934-g091855f
midi.c File Reference
#include "dmusic_midi.h"
#include "dmime_private.h"
#include "dmusic_band.h"
#include "winternl.h"
Include dependency graph for midi.c:

Go to the source code of this file.

Classes

struct  midi_event
 
struct  midi_seqtrack_item
 
struct  midi_parser
 

Macros

#define GET_BE_WORD(x)   RtlUshortByteSwap(x)
 
#define GET_BE_DWORD(x)   RtlUlongByteSwap(x)
 

Enumerations

enum  meta_event_type {
  MIDI_META_SEQUENCE_NUMBER = 0x00 , MIDI_META_TEXT_EVENT = 0x01 , MIDI_META_COPYRIGHT_NOTICE = 0x02 , MIDI_META_TRACK_NAME = 0x03 ,
  MIDI_META_INSTRUMENT_NAME = 0x04 , MIDI_META_LYRIC = 0x05 , MIDI_META_MARKER = 0x06 , MIDI_META_CUE_POINT = 0x07 ,
  MIDI_META_CHANNEL_PREFIX_ASSIGNMENT = 0x20 , MIDI_META_END_OF_TRACK = 0x2f , MIDI_META_SET_TEMPO = 0x51 , MIDI_META_SMPTE_OFFSET = 0x54 ,
  MIDI_META_TIME_SIGNATURE = 0x58 , MIDI_META_KEY_SIGNATURE = 0x59 , MIDI_META_SEQUENCER_SPECIFIC = 0x7f
}
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (dmime)
 
static HRESULT stream_read_at_most (IStream *stream, void *buffer, ULONG size, ULONG *bytes_left)
 
static HRESULT read_variable_length_number (IStream *stream, DWORD *out, ULONG *bytes_left)
 
static HRESULT read_midi_event (IStream *stream, struct midi_event *event, BYTE *last_status, ULONG *bytes_left)
 
static HRESULT midi_parser_handle_set_tempo (struct midi_parser *parser, struct midi_event *event)
 
static HRESULT midi_parser_handle_program_change (struct midi_parser *parser, struct midi_event *event)
 
static HRESULT midi_parser_handle_note_on_off (struct midi_parser *parser, struct midi_event *event)
 
static HRESULT midi_parser_handle_control (struct midi_parser *parser, struct midi_event *event)
 
static int midi_seqtrack_item_compare (const void *a, const void *b)
 
static HRESULT midi_parser_parse (struct midi_parser *parser, IDirectMusicSegment8 *segment)
 
static void midi_parser_destroy (struct midi_parser *parser)
 
static HRESULT midi_parser_new (IStream *stream, struct midi_parser **out_parser)
 
HRESULT parse_midi (IStream *stream, IDirectMusicSegment8 *segment)
 

Macro Definition Documentation

◆ GET_BE_DWORD

#define GET_BE_DWORD (   x)    RtlUlongByteSwap(x)

Definition at line 31 of file midi.c.

◆ GET_BE_WORD

#define GET_BE_WORD (   x)    RtlUshortByteSwap(x)

Definition at line 30 of file midi.c.

Enumeration Type Documentation

◆ meta_event_type

Enumerator
MIDI_META_SEQUENCE_NUMBER 
MIDI_META_TEXT_EVENT 
MIDI_META_COPYRIGHT_NOTICE 
MIDI_META_TRACK_NAME 
MIDI_META_INSTRUMENT_NAME 
MIDI_META_LYRIC 
MIDI_META_MARKER 
MIDI_META_CUE_POINT 
MIDI_META_CHANNEL_PREFIX_ASSIGNMENT 
MIDI_META_END_OF_TRACK 
MIDI_META_SET_TEMPO 
MIDI_META_SMPTE_OFFSET 
MIDI_META_TIME_SIGNATURE 
MIDI_META_KEY_SIGNATURE 
MIDI_META_SEQUENCER_SPECIFIC 

Definition at line 74 of file midi.c.

75{
81 MIDI_META_LYRIC = 0x05,
82 MIDI_META_MARKER = 0x06,
91};
@ 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

Function Documentation

◆ midi_parser_destroy()

static void midi_parser_destroy ( struct midi_parser *  parser)
static

Definition at line 413 of file midi.c.

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}
static void list_remove(struct list_entry *entry)
Definition: list.h:90
#define free
Definition: debug_ros.c:5
#define IDirectMusicTrack_Release(p)
Definition: dmplugin.h:226
uint32_t entry
Definition: isohybrid.c:63
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:242
DMUS_IO_SEQ_ITEM item
Definition: midi.c:55
Definition: import.c:81

Referenced by midi_parser_new(), and parse_midi().

◆ midi_parser_handle_control()

static HRESULT midi_parser_handle_control ( struct midi_parser *  parser,
struct midi_event *  event 
)
static

Definition at line 296 of file midi.c.

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}
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define NULL
Definition: types.h:112
LONG MUSIC_TIME
Definition: dmplugin.h:95
#define DMUS_PPQ
Definition: dmusici.h:314
#define S_OK
Definition: intsafe.h:52
if(dx< 0)
Definition: linetemp.h:194
#define calloc
Definition: rosglue.h:14
DWORD dwPChannel
Definition: dmusicf.h:434
MUSIC_TIME mtTime
Definition: dmusicf.h:432
MUSIC_TIME mtDuration
Definition: dmusicf.h:433
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by midi_parser_parse().

◆ midi_parser_handle_note_on_off()

static HRESULT midi_parser_handle_note_on_off ( struct midi_parser *  parser,
struct midi_event *  event 
)
static

Definition at line 244 of file midi.c.

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}
#define index(s, c)
Definition: various.h:29
int note(char *format,...)
Definition: util.c:12
#define MIDI_NOTE_OFF
Definition: beepmidi.c:61
#define MIDI_NOTE_ON
Definition: beepmidi.c:62
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint index
Definition: glext.h:6031
#define TRACE(s)
Definition: solgame.cpp:4
Definition: filter.c:185
unsigned char BYTE
Definition: xxhash.c:193

Referenced by midi_parser_parse().

◆ midi_parser_handle_program_change()

static HRESULT midi_parser_handle_program_change ( struct midi_parser *  parser,
struct midi_event *  event 
)
static

Definition at line 216 of file midi.c.

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}
HRESULT band_add_instrument(IDirectMusicBand *iface, DMUS_IO_INSTRUMENT *instrument)
Definition: band.c:531
#define WARN(fmt,...)
Definition: precomp.h:61
HRESULT hr
Definition: delayimp.cpp:582
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
#define IDirectMusicTrack_SetParam(p, a, b, c)
Definition: dmplugin.h:233
#define DMUS_IO_INST_PATCH
Definition: dmusicf.h:237
#define IDirectMusicBand_Release(p)
Definition: dmusici.h:815
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
MUSIC_TIME mtTimePhysical
Definition: dmusici.h:783
struct IDirectMusicBand * pBand
Definition: dmusici.h:784
Definition: band.c:76

Referenced by midi_parser_parse().

◆ midi_parser_handle_set_tempo()

static HRESULT midi_parser_handle_set_tempo ( struct midi_parser *  parser,
struct midi_event *  event 
)
static

Definition at line 200 of file midi.c.

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}
double dblTempo
Definition: dmusicf.h:477
MUSIC_TIME mtTime
Definition: dmusicf.h:476

Referenced by midi_parser_parse().

◆ midi_parser_new()

static HRESULT midi_parser_new ( IStream *  stream,
struct midi_parser **  out_parser 
)
static

Definition at line 429 of file midi.c.

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}
static void list_init(struct list_entry *head)
Definition: list.h:51
static void midi_parser_destroy(struct midi_parser *parser)
Definition: midi.c:413
#define GET_BE_WORD(x)
Definition: midi.c:30
#define GET_BE_DWORD(x)
Definition: midi.c:31
#define DMUS_E_UNSUPPORTED_STREAM
Definition: dmerror.h:100
unsigned short WORD
Definition: ntddk_ex.h:93
GLintptr offset
Definition: glext.h:5920
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
DWORD division
Definition: midi.c:71
IStream * stream
Definition: midi.c:70
Definition: parse.h:23

Referenced by parse_midi().

◆ midi_parser_parse()

static HRESULT midi_parser_parse ( struct midi_parser *  parser,
IDirectMusicSegment8 *  segment 
)
static

Definition at line 323 of file midi.c.

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}
#define read
Definition: acwin.h:97
#define FIXME(fmt,...)
Definition: precomp.h:53
#define MIDI_CONTROL_CHANGE
Definition: beepmidi.c:63
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 read_midi_event(IStream *stream, struct midi_event *event, BYTE *last_status, ULONG *bytes_left)
Definition: midi.c:120
static HRESULT midi_parser_handle_program_change(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:216
static HRESULT midi_parser_handle_control(struct midi_parser *parser, struct midi_event *event)
Definition: midi.c:296
static int midi_seqtrack_item_compare(const void *a, const void *b)
Definition: midi.c:317
_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 *))
void sequence_track_set_items(IDirectMusicTrack8 *track, DMUS_IO_SEQ_ITEM *items, unsigned int count)
Definition: seqtrack.c:507
@ MIDI_PITCH_BEND_CHANGE
Definition: dmusic_midi.h:33
#define IDirectMusicSegment8_SetLength(p, a)
Definition: dmusici.h:1086
#define IDirectMusicSegment8_InsertTrack(p, a, b)
Definition: dmusici.h:1093
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 MIDI_PROGRAM_CHANGE
Definition: midi.h:20
#define MIDI_CHANNEL_PRESSURE
Definition: midi.h:21
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:236
#define memset(x, y, z)
Definition: compat.h:39
uint32_t ULONG
Definition: typedefs.h:59

Referenced by parse_midi().

◆ midi_seqtrack_item_compare()

static int midi_seqtrack_item_compare ( const void *  a,
const void *  b 
)
static

Definition at line 317 of file midi.c.

318{
319 const DMUS_IO_SEQ_ITEM *item_a = a, *item_b = b;
320 return item_a->mtTime - item_b->mtTime;
321}
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79

Referenced by midi_parser_parse().

◆ parse_midi()

HRESULT parse_midi ( IStream *  stream,
IDirectMusicSegment8 *  segment 
)

Definition at line 483 of file midi.c.

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}
static HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser)
Definition: midi.c:429
static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment8 *segment)
Definition: midi.c:323

Referenced by segment_persist_stream_Load().

◆ read_midi_event()

static HRESULT read_midi_event ( IStream *  stream,
struct midi_event *  event,
BYTE *  last_status,
ULONG *  bytes_left 
)
static

Definition at line 120 of file midi.c.

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}
#define ERR(fmt,...)
Definition: precomp.h:57
#define E_FAIL
Definition: ddrawi.h:102
static HRESULT stream_read_at_most(IStream *stream, void *buffer, ULONG size, ULONG *bytes_left)
Definition: midi.c:93
static HRESULT read_variable_length_number(IStream *stream, DWORD *out, ULONG *bytes_left)
Definition: midi.c:105
#define byte(x, n)
Definition: tomcrypt.h:118
@ MIDI_SYSEX2
Definition: dmusic_midi.h:35
@ MIDI_SYSEX1
Definition: dmusic_midi.h:34
@ MIDI_META
Definition: dmusic_midi.h:37
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define S_FALSE
Definition: winerror.h:3451

Referenced by midi_parser_parse().

◆ read_variable_length_number()

static HRESULT read_variable_length_number ( IStream *  stream,
DWORD *  out,
ULONG *  bytes_left 
)
static

Definition at line 105 of file midi.c.

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}
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383

Referenced by read_midi_event().

◆ stream_read_at_most()

static HRESULT stream_read_at_most ( IStream *  stream,
void *  buffer,
ULONG  size,
ULONG *  bytes_left 
)
static

Definition at line 93 of file midi.c.

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}
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919

Referenced by read_midi_event(), and read_variable_length_number().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( dmime  )