Browse code

Implemented stereo sound.

Andrew Alderwick authored on 02/04/2021 19:43:03
Showing 2 changed files
... ...
@@ -43,11 +43,9 @@ BRK
43 43
 	~Time.second ~current.second NEQ #01 JNZ BRK
44 44
 	~Time.second =current.second
45 45
 
46
-	~Time.second #03 AND ^$no-sound JNZ
47
-	#ffff =Audio.ch1adsr
46
+	#1444 =Audio.ch1adsr
48 47
 	~Time.second #1d ADD =Audio.ch1pitch
49
-	#ff =Audio.ch1vol
50
-	$no-sound
48
+	~Time.second #03 AND #4b MUL #0f ADD =Audio.ch1vol
51 49
 
52 50
 	( clear )
53 51
 	#0080 SCALEX #0080 SCALEY ~needles.sx ~needles.sy #00 ,draw-line JSR2
... ...
@@ -51,26 +51,29 @@ Uint8 font[][8] = {
51 51
 
52 52
 #define SAMPLE_FREQUENCY 48000
53 53
 
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 */
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 */
67 68
 };
68 69
 
69
-static struct audio_channel {
70
+typedef struct audio_channel {
70 71
 	Uint32 period, count;
71 72
 	Sint32 age, a, d, s, r;
72
-	Sint16 volume, value;
73
-} channels[4];
73
+	Sint16 value[2];
74
+	Sint8 volume[2], phase;
75
+} Channel;
76
+Channel channels[4];
74 77
 
75 78
 static SDL_Window *gWindow;
76 79
 static SDL_Renderer *gRenderer;
... ...
@@ -236,39 +239,58 @@ togglezoom(Uxn *u)
236 239
 	redraw(pixels, u);
237 240
 }
238 241
 
242
+Sint16
243
+audio_envelope(Channel *c) {
244
+	if (c->age < c->a)
245
+		return 0x0888 * c->age / c->a;
246
+	else if (c->age < c->d)
247
+		return 0x0444 * (2 * c->d - c->a - c->age) / (c->d - c->a);
248
+	else if (c->age < c->s)
249
+		return 0x0444;
250
+	else if (c->age < c->r)
251
+		return 0x0444 * (c->r - c->age) / (c->r - c->s);
252
+	else
253
+		return 0x0000;
254
+}
255
+
239 256
 void
240 257
 audio_callback(void* userdata, Uint8* stream, int len) {
241 258
 	Sint16 *samples = (Sint16 *) stream;
242 259
 	int i, j;
243
-	len >>= 1; /* use len for number of samples, not bytes */
244
-	for (j = 0; j < len; ++j) samples[j] = 0;
260
+	len >>= 2; /* use len for number of samples, not bytes */
261
+	for (j = len * 2 - 1; j >= 0; --j) samples[j] = 0;
245 262
 	for (i = 0; i < 4; ++i) {
246
-		struct audio_channel *c = &channels[i];
247
-		if (!c->volume) continue;
263
+		Channel *c = &channels[i];
248 264
 		if (c->period < (1 << 20)) continue;
249 265
 		for (j = 0; j < len; ++j) {
250 266
 			c->age += 1;
251 267
 			c->count += 1 << 20;
252 268
 			while (c->count > c->period) {
253
-				int mul = c->value < 0 ? c->volume : -c->volume;
269
+				Sint16 mul;
254 270
 				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;
271
+				c->phase = !c->phase;
272
+				mul = (c->phase * 2 - 1) * audio_envelope(c);
273
+				c->value[0] = mul * c->volume[0];
274
+				c->value[1] = mul * c->volume[1];
265 275
 			}
266
-			samples[j] += c->value;
276
+			samples[j * 2] += c->value[0];
277
+			samples[j * 2 + 1] += c->value[1];
267 278
 		}
268 279
 	}
269 280
 	(void) userdata;
270 281
 }
271 282
 
283
+void
284
+silence(void) {
285
+	int i;
286
+	for (i = 0; i < 4; ++i) {
287
+		Channel *c = &channels[i];
288
+		c->volume[0] = 0;
289
+		c->volume[1] = 0;
290
+		c->period = 0;
291
+	}
292
+}
293
+
272 294
 void
273 295
 quit(void)
274 296
 {
... ...
@@ -301,11 +323,12 @@ init(void)
301 323
 	if(!(pixels = (Uint32 *)malloc(WIDTH * HEIGHT * sizeof(Uint32))))
302 324
 		return error("Pixels", "Failed to allocate memory");
303 325
 	clear(pixels);
326
+	silence();
304 327
 	SDL_StartTextInput();
305 328
 	SDL_ShowCursor(SDL_DISABLE);
306 329
 	as.freq = SAMPLE_FREQUENCY;
307 330
 	as.format = AUDIO_S16;
308
-	as.channels = 1;
331
+	as.channels = 2;
309 332
 	as.callback = audio_callback;
310 333
 	as.samples = 2048;
311 334
 	audio_id = SDL_OpenAudioDevice(NULL, 0, &as, NULL, 0);
... ...
@@ -474,17 +497,18 @@ audio_poke(Uxn *u, Uint16 ptr, Uint8 b0, Uint8 b1)
474 497
 {
475 498
 	Uint8 *m = u->ram.dat;
476 499
 	if (b0 & 1) {
477
-		Uint16 channel_addr = ptr + (b0 & 0x6);
478
-		struct audio_channel *c = &channels[(b0 & 0x6) >> 1];
500
+		Uint16 addr = ptr + (b0 & 0x6);
501
+		Channel *c = &channels[(b0 & 0x6) >> 1];
479 502
 		SDL_LockAudioDevice(audio_id);
480
-		c->period = note_periods[m[channel_addr + 8] % 12] >> (m[channel_addr + 8] / 12);
503
+		c->period = note_periods[m[addr + 8] % 12] >> (m[addr + 8] / 12);
481 504
 		c->count %= c->period;
482
-		c->volume = m[channel_addr + 9] << 5;
505
+		c->volume[0] = (m[addr + 9] >> 4) & 0xf;
506
+		c->volume[1] = m[addr + 9] & 0xf;
483 507
 		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);
508
+		c->a = (SAMPLE_FREQUENCY >> 4) * ((m[addr] >> 4) & 0xf);
509
+		c->d = c->a + (SAMPLE_FREQUENCY >> 4) * (m[addr] & 0xf);
510
+		c->s = c->d + (SAMPLE_FREQUENCY >> 4) * ((m[addr + 1] >> 4) & 0xf);
511
+		c->r = c->s + (SAMPLE_FREQUENCY >> 4) * (m[addr + 1] & 0xf);
488 512
 		SDL_UnlockAudioDevice(audio_id);
489 513
 	}
490 514
 	return b1;