2010-12-12 15:03:30 +00:00
|
|
|
/* MikMod sound library
|
|
|
|
(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
|
|
|
|
for complete list.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Library General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
the License, or (at your option) any later version.
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Library General Public License for more details.
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
License along with this library; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*==============================================================================
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
$Id$
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
Common source parts between the two software mixers.
|
|
|
|
This file is probably the ugliest part of libmikmod...
|
|
|
|
|
|
|
|
==============================================================================*/
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#if defined(HAVE_CONFIG_H) && !defined(_IN_VIRTCH_) /* config.h isn't guarded */
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
2010-12-12 15:03:30 +00:00
|
|
|
#include "mikmod_internals.h"
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#ifndef NO_HQMIXER
|
|
|
|
extern ULONG VC1_SilenceBytes(SBYTE*,ULONG);
|
|
|
|
extern ULONG VC2_SilenceBytes(SBYTE*,ULONG);
|
|
|
|
extern ULONG VC1_WriteBytes(SBYTE*,ULONG);
|
|
|
|
extern ULONG VC2_WriteBytes(SBYTE*,ULONG);
|
2010-12-12 15:03:30 +00:00
|
|
|
extern void VC1_Exit(void);
|
2020-08-09 01:56:15 +00:00
|
|
|
extern void VC2_Exit(void);
|
|
|
|
extern UWORD VC1_VoiceGetVolume(UBYTE);
|
|
|
|
extern UWORD VC2_VoiceGetVolume(UBYTE);
|
|
|
|
extern ULONG VC1_VoiceGetPanning(UBYTE);
|
|
|
|
extern ULONG VC2_VoiceGetPanning(UBYTE);
|
|
|
|
extern void VC1_VoiceSetFrequency(UBYTE,ULONG);
|
|
|
|
extern void VC2_VoiceSetFrequency(UBYTE,ULONG);
|
|
|
|
extern ULONG VC1_VoiceGetFrequency(UBYTE);
|
|
|
|
extern ULONG VC2_VoiceGetFrequency(UBYTE);
|
|
|
|
extern void VC1_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
|
|
|
extern void VC2_VoicePlay(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
|
|
|
extern void VC1_VoiceStop(UBYTE);
|
|
|
|
extern void VC2_VoiceStop(UBYTE);
|
|
|
|
extern int VC1_VoiceStopped(UBYTE);
|
|
|
|
extern int VC2_VoiceStopped(UBYTE);
|
|
|
|
extern SLONG VC1_VoiceGetPosition(UBYTE);
|
|
|
|
extern SLONG VC2_VoiceGetPosition(UBYTE);
|
|
|
|
extern void VC1_VoiceSetVolume(UBYTE,UWORD);
|
|
|
|
extern void VC2_VoiceSetVolume(UBYTE,UWORD);
|
|
|
|
extern void VC1_VoiceSetPanning(UBYTE,ULONG);
|
|
|
|
extern void VC2_VoiceSetPanning(UBYTE,ULONG);
|
|
|
|
extern void VC1_SampleUnload(SWORD);
|
|
|
|
extern void VC2_SampleUnload(SWORD);
|
|
|
|
extern SWORD VC1_SampleLoad(struct SAMPLOAD*,int);
|
|
|
|
extern SWORD VC2_SampleLoad(struct SAMPLOAD*,int);
|
2010-12-12 15:03:30 +00:00
|
|
|
extern ULONG VC1_SampleSpace(int);
|
2020-08-09 01:56:15 +00:00
|
|
|
extern ULONG VC2_SampleSpace(int);
|
2010-12-12 15:03:30 +00:00
|
|
|
extern ULONG VC1_SampleLength(int,SAMPLE*);
|
2020-08-09 01:56:15 +00:00
|
|
|
extern ULONG VC2_SampleLength(int,SAMPLE*);
|
|
|
|
extern ULONG VC1_VoiceRealVolume(UBYTE);
|
|
|
|
extern ULONG VC2_VoiceRealVolume(UBYTE);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _IN_VIRTCH_
|
|
|
|
|
|
|
|
#ifndef NO_HQMIXER
|
|
|
|
extern int VC1_Init(void);
|
|
|
|
extern int VC2_Init(void);
|
|
|
|
static int (*VC_Init_ptr)(void)=VC1_Init;
|
|
|
|
static void (*VC_Exit_ptr)(void)=VC1_Exit;
|
|
|
|
extern int VC1_SetNumVoices(void);
|
|
|
|
extern int VC2_SetNumVoices(void);
|
|
|
|
static int (*VC_SetNumVoices_ptr)(void);
|
|
|
|
static ULONG (*VC_SampleSpace_ptr)(int);
|
2010-12-12 15:03:30 +00:00
|
|
|
static ULONG (*VC_SampleLength_ptr)(int,SAMPLE*);
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
extern int VC2_PlayStart(void);
|
|
|
|
static int (*VC_PlayStart_ptr)(void);
|
2010-12-12 15:03:30 +00:00
|
|
|
extern void VC2_PlayStop(void);
|
|
|
|
static void (*VC_PlayStop_ptr)(void);
|
|
|
|
|
|
|
|
static SWORD (*VC_SampleLoad_ptr)(struct SAMPLOAD*,int);
|
|
|
|
static void (*VC_SampleUnload_ptr)(SWORD);
|
|
|
|
|
|
|
|
static ULONG (*VC_WriteBytes_ptr)(SBYTE*,ULONG);
|
|
|
|
static ULONG (*VC_SilenceBytes_ptr)(SBYTE*,ULONG);
|
|
|
|
|
|
|
|
static void (*VC_VoiceSetVolume_ptr)(UBYTE,UWORD);
|
|
|
|
static UWORD (*VC_VoiceGetVolume_ptr)(UBYTE);
|
|
|
|
static void (*VC_VoiceSetFrequency_ptr)(UBYTE,ULONG);
|
|
|
|
static ULONG (*VC_VoiceGetFrequency_ptr)(UBYTE);
|
|
|
|
static void (*VC_VoiceSetPanning_ptr)(UBYTE,ULONG);
|
|
|
|
static ULONG (*VC_VoiceGetPanning_ptr)(UBYTE);
|
|
|
|
static void (*VC_VoicePlay_ptr)(UBYTE,SWORD,ULONG,ULONG,ULONG,ULONG,UWORD);
|
|
|
|
|
|
|
|
static void (*VC_VoiceStop_ptr)(UBYTE);
|
|
|
|
static int (*VC_VoiceStopped_ptr)(UBYTE);
|
|
|
|
static SLONG (*VC_VoiceGetPosition_ptr)(UBYTE);
|
|
|
|
static ULONG (*VC_VoiceRealVolume_ptr)(UBYTE);
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#if defined __STDC__ || defined _MSC_VER || defined __WATCOMC__ || defined MPW_C
|
2010-12-12 15:03:30 +00:00
|
|
|
#define VC_PROC0(suffix) \
|
|
|
|
MIKMODAPI void VC_##suffix (void) { VC_##suffix##_ptr(); }
|
|
|
|
|
|
|
|
#define VC_FUNC0(suffix,ret) \
|
|
|
|
MIKMODAPI ret VC_##suffix (void) { return VC_##suffix##_ptr(); }
|
|
|
|
|
|
|
|
#define VC_PROC1(suffix,typ1) \
|
|
|
|
MIKMODAPI void VC_##suffix (typ1 a) { VC_##suffix##_ptr(a); }
|
|
|
|
|
|
|
|
#define VC_FUNC1(suffix,ret,typ1) \
|
|
|
|
MIKMODAPI ret VC_##suffix (typ1 a) { return VC_##suffix##_ptr(a); }
|
|
|
|
|
|
|
|
#define VC_PROC2(suffix,typ1,typ2) \
|
|
|
|
MIKMODAPI void VC_##suffix (typ1 a,typ2 b) { VC_##suffix##_ptr(a,b); }
|
|
|
|
|
|
|
|
#define VC_FUNC2(suffix,ret,typ1,typ2) \
|
|
|
|
MIKMODAPI ret VC_##suffix (typ1 a,typ2 b) { return VC_##suffix##_ptr(a,b); }
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
#else
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
#define VC_PROC0(suffix) \
|
|
|
|
MIKMODAPI void VC_/**/suffix (void) { VC_/**/suffix/**/_ptr(); }
|
|
|
|
|
|
|
|
#define VC_FUNC0(suffix,ret) \
|
|
|
|
MIKMODAPI ret VC_/**/suffix (void) { return VC_/**/suffix/**/_ptr(); }
|
|
|
|
|
|
|
|
#define VC_PROC1(suffix,typ1) \
|
|
|
|
MIKMODAPI void VC_/**/suffix (typ1 a) { VC_/**/suffix/**/_ptr(a); }
|
|
|
|
|
|
|
|
#define VC_FUNC1(suffix,ret,typ1) \
|
|
|
|
MIKMODAPI ret VC_/**/suffix (typ1 a) { return VC_/**/suffix/**/_ptr(a); }
|
|
|
|
|
|
|
|
#define VC_PROC2(suffix,typ1,typ2) \
|
|
|
|
MIKMODAPI void VC_/**/suffix (typ1 a,typ2 b) { VC_/**/suffix/**/_ptr(a,b); }
|
|
|
|
|
|
|
|
#define VC_FUNC2(suffix,ret,typ1,typ2) \
|
|
|
|
MIKMODAPI ret VC_/**/suffix (typ1 a,typ2 b) { return VC_/**/suffix/**/_ptr(a,b); }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
VC_FUNC0(Init,int)
|
|
|
|
VC_PROC0(Exit)
|
|
|
|
VC_FUNC0(SetNumVoices,int)
|
|
|
|
VC_FUNC1(SampleSpace,ULONG,int)
|
|
|
|
VC_FUNC2(SampleLength,ULONG,int,SAMPLE*)
|
|
|
|
VC_FUNC0(PlayStart,int)
|
|
|
|
VC_PROC0(PlayStop)
|
|
|
|
VC_FUNC2(SampleLoad,SWORD,struct SAMPLOAD*,int)
|
|
|
|
VC_PROC1(SampleUnload,SWORD)
|
|
|
|
VC_FUNC2(WriteBytes,ULONG,SBYTE*,ULONG)
|
|
|
|
VC_FUNC2(SilenceBytes,ULONG,SBYTE*,ULONG)
|
|
|
|
VC_PROC2(VoiceSetVolume,UBYTE,UWORD)
|
|
|
|
VC_FUNC1(VoiceGetVolume,UWORD,UBYTE)
|
|
|
|
VC_PROC2(VoiceSetFrequency,UBYTE,ULONG)
|
|
|
|
VC_FUNC1(VoiceGetFrequency,ULONG,UBYTE)
|
|
|
|
VC_PROC2(VoiceSetPanning,UBYTE,ULONG)
|
|
|
|
VC_FUNC1(VoiceGetPanning,ULONG,UBYTE)
|
2020-08-09 01:56:15 +00:00
|
|
|
|
|
|
|
void VC_VoicePlay(UBYTE a,SWORD b,ULONG c,ULONG d,ULONG e,ULONG f,UWORD g) {
|
|
|
|
VC_VoicePlay_ptr(a,b,c,d,e,f,g);
|
|
|
|
}
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
VC_PROC1(VoiceStop,UBYTE)
|
|
|
|
VC_FUNC1(VoiceStopped,int,UBYTE)
|
|
|
|
VC_FUNC1(VoiceGetPosition,SLONG,UBYTE)
|
|
|
|
VC_FUNC1(VoiceRealVolume,ULONG,UBYTE)
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
void VC_SetupPointers(void)
|
|
|
|
{
|
|
|
|
if (md_mode&DMODE_HQMIXER) {
|
|
|
|
VC_Init_ptr=VC2_Init;
|
|
|
|
VC_Exit_ptr=VC2_Exit;
|
|
|
|
VC_SetNumVoices_ptr=VC2_SetNumVoices;
|
|
|
|
VC_SampleSpace_ptr=VC2_SampleSpace;
|
|
|
|
VC_SampleLength_ptr=VC2_SampleLength;
|
|
|
|
VC_PlayStart_ptr=VC2_PlayStart;
|
|
|
|
VC_PlayStop_ptr=VC2_PlayStop;
|
|
|
|
VC_SampleLoad_ptr=VC2_SampleLoad;
|
|
|
|
VC_SampleUnload_ptr=VC2_SampleUnload;
|
|
|
|
VC_WriteBytes_ptr=VC2_WriteBytes;
|
|
|
|
VC_SilenceBytes_ptr=VC2_SilenceBytes;
|
|
|
|
VC_VoiceSetVolume_ptr=VC2_VoiceSetVolume;
|
|
|
|
VC_VoiceGetVolume_ptr=VC2_VoiceGetVolume;
|
|
|
|
VC_VoiceSetFrequency_ptr=VC2_VoiceSetFrequency;
|
|
|
|
VC_VoiceGetFrequency_ptr=VC2_VoiceGetFrequency;
|
|
|
|
VC_VoiceSetPanning_ptr=VC2_VoiceSetPanning;
|
|
|
|
VC_VoiceGetPanning_ptr=VC2_VoiceGetPanning;
|
|
|
|
VC_VoicePlay_ptr=VC2_VoicePlay;
|
|
|
|
VC_VoiceStop_ptr=VC2_VoiceStop;
|
|
|
|
VC_VoiceStopped_ptr=VC2_VoiceStopped;
|
|
|
|
VC_VoiceGetPosition_ptr=VC2_VoiceGetPosition;
|
|
|
|
VC_VoiceRealVolume_ptr=VC2_VoiceRealVolume;
|
|
|
|
} else {
|
|
|
|
VC_Init_ptr=VC1_Init;
|
|
|
|
VC_Exit_ptr=VC1_Exit;
|
|
|
|
VC_SetNumVoices_ptr=VC1_SetNumVoices;
|
|
|
|
VC_SampleSpace_ptr=VC1_SampleSpace;
|
|
|
|
VC_SampleLength_ptr=VC1_SampleLength;
|
|
|
|
VC_PlayStart_ptr=VC1_PlayStart;
|
|
|
|
VC_PlayStop_ptr=VC1_PlayStop;
|
|
|
|
VC_SampleLoad_ptr=VC1_SampleLoad;
|
|
|
|
VC_SampleUnload_ptr=VC1_SampleUnload;
|
|
|
|
VC_WriteBytes_ptr=VC1_WriteBytes;
|
|
|
|
VC_SilenceBytes_ptr=VC1_SilenceBytes;
|
|
|
|
VC_VoiceSetVolume_ptr=VC1_VoiceSetVolume;
|
|
|
|
VC_VoiceGetVolume_ptr=VC1_VoiceGetVolume;
|
|
|
|
VC_VoiceSetFrequency_ptr=VC1_VoiceSetFrequency;
|
|
|
|
VC_VoiceGetFrequency_ptr=VC1_VoiceGetFrequency;
|
|
|
|
VC_VoiceSetPanning_ptr=VC1_VoiceSetPanning;
|
|
|
|
VC_VoiceGetPanning_ptr=VC1_VoiceGetPanning;
|
|
|
|
VC_VoicePlay_ptr=VC1_VoicePlay;
|
|
|
|
VC_VoiceStop_ptr=VC1_VoiceStop;
|
|
|
|
VC_VoiceStopped_ptr=VC1_VoiceStopped;
|
|
|
|
VC_VoiceGetPosition_ptr=VC1_VoiceGetPosition;
|
|
|
|
VC_VoiceRealVolume_ptr=VC1_VoiceRealVolume;
|
2020-08-09 01:56:15 +00:00
|
|
|
}
|
2010-12-12 15:03:30 +00:00
|
|
|
}
|
2020-08-09 01:56:15 +00:00
|
|
|
#endif/* !NO_HQMIXER */
|
2010-12-12 15:03:30 +00:00
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#else /* _IN_VIRTCH_ */
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
#ifndef _VIRTCH_COMMON_
|
|
|
|
#define _VIRTCH_COMMON_
|
|
|
|
|
|
|
|
static ULONG samples2bytes(ULONG samples)
|
|
|
|
{
|
|
|
|
if(vc_mode & DMODE_FLOAT) samples <<= 2;
|
|
|
|
else if(vc_mode & DMODE_16BITS) samples <<= 1;
|
|
|
|
if(vc_mode & DMODE_STEREO) samples <<= 1;
|
|
|
|
return samples;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG bytes2samples(ULONG bytes)
|
|
|
|
{
|
|
|
|
if(vc_mode & DMODE_FLOAT) bytes >>= 2;
|
|
|
|
else if(vc_mode & DMODE_16BITS) bytes >>= 1;
|
|
|
|
if(vc_mode & DMODE_STEREO) bytes >>= 1;
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
|
|
|
|
how the buffer is filled) */
|
|
|
|
ULONG VC1_SilenceBytes(SBYTE* buf,ULONG todo)
|
|
|
|
{
|
|
|
|
todo=samples2bytes(bytes2samples(todo));
|
|
|
|
|
|
|
|
/* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
|
2020-08-09 01:56:15 +00:00
|
|
|
if(vc_mode &(DMODE_16BITS|DMODE_FLOAT))
|
2010-12-12 15:03:30 +00:00
|
|
|
memset(buf,0,todo);
|
|
|
|
else
|
|
|
|
memset(buf,0x80,todo);
|
|
|
|
|
|
|
|
return todo;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_WriteSamples(SBYTE*,ULONG);
|
|
|
|
|
|
|
|
/* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
|
|
|
|
actually written to 'buf' (which is rounded to number of samples that fit
|
|
|
|
into 'todo' bytes). */
|
|
|
|
ULONG VC1_WriteBytes(SBYTE* buf,ULONG todo)
|
|
|
|
{
|
|
|
|
if(!vc_softchn)
|
|
|
|
return VC1_SilenceBytes(buf,todo);
|
|
|
|
|
|
|
|
todo = bytes2samples(todo);
|
|
|
|
VC1_WriteSamples(buf,todo);
|
|
|
|
|
|
|
|
return samples2bytes(todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_Exit(void)
|
|
|
|
{
|
2020-08-09 01:56:15 +00:00
|
|
|
MikMod_free(vinf);
|
|
|
|
MikMod_afree(vc_tickbuf);
|
|
|
|
MikMod_afree(Samples);
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
vc_tickbuf = NULL;
|
|
|
|
vinf = NULL;
|
|
|
|
Samples = NULL;
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
VC_SetupPointers();
|
|
|
|
}
|
|
|
|
|
|
|
|
UWORD VC1_VoiceGetVolume(UBYTE voice)
|
|
|
|
{
|
|
|
|
return vinf[voice].vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG VC1_VoiceGetPanning(UBYTE voice)
|
|
|
|
{
|
|
|
|
return vinf[voice].pan;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_VoiceSetFrequency(UBYTE voice,ULONG frq)
|
|
|
|
{
|
|
|
|
vinf[voice].frq=frq;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG VC1_VoiceGetFrequency(UBYTE voice)
|
|
|
|
{
|
|
|
|
return vinf[voice].frq;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
|
|
|
|
{
|
2020-08-09 01:56:15 +00:00
|
|
|
vinf[voice].flags = flags;
|
|
|
|
vinf[voice].handle = handle;
|
|
|
|
vinf[voice].start = start;
|
|
|
|
vinf[voice].size = size;
|
|
|
|
vinf[voice].reppos = reppos;
|
|
|
|
vinf[voice].repend = repend;
|
|
|
|
vinf[voice].kick = 1;
|
2010-12-12 15:03:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_VoiceStop(UBYTE voice)
|
|
|
|
{
|
|
|
|
vinf[voice].active = 0;
|
2020-08-09 01:56:15 +00:00
|
|
|
}
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
int VC1_VoiceStopped(UBYTE voice)
|
|
|
|
{
|
|
|
|
return(vinf[voice].active==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
SLONG VC1_VoiceGetPosition(UBYTE voice)
|
|
|
|
{
|
|
|
|
return (SLONG)(vinf[voice].current>>FRACBITS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_VoiceSetVolume(UBYTE voice,UWORD vol)
|
2020-08-09 01:56:15 +00:00
|
|
|
{
|
2010-12-12 15:03:30 +00:00
|
|
|
/* protect against clicks if volume variation is too high */
|
|
|
|
if(abs((int)vinf[voice].vol-(int)vol)>32)
|
|
|
|
vinf[voice].rampvol=CLICK_BUFFER;
|
|
|
|
vinf[voice].vol=vol;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VC1_VoiceSetPanning(UBYTE voice,ULONG pan)
|
|
|
|
{
|
|
|
|
/* protect against clicks if panning variation is too high */
|
|
|
|
if(abs((int)vinf[voice].pan-(int)pan)>48)
|
|
|
|
vinf[voice].rampvol=CLICK_BUFFER;
|
|
|
|
vinf[voice].pan=pan;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*========== External mixer interface */
|
|
|
|
|
|
|
|
void VC1_SampleUnload(SWORD handle)
|
|
|
|
{
|
2020-08-09 01:56:15 +00:00
|
|
|
if (Samples && (handle < MAXSAMPLEHANDLES)) {
|
|
|
|
MikMod_afree(Samples[handle]);
|
2010-12-12 15:03:30 +00:00
|
|
|
Samples[handle]=NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SWORD VC1_SampleLoad(struct SAMPLOAD* sload,int type)
|
|
|
|
{
|
|
|
|
SAMPLE *s = sload->sample;
|
|
|
|
int handle;
|
2020-08-09 01:56:15 +00:00
|
|
|
ULONG t, length,loopstart,loopend,looplen;
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
if(type==MD_HARDWARE) return -1;
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
if(s->length > MAX_SAMPLE_SIZE) {
|
|
|
|
_mm_errno = MMERR_NOT_A_STREAM; /* better error? */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
/* Find empty slot to put sample address in */
|
|
|
|
for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
|
|
|
|
if(!Samples[handle]) break;
|
|
|
|
|
|
|
|
if(handle==MAXSAMPLEHANDLES) {
|
|
|
|
_mm_errno = MMERR_OUT_OF_HANDLES;
|
|
|
|
return -1;
|
|
|
|
}
|
2020-08-09 01:56:15 +00:00
|
|
|
|
2010-12-12 15:03:30 +00:00
|
|
|
/* Reality check for loop settings */
|
|
|
|
if (s->loopend > s->length)
|
|
|
|
s->loopend = s->length;
|
|
|
|
if (s->loopstart >= s->loopend)
|
|
|
|
s->flags &= ~SF_LOOP;
|
|
|
|
|
|
|
|
length = s->length;
|
|
|
|
loopstart = s->loopstart;
|
|
|
|
loopend = s->loopend;
|
|
|
|
|
|
|
|
SL_SampleSigned(sload);
|
|
|
|
SL_Sample8to16(sload);
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
if(!(Samples[handle]=(SWORD*)MikMod_amalloc((length+20)<<1))) {
|
2010-12-12 15:03:30 +00:00
|
|
|
_mm_errno = MMERR_SAMPLE_TOO_BIG;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read sample into buffer */
|
2020-08-09 01:56:15 +00:00
|
|
|
if (SL_Load(Samples[handle],sload,length)) {
|
|
|
|
MikMod_afree(Samples[handle]);
|
|
|
|
Samples[handle]=NULL;
|
2010-12-12 15:03:30 +00:00
|
|
|
return -1;
|
2020-08-09 01:56:15 +00:00
|
|
|
}
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
/* Unclick sample */
|
|
|
|
if(s->flags & SF_LOOP) {
|
2020-08-09 01:56:15 +00:00
|
|
|
looplen = loopend - loopstart;/* handle short samples */
|
2010-12-12 15:03:30 +00:00
|
|
|
if(s->flags & SF_BIDI)
|
2020-08-09 01:56:15 +00:00
|
|
|
for(t=0;t<16 && t<looplen;t++)
|
2010-12-12 15:03:30 +00:00
|
|
|
Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
|
|
|
|
else
|
2020-08-09 01:56:15 +00:00
|
|
|
for(t=0;t<16 && t<looplen;t++)
|
2010-12-12 15:03:30 +00:00
|
|
|
Samples[handle][loopend+t]=Samples[handle][t+loopstart];
|
|
|
|
} else
|
|
|
|
for(t=0;t<16;t++)
|
|
|
|
Samples[handle][t+length]=0;
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG VC1_SampleSpace(int type)
|
|
|
|
{
|
2020-08-09 01:56:15 +00:00
|
|
|
(void)type;
|
2010-12-12 15:03:30 +00:00
|
|
|
return vc_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG VC1_SampleLength(int type,SAMPLE* s)
|
|
|
|
{
|
2020-08-09 01:56:15 +00:00
|
|
|
(void)type;
|
2010-12-12 15:03:30 +00:00
|
|
|
if (!s) return 0;
|
|
|
|
|
|
|
|
return (s->length*((s->flags&SF_16BITS)?2:1))+16;
|
|
|
|
}
|
|
|
|
|
|
|
|
ULONG VC1_VoiceRealVolume(UBYTE voice)
|
|
|
|
{
|
|
|
|
ULONG i,s,size;
|
|
|
|
int k,j;
|
|
|
|
SWORD *smp;
|
|
|
|
SLONG t;
|
|
|
|
|
|
|
|
t = (SLONG)(vinf[voice].current>>FRACBITS);
|
|
|
|
if(!vinf[voice].active) return 0;
|
|
|
|
|
|
|
|
s = vinf[voice].handle;
|
|
|
|
size = vinf[voice].size;
|
|
|
|
|
|
|
|
i=64; t-=64; k=0; j=0;
|
|
|
|
if(i>size) i = size;
|
|
|
|
if(t<0) t = 0;
|
|
|
|
if(t+i > size) t = size-i;
|
|
|
|
|
|
|
|
i &= ~1; /* make sure it's EVEN. */
|
|
|
|
|
|
|
|
smp = &Samples[s][t];
|
|
|
|
for(;i;i--,smp++) {
|
|
|
|
if(k<*smp) k = *smp;
|
|
|
|
if(j>*smp) j = *smp;
|
|
|
|
}
|
|
|
|
return abs(k-j);
|
|
|
|
}
|
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#endif /* _VIRTCH_COMMON_ */
|
2010-12-12 15:03:30 +00:00
|
|
|
|
2020-08-09 01:56:15 +00:00
|
|
|
#endif /* _IN_VIRTCH_ */
|
2010-12-12 15:03:30 +00:00
|
|
|
|
|
|
|
/* ex:set ts=4: */
|