Manual: Fix part 1 of FS#11874 - touchscreen region in the manual isn't 100% correct.
[kugel-rb.git] / apps / plugins / mikmod / virtch_common.c
blob522f4509f0922c76db7049c310ab1eecbc600f84
1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 for complete list.
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.
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.
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.
21 /*==============================================================================
23 $Id: virtch_common.c,v 1.2 2005/03/30 19:11:50 realtech Exp $
25 Common source parts between the two software mixers.
26 This file is probably the ugliest part of libmikmod...
28 ==============================================================================*/
30 #ifndef _IN_VIRTCH_
32 #include "mikmod_internals.h"
34 extern int VC1_Init(void);
35 //extern int VC2_Init(void);
36 static int (*VC_Init_ptr)(void)=VC1_Init;
37 extern void VC1_Exit(void);
38 //extern void VC2_Exit(void);
39 static void (*VC_Exit_ptr)(void)=VC1_Exit;
40 extern int VC1_SetNumVoices(void);
41 //extern int VC2_SetNumVoices(void);
42 static int (*VC_SetNumVoices_ptr)(void);
43 extern ULONG VC1_SampleSpace(int);
44 //extern ULONG VC2_SampleSpace(int);
45 static ULONG (*VC_SampleSpace_ptr)(int);
46 extern ULONG VC1_SampleLength(int,SAMPLE*);
47 //extern ULONG VC2_SampleLength(int,SAMPLE*);
48 static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*);
50 extern int VC1_PlayStart(void);
51 //extern int VC2_PlayStart(void);
52 static int (*VC_PlayStart_ptr)(void);
53 extern void VC1_PlayStop(void);
54 extern void VC2_PlayStop(void);
55 static void (*VC_PlayStop_ptr)(void);
57 extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
58 //extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
59 static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int);
60 extern void VC1_SampleUnload(SWORD);
61 //extern void VC2_SampleUnload(SWORD);
62 static void (*VC_SampleUnload_ptr)(SWORD);
64 extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
65 //extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
66 static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG);
67 extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
68 //extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
69 static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG);
71 extern void VC1_VoiceSetVolume(UBYTE,UWORD);
72 //extern void VC2_VoiceSetVolume(UBYTE,UWORD);
73 static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD);
74 extern UWORD VC1_VoiceGetVolume(UBYTE);
75 //extern UWORD VC2_VoiceGetVolume(UBYTE);
76 static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE);
77 extern void VC1_VoiceSetFrequency(UBYTE,ULONG);
78 //extern void VC2_VoiceSetFrequency(UBYTE,ULONG);
79 static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG);
80 extern ULONG VC1_VoiceGetFrequency(UBYTE);
81 //extern ULONG VC2_VoiceGetFrequency(UBYTE);
82 static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE);
83 extern void VC1_VoiceSetPanning(UBYTE,ULONG);
84 //extern void VC2_VoiceSetPanning(UBYTE,ULONG);
85 static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG);
86 extern ULONG VC1_VoiceGetPanning(UBYTE);
87 //extern ULONG VC2_VoiceGetPanning(UBYTE);
88 static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE);
89 extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
90 //extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
91 static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
93 extern void VC1_VoiceStop(UBYTE);
94 //extern void VC2_VoiceStop(UBYTE);
95 static void (*VC_VoiceStop_ptr)(UBYTE);
96 extern int VC1_VoiceStopped(UBYTE);
97 //extern int VC2_VoiceStopped(UBYTE);
98 static int (*VC_VoiceStopped_ptr)(UBYTE);
99 extern SLONG VC1_VoiceGetPosition(UBYTE);
100 //extern SLONG VC2_VoiceGetPosition(UBYTE);
101 static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE);
102 extern ULONG VC1_VoiceRealVolume(UBYTE);
103 //extern ULONG VC2_VoiceRealVolume(UBYTE);
104 static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE);
106 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
107 #define VC_PROC0(suffix) \
108 MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); }
110 #define VC_FUNC0(suffix,ret) \
111 MIKMODAPI ret VC_##suffix (void) { return VC_##suffix##_ptr(); }
113 #define VC_PROC1(suffix,typ1) \
114 MIKMODAPI void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); }
116 #define VC_FUNC1(suffix,ret,typ1) \
117 MIKMODAPI ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); }
119 #define VC_PROC2(suffix,typ1,typ2) \
120 MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
122 #define VC_FUNC2(suffix,ret,typ1,typ2) \
123 MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
124 #else
125 #define VC_PROC0(suffix) \
126 MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); }
128 #define VC_FUNC0(suffix,ret) \
129 MIKMODAPI ret VC_/**/suffix (void) { return VC_/**/suffix/**/_ptr(); }
131 #define VC_PROC1(suffix,typ1) \
132 MIKMODAPI void VC_/**/suffix (typ1 a) { VC_/**/suffix/**/_ptr(a); }
134 #define VC_FUNC1(suffix,ret,typ1) \
135 MIKMODAPI ret VC_/**/suffix (typ1 a) { return VC_/**/suffix/**/_ptr(a); }
137 #define VC_PROC2(suffix,typ1,typ2) \
138 MIKMODAPI void VC_/**/suffix (typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); }
140 #define VC_FUNC2(suffix,ret,typ1,typ2) \
141 MIKMODAPI ret VC_/**/suffix (typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); }
142 #endif
144 VC_FUNC0(Init,int)
145 VC_PROC0(Exit)
146 VC_FUNC0(SetNumVoices,int)
147 VC_FUNC1(SampleSpace,ULONG,int)
148 VC_FUNC2(SampleLength,ULONG,int,SAMPLE*)
149 VC_FUNC0(PlayStart,int)
150 VC_PROC0(PlayStop)
151 VC_FUNC2(SampleLoad,SWORD,struct SAMPLOAD*,int)
152 VC_PROC1(SampleUnload,SWORD)
153 VC_FUNC2(WriteBytes,ULONG,SBYTE*,ULONG)
154 VC_FUNC2(SilenceBytes,ULONG,SBYTE*,ULONG)
155 VC_PROC2(VoiceSetVolume,UBYTE,UWORD)
156 VC_FUNC1(VoiceGetVolume,UWORD,UBYTE)
157 VC_PROC2(VoiceSetFrequency,UBYTE,ULONG)
158 VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE)
159 VC_PROC2(VoiceSetPanning,UBYTE,ULONG)
160 VC_FUNC1(VoiceGetPanning,ULONG,UBYTE)
162 void 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); }
165 VC_PROC1(VoiceStop,UBYTE)
166 VC_FUNC1(VoiceStopped,int,UBYTE)
167 VC_FUNC1(VoiceGetPosition,SLONG,UBYTE)
168 VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
170 void VC_SetupPointers(void)
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 {
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;
223 #else
225 #ifndef _VIRTCH_COMMON_
226 #define _VIRTCH_COMMON_
228 static ULONG samples2bytes(ULONG samples)
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;
236 static ULONG bytes2samples(ULONG bytes)
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;
244 /* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
245 how the buffer is filled) */
246 ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
248 todo=samples2bytes(bytes2samples(todo));
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);
258 return todo;
261 void VC1_WriteSamples(SBYTE*,ULONG);
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). */
266 ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
268 if(!vc_softchn)
269 return VC1_SilenceBytes(buf,todo);
271 todo = bytes2samples(todo);
272 VC1_WriteSamples(buf,todo);
274 return samples2bytes(todo);
277 void VC1_Exit(void)
279 if(vc_tickbuf) MikMod_free(vc_tickbuf);
280 if(vinf) MikMod_free(vinf);
281 if(Samples) MikMod_free(Samples);
283 vc_tickbuf = NULL;
284 vinf = NULL;
285 Samples = NULL;
287 VC_SetupPointers();
290 UWORD VC1_VoiceGetVolume(UBYTE voice)
292 return vinf[voice].vol;
295 ULONG VC1_VoiceGetPanning(UBYTE voice)
297 return vinf[voice].pan;
300 void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)
302 vinf[voice].frq=frq;
305 ULONG VC1_VoiceGetFrequency(UBYTE voice)
307 return vinf[voice].frq;
310 void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
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;
321 void VC1_VoiceStop(UBYTE voice)
323 vinf[voice].active = 0;
326 int VC1_VoiceStopped(UBYTE voice)
328 return(vinf[voice].active==0);
331 SLONG VC1_VoiceGetPosition(UBYTE voice)
333 return (SLONG)(vinf[voice].current>>FRACBITS);
336 void VC1_VoiceSetVolume(UBYTE voice,UWORD vol)
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;
344 void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
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;
352 /*========== External mixer interface */
354 void VC1_SampleUnload(SWORD handle)
356 if (handle<MAXSAMPLEHANDLES) {
357 if (Samples[handle])
358 MikMod_free(Samples[handle]);
359 Samples[handle]=NULL;
363 SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
365 SAMPLE *s = sload->sample;
366 int handle;
367 ULONG t, length,loopstart,loopend;
369 if(type==MD_HARDWARE) return -1;
371 /* Find empty slot to put sample address in */
372 for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
373 if(!Samples[handle]) break;
375 if(handle==MAXSAMPLEHANDLES) {
376 _mm_errno = MMERR_OUT_OF_HANDLES;
377 return -1;
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;
386 length = s->length;
387 loopstart = s->loopstart;
388 loopend = s->loopend;
390 SL_SampleSigned(sload);
391 SL_Sample8to16(sload);
393 if(!(Samples[handle]=(SWORD*)MikMod_malloc((length+20)<<1))) {
394 _mm_errno = MMERR_SAMPLE_TOO_BIG;
395 return -1;
398 /* read sample into buffer */
399 if (SL_Load(Samples[handle],sload,length))
400 return -1;
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;
414 return handle;
417 ULONG VC1_SampleSpace(int type)
419 return vc_memory;
422 ULONG VC1_SampleLength(int type,SAMPLE* s)
424 if (!s) return 0;
426 return (s->length*((s->flags&SF_16BITS)?2:1))+16;
429 ULONG VC1_VoiceRealVolume(UBYTE voice)
431 ULONG i,s,size;
432 int k,j;
433 SWORD *smp;
434 SLONG t;
436 t = (SLONG)(vinf[voice].current>>FRACBITS);
437 if(!vinf[voice].active) return 0;
439 s = vinf[voice].handle;
440 size = vinf[voice].size;
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;
447 i &= ~1; /* make sure it's EVEN. */
449 smp = &Samples[s][t];
450 for(;i;i--,smp++) {
451 if(k<*smp) k = *smp;
452 if(j>*smp) j = *smp;
454 return abs(k-j);
458 #endif
460 MikMod_callback_t vc_callback;
462 #endif
464 /* ex:set ts=4: */