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