changeset 2145:62a53c052d9b

PCM channel add should saturate on overflow, not wrap around
author Michael Pavone <pavone@retrodev.com>
date Sat, 26 Mar 2022 02:01:55 -0700
parents 10e4439d8f13
children 0c0d4233d826
files rf5c164.c rf5c164.h
diffstat 2 files changed, 13 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/rf5c164.c	Sat Mar 26 00:54:47 2022 -0700
+++ b/rf5c164.c	Sat Mar 26 02:01:55 2022 -0700
@@ -139,7 +139,6 @@
 			int16_t left = (sample * (pcm->channels[pcm->cur_channel].regs[PAN] >> 4)) >> 5;
 			int16_t right = (sample * (pcm->channels[pcm->cur_channel].regs[PAN] & 0xF)) >> 5;
 			//printf("chan %d, raw %X, sample %d, left %d, right %d, ptr %X (raw %X)\n", pcm->cur_channel, pcm->channels[pcm->cur_channel].sample, sample, left, right, pcm->channels[pcm->cur_channel].cur_ptr >> 11, pcm->channels[pcm->cur_channel].cur_ptr);
-			//TODO: saturating add
 			pcm->left += left;
 			pcm->right += right;
 		}
@@ -155,6 +154,16 @@
 		pcm->cur_channel++;
 		pcm->cur_channel &= 7;
 		if (!pcm->cur_channel) {
+			if (pcm->left > INT16_MAX) {
+				pcm->left = INT16_MAX;
+			} else if (pcm->left < INT16_MIN) {
+				pcm->left = INT16_MIN;
+			}
+			if (pcm->right > INT16_MAX) {
+				pcm->right = INT16_MAX;
+			} else if (pcm->right < INT16_MIN) {
+				pcm->right = INT16_MIN;
+			}
 			render_put_stereo_sample(pcm->audio, pcm->left, pcm->right);
 			pcm->left = pcm->right = 0;
 		}
@@ -185,7 +194,7 @@
 		for (int i = 0; i < 8; i++)
 		{
 			int mask = 1 << i;
-			if (changed & mask & value) {
+			if ((changed & mask) && !(mask & value)) {
 				pcm->channels[i].state = START;
 			}
 		}
--- a/rf5c164.h	Sat Mar 26 00:54:47 2022 -0700
+++ b/rf5c164.h	Sat Mar 26 02:01:55 2022 -0700
@@ -17,8 +17,8 @@
 	uint16_t        ram[64*1024];
 	uint16_t        ram_bank;
 	uint16_t        pending_address;
-	int16_t         left;
-	int16_t         right;
+	int32_t         left;
+	int32_t         right;
 	rf5c164_channel channels[8];
 	uint8_t         pending_byte;
 	uint8_t         channel_enable;