1 /*****************************************************************************
2 * smf.c : Standard MIDI File (.mid) demux module for vlc
3 *****************************************************************************
4 * Copyright © 2007 Rémi Denis-Courmont
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 *****************************************************************************/
26 #include <vlc_common.h>
27 #include <vlc_plugin.h>
28 #include <vlc_demux.h>
29 #include <vlc_charset.h>
35 #define TEMPO_MAX 250 /* Beats per minute */
38 * Reads MIDI variable length (7, 14, 21 or 28 bits) integer.
39 * @return read value, or -1 on EOF/error.
41 static int32_t ReadVarInt (stream_t
*s
)
46 for (unsigned i
= 0; i
< 4; i
++)
48 if (vlc_stream_Read (s
, &byte
, 1) < 1)
51 val
= (val
<< 7) | (byte
& 0x7f);
52 if ((byte
& 0x80) == 0)
59 typedef struct smf_track_t
61 uint64_t next
; /*< Time of next message (in term of pulses) */
62 uint64_t start
; /*< Start offset in the file */
63 uint32_t length
; /*< Bytes length */
64 uint32_t offset
; /*< Read offset relative to the start offset */
65 uint8_t running_event
; /*< Running (previous) event */
69 * Reads (delta) time from the next event of a given track.
70 * @param s stream to read data from (must be positioned at the right offset)
72 static int ReadDeltaTime (stream_t
*s
, mtrk_t
*track
)
76 assert (vlc_stream_Tell (s
) == track
->start
+ track
->offset
);
78 if (track
->offset
>= track
->length
)
80 /* This track is done */
81 track
->next
= UINT64_MAX
;
85 delta_time
= ReadVarInt (s
);
89 track
->next
+= delta_time
;
90 track
->offset
= vlc_stream_Tell (s
) - track
->start
;
97 date_t pts
; /*< Play timestamp */
98 uint64_t pulse
; /*< Pulses counter */
99 mtime_t tick
; /*< Last tick timestamp */
101 mtime_t duration
; /*< Total duration */
102 unsigned ppqn
; /*< Pulses Per Quarter Note */
103 /* by the way, "quarter note" is "noire" in French */
105 unsigned trackc
; /*< Number of tracks */
106 mtrk_t trackv
[]; /*< Track states */
110 * Non-MIDI Meta events handler
113 int HandleMeta (demux_t
*p_demux
, mtrk_t
*tr
)
115 stream_t
*s
= p_demux
->s
;
116 demux_sys_t
*p_sys
= p_demux
->p_sys
;
122 if (vlc_stream_Read (s
, &type
, 1) != 1)
125 length
= ReadVarInt (s
);
129 payload
= malloc (length
+ 1);
130 if ((payload
== NULL
)
131 || (vlc_stream_Read (s
, payload
, length
) != length
))
137 payload
[length
] = '\0';
141 case 0x00: /* Sequence Number */
144 case 0x01: /* Text (comment) */
145 EnsureUTF8 ((char *)payload
);
146 msg_Info (p_demux
, "Text : %s", (char *)payload
);
149 case 0x02: /* Copyright */
150 EnsureUTF8 ((char *)payload
);
151 msg_Info (p_demux
, "Copyright : %s", (char *)payload
);
154 case 0x03: /* Track name */
155 EnsureUTF8 ((char *)payload
);
156 msg_Info (p_demux
, "Track name: %s", (char *)payload
);
159 case 0x04: /* Instrument name */
160 EnsureUTF8 ((char *)payload
);
161 msg_Info (p_demux
, "Instrument: %s", (char *)payload
);
164 case 0x05: /* Lyric (one syllable) */
165 /*EnsureUTF8 ((char *)payload);*/
168 case 0x06: /* Marker text */
169 EnsureUTF8 ((char *)payload
);
170 msg_Info (p_demux
, "Marker : %s", (char *)payload
);
173 case 0x07: /* Cue point (WAVE filename) */
174 EnsureUTF8 ((char *)payload
);
175 msg_Info (p_demux
, "Cue point : %s", (char *)payload
);
178 case 0x08: /* Program/Patch name */
179 EnsureUTF8 ((char *)payload
);
180 msg_Info (p_demux
, "Patch name: %s", (char *)payload
);
183 case 0x09: /* MIDI port name */
184 EnsureUTF8 ((char *)payload
);
185 msg_Dbg (p_demux
, "MIDI port : %s", (char *)payload
);
188 case 0x2F: /* End of track */
189 if (tr
->start
+ tr
->length
!= vlc_stream_Tell (s
))
191 msg_Err (p_demux
, "misplaced end of track");
196 case 0x51: /* Tempo */
199 uint32_t uspqn
= (payload
[0] << 16)
200 | (payload
[1] << 8) | payload
[2];
201 unsigned tempo
= 60 * 1000000 / (uspqn
? uspqn
: 1);
202 msg_Dbg (p_demux
, "tempo: %uus/qn -> %u BPM",
203 (unsigned)uspqn
, tempo
);
205 if (tempo
< TEMPO_MIN
)
207 msg_Warn (p_demux
, "tempo too slow -> %u BPM", TEMPO_MIN
);
211 if (tempo
> TEMPO_MAX
)
213 msg_Warn (p_demux
, "tempo too fast -> %u BPM", TEMPO_MAX
);
216 date_Change (&p_sys
->pts
, p_sys
->ppqn
* tempo
, 60);
222 case 0x54: /* SMPTE offset */
224 msg_Warn (p_demux
, "SMPTE offset not implemented");
229 case 0x58: /* Time signature */
236 case 0x59: /* Key signature */
243 case 0x7f: /* Proprietary event */
244 msg_Dbg (p_demux
, "ignored proprietary SMF Meta Event (%d bytes)",
249 msg_Warn (p_demux
, "unknown SMF Meta Event type 0x%02X (%d bytes)",
258 int HandleMessage (demux_t
*p_demux
, mtrk_t
*tr
, es_out_t
*out
)
260 stream_t
*s
= p_demux
->s
;
261 demux_sys_t
*sys
= p_demux
->p_sys
;
263 uint8_t first
, event
;
266 if (vlc_stream_Seek (s
, tr
->start
+ tr
->offset
)
267 || (vlc_stream_Read (s
, &first
, 1) != 1))
270 event
= (first
& 0x80) ? first
: tr
->running_event
;
272 switch (event
& 0xf0)
274 case 0xF0: /* System Exclusive */
277 case 0xF0: /* System Specific start */
278 case 0xF7: /* System Specific continuation */
280 /* Variable length followed by SysEx event data */
281 int32_t len
= ReadVarInt (s
);
285 block
= vlc_stream_Block (s
, len
);
288 block
= block_Realloc (block
, 1, len
);
291 block
->p_buffer
[0] = event
;
294 case 0xFF: /* SMF Meta Event */
295 if (HandleMeta (p_demux
, tr
))
297 /* We MUST NOT pass this event forward. It would be
298 * confused as a MIDI Reset real-time event. */
309 /* We cannot handle undefined "common" (non-real-time)
310 * events inside SMF, as we cannot differentiate a
311 * one byte delta-time (< 0x80) from event data. */
326 /* FIXME: one message per block is very inefficient */
327 block
= block_Alloc (1 + datalen
);
331 block
->p_buffer
[0] = event
;
334 if (vlc_stream_Read(s
, block
->p_buffer
+ 1, datalen
) < datalen
)
340 { /* implicit running status requires non-empty payload */
341 msg_Err (p_demux
, "malformatted MIDI event");
345 block
->p_buffer
[1] = first
;
347 && vlc_stream_Read(s
, block
->p_buffer
+ 2, datalen
- 1) < datalen
- 1)
352 block
->i_dts
= block
->i_pts
= date_Get(&sys
->pts
);
354 es_out_Send(out
, sys
->es
, block
);
356 block_Release (block
);
360 /* If event is not real-time, update running status */
361 tr
->running_event
= event
;
363 tr
->offset
= vlc_stream_Tell (s
) - tr
->start
;
367 block_Release(block
);
371 static int SeekSet0 (demux_t
*demux
)
373 stream_t
*stream
= demux
->s
;
374 demux_sys_t
*sys
= demux
->p_sys
;
376 /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
377 date_Init (&sys
->pts
, sys
->ppqn
* 2, 1);
378 date_Set (&sys
->pts
, VLC_TS_0
);
380 sys
->tick
= VLC_TS_0
;
382 for (unsigned i
= 0; i
< sys
->trackc
; i
++)
384 mtrk_t
*tr
= sys
->trackv
+ i
;
388 /* Why 0xF6 (Tuning Calibration)?
389 * Because it has zero bytes of data, so the parser will detect the
390 * error if the first event uses running status. */
391 tr
->running_event
= 0xF6;
393 if (vlc_stream_Seek (stream
, tr
->start
)
394 || ReadDeltaTime (stream
, tr
))
396 msg_Err (demux
, "fatal parsing error");
404 static int ReadEvents (demux_t
*demux
, uint64_t *restrict pulse
,
407 uint64_t cur_pulse
= *pulse
, next_pulse
= UINT64_MAX
;
408 demux_sys_t
*sys
= demux
->p_sys
;
410 for (unsigned i
= 0; i
< sys
->trackc
; i
++)
412 mtrk_t
*track
= sys
->trackv
+ i
;
414 while (track
->next
<= cur_pulse
)
416 if (HandleMessage (demux
, track
, out
)
417 || ReadDeltaTime (demux
->s
, track
))
419 msg_Err (demux
, "fatal parsing error");
424 if (next_pulse
> track
->next
)
425 next_pulse
= track
->next
;
428 if (next_pulse
!= UINT64_MAX
)
429 date_Increment (&sys
->pts
, next_pulse
- cur_pulse
);
434 #define TICK (CLOCK_FREQ / 100)
436 /*****************************************************************************
437 * Demux: read chunks and send them to the synthesizer
438 *****************************************************************************
439 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
440 *****************************************************************************/
441 static int Demux (demux_t
*demux
)
443 demux_sys_t
*sys
= demux
->p_sys
;
445 /* MIDI Tick emulation (ping the decoder every 10ms) */
446 if (sys
->tick
<= date_Get (&sys
->pts
))
448 block_t
*tick
= block_Alloc (1);
449 if (unlikely(tick
== NULL
))
452 tick
->p_buffer
[0] = 0xF9;
453 tick
->i_dts
= tick
->i_pts
= sys
->tick
;
455 es_out_Send (demux
->out
, sys
->es
, tick
);
456 es_out_SetPCR (demux
->out
, sys
->tick
);
462 /* MIDI events in chronological order across all tracks */
463 uint64_t pulse
= sys
->pulse
;
465 if (ReadEvents (demux
, &pulse
, demux
->out
))
468 if (pulse
== UINT64_MAX
)
469 return 0; /* all tracks are done */
475 static int Seek (demux_t
*demux
, mtime_t pts
)
477 demux_sys_t
*sys
= demux
->p_sys
;
479 /* Rewind if needed */
480 if (pts
< date_Get (&sys
->pts
) && SeekSet0 (demux
))
484 uint64_t pulse
= sys
->pulse
;
486 while (pts
> date_Get (&sys
->pts
))
488 if (pulse
== UINT64_MAX
)
489 return VLC_SUCCESS
; /* premature end */
490 if (ReadEvents (demux
, &pulse
, NULL
))
495 sys
->tick
= ((date_Get (&sys
->pts
) - VLC_TS_0
) / TICK
) * TICK
+ VLC_TS_0
;
499 /*****************************************************************************
501 *****************************************************************************/
502 static int Control (demux_t
*demux
, int i_query
, va_list args
)
504 demux_sys_t
*sys
= demux
->p_sys
;
509 *va_arg (args
, bool *) = true;
511 case DEMUX_GET_POSITION
:
514 *va_arg (args
, double *) = (sys
->tick
- (double)VLC_TS_0
)
517 case DEMUX_SET_POSITION
:
518 return Seek (demux
, va_arg (args
, double) * sys
->duration
);
519 case DEMUX_GET_LENGTH
:
520 *va_arg (args
, int64_t *) = sys
->duration
;
523 *va_arg (args
, int64_t *) = sys
->tick
- VLC_TS_0
;
526 return Seek (demux
, va_arg (args
, int64_t));
528 case DEMUX_CAN_PAUSE
:
529 case DEMUX_SET_PAUSE_STATE
:
530 case DEMUX_CAN_CONTROL_PACE
:
531 case DEMUX_GET_PTS_DELAY
:
532 return demux_vaControlHelper( demux
->s
, 0, -1, 0, 1, i_query
, args
);
541 * Probes file format and starts demuxing.
543 static int Open (vlc_object_t
*obj
)
545 demux_t
*demux
= (demux_t
*)obj
;
546 stream_t
*stream
= demux
->s
;
550 /* (Try to) parse the SMF header */
551 /* Header chunk always has 6 bytes payload */
552 if (vlc_stream_Peek (stream
, &peek
, 14) < 14)
555 /* Skip RIFF MIDI header if present */
556 if (!memcmp (peek
, "RIFF", 4) && !memcmp (peek
+ 8, "RMID", 4))
558 uint32_t riff_len
= GetDWLE (peek
+ 4);
560 msg_Dbg (demux
, "detected RIFF MIDI file (%"PRIu32
" bytes)", riff_len
);
561 if ((vlc_stream_Read (stream
, NULL
, 12) < 12))
564 /* Look for the RIFF data chunk */
571 || (vlc_stream_Read (stream
, chnk_hdr
, 8) < 8))
575 chnk_len
= GetDWLE (chnk_hdr
+ 4);
576 if (riff_len
< chnk_len
)
578 riff_len
-= chnk_len
;
580 if (!memcmp (chnk_hdr
, "data", 4))
583 if (vlc_stream_Read (stream
, NULL
, chnk_len
) < (ssize_t
)chnk_len
)
587 /* Read real SMF header. Assume RIFF data chunk length is proper. */
588 if (vlc_stream_Peek (stream
, &peek
, 14) < 14)
592 if (memcmp (peek
, "MThd\x00\x00\x00\x06", 8))
596 /* First word: SMF type */
597 switch (GetWBE (peek
))
606 /* We don't implement SMF2 (as do many) */
607 msg_Err (demux
, "unsupported SMF file type %u", GetWBE (peek
));
612 /* Second word: number of tracks */
613 unsigned tracks
= GetWBE (peek
);
615 if (!multitrack
&& (tracks
!= 1))
617 msg_Err (demux
, "invalid SMF type 0 file");
621 msg_Dbg (demux
, "detected Standard MIDI File (type %u) with %u track(s)",
624 /* Third/last word: timing */
625 unsigned ppqn
= GetWBE (peek
);
628 msg_Err (demux
, "SMPTE timestamps not implemented");
635 msg_Err(demux
, "invalid SMF file PPQN: %u", ppqn
);
638 msg_Dbg (demux
, " %u pulses per quarter note", ppqn
);
641 demux_sys_t
*sys
= malloc (sizeof (*sys
) + (sizeof (mtrk_t
) * tracks
));
642 if (unlikely(sys
== NULL
))
645 /* We've had a valid SMF header - now skip it*/
646 if (vlc_stream_Read (stream
, NULL
, 14) < 14)
652 sys
->trackc
= tracks
;
654 /* Prefetch track offsets */
655 for (unsigned i
= 0; i
< tracks
; i
++)
657 mtrk_t
*tr
= sys
->trackv
+ i
;
660 /* Seeking screws streaming up, but there is no way around this, as
661 * SMF1 tracks are performed simultaneously.
662 * Not a big deal as SMF1 are usually only a few kbytes anyway. */
663 if (i
> 0 && vlc_stream_Seek (stream
, tr
[-1].start
+ tr
[-1].length
))
665 msg_Err (demux
, "cannot build SMF index (corrupted file?)");
671 if (vlc_stream_Read (stream
, head
, 8) < 8)
673 /* FIXME: don't give up if we have at least one valid track */
674 msg_Err (demux
, "incomplete SMF chunk, file is corrupted");
678 if (memcmp (head
, "MTrk", 4) == 0)
681 uint_fast32_t chunk_len
= GetDWBE(head
+ 4);
682 msg_Dbg(demux
, "skipping unknown SMF chunk (%"PRIuFAST32
" bytes)",
684 if (vlc_stream_Seek(stream
, vlc_stream_Tell(stream
) + chunk_len
))
688 tr
->start
= vlc_stream_Tell (stream
);
689 tr
->length
= GetDWBE (head
+ 4);
693 if (vlc_stream_Control (stream
, STREAM_CAN_FASTSEEK
, &b
) == 0 && b
)
695 if (SeekSet0 (demux
))
698 for (uint64_t pulse
= 0; pulse
!= UINT64_MAX
;)
699 if (ReadEvents (demux
, &pulse
, NULL
))
702 sys
->duration
= date_Get (&sys
->pts
);
705 if (SeekSet0 (demux
))
709 es_format_Init (&fmt
, AUDIO_ES
, VLC_CODEC_MIDI
);
710 fmt
.audio
.i_channels
= 2;
711 fmt
.audio
.i_rate
= 44100; /* dummy value */
712 sys
->es
= es_out_Add (demux
->out
, &fmt
);
714 demux
->pf_demux
= Demux
;
715 demux
->pf_control
= Control
;
724 * Releases allocate resources.
726 static void Close (vlc_object_t
* p_this
)
728 demux_t
*p_demux
= (demux_t
*)p_this
;
729 demux_sys_t
*p_sys
= p_demux
->p_sys
;
735 set_description (N_("SMF demuxer"))
736 set_category (CAT_INPUT
)
737 set_subcategory (SUBCAT_INPUT_DEMUX
)
738 set_capability ("demux", 20)
739 set_callbacks (Open
, Close
)