1
/* MikMod sound library
2
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
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
21
/*==============================================================================
23
$Id: virtch_common.c,v 1.2 2001/12/17 02:39:12 slouken Exp $
25
Common source parts between the two software mixers.
26
This file is probably the ugliest part of libmikmod...
28
==============================================================================*/
32
#include "mikmod_internals.h"
34
extern BOOL VC1_Init(void);
35
extern BOOL VC2_Init(void);
36
static BOOL (*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 BOOL VC1_SetNumVoices(void);
41
extern BOOL VC2_SetNumVoices(void);
42
static BOOL (*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 BOOL VC1_PlayStart(void);
51
extern BOOL VC2_PlayStart(void);
52
static BOOL (*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 BOOL VC1_VoiceStopped(UBYTE);
97
extern BOOL VC2_VoiceStopped(UBYTE);
98
static BOOL (*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);
107
#define VC_PROC0(suffix) \
108
void VC_##suffix (void) { VC_##suffix##_ptr(); }
110
#define VC_FUNC0(suffix,ret) \
111
ret VC_##suffix (void) { return VC_##suffix##_ptr(); }
113
#define VC_PROC1(suffix,typ1) \
114
void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); }
116
#define VC_FUNC1(suffix,ret,typ1) \
117
ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); }
119
#define VC_PROC2(suffix,typ1,typ2) \
120
void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
122
#define VC_FUNC2(suffix,ret,typ1,typ2) \
123
ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
125
#define VC_PROC0(suffix) \
126
void VC_/**/suffix/**/(void) { VC_/**/suffix/**/_ptr(); }
128
#define VC_FUNC0(suffix,ret) \
129
ret VC_/**/suffix/**/(void) { return VC_/**/suffix/**/_ptr(); }
131
#define VC_PROC1(suffix,typ1) \
132
void VC_/**/suffix/**/(typ1 a) { VC_/**/suffix/**/_ptr(a); }
134
#define VC_FUNC1(suffix,ret,typ1) \
135
ret VC_/**/suffix/**/(typ1 a) { return VC_/**/suffix/**/_ptr(a); }
137
#define VC_PROC2(suffix,typ1,typ2) \
138
void VC_/**/suffix/**/(typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); }
140
#define VC_FUNC2(suffix,ret,typ1,typ2) \
141
ret VC_/**/suffix/**/(typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); }
146
VC_FUNC0(SetNumVoices,BOOL)
147
VC_FUNC1(SampleSpace,ULONG,int)
148
VC_FUNC2(SampleLength,ULONG,int,SAMPLE*)
149
VC_FUNC0(PlayStart,BOOL)
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,BOOL,UBYTE)
167
VC_FUNC1(VoiceGetPosition,SLONG,UBYTE)
168
VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
170
void VC_SetupPointers(void)
172
if (md_mode&DMODE_HQMIXER) {
173
VC_Init_ptr=VC2_Init;
174
VC_Exit_ptr=VC2_Exit;
175
VC_SetNumVoices_ptr=VC2_SetNumVoices;
176
VC_SampleSpace_ptr=VC2_SampleSpace;
177
VC_SampleLength_ptr=VC2_SampleLength;
178
VC_PlayStart_ptr=VC2_PlayStart;
179
VC_PlayStop_ptr=VC2_PlayStop;
180
VC_SampleLoad_ptr=VC2_SampleLoad;
181
VC_SampleUnload_ptr=VC2_SampleUnload;
182
VC_WriteBytes_ptr=VC2_WriteBytes;
183
VC_SilenceBytes_ptr=VC2_SilenceBytes;
184
VC_VoiceSetVolume_ptr=VC2_VoiceSetVolume;
185
VC_VoiceGetVolume_ptr=VC2_VoiceGetVolume;
186
VC_VoiceSetFrequency_ptr=VC2_VoiceSetFrequency;
187
VC_VoiceGetFrequency_ptr=VC2_VoiceGetFrequency;
188
VC_VoiceSetPanning_ptr=VC2_VoiceSetPanning;
189
VC_VoiceGetPanning_ptr=VC2_VoiceGetPanning;
190
VC_VoicePlay_ptr=VC2_VoicePlay;
191
VC_VoiceStop_ptr=VC2_VoiceStop;
192
VC_VoiceStopped_ptr=VC2_VoiceStopped;
193
VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition;
194
VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume;
196
VC_Init_ptr=VC1_Init;
197
VC_Exit_ptr=VC1_Exit;
198
VC_SetNumVoices_ptr=VC1_SetNumVoices;
199
VC_SampleSpace_ptr=VC1_SampleSpace;
200
VC_SampleLength_ptr=VC1_SampleLength;
201
VC_PlayStart_ptr=VC1_PlayStart;
202
VC_PlayStop_ptr=VC1_PlayStop;
203
VC_SampleLoad_ptr=VC1_SampleLoad;
204
VC_SampleUnload_ptr=VC1_SampleUnload;
205
VC_WriteBytes_ptr=VC1_WriteBytes;
206
VC_SilenceBytes_ptr=VC1_SilenceBytes;
207
VC_VoiceSetVolume_ptr=VC1_VoiceSetVolume;
208
VC_VoiceGetVolume_ptr=VC1_VoiceGetVolume;
209
VC_VoiceSetFrequency_ptr=VC1_VoiceSetFrequency;
210
VC_VoiceGetFrequency_ptr=VC1_VoiceGetFrequency;
211
VC_VoiceSetPanning_ptr=VC1_VoiceSetPanning;
212
VC_VoiceGetPanning_ptr=VC1_VoiceGetPanning;
213
VC_VoicePlay_ptr=VC1_VoicePlay;
214
VC_VoiceStop_ptr=VC1_VoiceStop;
215
VC_VoiceStopped_ptr=VC1_VoiceStopped;
216
VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition;
217
VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume;
223
#ifndef _VIRTCH_COMMON_
224
#define _VIRTCH_COMMON_
226
static ULONG samples2bytes(ULONG samples)
228
if(vc_mode & DMODE_16BITS) samples <<= 1;
229
if(vc_mode & DMODE_STEREO) samples <<= 1;
233
static ULONG bytes2samples(ULONG bytes)
235
if(vc_mode & DMODE_16BITS) bytes >>= 1;
236
if(vc_mode & DMODE_STEREO) bytes >>= 1;
240
/* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
241
how the buffer is filled) */
242
ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
244
todo=samples2bytes(bytes2samples(todo));
246
/* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
247
if(vc_mode & DMODE_16BITS)
250
memset(buf,0x80,todo);
255
void VC1_WriteSamples(SBYTE*,ULONG);
257
/* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
258
actually written to 'buf' (which is rounded to number of samples that fit
259
into 'todo' bytes). */
260
ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
263
return VC1_SilenceBytes(buf,todo);
265
todo = bytes2samples(todo);
266
VC1_WriteSamples(buf,todo);
268
return samples2bytes(todo);
273
if(vc_tickbuf) free(vc_tickbuf);
275
if(Samples) free(Samples);
284
UWORD VC1_VoiceGetVolume(UBYTE voice)
286
return vinf[voice].vol;
289
ULONG VC1_VoiceGetPanning(UBYTE voice)
291
return vinf[voice].pan;
294
void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)
299
ULONG VC1_VoiceGetFrequency(UBYTE voice)
301
return vinf[voice].frq;
304
void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
306
vinf[voice].flags = flags;
307
vinf[voice].handle = handle;
308
vinf[voice].start = start;
309
vinf[voice].size = size;
310
vinf[voice].reppos = reppos;
311
vinf[voice].repend = repend;
312
vinf[voice].kick = 1;
315
void VC1_VoiceStop(UBYTE voice)
317
vinf[voice].active = 0;
320
BOOL VC1_VoiceStopped(UBYTE voice)
322
return(vinf[voice].active==0);
325
SLONG VC1_VoiceGetPosition(UBYTE voice)
327
return(vinf[voice].current>>FRACBITS);
330
void VC1_VoiceSetVolume(UBYTE voice,UWORD vol)
332
/* protect against clicks if volume variation is too high */
333
if(abs((int)vinf[voice].vol-(int)vol)>32)
334
vinf[voice].rampvol=CLICK_BUFFER;
338
void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
340
/* protect against clicks if panning variation is too high */
341
if(abs((int)vinf[voice].pan-(int)pan)>48)
342
vinf[voice].rampvol=CLICK_BUFFER;
346
/*========== External mixer interface */
348
void VC1_SampleUnload(SWORD handle)
350
if (handle<MAXSAMPLEHANDLES) {
352
free(Samples[handle]);
353
Samples[handle]=NULL;
357
SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
359
SAMPLE *s = sload->sample;
361
ULONG t, length,loopstart,loopend;
363
if(type==MD_HARDWARE) return -1;
365
/* Find empty slot to put sample address in */
366
for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
367
if(!Samples[handle]) break;
369
if(handle==MAXSAMPLEHANDLES) {
370
_mm_errno = MMERR_OUT_OF_HANDLES;
375
loopstart = s->loopstart;
376
loopend = s->loopend;
378
SL_SampleSigned(sload);
379
SL_Sample8to16(sload);
381
if(!(Samples[handle]=(SWORD*)_mm_malloc((length+20)<<1))) {
382
_mm_errno = MMERR_SAMPLE_TOO_BIG;
386
/* read sample into buffer */
387
if (SL_Load(Samples[handle],sload,length))
391
if(s->flags & SF_LOOP) {
392
if(s->flags & SF_BIDI)
394
Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
397
Samples[handle][loopend+t]=Samples[handle][t+loopstart];
400
Samples[handle][t+length]=0;
405
ULONG VC1_SampleSpace(int type)
410
ULONG VC1_SampleLength(int type,SAMPLE* s)
414
return (s->length*((s->flags&SF_16BITS)?2:1))+16;
417
ULONG VC1_VoiceRealVolume(UBYTE voice)
424
t = vinf[voice].current>>FRACBITS;
425
if(!vinf[voice].active) return 0;
427
s = vinf[voice].handle;
428
size = vinf[voice].size;
430
i=64; t-=64; k=0; j=0;
433
if(t+i > size) t = size-i;
435
i &= ~1; /* make sure it's EVEN. */
437
smp = &Samples[s][t];