... | ... |
@@ -11,14 +11,13 @@ |
11 | 11 |
;needles { hx 2 hy 2 mx 2 my 2 sx 2 sy 2 } |
12 | 12 |
;line { x0 2 y0 2 x 2 y 2 sx 2 sy 2 dx 2 dy 2 e1 2 e2 2 } |
13 | 13 |
;color { byte 1 } |
14 |
-;ding { volume 1 } |
|
15 | 14 |
|
16 | 15 |
( devices ) |
17 | 16 |
|
18 | 17 |
|0100 ;Console { pad 8 char 1 byte 1 short 2 } |
19 | 18 |
|0110 ;Screen { width 2 height 2 pad 4 x 2 y 2 color 1 } |
20 | 19 |
|0120 ;Sprite { pad 8 x 2 y 2 addr 2 color 1 } |
21 |
-|0170 ;Audio { ch1asdr 2 ch2asdr 2 ch3asdr 2 ch4asdr 2 ch1pitch 1 ch1vol 1 ch2pitch 1 ch2vol 1 ch3pitch 1 ch3vol 1 ch4pitch 1 ch4vol 1 } |
|
20 |
+|0170 ;Audio { ch1adsr 2 ch2adsr 2 ch3adsr 2 ch4adsr 2 ch1pitch 1 ch1vol 1 ch2pitch 1 ch2vol 1 ch3pitch 1 ch3vol 1 ch4pitch 1 ch4vol 1 } |
|
22 | 21 |
|0190 ;Time { year 2 month 1 day 1 hour 1 minute 1 second 1 dow 1 doy 2 isdst 1 get 1 } |
23 | 22 |
|01F0 ;System { pad 8 r 2 g 2 b 2 } |
24 | 23 |
|
... | ... |
@@ -38,20 +37,17 @@ BRK |
38 | 37 |
|
39 | 38 |
@FRAME |
40 | 39 |
|
41 |
- ~ding.volume |
|
42 |
- DUP #00 EQU ^$keep JNZ |
|
43 |
- DUP #04 SUB =ding.volume |
|
44 |
- $keep |
|
45 |
- =Audio.ch1vol |
|
46 |
- |
|
47 | 40 |
#00 =Time.get |
48 | 41 |
|
49 | 42 |
( only draw once per second ) |
50 | 43 |
~Time.second ~current.second NEQ #01 JNZ BRK |
51 | 44 |
~Time.second =current.second |
52 | 45 |
|
46 |
+ ~Time.second #03 AND ^$no-sound JNZ |
|
47 |
+ #ffff =Audio.ch1adsr |
|
53 | 48 |
~Time.second #1d ADD =Audio.ch1pitch |
54 |
- #fc =ding.volume |
|
49 |
+ #ff =Audio.ch1vol |
|
50 |
+ $no-sound |
|
55 | 51 |
|
56 | 52 |
( clear ) |
57 | 53 |
#0080 SCALEX #0080 SCALEY ~needles.sx ~needles.sy #00 ,draw-line JSR2 |
... | ... |
@@ -51,26 +51,25 @@ Uint8 font[][8] = { |
51 | 51 |
|
52 | 52 |
#define SAMPLE_FREQUENCY 48000 |
53 | 53 |
|
54 |
-static Uint32 note_periods[12] = { |
|
55 |
- /* middle C (C4) is note 60 */ |
|
56 |
- (Uint32)0xfa7e * SAMPLE_FREQUENCY, /* C-1 */ |
|
57 |
- (Uint32)0xec6f * SAMPLE_FREQUENCY, |
|
58 |
- (Uint32)0xdf2a * SAMPLE_FREQUENCY, /* D-1 */ |
|
59 |
- (Uint32)0xd2a4 * SAMPLE_FREQUENCY, |
|
60 |
- (Uint32)0xc6d1 * SAMPLE_FREQUENCY, /* E-1 */ |
|
61 |
- (Uint32)0xbba8 * SAMPLE_FREQUENCY, /* F-1 */ |
|
62 |
- (Uint32)0xb120 * SAMPLE_FREQUENCY, |
|
63 |
- (Uint32)0xa72f * SAMPLE_FREQUENCY, /* G-1 */ |
|
64 |
- (Uint32)0x9dcd * SAMPLE_FREQUENCY, |
|
65 |
- (Uint32)0x94f2 * SAMPLE_FREQUENCY, /* A-1 */ |
|
66 |
- (Uint32)0x8c95 * SAMPLE_FREQUENCY, |
|
67 |
- (Uint32)0x84b2 * SAMPLE_FREQUENCY /* B-1 */ |
|
54 |
+static Uint32 note_periods[12] = { /* middle C (C4) is note 60 */ |
|
55 |
+ (Uint32) 0xfa7e * SAMPLE_FREQUENCY, /* C-1 */ |
|
56 |
+ (Uint32) 0xec6f * SAMPLE_FREQUENCY, |
|
57 |
+ (Uint32) 0xdf2a * SAMPLE_FREQUENCY, /* D-1 */ |
|
58 |
+ (Uint32) 0xd2a4 * SAMPLE_FREQUENCY, |
|
59 |
+ (Uint32) 0xc6d1 * SAMPLE_FREQUENCY, /* E-1 */ |
|
60 |
+ (Uint32) 0xbba8 * SAMPLE_FREQUENCY, /* F-1 */ |
|
61 |
+ (Uint32) 0xb120 * SAMPLE_FREQUENCY, |
|
62 |
+ (Uint32) 0xa72f * SAMPLE_FREQUENCY, /* G-1 */ |
|
63 |
+ (Uint32) 0x9dcd * SAMPLE_FREQUENCY, |
|
64 |
+ (Uint32) 0x94f2 * SAMPLE_FREQUENCY, /* A-1 */ |
|
65 |
+ (Uint32) 0x8c95 * SAMPLE_FREQUENCY, |
|
66 |
+ (Uint32) 0x84b2 * SAMPLE_FREQUENCY /* B-1 */ |
|
68 | 67 |
}; |
69 | 68 |
|
70 | 69 |
static struct audio_channel { |
71 | 70 |
Uint32 period, count; |
72 |
- int value; |
|
73 |
- Sint16 volume; |
|
71 |
+ Sint32 age, a, d, s, r; |
|
72 |
+ Sint16 volume, value; |
|
74 | 73 |
} channels[4]; |
75 | 74 |
|
76 | 75 |
static SDL_Window *gWindow; |
... | ... |
@@ -238,26 +237,36 @@ togglezoom(Uxn *u) |
238 | 237 |
} |
239 | 238 |
|
240 | 239 |
void |
241 |
-audio_callback(void *userdata, Uint8 *stream, int len) |
|
242 |
-{ |
|
243 |
- Sint16 *samples = (Sint16 *)stream; |
|
240 |
+audio_callback(void* userdata, Uint8* stream, int len) { |
|
241 |
+ Sint16 *samples = (Sint16 *) stream; |
|
244 | 242 |
int i, j; |
245 | 243 |
len >>= 1; /* use len for number of samples, not bytes */ |
246 |
- for(j = 0; j < len; ++j) samples[j] = 0; |
|
247 |
- for(i = 0; i < 4; ++i) { |
|
244 |
+ for (j = 0; j < len; ++j) samples[j] = 0; |
|
245 |
+ for (i = 0; i < 4; ++i) { |
|
248 | 246 |
struct audio_channel *c = &channels[i]; |
249 |
- if(!c->volume) continue; |
|
250 |
- if(c->period < (1 << 20)) continue; |
|
251 |
- for(j = 0; j < len; ++j) { |
|
247 |
+ if (!c->volume) continue; |
|
248 |
+ if (c->period < (1 << 20)) continue; |
|
249 |
+ for (j = 0; j < len; ++j) { |
|
250 |
+ c->age += 1; |
|
252 | 251 |
c->count += 1 << 20; |
253 |
- while(c->count > c->period) { |
|
254 |
- c->value = !c->value; |
|
252 |
+ while (c->count > c->period) { |
|
253 |
+ int mul = c->value < 0 ? c->volume : -c->volume; |
|
255 | 254 |
c->count -= c->period; |
255 |
+ if (c->age < c->a) |
|
256 |
+ c->value = mul * c->age / c->a; |
|
257 |
+ else if (c->age < c->d) |
|
258 |
+ c->value = mul * (2 * c->d - c->a - c->age) / 2 / (c->d - c->a); |
|
259 |
+ else if (c->age < c->s) |
|
260 |
+ c->value = mul / 2; |
|
261 |
+ else if (c->age < c->r) |
|
262 |
+ c->value = mul * (c->r - c->age) / 2 / (c->r - c->s); |
|
263 |
+ else |
|
264 |
+ c->volume = c->value = 0; |
|
256 | 265 |
} |
257 |
- samples[j] += (c->value * 2 - 1) * c->volume; |
|
266 |
+ samples[j] += c->value; |
|
258 | 267 |
} |
259 | 268 |
} |
260 |
- (void)userdata; |
|
269 |
+ (void) userdata; |
|
261 | 270 |
} |
262 | 271 |
|
263 | 272 |
void |
... | ... |
@@ -464,13 +473,18 @@ Uint8 |
464 | 473 |
audio_poke(Uxn *u, Uint16 ptr, Uint8 b0, Uint8 b1) |
465 | 474 |
{ |
466 | 475 |
Uint8 *m = u->ram.dat; |
467 |
- if(b0 & 1) { |
|
476 |
+ if (b0 & 1) { |
|
468 | 477 |
Uint16 channel_addr = ptr + (b0 & 0x6); |
469 | 478 |
struct audio_channel *c = &channels[(b0 & 0x6) >> 1]; |
470 | 479 |
SDL_LockAudioDevice(audio_id); |
471 | 480 |
c->period = note_periods[m[channel_addr + 8] % 12] >> (m[channel_addr + 8] / 12); |
472 | 481 |
c->count %= c->period; |
473 | 482 |
c->volume = m[channel_addr + 9] << 5; |
483 |
+ c->age = 0; |
|
484 |
+ c->a = ((m[channel_addr] >> 4) & 0xf) * (SAMPLE_FREQUENCY >> 4); |
|
485 |
+ c->d = c->a + (m[channel_addr] & 0xf) * (SAMPLE_FREQUENCY >> 4); |
|
486 |
+ c->s = c->d + ((m[channel_addr + 1] >> 4) & 0xf) * (SAMPLE_FREQUENCY >> 4); |
|
487 |
+ c->r = c->s + (m[channel_addr + 1] & 0xf) * (SAMPLE_FREQUENCY >> 4); |
|
474 | 488 |
SDL_UnlockAudioDevice(audio_id); |
475 | 489 |
} |
476 | 490 |
return b1; |