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