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