File: tempomap.c

package info (click to toggle)
audacity 2.0.6-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 80,076 kB
  • sloc: cpp: 192,859; ansic: 158,072; sh: 34,021; python: 24,248; lisp: 7,495; makefile: 3,667; xml: 573; perl: 31; sed: 16
file content (124 lines) | stat: -rw-r--r-- 3,322 bytes parent folder | download | duplicates (15)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* tempomap.c -- used by midifile reader to record and lookup time maps */
/*
 *  This module is designed to provide tempo change list insert and
 *  lookup facilities.  The exact interpretation of beat and tempo are
 *  defined in one function, elapsed_time, which takes a tempo and a
 *  number of beats, and returns time.
 */

#include "cext.h"
#include "midifns.h"
#include "timebase.h"
#include "moxc.h"
#include "seq.h"
#include "tempomap.h"

static time_type elapsed_time();

/* tempomap_create -- create a tempomap */
/**/
tempomap_type tempomap_create()
{
    tempochange_type tempochange = tempochange_alloc();
    tempomap_type tempomap = tempomap_alloc();
    tempomap->hint = tempomap->entries = tempochange;
    tempochange->beat = 0L;
    /* default tempo is 120 (= 50000microsec/beat) and 24 divisions/quarter */
    /* this may be overridden by a tempomap_insert */
    tempochange->tempo = 500000L / 24;
    tempochange->rtime = 0L;
    tempochange->next = NULL;
    return tempomap;
}


/* tempomap_free -- deallocate storage for tempo map */
/**/
void tempomap_free(tm)
  tempomap_type tm;
{
    while (tm->entries) {
        tempochange_type tc = tm->entries;
        tm->entries = tc->next;
        tempochange_free(tc);
    }
    memfree(tm, sizeof(tempomap_node));
}


/* tempomap_insert -- insert a tempo change into the map */
/**/
void tempomap_insert(tempomap, beat, tempo)
  tempomap_type tempomap;
  long beat;    /* beat division number */
  long tempo;   /* microseconds per beat division */
{
    tempochange_type tempochange = tempochange_alloc();
    register tempochange_type prev;
    register tempochange_type next;

    tempochange->tempo = tempo;
    tempochange->beat = beat;

    if ((!(tempomap->hint->next)) ||
          (tempomap->hint->beat > beat))
        tempomap->hint = tempomap->entries;

    /* find the insert point */
    for (prev = tempomap->hint;
         (next = prev->next) && (next->beat <= beat);
         prev = next);

     /* make the insert */
    tempochange->next = next;
    prev->next = tempochange;
    tempomap->hint = prev;

    /* update the real time of each change */
    for (tempochange = prev;
         tempochange->next;
         tempochange = tempochange->next) {
        tempochange->next->rtime =
            tempochange->rtime +
            elapsed_time(tempochange->tempo,
                         tempochange->next->beat - tempochange->beat);
    }
}


/* tempomap_lookup -- convert beat to 4us time */
/*
 * The returned time is real time in units of 4us.
 */
time_type tempomap_lookup(tempomap, beat)
  tempomap_type tempomap;
  long beat;
{
    register tempochange_type prev;
    register tempochange_type next;

    if ((!(tempomap->hint->next)) || 
          (tempomap->hint->beat > beat))
        tempomap->hint = tempomap->entries;

    /* find the last inflection point */
    for (prev = tempomap->hint;
         (next = prev->next) && (next->beat <= beat);
         prev = next);

    /* interpolate */
    return prev->rtime +
           elapsed_time(prev->tempo, beat - prev->beat);
}


/* elapsed_time -- compute the real elapsed time at a given tempo */
/*
 * the time returned is in units of 4us.
 */
static time_type elapsed_time(tempo, beat)
  long tempo;
  long beat;
{
    return (time_type)((tempo * beat) >> 2);
}