1 /* OpenCP Module Player
2  * copyright (c) 2009-2010 Stian Skjelstad <stian@nixia.no>
3  *
4  * Unit-test for "dwmixfa.c"
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include "config.h"
22 #include "types.h"
23 #include <stdio.h>
24 #include "dwmixfa.h"
25 #include "dev/mcp.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #ifdef I386_ASM
29 #include <unistd.h>
30 #include <sys/mman.h>
31 #include "stuff/pagesize.inc.c"
32 #endif
33 
34 static int channelnum;
35 
initAsm(void)36 static int initAsm(void)
37 {
38 #ifdef I386_ASM
39 	/* Self-modifying code needs access to modify it self */
40 	int fd;
41 	char file[128]="/tmp/ocpXXXXXX";
42 	char *start1, *stop1;
43 	int len1;
44 	fd=mkstemp(file);
45 
46 	start1=(void *)start_dwmixfa;
47 	stop1=(void *)stop_dwmixfa;
48 
49 	start1=(char *)(((int)start1)&~(pagesize()-1));
50 	len1=((stop1-start1)+pagesize()-1)& ~(pagesize()-1);
51 	if (write(fd, start1, len1)!=len1)
52 	{
53 		close(fd);
54 		unlink(file);
55 		return 0;
56 	}
57 	if (mmap(start1, len1, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, 0)==MAP_FAILED)
58 	{
59 		perror("mmap()");
60 		close(fd);
61 		unlink(file);
62 		return 0;
63 	}
64 
65 	close(fd);
66 	unlink(file);
67 #endif
68 
69 	return 1;
70 }
71 
calcinterpoltab(void)72 static void calcinterpoltab(void)
73 {
74 	int i;
75 	for (i=0; i<256; i++)
76 	{
77 		float x1=i/256.0;
78 		float x2=x1*x1;
79 		float x3=x1*x1*x1;
80 		dwmixfa_state.ct0[i]=-0.5*x3+x2-0.5*x1;
81 		dwmixfa_state.ct1[i]=1.5*x3-2.5*x2+1;
82 		dwmixfa_state.ct2[i]=-1.5*x3+2*x2+0.5*x1;
83 		dwmixfa_state.ct3[i]=0.5*x3-0.5*x2;
84 	};
85 }
86 
OpenPlayer(int chan)87 static void OpenPlayer(int chan)
88 {
89 	/*
90 	uint32_t currentrate;
91 	uint16_t mixfate;
92 	*/
93 	int i;
94 
95 	/* playsamps=pausesamps=0; not needed, since we don't need to track time */
96 
97 	/*
98 	currentrate=mcpMixProcRate/chan;
99 	mixfate=(currentrate>mcpMixMaxRate)?mcpMixMaxRate:currentrate;
100 	plrSetOptions(mixfate, mcpMixOpt);
101 
102 	We don't care about tracking output rate
103 	*/
104 
105 	if (!(dwmixfa_state.tempbuf=malloc(sizeof(float)*(MIXF_MIXBUFLEN<<1))))
106 		exit(1);
107 	/*
108 	Don't think I need this
109 	if (!mixInit(GetMixChannel, 0, chan, amplify))
110 		return 0;
111 	*/
112 
113 	for (i=0; i<chan; i++)
114 	{
115 		dwmixfa_state.voiceflags[i]=0;
116 	}
117 
118 	/*stereo=(plrOpt&PLR_STEREO)?1:0;*/
119 	/*bit16=(plrOpt&PLR_16BIT)?1:0;*/
120 	/*signedout=(plrOpt&PLR_SIGNEDOUT)?1:0;*/
121 	/*reversestereo=!!(plrOpt&PLR_REVERSESTEREO);*/
122 	dwmixfa_state.samprate=/*plrRate*/44100;
123 /*
124 	bufpos=0;
125 	dopause=0;
126 	orgspeed=12800;
127 */
128 	channelnum=chan;
129 /*
130 	mcpNChan=chan;
131 	mcpIdle=Idle;
132 
133 	isstereo=stereo;
134 	outfmt=(bit16<<1)|(!signedout);*/
135 	dwmixfa_state.nvoices=channelnum;
136 
137 	prepare_mixer();
138 
139 	/*calcspeed();*/
140 	   /*/  playerproc();*/  /* some timing is wrong here! */
141 	/* tickwidth=newtickwidth; */
142 	/* tickplayed=0; */
143 	/* cmdtimerpos=0; */
144 /*
145 	if (!pollInit(timerproc))
146 	{
147 		mcpNChan=0;
148 		mcpIdle=0;
149 		plrClosePlayer();
150 		mixClose();
151 		return 0;
152 	}
153 	{
154 		struct mixfpostprocregstruct *mode;
155 
156 		for (mode=postprocs; mode; mode=mode->next)
157 			if (mode->Init) mode->Init(samprate, stereo);
158 	}
159 */
160 }
161 
ClosePlayer()162 static void ClosePlayer()
163 {
164 /*
165 	  struct mixfpostprocregstruct *mode;
166 
167 	  mcpNChan=0;
168 	  mcpIdle=0;
169 
170 	  pollClose();
171 
172 	  plrClosePlayer();
173 
174 	  channelnum=0;
175 
176 	  mixClose();
177 
178 	  for (mode=postprocs; mode; mode=mode->next)
179 		  if (mode->Close) mode->Close();
180 */
181 	  free(dwmixfa_state.tempbuf);
182 }
183 
main(int argc,char * argv[])184 int main(int argc, char *argv[])
185 {
186 	float sample_1[] = {12345.0f, 23451.1234f, 30000.543f, 32767.0f, 1023.09f, -5435.05f, -32768.0f, -16000.02f}; /* normalized around 32767 and -32768 */
187 	int16_t output[1024];
188 /* INIT START */
189 	initAsm();
190 
191 	/* volramp=!!(dev->opt&MIXF_VOLRAMP); */
192 	/* declick=!!(dev->opt&MIXF_DECLICK); */
193 
194 	calcinterpoltab();
195 
196 	/* amplify=65535; */
197 	/* relspeed=256; */
198 	/* relpitch=256; */
199 	/* interpolation=0; */
200 	/* mastervol=64; */
201 	/* masterbal=0; */
202 	/* masterpan=0; */
203 	/* mastersrnd=0; */
204 	/* channelnum=0; */
205 /* INIT DONE */
206 
207 /* LOAD */
208 	/* LoadSamples (sampleinfo_1, 1); */
209 	/*
210 		samples=sampleinfo_1; */
211 	/*
212 		samplenum=1; */
213 
214 	prepare_mixer();
215 
216 	OpenPlayer(1);
217 
218 	memset(output, 1, sizeof(output));
219 	dwmixfa_state.outbuf=output+2;
220 	dwmixfa_state.nsamples=308;//508;
221 
222 	dwmixfa_state.isstereo=0; //1;
223 
224 	dwmixfa_state.voiceflags[0] = MIXF_PLAYING|MIXF_LOOPED; /* this is so broken! */
225 
226 	dwmixfa_state.freqf[0]=0x3a987654; /* pitch */
227 	dwmixfa_state.freqw[0]=0x00000000; /* pitch */
228 
229 	dwmixfa_state.fl1[0]=0; /* reset filter */
230 	dwmixfa_state.fb1[0]=0; /* reset feilter */
231 
232 	dwmixfa_state.ffreq[0] = 1;      /* filter frequency (0<=x<=1) TODO, needs testing / study */
233 	dwmixfa_state.freso[0] = 0;      /* filter resonance (0<=x<1)  TODO, needs testing / study*/
234 
235 	dwmixfa_state.smpposf[0]=0;
236 	dwmixfa_state.smpposw[0]=sample_1;
237 
238 	dwmixfa_state.looplen[0]=4;
239 	dwmixfa_state.loopend[0]=&sample_1[7];
240 
241 	dwmixfa_state.volleft[0]=0.125f;
242 	dwmixfa_state.volright[0]=0.125f;
243 	dwmixfa_state.rampleft[0]=0.0f;
244 	dwmixfa_state.rampright[0]=0.0f;
245 
246 	dwmixfa_state.fadeleft=0.5f;
247 	dwmixfa_state.faderight=-0.5f;
248 
249 	dwmixfa_state.outfmt=2; /* 2 = 16bit, 1 = unsigned, can be or'ed */
250 
251 	//".long clip_8s, clip_8u, clip_16s, clip_16u\n"
252 
253 /*
254 	voll=1.0f;
255 	volr=1.0f;
256 		This is output from getchanvol probably
257 */
258 
259 	mixer();
260 
261 	{
262 		int i;
263 		fprintf(stderr, "output: ");
264 		for (i=0;i<512;i++)
265 			fprintf(stderr, "[%d %d]", output[i*2], output[i*2+1]);
266 		fprintf(stderr, "\n");
267 	}
268 
269 	fprintf(stderr, "smppos: %u.%u\n", (unsigned int)(dwmixfa_state.smpposw[0]-sample_1), dwmixfa_state.smpposf[0]);
270 
271 	ClosePlayer();
272 
273 	return 0;
274 }
275