1 /*	MikMod sound library
2 	(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 	for complete list.
4 
5 	This library is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU Library General Public License as
7 	published by the Free Software Foundation; either version 2 of
8 	the License, or (at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU Library General Public License for more details.
14 
15 	You should have received a copy of the GNU Library General Public
16 	License along with this library; if not, write to the Free Software
17 	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 	02111-1307, USA.
19 */
20 
21 /*==============================================================================
22 
23   $Id$
24 
25   Common source parts between the two software mixers.
26   This file is probably the ugliest part of libmikmod...
27 
28 ==============================================================================*/
29 
30 #if defined(HAVE_CONFIG_H) && !defined(_IN_VIRTCH_) /* config.h isn't guarded */
31 #include "config.h"
32 #endif
33 #include "mikmod_internals.h"
34 
35 #ifndef NO_HQMIXER
36 extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
37 extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
38 extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
39 extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
40 extern void  VC1_Exit(void);
41 extern void  VC2_Exit(void);
42 extern UWORD VC1_VoiceGetVolume(UBYTE);
43 extern UWORD VC2_VoiceGetVolume(UBYTE);
44 extern ULONG VC1_VoiceGetPanning(UBYTE);
45 extern ULONG VC2_VoiceGetPanning(UBYTE);
46 extern void  VC1_VoiceSetFrequency(UBYTE,ULONG);
47 extern void  VC2_VoiceSetFrequency(UBYTE,ULONG);
48 extern ULONG VC1_VoiceGetFrequency(UBYTE);
49 extern ULONG VC2_VoiceGetFrequency(UBYTE);
50 extern void  VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
51 extern void  VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
52 extern void  VC1_VoiceStop(UBYTE);
53 extern void  VC2_VoiceStop(UBYTE);
54 extern BOOL  VC1_VoiceStopped(UBYTE);
55 extern BOOL  VC2_VoiceStopped(UBYTE);
56 extern SLONG VC1_VoiceGetPosition(UBYTE);
57 extern SLONG VC2_VoiceGetPosition(UBYTE);
58 extern void  VC1_VoiceSetVolume(UBYTE,UWORD);
59 extern void  VC2_VoiceSetVolume(UBYTE,UWORD);
60 extern void  VC1_VoiceSetPanning(UBYTE,ULONG);
61 extern void  VC2_VoiceSetPanning(UBYTE,ULONG);
62 extern void  VC1_SampleUnload(SWORD);
63 extern void  VC2_SampleUnload(SWORD);
64 extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
65 extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
66 extern ULONG VC1_SampleSpace(int);
67 extern ULONG VC2_SampleSpace(int);
68 extern ULONG VC1_SampleLength(int,SAMPLE*);
69 extern ULONG VC2_SampleLength(int,SAMPLE*);
70 extern ULONG VC1_VoiceRealVolume(UBYTE);
71 extern ULONG VC2_VoiceRealVolume(UBYTE);
72 #endif
73 
74 
75 #ifndef _IN_VIRTCH_
76 
77 #ifndef NO_HQMIXER
78 extern int   VC1_Init(void);
79 extern int   VC2_Init(void);
80 static int  (*VC_Init_ptr)(void)=VC1_Init;
81 static void (*VC_Exit_ptr)(void)=VC1_Exit;
82 extern int   VC1_SetNumVoices(void);
83 extern int   VC2_SetNumVoices(void);
84 static int  (*VC_SetNumVoices_ptr)(void);
85 static ULONG (*VC_SampleSpace_ptr)(int);
86 static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*);
87 
88 extern int   VC2_PlayStart(void);
89 static int  (*VC_PlayStart_ptr)(void);
90 extern void  VC2_PlayStop(void);
91 static void (*VC_PlayStop_ptr)(void);
92 
93 static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int);
94 static void (*VC_SampleUnload_ptr)(SWORD);
95 
96 static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG);
97 static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG);
98 
99 static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD);
100 static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE);
101 static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG);
102 static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE);
103 static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG);
104 static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE);
105 static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
106 
107 static void (*VC_VoiceStop_ptr)(UBYTE);
108 static BOOL (*VC_VoiceStopped_ptr)(UBYTE);
109 static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE);
110 static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE);
111 
112 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
113 #define VC_PROC0(suffix) \
114 MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); }
115 
116 #define VC_FUNC0(suffix,ret) \
117 MIKMODAPI ret VC_##suffix (void) { return VC_##suffix##_ptr(); }
118 
119 #define VC_PROC1(suffix,typ1) \
120 MIKMODAPI void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); }
121 
122 #define VC_FUNC1(suffix,ret,typ1) \
123 MIKMODAPI ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); }
124 
125 #define VC_PROC2(suffix,typ1,typ2) \
126 MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
127 
128 #define VC_FUNC2(suffix,ret,typ1,typ2) \
129 MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
130 
131 #else
132 
133 #define VC_PROC0(suffix) \
134 MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); }
135 
136 #define VC_FUNC0(suffix,ret) \
137 MIKMODAPI ret VC_/**/suffix (void) { return VC_/**/suffix/**/_ptr(); }
138 
139 #define VC_PROC1(suffix,typ1) \
140 MIKMODAPI void VC_/**/suffix (typ1 a) { VC_/**/suffix/**/_ptr(a); }
141 
142 #define VC_FUNC1(suffix,ret,typ1) \
143 MIKMODAPI ret VC_/**/suffix (typ1 a) { return VC_/**/suffix/**/_ptr(a); }
144 
145 #define VC_PROC2(suffix,typ1,typ2) \
146 MIKMODAPI void VC_/**/suffix (typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); }
147 
148 #define VC_FUNC2(suffix,ret,typ1,typ2) \
149 MIKMODAPI ret VC_/**/suffix (typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); }
150 #endif
151 
VC_FUNC0(Init,int)152 VC_FUNC0(Init,int)
153 VC_PROC0(Exit)
154 VC_FUNC0(SetNumVoices,int)
155 VC_FUNC1(SampleSpace,ULONG,int)
156 VC_FUNC2(SampleLength,ULONG,int,SAMPLE*)
157 VC_FUNC0(PlayStart,int)
158 VC_PROC0(PlayStop)
159 VC_FUNC2(SampleLoad,SWORD,struct SAMPLOAD*,int)
160 VC_PROC1(SampleUnload,SWORD)
161 VC_FUNC2(WriteBytes,ULONG,SBYTE*,ULONG)
162 VC_FUNC2(SilenceBytes,ULONG,SBYTE*,ULONG)
163 VC_PROC2(VoiceSetVolume,UBYTE,UWORD)
164 VC_FUNC1(VoiceGetVolume,UWORD,UBYTE)
165 VC_PROC2(VoiceSetFrequency,UBYTE,ULONG)
166 VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE)
167 VC_PROC2(VoiceSetPanning,UBYTE,ULONG)
168 VC_FUNC1(VoiceGetPanning,ULONG,UBYTE)
169 
170 void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g) {
171      VC_VoicePlay_ptr(a,b,c,d,e,f,g);
172 }
173 
VC_PROC1(VoiceStop,UBYTE)174 VC_PROC1(VoiceStop,UBYTE)
175 VC_FUNC1(VoiceStopped,BOOL,UBYTE)
176 VC_FUNC1(VoiceGetPosition,SLONG,UBYTE)
177 VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
178 
179 void VC_SetupPointers(void)
180 {
181 	if (md_mode&DMODE_HQMIXER) {
182 		VC_Init_ptr=VC2_Init;
183 		VC_Exit_ptr=VC2_Exit;
184 		VC_SetNumVoices_ptr=VC2_SetNumVoices;
185 		VC_SampleSpace_ptr=VC2_SampleSpace;
186 		VC_SampleLength_ptr=VC2_SampleLength;
187 		VC_PlayStart_ptr=VC2_PlayStart;
188 		VC_PlayStop_ptr=VC2_PlayStop;
189 		VC_SampleLoad_ptr=VC2_SampleLoad;
190 		VC_SampleUnload_ptr=VC2_SampleUnload;
191 		VC_WriteBytes_ptr=VC2_WriteBytes;
192 		VC_SilenceBytes_ptr=VC2_SilenceBytes;
193 		VC_VoiceSetVolume_ptr=VC2_VoiceSetVolume;
194 		VC_VoiceGetVolume_ptr=VC2_VoiceGetVolume;
195 		VC_VoiceSetFrequency_ptr=VC2_VoiceSetFrequency;
196 		VC_VoiceGetFrequency_ptr=VC2_VoiceGetFrequency;
197 		VC_VoiceSetPanning_ptr=VC2_VoiceSetPanning;
198 		VC_VoiceGetPanning_ptr=VC2_VoiceGetPanning;
199 		VC_VoicePlay_ptr=VC2_VoicePlay;
200 		VC_VoiceStop_ptr=VC2_VoiceStop;
201 		VC_VoiceStopped_ptr=VC2_VoiceStopped;
202 		VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition;
203 		VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume;
204 	} else {
205 		VC_Init_ptr=VC1_Init;
206 		VC_Exit_ptr=VC1_Exit;
207 		VC_SetNumVoices_ptr=VC1_SetNumVoices;
208 		VC_SampleSpace_ptr=VC1_SampleSpace;
209 		VC_SampleLength_ptr=VC1_SampleLength;
210 		VC_PlayStart_ptr=VC1_PlayStart;
211 		VC_PlayStop_ptr=VC1_PlayStop;
212 		VC_SampleLoad_ptr=VC1_SampleLoad;
213 		VC_SampleUnload_ptr=VC1_SampleUnload;
214 		VC_WriteBytes_ptr=VC1_WriteBytes;
215 		VC_SilenceBytes_ptr=VC1_SilenceBytes;
216 		VC_VoiceSetVolume_ptr=VC1_VoiceSetVolume;
217 		VC_VoiceGetVolume_ptr=VC1_VoiceGetVolume;
218 		VC_VoiceSetFrequency_ptr=VC1_VoiceSetFrequency;
219 		VC_VoiceGetFrequency_ptr=VC1_VoiceGetFrequency;
220 		VC_VoiceSetPanning_ptr=VC1_VoiceSetPanning;
221 		VC_VoiceGetPanning_ptr=VC1_VoiceGetPanning;
222 		VC_VoicePlay_ptr=VC1_VoicePlay;
223 		VC_VoiceStop_ptr=VC1_VoiceStop;
224 		VC_VoiceStopped_ptr=VC1_VoiceStopped;
225 		VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition;
226 		VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume;
227 	}
228 }
229 #endif/* !NO_HQMIXER */
230 
231 #else /* _IN_VIRTCH_ */
232 
233 #ifndef _VIRTCH_COMMON_
234 #define _VIRTCH_COMMON_
235 
samples2bytes(ULONG samples)236 static ULONG samples2bytes(ULONG samples)
237 {
238 	if(vc_mode & DMODE_FLOAT) samples <<= 2;
239 	else if(vc_mode & DMODE_16BITS) samples <<= 1;
240 	if(vc_mode & DMODE_STEREO) samples <<= 1;
241 	return samples;
242 }
243 
bytes2samples(ULONG bytes)244 static ULONG bytes2samples(ULONG bytes)
245 {
246 	if(vc_mode & DMODE_FLOAT) bytes >>= 2;
247 	else if(vc_mode & DMODE_16BITS) bytes >>= 1;
248 	if(vc_mode & DMODE_STEREO) bytes >>= 1;
249 	return bytes;
250 }
251 
252 /* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
253    how the buffer is filled) */
VC1_SilenceBytes(SBYTE * buf,ULONG todo)254 ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
255 {
256 	todo=samples2bytes(bytes2samples(todo));
257 
258 	/* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
259 	if(vc_mode &(DMODE_16BITS|DMODE_FLOAT))
260 		memset(buf,0,todo);
261 	else
262 		memset(buf,0x80,todo);
263 
264 	return todo;
265 }
266 
267 void VC1_WriteSamples(SBYTE*,ULONG);
268 
269 /* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
270    actually written to 'buf' (which is rounded to number of samples that fit
271    into 'todo' bytes). */
VC1_WriteBytes(SBYTE * buf,ULONG todo)272 ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
273 {
274 	if(!vc_softchn)
275 		return VC1_SilenceBytes(buf,todo);
276 
277 	todo = bytes2samples(todo);
278 	VC1_WriteSamples(buf,todo);
279 
280 	return samples2bytes(todo);
281 }
282 
VC1_Exit(void)283 void VC1_Exit(void)
284 {
285 	MikMod_free(vinf);
286 	MikMod_afree(vc_tickbuf);
287 	MikMod_afree(Samples);
288 
289 	vc_tickbuf = NULL;
290 	vinf = NULL;
291 	Samples = NULL;
292 
293 	VC_SetupPointers();
294 }
295 
VC1_VoiceGetVolume(UBYTE voice)296 UWORD VC1_VoiceGetVolume(UBYTE voice)
297 {
298 	return vinf[voice].vol;
299 }
300 
VC1_VoiceGetPanning(UBYTE voice)301 ULONG VC1_VoiceGetPanning(UBYTE voice)
302 {
303 	return vinf[voice].pan;
304 }
305 
VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)306 void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)
307 {
308 	vinf[voice].frq=frq;
309 }
310 
VC1_VoiceGetFrequency(UBYTE voice)311 ULONG VC1_VoiceGetFrequency(UBYTE voice)
312 {
313 	return vinf[voice].frq;
314 }
315 
VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)316 void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
317 {
318 	vinf[voice].flags  = flags;
319 	vinf[voice].handle = handle;
320 	vinf[voice].start  = start;
321 	vinf[voice].size   = size;
322 	vinf[voice].reppos = reppos;
323 	vinf[voice].repend = repend;
324 	vinf[voice].kick   = 1;
325 }
326 
VC1_VoiceStop(UBYTE voice)327 void VC1_VoiceStop(UBYTE voice)
328 {
329 	vinf[voice].active = 0;
330 }
331 
VC1_VoiceStopped(UBYTE voice)332 BOOL VC1_VoiceStopped(UBYTE voice)
333 {
334 	return(vinf[voice].active==0);
335 }
336 
VC1_VoiceGetPosition(UBYTE voice)337 SLONG VC1_VoiceGetPosition(UBYTE voice)
338 {
339 	return (SLONG)(vinf[voice].current>>FRACBITS);
340 }
341 
VC1_VoiceSetVolume(UBYTE voice,UWORD vol)342 void VC1_VoiceSetVolume(UBYTE voice,UWORD vol)
343 {
344 	/* protect against clicks if volume variation is too high */
345 	if(abs((int)vinf[voice].vol-(int)vol)>32)
346 		vinf[voice].rampvol=CLICK_BUFFER;
347 	vinf[voice].vol=vol;
348 }
349 
VC1_VoiceSetPanning(UBYTE voice,ULONG pan)350 void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
351 {
352 	/* protect against clicks if panning variation is too high */
353 	if(abs((int)vinf[voice].pan-(int)pan)>48)
354 		vinf[voice].rampvol=CLICK_BUFFER;
355 	vinf[voice].pan=pan;
356 }
357 
358 /*========== External mixer interface */
359 
VC1_SampleUnload(SWORD handle)360 void VC1_SampleUnload(SWORD handle)
361 {
362 	if (Samples && (handle < MAXSAMPLEHANDLES)) {
363 		MikMod_afree(Samples[handle]);
364 		Samples[handle]=NULL;
365 	}
366 }
367 
VC1_SampleLoad(struct SAMPLOAD * sload,int type)368 SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
369 {
370 	SAMPLE *s = sload->sample;
371 	int handle;
372 	ULONG t, length,loopstart,loopend,looplen;
373 
374 	if(type==MD_HARDWARE) return -1;
375 
376 	if(s->length > MAX_SAMPLE_SIZE) {
377 		_mm_errno = MMERR_NOT_A_STREAM; /* better error? */
378 		return -1;
379 	}
380 
381 	/* Find empty slot to put sample address in */
382 	for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
383 		if(!Samples[handle]) break;
384 
385 	if(handle==MAXSAMPLEHANDLES) {
386 		_mm_errno = MMERR_OUT_OF_HANDLES;
387 		return -1;
388 	}
389 
390 	/* Reality check for loop settings */
391 	if (s->loopend > s->length)
392 		s->loopend = s->length;
393 	if (s->loopstart >= s->loopend)
394 		s->flags &= ~SF_LOOP;
395 
396 	length    = s->length;
397 	loopstart = s->loopstart;
398 	loopend   = s->loopend;
399 
400 	SL_SampleSigned(sload);
401 	SL_Sample8to16(sload);
402 
403 	if(!(Samples[handle]=(SWORD*)MikMod_amalloc((length+20)<<1))) {
404 		_mm_errno = MMERR_SAMPLE_TOO_BIG;
405 		return -1;
406 	}
407 
408 	/* read sample into buffer */
409 	if (SL_Load(Samples[handle],sload,length)) {
410 		MikMod_afree(Samples[handle]);
411 		Samples[handle]=NULL;
412 		return -1;
413 	}
414 
415 	/* Unclick sample */
416 	if(s->flags & SF_LOOP) {
417 		looplen = loopend - loopstart;/* handle short samples */
418 		if(s->flags & SF_BIDI)
419 			for(t=0;t<16 && t<looplen;t++)
420 				Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
421 		else
422 			for(t=0;t<16 && t<looplen;t++)
423 				Samples[handle][loopend+t]=Samples[handle][t+loopstart];
424 	} else
425 		for(t=0;t<16;t++)
426 			Samples[handle][t+length]=0;
427 
428 	return handle;
429 }
430 
VC1_SampleSpace(int type)431 ULONG VC1_SampleSpace(int type)
432 {
433 	return vc_memory;
434 }
435 
VC1_SampleLength(int type,SAMPLE * s)436 ULONG VC1_SampleLength(int type,SAMPLE* s)
437 {
438 	if (!s) return 0;
439 
440 	return (s->length*((s->flags&SF_16BITS)?2:1))+16;
441 }
442 
VC1_VoiceRealVolume(UBYTE voice)443 ULONG VC1_VoiceRealVolume(UBYTE voice)
444 {
445 	ULONG i,s,size;
446 	int k,j;
447 	SWORD *smp;
448 	SLONG t;
449 
450 	t = (SLONG)(vinf[voice].current>>FRACBITS);
451 	if(!vinf[voice].active) return 0;
452 
453 	s = vinf[voice].handle;
454 	size = vinf[voice].size;
455 
456 	i=64; t-=64; k=0; j=0;
457 	if(i>size) i = size;
458 	if(t<0) t = 0;
459 	if(t+i > size) t = size-i;
460 
461 	i &= ~1;  /* make sure it's EVEN. */
462 
463 	smp = &Samples[s][t];
464 	for(;i;i--,smp++) {
465 		if(k<*smp) k = *smp;
466 		if(j>*smp) j = *smp;
467 	}
468 	return abs(k-j);
469 }
470 
471 #endif /* _VIRTCH_COMMON_ */
472 
473 #endif /* _IN_VIRTCH_ */
474 
475 /* ex:set ts=4: */
476