2010-12-12 15:03:30 +00:00
/* MikMod sound library
( c ) 1998 , 1999 , 2005 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 .
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 .
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 .
*/
/*==============================================================================
MikMod sound library internal definitions
2020-08-09 01:56:15 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2010-12-12 15:03:30 +00:00
# ifndef _MIKMOD_INTERNALS_H
# define _MIKMOD_INTERNALS_H
# ifdef __cplusplus
extern " C " {
# endif
# include <stdarg.h>
2020-08-09 01:56:15 +00:00
# if defined(_MSC_VER) && !defined(__cplusplus) && !defined(HAVE_CONFIG_H)
# define inline __inline
2010-12-12 15:03:30 +00:00
# endif
# include "mikmod.h"
2020-08-09 01:56:15 +00:00
# ifndef MIKMOD_UNIX
# if (defined(unix) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) && \
! ( defined ( _MIKMOD_WIN32 ) | | defined ( _MIKMOD_OS2 ) | | defined ( _MIKMOD_DOS ) | | defined ( _MIKMOD_AMIGA ) | | defined ( macintosh ) )
# define MIKMOD_UNIX 1
# else
# define MIKMOD_UNIX 0
# endif
# endif /* MIKMOD_UNIX */
2010-12-12 15:03:30 +00:00
/*========== More type definitions */
/* SLONGLONG: 64bit, signed */
2020-08-09 01:56:15 +00:00
# if !defined(_WIN32) && \
( defined ( _LP64 ) | | defined ( __LP64__ ) | | defined ( __arch64__ ) | | defined ( __alpha ) | | defined ( __x64_64 ) | | defined ( __powerpc64__ ) )
typedef long SLONGLONG ;
# define NATIVE_64BIT_INT
# elif defined(_WIN64) /* win64 is LLP64, not LP64 */
2010-12-12 15:03:30 +00:00
# define NATIVE_64BIT_INT
2020-08-09 01:56:15 +00:00
typedef long long SLONGLONG ;
2010-12-12 15:03:30 +00:00
# elif defined(__WATCOMC__)
2020-08-09 01:56:15 +00:00
typedef __int64 SLONGLONG ;
# elif defined(_WIN32) && !defined(__MWERKS__)
typedef LONGLONG SLONGLONG ;
# elif defined(macintosh) && !TYPE_LONGLONG
2010-12-12 15:03:30 +00:00
# include <Types.h>
2020-08-09 01:56:15 +00:00
typedef SInt64 SLONGLONG ;
# else
typedef long long SLONGLONG ;
2010-12-12 15:03:30 +00:00
# endif
2020-08-09 01:56:15 +00:00
typedef int __s64_typetest [ ( sizeof ( SLONGLONG ) = = 8 ) * 2 - 1 ] ;
/* pointer-sized signed int (ssize_t/intptr_t) : */
# if defined(_WIN64) /* win64 is LLP64, not LP64 */
typedef long long SINTPTR_T ;
2010-12-12 15:03:30 +00:00
# else
2020-08-09 01:56:15 +00:00
/* long should be pointer-sized for all others : */
typedef long SINTPTR_T ;
2010-12-12 15:03:30 +00:00
# endif
2020-08-09 01:56:15 +00:00
typedef int __iptr_typetest [ ( sizeof ( SINTPTR_T ) = = sizeof ( void * ) ) * 2 - 1 ] ;
2010-12-12 15:03:30 +00:00
/*========== Error handling */
# define _mm_errno MikMod_errno
# define _mm_critical MikMod_critical
extern MikMod_handler_t _mm_errorhandler ;
/*========== MT stuff */
# ifdef HAVE_PTHREAD
# include <pthread.h>
# define DECLARE_MUTEX(name) \
2020-08-09 01:56:15 +00:00
extern pthread_mutex_t _mm_mutex_ # # name
# define MUTEX_LOCK(name) \
pthread_mutex_lock ( & _mm_mutex_ # # name )
# define MUTEX_UNLOCK(name) \
pthread_mutex_unlock ( & _mm_mutex_ # # name )
2010-12-12 15:03:30 +00:00
# elif defined(__OS2__)||defined(__EMX__)
2020-08-09 01:56:15 +00:00
# define DECLARE_MUTEX(name) \
extern HMTX _mm_mutex_ # # name
# define MUTEX_LOCK(name) \
if ( _mm_mutex_ # # name ) \
DosRequestMutexSem ( _mm_mutex_ # # name , SEM_INDEFINITE_WAIT )
# define MUTEX_UNLOCK(name) \
if ( _mm_mutex_ # # name ) \
DosReleaseMutexSem ( _mm_mutex_ # # name )
# elif defined(_WIN32)
2010-12-12 15:03:30 +00:00
# include <windows.h>
2020-08-09 01:56:15 +00:00
# define DECLARE_MUTEX(name) \
extern HANDLE _mm_mutex_ # # name
# define MUTEX_LOCK(name) \
if ( _mm_mutex_ # # name ) \
WaitForSingleObject ( _mm_mutex_ # # name , INFINITE )
# define MUTEX_UNLOCK(name) \
if ( _mm_mutex_ # # name ) \
ReleaseMutex ( _mm_mutex_ # # name )
2010-12-12 15:03:30 +00:00
# else
2020-08-09 01:56:15 +00:00
# define DECLARE_MUTEX(name) \
extern void * _mm_mutex_ # # name
2010-12-12 15:03:30 +00:00
# define MUTEX_LOCK(name)
# define MUTEX_UNLOCK(name)
# endif
DECLARE_MUTEX ( lists ) ;
DECLARE_MUTEX ( vars ) ;
2020-08-09 01:56:15 +00:00
/*========== Replacement funcs */
//extern int strcasecmp (const char *__s1, const char *__s2);
2010-12-12 15:03:30 +00:00
/*========== Portable file I/O */
2020-08-09 01:56:15 +00:00
extern MREADER * _mm_new_mem_reader ( const void * buffer , long len ) ;
2010-12-12 15:03:30 +00:00
extern void _mm_delete_mem_reader ( MREADER * reader ) ;
extern MREADER * _mm_new_file_reader ( int fp ) ;
extern void _mm_delete_file_reader ( MREADER * ) ;
extern MWRITER * _mm_new_file_writer ( int fp ) ;
extern void _mm_delete_file_writer ( MWRITER * ) ;
2020-08-09 01:56:15 +00:00
extern int _mm_FileExists ( const CHAR * fname ) ;
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define _mm_write_SBYTE(x,y) y->Put(y,(int)x)
# define _mm_write_UBYTE(x,y) y->Put(y,(int)x)
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define _mm_read_SBYTE(x) (SBYTE)x->Get(x)
# define _mm_read_UBYTE(x) (UBYTE)x->Get(x)
# define _mm_skip_BYTE(x) (void)x->Get(x)
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define _mm_write_SBYTES(x,y,z) z->Write(z,(const void *)x,y)
# define _mm_write_UBYTES(x,y,z) z->Write(z,(const void *)x,y)
2010-12-12 15:03:30 +00:00
# define _mm_read_SBYTES(x,y,z) z->Read(z,(void *)x,y)
# define _mm_read_UBYTES(x,y,z) z->Read(z,(void *)x,y)
2020-08-09 01:56:15 +00:00
# define _mm_fseek(x,y,z) x->Seek(x,y,z)
# define _mm_ftell(x) x->Tell(x)
# define _mm_rewind(x) _mm_fseek(x,0,SEEK_SET)
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define _mm_eof(x) x->Eof(x)
2010-12-12 15:03:30 +00:00
extern void _mm_iobase_setcur ( MREADER * ) ;
extern void _mm_iobase_revert ( MREADER * ) ;
2020-08-09 01:56:15 +00:00
extern int _mm_fopen ( const CHAR * , const CHAR * ) ;
extern int _mm_fclose ( int ) ;
extern void _mm_write_string ( const CHAR * , MWRITER * ) ;
extern int _mm_read_string ( CHAR * , int , MREADER * ) ;
2010-12-12 15:03:30 +00:00
extern SWORD _mm_read_M_SWORD ( MREADER * ) ;
extern SWORD _mm_read_I_SWORD ( MREADER * ) ;
extern UWORD _mm_read_M_UWORD ( MREADER * ) ;
extern UWORD _mm_read_I_UWORD ( MREADER * ) ;
extern SLONG _mm_read_M_SLONG ( MREADER * ) ;
extern SLONG _mm_read_I_SLONG ( MREADER * ) ;
extern ULONG _mm_read_M_ULONG ( MREADER * ) ;
extern ULONG _mm_read_I_ULONG ( MREADER * ) ;
extern int _mm_read_M_SWORDS ( SWORD * , int , MREADER * ) ;
extern int _mm_read_I_SWORDS ( SWORD * , int , MREADER * ) ;
extern int _mm_read_M_UWORDS ( UWORD * , int , MREADER * ) ;
extern int _mm_read_I_UWORDS ( UWORD * , int , MREADER * ) ;
extern int _mm_read_M_SLONGS ( SLONG * , int , MREADER * ) ;
extern int _mm_read_I_SLONGS ( SLONG * , int , MREADER * ) ;
extern int _mm_read_M_ULONGS ( ULONG * , int , MREADER * ) ;
extern int _mm_read_I_ULONGS ( ULONG * , int , MREADER * ) ;
extern void _mm_write_M_SWORD ( SWORD , MWRITER * ) ;
extern void _mm_write_I_SWORD ( SWORD , MWRITER * ) ;
extern void _mm_write_M_UWORD ( UWORD , MWRITER * ) ;
extern void _mm_write_I_UWORD ( UWORD , MWRITER * ) ;
extern void _mm_write_M_SLONG ( SLONG , MWRITER * ) ;
extern void _mm_write_I_SLONG ( SLONG , MWRITER * ) ;
extern void _mm_write_M_ULONG ( ULONG , MWRITER * ) ;
extern void _mm_write_I_ULONG ( ULONG , MWRITER * ) ;
extern void _mm_write_M_SWORDS ( SWORD * , int , MWRITER * ) ;
extern void _mm_write_I_SWORDS ( SWORD * , int , MWRITER * ) ;
extern void _mm_write_M_UWORDS ( UWORD * , int , MWRITER * ) ;
extern void _mm_write_I_UWORDS ( UWORD * , int , MWRITER * ) ;
extern void _mm_write_M_SLONGS ( SLONG * , int , MWRITER * ) ;
extern void _mm_write_I_SLONGS ( SLONG * , int , MWRITER * ) ;
extern void _mm_write_M_ULONGS ( ULONG * , int , MWRITER * ) ;
extern void _mm_write_I_ULONGS ( ULONG * , int , MWRITER * ) ;
/*========== Samples */
2020-08-09 01:56:15 +00:00
# define MAX_SAMPLE_SIZE 0x10000000 /* a sane value guaranteed to not overflow an SLONG */
2010-12-12 15:03:30 +00:00
/* This is a handle of sorts attached to any sample registered with
SL_RegisterSample . Generally , this only need be used or changed by the
loaders and drivers of mikmod . */
typedef struct SAMPLOAD {
2020-08-09 01:56:15 +00:00
struct SAMPLOAD * next ;
ULONG length ; /* length of sample (in samples!) */
ULONG loopstart ; /* repeat position (relative to start, in samples) */
ULONG loopend ; /* repeat end */
UWORD infmt , outfmt ;
int scalefactor ;
SAMPLE * sample ;
MREADER * reader ;
2010-12-12 15:03:30 +00:00
} SAMPLOAD ;
/*========== Sample and waves loading interface */
extern void SL_HalveSample ( SAMPLOAD * , int ) ;
extern void SL_Sample8to16 ( SAMPLOAD * ) ;
extern void SL_Sample16to8 ( SAMPLOAD * ) ;
extern void SL_SampleSigned ( SAMPLOAD * ) ;
extern void SL_SampleUnsigned ( SAMPLOAD * ) ;
2020-08-09 01:56:15 +00:00
extern int SL_LoadSamples ( void ) ;
2010-12-12 15:03:30 +00:00
extern SAMPLOAD * SL_RegisterSample ( SAMPLE * , int , MREADER * ) ;
2020-08-09 01:56:15 +00:00
extern int SL_Load ( void * , SAMPLOAD * , ULONG ) ;
2010-12-12 15:03:30 +00:00
extern int SL_Init ( SAMPLOAD * ) ;
extern void SL_Exit ( SAMPLOAD * ) ;
/*========== Internal module representation (UniMod) interface */
/* number of notes in an octave */
# define OCTAVE 12
extern void UniSetRow ( UBYTE * ) ;
extern UBYTE UniGetByte ( void ) ;
extern UWORD UniGetWord ( void ) ;
extern UBYTE * UniFindRow ( UBYTE * , UWORD ) ;
extern void UniSkipOpcode ( void ) ;
extern void UniReset ( void ) ;
extern void UniWriteByte ( UBYTE ) ;
extern void UniWriteWord ( UWORD ) ;
extern void UniNewline ( void ) ;
extern UBYTE * UniDup ( void ) ;
extern int UniInit ( void ) ;
extern void UniCleanup ( void ) ;
extern void UniEffect ( UWORD , UWORD ) ;
2020-08-09 01:56:15 +00:00
# define UniInstrument(x) UniEffect(UNI_INSTRUMENT,x)
# define UniNote(x) UniEffect(UNI_NOTE,x)
2010-12-12 15:03:30 +00:00
extern void UniPTEffect ( UBYTE , UBYTE ) ;
extern void UniVolEffect ( UWORD , UBYTE ) ;
/*========== Module Commands */
enum {
2020-08-09 01:56:15 +00:00
/* Simple note */
UNI_NOTE = 1 ,
/* Instrument change */
UNI_INSTRUMENT ,
/* Protracker effects */
UNI_PTEFFECT0 , /* arpeggio */
UNI_PTEFFECT1 , /* porta up */
UNI_PTEFFECT2 , /* porta down */
UNI_PTEFFECT3 , /* porta to note */
UNI_PTEFFECT4 , /* vibrato */
UNI_PTEFFECT5 , /* dual effect 3+A */
UNI_PTEFFECT6 , /* dual effect 4+A */
UNI_PTEFFECT7 , /* tremolo */
UNI_PTEFFECT8 , /* pan */
UNI_PTEFFECT9 , /* sample offset */
UNI_PTEFFECTA , /* volume slide */
UNI_PTEFFECTB , /* pattern jump */
UNI_PTEFFECTC , /* set volume */
UNI_PTEFFECTD , /* pattern break */
UNI_PTEFFECTE , /* extended effects */
UNI_PTEFFECTF , /* set speed */
/* Scream Tracker effects */
UNI_S3MEFFECTA , /* set speed */
UNI_S3MEFFECTD , /* volume slide */
UNI_S3MEFFECTE , /* porta down */
UNI_S3MEFFECTF , /* porta up */
UNI_S3MEFFECTI , /* tremor */
UNI_S3MEFFECTQ , /* retrig */
UNI_S3MEFFECTR , /* tremolo */
UNI_S3MEFFECTT , /* set tempo */
UNI_S3MEFFECTU , /* fine vibrato */
UNI_KEYOFF , /* note off */
/* Fast Tracker effects */
UNI_KEYFADE , /* note fade */
UNI_VOLEFFECTS , /* volume column effects */
UNI_XMEFFECT4 , /* vibrato */
UNI_XMEFFECT6 , /* dual effect 4+A */
UNI_XMEFFECTA , /* volume slide */
UNI_XMEFFECTE1 , /* fine porta up */
UNI_XMEFFECTE2 , /* fine porta down */
UNI_XMEFFECTEA , /* fine volume slide up */
UNI_XMEFFECTEB , /* fine volume slide down */
UNI_XMEFFECTG , /* set global volume */
UNI_XMEFFECTH , /* global volume slide */
UNI_XMEFFECTL , /* set envelope position */
UNI_XMEFFECTP , /* pan slide */
UNI_XMEFFECTX1 , /* extra fine porta up */
UNI_XMEFFECTX2 , /* extra fine porta down */
/* Impulse Tracker effects */
UNI_ITEFFECTG , /* porta to note */
UNI_ITEFFECTH , /* vibrato */
UNI_ITEFFECTI , /* tremor (xy not incremented) */
UNI_ITEFFECTM , /* set channel volume */
UNI_ITEFFECTN , /* slide / fineslide channel volume */
UNI_ITEFFECTP , /* slide / fineslide channel panning */
UNI_ITEFFECTT , /* slide tempo */
UNI_ITEFFECTU , /* fine vibrato */
UNI_ITEFFECTW , /* slide / fineslide global volume */
UNI_ITEFFECTY , /* panbrello */
UNI_ITEFFECTZ , /* resonant filters */
UNI_ITEFFECTS0 ,
/* UltraTracker effects */
UNI_ULTEFFECT9 , /* Sample fine offset */
/* OctaMED effects */
UNI_MEDSPEED ,
UNI_MEDEFFECTF1 , /* play note twice */
UNI_MEDEFFECTF2 , /* delay note */
UNI_MEDEFFECTF3 , /* play note three times */
/* Oktalyzer effects */
UNI_OKTARP , /* arpeggio */
UNI_LAST
2010-12-12 15:03:30 +00:00
} ;
2020-08-09 01:56:15 +00:00
extern const UWORD unioperands [ UNI_LAST ] ;
2010-12-12 15:03:30 +00:00
/* IT / S3M Extended SS effects: */
enum {
2020-08-09 01:56:15 +00:00
SS_GLISSANDO = 1 ,
SS_FINETUNE ,
SS_VIBWAVE ,
SS_TREMWAVE ,
SS_PANWAVE ,
SS_FRAMEDELAY ,
SS_S7EFFECTS ,
SS_PANNING ,
SS_SURROUND ,
SS_HIOFFSET ,
SS_PATLOOP ,
SS_NOTECUT ,
SS_NOTEDELAY ,
SS_PATDELAY
2010-12-12 15:03:30 +00:00
} ;
/* IT Volume column effects */
enum {
2020-08-09 01:56:15 +00:00
VOL_VOLUME = 1 ,
VOL_PANNING ,
VOL_VOLSLIDE ,
VOL_PITCHSLIDEDN ,
VOL_PITCHSLIDEUP ,
VOL_PORTAMENTO ,
VOL_VIBRATO
2010-12-12 15:03:30 +00:00
} ;
/* IT resonant filter information */
2020-08-09 01:56:15 +00:00
# define UF_MAXMACRO 0x10
# define UF_MAXFILTER 0x100
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define FILT_CUT 0x80
# define FILT_RESONANT 0x81
2010-12-12 15:03:30 +00:00
typedef struct FILTER {
UBYTE filter , inf ;
} FILTER ;
/*========== Instruments */
/* Instrument format flags */
# define IF_OWNPAN 1
# define IF_PITCHPAN 2
/* Envelope flags: */
# define EF_ON 1
# define EF_SUSTAIN 2
# define EF_LOOP 4
# define EF_VOLENV 8
/* New Note Action Flags */
# define NNA_CUT 0
# define NNA_CONTINUE 1
# define NNA_OFF 2
# define NNA_FADE 3
# define NNA_MASK 3
# define DCT_OFF 0
# define DCT_NOTE 1
# define DCT_SAMPLE 2
# define DCT_INST 3
# define DCA_CUT 0
# define DCA_OFF 1
# define DCA_FADE 2
# define KEY_KICK 0
# define KEY_OFF 1
# define KEY_FADE 2
# define KEY_KILL (KEY_OFF|KEY_FADE)
# define KICK_ABSENT 0
# define KICK_NOTE 1
# define KICK_KEYOFF 2
# define KICK_ENV 4
# define AV_IT 1 /* IT vs. XM vibrato info */
/*========== Playing */
2020-08-09 01:56:15 +00:00
# define POS_NONE (-2) /* no loop position defined */
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# define LAST_PATTERN (UWORD)(-1) /* special ``end of song'' pattern */
2010-12-12 15:03:30 +00:00
typedef struct ENVPR {
2020-08-09 01:56:15 +00:00
UBYTE flg ; /* envelope flag */
UBYTE pts ; /* number of envelope points */
UBYTE susbeg ; /* envelope sustain index begin */
UBYTE susend ; /* envelope sustain index end */
UBYTE beg ; /* envelope loop begin */
UBYTE end ; /* envelope loop end */
SWORD p ; /* current envelope counter */
UWORD a ; /* envelope index a */
UWORD b ; /* envelope index b */
ENVPT * env ; /* envelope points */
2010-12-12 15:03:30 +00:00
} ENVPR ;
typedef struct MP_CHANNEL {
2020-08-09 01:56:15 +00:00
INSTRUMENT * i ;
SAMPLE * s ;
UBYTE sample ; /* which sample number */
UBYTE note ; /* the audible note as heard, direct rep of period */
SWORD outvolume ; /* output volume (vol + sampcol + instvol) */
SBYTE chanvol ; /* channel's "global" volume */
UWORD fadevol ; /* fading volume rate */
SWORD panning ; /* panning position */
UBYTE kick ; /* if true = sample has to be restarted */
UBYTE kick_flag ; /* kick has been true */
UWORD period ; /* period to play the sample at */
UBYTE nna ; /* New note action type + master/slave flags */
UBYTE volflg ; /* volume envelope settings */
UBYTE panflg ; /* panning envelope settings */
UBYTE pitflg ; /* pitch envelope settings */
UBYTE keyoff ; /* if true = fade out and stuff */
SWORD handle ; /* which sample-handle */
UBYTE notedelay ; /* (used for note delay) */
SLONG start ; /* The starting byte index in the sample */
2010-12-12 15:03:30 +00:00
} MP_CHANNEL ;
typedef struct MP_CONTROL {
2020-08-09 01:56:15 +00:00
struct MP_CHANNEL main ;
struct MP_VOICE * slave ; /* Audio Slave of current effects control channel */
UBYTE slavechn ; /* Audio Slave of current effects control channel */
UBYTE muted ; /* if set, channel not played */
UWORD ultoffset ; /* fine sample offset memory */
UBYTE anote ; /* the note that indexes the audible */
UBYTE oldnote ;
SWORD ownper ;
SWORD ownvol ;
UBYTE dca ; /* duplicate check action */
UBYTE dct ; /* duplicate check type */
UBYTE * row ; /* row currently playing on this channel */
SBYTE retrig ; /* retrig value (0 means don't retrig) */
ULONG speed ; /* what finetune to use */
SWORD volume ; /* amiga volume (0 t/m 64) to play the sample at */
SWORD tmpvolume ; /* tmp volume */
UWORD tmpperiod ; /* tmp period */
UWORD wantedperiod ; /* period to slide to (with effect 3 or 5) */
UBYTE arpmem ; /* arpeggio command memory */
UBYTE pansspd ; /* panslide speed */
UWORD slidespeed ;
UWORD portspeed ; /* noteslide speed (toneportamento) */
UBYTE s3mtremor ; /* s3m tremor (effect I) counter */
UBYTE s3mtronof ; /* s3m tremor ontime/offtime */
UBYTE s3mvolslide ; /* last used volslide */
SBYTE sliding ;
UBYTE s3mrtgspeed ; /* last used retrig speed */
UBYTE s3mrtgslide ; /* last used retrig slide */
UBYTE glissando ; /* glissando (0 means off) */
UBYTE wavecontrol ;
SBYTE vibpos ; /* current vibrato position */
UBYTE vibspd ; /* "" speed */
UBYTE vibdepth ; /* "" depth */
SBYTE trmpos ; /* current tremolo position */
UBYTE trmspd ; /* "" speed */
UBYTE trmdepth ; /* "" depth */
UBYTE fslideupspd ;
UBYTE fslidednspd ;
UBYTE fportupspd ; /* fx E1 (extra fine portamento up) data */
UBYTE fportdnspd ; /* fx E2 (extra fine portamento dn) data */
UBYTE ffportupspd ; /* fx X1 (extra fine portamento up) data */
UBYTE ffportdnspd ; /* fx X2 (extra fine portamento dn) data */
ULONG hioffset ; /* last used high order of sample offset */
UWORD soffset ; /* last used low order of sample-offset (effect 9) */
UBYTE sseffect ; /* last used Sxx effect */
UBYTE ssdata ; /* last used Sxx data info */
UBYTE chanvolslide ; /* last used channel volume slide */
UBYTE panbwave ; /* current panbrello waveform */
UBYTE panbpos ; /* current panbrello position */
SBYTE panbspd ; /* "" speed */
UBYTE panbdepth ; /* "" depth */
UWORD newsamp ; /* set to 1 upon a sample / inst change */
UBYTE voleffect ; /* Volume Column Effect Memory as used by IT */
UBYTE voldata ; /* Volume Column Data Memory */
SWORD pat_reppos ; /* patternloop position */
UWORD pat_repcnt ; /* times to loop */
2010-12-12 15:03:30 +00:00
} MP_CONTROL ;
/* Used by NNA only player (audio control. AUDTMP is used for full effects
control ) . */
typedef struct MP_VOICE {
2020-08-09 01:56:15 +00:00
struct MP_CHANNEL main ;
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
ENVPR venv ;
ENVPR penv ;
ENVPR cenv ;
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
UWORD avibpos ; /* autovibrato pos */
UWORD aswppos ; /* autovibrato sweep pos */
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
ULONG totalvol ; /* total volume of channel (before global mixings) */
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
int mflag ;
SWORD masterchn ;
UWORD masterperiod ;
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
MP_CONTROL * master ; /* index of "master" effects channel */
2010-12-12 15:03:30 +00:00
} MP_VOICE ;
/*========== Loaders */
typedef struct MLOADER {
2020-08-09 01:56:15 +00:00
struct MLOADER * next ;
const CHAR * type ;
const CHAR * version ;
int ( * Init ) ( void ) ;
int ( * Test ) ( void ) ;
int ( * Load ) ( int ) ;
void ( * Cleanup ) ( void ) ;
CHAR * ( * LoadTitle ) ( void ) ;
2010-12-12 15:03:30 +00:00
} MLOADER ;
/* internal loader variables */
extern MREADER * modreader ;
extern MODULE of ; /* static unimod loading space */
2020-08-09 01:56:15 +00:00
extern const UWORD finetune [ 16 ] ;
extern const UWORD npertab [ 7 * OCTAVE ] ; /* used by the original MOD loaders */
2010-12-12 15:03:30 +00:00
extern SBYTE remap [ UF_MAXCHAN ] ; /* for removing empty channels */
extern UBYTE * poslookup ; /* lookup table for pattern jumps after
2020-08-09 01:56:15 +00:00
blank pattern removal */
2010-12-12 15:03:30 +00:00
extern UWORD poslookupcnt ;
extern UWORD * origpositions ;
extern int filters ; /* resonant filters in use */
extern UBYTE activemacro ; /* active midi macro number for Sxx */
extern UBYTE filtermacros [ UF_MAXMACRO ] ; /* midi macro settings */
extern FILTER filtersettings [ UF_MAXFILTER ] ; /* computed filter settings */
extern int * noteindex ;
/*========== Internal loader interface */
extern int ReadComment ( UWORD ) ;
extern int ReadLinedComment ( UWORD , UWORD ) ;
extern int AllocPositions ( int ) ;
extern int AllocPatterns ( void ) ;
extern int AllocTracks ( void ) ;
extern int AllocInstruments ( void ) ;
extern int AllocSamples ( void ) ;
2020-08-09 01:56:15 +00:00
extern CHAR * DupStr ( const CHAR * , UWORD , int ) ;
2010-12-12 15:03:30 +00:00
/* loader utility functions */
extern int * AllocLinear ( void ) ;
extern void FreeLinear ( void ) ;
extern int speed_to_finetune ( ULONG , int ) ;
extern void S3MIT_ProcessCmd ( UBYTE , UBYTE , unsigned int ) ;
extern void S3MIT_CreateOrders ( int ) ;
/* flags for S3MIT_ProcessCmd */
2020-08-09 01:56:15 +00:00
# define S3MIT_OLDSTYLE 1 /* behave as old scream tracker */
# define S3MIT_IT 2 /* behave as impulse tracker */
# define S3MIT_SCREAM 4 /* enforce scream tracker specific limits */
2010-12-12 15:03:30 +00:00
/* used to convert c4spd to linear XM periods (IT and IMF loaders). */
extern UWORD getlinearperiod ( UWORD , ULONG ) ;
extern ULONG getfrequency ( UWORD , ULONG ) ;
/* loader shared data */
2020-08-09 01:56:15 +00:00
# define STM_NTRACKERS 3
extern const CHAR * STM_Signatures [ STM_NTRACKERS ] ;
2010-12-12 15:03:30 +00:00
/*========== Player interface */
2020-08-09 01:56:15 +00:00
extern int Player_Init ( MODULE * ) ;
2010-12-12 15:03:30 +00:00
extern void Player_Exit ( MODULE * ) ;
extern void Player_HandleTick ( void ) ;
2020-08-09 01:56:15 +00:00
/*========== UnPackers */
typedef int ( * MUNPACKER ) ( struct MREADER * ,
void * * /* unpacked data out */ ,
long * /* unpacked data size */ ) ;
extern int PP20_Unpack ( MREADER * , void * * , long * ) ;
extern int MMCMP_Unpack ( MREADER * , void * * , long * ) ;
extern int XPK_Unpack ( MREADER * , void * * , long * ) ;
extern int S404_Unpack ( MREADER * , void * * , long * ) ;
2010-12-12 15:03:30 +00:00
/*========== Drivers */
/* max. number of handles a driver has to provide. (not strict) */
2020-08-09 01:56:15 +00:00
# define MAXSAMPLEHANDLES 384
2010-12-12 15:03:30 +00:00
/* These variables can be changed at ANY time and results will be immediate */
extern UWORD md_bpm ; /* current song / hardware BPM rate */
/* Variables below can be changed via MD_SetNumVoices at any time. However, a
call to MD_SetNumVoicess while the driver is active will cause the sound to
skip slightly . */
extern UBYTE md_numchn ; /* number of song + sound effects voices */
extern UBYTE md_sngchn ; /* number of song voices */
extern UBYTE md_sfxchn ; /* number of sound effects voices */
extern UBYTE md_hardchn ; /* number of hardware mixed voices */
extern UBYTE md_softchn ; /* number of software mixed voices */
/* This is for use by the hardware drivers only. It points to the registered
tickhandler function . */
2020-08-09 01:56:15 +00:00
extern MikMod_player_t md_player ;
2010-12-12 15:03:30 +00:00
extern SWORD MD_SampleLoad ( SAMPLOAD * , int ) ;
extern void MD_SampleUnload ( SWORD ) ;
extern ULONG MD_SampleSpace ( int ) ;
extern ULONG MD_SampleLength ( int , SAMPLE * ) ;
/* uLaw conversion */
extern void unsignedtoulaw ( char * , int ) ;
/* Parameter extraction helper */
2020-08-09 01:56:15 +00:00
extern CHAR * MD_GetAtom ( const CHAR * , const CHAR * , int ) ;
2010-12-12 15:03:30 +00:00
/* Internal software mixer stuff */
extern void VC_SetupPointers ( void ) ;
2020-08-09 01:56:15 +00:00
extern int VC1_Init ( void ) ;
extern int VC2_Init ( void ) ;
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# if (MIKMOD_UNIX)
2010-12-12 15:03:30 +00:00
/* POSIX helper functions */
2020-08-09 01:56:15 +00:00
extern int MD_Access ( const CHAR * ) ;
extern int MD_DropPrivileges ( void ) ;
2010-12-12 15:03:30 +00:00
# endif
/* Macro to define a missing driver, yet allowing binaries to dynamically link
with the library without missing symbol errors */
# define MISSING(a) MDRIVER a = { NULL, NULL, NULL, 0, 0 }
/*========== Prototypes for non-MT safe versions of some public functions */
extern void _mm_registerdriver ( struct MDRIVER * ) ;
extern void _mm_registerloader ( struct MLOADER * ) ;
extern int MikMod_Active_internal ( void ) ;
extern void MikMod_DisableOutput_internal ( void ) ;
2020-08-09 01:56:15 +00:00
extern int MikMod_EnableOutput_internal ( void ) ;
2010-12-12 15:03:30 +00:00
extern void MikMod_Exit_internal ( void ) ;
2020-08-09 01:56:15 +00:00
extern int MikMod_SetNumVoices_internal ( int , int ) ;
2010-12-12 15:03:30 +00:00
extern void Player_Exit_internal ( MODULE * ) ;
extern void Player_Stop_internal ( void ) ;
extern int Player_Paused_internal ( void ) ;
extern void Sample_Free_internal ( SAMPLE * ) ;
extern void Voice_Play_internal ( SBYTE , SAMPLE * , ULONG ) ;
extern void Voice_SetFrequency_internal ( SBYTE , ULONG ) ;
extern void Voice_SetPanning_internal ( SBYTE , ULONG ) ;
extern void Voice_SetVolume_internal ( SBYTE , UWORD ) ;
extern void Voice_Stop_internal ( SBYTE ) ;
extern int Voice_Stopped_internal ( SBYTE ) ;
2020-08-09 01:56:15 +00:00
extern int VC1_PlayStart ( void ) ;
extern int VC2_PlayStart ( void ) ;
extern void VC1_PlayStop ( void ) ;
extern void VC2_PlayStop ( void ) ;
extern int VC1_SetNumVoices ( void ) ;
extern int VC2_SetNumVoices ( void ) ;
extern MikMod_callback_t vc_callback ;
2010-12-12 15:03:30 +00:00
# ifdef __cplusplus
}
# endif
/*========== SIMD mixing routines */
# undef HAVE_ALTIVEC
# undef HAVE_SSE2
2020-08-09 01:56:15 +00:00
# if defined(MIKMOD_SIMD)
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# if (defined(__ppc__) || defined(__ppc64__)) && defined(__VEC__) && !(defined(__GNUC__) && (__GNUC__ < 3))
2010-12-12 15:03:30 +00:00
# define HAVE_ALTIVEC
2020-08-09 01:56:15 +00:00
# elif defined(__GNUC__) && defined(__SSE2__) /* x86 / x86_64 */
2010-12-12 15:03:30 +00:00
# define HAVE_SSE2
2020-08-09 01:56:15 +00:00
# elif defined(_MSC_VER) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64))
/* FIXME: emmintrin.h requires VC6 processor pack or VC2003+ */
# define HAVE_SSE2
/* avoid some warnings */
2010-12-12 15:03:30 +00:00
# pragma warning(disable:4761)
# pragma warning(disable:4391)
# pragma warning(disable:4244)
2020-08-09 01:56:15 +00:00
# endif /* AltiVec/SSE2 */
# endif /* MIKMOD_SIMD */
2010-12-12 15:03:30 +00:00
/*========== SIMD mixing helper functions =============*/
2020-08-09 01:56:15 +00:00
# if defined(_WIN64)
# if defined(_MSC_VER)
# define IS_ALIGNED_16(ptr) (!((__int64)(ptr) & 15i64))
# else /* GCC, LCC, .. */
# define IS_ALIGNED_16(ptr) (!((long long)(ptr) & 15LL))
# endif
# else /* long cast should be OK for all else */
# define IS_ALIGNED_16(ptr) (!((long)(ptr) & 15L))
# endif
2010-12-12 15:03:30 +00:00
/* Altivec helper function */
# if defined HAVE_ALTIVEC
# define simd_m128i vector signed int
# define simd_m128 vector float
# ifdef __GNUC__
# include <ppc_intrinsics.h>
# endif
2020-08-09 01:56:15 +00:00
/* Helper functions */
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
/* Set single float across the four values */
static inline vector float vec_mul ( const vector float a , const vector float b ) {
2010-12-12 15:03:30 +00:00
return vec_madd ( a , b , ( const vector float ) ( 0.f ) ) ;
}
2020-08-09 01:56:15 +00:00
/* Set single float across the four values */
static inline vector float vec_load_ps1 ( const float * pF ) {
2010-12-12 15:03:30 +00:00
vector float data = vec_lde ( 0 , pF ) ;
return vec_splat ( vec_perm ( data , data , vec_lvsl ( 0 , pF ) ) , 0 ) ;
}
2020-08-09 01:56:15 +00:00
/* Set vector to 0 */
static inline vector float vec_setzero ( ) {
return ( vector float ) ( 0. ) ;
2010-12-12 15:03:30 +00:00
}
2020-08-09 01:56:15 +00:00
static inline vector signed char vec_set1_8 ( unsigned char splatchar ) {
vector unsigned char splatmap = vec_lvsl ( 0 , & splatchar ) ;
vector unsigned char result = vec_lde ( 0 , & splatchar ) ;
splatmap = vec_splat ( splatmap , 0 ) ;
return ( vector signed char ) vec_perm ( result , result , splatmap ) ;
2010-12-12 15:03:30 +00:00
}
# define PERM_A0 0x00,0x01,0x02,0x03
# define PERM_A1 0x04,0x05,0x06,0x07
# define PERM_A2 0x08,0x09,0x0A,0x0B
# define PERM_A3 0x0C,0x0D,0x0E,0x0F
# define PERM_B0 0x10,0x11,0x12,0x13
# define PERM_B1 0x14,0x15,0x16,0x17
# define PERM_B2 0x18,0x19,0x1A,0x1B
# define PERM_B3 0x1C,0x1D,0x1E,0x1F
2020-08-09 01:56:15 +00:00
/* Equivalent to _mm_unpacklo_epi32 */
static inline vector signed int vec_unpacklo ( vector signed int a , vector signed int b ) {
2010-12-12 15:03:30 +00:00
return vec_perm ( a , b , ( vector unsigned char ) ( PERM_A0 , PERM_A1 , PERM_B0 , PERM_B1 ) ) ;
}
2020-08-09 01:56:15 +00:00
/* Equivalent to _mm_srli_si128(a, 8) (without the zeroing in high part). */
static inline vector signed int vec_hiqq ( vector signed int a ) {
2010-12-12 15:03:30 +00:00
vector signed int b = vec_splat_s32 ( 0 ) ;
return vec_perm ( a , b , ( vector unsigned char ) ( PERM_A2 , PERM_A3 , PERM_B2 , PERM_B3 ) ) ;
}
2020-08-09 01:56:15 +00:00
/* vec_sra is max +15. We have to do in two times ... */
# define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = vec_mul(vec_ctf(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(BITSHIFT-size)),0), mul);
# define EXTRACT_SAMPLE_SIMD_0(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-0));
# define EXTRACT_SAMPLE_SIMD_8(srce, var) var = vec_sra(vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(15)), vec_splat_u32(BITSHIFT+16-15-8));
# define EXTRACT_SAMPLE_SIMD_16(srce, var) var = vec_sra(vec_ld(0, (vector signed int const *)(srce)), vec_splat_u32(BITSHIFT+16-16));
# define PUT_SAMPLE_SIMD_W(dste, v1, v2) vec_st(vec_packs(v1, v2), 0, dste);
# define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) vec_st(vec_add(vec_packs((vector signed short)vec_packs(v1, v2), (vector signed short)vec_packs(v3, v4)), vec_set1_8(128)), 0, dste);
2010-12-12 15:03:30 +00:00
# define PUT_SAMPLE_SIMD_F(dste, v1) vec_st(v1, 0, dste);
# define LOAD_PS1_SIMD(ptr) vec_load_ps1(ptr)
# elif defined HAVE_SSE2
# include <emmintrin.h>
2020-08-09 01:56:15 +00:00
/* SSE2 helper function */
static __inline __m128i mm_hiqq ( const __m128i a ) {
return _mm_srli_si128 ( a , 8 ) ; /* get the 64bit upper part. new 64bit upper is undefined (zeroed is fine). */
2010-12-12 15:03:30 +00:00
}
/* 128-bit mixing macros */
2020-08-09 01:56:15 +00:00
# define EXTRACT_SAMPLE_SIMD(srce, var, size) var = _mm_srai_epi32(_mm_load_si128((__m128i const *)(srce)), BITSHIFT+16-size);
# define EXTRACT_SAMPLE_SIMD_F(srce, var, size, mul) var = _mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_load_si128((__m128i const *)(srce)), BITSHIFT-size)), mul);
2010-12-12 15:03:30 +00:00
# define EXTRACT_SAMPLE_SIMD_0(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 0)
# define EXTRACT_SAMPLE_SIMD_8(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 8)
# define EXTRACT_SAMPLE_SIMD_16(srce, var) EXTRACT_SAMPLE_SIMD(srce, var, 16)
2020-08-09 01:56:15 +00:00
# define PUT_SAMPLE_SIMD_W(dste, v1, v2) _mm_store_si128((__m128i*)(dste), _mm_packs_epi32(v1, v2));
# define PUT_SAMPLE_SIMD_B(dste, v1, v2, v3, v4) _mm_store_si128((__m128i*)(dste), _mm_add_epi8(_mm_packs_epi16(_mm_packs_epi32(v1, v2), _mm_packs_epi32(v3, v4)), _mm_set1_epi8(128)));
2010-12-12 15:03:30 +00:00
# define PUT_SAMPLE_SIMD_F(dste, v1) _mm_store_ps((float*)(dste), v1);
# define LOAD_PS1_SIMD(ptr) _mm_load_ps1(ptr)
# define simd_m128i __m128i
# define simd_m128 __m128
# endif
2020-08-09 01:56:15 +00:00
# if defined(HAVE_SSE2) || defined(HAVE_ALTIVEC)
/* MikMod_amalloc() returns a 16 byte aligned zero-filled
memory in SIMD - enabled builds .
- the returned memory can be freed with MikMod_afree ( )
- the returned memory CAN NOT be realloc ( ) ' ed safely . */
# ifdef __cplusplus
extern " C " {
# endif
void * MikMod_amalloc ( size_t ) ;
void MikMod_afree ( void * ) ; /* frees if ptr != NULL */
# ifdef __cplusplus
}
# endif
2010-12-12 15:03:30 +00:00
2020-08-09 01:56:15 +00:00
# else /* NO SIMD */
# define MikMod_amalloc MikMod_malloc
# define MikMod_afree MikMod_free
2010-12-12 15:03:30 +00:00
# endif
2020-08-09 01:56:15 +00:00
# endif /* _MIKMOD_INTERNALS_H */
2010-12-12 15:03:30 +00:00
/* ex:set ts=4: */