2 * Copyright (c) 2007, 2008 Edward Tomasz NapieraĆa <trasz@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 * This is Standard MIDI File format implementation, tempo map related part.
31 * For questions and comments, contact Edward Tomasz Napierala <trasz@FreeBSD.org>.
38 #include "smf_private.h"
40 static double seconds_from_pulses(const smf_t
*smf
, int pulses
);
43 * If there is tempo starting at "pulses" already, return it. Otherwise,
44 * allocate new one, fill it with values from previous one (or default ones,
45 * if there is no previous one) and attach it to "smf".
48 new_tempo(smf_t
*smf
, int pulses
)
50 smf_tempo_t
*tempo
, *previous_tempo
= NULL
;
52 if (smf
->tempo_array
->len
> 0) {
53 previous_tempo
= smf_get_last_tempo(smf
);
55 /* If previous tempo starts at the same time as new one, reuse it, updating in place. */
56 if (previous_tempo
->time_pulses
== pulses
)
57 return previous_tempo
;
60 tempo
= malloc(sizeof(smf_tempo_t
));
62 g_critical("Cannot allocate smf_tempo_t.");
66 tempo
->time_pulses
= pulses
;
68 if (previous_tempo
!= NULL
) {
69 tempo
->microseconds_per_quarter_note
= previous_tempo
->microseconds_per_quarter_note
;
70 tempo
->numerator
= previous_tempo
->numerator
;
71 tempo
->denominator
= previous_tempo
->denominator
;
72 tempo
->clocks_per_click
= previous_tempo
->clocks_per_click
;
73 tempo
->notes_per_note
= previous_tempo
->notes_per_note
;
75 tempo
->microseconds_per_quarter_note
= 500000; /* Initial tempo is 120 BPM. */
77 tempo
->denominator
= 4;
78 tempo
->clocks_per_click
= -1;
79 tempo
->notes_per_note
= -1;
82 g_ptr_array_add(smf
->tempo_array
, tempo
);
85 tempo
->time_seconds
= 0.0;
87 tempo
->time_seconds
= seconds_from_pulses(smf
, pulses
);
93 add_tempo(smf_t
*smf
, int pulses
, int tempo
)
95 smf_tempo_t
*smf_tempo
= new_tempo(smf
, pulses
);
96 if (smf_tempo
== NULL
)
99 smf_tempo
->microseconds_per_quarter_note
= tempo
;
105 add_time_signature(smf_t
*smf
, int pulses
, int numerator
, int denominator
, int clocks_per_click
, int notes_per_note
)
107 smf_tempo_t
*smf_tempo
= new_tempo(smf
, pulses
);
108 if (smf_tempo
== NULL
)
111 smf_tempo
->numerator
= numerator
;
112 smf_tempo
->denominator
= denominator
;
113 smf_tempo
->clocks_per_click
= clocks_per_click
;
114 smf_tempo
->notes_per_note
= notes_per_note
;
120 maybe_add_to_tempo_map(smf_event_t
*event
)
122 if (!smf_event_is_metadata(event
))
125 assert(event
->track
!= NULL
);
126 assert(event
->track
->smf
!= NULL
);
127 assert(event
->midi_buffer_length
>= 1);
130 if (event
->midi_buffer
[1] == 0x51) {
131 int new_tempo
= (event
->midi_buffer
[3] << 16) + (event
->midi_buffer
[4] << 8) + event
->midi_buffer
[5];
132 if (new_tempo
<= 0) {
133 g_critical("Ignoring invalid tempo change.");
137 add_tempo(event
->track
->smf
, event
->time_pulses
, new_tempo
);
140 /* Time Signature? */
141 if (event
->midi_buffer
[1] == 0x58) {
142 int numerator
, denominator
, clocks_per_click
, notes_per_note
;
144 if (event
->midi_buffer_length
< 7) {
145 g_critical("Time Signature event seems truncated.");
149 numerator
= event
->midi_buffer
[3];
150 denominator
= (int)pow(2, event
->midi_buffer
[4]);
151 clocks_per_click
= event
->midi_buffer
[5];
152 notes_per_note
= event
->midi_buffer
[6];
154 add_time_signature(event
->track
->smf
, event
->time_pulses
, numerator
, denominator
, clocks_per_click
, notes_per_note
);
161 * This is an internal function, called from smf_track_remove_event when tempo-related
162 * event being removed does not require recreation of tempo map, i.e. there are no events
166 remove_last_tempo_with_pulses(smf_t
*smf
, int pulses
)
170 /* XXX: This is a workaround for the following problem: we have two tempo-related
171 events, A and B, that occur at the same time. We remove B, then try to remove
172 A. However, both tempo changes got coalesced in new_tempo(), so it is impossible
174 if (smf
->tempo_array
->len
== 0)
177 tempo
= smf_get_last_tempo(smf
);
179 /* Workaround part two. */
180 if (tempo
->time_pulses
!= pulses
)
185 g_ptr_array_remove_index(smf
->tempo_array
, smf
->tempo_array
->len
- 1);
189 seconds_from_pulses(const smf_t
*smf
, int pulses
)
194 tempo
= smf_get_tempo_by_pulses(smf
, pulses
);
196 assert(tempo
->time_pulses
<= pulses
);
198 seconds
= tempo
->time_seconds
+ (double)(pulses
- tempo
->time_pulses
) *
199 (tempo
->microseconds_per_quarter_note
/ ((double)smf
->ppqn
* 1000000.0));
205 pulses_from_seconds(const smf_t
*smf
, double seconds
)
210 tempo
= smf_get_tempo_by_seconds(smf
, seconds
);
212 assert(tempo
->time_seconds
<= seconds
);
214 pulses
= tempo
->time_pulses
+ (seconds
- tempo
->time_seconds
) *
215 ((double)smf
->ppqn
* 1000000.0 / tempo
->microseconds_per_quarter_note
);
221 * Computes value of event->time_seconds for all events in smf.
222 * Warning: rewinds the smf.
225 smf_create_tempo_map_and_compute_seconds(smf_t
*smf
)
233 event
= smf_get_next_event(smf
);
238 maybe_add_to_tempo_map(event
);
240 event
->time_seconds
= seconds_from_pulses(smf
, event
->time_pulses
);
248 smf_get_tempo_by_number(const smf_t
*smf
, int number
)
252 if (number
>= smf
->tempo_array
->len
)
255 return g_ptr_array_index(smf
->tempo_array
, number
);
259 * Return last tempo (i.e. tempo with greatest time_pulses) that happens before "pulses".
262 smf_get_tempo_by_pulses(const smf_t
*smf
, int pulses
)
270 return smf_get_tempo_by_number(smf
, 0);
272 assert(smf
->tempo_array
!= NULL
);
274 for (i
= smf
->tempo_array
->len
- 1; i
>= 0; i
--) {
275 tempo
= smf_get_tempo_by_number(smf
, i
);
278 if (tempo
->time_pulses
< pulses
)
286 * Return last tempo (i.e. tempo with greatest time_seconds) that happens before "seconds".
289 smf_get_tempo_by_seconds(const smf_t
*smf
, double seconds
)
294 assert(seconds
>= 0.0);
297 return smf_get_tempo_by_number(smf
, 0);
299 assert(smf
->tempo_array
!= NULL
);
301 for (i
= smf
->tempo_array
->len
- 1; i
>= 0; i
--) {
302 tempo
= smf_get_tempo_by_number(smf
, i
);
305 if (tempo
->time_seconds
< seconds
)
317 smf_get_last_tempo(const smf_t
*smf
)
321 tempo
= smf_get_tempo_by_number(smf
, smf
->tempo_array
->len
- 1);
328 * Remove any existing tempos and add default one.
331 smf_init_tempo(smf_t
*smf
)
335 while (smf
->tempo_array
->len
> 0) {
336 smf_tempo_t
*tempo
= g_ptr_array_index(smf
->tempo_array
, smf
->tempo_array
->len
- 1);
339 g_ptr_array_remove_index(smf
->tempo_array
, smf
->tempo_array
->len
- 1);
342 assert(smf
->tempo_array
->len
== 0);
344 tempo
= new_tempo(smf
, 0);
352 * Returns ->time_pulses of last event on the given track, or 0, if track is empty.
355 last_event_pulses(const smf_track_t
*track
)
357 /* Get time of last event on this track. */
358 if (track
->number_of_events
> 0) {
359 smf_event_t
*previous_event
= smf_track_get_last_event(track
);
360 assert(previous_event
);
361 assert(previous_event
->time_pulses
>= 0);
363 return previous_event
->time_pulses
;
370 * Adds event to the track at the time "pulses" clocks from the previous event in this track.
371 * The remaining two time fields will be computed automatically based on the third argument
372 * and current tempo map. Note that ->delta_pulses is computed by smf.c:smf_track_add_event,
376 smf_track_add_event_delta_pulses(smf_track_t
*track
, smf_event_t
*event
, int delta
)
379 assert(event
->time_pulses
== -1);
380 assert(event
->time_seconds
== -1.0);
381 assert(track
->smf
!= NULL
);
383 smf_track_add_event_pulses(track
, event
, last_event_pulses(track
) + delta
);
387 * Adds event to the track at the time "pulses" clocks from the start of song.
388 * The remaining two time fields will be computed automatically based on the third argument
389 * and current tempo map.
392 smf_track_add_event_pulses(smf_track_t
*track
, smf_event_t
*event
, int pulses
)
395 assert(event
->time_pulses
== -1);
396 assert(event
->time_seconds
== -1.0);
397 assert(track
->smf
!= NULL
);
399 event
->time_pulses
= pulses
;
400 event
->time_seconds
= seconds_from_pulses(track
->smf
, pulses
);
401 smf_track_add_event(track
, event
);
405 * Adds event to the track at the time "seconds" seconds from the start of song.
406 * The remaining two time fields will be computed automatically based on the third argument
407 * and current tempo map.
410 smf_track_add_event_seconds(smf_track_t
*track
, smf_event_t
*event
, double seconds
)
412 assert(seconds
>= 0.0);
413 assert(event
->time_pulses
== -1);
414 assert(event
->time_seconds
== -1.0);
415 assert(track
->smf
!= NULL
);
417 event
->time_seconds
= seconds
;
418 event
->time_pulses
= pulses_from_seconds(track
->smf
, seconds
);
419 smf_track_add_event(track
, event
);