1 /* Festalon - NSF Player
2 * Copyright (C) 2004 Xodnizel
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include <math.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <samplerate.h>
24
25 #include "types.h"
26
27 #include "filter.h"
28
29 #include "fcoeffs.h"
30
31 #include "cputest.h"
32
SexyFilter(FESTAFILT * ff,float * in,float * out,int32 count)33 static void SexyFilter(FESTAFILT *ff, float *in, float *out, int32 count)
34 {
35 double mul1,mul2,vmul;
36
37 mul1=(double)94/ff->rate;
38 mul2=(double)24/ff->rate;
39 vmul=(double)ff->SoundVolume*3/2/100;
40
41 while(count)
42 {
43 double ino=vmul * *in;
44 ff->acc1+=((ino-ff->acc1)*mul1);
45 ff->acc2+=((ino-ff->acc1-ff->acc2)*mul2);
46 {
47 float t=(ff->acc1-ino+ff->acc2);
48
49 t += 32767;
50 t /= 65535;
51 if(t < 0.0) t = 0.0;
52 if(t > 1.0) t = 1.0;
53 //if(t>32767 || t<-32768) printf("Flow: %d\n",t);
54 //if(t>32767) t=32767;
55 //if(t<-32768) t=-32768;
56 *out=t;
57 }
58 in++;
59 out++;
60 count--;
61 }
62 }
63
64 /* Returns number of samples written to out. */
65 /* leftover is set to the number of samples that need to be copied
66 from the end of in to the beginning of in.
67 */
68
69 /* This filtering code assumes that almost all input values stay below 32767.
70 Do not adjust the volume in the wlookup tables and the expansion sound
71 code to be higher, or you *might* overflow the FIR code.
72 */
FESTAFILT_Do(FESTAFILT * ff,float * in,float * out,uint32 maxoutlen,uint32 inlen,int32 * leftover,int sinput)73 int32 FESTAFILT_Do(FESTAFILT *ff, float *in, float *out, uint32 maxoutlen, uint32 inlen, int32 *leftover, int sinput)
74 {
75 uint32 x;
76 int32 max;
77 int32 count=0;
78 float *flout = ff->boobuf;
79
80 max = inlen & ~0x1F;
81 max -= NCOEFFS;
82 if(max < 0) max = 0;
83
84 #ifdef ARCH_X86
85
86 #ifdef __x86_64__
87 if(ff->cpuext & MM_MMX)
88 {
89 uint32 bigcount = max / ff->mrratio;
90 if(sinput)
91 {
92 #define FILTMMX_SKIP_ADD_STR "skippy"
93 #define FILTMMX_SKIP_ADD
94 #include "filter-amd64-mmx.h"
95 #undef FILTMMX_SKIP_ADD
96 #undef FILTMMX_SKIP_ADD_STR
97 }
98 else
99 {
100 #define FILTMMX_SKIP_ADD_STR ""
101 #include "filter-amd64-mmx.h"
102 #undef FILTMMX_SKIP_ADD_STR
103 }
104 }
105 #else
106 if(ff->cpuext & MM_SSE3)
107 {
108 #define TMP_FSSE3
109 #include "filter-sse.h"
110 #undef TMP_FSSE3
111 }
112 else if(ff->cpuext & MM_MMX)
113 {
114 uint32 bigcount = max / ff->mrratio;
115 if(sinput)
116 {
117 #define FILTMMX_SKIP_ADD_STR "skippy"
118 #define FILTMMX_SKIP_ADD
119 #include "filter-mmx.h"
120 #undef FILTMMX_SKIP_ADD
121 #undef FILTMMX_SKIP_ADD_STR
122 }
123 else
124 {
125 #define FILTMMX_SKIP_ADD_STR ""
126 #include "filter-mmx.h"
127 #undef FILTMMX_SKIP_ADD_STR
128 }
129 }
130 else if(ff->cpuext & MM_SSE)
131 {
132 #include "filter-sse.h"
133 }
134 else if(ff->cpuext & MM_3DNOW)
135 {
136 #include "filter-3dnow.h"
137 }
138 #endif
139 else
140 #elif ARCH_POWERPC
141 if(ff->cpuext & MM_ALTIVEC)
142 {
143 static unsigned int ld_vecsr14[4] __attribute__ ((aligned (16))) = {14,14,14,14};
144 vector unsigned int vecsr14 = vec_ld(0, ld_vecsr14);
145
146 for(x=0;x<max;x+=ff->mrratio)
147 {
148 vector signed int acc;
149 signed int acc_store[4];
150 signed short *wave,*coeffs;
151 unsigned int c;
152
153 acc = vec_xor(acc, acc);
154
155 coeffs = ff->coeffs_i16;
156 wave = (int16 *)in + x;
157
158 for(c=0;c<NCOEFFS;c+=8)
159 {
160 vector signed short wd, fd;
161 wd = vec_ld(c, wave);
162 fd = vec_ld(c, coeffs);
163
164 acc = vec_msums(wd, fd, acc);
165 }
166 vec_st(vec_sra(acc, vecsr14), 0, acc_store); // Shifting right might not be necessary at this point...
167 *flout = (float)((acc_store[0] + acc_store[1] + acc_store[2] + acc_store[3]) >> 2);
168
169 if(!sinput)
170 *flout += 32767;
171 flout++;
172 count++;
173 }
174 }
175 else
176 #endif
177 for(x=0;x<max;x+=ff->mrratio)
178 {
179 float acc = 0;
180 unsigned int c;
181 float *wave;
182 float *coeffs;
183
184 for(c=0,wave=(float *)&in[x],coeffs=ff->coeffs;c<NCOEFFS;c+=2)
185 {
186 acc+=wave[c] * coeffs[c];
187 acc+= (wave+1)[c] * (coeffs+1)[c];
188 }
189 *flout = acc;
190 flout++;
191 count++;
192 }
193
194 *leftover=inlen - max;
195
196 count = max / ff->mrratio;
197 if(ff->fidbuf)
198 ff->fidfuncp(ff->fidbuf, ff->boobuf, max / ff->mrratio);
199 {
200 SRC_DATA doot;
201 int error;
202
203 doot.data_in = ff->boobuf;
204 doot.data_out = out;
205 doot.input_frames = count;
206 doot.output_frames = maxoutlen;
207 doot.src_ratio = ff->lrhfactor;
208 doot.end_of_input = 0;
209
210 if((error=src_process(ff->lrh, &doot)))
211 {
212 //printf("Eeeek: %s, %d, %d\n",src_strerror(error),ff->boobuf,out);
213 //exit(1);
214 }
215
216 //if(doot.input_frames_used - count) exit(1);
217 //printf("Oops: %d\n\n", doot.input_frames_used - count);
218
219 //printf("%d\n",doot.output_frames_gen);
220 SexyFilter(ff, out, out, doot.output_frames_gen);
221 return(doot.output_frames_gen);
222 }
223 }
224
FreeFid(FESTAFILT * ff)225 static void FreeFid(FESTAFILT *ff)
226 {
227 if(ff->fidbuf)
228 {
229 fid_run_freebuf(ff->fidbuf);
230 ff->fidbuf = 0;
231 }
232
233 if(ff->fidrun)
234 {
235 fid_run_free(ff->fidrun);
236 ff->fidrun = 0;
237 }
238
239 if(ff->fid)
240 {
241 free(ff->fid);
242 ff->fid = 0;
243 }
244 }
245
FESTAFILT_Kill(FESTAFILT * ff)246 void FESTAFILT_Kill(FESTAFILT *ff)
247 {
248 if(ff->lrh)
249 src_delete(ff->lrh);
250
251 FreeFid(ff);
252 free(ff->realmem);
253 }
254
FESTAFILT_Init(int32 rate,double cpuclock,int PAL,int soundq)255 FESTAFILT * FESTAFILT_Init(int32 rate, double cpuclock, int PAL, int soundq)
256 {
257 double *tabs[2]={COEF_NTSC,COEF_PAL};
258 double *tabs2[2]={COEF_NTSC_HI,COEF_PAL_HI};
259 double *tmp;
260 int32 x;
261 uint32 nco;
262 uint32 div;
263 FESTAFILT *ff;
264 void *realmem;
265 int srctype;
266
267 if(!(realmem=ff=malloc(16 + sizeof(FESTAFILT)))) return(0);
268
269 ff = (FESTAFILT *)(unsigned long)(((unsigned long)ff+0xFLL)&~0xFLL);
270 memset(ff,0,sizeof(FESTAFILT));
271 ff->realmem = realmem;
272 ff->soundq=soundq;
273
274 nco=NCOEFFS;
275
276 if(soundq)
277 {
278 tmp=tabs2[(PAL?1:0)];
279 div = 16;
280 srctype = SRC_SINC_BEST_QUALITY;
281 }
282 else
283 {
284 tmp=tabs[(PAL?1:0)];
285 div = 32;
286 srctype = SRC_SINC_FASTEST;
287 }
288
289 ff->mrratio=div;
290 //int max=0;
291 for(x=0;x<NCOEFFS>>1;x++)
292 {
293 ff->coeffs_i16[x]=ff->coeffs_i16[NCOEFFS-1-x]=tmp[x] * 65536;
294 ff->coeffs[x]=ff->coeffs[NCOEFFS-1-x]=(float)tmp[x];
295 //if(abs(ff->coeffs_i16[x]) > abs(max)) max = abs(ff->coeffs_i16[x]);
296 }
297 ff->rate=rate;
298
299 ff->imrate = cpuclock / div;
300 ff->lrhfactor = rate / ff->imrate;
301
302 int error;
303 ff->lrh = src_new(srctype, 1, &error);
304
305
306 ff->cpuext = ac_mmflag();
307
308 ff->input_format = FFI_FLOAT;
309
310 //ff->cpuext &= MM_MMX;
311
312 if(ff->cpuext & MM_SSE3)
313 {
314
315 }
316 else if(ff->cpuext & MM_MMX)
317 ff->input_format = FFI_INT16;
318 else if(ff->cpuext & MM_ALTIVEC)
319 ff->input_format = FFI_INT16;
320
321 return(ff);
322 }
323
FESTAFILT_SetLowpass(FESTAFILT * ff,int on,uint32 corner,uint32 order)324 int FESTAFILT_SetLowpass(FESTAFILT *ff, int on, uint32 corner, uint32 order)
325 {
326 //FESTAFILT *ff = fe->apu->ff;
327 char spec[256];
328 char *speca;
329 char *err;
330
331 FreeFid(ff);
332
333 //on = 1;
334 if(on)
335 {
336 //snprintf(spec,256,"HpBuZ%d/%d",2,1000);
337 snprintf(spec,256,"LpBuZ%d/%d",order,corner);
338 speca = spec;
339 //printf("%s\n",spec);
340 // p = "LpBuZ2/5000";
341 //printf("%f, %s\n",ff->imrate,spec);
342 err = fid_parse(ff->imrate, &speca, &ff->fid);
343
344 if(!err)
345 {
346 if(!(ff->fidrun = fid_run_new(ff->fid, &ff->fidfuncp)))
347 {FreeFid(ff); return(0); }
348 if(!(ff->fidbuf = fid_run_newbuf(ff->fidrun)))
349 {FreeFid(ff); return(0); }
350 return(1);
351 }
352 else
353 {
354 ff->fid = 0;
355 return(0);
356 }
357 }
358 return(1);
359 }
360
361
362