-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
pcm_timer_driver.c
61 lines (50 loc) · 1.59 KB
/
pcm_timer_driver.c
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
#include "pcm_timer_driver.h"
#include "tools.h"
static void pcm_timer_driver_set_opm_tempo(struct timer_driver *driver, int opm_tempo) {
struct pcm_timer_driver *pdriver = (struct pcm_timer_driver *)driver;
int
clock = 4000000,
d = gcd(clock, 1024),
c1 = clock / d,
c2 = 1024 / d,
s = pdriver->sample_rate * c2,
d2 = gcd(c1, s);
pdriver->numerator = s * (256 - opm_tempo) / d2;
pdriver->denominator = c1 / d2;
}
int pcm_timer_driver_init(struct pcm_timer_driver *driver, int sample_rate) {
timer_driver_init(&driver->timer_driver);
driver->sample_rate = sample_rate;
driver->numerator = driver->denominator = driver->remainder = 0;
driver->timer_driver.set_opm_tempo = pcm_timer_driver_set_opm_tempo;
return 0;
}
void pcm_timer_driver_deinit(struct pcm_timer_driver *driver) {
timer_driver_deinit(&driver->timer_driver);
driver->numerator = driver->denominator = driver->remainder = 0;
}
int pcm_timer_driver_estimate(struct pcm_timer_driver *driver, int samples) {
int denom = driver->remainder;
for(int i = 1; i <= samples; i++) {
denom += driver->denominator;
if(denom >= driver->numerator)
return i;
}
return samples;
}
int pcm_timer_driver_advance(struct pcm_timer_driver *driver, int samples) {
int denom = driver->remainder;
int ticks = 0;
for(int i = 1; i <= samples; i++) {
denom += driver->denominator;
if(denom >= driver->numerator) {
if(driver->timer_driver.tick) {
driver->timer_driver.tick((struct timer_driver *)&driver, driver->timer_driver.data_ptr);
}
ticks++;
denom -= driver->numerator;
}
}
driver->remainder = denom;
return ticks;
}