... | ... |
@@ -16,6 +16,14 @@ WITH REGARD TO THIS SOFTWARE. |
16 | 16 |
#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025) |
17 | 17 |
#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf) |
18 | 18 |
|
19 |
+typedef struct { |
|
20 |
+ Uint8 *addr; |
|
21 |
+ Uint32 count, advance, period, age, a, d, s, r; |
|
22 |
+ Uint16 i, len; |
|
23 |
+ Sint8 volume[2]; |
|
24 |
+ Uint8 pitch, repeat; |
|
25 |
+} UxnAudio; |
|
26 |
+ |
|
19 | 27 |
/* clang-format off */ |
20 | 28 |
|
21 | 29 |
static Uint32 advances[12] = { |
... | ... |
@@ -40,8 +48,9 @@ envelope(UxnAudio *c, Uint32 age) |
40 | 48 |
} |
41 | 49 |
|
42 | 50 |
int |
43 |
-audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end) |
|
51 |
+audio_render(int instance, Sint16 *sample, Sint16 *end) |
|
44 | 52 |
{ |
53 |
+ UxnAudio *c = &uxn_audio[instance]; |
|
45 | 54 |
Sint32 s; |
46 | 55 |
if(!c->advance || !c->period) return 0; |
47 | 56 |
while(sample < end) { |
... | ... |
@@ -59,13 +68,26 @@ audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end) |
59 | 68 |
*sample++ += s * c->volume[0] / 0x180; |
60 | 69 |
*sample++ += s * c->volume[1] / 0x180; |
61 | 70 |
} |
62 |
- if(!c->advance) audio_finished_handler(c); |
|
71 |
+ if(!c->advance) audio_finished_handler(instance); |
|
63 | 72 |
return 1; |
64 | 73 |
} |
65 | 74 |
|
66 | 75 |
void |
67 |
-audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch) |
|
76 |
+audio_start(int instance, Device *d) |
|
68 | 77 |
{ |
78 |
+ UxnAudio *c = &uxn_audio[instance]; |
|
79 |
+ Uint16 addr, adsr; |
|
80 |
+ Uint8 pitch; |
|
81 |
+ DEVPEEK16(adsr, 0x8); |
|
82 |
+ DEVPEEK16(c->len, 0xa); |
|
83 |
+ DEVPEEK16(addr, 0xc); |
|
84 |
+ if(c->len > 0x10000 - addr) |
|
85 |
+ c->len = 0x10000 - addr; |
|
86 |
+ c->addr = &d->u->ram[addr]; |
|
87 |
+ c->volume[0] = d->dat[0xe] >> 4; |
|
88 |
+ c->volume[1] = d->dat[0xe] & 0xf; |
|
89 |
+ c->repeat = !(d->dat[0xf] & 0x80); |
|
90 |
+ pitch = d->dat[0xf] & 0x7f; |
|
69 | 91 |
if(pitch < 108 && c->len) |
70 | 92 |
c->advance = advances[pitch % 12] >> (8 - pitch / 12); |
71 | 93 |
else { |
... | ... |
@@ -85,8 +107,9 @@ audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch) |
85 | 107 |
} |
86 | 108 |
|
87 | 109 |
Uint8 |
88 |
-audio_get_vu(UxnAudio *c) |
|
110 |
+audio_get_vu(int instance) |
|
89 | 111 |
{ |
112 |
+ UxnAudio *c = &uxn_audio[instance]; |
|
90 | 113 |
int i; |
91 | 114 |
Sint32 sum[2] = {0, 0}; |
92 | 115 |
if(!c->advance || !c->period) return 0; |
... | ... |
@@ -97,3 +120,10 @@ audio_get_vu(UxnAudio *c) |
97 | 120 |
} |
98 | 121 |
return (sum[0] << 4) | sum[1]; |
99 | 122 |
} |
123 |
+ |
|
124 |
+Uint16 |
|
125 |
+audio_get_position(int instance) |
|
126 |
+{ |
|
127 |
+ UxnAudio *c = &uxn_audio[instance]; |
|
128 |
+ return c->i; |
|
129 |
+} |
... | ... |
@@ -15,17 +15,8 @@ typedef signed int Sint32; |
15 | 15 |
#define SAMPLE_FREQUENCY 44100 |
16 | 16 |
#define POLYPHONY 4 |
17 | 17 |
|
18 |
-typedef struct { |
|
19 |
- Uint8 *addr; |
|
20 |
- Uint32 count, advance, period, age, a, d, s, r; |
|
21 |
- Uint16 i, len; |
|
22 |
- Sint8 volume[2]; |
|
23 |
- Uint8 pitch, repeat; |
|
24 |
-} UxnAudio; |
|
25 |
- |
|
26 |
-extern UxnAudio uxn_audio[POLYPHONY]; |
|
27 |
- |
|
28 |
-Uint8 audio_get_vu(UxnAudio *c); |
|
29 |
-int audio_render(UxnAudio *c, Sint16 *sample, Sint16 *end); |
|
30 |
-void audio_start(UxnAudio *c, Uint16 adsr, Uint8 pitch); |
|
31 |
-void audio_finished_handler(UxnAudio *c); |
|
18 |
+Uint8 audio_get_vu(int instance); |
|
19 |
+Uint16 audio_get_position(int instance); |
|
20 |
+int audio_render(int instance, Sint16 *sample, Sint16 *end); |
|
21 |
+void audio_start(int instance, Device *d); |
|
22 |
+void audio_finished_handler(int instance); |
... | ... |
@@ -58,21 +58,21 @@ error(char *msg, const char *err) |
58 | 58 |
static void |
59 | 59 |
audio_callback(void *u, Uint8 *stream, int len) |
60 | 60 |
{ |
61 |
- int i, running = 0; |
|
61 |
+ int instance, running = 0; |
|
62 | 62 |
Sint16 *samples = (Sint16 *)stream; |
63 | 63 |
SDL_memset(stream, 0, len); |
64 |
- for(i = 0; i < POLYPHONY; i++) |
|
65 |
- running += audio_render(&uxn_audio[i], samples, samples + len / 2); |
|
64 |
+ for(instance = 0; instance < POLYPHONY; instance++) |
|
65 |
+ running += audio_render(instance, samples, samples + len / 2); |
|
66 | 66 |
if(!running) |
67 | 67 |
SDL_PauseAudioDevice(audio_id, 1); |
68 | 68 |
(void)u; |
69 | 69 |
} |
70 | 70 |
|
71 | 71 |
void |
72 |
-audio_finished_handler(UxnAudio *c) |
|
72 |
+audio_finished_handler(int instance) |
|
73 | 73 |
{ |
74 | 74 |
SDL_Event event; |
75 |
- event.type = audio0_event + (c - uxn_audio); |
|
75 |
+ event.type = audio0_event + instance; |
|
76 | 76 |
SDL_PushEvent(&event); |
77 | 77 |
} |
78 | 78 |
|
... | ... |
@@ -185,11 +185,11 @@ console_deo(Device *d, Uint8 port) |
185 | 185 |
static Uint8 |
186 | 186 |
audio_dei(Device *d, Uint8 port) |
187 | 187 |
{ |
188 |
- UxnAudio *c = &uxn_audio[d - devaudio0]; |
|
188 |
+ int instance = d - devaudio0; |
|
189 | 189 |
if(!audio_id) return d->dat[port]; |
190 | 190 |
switch(port) { |
191 |
- case 0x4: return audio_get_vu(c); |
|
192 |
- case 0x2: DEVPOKE16(0x2, c->i); /* fall through */ |
|
191 |
+ case 0x4: return audio_get_vu(instance); |
|
192 |
+ case 0x2: DEVPOKE16(0x2, audio_get_position(instance)); /* fall through */ |
|
193 | 193 |
default: return d->dat[port]; |
194 | 194 |
} |
195 | 195 |
} |
... | ... |
@@ -197,21 +197,11 @@ audio_dei(Device *d, Uint8 port) |
197 | 197 |
static void |
198 | 198 |
audio_deo(Device *d, Uint8 port) |
199 | 199 |
{ |
200 |
- UxnAudio *c = &uxn_audio[d - devaudio0]; |
|
200 |
+ int instance = d - devaudio0; |
|
201 | 201 |
if(!audio_id) return; |
202 | 202 |
if(port == 0xf) { |
203 |
- Uint16 addr, adsr; |
|
204 | 203 |
SDL_LockAudioDevice(audio_id); |
205 |
- DEVPEEK16(adsr, 0x8); |
|
206 |
- DEVPEEK16(c->len, 0xa); |
|
207 |
- DEVPEEK16(addr, 0xc); |
|
208 |
- if(c->len > 0x10000 - addr) |
|
209 |
- c->len = 0x10000 - addr; |
|
210 |
- c->addr = &d->u->ram[addr]; |
|
211 |
- c->volume[0] = d->dat[0xe] >> 4; |
|
212 |
- c->volume[1] = d->dat[0xe] & 0xf; |
|
213 |
- c->repeat = !(d->dat[0xf] & 0x80); |
|
214 |
- audio_start(c, adsr, d->dat[0xf] & 0x7f); |
|
204 |
+ audio_start(instance, d); |
|
215 | 205 |
SDL_UnlockAudioDevice(audio_id); |
216 | 206 |
SDL_PauseAudioDevice(audio_id, 0); |
217 | 207 |
} |