1 #include <math.h>
2 #include <stdio.h>
3 #include "fceu-types.h"
4 
5 #include "sound.h"
6 #include "x6502.h"
7 #include "fceu.h"
8 #include "filter.h"
9 
10 #include "fcoeffs.h"
11 
12 static uint32 mrindex;
13 static uint32 mrratio;
14 
SexyFilter2(int32 * in,int32 count)15 void SexyFilter2(int32 *in, int32 count) {
16  #ifdef moo
17 	static int64 acc = 0;
18 	double x, p;
19 	int64 c;
20 
21 	x = 2 * M_PI * 6000 / FSettings.SndRate;
22 	p = ((double)2 - cos(x)) - sqrt(pow((double)2 - cos(x), 2) - 1);
23 
24 	c = p * 0x100000;
25 	/* printf("%f\n",(double)c/0x100000); */
26  #endif
27 	static int64 acc = 0;
28 
29 	while (count--) {
30 		int64 dropcurrent;
31 		dropcurrent = ((*in << 16) - acc) >> 3;
32 
33 		acc += dropcurrent;
34 		*in = acc >> 16;
35 		in++;
36 #if 0
37 		 acc=((int64)0x100000-c)* *in + ((c*acc)>>20);
38 		*in=acc>>20;
39 		in++;
40 #endif
41 	}
42 }
43 
44 int64 sexyfilter_acc1 = 0, sexyfilter_acc2 = 0;
45 
SexyFilter(int32 * in,int32 * out,int32 count)46 void SexyFilter(int32 *in, int32 *out, int32 count) {
47 	int32 mul1, mul2, vmul;
48 
49 	mul1 = (94 << 16) / FSettings.SndRate;
50 	mul2 = (24 << 16) / FSettings.SndRate;
51 	vmul = (FSettings.SoundVolume << 16) * 3 / 4 / 100;
52 
53 	if (FSettings.soundq)
54 		vmul /= 4;
55 	else
56 		vmul *= 2;	/* TODO:  Increase volume in low quality sound rendering code itself */
57 
58 	while (count) {
59 		int64 ino = (int64) * in * vmul;
60 		sexyfilter_acc1 += ((ino - sexyfilter_acc1) * mul1) >> 16;
61 		sexyfilter_acc2 += ((ino - sexyfilter_acc1 - sexyfilter_acc2) * mul2) >> 16;
62 		/* printf("%d ",*in); */
63 		*in = 0;
64 		{
65 			int32 t = (sexyfilter_acc1 - ino + sexyfilter_acc2) >> 16;
66 			/* if(t>32767 || t<-32768) printf("Flow: %d\n",t); */
67 			if (t > 32767) t = 32767;
68 			if (t < -32768) t = -32768;
69 			*out = t;
70 		}
71 		in++;
72 		out++;
73 		count--;
74 	}
75 }
76 
77 /* Returns number of samples written to out. */
78 /* leftover is set to the number of samples that need to be copied
79 	from the end of in to the beginning of in.
80 */
81 
82 /* static uint32 mva=1000; */
83 
84 /* This filtering code assumes that almost all input values stay below 32767.
85 	Do not adjust the volume in the wlookup tables and the expansion sound
86 	code to be higher, or you *might* overflow the FIR code.
87 */
88 
NeoFilterSound(int32 * in,int32 * out,uint32 inlen,int32 * leftover)89 int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) {
90 	uint32 x;
91 	uint32 max;
92 	int32 *outsave = out;
93 	int32 count = 0;
94 
95 #if 0
96   for(x=0;x<inlen;x++)
97   {
98    if(in[x]>mva) { mva=in[x]; printf("%ld\n",in[x]);}
99   }
100 #endif
101 	max = (inlen - 1) << 16;
102 
103 	if (FSettings.soundq == 2) {
104 		for (x = mrindex; x < max; x += mrratio) {
105 			int32 acc = 0, acc2 = 0;
106 			uint32 c;
107 			int32 *S, *D;
108 
109 			for (c = SQ2NCOEFFS, S = &in[(x >> 16) - SQ2NCOEFFS], D = sq2coeffs; c; c--, D++) {
110 				acc += (S[c] * *D) >> 6;
111 				acc2 += (S[1 + c] * *D) >> 6;
112 			}
113 
114 			acc = ((int64)acc * (65536 - (x & 65535)) + (int64)acc2 * (x & 65535)) >> (16 + 11);
115 			*out = acc;
116 			out++;
117 			count++;
118 		}
119 	} else {
120 		for (x = mrindex; x < max; x += mrratio) {
121 			int32 acc = 0, acc2 = 0;
122 			uint32 c;
123 			int32 *S, *D;
124 
125 			for (c = NCOEFFS, S = &in[(x >> 16) - NCOEFFS], D = coeffs; c; c--, D++) {
126 				acc += (S[c] * *D) >> 6;
127 				acc2 += (S[1 + c] * *D) >> 6;
128 			}
129 
130 			acc = ((int64)acc * (65536 - (x & 65535)) + (int64)acc2 * (x & 65535)) >> (16 + 11);
131 			*out = acc;
132 			out++;
133 			count++;
134 		}
135 	}
136 
137 	mrindex = x - max;
138 
139 	if (FSettings.soundq == 2) {
140 		mrindex += SQ2NCOEFFS * 65536;
141 		*leftover = SQ2NCOEFFS + 1;
142 	} else {
143 		mrindex += NCOEFFS * 65536;
144 		*leftover = NCOEFFS + 1;
145 	}
146 
147 	if (GameExpSound.NeoFill)
148 		GameExpSound.NeoFill(outsave, count);
149 
150 	SexyFilter(outsave, outsave, count);
151 	if (FSettings.lowpass)
152 		SexyFilter2(outsave, count);
153 	return(count);
154 }
155 
MakeFilters(int32 rate)156 void MakeFilters(int32 rate) {
157 	int32 *tabs[6] = { C44100NTSC, C44100PAL, C48000NTSC, C48000PAL, C96000NTSC,
158 					   C96000PAL };
159 	int32 *sq2tabs[6] = { SQ2C44100NTSC, SQ2C44100PAL, SQ2C48000NTSC, SQ2C48000PAL,
160 						  SQ2C96000NTSC, SQ2C96000PAL };
161 
162 	int32 *tmp;
163 	int32 x;
164 	uint32 nco;
165 
166 	if (FSettings.soundq == 2)
167 		nco = SQ2NCOEFFS;
168 	else
169 		nco = NCOEFFS;
170 
171 	mrindex = (nco + 1) << 16;
172 	mrratio = (PAL ? (int64)(PAL_CPU * 65536) : (int64)(NTSC_CPU * 65536)) / rate;
173 
174 	if (FSettings.soundq == 2)
175 		tmp = sq2tabs[(PAL ? 1 : 0) | (rate == 48000 ? 2 : 0) | (rate == 96000 ? 4 : 0)];
176 	else
177 		tmp = tabs[(PAL ? 1 : 0) | (rate == 48000 ? 2 : 0) | (rate == 96000 ? 4 : 0)];
178 
179 	if (FSettings.soundq == 2)
180 		for (x = 0; x < (SQ2NCOEFFS >> 1); x++)
181 			sq2coeffs[x] = sq2coeffs[SQ2NCOEFFS - 1 - x] = tmp[x];
182 	else
183 		for (x = 0; x < (NCOEFFS >> 1); x++)
184 			coeffs[x] = coeffs[NCOEFFS - 1 - x] = tmp[x];
185 
186  #ifdef MOO
187 	/* Some tests involving precision and error. */
188 	{
189 		static int64 acc = 0;
190 		int x;
191 		for (x = 0; x < SQ2NCOEFFS; x++)
192 			acc += (int64)32767 * sq2coeffs[x];
193 		printf("Foo: %lld\n", acc);
194 	}
195  #endif
196 }
197