[AD] midi length + midi frequency

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


In response to a request on [Al], attached is a patch which adds a
function get_midi_length(). While making it, I noticed that the midi
player only is called 40 times / second. I understand nothing of music
at all, but I know there are sometimes 64th notes in music (now if that
means they are 1/64th second long, I don't know) - anyway, it was easy
to do, so I added another function to change the maximum timer frequency
the midi player uses. I tried changing it to 64 with some midis I found,
but can't here any difference to 40.. so maybe this is quite unrelated
after all.

-- 
Elias Pschernig
Index: src/midi.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/midi.c,v
retrieving revision 1.20
diff -u -p -r1.20 midi.c
--- src/midi.c	12 Mar 2005 05:47:18 -0000	1.20
+++ src/midi.c	17 Mar 2005 15:59:25 -0000
@@ -14,6 +14,8 @@
  *
  *      Pause and seek functions by George Foot.
  *
+ *      get_midi_length by Elias Pschernig.
+ *
  *      See readme.txt for copyright information.
  */
 
@@ -77,6 +79,7 @@ typedef struct PATCH_TABLE              
 
 
 volatile long midi_pos = -1;                    /* position in MIDI file */
+volatile long midi_time = 0;                    /* position in milli seconds */
 static long midi_pos_counter;                   /* delta for midi_pos */
 
 volatile long _midi_tick = 0;                   /* counter for killing notes */
@@ -95,6 +98,7 @@ long midi_loop_end = -1;                
 static int midi_semaphore = 0;                  /* reentrancy flag */
 static int midi_loaded_patches = FALSE;         /* loaded entire patch set? */
 
+static int midi_timer_frequency = 40;           /* how often the midi callback gets called */
 static long midi_timer_speed;                   /* midi_player's timer speed */
 static int midi_pos_speed;                      /* MIDI delta -> midi_pos */
 static int midi_speed;                          /* MIDI delta -> timer */
@@ -875,14 +879,16 @@ static void midi_player(void)
       return;
 
    if (midi_semaphore) {
-      midi_timer_speed += BPS_TO_TIMER(40);
-      install_int_ex(midi_player, BPS_TO_TIMER(40));
+      midi_timer_speed += BPS_TO_TIMER(midi_timer_frequency);
+      install_int_ex(midi_player, BPS_TO_TIMER(midi_timer_frequency));
       return;
    }
 
    midi_semaphore = TRUE;
    _midi_tick++;
 
+   midi_time += midi_timer_speed;
+
    do_it_all_again:
 
    for (c=0; c<MIDI_VOICES; c++)
@@ -976,8 +982,8 @@ static void midi_player(void)
    }
 
    /* reprogram the timer */
-   if (midi_timer_speed < BPS_TO_TIMER(40))
-      midi_timer_speed = BPS_TO_TIMER(40);
+   if (midi_timer_speed < BPS_TO_TIMER(midi_timer_frequency))
+      midi_timer_speed = BPS_TO_TIMER(midi_timer_frequency);
 
    if (!midi_seeking) 
       install_int_ex(midi_player, midi_timer_speed);
@@ -1184,6 +1190,7 @@ static void prepare_to_play(MIDI *midi)
 
    midifile = midi;
    midi_pos = 0;
+   midi_time = 0;
    midi_pos_counter = 0;
    midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions;   /* 120 bpm */
    midi_new_speed = -1;
@@ -1446,6 +1453,34 @@ END_OF_FUNCTION(midi_seek);
 
 
 
+/* set_midi_frequency:
+ *  Allows to change how often the midi player is called per second, default is
+ *  40 times. There's usually no need to change this, since the accuracy at
+ *  which Allegro timer's are called isn't much higher in most operating
+ *  systems.
+ */
+void set_midi_frequency(int f)
+{
+    midi_timer_frequency = f;
+}
+
+
+
+/* get_midi_length:
+ *  Returns the length, in seconds, of the specified midi. This will stop any
+ *  currently playing midi. Don't call it too often, since it simulates playing
+ *  all of the midi to get the time even if the midi contains tempo changes.
+ */
+int get_midi_length(MIDI *midi)
+{
+    play_midi(midi, 0);
+    while (midi_pos < 0);
+    midi_seek(INT_MAX);
+    return midi_time / TIMERS_PER_SECOND;
+}
+
+
+
 /* midi_out:
  *  Inserts MIDI command bytes into the output stream, in realtime.
  */
@@ -1498,6 +1533,7 @@ int load_midi_patches(void)
 static void midi_lock_mem(void)
 {
    LOCK_VARIABLE(midi_pos);
+   LOCK_VARIABLE(midi_time);
    LOCK_VARIABLE(midi_pos_counter);
    LOCK_VARIABLE(_midi_tick);
    LOCK_VARIABLE(midifile);
@@ -1505,6 +1541,7 @@ static void midi_lock_mem(void)
    LOCK_VARIABLE(midi_loop);
    LOCK_VARIABLE(midi_loop_start);
    LOCK_VARIABLE(midi_loop_end);
+   LOCK_VARIABLE(midi_timer_frequency);
    LOCK_VARIABLE(midi_timer_speed);
    LOCK_VARIABLE(midi_pos_speed);
    LOCK_VARIABLE(midi_speed);
Index: include/allegro/midi.h
===================================================================
RCS file: /cvsroot/alleg/allegro/include/allegro/midi.h,v
retrieving revision 1.2
diff -u -p -r1.2 midi.h
--- include/allegro/midi.h	31 Oct 2002 12:56:24 -0000	1.2
+++ include/allegro/midi.h	17 Mar 2005 15:59:25 -0000
@@ -121,8 +121,10 @@ AL_FUNC(void, stop_midi, (void));
 AL_FUNC(void, midi_pause, (void));
 AL_FUNC(void, midi_resume, (void));
 AL_FUNC(int, midi_seek, (int target));
+AL_FUNC(int, get_midi_length, (MIDI *midi));
 AL_FUNC(void, midi_out, (unsigned char *data, int length));
 AL_FUNC(int, load_midi_patches, (void));
+AL_FUNC(void, set_midi_frequency, (int f));
 
 AL_FUNCPTR(void, midi_msg_callback, (int msg, int byte1, int byte2));
 AL_FUNCPTR(void, midi_meta_callback, (int type, AL_CONST unsigned char *data, int length));


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/