ardour
smf_save.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2007, 2008 Edward Tomasz NapieraƂa <trasz@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE
15  * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18  * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
20  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
35 /* Reference: http://www.borg.com/~jglatt/tech/midifile.htm */
36 
37 #include <stdlib.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <math.h>
41 #include <errno.h>
42 #ifdef PLATFORM_WINDOWS
43 #include <winsock2.h>
44 #else
45 #include <arpa/inet.h>
46 #endif
47 #include "smf.h"
48 #include "smf_private.h"
49 
50 #define MAX_VLQ_LENGTH 128
51 
57 static void *
58 smf_extend(smf_t *smf, const int length)
59 {
60  int i, previous_file_buffer_length = smf->file_buffer_length;
61  char *previous_file_buffer = (char*)smf->file_buffer;
62 
63  /* XXX: Not terribly efficient. */
64  smf->file_buffer_length += length;
65  smf->file_buffer = realloc(smf->file_buffer, smf->file_buffer_length);
66  if (smf->file_buffer == NULL) {
67  g_critical("realloc(3) failed: %s", strerror(errno));
68  smf->file_buffer_length = 0;
69  return (NULL);
70  }
71 
72  /* Fix up pointers. XXX: omgwtf. */
73  for (i = 1; i <= smf->number_of_tracks; i++) {
74  smf_track_t *track;
75  track = smf_get_track_by_number(smf, i);
76  if (track->file_buffer != NULL)
77  track->file_buffer = (char *)track->file_buffer + ((char *)smf->file_buffer - previous_file_buffer);
78  }
79 
80  return ((char *)smf->file_buffer + previous_file_buffer_length);
81 }
82 
87 static int
88 smf_append(smf_t *smf, const void *buffer, const int buffer_length)
89 {
90  void *dest;
91 
92  dest = smf_extend(smf, buffer_length);
93  if (dest == NULL) {
94  g_critical("Cannot extend track buffer.");
95  return (-1);
96  }
97 
98  memcpy(dest, buffer, buffer_length);
99 
100  return (0);
101 }
102 
106 static int
108 {
109  struct mthd_chunk_struct mthd_chunk;
110 
111  memcpy(mthd_chunk.mthd_header.id, "MThd", 4);
112  mthd_chunk.mthd_header.length = htonl(6);
113  mthd_chunk.format = htons(smf->format);
114  mthd_chunk.number_of_tracks = htons(smf->number_of_tracks);
115  mthd_chunk.division = htons(smf->ppqn);
116 
117  return (smf_append(smf, &mthd_chunk, sizeof(mthd_chunk)));
118 }
119 
125 static void *
126 track_extend(smf_track_t *track, const int length)
127 {
128  void *buf;
129 
130  assert(track->smf);
131 
132  buf = smf_extend(track->smf, length);
133  if (buf == NULL)
134  return (NULL);
135 
136  track->file_buffer_length += length;
137  if (track->file_buffer == NULL)
138  track->file_buffer = buf;
139 
140  return (buf);
141 }
142 
147 static int
148 track_append(smf_track_t *track, const void *buffer, const int buffer_length)
149 {
150  void *dest;
151 
152  dest = track_extend(track, buffer_length);
153  if (dest == NULL) {
154  g_critical("Cannot extend track buffer.");
155  return (-1);
156  }
157 
158  memcpy(dest, buffer, buffer_length);
159 
160  return (0);
161 }
162 
163 int
164 smf_format_vlq(unsigned char *buf, int length, unsigned long value)
165 {
166  int i;
167  unsigned long buffer;
168 
169  /* Taken from http://www.borg.com/~jglatt/tech/midifile/vari.htm */
170  buffer = value & 0x7F;
171 
172  while ((value >>= 7)) {
173  buffer <<= 8;
174  buffer |= ((value & 0x7F) | 0x80);
175  }
176 
177  for (i = 0;; i++) {
178  buf[i] = buffer;
179 
180  if (buffer & 0x80)
181  buffer >>= 8;
182  else
183  break;
184  }
185 
186  assert(i <= length);
187 
188  /* + 1, because "i" is an offset, not a count. */
189  return (i + 1);
190 }
191 
192 smf_event_t *
193 smf_event_new_textual(int type, const char *text)
194 {
195  int vlq_length, text_length, copied_length;
196  smf_event_t *event;
197 
198  assert(type >= 1 && type <= 9);
199 
200  text_length = strlen(text);
201 
202  event = smf_event_new();
203  if (event == NULL)
204  return (NULL);
205 
206  /* "2 +" is for leading 0xFF 0xtype. */
207  event->midi_buffer_length = 2 + text_length + MAX_VLQ_LENGTH;
208  event->midi_buffer = (uint8_t*)malloc(event->midi_buffer_length);
209  if (event->midi_buffer == NULL) {
210  g_critical("Cannot allocate MIDI buffer structure: %s", strerror(errno));
211  smf_event_delete(event);
212 
213  return (NULL);
214  }
215 
216  event->midi_buffer[0] = 0xFF;
217  event->midi_buffer[1] = type;
218 
219  vlq_length = smf_format_vlq(event->midi_buffer + 2, MAX_VLQ_LENGTH - 2, text_length);
220  copied_length = snprintf((char *)event->midi_buffer + vlq_length + 2, event->midi_buffer_length - vlq_length - 2, "%s", text);
221 
222 #ifndef NDEBUG
223  (void) copied_length; /* stop gcc warning about unusued vars for non-debug build */
224 #else
225  assert(copied_length == text_length);
226 #endif
227 
228  event->midi_buffer_length = 2 + vlq_length + text_length;
229 
230  return event;
231 }
232 
236 static int
237 write_vlq(smf_event_t *event, unsigned long value)
238 {
239  unsigned char buf[MAX_VLQ_LENGTH];
240  int vlq_length;
241 
242  vlq_length = smf_format_vlq(buf, MAX_VLQ_LENGTH, value);
243 
244  return (track_append(event->track, buf, vlq_length));
245 }
246 
251 static int
253 {
254  assert(event->delta_time_pulses >= 0);
255 
256  return (write_vlq(event, event->delta_time_pulses));
257 }
258 
259 static int
261 {
262  int ret;
263  unsigned char sysex_status = 0xF0;
264 
265  assert(smf_event_is_sysex(event));
266 
267  ret = track_append(event->track, &sysex_status, 1);
268  if (ret)
269  return (ret);
270 
271  /* -1, because length does not include status byte. */
272  ret = write_vlq(event, event->midi_buffer_length - 1);
273  if (ret)
274  return (ret);
275 
276  ret = track_append(event->track, event->midi_buffer + 1, event->midi_buffer_length - 1);
277  if (ret)
278  return (ret);
279 
280  return (0);
281 }
282 
286 static int
288 {
289  int ret;
290  unsigned char escape_status = 0xF7;
291 
292  if (smf_event_is_sysex(event))
293  return (write_sysex_contents(event));
294 
295  ret = track_append(event->track, &escape_status, 1);
296  if (ret)
297  return (ret);
298 
299  ret = write_vlq(event, event->midi_buffer_length);
300  if (ret)
301  return (ret);
302 
303  ret = track_append(event->track, event->midi_buffer, event->midi_buffer_length);
304  if (ret)
305  return (ret);
306 
307  return (0);
308 }
309 
314 static int
316 {
318  return (write_escaped_event_contents(event));
319 
320  return (track_append(event->track, event->midi_buffer, event->midi_buffer_length));
321 }
322 
326 static int
328 {
329  int ret;
330 
331  ret = write_event_time(event);
332  if (ret)
333  return (ret);
334 
335  ret = write_event_contents(event);
336  if (ret)
337  return (ret);
338 
339  return (0);
340 }
341 
345 static int
347 {
348  struct chunk_header_struct mtrk_header;
349 
350  memcpy(mtrk_header.id, "MTrk", 4);
351 
352  return (track_append(track, &mtrk_header, sizeof(mtrk_header)));
353 }
354 
358 static int
360 {
361  struct chunk_header_struct *mtrk_header;
362 
363  assert(track->file_buffer != NULL);
364  assert(track->file_buffer_length >= 6);
365 
366  mtrk_header = (struct chunk_header_struct *)track->file_buffer;
367  mtrk_header->length = htonl(track->file_buffer_length - sizeof(struct chunk_header_struct));
368 
369  return (0);
370 }
371 
375 static int
377 {
378  int ret;
379  smf_event_t *event;
380 
381  ret = write_mtrk_header(track);
382  if (ret)
383  return (ret);
384 
385  while ((event = smf_track_get_next_event(track)) != NULL) {
386  ret = write_event(event);
387  if (ret)
388  return (ret);
389  }
390 
391  ret = write_mtrk_length(track);
392  if (ret)
393  return (ret);
394 
395  return (0);
396 }
397 
401 static int
402 write_file(smf_t *smf, FILE* stream)
403 {
404  if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
405  g_critical("fwrite(3) failed: %s", strerror(errno));
406 
407  return (-2);
408  }
409 
410  return (0);
411 }
412 
413 static void
415 {
416  int i;
417  smf_track_t *track;
418 
419  /* Clear the pointers. */
420  memset(smf->file_buffer, 0, smf->file_buffer_length);
421  free(smf->file_buffer);
422  smf->file_buffer = NULL;
423  smf->file_buffer_length = 0;
424 
425  for (i = 1; i <= smf->number_of_tracks; i++) {
426  track = smf_get_track_by_number(smf, i);
427  assert(track);
428  track->file_buffer = NULL;
429  track->file_buffer_length = 0;
430  }
431 }
432 
433 #ifndef NDEBUG
434 
438 static int
440 {
441  int i;
442 
443  smf_track_t *track;
444  if (smf->file_buffer != NULL) {
445  fprintf (stderr, "SFB != null but == %p\n", smf->file_buffer);
446  }
447  assert(smf->file_buffer == NULL);
448  assert(smf->file_buffer_length == 0);
449 
450  for (i = 1; i <= smf->number_of_tracks; i++) {
451  track = smf_get_track_by_number(smf, i);
452 
453  assert(track != NULL);
454  assert(track->file_buffer == NULL);
455  assert(track->file_buffer_length == 0);
456  }
457 
458  return (1);
459 }
460 
461 #endif /* !NDEBUG */
462 
466 int
468 {
469  if (event->midi_buffer_length != 3)
470  return (0);
471 
472  if (event->midi_buffer[0] != 0xFF || event->midi_buffer[1] != 0x2F || event->midi_buffer[2] != 0x00)
473  return (0);
474 
475  return (1);
476 }
477 
483 static int
485 {
486  int trackno, eot_found;
487  size_t eventno;
488  smf_track_t *track;
489  smf_event_t *event;
490 
491  if (smf->format < 0 || smf->format > 2) {
492  g_critical("SMF error: smf->format is less than zero of greater than two.");
493  return (-1);
494  }
495 
496  if (smf->number_of_tracks < 1) {
497  g_critical("SMF error: number of tracks is less than one.");
498  return (-2);
499  }
500 
501  if (smf->format == 0 && smf->number_of_tracks > 1) {
502  g_critical("SMF error: format is 0, but number of tracks is more than one.");
503  return (-3);
504  }
505 
506  if (smf->ppqn <= 0) {
507  g_critical("SMF error: PPQN has to be > 0.");
508  return (-4);
509  }
510 
511  for (trackno = 1; trackno <= smf->number_of_tracks; trackno++) {
512  track = smf_get_track_by_number(smf, trackno);
513  assert(track);
514 
515  eot_found = 0;
516 
517  for (eventno = 1; eventno <= track->number_of_events; eventno++) {
518  event = smf_track_get_event_by_number(track, eventno);
519  assert(event);
520 
521  if (!smf_event_is_valid(event)) {
522  g_critical("Event #%zu on track #%d is invalid.", eventno, trackno);
523  return (-5);
524  }
525 
526  if (smf_event_is_eot(event)) {
527  if (eot_found) {
528  g_critical("Duplicate End Of Track event on track #%d.", trackno);
529  return (-6);
530  }
531 
532  eot_found = 1;
533  }
534  }
535 
536  if (!eot_found) {
537  if (smf_track_add_eot_delta_pulses(track, 0)) {
538  g_critical("smf_track_add_eot_delta_pulses failed.");
539  return (-6);
540  }
541  }
542 
543  }
544 
545  return (0);
546 }
547 
548 #ifndef NDEBUG
549 
550 #define CHECK(cond) if (!(cond)) { return -1; }
551 
552 static int
554 {
555  CHECK(a->event_number == b->event_number);
557  CHECK(abs((long)(a->time_pulses - b->time_pulses)) <= 2);
558  CHECK(fabs(a->time_seconds - b->time_seconds) <= 0.01);
559  CHECK(a->track_number == b->track_number);
561  CHECK(memcmp(a->midi_buffer, b->midi_buffer, a->midi_buffer_length) == 0);
562  return 0;
563 }
564 
565 static int
567 {
568  size_t i;
569 
570  CHECK(a->track_number == b->track_number);
572 
573  for (i = 1; i <= a->number_of_events; i++)
575 
576  return 0;
577 }
578 
579 static int
580 check_smf_is_identical(const smf_t *a, const smf_t *b)
581 {
582  int i;
583 
584  CHECK(a->format == b->format);
585  CHECK(a->ppqn == b->ppqn);
587  CHECK(a->resolution == b->resolution);
589 
590  for (i = 1; i <= a->number_of_tracks; i++)
592 
593  /* We do not need to compare tempos explicitly, as tempo is always computed from track contents. */
594  return 0;
595 }
596 
597 static int
599 {
600  smf_t *saved;
601  int ret;
602 
603  saved = smf_load (file);
604  if (!saved) {
605  ret = -1;
606  } else {
607  ret = check_smf_is_identical(smf, saved);
608  }
609 
610  smf_delete(saved);
611  return (ret);
612 }
613 
614 #endif /* !NDEBUG */
615 
622 int
623 smf_save(smf_t *smf, FILE* file)
624 {
625  int i, error;
626  smf_track_t *track;
627 
628  smf_rewind(smf);
629 
630  assert(pointers_are_clear(smf));
631 
632  if (smf_validate(smf))
633  return (-1);
634 
635  if (write_mthd_header(smf))
636  return (-2);
637 
638  for (i = 1; i <= smf->number_of_tracks; i++) {
639  track = smf_get_track_by_number(smf, i);
640 
641  assert(track != NULL);
642 
643  error = write_track(track);
644  if (error) {
645  free_buffer(smf);
646  return (error);
647  }
648  }
649 
650  error = write_file(smf, file);
651 
652  free_buffer(smf);
653 
654  if (error)
655  return (error);
656 
657 #ifndef NDEBUG
658  if (check_smf_saved_correctly(smf, file)) {
659  g_warning("SMF warning: Did not save correctly, possible data loss.");
660  }
661 #endif
662 
663  return (0);
664 }
665 
void smf_rewind(smf_t *smf)
Definition: smf.c:908
#define CHECK(cond)
Definition: smf_save.c:550
int32_t delta_time_pulses
Definition: smf.h:309
int smf_event_is_valid(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_load.c:770
static int write_sysex_contents(smf_event_t *event)
Definition: smf_save.c:260
static int write_event_time(smf_event_t *event)
Definition: smf_save.c:252
int format
Definition: smf.h:235
static int smf_validate(smf_t *smf)
Definition: smf_save.c:484
void * file_buffer
Definition: smf.h:246
static int check_smf_track_is_identical(const smf_track_t *a, const smf_track_t *b)
Definition: smf_save.c:566
#define MAX_VLQ_LENGTH
Definition: smf_save.c:50
static int check_smf_is_identical(const smf_t *a, const smf_t *b)
Definition: smf_save.c:580
static int write_mthd_header(smf_t *smf)
Definition: smf_save.c:107
static int check_smf_saved_correctly(const smf_t *smf, FILE *file)
Definition: smf_save.c:598
size_t midi_buffer_length
Definition: smf.h:324
size_t event_number
Definition: smf.h:305
LIBPBD_API Transmitter error
static int write_escaped_event_contents(smf_event_t *event)
Definition: smf_save.c:287
int track_number
Definition: smf.h:279
smf_event_t * smf_track_get_event_by_number(const smf_track_t *track, size_t event_number)
Definition: smf.c:778
void smf_event_delete(smf_event_t *event)
Definition: smf.c:371
static void * smf_extend(smf_t *smf, const int length)
Definition: smf_save.c:58
int smf_event_is_system_common(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:90
smf_t * smf
Definition: smf.h:277
uint16_t ppqn
Definition: smf.h:239
static void free_buffer(smf_t *smf)
Definition: smf_save.c:414
static int write_event(smf_event_t *event)
Definition: smf_save.c:327
int smf_event_is_sysex(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:104
static int check_smf_event_is_identical(const smf_event_t *a, const smf_event_t *b)
Definition: smf_save.c:553
void smf_delete(smf_t *smf)
Definition: smf.c:88
size_t time_pulses
Definition: smf.h:312
int frames_per_second
Definition: smf.h:240
int smf_format_vlq(unsigned char *buf, int length, unsigned long value)
Definition: smf_save.c:164
int number_of_tracks
Definition: smf.h:242
smf_event_t * smf_event_new(void)
Definition: smf.c:225
static int write_mtrk_length(smf_track_t *track)
Definition: smf_save.c:359
static int smf_append(smf_t *smf, const void *buffer, const int buffer_length)
Definition: smf_save.c:88
int smf_event_is_system_realtime(const smf_event_t *event) WARN_UNUSED_RESULT
Definition: smf_decode.c:72
size_t number_of_events
Definition: smf.h:280
static int track_append(smf_track_t *track, const void *buffer, const int buffer_length)
Definition: smf_save.c:148
uint16_t number_of_tracks
Definition: smf_private.h:61
static int write_vlq(smf_event_t *event, unsigned long value)
Definition: smf_save.c:237
int resolution
Definition: smf.h:241
smf_event_t * smf_track_get_next_event(smf_track_t *track)
Definition: smf.c:698
smf_track_t * smf_get_track_by_number(const smf_t *smf, int track_number)
Definition: smf.c:757
static int write_event_contents(smf_event_t *event)
Definition: smf_save.c:315
int smf_save(smf_t *smf, FILE *file)
Definition: smf_save.c:623
double time_seconds
Definition: smf.h:315
size_t file_buffer_length
Definition: smf.h:247
int smf_track_add_eot_delta_pulses(smf_track_t *track, uint32_t delta)
Definition: smf.c:531
smf_event_t * smf_event_new_textual(int type, const char *text)
Definition: smf_save.c:193
static void * track_extend(smf_track_t *track, const int length)
Definition: smf_save.c:126
struct chunk_header_struct mthd_header
Definition: smf_private.h:59
smf_t * smf_load(FILE *) WARN_UNUSED_RESULT
Definition: smf_load.c:930
void * file_buffer
Definition: smf.h:283
uint16_t division
Definition: smf_private.h:62
static int write_file(smf_t *smf, FILE *stream)
Definition: smf_save.c:402
int track_number
Definition: smf.h:318
static int write_mtrk_header(smf_track_t *track)
Definition: smf_save.c:346
size_t file_buffer_length
Definition: smf.h:284
static int write_track(smf_track_t *track)
Definition: smf_save.c:376
static int pointers_are_clear(smf_t *smf)
Definition: smf_save.c:439
int smf_event_is_eot(const smf_event_t *event)
Definition: smf_save.c:467
uint8_t * midi_buffer
Definition: smf.h:321
smf_track_t * track
Definition: smf.h:302
smf_t * smf
Definition: smfsh.c:51
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64