A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 475 lines 13 kB view raw
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: */