9e86b6d7ae4048f3494c1e1effeeb96d5d99d08e
[ardour.git] / libs / ardour / test / tempo_test.cc
1 #include "ardour/tempo.h"
2 #include "tempo_test.h"
3
4 CPPUNIT_TEST_SUITE_REGISTRATION (TempoTest);
5
6 using namespace std;
7 using namespace ARDOUR;
8 using namespace Timecode;
9
10 void
11 TempoTest::recomputeMapTest48 ()
12 {
13         int const sampling_rate = 48000;
14
15         TempoMap map (sampling_rate);
16         Meter meterA (4, 4);
17         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
18
19         /*
20           120bpm at bar 1, 240bpm at bar 4
21
22           120bpm = 24e3 samples per beat
23           240bpm = 12e3 samples per beat
24         */
25
26
27         /*
28
29           120bpm                                                240bpm
30           0 beats                                               12 beats
31           0 frames                                              288e3 frames
32           0 pulses                                              3 pulses
33           |                 |                 |                 |             |
34           | 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
35
36         */
37
38         Tempo tempoA (120.0, 4.0);
39         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
40         Tempo tempoB (240.0, 4.0);
41         map.add_tempo (tempoB, 3.0, 0, MusicTime);
42         Meter meterB (3, 4);
43         map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), 0, MusicTime);
44         //map.dump (map._metrics, std::cout);
45         list<MetricSection*>::iterator i = map._metrics.begin();
46         CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
47         i = map._metrics.end();
48         --i;
49         CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), (*i)->frame ());
50
51         /* check the tempo section for expected result (no map) */
52         const TempoSection& tsa (map.tempo_section_at_frame (0));
53         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
54         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 2.0, tsa.minute_at_pulse (1.5), 1e-17);
55         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 3.0, tsa.minute_at_pulse (1.0), 1e-17);
56
57         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
58         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, tsa.pulse_at_minute (0.1 / 2.0), 1e-17);
59         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.pulse_at_minute (0.1 / 3.0), 1e-17);
60
61         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.minute_at_frame (60.0 * sampling_rate), 1e-17);
62
63         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
64         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
65
66         /* do the same via the map */
67
68         /* quarter note */
69
70         /* quarter note - frame*/
71         CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), map.frame_at_quarter_note (12.0));
72         CPPUNIT_ASSERT_EQUAL (framepos_t (144e3), map.frame_at_quarter_note (6.0));
73         CPPUNIT_ASSERT_EQUAL (framepos_t (96e3), map.frame_at_quarter_note (4.0));
74
75         /* frame - quarter note*/
76         CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_frame (288e3), 1e-17);
77         CPPUNIT_ASSERT_DOUBLES_EQUAL (6.0, map.quarter_note_at_frame (144e3), 1e-17);
78         CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, map.quarter_note_at_frame (96e3), 1e-17);
79
80         /* pulse - internal minute based interface */
81         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_pulse_locked (map._metrics, 3.0), 1e-17);
82         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_minute_locked (map._metrics, 0.1), 1e-17);
83
84         /* tempo */
85
86         /* tempo - frame */
87         CPPUNIT_ASSERT_EQUAL (framepos_t (288e3), map.frame_at_tempo (tempoB));
88         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_frame (288e3).note_types_per_minute(), 1e-17);
89         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_frame (288e3 - 1).note_types_per_minute(), 1e-17);
90
91         /* tempo - quarter note */
92         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (24.0).note_types_per_minute(), 1e-17);
93         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (12.0).note_types_per_minute(), 1e-17);
94         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (6.0).note_types_per_minute(), 1e-17);
95         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (0.0).note_types_per_minute(), 1e-17);
96
97         CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_tempo (tempoB), 1e-17);
98         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, map.quarter_note_at_tempo (tempoA), 1e-17);
99
100         /* tempo - internal minute interface  */
101         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_minute_locked (map._metrics, 0.1).note_types_per_minute(), 1e-17);
102         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_tempo_locked (map._metrics, tempoB), 1e-17);
103
104         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_pulse_locked (map._metrics, 3.0).note_types_per_minute(), 1e-17);
105         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_tempo_locked (map._metrics, tempoB), 1e-17);
106 }
107
108 void
109 TempoTest::recomputeMapTest44 ()
110 {
111         int const sampling_rate = 44100;
112
113         TempoMap map (sampling_rate);
114         Meter meterA (4, 4);
115         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
116
117         /*
118           120bpm at bar 1, 240bpm at bar 4
119
120           120bpm = 24e3 samples per beat
121           240bpm = 12e3 samples per beat
122         */
123
124
125         /*
126
127           120bpm                                                240bpm
128           0 beats                                               12 beats
129           0 frames                                              288e3 frames
130           0 pulses                                              3 pulses
131           |                 |                 |                 |             |
132           | 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
133
134         */
135
136         Tempo tempoA (120.0, 4.0);
137         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
138         Tempo tempoB (240.0, 4.0);
139         map.add_tempo (tempoB, 3.0, 0, MusicTime);
140         Meter meterB (3, 4);
141         map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), 288e3, MusicTime);
142
143         list<MetricSection*>::iterator i = map._metrics.begin();
144         CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
145         i = map._metrics.end();
146         --i;
147         CPPUNIT_ASSERT_EQUAL (framepos_t (264600), (*i)->frame ());
148
149         /* check the tempo section for expected result (no map) */
150         const TempoSection& tsa (map.tempo_section_at_frame (0));
151         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
152         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 2.0, tsa.minute_at_pulse (1.5), 1e-17);
153         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1 / 3.0, tsa.minute_at_pulse (1.0), 1e-17);
154
155         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
156         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5, tsa.pulse_at_minute (0.1 / 2.0), 1e-17);
157         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.pulse_at_minute (0.1 / 3.0), 1e-17);
158
159         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tsa.minute_at_frame (60.0 * sampling_rate), 1e-17);
160
161         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_ntpm (240.0, 3.0), 1e-17);
162
163         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, tsa.minute_at_pulse (3.0), 1e-17);
164         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, tsa.pulse_at_minute (0.1), 1e-17);
165
166         /* do the same via the map */
167
168         /* quarter note */
169
170         /* quarter note - frame */
171         CPPUNIT_ASSERT_EQUAL (framepos_t (264600), map.frame_at_quarter_note (12.0));
172         CPPUNIT_ASSERT_EQUAL (framepos_t (132300), map.frame_at_quarter_note (6.0));
173         CPPUNIT_ASSERT_EQUAL (framepos_t (88200), map.frame_at_quarter_note (4.0));
174
175         /* frame - quarter note */
176         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0 * 4.0, map.quarter_note_at_frame (264600), 1e-17);
177         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.5 * 4.0, map.quarter_note_at_frame (132300), 1e-17);
178         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0 * 4.0, map.quarter_note_at_frame (88200), 1e-17);
179
180         /* pulse - internal minute based interface */
181         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_pulse_locked (map._metrics, 3.0), 1e-17);
182         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_minute_locked (map._metrics, 0.1), 1e-17);
183
184         /* tempo */
185
186         /* tempo - frame */
187         CPPUNIT_ASSERT_EQUAL (framepos_t (264600), map.frame_at_tempo (tempoB));
188         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_frame (264600).note_types_per_minute(), 1e-17);
189         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_frame (264600 - 1).note_types_per_minute(), 1e-17);
190
191         /* tempo - quarter note */
192         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (24.0).note_types_per_minute(), 1e-17);
193         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_quarter_note (12.0).note_types_per_minute(), 1e-17);
194         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (6.0).note_types_per_minute(), 1e-17);
195         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, map.tempo_at_quarter_note (0.0).note_types_per_minute(), 1e-17);
196
197         CPPUNIT_ASSERT_DOUBLES_EQUAL (12.0, map.quarter_note_at_tempo (tempoB), 1e-17);
198         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, map.quarter_note_at_tempo (tempoA), 1e-17);
199
200         /* tempo - internal minute interface  */
201         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_minute_locked (map._metrics, 0.1).note_types_per_minute(), 1e-17);
202         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minute_at_tempo_locked (map._metrics, tempoB), 1e-17);
203
204         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, map.tempo_at_pulse_locked (map._metrics, 3.0).note_types_per_minute(), 1e-17);
205         CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, map.pulse_at_tempo_locked (map._metrics, tempoB), 1e-17);
206 }
207
208 void
209 TempoTest::qnDistanceTestConstant ()
210 {
211         int const sampling_rate = 44100;
212
213         TempoMap map (sampling_rate);
214         Meter meterA (4, 4);
215         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
216
217         /*
218           120bpm at bar 1, 240bpm at bar 4
219
220           120bpm = 24e3 samples per beat
221           240bpm = 12e3 samples per beat
222         */
223
224
225         /*
226
227           120bpm                                                240bpm
228           0 beats                                               12 beats
229           0 frames                                              288e3 frames
230           0 pulses                                              3 pulses
231           |                 |                 |                 |             |
232           | 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
233
234         */
235
236         Tempo tempoA (120.0, 4.0);
237         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
238         /* should have no effect on pulse */
239         Tempo tempoB (120.0, 4.0);
240         map.add_tempo (tempoB, 2.0, 0, MusicTime);
241         /* equivalent to pulse 3.0 @ 120 bpm*/
242         Tempo tempoC (240.0, 4.0);
243         map.add_tempo (tempoC, 0.0, 6 * sampling_rate, AudioTime);
244         Tempo tempoD (90.4, 4.0);
245         map.add_tempo (tempoD, 9.0, 0, MusicTime);
246         Tempo tempoE (110.6, 4.0);
247         map.add_tempo (tempoE, 12.0, 0, MusicTime);
248         Tempo tempoF (123.7, 4.0);
249         map.add_tempo (tempoF, 15.0, 0, MusicTime);
250         Tempo tempoG (111.8, 4.0);
251         map.add_tempo (tempoG, 0.0, (framepos_t) 2 * 60 * sampling_rate, AudioTime);
252
253         Meter meterB (3, 4);
254         map.add_meter (meterB, 12.0, BBT_Time (4, 1, 0), 288e3, MusicTime);
255
256         list<MetricSection*>::iterator i = map._metrics.begin();
257         CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
258         i = map._metrics.end();
259         --i;
260         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
261
262         --i;
263         /* tempoF */
264         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 15.0 * 4.0));
265         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 15.0 * 4.0), 1e-17);
266
267         --i;
268         /* tempoE */
269         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 12.0 * 4.0));
270         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 12.0 * 4.0), 1e-17);
271
272         --i;
273         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 9.0 * 4.0));
274         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 9.0 * 4.0), 1e-17);
275
276         --i;
277         /* tempoC */
278         CPPUNIT_ASSERT_EQUAL (framecnt_t (6 * sampling_rate), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
279         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
280
281         /* distance from beat 12.0 to 0.0 should be 6.0 seconds */
282         CPPUNIT_ASSERT_EQUAL (framecnt_t (264600), map.frames_between_quarter_notes (0.0, 3.0 * 4.0));
283         CPPUNIT_ASSERT_EQUAL (framecnt_t (-264600), map.frames_between_quarter_notes (3.0 * 4.0, 0.0));
284         CPPUNIT_ASSERT_EQUAL (framecnt_t (396900), map.frames_between_quarter_notes (0.0, 24.0));
285         CPPUNIT_ASSERT_EQUAL (framecnt_t (-396900), map.frames_between_quarter_notes (24.0, 0.0));
286         CPPUNIT_ASSERT_EQUAL (framecnt_t (88200), map.frames_between_quarter_notes (2.0 * 4.0, 3.0 * 4.0));
287 }
288 void
289 TempoTest::qnDistanceTestRamp ()
290 {
291         int const sampling_rate = 44100;
292
293         TempoMap map (sampling_rate);
294         Meter meterA (4, 4);
295         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
296
297         /*
298           120bpm at bar 1, 240bpm at bar 4
299
300           120bpm = 24e3 samples per beat
301           240bpm = 12e3 samples per beat
302         */
303
304
305         /*
306
307           120bpm                                                240bpm
308           0 beats                                               12 beats
309           0 frames                         288e3 frames
310           0 pulses                                              3 pulses
311           |                 |              |                 |                 |             |
312           | 1.1 1.2 1.3 1.4 |  -no music-  | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 |
313
314         */
315
316         Tempo tempoA (120.2, 4.0, 240.5);
317         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
318         Tempo tempoB (240.5, 4.0, 130.1);
319         map.add_tempo (tempoB, 3.0, 0, MusicTime);
320
321         Tempo tempoC (130.1, 4.0, 90.3);
322         map.add_tempo (tempoC, 0.0, 6 * sampling_rate, AudioTime);
323         Tempo tempoD (90.3, 4.0, 110.7);
324         map.add_tempo (tempoD, 9.0, 0, MusicTime);
325         Tempo tempoE (110.7, 4.0, 123.9);
326         map.add_tempo (tempoE, 12.0, 0, MusicTime);
327         Tempo tempoF (123.9, 4.0, 111.8);
328         map.add_tempo (tempoF, 15.0, 0, MusicTime);
329         Tempo tempoG (111.8, 4.0);
330         map.add_tempo (tempoG, 0.0, (framepos_t) 2 * 60 * sampling_rate, AudioTime);
331         Meter meterB (3, 4);
332         map.add_meter (meterB, 4.0, BBT_Time (2, 1, 0), 288e3, AudioTime);
333         map.dump (std::cout);
334         map.recompute_map (map._metrics, 1);
335
336         list<MetricSection*>::iterator i = map._metrics.begin();
337         CPPUNIT_ASSERT_EQUAL (framepos_t (0), (*i)->frame ());
338         i = map._metrics.end();
339         --i;
340         /* tempoG */
341         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
342         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
343
344         --i;
345         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 60.0));
346         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 60.0), 1e-17);
347
348         --i;
349         /* tempoE */
350         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 48.0));
351         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 48.0), 1e-17);
352
353         --i;
354         CPPUNIT_ASSERT_EQUAL ((*i)->frame(), map.frames_between_quarter_notes (0.0, 36.0));
355         CPPUNIT_ASSERT_DOUBLES_EQUAL ((*i)->minute(), map.minutes_between_quarter_notes_locked (map._metrics, 0.0, 36.0), 1e-17);
356
357         --i;
358         /* tempoC */
359         CPPUNIT_ASSERT_EQUAL (framecnt_t (6 * sampling_rate), map.frames_between_quarter_notes (0.0, (*i)->pulse() * 4.0));
360         CPPUNIT_ASSERT_DOUBLES_EQUAL (0.1, map.minutes_between_quarter_notes_locked (map._metrics, 0.0, (*i)->pulse() * 4.0), 1e-17);
361
362 }
363
364 void
365 TempoTest::rampTest48 ()
366 {
367         int const sampling_rate = 48000;
368
369         TempoMap map (sampling_rate);
370         Meter meterA (4, 4);
371         Tempo tempoA (77.0, 4.0, 217.0);
372         Tempo tempoB (217.0, 4.0);
373         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
374         map.add_tempo (tempoB, 0.0, (framepos_t) 60 * sampling_rate, AudioTime);
375         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
376
377         /*
378
379           77bpm                                                 217bpm
380           0 frames                                              60 * sample rate frames
381           |                 |                 |                 |             |
382           |                                                    *|
383           |                                                  *  |
384           |                                                *    |
385           |                                             *       |
386           |                                          *          |
387           |                                      *              |
388           |                                 *                   |
389           |                           *  |                      |
390           |                  *           |                      |
391           |     *            |           |                      |
392           -------------------|-----------|-----------------------
393                              20 seconds  125.0 bpm / note_type
394         */
395
396         TempoSection& tA = map.first_tempo();
397         const TempoSection& tB = map.tempo_section_at_frame ((framepos_t) 60 * sampling_rate);
398
399         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, 300.0), 1e-17);
400         CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_minute (1.0).note_types_per_minute(), 1e-17);
401
402         /* note 1e-14 here. pulse is two derivatives away from time */
403         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_minute (1.0), 1e-14);
404         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_pulse (tB.pulse()), 1e-15);
405
406         /* note 1e-17 here. tempo is one derivative away from pulse, so we can get the same stuff with more precision */
407         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 1.0), 1e-17);
408         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, tB.pulse()), 1e-17);
409
410         /* self-check tempo at pulse @ 125 bpm. */
411         CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
412
413         /* check that tB's pulse is what tA thinks it should be */
414         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 0), 1e-17);
415
416         /* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
417         CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0).note_types_per_minute(), 1e-17);
418         CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_ntpm (147.0, 0), 1e-17);
419
420         /* self-check frame at pulse 20 seconds in. */
421         const double target = 20.0 / 60.0;
422         const double result = tA.minute_at_pulse (tA.pulse_at_minute (target));
423         CPPUNIT_ASSERT_DOUBLES_EQUAL (target, result, 1e-14);
424 }
425
426 void
427 TempoTest::rampTest44 ()
428 {
429         int const sampling_rate = 44100;
430
431         TempoMap map (sampling_rate);
432         Meter meterA (4, 4);
433         Tempo tempoA (77.0, 4.0, 217.0);
434         Tempo tempoB (217.0, 4.0);
435         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
436         map.add_tempo (tempoB, 0.0, (framepos_t) 60 * sampling_rate, AudioTime);
437         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
438
439         /*
440
441           77bpm                                                 217bpm
442           0 frames                                              60 * sample rate frames
443           |                 |                 |                 |             |
444           |                                                    *|
445           |                                                  *  |
446           |                                                *    |
447           |                                             *       |
448           |                                          *          |
449           |                                      *              |
450           |                                 *                   |
451           |                           *  |                      |
452           |                  *           |                      |
453           |     *            |           |                      |
454           -------------------|-----------|-----------------------
455                              20 seconds  125.0 bpm / note_type
456         */
457
458         TempoSection& tA = map.first_tempo();
459         const TempoSection& tB = map.tempo_section_at_frame ((framepos_t) 60 * sampling_rate);
460
461         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, 300.0), 1e-17);
462         CPPUNIT_ASSERT_DOUBLES_EQUAL (217.0, tA.tempo_at_minute (1.0).note_types_per_minute(), 1e-17);
463
464         /* note 1e-14 here. pulse is two derivatives away from time */
465         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_minute (1.0), 1e-14);
466         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_pulse (tB.pulse()), 1e-15);
467
468         /* note 1e-17 here. tempo is one derivative away from pulse, so we can get the same stuff with more precision */
469         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 1.0), 1e-17);
470         CPPUNIT_ASSERT_DOUBLES_EQUAL (1.0, tA.minute_at_ntpm (217.0, tB.pulse()), 1e-17);
471
472         /* self-check tempo at pulse @ 125 bpm. */
473         CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA.tempo_at_pulse (tA.pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
474
475         /* check that tB's pulse is what tA thinks it should be */
476         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB.pulse(), tA.pulse_at_ntpm (217.0, 0), 1e-17);
477
478         /* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
479         CPPUNIT_ASSERT_DOUBLES_EQUAL (147.0, tA.tempo_at_pulse (tB.pulse() / 2.0).note_types_per_minute(), 1e-17);
480         CPPUNIT_ASSERT_DOUBLES_EQUAL ((tB.pulse() - tA.pulse()) / 2.0, tA.pulse_at_ntpm (147.0, 0), 1e-17);
481
482         /* self-check frame at pulse 20 seconds in. */
483         const double target = 20.0 / 60.0;
484         const double result = tA.minute_at_pulse (tA.pulse_at_minute (target));
485         CPPUNIT_ASSERT_DOUBLES_EQUAL (target, result, 1e-14);
486 }
487
488 void
489 TempoTest::tempoAtPulseTest ()
490 {
491         int const sampling_rate = 48000;
492
493         TempoMap map (sampling_rate);
494         Meter meterA (4, 8);
495         Tempo tempoA (80.0, 8.0, 160.0);
496         Tempo tempoB (160.0, 3.0, 123.0);
497         Tempo tempoC (123.0, 4.0);
498
499         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
500         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
501
502         map.add_tempo (tempoB, 20.0, 0, MusicTime);
503         map.add_tempo (tempoC, 30.0, 0, MusicTime);
504
505         TempoSection* tA = 0;
506         TempoSection* tB = 0;
507         TempoSection* tC = 0;
508
509         list<MetricSection*>::iterator i;
510
511         for (i = map._metrics.begin(); i != map._metrics.end(); ++i) {
512                 TempoSection* t;
513                 if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
514                         if (!tA) {
515                                 tA = t;
516                                 continue;
517                         }
518                         if (!tB) {
519                                 tB = t;
520                                 continue;
521                         }
522                         if (!tC) {
523                                 tC = t;
524                                 continue;
525                         }
526                 }
527         }
528
529         CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_pulse (20.0).note_types_per_minute(), 1e-17);
530         CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_pulse (30.0).note_types_per_minute(), 1e-17);
531
532         /* check that the tempo at the halfway mark (in pulses) is half the tempo delta.*/
533         CPPUNIT_ASSERT_DOUBLES_EQUAL (((80.0 - 160.0)  / 2.0) + 160.0, tA->tempo_at_pulse (10.0).note_types_per_minute(), 1e-17);
534         CPPUNIT_ASSERT_DOUBLES_EQUAL (20.0 / 2.0, tA->pulse_at_ntpm (120.0, 0), 1e-17);
535         CPPUNIT_ASSERT_DOUBLES_EQUAL (((160.0 - 123.0)  / 2.0) + 123.0, tB->tempo_at_pulse (25.0).note_types_per_minute(), 1e-17);
536         CPPUNIT_ASSERT_DOUBLES_EQUAL (((20.0 - 30.0)  / 2.0) + 30.0, tB->pulse_at_ntpm (141.5, 0), 1e-17);
537
538         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_pulse (20.0), 1e-17);
539         CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_pulse (30.0), 1e-17);
540
541         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_ntpm (160.0, 20.0), 1e-17);
542         CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_ntpm (123.0, 30.0), 1e-17);
543
544         /* self-check tempo at pulse @ 125 bpm. */
545         CPPUNIT_ASSERT_DOUBLES_EQUAL (125.0, tA->tempo_at_pulse (tA->pulse_at_ntpm (125.0, 0)).note_types_per_minute(), 1e-17);
546         CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_pulse (20.0).note_types_per_minute(), 1e-17);
547         CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_pulse (30.0).note_types_per_minute(), 1e-17);
548         /* test minute based measurements */
549         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_pulse (20.0), 1e-17);
550         CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_pulse (30.0), 1e-17);
551
552         CPPUNIT_ASSERT_DOUBLES_EQUAL (tB->minute(), tA->minute_at_ntpm (160.0, 20.0), 1e-17);
553         CPPUNIT_ASSERT_DOUBLES_EQUAL (tC->minute(), tB->minute_at_ntpm (123.0, 30.0), 1e-17);
554
555         CPPUNIT_ASSERT_DOUBLES_EQUAL (160.0, tA->tempo_at_minute (tB->minute()).note_types_per_minute(), 1e-17);
556         CPPUNIT_ASSERT_DOUBLES_EQUAL (123.0, tB->tempo_at_minute (tC->minute()).note_types_per_minute(), 1e-17);
557 }
558
559 void
560 TempoTest::tempoFundamentalsTest ()
561 {
562         int const sampling_rate = 48000;
563
564         TempoMap map (sampling_rate);
565         Meter meterA (4, 8);
566         Tempo tempoA (120.0, 4.0);
567         Tempo tempoB (120.0, 8.0);
568         Tempo tempoC (120.0, 2.0);
569         Tempo tempoD (160.0, 2.0);
570         Tempo tempoE (123.0, 3.0);
571
572         map.replace_meter (map.first_meter(), meterA, BBT_Time (1, 1, 0), 0, AudioTime);
573         map.replace_tempo (map.first_tempo(), tempoA, 0.0, 0, AudioTime);
574
575         map.add_tempo (tempoB, 20.0, 0, MusicTime);
576         map.add_tempo (tempoC, 30.0, 0, MusicTime);
577
578         map.add_tempo (tempoD, 40.0, 0, MusicTime);
579         map.add_tempo (tempoE, 50.0, 0, MusicTime);
580
581         TempoSection* tA = 0;
582         TempoSection* tB = 0;
583         TempoSection* tC = 0;
584         TempoSection* tD = 0;
585         TempoSection* tE = 0;
586         list<MetricSection*>::iterator i;
587
588         for (i = map._metrics.begin(); i != map._metrics.end(); ++i) {
589                 TempoSection* t;
590                 if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
591                         if (!tA) {
592                                 tA = t;
593                                 continue;
594                         }
595                         if (!tB) {
596                                 tB = t;
597                                 continue;
598                         }
599                         if (!tC) {
600                                 tC = t;
601                                 continue;
602                         }
603                         if (!tD) {
604                                 tD = t;
605                                 continue;
606                         }
607                         if (!tE) {
608                                 tE = t;
609                                 continue;
610                         }
611                 }
612         }
613
614         CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tA->frames_per_quarter_note (sampling_rate), 1e-17);
615         CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tA->frames_per_note_type (sampling_rate), 1e-17);
616         CPPUNIT_ASSERT_DOUBLES_EQUAL (120.0, tA->quarter_notes_per_minute (), 1e-17);
617         CPPUNIT_ASSERT_DOUBLES_EQUAL (30.0, tA->pulses_per_minute (), 1e-17);
618
619         CPPUNIT_ASSERT_DOUBLES_EQUAL (48000.0, tB->frames_per_quarter_note (sampling_rate), 1e-17);
620         CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tB->frames_per_note_type (sampling_rate), 1e-17);
621         CPPUNIT_ASSERT_DOUBLES_EQUAL (60.0, tB->quarter_notes_per_minute (), 1e-17);
622         CPPUNIT_ASSERT_DOUBLES_EQUAL (15.0, tB->pulses_per_minute (), 1e-17);
623
624         CPPUNIT_ASSERT_DOUBLES_EQUAL (12000.0, tC->frames_per_quarter_note (sampling_rate), 1e-17);
625         CPPUNIT_ASSERT_DOUBLES_EQUAL (24000.0, tC->frames_per_note_type (sampling_rate), 1e-17);
626         CPPUNIT_ASSERT_DOUBLES_EQUAL (240.0, tC->quarter_notes_per_minute (), 1e-17);
627         CPPUNIT_ASSERT_DOUBLES_EQUAL (60.0, tC->pulses_per_minute (), 1e-17);
628
629         CPPUNIT_ASSERT_DOUBLES_EQUAL (9000.0, tD->frames_per_quarter_note (sampling_rate), 1e-17);
630         CPPUNIT_ASSERT_DOUBLES_EQUAL (18000.0, tD->frames_per_note_type (sampling_rate), 1e-17);
631         CPPUNIT_ASSERT_DOUBLES_EQUAL (320.0, tD->quarter_notes_per_minute (), 1e-17);
632         CPPUNIT_ASSERT_DOUBLES_EQUAL (80.0, tD->pulses_per_minute (), 1e-17);
633
634         CPPUNIT_ASSERT_DOUBLES_EQUAL (17560.975609756097, tE->frames_per_quarter_note (sampling_rate), 1e-17);
635         CPPUNIT_ASSERT_DOUBLES_EQUAL (23414.634146341465, tE->frames_per_note_type (sampling_rate), 1e-17);
636         CPPUNIT_ASSERT_DOUBLES_EQUAL (164.0, tE->quarter_notes_per_minute (), 1e-17);
637         CPPUNIT_ASSERT_DOUBLES_EQUAL (41.0, tE->pulses_per_minute (), 1e-17);
638 }