AG_GST_CHECK_PLUGIN(freeze)
AG_GST_CHECK_PLUGIN(h264parse)
AG_GST_CHECK_PLUGIN(librfb)
-AG_GST_CHECK_PLUGIN(modplug)
AG_GST_CHECK_PLUGIN(mpegdemux)
AG_GST_CHECK_PLUGIN(mpegtsmux)
AG_GST_CHECK_PLUGIN(mpeg4videoparse)
dnl *** plug-ins to exclude ***
-dnl see if we can build C++ plug-ins
-if test "x$HAVE_CXX" != "xyes"; then
- AC_MSG_WARN([Not compiling plug-ins requiring C++ compiler])
- AG_GST_DISABLE_PLUGIN(modplug)
-fi
-
dnl real plugin only works on i386 and x86_64 for the time being.
if test "x$HAVE_CPU_I386" != "xyes" && test "x$HAVE_CPU_X86_64" != "xyes"; then
AC_MSG_WARN([Not building real plugin, only works on 32bit and 64bit x86 platforms])
])
AC_SUBST(LIBMMS_LIBS)
+dnl *** modplug ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_MODPLUG, true)
+AG_GST_CHECK_FEATURE(MODPLUG, modplug, modplug, [
+ if test "x$HAVE_CXX" != "xyes"; then
+ AC_MSG_WARN([Not compiling modplug plugin as it requires a C++ compiler])
+ HAVE_MODPLUG="no"
+ else
+ PKG_CHECK_MODULES(MODPLUG, libmodplug, HAVE_MODPLUG="yes", HAVE_MODPLUG="no")
+ fi
+ AC_SUBST(MODPLUG_CFLAGS)
+ AC_SUBST(MODPLUG_LIBS)
+])
+
dnl *** mjpegtools version info ***
dnl some may prefer older version (given quirks above)
dnl hm, no version info seems available within mjpegtools headers
AM_CONDITIONAL(USE_JP2K, false)
AM_CONDITIONAL(USE_LADSPA, false)
AM_CONDITIONAL(USE_LIBMMS, false)
+AM_CONDITIONAL(USE_MODPLUG, false)
AM_CONDITIONAL(USE_METADATA, false)
AM_CONDITIONAL(USE_MPEG2ENC, false)
AM_CONDITIONAL(USE_MPLEX, false)
gst/freeze/Makefile
gst/h264parse/Makefile
gst/librfb/Makefile
-gst/modplug/Makefile
-gst/modplug/libmodplug/Makefile
gst/mpegdemux/Makefile
gst/mpegtsmux/Makefile
gst/mpegtsmux/tsmux/Makefile
ext/libmms/Makefile
ext/Makefile
ext/nas/Makefile
+ext/modplug/Makefile
ext/mpeg2enc/Makefile
ext/mplex/Makefile
ext/musepack/Makefile
$(top_srcdir)/ext/metadata/gstbasemetadata.h \
$(top_srcdir)/ext/metadata/gstmetadatademux.h \
$(top_srcdir)/ext/metadata/gstmetadatamux.h \
+ $(top_srcdir)/ext/modplug/gstmodplug.h \
$(top_srcdir)/ext/mpeg2enc/gstmpeg2enc.hh \
$(top_srcdir)/ext/mplex/gstmplex.hh \
$(top_srcdir)/ext/mythtv/gstmythtvsrc.h \
$(top_srcdir)/gst/dccp/gstdccpserversrc.h \
$(top_srcdir)/gst/dvdspu/gstdvdspu.h \
$(top_srcdir)/gst/festival/gstfestival.h \
- $(top_srcdir)/gst/modplug/gstmodplug.h \
$(top_srcdir)/gst/mxf/mxfdemux.h \
$(top_srcdir)/gst/nuvdemux/gstnuvdemux.h \
$(top_srcdir)/gst/rawparse/gstaudioparse.h \
LIBMMS_DIR=
endif
+if USE_MODPLUG
+MODPLUG_DIR=modplug
+else
+MODPLUG_DIR=
+endif
+
if USE_MPEG2ENC
MPEG2ENC_DIR=mpeg2enc
else
$(LCS_DIR) \
$(LIBFAME_DIR) \
$(LIBMMS_DIR) \
+ $(MODPLUG_DIR) \
$(MPEG2ENC_DIR) \
$(METADATA_DIR) \
$(MPLEX_DIR) \
libmms \
dts \
divx \
+ modplug \
metadata \
mpeg2enc \
mplex \
-SUBDIRS=libmodplug .
-
plugin_LTLIBRARIES = libgstmodplug.la
libgstmodplug_la_SOURCES = gstmodplug.cc
-libgstmodplug_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CXXFLAGS)
-libgstmodplug_la_LIBADD = $(top_builddir)/gst/modplug/libmodplug/libmodplug.la $(GST_PLUGINS_BASE_LIBS) -lstdc++ $(LIBM)
+libgstmodplug_la_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CXXFLAGS) $(MODPLUG_CFLAGS)
+libgstmodplug_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lstdc++ $(LIBM) $(MODPLUG_LIBS)
libgstmodplug_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmodplug_la_LIBTOOLFLAGS = --tag=disable-static
#include "config.h"
#endif
-#include "libmodplug/stdafx.h"
-#include "libmodplug/sndfile.h"
+#include <stdafx.h>
+#include <sndfile.h>
#include "gstmodplug.h"
+++ /dev/null
-noinst_LTLIBRARIES = libmodplug.la
-
-libmodplug_la_CXXFLAGS = $(GST_CXXFLAGS) -D_REENTRANT
-libmodplug_la_LDFLAGS = -module -avoid-version
-libmodplug_la_SOURCES = tables.cpp \
- sndmix.cpp \
- sndfile.cpp \
- snd_fx.cpp \
- snd_flt.cpp \
- snd_dsp.cpp \
- fastmix.cpp \
- mmcmp.cpp \
- load_xm.cpp \
- load_wav.cpp \
- load_umx.cpp \
- load_ult.cpp \
- load_stm.cpp \
- load_s3m.cpp \
- load_ptm.cpp \
- load_okt.cpp \
- load_mtm.cpp \
- load_mod.cpp \
- load_med.cpp \
- load_mdl.cpp \
- load_it.cpp \
- load_far.cpp \
- load_dsm.cpp \
- load_dmf.cpp \
- load_dbm.cpp \
- load_ams.cpp \
- load_amf.cpp \
- load_669.cpp \
- load_j2b.cpp \
- load_mt2.cpp \
- load_psm.cpp \
- modplug.cpp
-
-noinst_HEADERS = it_defs.h stdafx.h sndfile.h modplug.h
-
-EXTRA_DIST = changes.txt
+++ /dev/null
-libmodplug v0.7 - A library for decoding MOD-like music formats.
- Based on the ModPlug sound engine by Olivier Lapicque <olivierl@jps.net>
- Ported to Unix by Kenton Varda <temporal@gauge3d.org>
- Additional modifications by Markus Fick <marf@gmx.net> and
- Adam Goode <adam@evdebs.org>
- Placed in the public domain in October, 2001
-
-
-All the documentation needed can be found in the comments in modplug.h.
-This library should be perfectly accessible from C, although it is written
-in C++. Just #include <modplug.h> to use it, and link against
-libmodplug.so.
-
-This library has been known to compile fine in Windows using MinGW32 (A
-GCC-based compiler). Windows is not yet officially supported, however.
-(With about half an hour of hacking, any decent programmer should be able
-to convince WinAmp to play mods using this library. ;) )
-
-I need a maintainer for this. I have too many other projects I am working
-on, and ModPlug has dropped low on the list. If you would like to be the
-new maintainer, please e-mail me at <temporal@gauge3d.org> and tell me why
-you think you would be the right person for the job. :)
\ No newline at end of file
+++ /dev/null
-changes:\r
-date = 09-feb-2001 [Markus Fick]\r
--> file: fastmix.cpp\r
- where: spline creation, spline macros\r
- what: added unity gain clamp code, added Quantizer_Bits(shift) preprocessor constants\r
- where: fir creation, fir macros\r
- what: - removed x<pi/2 condition in coef creation\r
- - added quantizer_bits(shift) preprocessor constants\r
- - set default quantizer bits to 15 instead 14 (scale now 32768 instead 16384)\r
- there should not occure any overflows during fir response calculation because\r
- of the symmetric form of filter and the position of the negative fir coefs\r
- - changed final volume calculation for 16bit samples (quality enhancement)\r
-\r
-date = 08-feb-2001 [Markus Fick]\r
--> file: sndmix.cpp\r
- where: function ReadNote()\r
- what: modified behaviour of modplug so that interpolation is only deactivated if\r
- a) the user selects "no interpolation"\r
- b) linear interpolation is set and speed incr. > 0xff00\r
- => if spline or fir is active then we use always interpolation\r
-\r
--> file: fastmix.cpp\r
- where: spline macros\r
- what: changed spline macros to use precalculated tables (way faster)\r
- where: file\r
- what: - implemented spline table precalculator\r
- - changed fir precalculator + macros (for higher quality and clearer source)\r
- - added some comments and documentation\r
- comment: \r
- - preprocessor constant: SPLINE_FRACBITS\r
- ) controls quality/memory usage\r
- range is [4..14] inclusive\r
- 4 = low quality, low memory usage\r
- 14 = highest quality, highest memory usage (1L<<14)*4*2 bytes\r
- - preprocessor constant: WFIR_FRACBITS\r
- ) controls quality/memory usage\r
- range is [4..12] inclusive\r
- 4 = low quality, low mu\r
- 12 = highest quality, highest memory usage ((1L<<(12+1))+1)*8*2 bytes\r
-\r
-date = 07-feb-2001 [Markus Fick]\r
--> file: fastmix.cpp\r
- where: spline macros\r
- what: fixed error in coef calculation\r
-\r
-date = 07-feb-2001 [Markus Fick]\r
--> file: sndfile.h\r
- where: class definition of soundfile \r
- what: removed InitFIR + DoneFIR function prototypes\r
--> file: sndfile.cpp\r
- function:CSoundFile::CSoundFile()\r
- what: [modify] removed call to CSoundFile::InitFIRMixer( )\r
-\r
- function:CSoundFile::~CSoundFile()\r
- what: [modify] removed call to CSoundFile::DoneFIRMixer( )\r
--> file: fastmix.cpp\r
- where: spline macros\r
- what: changed formula + added some guard bits to calculation\r
-\r
- where: fir macros + implementation\r
- what: - moved CSoundfile::FIR funtions to CzFIR (single instance sfir)\r
- - changed fir macros to support CzFIR class\r
-\r
-date = 06-feb-2001 [Markus Fick]\r
--> file: fastmix.cpp\r
- where: macros\r
- what: - removed fir filter with coef interpolation\r
- - add spline interpolation\r
- RM: now modplug->select( SPLINE ) selects spline and\r
- modplug->select( POLYPHASE ) selects 8tap fir filter\r
-\r
-date = 05-feb-2001 [Markus Fick]\r
--> file: fastmix.cpp\r
- where: macros + filter order\r
- what: [modify] changed filter order to 8 instead of 10\r
-\r
--> file: fastmix.cpp\r
- what: new macros+switch for fir-interpolator with coef interpolation\r
-\r
-date = 04-feb-2001 [Markus Fick]\r
-\r
--> file: sndfile.h\r
- where: class CSoundFile (bottom)\r
- what: [add] methods for FIR mixer support\r
- 1. int InitFIRInterpolator( );\r
- 2. int DoneFIRInterpolator( );\r
-\r
--> file: sndfile.cpp\r
- function:CSoundFile::CSoundFile()\r
- what: [modify] add call to CSoundFile::InitFIRMixer( )\r
- \r
- function:CSoundFile::~CSoundFile()\r
- what: [modify] add call to CSoundFile::DoneFIRMixer( )\r
-\r
--> file: fastmix.cpp\r
- new include: <math.h>\r
- why: need it for fir-coef calculation\r
- new function: CSoundFile::InitFIRMixer( ) // initializes fir filter lookup (if necessary)\r
- new function: CSoundFile::DoneFIRMixer( ) // decrements ReferenceCounter (for static vars) and deinitializes fir struct (if possible).\r
- new defs:\r
- #define FIRCPWBN 10 // log2 of number of precalculated wings (-(1L<<FIRCPWBN)..(1L<<FIRCPWBN))\r
- #define FIRLOPOSSHIFT (16-(FIRCPWBN+1)) // shift for lopos of sampleposition -> (16 - FIRCPWBN - 1)\r
- #define FIRLEN 9 // number(-1) of multiplications per sample\r
- #define FIRCUT 0.90f // cutoff of filter\r
- #define MIXNDX_FIRMIXERSRC 0x20 // src-type for firfilter\r
- new vars:\r
- static signed short *cFirLut; // lulines\r
- static int bFirInitialized = 0; // initialized?\r
- static int nFirOrder = FIRLEN; // order (modplug has 4smps pre/post extension, so limit this to 9)\r
- static float nFirFC = FIRCUT; // cutoff (normalized to pi/2)\r
- static int nFirCpw = (1L<<FIRCPWBN); // number of precalculted filter lines\r
- static int nFirUsers = 0; // reference counter\r
- new macros:\r
- #define SNDMIX_GETMONOVOL8FIRFILTER\r
- #define SNDMIX_GETMONOVOL16FIRFILTER\r
- #define SNDMIX_GETSTEREOVOL8FIRFILTER\r
- #define SNDMIX_GETSTEREOVOL16FIRFILTER\r
- new mixer interface macros:\r
- BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix)\r
- BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix)\r
- BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix)\r
- BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix)\r
- BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix)\r
- BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix)\r
- BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix)\r
- BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix)\r
- BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix)\r
- BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix)\r
- BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix)\r
- BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix)\r
- BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix)\r
- BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix)\r
- BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix)\r
- BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix)\r
- BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix)\r
- BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix)\r
- BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix)\r
- BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix)\r
- modified:\r
- const LPMIXINTERFACE gpMixFunctionTable[2*2*16] // to hold new fir mixer interface\r
- const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] // to hold new fir mixer interface\r
- functioN: UINT CSoundFile::CreateStereoMix(int count)\r
- new: \r
- if (!(pChannel->dwFlags & CHN_NOIDO))\r
- {\r
- // use hq-fir mixer?\r
- if( ((gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) ||\r
- ((gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == (SNDMIX_HQRESAMPLER)) )\r
- nFlags += MIXNDX_FIRMIXERSRC;\r
- else\r
- nFlags += MIXNDX_LINEARSRC; // use \r
- }\r
- was:\r
- if (!(pChannel->dwFlags & CHN_NOIDO))\r
- {\r
- nFlags += MIXNDX_LINEARSRC; // use \r
- }\r
-\r
-\r
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
- * Markus Fick <webmaster@mark-f.de> spline + fir-resampler
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-#include <math.h>
-
-#ifdef MSC_VER
-#pragma bss_seg(".modplug")
-#endif
-
-// Front Mix Buffer (Also room for interleaved rear mix)
-int MixSoundBuffer[MIXBUFFERSIZE*4];
-
-// Reverb Mix Buffer
-#ifndef NO_REVERB
-int MixReverbBuffer[MIXBUFFERSIZE*2];
-extern UINT gnReverbSend;
-#endif
-
-#ifndef FASTSOUNDLIB
-int MixRearBuffer[MIXBUFFERSIZE*2];
-float MixFloatBuffer[MIXBUFFERSIZE*2];
-#endif
-
-#ifdef MSC_VER
-#pragma bss_seg()
-#endif
-
-
-extern LONG gnDryROfsVol;
-extern LONG gnDryLOfsVol;
-extern LONG gnRvbROfsVol;
-extern LONG gnRvbLOfsVol;
-
-// 4x256 taps polyphase FIR resampling filter
-extern short int gFastSinc[];
-extern short int gKaiserSinc[]; // 8-taps polyphase
-/*
- ------------------------------------------------------------------------------------------------
- cubic spline interpolation doc,
- (derived from "digital image warping", g. wolberg)
-
- interpolation polynomial: f(x) = A3*(x-floor(x))**3 + A2*(x-floor(x))**2 + A1*(x-floor(x)) + A0
-
- with Y = equispaced data points (dist=1), YD = first derivates of data points and IP = floor(x)
- the A[0..3] can be found by solving
- A0 = Y[IP]
- A1 = YD[IP]
- A2 = 3*(Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
- A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] - YD[IP+1]
-
- with the first derivates as
- YD[IP] = 0.5 * (Y[IP+1] - Y[IP-1]);
- YD[IP+1] = 0.5 * (Y[IP+2] - Y[IP])
-
- the coefs becomes
- A0 = Y[IP]
- A1 = YD[IP]
- = 0.5 * (Y[IP+1] - Y[IP-1]);
- A2 = 3.0 * (Y[IP+1]-Y[IP])-2.0*YD[IP]-YD[IP+1]
- = 3.0 * (Y[IP+1] - Y[IP]) - 0.5 * 2.0 * (Y[IP+1] - Y[IP-1]) - 0.5 * (Y[IP+2] - Y[IP])
- = 3.0 * Y[IP+1] - 3.0 * Y[IP] - Y[IP+1] + Y[IP-1] - 0.5 * Y[IP+2] + 0.5 * Y[IP]
- = -0.5 * Y[IP+2] + 2.0 * Y[IP+1] - 2.5 * Y[IP] + Y[IP-1]
- = Y[IP-1] + 2 * Y[IP+1] - 0.5 * (5.0 * Y[IP] + Y[IP+2])
- A3 = -2.0 * (Y[IP+1]-Y[IP]) + YD[IP] + YD[IP+1]
- = -2.0 * Y[IP+1] + 2.0 * Y[IP] + 0.5 * (Y[IP+1] - Y[IP-1]) + 0.5 * (Y[IP+2] - Y[IP])
- = -2.0 * Y[IP+1] + 2.0 * Y[IP] + 0.5 * Y[IP+1] - 0.5 * Y[IP-1] + 0.5 * Y[IP+2] - 0.5 * Y[IP]
- = 0.5 * Y[IP+2] - 1.5 * Y[IP+1] + 1.5 * Y[IP] - 0.5 * Y[IP-1]
- = 0.5 * (3.0 * (Y[IP] - Y[IP+1]) - Y[IP-1] + YP[IP+2])
-
- then interpolated data value is (horner rule)
- out = (((A3*x)+A2)*x+A1)*x+A0
-
- this gives parts of data points Y[IP-1] to Y[IP+2] of
- part x**3 x**2 x**1 x**0
- Y[IP-1] -0.5 1 -0.5 0
- Y[IP] 1.5 -2.5 0 1
- Y[IP+1] -1.5 2 0.5 0
- Y[IP+2] 0.5 -0.5 0 0
- --------------------------------------------------------------------------------------------------
-*/
-// number of bits used to scale spline coefs
-#define SPLINE_QUANTBITS 14
-#define SPLINE_QUANTSCALE (1L<<SPLINE_QUANTBITS)
-#define SPLINE_8SHIFT (SPLINE_QUANTBITS-8)
-#define SPLINE_16SHIFT (SPLINE_QUANTBITS)
-// forces coefsset to unity gain
-#define SPLINE_CLAMPFORUNITY
-// log2(number) of precalculated splines (range is [4..14])
-#define SPLINE_FRACBITS 10
-#define SPLINE_LUTLEN (1L<<SPLINE_FRACBITS)
-
-class CzCUBICSPLINE
-{ public:
- CzCUBICSPLINE( );
- ~CzCUBICSPLINE( );
- static signed short lut[4*(1L<<SPLINE_FRACBITS)];
-};
-
-signed short CzCUBICSPLINE::lut[4*(1L<<SPLINE_FRACBITS)];
-
-CzCUBICSPLINE::CzCUBICSPLINE( )
-{ int _LIi;
- int _LLen = (1L<<SPLINE_FRACBITS);
- float _LFlen = 1.0f / (float)_LLen;
- float _LScale = (float)SPLINE_QUANTSCALE;
- for(_LIi=0;_LIi<_LLen;_LIi++)
- { float _LCm1, _LC0, _LC1, _LC2;
- float _LX = ((float)_LIi)*_LFlen;
- int _LSum,_LIdx = _LIi<<2;
- _LCm1 = (float)floor( 0.5 + _LScale * (-0.5*_LX*_LX*_LX + 1.0 * _LX*_LX - 0.5 * _LX ) );
- _LC0 = (float)floor( 0.5 + _LScale * ( 1.5*_LX*_LX*_LX - 2.5 * _LX*_LX + 1.0 ) );
- _LC1 = (float)floor( 0.5 + _LScale * (-1.5*_LX*_LX*_LX + 2.0 * _LX*_LX + 0.5 * _LX ) );
- _LC2 = (float)floor( 0.5 + _LScale * ( 0.5*_LX*_LX*_LX - 0.5 * _LX*_LX ) );
- lut[_LIdx+0] = (signed short)( (_LCm1 < -_LScale) ? -_LScale : ((_LCm1 > _LScale) ? _LScale : _LCm1) );
- lut[_LIdx+1] = (signed short)( (_LC0 < -_LScale) ? -_LScale : ((_LC0 > _LScale) ? _LScale : _LC0 ) );
- lut[_LIdx+2] = (signed short)( (_LC1 < -_LScale) ? -_LScale : ((_LC1 > _LScale) ? _LScale : _LC1 ) );
- lut[_LIdx+3] = (signed short)( (_LC2 < -_LScale) ? -_LScale : ((_LC2 > _LScale) ? _LScale : _LC2 ) );
-#ifdef SPLINE_CLAMPFORUNITY
- _LSum = lut[_LIdx+0]+lut[_LIdx+1]+lut[_LIdx+2]+lut[_LIdx+3];
- if( _LSum != SPLINE_QUANTSCALE )
- { int _LMax = _LIdx;
- if( lut[_LIdx+1]>lut[_LMax] ) _LMax = _LIdx+1;
- if( lut[_LIdx+2]>lut[_LMax] ) _LMax = _LIdx+2;
- if( lut[_LIdx+3]>lut[_LMax] ) _LMax = _LIdx+3;
- lut[_LMax] += (SPLINE_QUANTSCALE-_LSum);
- }
-#endif
- }
-}
-
-CzCUBICSPLINE::~CzCUBICSPLINE( )
-{ // nothing todo
-}
-
-CzCUBICSPLINE sspline;
-
-/*
- ------------------------------------------------------------------------------------------------
- fir interpolation doc,
- (derived from "an engineer's guide to fir digital filters", n.j. loy)
-
- calculate coefficients for ideal lowpass filter (with cutoff = fc in 0..1 (mapped to 0..nyquist))
- c[-N..N] = (i==0) ? fc : sin(fc*pi*i)/(pi*i)
-
- then apply selected window to coefficients
- c[-N..N] *= w(0..N)
- with n in 2*N and w(n) being a window function (see loy)
-
- then calculate gain and scale filter coefs to have unity gain.
- ------------------------------------------------------------------------------------------------
-*/
-// quantizer scale of window coefs
-#define WFIR_QUANTBITS 15
-#define WFIR_QUANTSCALE (1L<<WFIR_QUANTBITS)
-#define WFIR_8SHIFT (WFIR_QUANTBITS-8)
-#define WFIR_16BITSHIFT (WFIR_QUANTBITS)
-// log2(number)-1 of precalculated taps range is [4..12]
-#define WFIR_FRACBITS 10
-#define WFIR_LUTLEN ((1L<<(WFIR_FRACBITS+1))+1)
-// number of samples in window
-#define WFIR_LOG2WIDTH 3
-#define WFIR_WIDTH (1L<<WFIR_LOG2WIDTH)
-#define WFIR_SMPSPERWING ((WFIR_WIDTH-1)>>1)
-// cutoff (1.0 == pi/2)
-#define WFIR_CUTOFF 0.90f
-// wfir type
-#define WFIR_HANN 0
-#define WFIR_HAMMING 1
-#define WFIR_BLACKMANEXACT 2
-#define WFIR_BLACKMAN3T61 3
-#define WFIR_BLACKMAN3T67 4
-#define WFIR_BLACKMAN4T92 5
-#define WFIR_BLACKMAN4T74 6
-#define WFIR_KAISER4T 7
-#define WFIR_TYPE WFIR_BLACKMANEXACT
-// wfir help
-#ifndef M_zPI
-#define M_zPI 3.1415926535897932384626433832795
-#endif
-#define M_zEPS 1e-8
-#define M_zBESSELEPS 1e-21
-
-class CzWINDOWEDFIR
-{ public:
- CzWINDOWEDFIR( );
- ~CzWINDOWEDFIR( );
- float coef( int _PCnr, float _POfs, float _PCut, int _PWidth, int _PType ) //float _PPos, float _PFc, int _PLen )
- { double _LWidthM1 = _PWidth-1;
- double _LWidthM1Half = 0.5*_LWidthM1;
- double _LPosU = ((double)_PCnr - _POfs);
- double _LPos = _LPosU-_LWidthM1Half;
- double _LPIdl = 2.0*M_zPI/_LWidthM1;
- double _LWc,_LSi;
- if( fabs(_LPos)<M_zEPS )
- { _LWc = 1.0;
- _LSi = _PCut;
- }
- else
- { switch( _PType )
- { case WFIR_HANN:
- _LWc = 0.50 - 0.50 * cos(_LPIdl*_LPosU);
- break;
- case WFIR_HAMMING:
- _LWc = 0.54 - 0.46 * cos(_LPIdl*_LPosU);
- break;
- case WFIR_BLACKMANEXACT:
- _LWc = 0.42 - 0.50 * cos(_LPIdl*_LPosU) + 0.08 * cos(2.0*_LPIdl*_LPosU);
- break;
- case WFIR_BLACKMAN3T61:
- _LWc = 0.44959 - 0.49364 * cos(_LPIdl*_LPosU) + 0.05677 * cos(2.0*_LPIdl*_LPosU);
- break;
- case WFIR_BLACKMAN3T67:
- _LWc = 0.42323 - 0.49755 * cos(_LPIdl*_LPosU) + 0.07922 * cos(2.0*_LPIdl*_LPosU);
- break;
- case WFIR_BLACKMAN4T92:
- _LWc = 0.35875 - 0.48829 * cos(_LPIdl*_LPosU) + 0.14128 * cos(2.0*_LPIdl*_LPosU) - 0.01168 * cos(3.0*_LPIdl*_LPosU);
- break;
- case WFIR_BLACKMAN4T74:
- _LWc = 0.40217 - 0.49703 * cos(_LPIdl*_LPosU) + 0.09392 * cos(2.0*_LPIdl*_LPosU) - 0.00183 * cos(3.0*_LPIdl*_LPosU);
- break;
- case WFIR_KAISER4T:
- _LWc = 0.40243 - 0.49804 * cos(_LPIdl*_LPosU) + 0.09831 * cos(2.0*_LPIdl*_LPosU) - 0.00122 * cos(3.0*_LPIdl*_LPosU);
- break;
- default:
- _LWc = 1.0;
- break;
- }
- _LPos *= M_zPI;
- _LSi = sin(_PCut*_LPos)/_LPos;
- }
- return (float)(_LWc*_LSi);
- }
- static signed short lut[WFIR_LUTLEN*WFIR_WIDTH];
-};
-
-signed short CzWINDOWEDFIR::lut[WFIR_LUTLEN*WFIR_WIDTH];
-
-CzWINDOWEDFIR::CzWINDOWEDFIR()
-{ int _LPcl;
- float _LPcllen = (float)(1L<<WFIR_FRACBITS); // number of precalculated lines for 0..1 (-1..0)
- float _LNorm = 1.0f / (float)(2.0f * _LPcllen);
- float _LCut = WFIR_CUTOFF;
- float _LScale = (float)WFIR_QUANTSCALE;
- for( _LPcl=0;_LPcl<WFIR_LUTLEN;_LPcl++ )
- { float _LGain,_LCoefs[WFIR_WIDTH];
- float _LOfs = ((float)_LPcl-_LPcllen)*_LNorm;
- int _LCc,_LIdx = _LPcl<<WFIR_LOG2WIDTH;
- for( _LCc=0,_LGain=0.0f;_LCc<WFIR_WIDTH;_LCc++ )
- { _LGain += (_LCoefs[_LCc] = coef( _LCc, _LOfs, _LCut, WFIR_WIDTH, WFIR_TYPE ));
- }
- _LGain = 1.0f/_LGain;
- for( _LCc=0;_LCc<WFIR_WIDTH;_LCc++ )
- { float _LCoef = (float)floor( 0.5 + _LScale*_LCoefs[_LCc]*_LGain );
- lut[_LIdx+_LCc] = (signed short)( (_LCoef<-_LScale)?-_LScale:((_LCoef>_LScale)?_LScale:_LCoef) );
- }
- }
-}
-
-CzWINDOWEDFIR::~CzWINDOWEDFIR()
-{ // nothing todo
-}
-
-CzWINDOWEDFIR sfir;
-
-// ------------------------------------------------------------------------------------------------
-// MIXING MACROS
-// ------------------------------------------------------------------------------------------------
-/////////////////////////////////////////////////////
-// Mixing Macros
-
-#define SNDMIX_BEGINSAMPLELOOP8\
- register MODCHANNEL * const pChn = pChannel;\
- nPos = pChn->nPosLo;\
- const signed char *p = (signed char *)(pChn->pCurrentSample+pChn->nPos);\
- if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
- int *pvol = pbuffer;\
- do {
-
-#define SNDMIX_BEGINSAMPLELOOP16\
- register MODCHANNEL * const pChn = pChannel;\
- nPos = pChn->nPosLo;\
- const signed short *p = (signed short *)(pChn->pCurrentSample+(pChn->nPos*2));\
- if (pChn->dwFlags & CHN_STEREO) p += pChn->nPos;\
- int *pvol = pbuffer;\
- do {
-
-#define SNDMIX_ENDSAMPLELOOP\
- nPos += pChn->nInc;\
- } while (pvol < pbufmax);\
- pChn->nPos += nPos >> 16;\
- pChn->nPosLo = nPos & 0xFFFF;
-
-#define SNDMIX_ENDSAMPLELOOP8 SNDMIX_ENDSAMPLELOOP
-#define SNDMIX_ENDSAMPLELOOP16 SNDMIX_ENDSAMPLELOOP
-
-//////////////////////////////////////////////////////////////////////////////
-// Mono
-
-// No interpolation
-#define SNDMIX_GETMONOVOL8NOIDO\
- int vol = p[nPos >> 16] << 8;
-
-#define SNDMIX_GETMONOVOL16NOIDO\
- int vol = p[nPos >> 16];
-
-// Linear Interpolation
-#define SNDMIX_GETMONOVOL8LINEAR\
- int poshi = nPos >> 16;\
- int poslo = (nPos >> 8) & 0xFF;\
- int srcvol = p[poshi];\
- int destvol = p[poshi+1];\
- int vol = (srcvol<<8) + ((int)(poslo * (destvol - srcvol)));
-
-#define SNDMIX_GETMONOVOL16LINEAR\
- int poshi = nPos >> 16;\
- int poslo = (nPos >> 8) & 0xFF;\
- int srcvol = p[poshi];\
- int destvol = p[poshi+1];\
- int vol = srcvol + ((int)(poslo * (destvol - srcvol)) >> 8);
-
-// spline interpolation (2 guard bits should be enough???)
-#define SPLINE_FRACSHIFT ((16-SPLINE_FRACBITS)-2)
-#define SPLINE_FRACMASK (((1L<<(16-SPLINE_FRACSHIFT))-1)&~3)
-
-#define SNDMIX_GETMONOVOL8SPLINE \
- int poshi = nPos >> 16; \
- int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
- int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_8SHIFT;
-
-#define SNDMIX_GETMONOVOL16SPLINE \
- int poshi = nPos >> 16; \
- int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
- int vol = (CzCUBICSPLINE::lut[poslo ]*(int)p[poshi-1] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[poshi ] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[poshi+2] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[poshi+1]) >> SPLINE_16SHIFT;
-
-
-// fir interpolation
-#define WFIR_FRACSHIFT (16-(WFIR_FRACBITS+1+WFIR_LOG2WIDTH))
-#define WFIR_FRACMASK ((((1L<<(17-WFIR_FRACSHIFT))-1)&~((1L<<WFIR_LOG2WIDTH)-1)))
-#define WFIR_FRACHALVE (1L<<(16-(WFIR_FRACBITS+2)))
-
-#define SNDMIX_GETMONOVOL8FIRFILTER \
- int poshi = nPos >> 16;\
- int poslo = (nPos & 0xFFFF);\
- int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
- int vol = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \
- vol += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \
- vol >>= WFIR_8SHIFT;
-
-#define SNDMIX_GETMONOVOL16FIRFILTER \
- int poshi = nPos >> 16;\
- int poslo = (nPos & 0xFFFF);\
- int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
- int vol1 = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[poshi+1-4]); \
- vol1 += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[poshi+2-4]); \
- vol1 += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[poshi+3-4]); \
- vol1 += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[poshi+4-4]); \
- int vol2 = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[poshi+5-4]); \
- vol2 += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[poshi+6-4]); \
- vol2 += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[poshi+7-4]); \
- vol2 += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[poshi+8-4]); \
- int vol = ((vol1>>1)+(vol2>>1)) >> (WFIR_16BITSHIFT-1);
-
-/////////////////////////////////////////////////////////////////////////////
-// Stereo
-
-// No interpolation
-#define SNDMIX_GETSTEREOVOL8NOIDO\
- int vol_l = p[(nPos>>16)*2] << 8;\
- int vol_r = p[(nPos>>16)*2+1] << 8;
-
-#define SNDMIX_GETSTEREOVOL16NOIDO\
- int vol_l = p[(nPos>>16)*2];\
- int vol_r = p[(nPos>>16)*2+1];
-
-// Linear Interpolation
-#define SNDMIX_GETSTEREOVOL8LINEAR\
- int poshi = nPos >> 16;\
- int poslo = (nPos >> 8) & 0xFF;\
- int srcvol_l = p[poshi*2];\
- int vol_l = (srcvol_l<<8) + ((int)(poslo * (p[poshi*2+2] - srcvol_l)));\
- int srcvol_r = p[poshi*2+1];\
- int vol_r = (srcvol_r<<8) + ((int)(poslo * (p[poshi*2+3] - srcvol_r)));
-
-#define SNDMIX_GETSTEREOVOL16LINEAR\
- int poshi = nPos >> 16;\
- int poslo = (nPos >> 8) & 0xFF;\
- int srcvol_l = p[poshi*2];\
- int vol_l = srcvol_l + ((int)(poslo * (p[poshi*2+2] - srcvol_l)) >> 8);\
- int srcvol_r = p[poshi*2+1];\
- int vol_r = srcvol_r + ((int)(poslo * (p[poshi*2+3] - srcvol_r)) >> 8);\
-
-// Spline Interpolation
-#define SNDMIX_GETSTEREOVOL8SPLINE \
- int poshi = nPos >> 16; \
- int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
- int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_8SHIFT; \
- int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_8SHIFT;
-
-#define SNDMIX_GETSTEREOVOL16SPLINE \
- int poshi = nPos >> 16; \
- int poslo = (nPos >> SPLINE_FRACSHIFT) & SPLINE_FRACMASK; \
- int vol_l = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2 ] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2 ] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2 ] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2 ]) >> SPLINE_16SHIFT; \
- int vol_r = (CzCUBICSPLINE::lut[poslo ]*(int)p[(poshi-1)*2+1] + \
- CzCUBICSPLINE::lut[poslo+1]*(int)p[(poshi )*2+1] + \
- CzCUBICSPLINE::lut[poslo+2]*(int)p[(poshi+1)*2+1] + \
- CzCUBICSPLINE::lut[poslo+3]*(int)p[(poshi+2)*2+1]) >> SPLINE_16SHIFT;
-
-// fir interpolation
-#define SNDMIX_GETSTEREOVOL8FIRFILTER \
- int poshi = nPos >> 16;\
- int poslo = (nPos & 0xFFFF);\
- int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
- int vol_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \
- vol_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \
- vol_l >>= WFIR_8SHIFT; \
- int vol_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \
- vol_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \
- vol_r >>= WFIR_8SHIFT;
-
-#define SNDMIX_GETSTEREOVOL16FIRFILTER \
- int poshi = nPos >> 16;\
- int poslo = (nPos & 0xFFFF);\
- int firidx = ((poslo+WFIR_FRACHALVE)>>WFIR_FRACSHIFT) & WFIR_FRACMASK; \
- int vol1_l = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2 ]); \
- vol1_l += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2 ]); \
- vol1_l += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2 ]); \
- vol1_l += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2 ]); \
- int vol2_l = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2 ]); \
- vol2_l += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2 ]); \
- vol2_l += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2 ]); \
- vol2_l += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2 ]); \
- int vol_l = ((vol1_l>>1)+(vol2_l>>1)) >> (WFIR_16BITSHIFT-1); \
- int vol1_r = (CzWINDOWEDFIR::lut[firidx+0]*(int)p[(poshi+1-4)*2+1]); \
- vol1_r += (CzWINDOWEDFIR::lut[firidx+1]*(int)p[(poshi+2-4)*2+1]); \
- vol1_r += (CzWINDOWEDFIR::lut[firidx+2]*(int)p[(poshi+3-4)*2+1]); \
- vol1_r += (CzWINDOWEDFIR::lut[firidx+3]*(int)p[(poshi+4-4)*2+1]); \
- int vol2_r = (CzWINDOWEDFIR::lut[firidx+4]*(int)p[(poshi+5-4)*2+1]); \
- vol2_r += (CzWINDOWEDFIR::lut[firidx+5]*(int)p[(poshi+6-4)*2+1]); \
- vol2_r += (CzWINDOWEDFIR::lut[firidx+6]*(int)p[(poshi+7-4)*2+1]); \
- vol2_r += (CzWINDOWEDFIR::lut[firidx+7]*(int)p[(poshi+8-4)*2+1]); \
- int vol_r = ((vol1_r>>1)+(vol2_r>>1)) >> (WFIR_16BITSHIFT-1);
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-#define SNDMIX_STOREMONOVOL\
- pvol[0] += vol * pChn->nRightVol;\
- pvol[1] += vol * pChn->nLeftVol;\
- pvol += 2;
-
-#define SNDMIX_STORESTEREOVOL\
- pvol[0] += vol_l * pChn->nRightVol;\
- pvol[1] += vol_r * pChn->nLeftVol;\
- pvol += 2;
-
-#define SNDMIX_STOREFASTMONOVOL\
- int v = vol * pChn->nRightVol;\
- pvol[0] += v;\
- pvol[1] += v;\
- pvol += 2;
-
-#define SNDMIX_RAMPMONOVOL\
- nRampLeftVol += pChn->nLeftRamp;\
- nRampRightVol += pChn->nRightRamp;\
- pvol[0] += vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
- pvol[1] += vol * (nRampLeftVol >> VOLUMERAMPPRECISION);\
- pvol += 2;
-
-#define SNDMIX_RAMPFASTMONOVOL\
- nRampRightVol += pChn->nRightRamp;\
- int fastvol = vol * (nRampRightVol >> VOLUMERAMPPRECISION);\
- pvol[0] += fastvol;\
- pvol[1] += fastvol;\
- pvol += 2;
-
-#define SNDMIX_RAMPSTEREOVOL\
- nRampLeftVol += pChn->nLeftRamp;\
- nRampRightVol += pChn->nRightRamp;\
- pvol[0] += vol_l * (nRampRightVol >> VOLUMERAMPPRECISION);\
- pvol[1] += vol_r * (nRampLeftVol >> VOLUMERAMPPRECISION);\
- pvol += 2;
-
-
-///////////////////////////////////////////////////
-// Resonant Filters
-
-// Mono
-#define MIX_BEGIN_FILTER\
- int fy1 = pChannel->nFilter_Y1;\
- int fy2 = pChannel->nFilter_Y2;\
-
-#define MIX_END_FILTER\
- pChannel->nFilter_Y1 = fy1;\
- pChannel->nFilter_Y2 = fy2;
-
-#define SNDMIX_PROCESSFILTER\
- vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
- fy2 = fy1;\
- fy1 = vol;\
-
-// Stereo
-#define MIX_BEGIN_STEREO_FILTER\
- int fy1 = pChannel->nFilter_Y1;\
- int fy2 = pChannel->nFilter_Y2;\
- int fy3 = pChannel->nFilter_Y3;\
- int fy4 = pChannel->nFilter_Y4;\
-
-#define MIX_END_STEREO_FILTER\
- pChannel->nFilter_Y1 = fy1;\
- pChannel->nFilter_Y2 = fy2;\
- pChannel->nFilter_Y3 = fy3;\
- pChannel->nFilter_Y4 = fy4;\
-
-#define SNDMIX_PROCESSSTEREOFILTER\
- vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
- vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\
- fy2 = fy1; fy1 = vol_l;\
- fy4 = fy3; fy3 = vol_r;\
-
-//////////////////////////////////////////////////////////
-// Interfaces
-
-typedef VOID (MPPASMCALL * LPMIXINTERFACE)(MODCHANNEL *, int *, int *);
-
-#define BEGIN_MIX_INTERFACE(func)\
- VOID MPPASMCALL func(MODCHANNEL *pChannel, int *pbuffer, int *pbufmax)\
- {\
- LONG nPos;
-
-#define END_MIX_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- }
-
-// Volume Ramps
-#define BEGIN_RAMPMIX_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- LONG nRampRightVol = pChannel->nRampRightVol;\
- LONG nRampLeftVol = pChannel->nRampLeftVol;
-
-#define END_RAMPMIX_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- pChannel->nRampRightVol = nRampRightVol;\
- pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
- pChannel->nRampLeftVol = nRampLeftVol;\
- pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
- }
-
-#define BEGIN_FASTRAMPMIX_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- LONG nRampRightVol = pChannel->nRampRightVol;
-
-#define END_FASTRAMPMIX_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- pChannel->nRampRightVol = nRampRightVol;\
- pChannel->nRampLeftVol = nRampRightVol;\
- pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
- pChannel->nLeftVol = pChannel->nRightVol;\
- }
-
-
-// Mono Resonant Filters
-#define BEGIN_MIX_FLT_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- MIX_BEGIN_FILTER
-
-
-#define END_MIX_FLT_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- MIX_END_FILTER\
- }
-
-#define BEGIN_RAMPMIX_FLT_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- LONG nRampRightVol = pChannel->nRampRightVol;\
- LONG nRampLeftVol = pChannel->nRampLeftVol;\
- MIX_BEGIN_FILTER
-
-#define END_RAMPMIX_FLT_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- MIX_END_FILTER\
- pChannel->nRampRightVol = nRampRightVol;\
- pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
- pChannel->nRampLeftVol = nRampLeftVol;\
- pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
- }
-
-// Stereo Resonant Filters
-#define BEGIN_MIX_STFLT_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- MIX_BEGIN_STEREO_FILTER
-
-
-#define END_MIX_STFLT_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- MIX_END_STEREO_FILTER\
- }
-
-#define BEGIN_RAMPMIX_STFLT_INTERFACE(func)\
- BEGIN_MIX_INTERFACE(func)\
- LONG nRampRightVol = pChannel->nRampRightVol;\
- LONG nRampLeftVol = pChannel->nRampLeftVol;\
- MIX_BEGIN_STEREO_FILTER
-
-#define END_RAMPMIX_STFLT_INTERFACE()\
- SNDMIX_ENDSAMPLELOOP\
- MIX_END_STEREO_FILTER\
- pChannel->nRampRightVol = nRampRightVol;\
- pChannel->nRightVol = nRampRightVol >> VOLUMERAMPPRECISION;\
- pChannel->nRampLeftVol = nRampLeftVol;\
- pChannel->nLeftVol = nRampLeftVol >> VOLUMERAMPPRECISION;\
- }
-
-
-/////////////////////////////////////////////////////
-//
-
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples);
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount);
-void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
-
-/////////////////////////////////////////////////////
-// Mono samples functions
-
-BEGIN_MIX_INTERFACE(Mono8BitMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono16BitMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono8BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono16BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono8BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono16BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono8BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Mono16BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_INTERFACE()
-
-
-// Volume Ramps
-BEGIN_RAMPMIX_INTERFACE(Mono8BitRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono16BitRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono8BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono16BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono8BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono16BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono8BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Mono16BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_INTERFACE()
-
-
-//////////////////////////////////////////////////////
-// Fast mono mix for leftvol=rightvol (1 less imul)
-
-BEGIN_MIX_INTERFACE(FastMono8BitMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono16BitMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono8BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono16BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono8BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono16BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono8BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(FastMono16BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_STOREFASTMONOVOL
-END_MIX_INTERFACE()
-
-
-// Fast Ramps
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono8BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-BEGIN_FASTRAMPMIX_INTERFACE(FastMono16BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_RAMPFASTMONOVOL
-END_FASTRAMPMIX_INTERFACE()
-
-
-//////////////////////////////////////////////////////
-// Stereo samples
-
-BEGIN_MIX_INTERFACE(Stereo8BitMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8NOIDO
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo16BitMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16NOIDO
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo8BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8LINEAR
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo16BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16LINEAR
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo8BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8SPLINE
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo16BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16SPLINE
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo8BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8FIRFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-BEGIN_MIX_INTERFACE(Stereo16BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16FIRFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_INTERFACE()
-
-
-// Volume Ramps
-BEGIN_RAMPMIX_INTERFACE(Stereo8BitRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8NOIDO
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo16BitRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16NOIDO
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo8BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8LINEAR
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo16BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16LINEAR
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo8BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8SPLINE
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo16BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16SPLINE
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo8BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8FIRFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-BEGIN_RAMPMIX_INTERFACE(Stereo16BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16FIRFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_INTERFACE()
-
-
-
-//////////////////////////////////////////////////////
-// Resonant Filter Mix
-
-#ifndef NO_FILTER
-
-// Mono Filter Mix
-BEGIN_MIX_FLT_INTERFACE(FilterMono8BitMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono16BitMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono8BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono16BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono8BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono16BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono8BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-BEGIN_MIX_FLT_INTERFACE(FilterMono16BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_PROCESSFILTER
- SNDMIX_STOREMONOVOL
-END_MIX_FLT_INTERFACE()
-
-// Filter + Ramp
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8NOIDO
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16NOIDO
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8LINEAR
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16LINEAR
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8SPLINE
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16SPLINE
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono8BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETMONOVOL8FIRFILTER
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-BEGIN_RAMPMIX_FLT_INTERFACE(FilterMono16BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETMONOVOL16FIRFILTER
- SNDMIX_PROCESSFILTER
- SNDMIX_RAMPMONOVOL
-END_RAMPMIX_FLT_INTERFACE()
-
-
-// Stereo Filter Mix
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8NOIDO
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16NOIDO
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8LINEAR
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitLinearMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16LINEAR
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8SPLINE
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitSplineMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16SPLINE
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo8BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8FIRFILTER
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-BEGIN_MIX_STFLT_INTERFACE(FilterStereo16BitFirFilterMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16FIRFILTER
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_STORESTEREOVOL
-END_MIX_STFLT_INTERFACE()
-
-// Stereo Filter + Ramp
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8NOIDO
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16NOIDO
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8LINEAR
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitLinearRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16LINEAR
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8SPLINE
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitSplineRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16SPLINE
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo8BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP8
- SNDMIX_GETSTEREOVOL8FIRFILTER
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-BEGIN_RAMPMIX_STFLT_INTERFACE(FilterStereo16BitFirFilterRampMix)
- SNDMIX_BEGINSAMPLELOOP16
- SNDMIX_GETSTEREOVOL16FIRFILTER
- SNDMIX_PROCESSSTEREOFILTER
- SNDMIX_RAMPSTEREOVOL
-END_RAMPMIX_STFLT_INTERFACE()
-
-
-#else
-// Mono
-#define FilterMono8BitMix Mono8BitMix
-#define FilterMono16BitMix Mono16BitMix
-#define FilterMono8BitLinearMix Mono8BitLinearMix
-#define FilterMono16BitLinearMix Mono16BitLinearMix
-#define FilterMono8BitSplineMix Mono8BitSplineMix
-#define FilterMono16BitSplineMix Mono16BitSplineMix
-#define FilterMono8BitFirFilterMix Mono8BitFirFilterMix
-#define FilterMono16BitFirFilterMix Mono16BitFirFilterMix
-#define FilterMono8BitRampMix Mono8BitRampMix
-#define FilterMono16BitRampMix Mono16BitRampMix
-#define FilterMono8BitLinearRampMix Mono8BitLinearRampMix
-#define FilterMono16BitLinearRampMix Mono16BitLinearRampMix
-#define FilterMono8BitSplineRampMix Mono8BitSplineRampMix
-#define FilterMono16BitSplineRampMix Mono16BitSplineRampMix
-#define FilterMono8BitFirFilterRampMix Mono8BitFirFilterRampMix
-#define FilterMono16BitFirFilterRampMix Mono16BitFirFilterRampMix
-// Stereo
-#define FilterStereo8BitMix Stereo8BitMix
-#define FilterStereo16BitMix Stereo16BitMix
-#define FilterStereo8BitLinearMix Stereo8BitLinearMix
-#define FilterStereo16BitLinearMix Stereo16BitLinearMix
-#define FilterStereo8BitSplineMix Stereo8BitSplineMix
-#define FilterStereo16BitSplineMix Stereo16BitSplineMix
-#define FilterStereo8BitFirFilterMix Stereo8BitFirFilterMix
-#define FilterStereo16BitFirFilterMix Stereo16BitFirFilterMix
-#define FilterStereo8BitRampMix Stereo8BitRampMix
-#define FilterStereo16BitRampMix Stereo16BitRampMix
-#define FilterStereo8BitLinearRampMix Stereo8BitLinearRampMix
-#define FilterStereo16BitLinearRampMix Stereo16BitLinearRampMix
-#define FilterStereo8BitSplineRampMix Stereo8BitSplineRampMix
-#define FilterStereo16BitSplineRampMix Stereo16BitSplineRampMix
-#define FilterStereo8BitFirFilterRampMix Stereo8BitFirFilterRampMix
-#define FilterStereo16BitFirFilterRampMix Stereo16BitFirFilterRampMix
-
-#endif
-
-/////////////////////////////////////////////////////////////////////////////////////
-//
-// Mix function tables
-//
-//
-// Index is as follow:
-// [b1-b0] format (8-bit-mono, 16-bit-mono, 8-bit-stereo, 16-bit-stereo)
-// [b2] ramp
-// [b3] filter
-// [b5-b4] src type
-//
-
-#define MIXNDX_16BIT 0x01
-#define MIXNDX_STEREO 0x02
-#define MIXNDX_RAMP 0x04
-#define MIXNDX_FILTER 0x08
-#define MIXNDX_LINEARSRC 0x10
-#define MIXNDX_SPLINESRC 0x20
-#define MIXNDX_FIRSRC 0x30
-
-const LPMIXINTERFACE gpMixFunctionTable[2*2*16] =
-{
- // No SRC
- Mono8BitMix, Mono16BitMix, Stereo8BitMix, Stereo16BitMix,
- Mono8BitRampMix, Mono16BitRampMix, Stereo8BitRampMix, Stereo16BitRampMix,
- // No SRC, Filter
- FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, FilterStereo16BitMix,
- FilterMono8BitRampMix, FilterMono16BitRampMix, FilterStereo8BitRampMix,FilterStereo16BitRampMix,
- // Linear SRC
- Mono8BitLinearMix, Mono16BitLinearMix, Stereo8BitLinearMix, Stereo16BitLinearMix,
- Mono8BitLinearRampMix, Mono16BitLinearRampMix, Stereo8BitLinearRampMix,Stereo16BitLinearRampMix,
- // Linear SRC, Filter
- FilterMono8BitLinearMix, FilterMono16BitLinearMix, FilterStereo8BitLinearMix, FilterStereo16BitLinearMix,
- FilterMono8BitLinearRampMix,FilterMono16BitLinearRampMix,FilterStereo8BitLinearRampMix,FilterStereo16BitLinearRampMix,
-
- // FirFilter SRC
- Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, Stereo16BitSplineMix,
- Mono8BitSplineRampMix, Mono16BitSplineRampMix, Stereo8BitSplineRampMix,Stereo16BitSplineRampMix,
- // Spline SRC, Filter
- FilterMono8BitSplineMix, FilterMono16BitSplineMix, FilterStereo8BitSplineMix, FilterStereo16BitSplineMix,
- FilterMono8BitSplineRampMix,FilterMono16BitSplineRampMix,FilterStereo8BitSplineRampMix,FilterStereo16BitSplineRampMix,
-
- // FirFilter SRC
- Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, Stereo16BitFirFilterMix,
- Mono8BitFirFilterRampMix, Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix,Stereo16BitFirFilterRampMix,
- // FirFilter SRC, Filter
- FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix,
- FilterMono8BitFirFilterRampMix,FilterMono16BitFirFilterRampMix,FilterStereo8BitFirFilterRampMix,FilterStereo16BitFirFilterRampMix
-};
-
-const LPMIXINTERFACE gpFastMixFunctionTable[2*2*16] =
-{
- // No SRC
- FastMono8BitMix, FastMono16BitMix, Stereo8BitMix, Stereo16BitMix,
- FastMono8BitRampMix, FastMono16BitRampMix, Stereo8BitRampMix, Stereo16BitRampMix,
- // No SRC, Filter
- FilterMono8BitMix, FilterMono16BitMix, FilterStereo8BitMix, FilterStereo16BitMix,
- FilterMono8BitRampMix, FilterMono16BitRampMix, FilterStereo8BitRampMix,FilterStereo16BitRampMix,
- // Linear SRC
- FastMono8BitLinearMix, FastMono16BitLinearMix, Stereo8BitLinearMix, Stereo16BitLinearMix,
- FastMono8BitLinearRampMix, FastMono16BitLinearRampMix, Stereo8BitLinearRampMix,Stereo16BitLinearRampMix,
- // Linear SRC, Filter
- FilterMono8BitLinearMix, FilterMono16BitLinearMix, FilterStereo8BitLinearMix, FilterStereo16BitLinearMix,
- FilterMono8BitLinearRampMix,FilterMono16BitLinearRampMix,FilterStereo8BitLinearRampMix,FilterStereo16BitLinearRampMix,
-
- // Spline SRC
- Mono8BitSplineMix, Mono16BitSplineMix, Stereo8BitSplineMix, Stereo16BitSplineMix,
- Mono8BitSplineRampMix, Mono16BitSplineRampMix, Stereo8BitSplineRampMix,Stereo16BitSplineRampMix,
- // Spline SRC, Filter
- FilterMono8BitSplineMix, FilterMono16BitSplineMix, FilterStereo8BitSplineMix, FilterStereo16BitSplineMix,
- FilterMono8BitSplineRampMix,FilterMono16BitSplineRampMix,FilterStereo8BitSplineRampMix,FilterStereo16BitSplineRampMix,
-
- // FirFilter SRC
- Mono8BitFirFilterMix, Mono16BitFirFilterMix, Stereo8BitFirFilterMix, Stereo16BitFirFilterMix,
- Mono8BitFirFilterRampMix, Mono16BitFirFilterRampMix, Stereo8BitFirFilterRampMix,Stereo16BitFirFilterRampMix,
- // FirFilter SRC, Filter
- FilterMono8BitFirFilterMix, FilterMono16BitFirFilterMix, FilterStereo8BitFirFilterMix, FilterStereo16BitFirFilterMix,
- FilterMono8BitFirFilterRampMix,FilterMono16BitFirFilterRampMix,FilterStereo8BitFirFilterRampMix,FilterStereo16BitFirFilterRampMix,
-};
-
-
-/////////////////////////////////////////////////////////////////////////
-
-static LONG MPPFASTCALL GetSampleCount(MODCHANNEL *pChn, LONG nSamples)
-//---------------------------------------------------------------------
-{
- LONG nLoopStart = (pChn->dwFlags & CHN_LOOP) ? pChn->nLoopStart : 0;
- LONG nInc = pChn->nInc;
-
- if ((nSamples <= 0) || (!nInc) || (!pChn->nLength)) return 0;
- // Under zero ?
- if ((LONG)pChn->nPos < nLoopStart)
- {
- if (nInc < 0)
- {
- // Invert loop for bidi loops
- LONG nDelta = ((nLoopStart - pChn->nPos) << 16) - (pChn->nPosLo & 0xffff);
- pChn->nPos = nLoopStart | (nDelta>>16);
- pChn->nPosLo = nDelta & 0xffff;
- if (((LONG)pChn->nPos < nLoopStart) || (pChn->nPos >= (nLoopStart+pChn->nLength)/2))
- {
- pChn->nPos = nLoopStart; pChn->nPosLo = 0;
- }
- nInc = -nInc;
- pChn->nInc = nInc;
- pChn->dwFlags &= ~(CHN_PINGPONGFLAG); // go forward
- if ((!(pChn->dwFlags & CHN_LOOP)) || (pChn->nPos >= pChn->nLength))
- {
- pChn->nPos = pChn->nLength;
- pChn->nPosLo = 0;
- return 0;
- }
- } else
- {
- // We probably didn't hit the loop end yet (first loop), so we do nothing
- if ((LONG)pChn->nPos < 0) pChn->nPos = 0;
- }
- } else
- // Past the end
- if (pChn->nPos >= pChn->nLength)
- {
- if (!(pChn->dwFlags & CHN_LOOP)) return 0; // not looping -> stop this channel
- if (pChn->dwFlags & CHN_PINGPONGLOOP)
- {
- // Invert loop
- if (nInc > 0)
- {
- nInc = -nInc;
- pChn->nInc = nInc;
- }
- pChn->dwFlags |= CHN_PINGPONGFLAG;
- // adjust loop position
- LONG nDeltaHi = (pChn->nPos - pChn->nLength);
- LONG nDeltaLo = 0x10000 - (pChn->nPosLo & 0xffff);
- pChn->nPos = pChn->nLength - nDeltaHi - (nDeltaLo>>16);
- pChn->nPosLo = nDeltaLo & 0xffff;
- if ((pChn->nPos <= pChn->nLoopStart) || (pChn->nPos >= pChn->nLength)) pChn->nPos = pChn->nLength-1;
- } else
- {
- if (nInc < 0) // This is a bug
- {
- nInc = -nInc;
- pChn->nInc = nInc;
- }
- // Restart at loop start
- pChn->nPos += nLoopStart - pChn->nLength;
- if ((LONG)pChn->nPos < nLoopStart) pChn->nPos = pChn->nLoopStart;
- }
- }
- LONG nPos = pChn->nPos;
- // too big increment, and/or too small loop length
- if (nPos < nLoopStart)
- {
- if ((nPos < 0) || (nInc < 0)) return 0;
- }
- if ((nPos < 0) || (nPos >= (LONG)pChn->nLength)) return 0;
- LONG nPosLo = (USHORT)pChn->nPosLo, nSmpCount = nSamples;
- if (nInc < 0)
- {
- LONG nInv = -nInc;
- LONG maxsamples = 16384 / ((nInv>>16)+1);
- if (maxsamples < 2) maxsamples = 2;
- if (nSamples > maxsamples) nSamples = maxsamples;
- LONG nDeltaHi = (nInv>>16) * (nSamples - 1);
- LONG nDeltaLo = (nInv&0xffff) * (nSamples - 1);
- LONG nPosDest = nPos - nDeltaHi + ((nPosLo - nDeltaLo) >> 16);
- if (nPosDest < nLoopStart)
- {
- nSmpCount = (ULONG)(((((LONGLONG)nPos - nLoopStart) << 16) + nPosLo - 1) / nInv) + 1;
- }
- } else
- {
- LONG maxsamples = 16384 / ((nInc>>16)+1);
- if (maxsamples < 2) maxsamples = 2;
- if (nSamples > maxsamples) nSamples = maxsamples;
- LONG nDeltaHi = (nInc>>16) * (nSamples - 1);
- LONG nDeltaLo = (nInc&0xffff) * (nSamples - 1);
- LONG nPosDest = nPos + nDeltaHi + ((nPosLo + nDeltaLo)>>16);
- if (nPosDest >= (LONG)pChn->nLength)
- {
- nSmpCount = (ULONG)(((((LONGLONG)pChn->nLength - nPos) << 16) - nPosLo - 1) / nInc) + 1;
- }
- }
- if (nSmpCount <= 1) return 1;
- if (nSmpCount > nSamples) return nSamples;
- return nSmpCount;
-}
-
-
-UINT CSoundFile::CreateStereoMix(int count)
-//-----------------------------------------
-{
- LPLONG pOfsL, pOfsR;
- DWORD nchused, nchmixed;
-
- if (!count) return 0;
-#ifndef FASTSOUNDLIB
- if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
-#endif
- nchused = nchmixed = 0;
- for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
- {
- const LPMIXINTERFACE *pMixFuncTable;
- MODCHANNEL * const pChannel = &Chn[ChnMix[nChn]];
- UINT nFlags, nMasterCh;
- LONG nSmpCount;
- int nsamples;
- int *pbuffer;
-
- if (!pChannel->pCurrentSample) continue;
- nMasterCh = (ChnMix[nChn] < m_nChannels) ? ChnMix[nChn]+1 : pChannel->nMasterChn;
- pOfsR = &gnDryROfsVol;
- pOfsL = &gnDryLOfsVol;
- nFlags = 0;
- if (pChannel->dwFlags & CHN_16BIT) nFlags |= MIXNDX_16BIT;
- if (pChannel->dwFlags & CHN_STEREO) nFlags |= MIXNDX_STEREO;
- #ifndef NO_FILTER
- if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER;
- #endif
- if (!(pChannel->dwFlags & CHN_NOIDO))
- {
- // use hq-fir mixer?
- if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
- nFlags += MIXNDX_FIRSRC;
- else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
- nFlags += MIXNDX_SPLINESRC;
- else
- nFlags += MIXNDX_LINEARSRC; // use
- }
- if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol)
- && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp)))
- {
- pMixFuncTable = gpFastMixFunctionTable;
- } else
- {
- pMixFuncTable = gpMixFunctionTable;
- }
- nsamples = count;
-#ifndef NO_REVERB
- pbuffer = (gdwSoundSetup & SNDMIX_REVERB) ? MixReverbBuffer : MixSoundBuffer;
- if (pChannel->dwFlags & CHN_NOREVERB) pbuffer = MixSoundBuffer;
- if (pChannel->dwFlags & CHN_REVERB) pbuffer = MixReverbBuffer;
- if (pbuffer == MixReverbBuffer)
- {
- if (!gnReverbSend) memset(MixReverbBuffer, 0, count * 8);
- gnReverbSend += count;
- }
-#else
- pbuffer = MixSoundBuffer;
-#endif
- nchused++;
- ////////////////////////////////////////////////////
- SampleLooping:
- UINT nrampsamples = nsamples;
- if (pChannel->nRampLength > 0)
- {
- if ((LONG)nrampsamples > pChannel->nRampLength) nrampsamples = pChannel->nRampLength;
- }
- if ((nSmpCount = GetSampleCount(pChannel, nrampsamples)) <= 0)
- {
- // Stopping the channel
- pChannel->pCurrentSample = NULL;
- pChannel->nLength = 0;
- pChannel->nPos = 0;
- pChannel->nPosLo = 0;
- pChannel->nRampLength = 0;
- X86_EndChannelOfs(pChannel, pbuffer, nsamples);
- *pOfsR += pChannel->nROfs;
- *pOfsL += pChannel->nLOfs;
- pChannel->nROfs = pChannel->nLOfs = 0;
- pChannel->dwFlags &= ~CHN_PINGPONGFLAG;
- continue;
- }
- // Should we mix this channel ?
- UINT naddmix;
- if (((nchmixed >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
- || ((!pChannel->nRampLength) && (!(pChannel->nLeftVol|pChannel->nRightVol))))
- {
- LONG delta = (pChannel->nInc * (LONG)nSmpCount) + (LONG)pChannel->nPosLo;
- pChannel->nPosLo = delta & 0xFFFF;
- pChannel->nPos += (delta >> 16);
- pChannel->nROfs = pChannel->nLOfs = 0;
- pbuffer += nSmpCount*2;
- naddmix = 0;
- } else
- // Do mixing
- {
- // Choose function for mixing
- LPMIXINTERFACE pMixFunc;
- pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags];
- int *pbufmax = pbuffer + (nSmpCount*2);
- pChannel->nROfs = - *(pbufmax-2);
- pChannel->nLOfs = - *(pbufmax-1);
- pMixFunc(pChannel, pbuffer, pbufmax);
- pChannel->nROfs += *(pbufmax-2);
- pChannel->nLOfs += *(pbufmax-1);
- pbuffer = pbufmax;
- naddmix = 1;
-
- }
- nsamples -= nSmpCount;
- if (pChannel->nRampLength)
- {
- pChannel->nRampLength -= nSmpCount;
- if (pChannel->nRampLength <= 0)
- {
- pChannel->nRampLength = 0;
- pChannel->nRightVol = pChannel->nNewRightVol;
- pChannel->nLeftVol = pChannel->nNewLeftVol;
- pChannel->nRightRamp = pChannel->nLeftRamp = 0;
- if ((pChannel->dwFlags & CHN_NOTEFADE) && (!(pChannel->nFadeOutVol)))
- {
- pChannel->nLength = 0;
- pChannel->pCurrentSample = NULL;
- }
- }
- }
- if (nsamples > 0) goto SampleLooping;
- nchmixed += naddmix;
- }
- return nchused;
-}
-
-
-#ifdef MSC_VER
-#pragma warning (disable:4100)
-#endif
-
-// Clip and convert to 8 bit
-#ifdef MSC_VER
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//----------------------------------------------------------------------------------------------------------------------------
-{
- _asm {
- push ebx
- push esi
- push edi
- mov ebx, 16[esp] // ebx = 8-bit buffer
- mov esi, 20[esp] // esi = pBuffer
- mov edi, 24[esp] // edi = lSampleCount
- mov eax, 28[esp]
- mov ecx, dword ptr [eax] // ecx = clipmin
- mov eax, 32[esp]
- mov edx, dword ptr [eax] // edx = clipmax
-cliploop:
- mov eax, dword ptr [esi]
- inc ebx
- cdq
- and edx, (1 << (24-MIXING_ATTENUATION)) - 1
- add eax, edx
- cmp eax, MIXING_CLIPMIN
- jl cliplow
- cmp eax, MIXING_CLIPMAX
- jg cliphigh
- cmp eax, ecx
- jl updatemin
- cmp eax, edx
- jg updatemax
-cliprecover:
- add esi, 4
- sar eax, 24-MIXING_ATTENUATION
- xor eax, 0x80
- dec edi
- mov byte ptr [ebx-1], al
- jnz cliploop
- mov eax, 28[esp]
- mov dword ptr [eax], ecx
- mov eax, 32[esp]
- mov dword ptr [eax], edx
- mov eax, 24[esp]
- pop edi
- pop esi
- pop ebx
- ret
-updatemin:
- mov ecx, eax
- jmp cliprecover
-updatemax:
- mov edx, eax
- jmp cliprecover
-cliplow:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMIN
- jmp cliprecover
-cliphigh:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMAX
- jmp cliprecover
- }
-}
-#else //MSC_VER
-//---GCCFIX: Asm replaced with C function
-// The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-{
- int vumin = *lpMin, vumax = *lpMax;
- unsigned char *p = (unsigned char *)lp8;
- for (UINT i=0; i<lSampleCount; i++)
- {
- int n = pBuffer[i];
- if (n < MIXING_CLIPMIN)
- n = MIXING_CLIPMIN;
- else if (n > MIXING_CLIPMAX)
- n = MIXING_CLIPMAX;
- if (n < vumin)
- vumin = n;
- else if (n > vumax)
- vumax = n;
- p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned
- }
- *lpMin = vumin;
- *lpMax = vumax;
- return lSampleCount;
-}
-#endif //MSC_VER, else
-
-
-#ifdef MSC_VER
-// Clip and convert to 16 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
- _asm {
- push ebx
- push esi
- push edi
- mov ebx, 16[esp] // ebx = 16-bit buffer
- mov eax, 28[esp]
- mov esi, 20[esp] // esi = pBuffer
- mov ecx, dword ptr [eax] // ecx = clipmin
- mov edi, 24[esp] // edi = lSampleCount
- mov eax, 32[esp]
- push ebp
- mov ebp, dword ptr [eax] // edx = clipmax
-cliploop:
- mov eax, dword ptr [esi]
- add ebx, 2
- cdq
- and edx, (1 << (16-MIXING_ATTENUATION)) - 1
- add esi, 4
- add eax, edx
- cmp eax, MIXING_CLIPMIN
- jl cliplow
- cmp eax, MIXING_CLIPMAX
- jg cliphigh
- cmp eax, ecx
- jl updatemin
- cmp eax, ebp
- jg updatemax
-cliprecover:
- sar eax, 16-MIXING_ATTENUATION
- dec edi
- mov word ptr [ebx-2], ax
- jnz cliploop
- mov edx, ebp
- pop ebp
- mov eax, 28[esp]
- mov dword ptr [eax], ecx
- mov eax, 32[esp]
- mov dword ptr [eax], edx
- mov eax, 24[esp]
- pop edi
- shl eax, 1
- pop esi
- pop ebx
- ret
-updatemin:
- mov ecx, eax
- jmp cliprecover
-updatemax:
- mov ebp, eax
- jmp cliprecover
-cliplow:
- mov ecx, MIXING_CLIPMIN
- mov ebp, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMIN
- jmp cliprecover
-cliphigh:
- mov ecx, MIXING_CLIPMIN
- mov ebp, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMAX
- jmp cliprecover
- }
-}
-#else //MSC_VER
-//---GCCFIX: Asm replaced with C function
-// The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-{
- int vumin = *lpMin, vumax = *lpMax;
- signed short *p = (signed short *)lp16;
- for (UINT i=0; i<lSampleCount; i++)
- {
- int n = pBuffer[i];
- if (n < MIXING_CLIPMIN)
- n = MIXING_CLIPMIN;
- else if (n > MIXING_CLIPMAX)
- n = MIXING_CLIPMAX;
- if (n < vumin)
- vumin = n;
- else if (n > vumax)
- vumax = n;
- p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed
- }
- *lpMin = vumin;
- *lpMax = vumax;
- return lSampleCount * 2;
-}
-#endif //MSC_VER, else
-
-#ifdef MSC_VER
-// Clip and convert to 24 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
- _asm {
- push ebx
- push esi
- push edi
- mov ebx, 16[esp] // ebx = 8-bit buffer
- mov esi, 20[esp] // esi = pBuffer
- mov edi, 24[esp] // edi = lSampleCount
- mov eax, 28[esp]
- mov ecx, dword ptr [eax] // ecx = clipmin
- mov eax, 32[esp]
- push ebp
- mov edx, dword ptr [eax] // edx = clipmax
-cliploop:
- mov eax, dword ptr [esi]
- mov ebp, eax
- sar ebp, 31
- and ebp, (1 << (8-MIXING_ATTENUATION)) - 1
- add eax, ebp
- cmp eax, MIXING_CLIPMIN
- jl cliplow
- cmp eax, MIXING_CLIPMAX
- jg cliphigh
- cmp eax, ecx
- jl updatemin
- cmp eax, edx
- jg updatemax
-cliprecover:
- add ebx, 3
- sar eax, 8-MIXING_ATTENUATION
- add esi, 4
- mov word ptr [ebx-3], ax
- shr eax, 16
- dec edi
- mov byte ptr [ebx-1], al
- jnz cliploop
- pop ebp
- mov eax, 28[esp]
- mov dword ptr [eax], ecx
- mov eax, 32[esp]
- mov dword ptr [eax], edx
- mov edx, 24[esp]
- mov eax, edx
- pop edi
- shl eax, 1
- pop esi
- add eax, edx
- pop ebx
- ret
-updatemin:
- mov ecx, eax
- jmp cliprecover
-updatemax:
- mov edx, eax
- jmp cliprecover
-cliplow:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMIN
- jmp cliprecover
-cliphigh:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMAX
- jmp cliprecover
- }
-}
-#else //MSC_VER
-//---GCCFIX: Asm replaced with C function
-// 24-bit audio not supported.
-DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-{
- return 0;
-}
-#endif
-
-#ifdef MSC_VER
-// Clip and convert to 32 bit
-__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-//-----------------------------------------------------------------------------------------------------------------------------
-{
- _asm {
- push ebx
- push esi
- push edi
- mov ebx, 16[esp] // ebx = 32-bit buffer
- mov esi, 20[esp] // esi = pBuffer
- mov edi, 24[esp] // edi = lSampleCount
- mov eax, 28[esp]
- mov ecx, dword ptr [eax] // ecx = clipmin
- mov eax, 32[esp]
- mov edx, dword ptr [eax] // edx = clipmax
-cliploop:
- mov eax, dword ptr [esi]
- add ebx, 4
- add esi, 4
- cmp eax, MIXING_CLIPMIN
- jl cliplow
- cmp eax, MIXING_CLIPMAX
- jg cliphigh
- cmp eax, ecx
- jl updatemin
- cmp eax, edx
- jg updatemax
-cliprecover:
- shl eax, MIXING_ATTENUATION
- dec edi
- mov dword ptr [ebx-4], eax
- jnz cliploop
- mov eax, 28[esp]
- mov dword ptr [eax], ecx
- mov eax, 32[esp]
- mov dword ptr [eax], edx
- mov edx, 24[esp]
- pop edi
- mov eax, edx
- pop esi
- shl eax, 2
- pop ebx
- ret
-updatemin:
- mov ecx, eax
- jmp cliprecover
-updatemax:
- mov edx, eax
- jmp cliprecover
-cliplow:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMIN
- jmp cliprecover
-cliphigh:
- mov ecx, MIXING_CLIPMIN
- mov edx, MIXING_CLIPMAX
- mov eax, MIXING_CLIPMAX
- jmp cliprecover
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-// 32-bit audio not supported
-DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
-{
- return 0;
-}
-#endif
-
-
-#ifdef MSC_VER
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
-//------------------------------------------------------------
-{
- _asm {
- mov ecx, nSamples
- mov esi, pBuffer
- xor eax, eax
- mov edx, ecx
- shr ecx, 2
- and edx, 3
- jz unroll4x
-loop1x:
- add esi, 4
- dec edx
- mov dword ptr [esi-4], eax
- jnz loop1x
-unroll4x:
- or ecx, ecx
- jnz loop4x
- jmp done
-loop4x:
- add esi, 16
- dec ecx
- mov dword ptr [esi-16], eax
- mov dword ptr [esi-12], eax
- mov dword ptr [esi-8], eax
- mov dword ptr [esi-4], eax
- jnz loop4x
-done:;
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-// Will fill in later.
-void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
-{
- memset(pBuffer, 0, nSamples * sizeof(int));
-}
-#endif
-
-
-#ifdef MSC_VER
-__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
-//------------------------------------------------------------------------------------------------------
-{
- _asm {
- push ebx
- push ebp
- push esi
- push edi
- mov ecx, 28[esp] // ecx = samplecount
- mov esi, 20[esp] // esi = front buffer
- mov edi, 24[esp] // edi = rear buffer
- lea esi, [esi+ecx*4] // esi = &front[N]
- lea edi, [edi+ecx*4] // edi = &rear[N]
- lea ebx, [esi+ecx*4] // ebx = &front[N*2]
-interleaveloop:
- mov eax, dword ptr [esi-8]
- mov edx, dword ptr [esi-4]
- sub ebx, 16
- mov ebp, dword ptr [edi-8]
- mov dword ptr [ebx], eax
- mov dword ptr [ebx+4], edx
- mov eax, dword ptr [edi-4]
- sub esi, 8
- sub edi, 8
- dec ecx
- mov dword ptr [ebx+8], ebp
- mov dword ptr [ebx+12], eax
- jnz interleaveloop
- pop edi
- pop esi
- pop ebp
- pop ebx
- ret
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-// Multichannel not supported.
-void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
-{
-}
-#endif
-
-
-#ifdef MSC_VER
-VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
-//-------------------------------------------------------------
-{
- _asm {
- mov ecx, nSamples
- mov esi, pMixBuf
- mov edi, esi
-stloop:
- mov eax, dword ptr [esi]
- mov edx, dword ptr [esi+4]
- add edi, 4
- add esi, 8
- add eax, edx
- sar eax, 1
- dec ecx
- mov dword ptr [edi-4], eax
- jnz stloop
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
-{
- UINT j;
- for(UINT i = 0; i < nSamples; i++)
- {
- j = i << 1;
- pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1;
- }
-}
-#endif
-
-#define OFSDECAYSHIFT 8
-#define OFSDECAYMASK 0xFF
-
-
-#ifdef MSC_VER
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
-//---------------------------------------------------------------------------------------
-{
- _asm {
- mov edi, pBuffer
- mov ecx, nSamples
- mov eax, lpROfs
- mov edx, lpLOfs
- mov eax, [eax]
- mov edx, [edx]
- or ecx, ecx
- jz fill_loop
- mov ebx, eax
- or ebx, edx
- jz fill_loop
-ofsloop:
- mov ebx, eax
- mov esi, edx
- neg ebx
- neg esi
- sar ebx, 31
- sar esi, 31
- and ebx, OFSDECAYMASK
- and esi, OFSDECAYMASK
- add ebx, eax
- add esi, edx
- sar ebx, OFSDECAYSHIFT
- sar esi, OFSDECAYSHIFT
- sub eax, ebx
- sub edx, esi
- mov ebx, eax
- or ebx, edx
- jz fill_loop
- add edi, 8
- dec ecx
- mov [edi-8], eax
- mov [edi-4], edx
- jnz ofsloop
-fill_loop:
- mov ebx, ecx
- and ebx, 3
- jz fill4x
-fill1x:
- mov [edi], eax
- mov [edi+4], edx
- add edi, 8
- dec ebx
- jnz fill1x
-fill4x:
- shr ecx, 2
- or ecx, ecx
- jz done
-fill4xloop:
- mov [edi], eax
- mov [edi+4], edx
- mov [edi+8], eax
- mov [edi+12], edx
- add edi, 8*4
- dec ecx
- mov [edi-16], eax
- mov [edi-12], edx
- mov [edi-8], eax
- mov [edi-4], edx
- jnz fill4xloop
-done:
- mov esi, lpROfs
- mov edi, lpLOfs
- mov [esi], eax
- mov [edi], edx
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-#define OFSDECAYSHIFT 8
-#define OFSDECAYMASK 0xFF
-void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
-//---------------------------------------------------------------------------------------------------------
-{
- int rofs = *lpROfs;
- int lofs = *lpLOfs;
-
- if ((!rofs) && (!lofs))
- {
- X86_InitMixBuffer(pBuffer, nSamples*2);
- return;
- }
- for (UINT i=0; i<nSamples; i++)
- {
- int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
- int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
- rofs -= x_r;
- lofs -= x_l;
- pBuffer[i*2] = x_r;
- pBuffer[i*2+1] = x_l;
- }
- *lpROfs = rofs;
- *lpLOfs = lofs;
-}
-#endif
-
-#ifdef MSC_VER
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
-//----------------------------------------------------------------------------------
-{
- _asm {
- mov esi, pChannel
- mov edi, pBuffer
- mov ecx, nSamples
- mov eax, dword ptr [esi+MODCHANNEL.nROfs]
- mov edx, dword ptr [esi+MODCHANNEL.nLOfs]
- or ecx, ecx
- jz brkloop
-ofsloop:
- mov ebx, eax
- mov esi, edx
- neg ebx
- neg esi
- sar ebx, 31
- sar esi, 31
- and ebx, OFSDECAYMASK
- and esi, OFSDECAYMASK
- add ebx, eax
- add esi, edx
- sar ebx, OFSDECAYSHIFT
- sar esi, OFSDECAYSHIFT
- sub eax, ebx
- sub edx, esi
- mov ebx, eax
- add dword ptr [edi], eax
- add dword ptr [edi+4], edx
- or ebx, edx
- jz brkloop
- add edi, 8
- dec ecx
- jnz ofsloop
-brkloop:
- mov esi, pChannel
- mov dword ptr [esi+MODCHANNEL.nROfs], eax
- mov dword ptr [esi+MODCHANNEL.nLOfs], edx
- }
-}
-#else
-//---GCCFIX: Asm replaced with C function
-// Will fill in later.
-void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
-{
- int rofs = pChannel->nROfs;
- int lofs = pChannel->nLOfs;
-
- if ((!rofs) && (!lofs)) return;
- for (UINT i=0; i<nSamples; i++)
- {
- int x_r = (rofs + (((-rofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
- int x_l = (lofs + (((-lofs)>>31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
- rofs -= x_r;
- lofs -= x_l;
- pBuffer[i*2] += x_r;
- pBuffer[i*2+1] += x_l;
- }
- pChannel->nROfs = rofs;
- pChannel->nLOfs = lofs;
-}
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////////
-// Automatic Gain Control
-
-#ifndef NO_AGC
-
-// Limiter
-#define MIXING_LIMITMAX (0x08100000)
-#define MIXING_LIMITMIN (-MIXING_LIMITMAX)
-
-__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
-//-------------------------------------------------------------------------------
-{
- __asm {
- push ebx
- push ebp
- push esi
- push edi
- mov esi, 20[esp] // esi = pBuffer+i
- mov ecx, 24[esp] // ecx = i
- mov edi, 28[esp] // edi = AGC (0..256)
-agcloop:
- mov eax, dword ptr [esi]
- imul edi
- shrd eax, edx, AGC_PRECISION
- add esi, 4
- cmp eax, MIXING_LIMITMIN
- jl agcupdate
- cmp eax, MIXING_LIMITMAX
- jg agcupdate
-agcrecover:
- dec ecx
- mov dword ptr [esi-4], eax
- jnz agcloop
- mov eax, edi
- pop edi
- pop esi
- pop ebp
- pop ebx
- ret
-agcupdate:
- dec edi
- jmp agcrecover
- }
-}
-
-#pragma warning (default:4100)
-
-void CSoundFile::ProcessAGC(int count)
-//------------------------------------
-{
- static DWORD gAGCRecoverCount = 0;
- UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC);
- // Some kind custom law, so that the AGC stays quite stable, but slowly
- // goes back up if the sound level stays below a level inversely proportional
- // to the AGC level. (J'me comprends)
- if ((agc >= gnAGC) && (gnAGC < AGC_UNITY) && (gnVUMeter < (0xFF - (gnAGC >> (AGC_PRECISION-7))) ))
- {
- gAGCRecoverCount += count;
- UINT agctimeout = gdwMixingFreq + gnAGC;
- if (gnChannels >= 2) agctimeout <<= 1;
- if (gAGCRecoverCount >= agctimeout)
- {
- gAGCRecoverCount = 0;
- gnAGC++;
- }
- } else
- {
- gnAGC = agc;
- gAGCRecoverCount = 0;
- }
-}
-
-
-
-void CSoundFile::ResetAGC()
-//-------------------------
-{
- gnAGC = AGC_UNITY;
-}
-
-#endif // NO_AGC
-
+++ /dev/null
-#ifndef _ITDEFS_H_
-#define _ITDEFS_H_
-
-#pragma pack(1)
-
-typedef struct tagITFILEHEADER
-{
- DWORD id; /* 0x4D504D49 */
- CHAR songname[26];
- WORD reserved1; /* 0x1004 */
- WORD ordnum;
- WORD insnum;
- WORD smpnum;
- WORD patnum;
- WORD cwtv;
- WORD cmwt;
- WORD flags;
- WORD special;
- BYTE globalvol;
- BYTE mv;
- BYTE speed;
- BYTE tempo;
- BYTE sep;
- BYTE zero;
- WORD msglength;
- DWORD msgoffset;
- DWORD reserved2;
- BYTE chnpan[64];
- BYTE chnvol[64];
-} ITFILEHEADER;
-
-
-typedef struct tagITENVELOPE
-{
- BYTE flags;
- BYTE num;
- BYTE lpb;
- BYTE lpe;
- BYTE slb;
- BYTE sle;
- BYTE data[25*3];
- BYTE reserved;
-} ITENVELOPE;
-
-/* Old Impulse Instrument Format (cmwt < 0x200) */
-typedef struct tagITOLDINSTRUMENT
-{
- DWORD id; /* IMPI = 0x49504D49 */
- CHAR filename[12]; /* DOS file name */
- BYTE zero;
- BYTE flags;
- BYTE vls;
- BYTE vle;
- BYTE sls;
- BYTE sle;
- WORD reserved1;
- WORD fadeout;
- BYTE nna;
- BYTE dnc;
- WORD trkvers;
- BYTE nos;
- BYTE reserved2;
- CHAR name[26];
- WORD reserved3[3];
- BYTE keyboard[240];
- BYTE volenv[200];
- BYTE nodes[50];
-} ITOLDINSTRUMENT;
-
-
-/* Impulse Instrument Format */
-typedef struct tagITINSTRUMENT
-{
- DWORD id;
- CHAR filename[12];
- BYTE zero;
- BYTE nna;
- BYTE dct;
- BYTE dca;
- WORD fadeout;
- signed char pps;
- BYTE ppc;
- BYTE gbv;
- BYTE dfp;
- BYTE rv;
- BYTE rp;
- WORD trkvers;
- BYTE nos;
- BYTE reserved1;
- CHAR name[26];
- BYTE ifc;
- BYTE ifr;
- BYTE mch;
- BYTE mpr;
- WORD mbank;
- BYTE keyboard[240];
- ITENVELOPE volenv;
- ITENVELOPE panenv;
- ITENVELOPE pitchenv;
- BYTE dummy[4]; /* was 7, but IT v2.17 saves 554 bytes */
-} ITINSTRUMENT;
-
-
-/* IT Sample Format */
-typedef struct ITSAMPLESTRUCT
-{
- DWORD id; /* 0x53504D49 */
- CHAR filename[12];
- BYTE zero;
- BYTE gvl;
- BYTE flags;
- BYTE vol;
- CHAR name[26];
- BYTE cvt;
- BYTE dfp;
- DWORD length;
- DWORD loopbegin;
- DWORD loopend;
- DWORD C5Speed;
- DWORD susloopbegin;
- DWORD susloopend;
- DWORD samplepointer;
- BYTE vis;
- BYTE vid;
- BYTE vir;
- BYTE vit;
-} ITSAMPLESTRUCT;
-
-#pragma pack()
-
-extern BYTE autovibit2xm[8];
-extern BYTE autovibxm2it[8];
-
-#endif
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-////////////////////////////////////////////////////////////
-// 669 Composer / UNIS 669 module loader
-////////////////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-typedef struct tagFILEHEADER669
-{
- WORD sig; // 'if' or 'JN'
- signed char songmessage[108]; // Song Message
- BYTE samples; // number of samples (1-64)
- BYTE patterns; // number of patterns (1-128)
- BYTE restartpos;
- BYTE orders[128];
- BYTE tempolist[128];
- BYTE breaks[128];
-} FILEHEADER669;
-
-
-typedef struct tagSAMPLE669
-{
- BYTE filename[13];
- BYTE length[4]; // when will somebody think about DWORD align ???
- BYTE loopstart[4];
- BYTE loopend[4];
-} SAMPLE669;
-
-
-BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- BOOL b669Ext;
- const FILEHEADER669 *pfh = (const FILEHEADER669 *)lpStream;
- const SAMPLE669 *psmp = (const SAMPLE669 *)(lpStream + 0x1F1);
- DWORD dwMemPos = 0;
-
- if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE;
- if ((bswapLE16(pfh->sig) != 0x6669) && (bswapLE16(pfh->sig) != 0x4E4A)) return FALSE;
- b669Ext = (bswapLE16(pfh->sig) == 0x4E4A) ? TRUE : FALSE;
- if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128)
- || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
- DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
- if (dontfuckwithme > dwMemLength) return FALSE;
- for (UINT ichk=0; ichk<pfh->samples; ichk++)
- {
- DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length)));
- dontfuckwithme += len;
- }
- if (dontfuckwithme > dwMemLength) return FALSE;
- // That should be enough checking: this must be a 669 module.
- m_nType = MOD_TYPE_669;
- m_dwSongFlags |= SONG_LINEARSLIDES;
- m_nMinPeriod = 28 << 2;
- m_nMaxPeriod = 1712 << 3;
- m_nDefaultTempo = 125;
- m_nDefaultSpeed = 6;
- m_nChannels = 8;
- memcpy(m_szNames[0], pfh->songmessage, 16);
- m_nSamples = pfh->samples;
- for (UINT nins=1; nins<=m_nSamples; nins++, psmp++)
- {
- DWORD len = bswapLE32(*((DWORD *)(&psmp->length)));
- DWORD loopstart = bswapLE32(*((DWORD *)(&psmp->loopstart)));
- DWORD loopend = bswapLE32(*((DWORD *)(&psmp->loopend)));
- if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
- if ((loopend > len) && (!loopstart)) loopend = 0;
- if (loopend > len) loopend = len;
- if (loopstart + 4 >= loopend) loopstart = loopend = 0;
- Ins[nins].nLength = len;
- Ins[nins].nLoopStart = loopstart;
- Ins[nins].nLoopEnd = loopend;
- if (loopend) Ins[nins].uFlags |= CHN_LOOP;
- memcpy(m_szNames[nins], psmp->filename, 13);
- Ins[nins].nVolume = 256;
- Ins[nins].nGlobalVol = 64;
- Ins[nins].nPan = 128;
- }
- // Song Message
- m_lpszSongComments = new char[109];
- memcpy(m_lpszSongComments, pfh->songmessage, 108);
- m_lpszSongComments[108] = 0;
- // Reading Orders
- memcpy(Order, pfh->orders, 128);
- m_nRestartPos = pfh->restartpos;
- if (Order[m_nRestartPos] >= pfh->patterns) m_nRestartPos = 0;
- // Reading Pattern Break Locations
- for (UINT npan=0; npan<8; npan++)
- {
- ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0;
- ChnSettings[npan].nVolume = 64;
- }
- // Reading Patterns
- dwMemPos = 0x1F1 + pfh->samples * 25;
- for (UINT npat=0; npat<pfh->patterns; npat++)
- {
- Patterns[npat] = AllocatePattern(64, m_nChannels);
- if (!Patterns[npat]) break;
- PatternSize[npat] = 64;
- MODCOMMAND *m = Patterns[npat];
- const BYTE *p = lpStream + dwMemPos;
- for (UINT row=0; row<64; row++)
- {
- MODCOMMAND *mspeed = m;
- if ((row == pfh->breaks[npat]) && (row != 63))
- {
- for (UINT i=0; i<8; i++)
- {
- m[i].command = CMD_PATTERNBREAK;
- m[i].param = 0;
- }
- }
- for (UINT n=0; n<8; n++, m++, p+=3)
- {
- UINT note = p[0] >> 2;
- UINT instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
- UINT vol = p[1] & 0x0F;
- if (p[0] < 0xFE)
- {
- m->note = note + 37;
- m->instr = instr + 1;
- }
- if (p[0] <= 0xFE)
- {
- m->volcmd = VOLCMD_VOLUME;
- m->vol = (vol << 2) + 2;
- }
- if (p[2] != 0xFF)
- {
- UINT command = p[2] >> 4;
- UINT param = p[2] & 0x0F;
- switch(command)
- {
- case 0x00: command = CMD_PORTAMENTOUP; break;
- case 0x01: command = CMD_PORTAMENTODOWN; break;
- case 0x02: command = CMD_TONEPORTAMENTO; break;
- case 0x03: command = CMD_MODCMDEX; param |= 0x50; break;
- case 0x04: command = CMD_VIBRATO; param |= 0x40; break;
- case 0x05: if (param) command = CMD_SPEED; else command = 0; param += 2; break;
- case 0x06: if (param == 0) { command = CMD_PANNINGSLIDE; param = 0xFE; } else
- if (param == 1) { command = CMD_PANNINGSLIDE; param = 0xEF; } else
- command = 0;
- break;
- default: command = 0;
- }
- if (command)
- {
- if (command == CMD_SPEED) mspeed = NULL;
- m->command = command;
- m->param = param;
- }
- }
- }
- if ((!row) && (mspeed))
- {
- for (UINT i=0; i<8; i++) if (!mspeed[i].command)
- {
- mspeed[i].command = CMD_SPEED;
- mspeed[i].param = pfh->tempolist[npat] + 2;
- break;
- }
- }
- }
- dwMemPos += 0x600;
- }
- // Reading Samples
- for (UINT n=1; n<=m_nSamples; n++)
- {
- UINT len = Ins[n].nLength;
- if (dwMemPos >= dwMemLength) break;
- if (len > 4) ReadSample(&Ins[n], RS_PCM8U, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
- dwMemPos += len;
- }
- return TRUE;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
- */
-
-///////////////////////////////////////////////////
-//
-// AMF module loader
-//
-// There is 2 types of AMF files:
-// - ASYLUM Music Format
-// - Advanced Music Format(DSM)
-//
-///////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#define AMFLOG
-
-//#pragma warning(disable:4244)
-
-#pragma pack(1)
-
-typedef struct _AMFFILEHEADER
-{
- UCHAR szAMF[3];
- UCHAR version;
- CHAR title[32];
- UCHAR numsamples;
- UCHAR numorders;
- USHORT numtracks;
- UCHAR numchannels;
-} AMFFILEHEADER;
-
-typedef struct _AMFSAMPLE
-{
- UCHAR type;
- CHAR samplename[32];
- CHAR filename[13];
- ULONG offset;
- ULONG length;
- USHORT c2spd;
- UCHAR volume;
-} AMFSAMPLE;
-
-
-#pragma pack()
-
-
-#ifdef AMFLOG
-extern void Log(LPCSTR, ...);
-#endif
-
-VOID AMF_Unpack(MODCOMMAND *pPat, const BYTE *pTrack, UINT nRows, UINT nChannels)
-//-------------------------------------------------------------------------------
-{
- UINT lastinstr = 0;
- UINT nTrkSize = *(USHORT *)pTrack;
- nTrkSize += (UINT)pTrack[2] << 16;
- pTrack += 3;
- while (nTrkSize--)
- {
- UINT row = pTrack[0];
- UINT cmd = pTrack[1];
- UINT arg = pTrack[2];
- if (row >= nRows) break;
- MODCOMMAND *m = pPat + row * nChannels;
- if (cmd < 0x7F) // note+vol
- {
- m->note = cmd+1;
- if (!m->instr) m->instr = lastinstr;
- m->volcmd = VOLCMD_VOLUME;
- m->vol = arg;
- } else
- if (cmd == 0x7F) // duplicate row
- {
- signed char rdelta = (signed char)arg;
- int rowsrc = (int)row + (int)rdelta;
- if ((rowsrc >= 0) && (rowsrc < (int)nRows)) *m = pPat[rowsrc*nChannels];
- } else
- if (cmd == 0x80) // instrument
- {
- m->instr = arg+1;
- lastinstr = m->instr;
- } else
- if (cmd == 0x83) // volume
- {
- m->volcmd = VOLCMD_VOLUME;
- m->vol = arg;
- } else
- // effect
- {
- UINT command = cmd & 0x7F;
- UINT param = arg;
- switch(command)
- {
- // 0x01: Set Speed
- case 0x01: command = CMD_SPEED; break;
- // 0x02: Volume Slide
- // 0x0A: Tone Porta + Vol Slide
- // 0x0B: Vibrato + Vol Slide
- case 0x02: command = CMD_VOLUMESLIDE;
- case 0x0A: if (command == 0x0A) command = CMD_TONEPORTAVOL;
- case 0x0B: if (command == 0x0B) command = CMD_VIBRATOVOL;
- if (param & 0x80) param = (-(signed char)param)&0x0F;
- else param = (param&0x0F)<<4;
- break;
- // 0x04: Porta Up/Down
- case 0x04: if (param & 0x80) { command = CMD_PORTAMENTOUP; param = -(signed char)param; }
- else { command = CMD_PORTAMENTODOWN; } break;
- // 0x06: Tone Portamento
- case 0x06: command = CMD_TONEPORTAMENTO; break;
- // 0x07: Tremor
- case 0x07: command = CMD_TREMOR; break;
- // 0x08: Arpeggio
- case 0x08: command = CMD_ARPEGGIO; break;
- // 0x09: Vibrato
- case 0x09: command = CMD_VIBRATO; break;
- // 0x0C: Pattern Break
- case 0x0C: command = CMD_PATTERNBREAK; break;
- // 0x0D: Position Jump
- case 0x0D: command = CMD_POSITIONJUMP; break;
- // 0x0F: Retrig
- case 0x0F: command = CMD_RETRIG; break;
- // 0x10: Offset
- case 0x10: command = CMD_OFFSET; break;
- // 0x11: Fine Volume Slide
- case 0x11: if (param) { command = CMD_VOLUMESLIDE;
- if (param & 0x80) param = 0xF0|((-(signed char)param)&0x0F);
- else param = 0x0F|((param&0x0F)<<4);
- } else command = 0; break;
- // 0x12: Fine Portamento
- // 0x16: Extra Fine Portamento
- case 0x12:
- case 0x16: if (param) { int mask = (command == 0x16) ? 0xE0 : 0xF0;
- command = (param & 0x80) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN;
- if (param & 0x80) param = mask|((-(signed char)param)&0x0F);
- else param |= mask;
- } else command = 0; break;
- // 0x13: Note Delay
- case 0x13: command = CMD_S3MCMDEX; param = 0xD0|(param & 0x0F); break;
- // 0x14: Note Cut
- case 0x14: command = CMD_S3MCMDEX; param = 0xC0|(param & 0x0F); break;
- // 0x15: Set Tempo
- case 0x15: command = CMD_TEMPO; break;
- // 0x17: Panning
- case 0x17: param = (param+64)&0x7F;
- if (m->command) { if (!m->volcmd) { m->volcmd = VOLCMD_PANNING; m->vol = param/2; } command = 0; }
- else { command = CMD_PANNING8; }
- // Unknown effects
- default: command = param = 0;
- }
- if (command)
- {
- m->command = command;
- m->param = param;
- }
- }
- pTrack += 3;
- }
-}
-
-
-
-BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
- DWORD dwMemPos;
-
- if ((!lpStream) || (dwMemLength < 2048)) return FALSE;
- if ((!strncmp((LPCTSTR)lpStream, "ASYLUM Music Format V1.0", 25)) && (dwMemLength > 4096))
- {
- UINT numorders, numpats, numsamples;
-
- dwMemPos = 32;
- numpats = lpStream[dwMemPos+3];
- numorders = lpStream[dwMemPos+4];
- numsamples = 64;
- dwMemPos += 6;
- if ((!numpats) || (numpats > MAX_PATTERNS) || (!numorders)
- || (numpats*64*32 + 294 + 37*64 >= dwMemLength)) return FALSE;
- m_nType = MOD_TYPE_AMF0;
- m_nChannels = 8;
- m_nInstruments = 0;
- m_nSamples = 31;
- m_nDefaultTempo = 125;
- m_nDefaultSpeed = 6;
- for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
- {
- Order[iOrd] = (iOrd < numorders) ? lpStream[dwMemPos+iOrd] : 0xFF;
- }
- dwMemPos = 294; // ???
- for (UINT iSmp=0; iSmp<numsamples; iSmp++)
- {
- MODINSTRUMENT *psmp = &Ins[iSmp+1];
- memcpy(m_szNames[iSmp+1], lpStream+dwMemPos, 22);
- psmp->nFineTune = MOD2XMFineTune(lpStream[dwMemPos+22]);
- psmp->nVolume = lpStream[dwMemPos+23];
- psmp->nGlobalVol = 64;
- if (psmp->nVolume > 0x40) psmp->nVolume = 0x40;
- psmp->nVolume <<= 2;
- psmp->nLength = *((LPDWORD)(lpStream+dwMemPos+25));
- psmp->nLoopStart = *((LPDWORD)(lpStream+dwMemPos+29));
- psmp->nLoopEnd = psmp->nLoopStart + *((LPDWORD)(lpStream+dwMemPos+33));
- if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength))
- {
- psmp->uFlags = CHN_LOOP;
- } else
- {
- psmp->nLoopStart = psmp->nLoopEnd = 0;
- }
- if ((psmp->nLength) && (iSmp>31)) m_nSamples = iSmp+1;
- dwMemPos += 37;
- }
- for (UINT iPat=0; iPat<numpats; iPat++)
- {
- MODCOMMAND *p = AllocatePattern(64, m_nChannels);
- if (!p) break;
- Patterns[iPat] = p;
- PatternSize[iPat] = 64;
- const UCHAR *pin = lpStream + dwMemPos;
- for (UINT i=0; i<8*64; i++)
- {
- p->note = 0;
-
- if (pin[0])
- {
- p->note = pin[0] + 13;
- }
- p->instr = pin[1];
- p->command = pin[2];
- p->param = pin[3];
- if (p->command > 0x0F)
- {
- #ifdef AMFLOG
- Log("0x%02X.0x%02X ?", p->command, p->param);
- #endif
- p->command = 0;
- }
- ConvertModCommand(p);
- pin += 4;
- p++;
- }
- dwMemPos += 64*32;
- }
- // Read samples
- for (UINT iData=0; iData<m_nSamples; iData++)
- {
- MODINSTRUMENT *psmp = &Ins[iData+1];
- if (psmp->nLength)
- {
- dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength);
- }
- }
- return TRUE;
- }
- ////////////////////////////
- // DSM/AMF
- USHORT *ptracks[MAX_PATTERNS];
- DWORD sampleseekpos[MAX_SAMPLES];
-
- if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F')
- || (pfh->version < 10) || (pfh->version > 14) || (!pfh->numtracks)
- || (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS)
- || (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES)
- || (pfh->numchannels < 4) || (pfh->numchannels > 32))
- return FALSE;
- memcpy(m_szNames[0], pfh->title, 32);
- dwMemPos = sizeof(AMFFILEHEADER);
- m_nType = MOD_TYPE_AMF;
- m_nChannels = pfh->numchannels;
- m_nSamples = pfh->numsamples;
- m_nInstruments = 0;
- // Setup Channel Pan Positions
- if (pfh->version >= 11)
- {
- signed char *panpos = (signed char *)(lpStream + dwMemPos);
- UINT nchannels = (pfh->version >= 13) ? 32 : 16;
- for (UINT i=0; i<nchannels; i++)
- {
- int pan = (panpos[i] + 64) * 2;
- if (pan < 0) pan = 0;
- if (pan > 256) { pan = 128; ChnSettings[i].dwFlags |= CHN_SURROUND; }
- ChnSettings[i].nPan = pan;
- }
- dwMemPos += nchannels;
- } else
- {
- for (UINT i=0; i<16; i++)
- {
- ChnSettings[i].nPan = (lpStream[dwMemPos+i] & 1) ? 0x30 : 0xD0;
- }
- dwMemPos += 16;
- }
- // Get Tempo/Speed
- m_nDefaultTempo = 125;
- m_nDefaultSpeed = 6;
- if (pfh->version >= 13)
- {
- if (lpStream[dwMemPos] >= 32) m_nDefaultTempo = lpStream[dwMemPos];
- if (lpStream[dwMemPos+1] <= 32) m_nDefaultSpeed = lpStream[dwMemPos+1];
- dwMemPos += 2;
- }
- // Setup sequence list
- for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
- {
- Order[iOrd] = 0xFF;
- if (iOrd < pfh->numorders)
- {
- Order[iOrd] = iOrd;
- PatternSize[iOrd] = 64;
- if (pfh->version >= 14)
- {
- PatternSize[iOrd] = *(USHORT *)(lpStream+dwMemPos);
- dwMemPos += 2;
- }
- ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
- dwMemPos += m_nChannels * sizeof(USHORT);
- }
- }
- if (dwMemPos + m_nSamples * (sizeof(AMFSAMPLE)+8) > dwMemLength) return TRUE;
- // Read Samples
- UINT maxsampleseekpos = 0;
- for (UINT iIns=0; iIns<m_nSamples; iIns++)
- {
- MODINSTRUMENT *pins = &Ins[iIns+1];
- AMFSAMPLE *psh = (AMFSAMPLE *)(lpStream + dwMemPos);
-
- dwMemPos += sizeof(AMFSAMPLE);
- memcpy(m_szNames[iIns+1], psh->samplename, 32);
- memcpy(pins->name, psh->filename, 13);
- pins->nLength = psh->length;
- pins->nC4Speed = psh->c2spd;
- pins->nGlobalVol = 64;
- pins->nVolume = psh->volume * 4;
- if (pfh->version >= 11)
- {
- pins->nLoopStart = *(DWORD *)(lpStream+dwMemPos);
- pins->nLoopEnd = *(DWORD *)(lpStream+dwMemPos+4);
- dwMemPos += 8;
- } else
- {
- pins->nLoopStart = *(WORD *)(lpStream+dwMemPos);
- pins->nLoopEnd = pins->nLength;
- dwMemPos += 2;
- }
- sampleseekpos[iIns] = 0;
- if ((psh->type) && (psh->offset < dwMemLength-1))
- {
- sampleseekpos[iIns] = psh->offset;
- if (psh->offset > maxsampleseekpos) maxsampleseekpos = psh->offset;
- if ((pins->nLoopEnd > pins->nLoopStart + 2)
- && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
- }
- }
- // Read Track Mapping Table
- USHORT *pTrackMap = (USHORT *)(lpStream+dwMemPos);
- UINT realtrackcnt = 0;
- dwMemPos += pfh->numtracks * sizeof(USHORT);
- for (UINT iTrkMap=0; iTrkMap<pfh->numtracks; iTrkMap++)
- {
- if (realtrackcnt < pTrackMap[iTrkMap]) realtrackcnt = pTrackMap[iTrkMap];
- }
- // Store tracks positions
- BYTE **pTrackData = new BYTE *[realtrackcnt];
- memset(pTrackData, 0, sizeof(pTrackData));
- for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength)
- {
- UINT nTrkSize = *(USHORT *)(lpStream+dwMemPos);
- nTrkSize += (UINT)lpStream[dwMemPos+2] << 16;
- if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength)
- {
- pTrackData[iTrack] = (BYTE *)(lpStream + dwMemPos);
- }
- dwMemPos += nTrkSize * 3 + 3;
- }
- // Create the patterns from the list of tracks
- for (UINT iPat=0; iPat<pfh->numorders; iPat++)
- {
- MODCOMMAND *p = AllocatePattern(PatternSize[iPat], m_nChannels);
- if (!p) break;
- Patterns[iPat] = p;
- for (UINT iChn=0; iChn<m_nChannels; iChn++)
- {
- UINT nTrack = ptracks[iPat][iChn];
- if ((nTrack) && (nTrack <= pfh->numtracks))
- {
- UINT realtrk = pTrackMap[nTrack-1];
- if (realtrk)
- {
- realtrk--;
- if ((realtrk < realtrackcnt) && (pTrackData[realtrk]))
- {
- AMF_Unpack(p+iChn, pTrackData[realtrk], PatternSize[iPat], m_nChannels);
- }
- }
- }
- }
- }
- delete pTrackData;
- // Read Sample Data
- for (UINT iSeek=1; iSeek<=maxsampleseekpos; iSeek++)
- {
- if (dwMemPos >= dwMemLength) break;
- for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (iSeek == sampleseekpos[iSmp])
- {
- MODINSTRUMENT *pins = &Ins[iSmp+1];
- dwMemPos += ReadSample(pins, RS_PCM8U, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
- break;
- }
- }
- return TRUE;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-//////////////////////////////////////////////
-// AMS module loader //
-//////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#pragma pack(1)
-
-typedef struct AMSFILEHEADER
-{
- char szHeader[7]; // "Extreme" // changed from CHAR
- BYTE verlo, verhi; // 0x??,0x01
- BYTE chncfg;
- BYTE samples;
- WORD patterns;
- WORD orders;
- BYTE vmidi;
- WORD extra;
-} AMSFILEHEADER;
-
-typedef struct AMSSAMPLEHEADER
-{
- DWORD length;
- DWORD loopstart;
- DWORD loopend;
- BYTE finetune_and_pan;
- WORD samplerate; // C-2 = 8363
- BYTE volume; // 0-127
- BYTE infobyte;
-} AMSSAMPLEHEADER;
-
-
-#pragma pack()
-
-
-
-BOOL CSoundFile::ReadAMS(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- BYTE pkinf[MAX_SAMPLES];
- AMSFILEHEADER *pfh = (AMSFILEHEADER *)lpStream;
- DWORD dwMemPos;
- UINT tmp, tmp2;
-
- if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
- if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7))
- || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES)
- || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS))
- {
- return ReadAMS2(lpStream, dwMemLength);
- }
- dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra;
- if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return FALSE;
- m_nType = MOD_TYPE_AMS;
- m_nInstruments = 0;
- m_nChannels = (pfh->chncfg & 0x1F) + 1;
- m_nSamples = pfh->samples;
- for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER))
- {
- AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos);
- MODINSTRUMENT *pins = &Ins[nSmp];
- pins->nLength = psh->length;
- pins->nLoopStart = psh->loopstart;
- pins->nLoopEnd = psh->loopend;
- pins->nGlobalVol = 64;
- pins->nVolume = psh->volume << 1;
- pins->nC4Speed = psh->samplerate;
- pins->nPan = (psh->finetune_and_pan & 0xF0);
- if (pins->nPan < 0x80) pins->nPan += 0x10;
- pins->nFineTune = MOD2XMFineTune(psh->finetune_and_pan & 0x0F);
- pins->uFlags = (psh->infobyte & 0x80) ? CHN_16BIT : 0;
- if ((pins->nLoopEnd <= pins->nLength) && (pins->nLoopStart+4 <= pins->nLoopEnd)) pins->uFlags |= CHN_LOOP;
- pkinf[nSmp] = psh->infobyte;
- }
- // Read Song Name
- tmp = lpStream[dwMemPos++];
- if (dwMemPos + tmp + 1 >= dwMemLength) return TRUE;
- tmp2 = (tmp < 32) ? tmp : 31;
- if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2);
- m_szNames[0][tmp2] = 0;
- dwMemPos += tmp;
- // Read sample names
- for (UINT sNam=1; sNam<=m_nSamples; sNam++)
- {
- if (dwMemPos + 32 >= dwMemLength) return TRUE;
- tmp = lpStream[dwMemPos++];
- tmp2 = (tmp < 32) ? tmp : 31;
- if (tmp2) memcpy(m_szNames[sNam], lpStream+dwMemPos, tmp2);
- dwMemPos += tmp;
- }
- // Skip Channel names
- for (UINT cNam=0; cNam<m_nChannels; cNam++)
- {
- if (dwMemPos + 32 >= dwMemLength) return TRUE;
- tmp = lpStream[dwMemPos++];
- dwMemPos += tmp;
- }
- // Read Pattern Names
- m_lpszPatternNames = new char[pfh->patterns * 32]; // changed from CHAR
- if (!m_lpszPatternNames) return TRUE;
- m_nPatternNames = pfh->patterns;
- memset(m_lpszPatternNames, 0, m_nPatternNames * 32);
- for (UINT pNam=0; pNam < m_nPatternNames; pNam++)
- {
- if (dwMemPos + 32 >= dwMemLength) return TRUE;
- tmp = lpStream[dwMemPos++];
- tmp2 = (tmp < 32) ? tmp : 31;
- if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2);
- dwMemPos += tmp;
- }
- // Read Song Comments
- tmp = *((WORD *)(lpStream+dwMemPos));
- dwMemPos += 2;
- if (dwMemPos + tmp >= dwMemLength) return TRUE;
- if (tmp)
- {
- m_lpszSongComments = new char[tmp+1]; // changed from CHAR
- if (!m_lpszSongComments) return TRUE;
- memset(m_lpszSongComments, 0, tmp+1);
- memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp);
- dwMemPos += tmp;
- }
- // Read Order List
- for (UINT iOrd=0; iOrd<pfh->orders; iOrd++, dwMemPos += 2)
- {
- UINT n = *((WORD *)(lpStream+dwMemPos));
- Order[iOrd] = (BYTE)n;
- }
- // Read Patterns
- for (UINT iPat=0; iPat<pfh->patterns; iPat++)
- {
- if (dwMemPos + 4 >= dwMemLength) return TRUE;
- UINT len = *((DWORD *)(lpStream + dwMemPos));
- dwMemPos += 4;
- if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE;
- PatternSize[iPat] = 64;
- MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels);
- if (!m) return TRUE;
- Patterns[iPat] = m;
- const BYTE *p = lpStream + dwMemPos;
- UINT row = 0, i = 0;
- while ((row < PatternSize[iPat]) && (i+2 < len))
- {
- BYTE b0 = p[i++];
- BYTE b1 = p[i++];
- BYTE b2 = 0;
- UINT ch = b0 & 0x3F;
- // Note+Instr
- if (!(b0 & 0x40))
- {
- b2 = p[i++];
- if (ch < m_nChannels)
- {
- if (b1 & 0x7F) m[ch].note = (b1 & 0x7F) + 25;
- m[ch].instr = b2;
- }
- if (b1 & 0x80)
- {
- b0 |= 0x40;
- b1 = p[i++];
- }
- }
- // Effect
- if (b0 & 0x40)
- {
- anothercommand:
- if (b1 & 0x40)
- {
- if (ch < m_nChannels)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = b1 & 0x3F;
- }
- } else
- {
- b2 = p[i++];
- if (ch < m_nChannels)
- {
- UINT cmd = b1 & 0x3F;
- if (cmd == 0x0C)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = b2 >> 1;
- } else
- if (cmd == 0x0E)
- {
- if (!m[ch].command)
- {
- UINT command = CMD_S3MCMDEX;
- UINT param = b2;
- switch(param & 0xF0)
- {
- case 0x00: if (param & 0x08) { param &= 0x07; param |= 0x90; } else {command=param=0;} break;
- case 0x10: command = CMD_PORTAMENTOUP; param |= 0xF0; break;
- case 0x20: command = CMD_PORTAMENTODOWN; param |= 0xF0; break;
- case 0x30: param = (param & 0x0F) | 0x10; break;
- case 0x40: param = (param & 0x0F) | 0x30; break;
- case 0x50: param = (param & 0x0F) | 0x20; break;
- case 0x60: param = (param & 0x0F) | 0xB0; break;
- case 0x70: param = (param & 0x0F) | 0x40; break;
- case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
- case 0xA0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param = (param << 4) | 0x0F; } else command=param=0; break;
- case 0xB0: if (param & 0x0F) { command = CMD_VOLUMESLIDE; param |= 0xF0; } else command=param=0; break;
- }
- m[ch].command = command;
- m[ch].param = param;
- }
- } else
- {
- m[ch].command = cmd;
- m[ch].param = b2;
- ConvertModCommand(&m[ch]);
- }
- }
- }
- if (b1 & 0x80)
- {
- b1 = p[i++];
- if (i <= len) goto anothercommand;
- }
- }
- if (b0 & 0x80)
- {
- row++;
- m += m_nChannels;
- }
- }
- dwMemPos += len;
- }
- // Read Samples
- for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
- {
- if (dwMemPos >= dwMemLength - 9) return TRUE;
- UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
- dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
- }
- return TRUE;
-}
-
-
-/////////////////////////////////////////////////////////////////////
-// AMS 2.2 loader
-
-#pragma pack(1)
-
-typedef struct AMS2FILEHEADER
-{
- DWORD dwHdr1; // AMShdr
- WORD wHdr2;
- BYTE b1A; // 0x1A
- BYTE titlelen; // 30-bytes max
- CHAR szTitle[30]; // [titlelen]
-} AMS2FILEHEADER;
-
-typedef struct AMS2SONGHEADER
-{
- WORD version;
- BYTE instruments;
- WORD patterns;
- WORD orders;
- WORD bpm;
- BYTE speed;
- BYTE channels;
- BYTE commands;
- BYTE rows;
- WORD flags;
-} AMS2SONGHEADER;
-
-typedef struct AMS2INSTRUMENT
-{
- BYTE samples;
- BYTE notemap[120];
-} AMS2INSTRUMENT;
-
-typedef struct AMS2ENVELOPE
-{
- BYTE speed;
- BYTE sustain;
- BYTE loopbegin;
- BYTE loopend;
- BYTE points;
- BYTE info[3];
-} AMS2ENVELOPE;
-
-typedef struct AMS2SAMPLE
-{
- DWORD length;
- DWORD loopstart;
- DWORD loopend;
- WORD frequency;
- BYTE finetune;
- WORD c4speed;
- CHAR transpose;
- BYTE volume;
- BYTE flags;
-} AMS2SAMPLE;
-
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength)
-//------------------------------------------------------------
-{
- AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
- AMS2SONGHEADER *psh;
- DWORD dwMemPos;
- BYTE smpmap[16];
- BYTE packedsamples[MAX_SAMPLES];
-
- if ((pfh->dwHdr1 != 0x68534D41) || (pfh->wHdr2 != 0x7264)
- || (pfh->b1A != 0x1A) || (pfh->titlelen > 30)) return FALSE;
- dwMemPos = pfh->titlelen + 8;
- psh = (AMS2SONGHEADER *)(lpStream + dwMemPos);
- if (((psh->version & 0xFF00) != 0x0200) || (!psh->instruments)
- || (psh->instruments > MAX_INSTRUMENTS) || (!psh->patterns) || (!psh->orders)) return FALSE;
- dwMemPos += sizeof(AMS2SONGHEADER);
- if (pfh->titlelen)
- {
- memcpy(m_szNames, pfh->szTitle, pfh->titlelen);
- m_szNames[0][pfh->titlelen] = 0;
- }
- m_nType = MOD_TYPE_AMS;
- m_nChannels = 32;
- m_nDefaultTempo = psh->bpm >> 8;
- m_nDefaultSpeed = psh->speed;
- m_nInstruments = psh->instruments;
- m_nSamples = 0;
- if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES;
- for (UINT nIns=1; nIns<=m_nInstruments; nIns++)
- {
- UINT insnamelen = lpStream[dwMemPos];
- CHAR *pinsname = (CHAR *)(lpStream+dwMemPos+1);
- dwMemPos += insnamelen + 1;
- AMS2INSTRUMENT *pins = (AMS2INSTRUMENT *)(lpStream + dwMemPos);
- dwMemPos += sizeof(AMS2INSTRUMENT);
- if (dwMemPos + 1024 >= dwMemLength) return TRUE;
- AMS2ENVELOPE *volenv, *panenv, *pitchenv;
- volenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
- dwMemPos += 5 + volenv->points*3;
- panenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
- dwMemPos += 5 + panenv->points*3;
- pitchenv = (AMS2ENVELOPE *)(lpStream+dwMemPos);
- dwMemPos += 5 + pitchenv->points*3;
- INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
- if (!penv) return TRUE;
- memset(smpmap, 0, sizeof(smpmap));
- memset(penv, 0, sizeof(INSTRUMENTHEADER));
- for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++)
- {
- if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break;
- m_nSamples++;
- smpmap[ismpmap] = m_nSamples;
- }
- penv->nGlobalVol = 64;
- penv->nPan = 128;
- penv->nPPC = 60;
- Headers[nIns] = penv;
- if (insnamelen)
- {
- if (insnamelen > 31) insnamelen = 31;
- memcpy(penv->name, pinsname, insnamelen);
- penv->name[insnamelen] = 0;
- }
- for (UINT inotemap=0; inotemap<120; inotemap++)
- {
- penv->NoteMap[inotemap] = inotemap+1;
- penv->Keyboard[inotemap] = smpmap[pins->notemap[inotemap] & 0x0F];
- }
- // Volume Envelope
- {
- UINT pos = 0;
- penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points;
- penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain;
- penv->nVolLoopStart = volenv->loopbegin;
- penv->nVolLoopEnd = volenv->loopend;
- for (UINT i=0; i<penv->nVolEnv; i++)
- {
- penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
- pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
- penv->VolPoints[i] = (WORD)pos;
- }
- }
- penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3;
- UINT envflags = lpStream[dwMemPos+3];
- if (envflags & 0x01) penv->dwFlags |= ENV_VOLLOOP;
- if (envflags & 0x02) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (envflags & 0x04) penv->dwFlags |= ENV_VOLUME;
- dwMemPos += 5;
- // Read Samples
- for (UINT ismp=0; ismp<pins->samples; ismp++)
- {
- MODINSTRUMENT *psmp = ((ismp < 16) && (smpmap[ismp])) ? &Ins[smpmap[ismp]] : NULL;
- UINT smpnamelen = lpStream[dwMemPos];
- if ((psmp) && (smpnamelen) && (smpnamelen <= 22))
- {
- memcpy(m_szNames[smpmap[ismp]], lpStream+dwMemPos+1, smpnamelen);
- }
- dwMemPos += smpnamelen + 1;
- if (psmp)
- {
- AMS2SAMPLE *pams = (AMS2SAMPLE *)(lpStream+dwMemPos);
- psmp->nGlobalVol = 64;
- psmp->nPan = 128;
- psmp->nLength = pams->length;
- psmp->nLoopStart = pams->loopstart;
- psmp->nLoopEnd = pams->loopend;
- psmp->nC4Speed = pams->c4speed;
- psmp->RelativeTone = pams->transpose;
- psmp->nVolume = pams->volume / 2;
- packedsamples[smpmap[ismp]] = pams->flags;
- if (pams->flags & 0x04) psmp->uFlags |= CHN_16BIT;
- if (pams->flags & 0x08) psmp->uFlags |= CHN_LOOP;
- if (pams->flags & 0x10) psmp->uFlags |= CHN_PINGPONGLOOP;
- }
- dwMemPos += sizeof(AMS2SAMPLE);
- }
- }
- if (dwMemPos + 256 >= dwMemLength) return TRUE;
- // Comments
- {
- UINT composernamelen = lpStream[dwMemPos];
- if (composernamelen)
- {
- m_lpszSongComments = new char[composernamelen+1]; // changed from CHAR
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen);
- m_lpszSongComments[composernamelen] = 0;
- }
- }
- dwMemPos += composernamelen + 1;
- // channel names
- for (UINT i=0; i<32; i++)
- {
- UINT chnnamlen = lpStream[dwMemPos];
- if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME))
- {
- memcpy(ChnSettings[i].szName, lpStream+dwMemPos+1, chnnamlen);
- }
- dwMemPos += chnnamlen + 1;
- if (dwMemPos + chnnamlen + 256 >= dwMemLength) return TRUE;
- }
- // packed comments (ignored)
- UINT songtextlen = *((LPDWORD)(lpStream+dwMemPos));
- dwMemPos += songtextlen;
- if (dwMemPos + 256 >= dwMemLength) return TRUE;
- }
- // Order List
- {
- for (UINT i=0; i<MAX_ORDERS; i++)
- {
- Order[i] = 0xFF;
- if (dwMemPos + 2 >= dwMemLength) return TRUE;
- if (i < psh->orders)
- {
- Order[i] = lpStream[dwMemPos];
- dwMemPos += 2;
- }
- }
- }
- // Pattern Data
- for (UINT ipat=0; ipat<psh->patterns; ipat++)
- {
- if (dwMemPos+8 >= dwMemLength) return TRUE;
- UINT packedlen = *((LPDWORD)(lpStream+dwMemPos));
- UINT numrows = 1 + (UINT)(lpStream[dwMemPos+4]);
- //UINT patchn = 1 + (UINT)(lpStream[dwMemPos+5] & 0x1F);
- //UINT patcmds = 1 + (UINT)(lpStream[dwMemPos+5] >> 5);
- UINT patnamlen = lpStream[dwMemPos+6];
- dwMemPos += 4;
- if ((ipat < MAX_PATTERNS) && (packedlen < dwMemLength-dwMemPos) && (numrows >= 8))
- {
- if ((patnamlen) && (patnamlen < MAX_PATTERNNAME))
- {
- char s[MAX_PATTERNNAME]; // changed from CHAR
- memcpy(s, lpStream+dwMemPos+3, patnamlen);
- s[patnamlen] = 0;
- SetPatternName(ipat, s);
- }
- PatternSize[ipat] = numrows;
- Patterns[ipat] = AllocatePattern(numrows, m_nChannels);
- if (!Patterns[ipat]) return TRUE;
- // Unpack Pattern Data
- LPCBYTE psrc = lpStream + dwMemPos;
- UINT pos = 3 + patnamlen;
- UINT row = 0;
- while ((pos < packedlen) && (row < numrows))
- {
- MODCOMMAND *m = Patterns[ipat] + row * m_nChannels;
- UINT byte1 = psrc[pos++];
- UINT ch = byte1 & 0x1F;
- // Read Note + Instr
- if (!(byte1 & 0x40))
- {
- UINT byte2 = psrc[pos++];
- UINT note = byte2 & 0x7F;
- if (note) m[ch].note = (note > 1) ? (note-1) : 0xFF;
- m[ch].instr = psrc[pos++];
- // Read Effect
- while (byte2 & 0x80)
- {
- byte2 = psrc[pos++];
- if (byte2 & 0x40)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = byte2 & 0x3F;
- } else
- {
- UINT command = byte2 & 0x3F;
- UINT param = psrc[pos++];
- if (command == 0x0C)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = param / 2;
- } else
- if (command < 0x10)
- {
- m[ch].command = command;
- m[ch].param = param;
- ConvertModCommand(&m[ch]);
- } else
- {
- // TODO: AMS effects
- }
- }
- }
- }
- if (byte1 & 0x80) row++;
- }
- }
- dwMemPos += packedlen;
- }
- // Read Samples
- for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Ins[iSmp].nLength)
- {
- if (dwMemPos >= dwMemLength - 9) return TRUE;
- UINT flags;
- if (packedsamples[iSmp] & 0x03)
- {
- flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_AMS16 : RS_AMS8;
- } else
- {
- flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
- }
- dwMemPos += ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
- }
- return TRUE;
-}
-
-
-/////////////////////////////////////////////////////////////////////
-// AMS Sample unpacking
-
-void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter)
-{
- UINT tmplen = dmax;
- signed char *amstmp = new signed char[tmplen];
-
- if (!amstmp) return;
- // Unpack Loop
- {
- signed char *p = amstmp;
- UINT i=0, j=0;
- while ((i < inputlen) && (j < tmplen))
- {
- signed char ch = psrc[i++];
- if (ch == packcharacter)
- {
- BYTE ch2 = psrc[i++];
- if (ch2)
- {
- ch = psrc[i++];
- while (ch2--)
- {
- p[j++] = ch;
- if (j >= tmplen) break;
- }
- } else p[j++] = packcharacter;
- } else p[j++] = ch;
- }
- }
- // Bit Unpack Loop
- {
- signed char *p = amstmp;
- UINT bitcount = 0x80, dh;
- UINT k=0;
- for (UINT i=0; i<dmax; i++)
- {
- BYTE al = *p++;
- dh = 0;
- for (UINT count=0; count<8; count++)
- {
- UINT bl = al & bitcount;
- bl = ((bl|(bl<<8)) >> ((dh+8-count) & 7)) & 0xFF;
- bitcount = ((bitcount|(bitcount<<8)) >> 1) & 0xFF;
- pdest[k++] |= bl;
- if (k >= dmax)
- {
- k = 0;
- dh++;
- }
- }
- bitcount = ((bitcount|(bitcount<<8)) >> dh) & 0xFF;
- }
- }
- // Delta Unpack
- {
- signed char old = 0;
- for (UINT i=0; i<dmax; i++)
- {
- int pos = ((LPBYTE)pdest)[i];
- if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F);
- old -= (signed char)pos;
- pdest[i] = old;
- }
- }
- delete amstmp;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-///////////////////////////////////////////////////////////////
-//
-// DigiBooster Pro Module Loader (*.dbm)
-//
-// Note: this loader doesn't handle multiple songs
-//
-///////////////////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#define DBM_FILE_MAGIC 0x304d4244
-#define DBM_ID_NAME 0x454d414e
-#define DBM_NAMELEN 0x2c000000
-#define DBM_ID_INFO 0x4f464e49
-#define DBM_INFOLEN 0x0a000000
-#define DBM_ID_SONG 0x474e4f53
-#define DBM_ID_INST 0x54534e49
-#define DBM_ID_VENV 0x564e4556
-#define DBM_ID_PATT 0x54544150
-#define DBM_ID_SMPL 0x4c504d53
-
-#pragma pack(1)
-
-typedef struct DBMFILEHEADER
-{
- DWORD dbm_id; // "DBM0" = 0x304d4244
- WORD trkver; // Tracker version: 02.15
- WORD reserved;
- DWORD name_id; // "NAME" = 0x454d414e
- DWORD name_len; // name length: always 44
- CHAR songname[44];
- DWORD info_id; // "INFO" = 0x4f464e49
- DWORD info_len; // 0x0a000000
- WORD instruments;
- WORD samples;
- WORD songs;
- WORD patterns;
- WORD channels;
- DWORD song_id; // "SONG" = 0x474e4f53
- DWORD song_len;
- CHAR songname2[44];
- WORD orders;
-// WORD orderlist[0]; // orderlist[orders] in words
-} DBMFILEHEADER;
-
-typedef struct DBMINSTRUMENT
-{
- CHAR name[30];
- WORD sampleno;
- WORD volume;
- DWORD finetune;
- DWORD loopstart;
- DWORD looplen;
- WORD panning;
- WORD flags;
-} DBMINSTRUMENT;
-
-typedef struct DBMENVELOPE
-{
- WORD instrument;
- BYTE flags;
- BYTE numpoints;
- BYTE sustain1;
- BYTE loopbegin;
- BYTE loopend;
- BYTE sustain2;
- WORD volenv[2*32];
-} DBMENVELOPE;
-
-typedef struct DBMPATTERN
-{
- WORD rows;
- DWORD packedsize;
- BYTE patterndata[2]; // [packedsize]
-} DBMPATTERN;
-
-typedef struct DBMSAMPLE
-{
- DWORD flags;
- DWORD samplesize;
- BYTE sampledata[2]; // [samplesize]
-} DBMSAMPLE;
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream;
- DWORD dwMemPos;
- UINT nOrders, nSamples, nInstruments, nPatterns;
-
- if ((!lpStream) || (dwMemLength <= sizeof(DBMFILEHEADER)) || (!pfh->channels)
- || (pfh->dbm_id != DBM_FILE_MAGIC) || (!pfh->songs) || (pfh->song_id != DBM_ID_SONG)
- || (pfh->name_id != DBM_ID_NAME) || (pfh->name_len != DBM_NAMELEN)
- || (pfh->info_id != DBM_ID_INFO) || (pfh->info_len != DBM_INFOLEN)) return FALSE;
- dwMemPos = sizeof(DBMFILEHEADER);
- nOrders = bswapBE16(pfh->orders);
- if (dwMemPos + 2 * nOrders + 8*3 >= dwMemLength) return FALSE;
- nInstruments = bswapBE16(pfh->instruments);
- nSamples = bswapBE16(pfh->samples);
- nPatterns = bswapBE16(pfh->patterns);
- m_nType = MOD_TYPE_DBM;
- m_nChannels = bswapBE16(pfh->channels);
- if (m_nChannels < 4) m_nChannels = 4;
- if (m_nChannels > 64) m_nChannels = 64;
- memcpy(m_szNames[0], (pfh->songname[0]) ? pfh->songname : pfh->songname2, 32);
- m_szNames[0][31] = 0;
- for (UINT iOrd=0; iOrd < nOrders; iOrd++)
- {
- Order[iOrd] = lpStream[dwMemPos+iOrd*2+1];
- if (iOrd >= MAX_ORDERS-2) break;
- }
- dwMemPos += 2*nOrders;
- while (dwMemPos + 10 < dwMemLength)
- {
- DWORD chunk_id = ((LPDWORD)(lpStream+dwMemPos))[0];
- DWORD chunk_size = bswapBE32(((LPDWORD)(lpStream+dwMemPos))[1]);
- DWORD chunk_pos;
-
- dwMemPos += 8;
- chunk_pos = dwMemPos;
- if ((dwMemPos + chunk_size > dwMemLength) || (chunk_size > dwMemLength)) break;
- dwMemPos += chunk_size;
- // Instruments
- if (chunk_id == DBM_ID_INST)
- {
- if (nInstruments >= MAX_INSTRUMENTS) nInstruments = MAX_INSTRUMENTS-1;
- for (UINT iIns=0; iIns<nInstruments; iIns++)
- {
- MODINSTRUMENT *psmp;
- INSTRUMENTHEADER *penv;
- DBMINSTRUMENT *pih;
- UINT nsmp;
-
- if (chunk_pos + sizeof(DBMINSTRUMENT) > dwMemPos) break;
- if ((penv = new INSTRUMENTHEADER) == NULL) break;
- pih = (DBMINSTRUMENT *)(lpStream+chunk_pos);
- nsmp = bswapBE16(pih->sampleno);
- psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL;
- memset(penv, 0, sizeof(INSTRUMENTHEADER));
- memcpy(penv->name, pih->name, 30);
- if (psmp)
- {
- memcpy(m_szNames[nsmp], pih->name, 30);
- m_szNames[nsmp][30] = 0;
- }
- Headers[iIns+1] = penv;
- penv->nFadeOut = 1024; // ???
- penv->nGlobalVol = 64;
- penv->nPan = bswapBE16(pih->panning);
- if ((penv->nPan) && (penv->nPan < 256))
- penv->dwFlags = ENV_SETPANNING;
- else
- penv->nPan = 128;
- penv->nPPC = 5*12;
- for (UINT i=0; i<120; i++)
- {
- penv->Keyboard[i] = nsmp;
- penv->NoteMap[i] = i+1;
- }
- // Sample Info
- if (psmp)
- {
- DWORD sflags = bswapBE16(pih->flags);
- psmp->nVolume = bswapBE16(pih->volume) * 4;
- if ((!psmp->nVolume) || (psmp->nVolume > 256)) psmp->nVolume = 256;
- psmp->nGlobalVol = 64;
- psmp->nC4Speed = bswapBE32(pih->finetune);
- int f2t = FrequencyToTranspose(psmp->nC4Speed);
- psmp->RelativeTone = f2t >> 7;
- psmp->nFineTune = f2t & 0x7F;
- if ((pih->looplen) && (sflags & 3))
- {
- psmp->nLoopStart = bswapBE32(pih->loopstart);
- psmp->nLoopEnd = psmp->nLoopStart + bswapBE32(pih->looplen);
- psmp->uFlags |= CHN_LOOP;
- psmp->uFlags &= ~CHN_PINGPONGLOOP;
- if (sflags & 2) psmp->uFlags |= CHN_PINGPONGLOOP;
- }
- }
- chunk_pos += sizeof(DBMINSTRUMENT);
- m_nInstruments = iIns+1;
- }
- } else
- // Volume Envelopes
- if (chunk_id == DBM_ID_VENV)
- {
- UINT nEnvelopes = lpStream[chunk_pos+1];
-
- chunk_pos += 2;
- for (UINT iEnv=0; iEnv<nEnvelopes; iEnv++)
- {
- DBMENVELOPE *peh;
- UINT nins;
-
- if (chunk_pos + sizeof(DBMENVELOPE) > dwMemPos) break;
- peh = (DBMENVELOPE *)(lpStream+chunk_pos);
- nins = bswapBE16(peh->instrument);
- if ((nins) && (nins < MAX_INSTRUMENTS) && (Headers[nins]) && (peh->numpoints))
- {
- INSTRUMENTHEADER *penv = Headers[nins];
-
- if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME;
- if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP;
- penv->nVolEnv = peh->numpoints + 1;
- if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS;
- penv->nVolLoopStart = peh->loopbegin;
- penv->nVolLoopEnd = peh->loopend;
- penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1;
- for (UINT i=0; i<penv->nVolEnv; i++)
- {
- penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]);
- penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]);
- }
- }
- chunk_pos += sizeof(DBMENVELOPE);
- }
- } else
- // Packed Pattern Data
- if (chunk_id == DBM_ID_PATT)
- {
- if (nPatterns > MAX_PATTERNS) nPatterns = MAX_PATTERNS;
- for (UINT iPat=0; iPat<nPatterns; iPat++)
- {
- DBMPATTERN *pph;
- DWORD pksize;
- UINT nRows;
-
- if (chunk_pos + sizeof(DBMPATTERN) > dwMemPos) break;
- pph = (DBMPATTERN *)(lpStream+chunk_pos);
- pksize = bswapBE32(pph->packedsize);
- if ((chunk_pos + pksize + 6 > dwMemPos) || (pksize > dwMemPos)) break;
- nRows = bswapBE16(pph->rows);
- if ((nRows >= 4) && (nRows <= 256))
- {
- MODCOMMAND *m = AllocatePattern(nRows, m_nChannels);
- if (m)
- {
- LPBYTE pkdata = (LPBYTE)&pph->patterndata;
- UINT row = 0;
- UINT i = 0;
-
- PatternSize[iPat] = nRows;
- Patterns[iPat] = m;
- while ((i+3<pksize) && (row < nRows))
- {
- UINT ch = pkdata[i++];
-
- if (ch)
- {
- BYTE b = pkdata[i++];
- ch--;
- if (ch < m_nChannels)
- {
- if (b & 0x01)
- {
- UINT note = pkdata[i++];
-
- if (note == 0x1F) note = 0xFF; else
- if ((note) && (note < 0xFE))
- {
- note = ((note >> 4)*12) + (note & 0x0F) + 13;
- }
- m[ch].note = note;
- }
- if (b & 0x02) m[ch].instr = pkdata[i++];
- if (b & 0x3C)
- {
- UINT cmd1 = 0xFF, param1 = 0, cmd2 = 0xFF, param2 = 0;
- if (b & 0x04) cmd1 = (UINT)pkdata[i++];
- if (b & 0x08) param1 = pkdata[i++];
- if (b & 0x10) cmd2 = (UINT)pkdata[i++];
- if (b & 0x20) param2 = pkdata[i++];
- if (cmd1 == 0x0C)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = param1;
- cmd1 = 0xFF;
- } else
- if (cmd2 == 0x0C)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = param2;
- cmd2 = 0xFF;
- }
- if ((cmd1 > 0x13) || ((cmd1 >= 0x10) && (cmd2 < 0x10)))
- {
- cmd1 = cmd2;
- param1 = param2;
- cmd2 = 0xFF;
- }
- if (cmd1 <= 0x13)
- {
- m[ch].command = cmd1;
- m[ch].param = param1;
- ConvertModCommand(&m[ch]);
- }
- }
- } else
- {
- if (b & 0x01) i++;
- if (b & 0x02) i++;
- if (b & 0x04) i++;
- if (b & 0x08) i++;
- if (b & 0x10) i++;
- if (b & 0x20) i++;
- }
- } else
- {
- row++;
- m += m_nChannels;
- }
- }
- }
- }
- chunk_pos += 6 + pksize;
- }
- } else
- // Reading Sample Data
- if (chunk_id == DBM_ID_SMPL)
- {
- if (nSamples >= MAX_SAMPLES) nSamples = MAX_SAMPLES-1;
- m_nSamples = nSamples;
- for (UINT iSmp=1; iSmp<=nSamples; iSmp++)
- {
- MODINSTRUMENT *pins;
- DBMSAMPLE *psh;
- DWORD samplesize;
- DWORD sampleflags;
-
- if (chunk_pos + sizeof(DBMSAMPLE) >= dwMemPos) break;
- psh = (DBMSAMPLE *)(lpStream+chunk_pos);
- chunk_pos += 8;
- samplesize = bswapBE32(psh->samplesize);
- sampleflags = bswapBE32(psh->flags);
- pins = &Ins[iSmp];
- pins->nLength = samplesize;
- if (sampleflags & 2)
- {
- pins->uFlags |= CHN_16BIT;
- samplesize <<= 1;
- }
- if ((chunk_pos+samplesize > dwMemPos) || (samplesize > dwMemLength)) break;
- if (sampleflags & 3)
- {
- ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16M : RS_PCM8S,
- (LPSTR)(psh->sampledata), samplesize);
- }
- chunk_pos += samplesize;
- }
- }
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-///////////////////////////////////////////////////////
-// DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) //
-///////////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#define DMFLOG
-
-//#pragma warning(disable:4244)
-
-#pragma pack(1)
-
-typedef struct DMFHEADER
-{
- DWORD id; // "DDMF" = 0x464d4444
- BYTE version; // 4
- CHAR trackername[8]; // "XTRACKER"
- CHAR songname[30];
- CHAR composer[20];
- BYTE date[3];
-} DMFHEADER;
-
-typedef struct DMFINFO
-{
- DWORD id; // "INFO"
- DWORD infosize;
-} DMFINFO;
-
-typedef struct DMFSEQU
-{
- DWORD id; // "SEQU"
- DWORD seqsize;
- WORD loopstart;
- WORD loopend;
- WORD sequ[2];
-} DMFSEQU;
-
-typedef struct DMFPATT
-{
- DWORD id; // "PATT"
- DWORD patsize;
- WORD numpat; // 1-1024
- BYTE tracks;
- BYTE firstpatinfo;
-} DMFPATT;
-
-typedef struct DMFTRACK
-{
- BYTE tracks;
- BYTE beat; // [hi|lo] -> hi=ticks per beat, lo=beats per measure
- WORD ticks; // max 512
- DWORD jmpsize;
-} DMFTRACK;
-
-typedef struct DMFSMPI
-{
- DWORD id;
- DWORD size;
- BYTE samples;
-} DMFSMPI;
-
-typedef struct DMFSAMPLE
-{
- DWORD len;
- DWORD loopstart;
- DWORD loopend;
- WORD c3speed;
- BYTE volume;
- BYTE flags;
-} DMFSAMPLE;
-
-#pragma pack()
-
-
-#ifdef DMFLOG
-extern void Log(LPCSTR s, ...);
-#endif
-
-
-BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- DMFHEADER *pfh = (DMFHEADER *)lpStream;
- DMFINFO *psi;
- DMFSEQU *sequ;
- DWORD dwMemPos;
- BYTE infobyte[32];
- BYTE smplflags[MAX_SAMPLES];
-
- if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
- if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return FALSE;
- dwMemPos = 66;
- memcpy(m_szNames[0], pfh->songname, 30);
- m_szNames[0][30] = 0;
- m_nType = MOD_TYPE_DMF;
- m_nChannels = 0;
-#ifdef DMFLOG
- Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength);
-#endif
- while (dwMemPos + 7 < dwMemLength)
- {
- DWORD id = *((LPDWORD)(lpStream+dwMemPos));
-
- switch(id)
- {
- // "INFO"
- case 0x4f464e49:
- // "CMSG"
- case 0x47534d43:
- psi = (DMFINFO *)(lpStream+dwMemPos);
- if (id == 0x47534d43) dwMemPos++;
- if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit;
- if ((psi->infosize >= 8) && (!m_lpszSongComments))
- {
- m_lpszSongComments = new char[psi->infosize]; // changed from CHAR
- if (m_lpszSongComments)
- {
- for (UINT i=0; i<psi->infosize-1; i++)
- {
- CHAR c = lpStream[dwMemPos+8+i];
- if ((i % 40) == 39)
- m_lpszSongComments[i] = 0x0d;
- else
- m_lpszSongComments[i] = (c < ' ') ? ' ' : c;
- }
- m_lpszSongComments[psi->infosize-1] = 0;
- }
- }
- dwMemPos += psi->infosize + 8 - 1;
- break;
-
- // "SEQU"
- case 0x55514553:
- sequ = (DMFSEQU *)(lpStream+dwMemPos);
- if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit;
- {
- UINT nseq = sequ->seqsize >> 1;
- if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1;
- if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart;
- for (UINT i=0; i<nseq; i++) Order[i] = (BYTE)sequ->sequ[i];
- }
- dwMemPos += sequ->seqsize + 8;
- break;
-
- // "PATT"
- case 0x54544150:
- if (!m_nChannels)
- {
- DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos);
- UINT numpat;
- DWORD dwPos = dwMemPos + 11;
- if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit;
- numpat = patt->numpat;
- if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS;
- m_nChannels = patt->tracks;
- if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo;
- if (m_nChannels > 32) m_nChannels = 32;
- if (m_nChannels < 4) m_nChannels = 4;
- for (UINT npat=0; npat<numpat; npat++)
- {
- DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos);
- #ifdef DMFLOG
- Log("Pattern #%d: %d tracks, %d rows\n", npat, pt->tracks, pt->ticks);
- #endif
- UINT tracks = pt->tracks;
- if (tracks > 32) tracks = 32;
- UINT ticks = pt->ticks;
- if (ticks > 256) ticks = 256;
- if (ticks < 16) ticks = 16;
- dwPos += 8;
- if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break;
- PatternSize[npat] = (WORD)ticks;
- MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels);
- if (!m) goto dmfexit;
- Patterns[npat] = m;
- DWORD d = dwPos;
- dwPos += pt->jmpsize;
- UINT ttype = 1;
- UINT tempo = 125;
- UINT glbinfobyte = 0;
- UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8;
- BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE;
- memset(infobyte, 0, sizeof(infobyte));
- for (UINT row=0; row<ticks; row++)
- {
- MODCOMMAND *p = &m[row*m_nChannels];
- // Parse track global effects
- if (!glbinfobyte)
- {
- BYTE info = lpStream[d++];
- BYTE infoval = 0;
- if ((info & 0x80) && (d < dwPos)) glbinfobyte = lpStream[d++];
- info &= 0x7f;
- if ((info) && (d < dwPos)) infoval = lpStream[d++];
- switch(info)
- {
- case 1: ttype = 0; tempo = infoval; tempochange = TRUE; break;
- case 2: ttype = 1; tempo = infoval; tempochange = TRUE; break;
- case 3: pbeat = infoval>>4; tempochange = ttype; break;
- #ifdef DMFLOG
- default: if (info) Log("GLB: %02X.%02X\n", info, infoval);
- #endif
- }
- } else
- {
- glbinfobyte--;
- }
- // Parse channels
- for (UINT i=0; i<tracks; i++) if (!infobyte[i])
- {
- MODCOMMAND cmd = {0,0,0,0,0,0};
- BYTE info = lpStream[d++];
- if (info & 0x80) infobyte[i] = lpStream[d++];
- // Instrument
- if (info & 0x40)
- {
- cmd.instr = lpStream[d++];
- }
- // Note
- if (info & 0x20)
- {
- cmd.note = lpStream[d++];
- if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f;
- if ((cmd.note) && (cmd.note < 128)) cmd.note += 24;
- }
- // Volume
- if (info & 0x10)
- {
- cmd.volcmd = VOLCMD_VOLUME;
- cmd.vol = (lpStream[d++]+3)>>2;
- }
- // Effect 1
- if (info & 0x08)
- {
- BYTE efx = lpStream[d++];
- BYTE eval = lpStream[d++];
- switch(efx)
- {
- // 1: Key Off
- case 1: if (!cmd.note) cmd.note = 0xFE; break;
- // 2: Set Loop
- // 4: Sample Delay
- case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break;
- // 5: Retrig
- case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break;
- // 6: Offset
- case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break;
- #ifdef DMFLOG
- default: Log("FX1: %02X.%02X\n", efx, eval);
- #endif
- }
- }
- // Effect 2
- if (info & 0x04)
- {
- BYTE efx = lpStream[d++];
- BYTE eval = lpStream[d++];
- switch(efx)
- {
- // 1: Finetune
- case 1: if (eval&0xf0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>4)|0x20; } break;
- // 2: Note Delay
- case 2: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break;
- // 3: Arpeggio
- case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break;
- // 4: Portamento Up
- case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break;
- // 5: Portamento Down
- case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break;
- // 6: Tone Portamento
- case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break;
- // 8: Vibrato
- case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break;
- // 12: Note cut
- case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; }
- else if (!cmd.note) { cmd.note = 0xfe; } break;
- #ifdef DMFLOG
- default: Log("FX2: %02X.%02X\n", efx, eval);
- #endif
- }
- }
- // Effect 3
- if (info & 0x02)
- {
- BYTE efx = lpStream[d++];
- BYTE eval = lpStream[d++];
- switch(efx)
- {
- // 1: Vol Slide Up
- case 1: if (eval == 0xff) break;
- eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
- cmd.command = CMD_VOLUMESLIDE; cmd.param = eval<<4; break;
- // 2: Vol Slide Down
- case 2: if (eval == 0xff) break;
- eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
- cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break;
- // 7: Set Pan
- case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; }
- else { cmd.command = CMD_PANNING8; cmd.param = eval; } break;
- // 8: Pan Slide Left
- case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
- cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break;
- // 9: Pan Slide Right
- case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f;
- cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break;
- #ifdef DMFLOG
- default: Log("FX3: %02X.%02X\n", efx, eval);
- #endif
-
- }
- }
- // Store effect
- if (i < m_nChannels) p[i] = cmd;
- if (d > dwPos)
- {
- #ifdef DMFLOG
- Log("Unexpected EOP: row=%d\n", row);
- #endif
- break;
- }
- } else
- {
- infobyte[i]--;
- }
-
- // Find free channel for tempo change
- if (tempochange)
- {
- tempochange = FALSE;
- UINT speed=6, modtempo=tempo;
- UINT rpm = ((ttype) && (pbeat)) ? tempo*pbeat : (tempo+1)*15;
- for (speed=30; speed>1; speed--)
- {
- modtempo = rpm*speed/24;
- if (modtempo <= 200) break;
- if ((speed < 6) && (modtempo < 256)) break;
- }
- #ifdef DMFLOG
- Log("Tempo change: ttype=%d pbeat=%d tempo=%3d -> speed=%d tempo=%d\n",
- ttype, pbeat, tempo, speed, modtempo);
- #endif
- for (UINT ich=0; ich<m_nChannels; ich++) if (!p[ich].command)
- {
- if (speed)
- {
- p[ich].command = CMD_SPEED;
- p[ich].param = (BYTE)speed;
- speed = 0;
- } else
- if ((modtempo >= 32) && (modtempo < 256))
- {
- p[ich].command = CMD_TEMPO;
- p[ich].param = (BYTE)modtempo;
- modtempo = 0;
- } else
- {
- break;
- }
- }
- }
- if (d >= dwPos) break;
- }
- #ifdef DMFLOG
- Log(" %d/%d bytes remaining\n", dwPos-d, pt->jmpsize);
- #endif
- if (dwPos + 8 >= dwMemLength) break;
- }
- dwMemPos += patt->patsize + 8;
- }
- break;
-
- // "SMPI": Sample Info
- case 0x49504d53:
- {
- DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos);
- if (pds->size <= dwMemLength - dwMemPos)
- {
- DWORD dwPos = dwMemPos + 9;
- m_nSamples = pds->samples;
- if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
- for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++)
- {
- UINT namelen = lpStream[dwPos];
- smplflags[iSmp] = 0;
- if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break;
- if (namelen)
- {
- UINT rlen = (namelen < 32) ? namelen : 31;
- memcpy(m_szNames[iSmp], lpStream+dwPos+1, rlen);
- m_szNames[iSmp][rlen] = 0;
- }
- dwPos += namelen + 1;
- DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos);
- MODINSTRUMENT *psmp = &Ins[iSmp];
- psmp->nLength = psh->len;
- psmp->nLoopStart = psh->loopstart;
- psmp->nLoopEnd = psh->loopend;
- psmp->nC4Speed = psh->c3speed;
- psmp->nGlobalVol = 64;
- psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256;
- psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0;
- if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1;
- if (psh->flags & 1) psmp->uFlags |= CHN_LOOP;
- smplflags[iSmp] = psh->flags;
- dwPos += (pfh->version < 8) ? 22 : 30;
- #ifdef DMFLOG
- Log("SMPI %d/%d: len=%d flags=0x%02X\n", iSmp, m_nSamples, psmp->nLength, psh->flags);
- #endif
- }
- }
- dwMemPos += pds->size + 8;
- }
- break;
-
- // "SMPD": Sample Data
- case 0x44504d53:
- {
- DWORD dwPos = dwMemPos + 8;
- UINT ismpd = 0;
- for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++)
- {
- ismpd++;
- DWORD pksize;
- if (dwPos + 4 >= dwMemLength)
- {
- #ifdef DMFLOG
- Log("Unexpected EOF at sample %d/%d! (pos=%d)\n", iSmp, m_nSamples, dwPos);
- #endif
- break;
- }
- pksize = *((LPDWORD)(lpStream+dwPos));
- #ifdef DMFLOG
- Log("sample %d: pos=0x%X pksize=%d ", iSmp, dwPos, pksize);
- Log("len=%d flags=0x%X [%08X]\n", Ins[iSmp].nLength, smplflags[ismpd], *((LPDWORD)(lpStream+dwPos+4)));
- #endif
- dwPos += 4;
- if (pksize > dwMemLength - dwPos)
- {
- #ifdef DMFLOG
- Log("WARNING: pksize=%d, but only %d bytes left\n", pksize, dwMemLength-dwPos);
- #endif
- pksize = dwMemLength - dwPos;
- }
- if ((pksize) && (iSmp <= m_nSamples))
- {
- UINT flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
- if (smplflags[ismpd] & 4) flags = (Ins[iSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8;
- ReadSample(&Ins[iSmp], flags, (LPSTR)(lpStream+dwPos), pksize);
- }
- dwPos += pksize;
- }
- dwMemPos = dwPos;
- }
- break;
-
- // "ENDE": end of file
- case 0x45444e45:
- goto dmfexit;
-
- // Unrecognized id, or "ENDE" field
- default:
- dwMemPos += 4;
- break;
- }
- }
-dmfexit:
- if (!m_nChannels)
- {
- if (!m_nSamples)
- {
- m_nType = MOD_TYPE_NONE;
- return FALSE;
- }
- m_nChannels = 4;
- }
- return TRUE;
-}
-
-
-///////////////////////////////////////////////////////////////////////
-// DMF Compression
-
-#pragma pack(1)
-
-typedef struct DMF_HNODE
-{
- short int left, right;
- BYTE value;
-} DMF_HNODE;
-
-typedef struct DMF_HTREE
-{
- LPBYTE ibuf, ibufmax;
- DWORD bitbuf;
- UINT bitnum;
- UINT lastnode, nodecount;
- DMF_HNODE nodes[256];
-} DMF_HTREE;
-
-#pragma pack()
-
-
-// DMF Huffman ReadBits
-BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits)
-//-------------------------------------------
-{
- BYTE x = 0, bitv = 1;
- while (nbits--)
- {
- if (tree->bitnum)
- {
- tree->bitnum--;
- } else
- {
- tree->bitbuf = (tree->ibuf < tree->ibufmax) ? *(tree->ibuf++) : 0;
- tree->bitnum = 7;
- }
- if (tree->bitbuf & 1) x |= bitv;
- bitv <<= 1;
- tree->bitbuf >>= 1;
- }
- return x;
-}
-
-//
-// tree: [8-bit value][12-bit index][12-bit index] = 32-bit
-//
-
-void DMFNewNode(DMF_HTREE *tree)
-//------------------------------
-{
- BYTE isleft, isright;
- UINT actnode;
-
- actnode = tree->nodecount;
- if (actnode > 255) return;
- tree->nodes[actnode].value = DMFReadBits(tree, 7);
- isleft = DMFReadBits(tree, 1);
- isright = DMFReadBits(tree, 1);
- actnode = tree->lastnode;
- if (actnode > 255) return;
- tree->nodecount++;
- tree->lastnode = tree->nodecount;
- if (isleft)
- {
- tree->nodes[actnode].left = tree->lastnode;
- DMFNewNode(tree);
- } else
- {
- tree->nodes[actnode].left = -1;
- }
- tree->lastnode = tree->nodecount;
- if (isright)
- {
- tree->nodes[actnode].right = tree->lastnode;
- DMFNewNode(tree);
- } else
- {
- tree->nodes[actnode].right = -1;
- }
-}
-
-
-int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen)
-//----------------------------------------------------------------------
-{
- DMF_HTREE tree;
- UINT actnode;
- BYTE value, sign, delta = 0;
-
- memset(&tree, 0, sizeof(tree));
- tree.ibuf = ibuf;
- tree.ibufmax = ibufmax;
- DMFNewNode(&tree);
- value = 0;
- for (UINT i=0; i<maxlen; i++)
- {
- actnode = 0;
- sign = DMFReadBits(&tree, 1);
- do
- {
- if (DMFReadBits(&tree, 1))
- actnode = tree.nodes[actnode].right;
- else
- actnode = tree.nodes[actnode].left;
- if (actnode > 255) break;
- delta = tree.nodes[actnode].value;
- if ((tree.ibuf >= tree.ibufmax) && (!tree.bitnum)) break;
- } while ((tree.nodes[actnode].left >= 0) && (tree.nodes[actnode].right >= 0));
- if (sign) delta ^= 0xFF;
- value += delta;
- psample[i] = (i) ? value : 0;
- }
-#ifdef DMFLOG
-// Log("DMFUnpack: %d remaining bytes\n", tree.ibufmax-tree.ibuf);
-#endif
- return tree.ibuf - ibuf;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-//////////////////////////////////////////////
-// DSIK Internal Format (DSM) module loader //
-//////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#pragma pack(1)
-
-#define DSMID_RIFF 0x46464952 // "RIFF"
-#define DSMID_DSMF 0x464d5344 // "DSMF"
-#define DSMID_SONG 0x474e4f53 // "SONG"
-#define DSMID_INST 0x54534e49 // "INST"
-#define DSMID_PATT 0x54544150 // "PATT"
-
-
-typedef struct DSMNOTE
-{
- BYTE note,ins,vol,cmd,inf;
-} DSMNOTE;
-
-
-typedef struct DSMINST
-{
- DWORD id_INST;
- DWORD inst_len;
- CHAR filename[13];
- BYTE flags;
- BYTE flags2;
- BYTE volume;
- DWORD length;
- DWORD loopstart;
- DWORD loopend;
- DWORD reserved1;
- WORD c2spd;
- WORD reserved2;
- CHAR samplename[28];
-} DSMINST;
-
-
-typedef struct DSMFILEHEADER
-{
- DWORD id_RIFF; // "RIFF"
- DWORD riff_len;
- DWORD id_DSMF; // "DSMF"
- DWORD id_SONG; // "SONG"
- DWORD song_len;
-} DSMFILEHEADER;
-
-
-typedef struct DSMSONG
-{
- CHAR songname[28];
- WORD reserved1;
- WORD flags;
- DWORD reserved2;
- WORD numord;
- WORD numsmp;
- WORD numpat;
- WORD numtrk;
- BYTE globalvol;
- BYTE mastervol;
- BYTE speed;
- BYTE bpm;
- BYTE panpos[16];
- BYTE orders[128];
-} DSMSONG;
-
-typedef struct DSMPATT
-{
- DWORD id_PATT;
- DWORD patt_len;
- BYTE dummy1;
- BYTE dummy2;
-} DSMPATT;
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream;
- DSMSONG *psong;
- DWORD dwMemPos;
- UINT nPat, nSmp;
-
- if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF)
- || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024)
- || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG)
- || (pfh->song_len > dwMemLength)) return FALSE;
- psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER));
- dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len;
- m_nType = MOD_TYPE_DSM;
- m_nChannels = psong->numtrk;
- if (m_nChannels < 4) m_nChannels = 4;
- if (m_nChannels > 16) m_nChannels = 16;
- m_nSamples = psong->numsmp;
- if (m_nSamples > MAX_SAMPLES) m_nSamples = MAX_SAMPLES;
- m_nDefaultSpeed = psong->speed;
- m_nDefaultTempo = psong->bpm;
- m_nDefaultGlobalVolume = psong->globalvol << 2;
- if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256;
- m_nSongPreAmp = psong->mastervol & 0x7F;
- for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
- {
- Order[iOrd] = (BYTE)((iOrd < psong->numord) ? psong->orders[iOrd] : 0xFF);
- }
- for (UINT iPan=0; iPan<16; iPan++)
- {
- ChnSettings[iPan].nPan = 0x80;
- if (psong->panpos[iPan] <= 0x80)
- {
- ChnSettings[iPan].nPan = psong->panpos[iPan] << 1;
- }
- }
- memcpy(m_szNames[0], psong->songname, 28);
- nPat = 0;
- nSmp = 1;
- while (dwMemPos < dwMemLength - 8)
- {
- DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos);
- DSMINST *pins = (DSMINST *)(lpStream+dwMemPos);
- // Reading Patterns
- if (ppatt->id_PATT == DSMID_PATT)
- {
- dwMemPos += 8;
- if (dwMemPos + ppatt->patt_len >= dwMemLength) break;
- DWORD dwPos = dwMemPos;
- dwMemPos += ppatt->patt_len;
- MODCOMMAND *m = AllocatePattern(64, m_nChannels);
- if (!m) break;
- PatternSize[nPat] = 64;
- Patterns[nPat] = m;
- UINT row = 0;
- while ((row < 64) && (dwPos + 2 <= dwMemPos))
- {
- UINT flag = lpStream[dwPos++];
- if (flag)
- {
- UINT ch = (flag & 0x0F) % m_nChannels;
- if (flag & 0x80)
- {
- UINT note = lpStream[dwPos++];
- if (note)
- {
- if (note <= 12*9) note += 12;
- m[ch].note = (BYTE)note;
- }
- }
- if (flag & 0x40)
- {
- m[ch].instr = lpStream[dwPos++];
- }
- if (flag & 0x20)
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = lpStream[dwPos++];
- }
- if (flag & 0x10)
- {
- UINT command = lpStream[dwPos++];
- UINT param = lpStream[dwPos++];
- switch(command)
- {
- // 4-bit Panning
- case 0x08:
- switch(param & 0xF0)
- {
- case 0x00: param <<= 4; break;
- case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break;
- case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break;
- case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break;
- case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break;
- default: command = 0;
- }
- break;
- // Portamentos
- case 0x11:
- case 0x12:
- command &= 0x0F;
- break;
- // 3D Sound (?)
- case 0x13:
- command = 'X' - 55;
- param = 0x91;
- break;
- default:
- // Volume + Offset (?)
- command = ((command & 0xF0) == 0x20) ? 0x09 : 0;
- }
- m[ch].command = (BYTE)command;
- m[ch].param = (BYTE)param;
- if (command) ConvertModCommand(&m[ch]);
- }
- } else
- {
- m += m_nChannels;
- row++;
- }
- }
- nPat++;
- } else
- // Reading Samples
- if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST))
- {
- if (dwMemPos + pins->inst_len >= dwMemLength - 8) break;
- DWORD dwPos = dwMemPos + sizeof(DSMINST);
- dwMemPos += 8 + pins->inst_len;
- memcpy(m_szNames[nSmp], pins->samplename, 28);
- MODINSTRUMENT *psmp = &Ins[nSmp];
- memcpy(psmp->name, pins->filename, 13);
- psmp->nGlobalVol = 64;
- psmp->nC4Speed = pins->c2spd;
- psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0);
- psmp->nLength = pins->length;
- psmp->nLoopStart = pins->loopstart;
- psmp->nLoopEnd = pins->loopend;
- psmp->nVolume = (WORD)(pins->volume << 2);
- if (psmp->nVolume > 256) psmp->nVolume = 256;
- UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U;
- ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos);
- nSmp++;
- } else
- {
- break;
- }
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-////////////////////////////////////////
-// Farandole (FAR) module loader //
-////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#define FARFILEMAGIC 0xFE524146 // "FAR"
-
-#pragma pack(1)
-
-typedef struct FARHEADER1
-{
- DWORD id; // file magic FAR=
- CHAR songname[40]; // songname
- CHAR magic2[3]; // 13,10,26
- WORD headerlen; // remaining length of header in bytes
- BYTE version; // 0xD1
- BYTE onoff[16];
- BYTE edit1[9];
- BYTE speed;
- BYTE panning[16];
- BYTE edit2[4];
- WORD stlen;
-} FARHEADER1;
-
-typedef struct FARHEADER2
-{
- BYTE orders[256];
- BYTE numpat;
- BYTE snglen;
- BYTE loopto;
- WORD patsiz[256];
-} FARHEADER2;
-
-typedef struct FARSAMPLE
-{
- CHAR samplename[32];
- DWORD length;
- BYTE finetune;
- BYTE volume;
- DWORD reppos;
- DWORD repend;
- BYTE type;
- BYTE loop;
-} FARSAMPLE;
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- FARHEADER1 *pmh1 = (FARHEADER1 *)lpStream;
- FARHEADER2 *pmh2;
- DWORD dwMemPos = sizeof(FARHEADER1);
- UINT headerlen;
- BYTE samplemap[8];
-
- if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC)
- || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
- headerlen = pmh1->headerlen;
- if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE;
- // Globals
- m_nType = MOD_TYPE_FAR;
- m_nChannels = 16;
- m_nInstruments = 0;
- m_nSamples = 0;
- m_nSongPreAmp = 0x20;
- m_nDefaultSpeed = pmh1->speed;
- m_nDefaultTempo = 80;
- m_nDefaultGlobalVolume = 256;
-
- memcpy(m_szNames[0], pmh1->songname, 32);
- // Channel Setting
- for (UINT nchpan=0; nchpan<16; nchpan++)
- {
- ChnSettings[nchpan].dwFlags = 0;
- ChnSettings[nchpan].nPan = ((pmh1->panning[nchpan] & 0x0F) << 4) + 8;
- ChnSettings[nchpan].nVolume = 64;
- }
- // Reading comment
- if (pmh1->stlen)
- {
- UINT szLen = pmh1->stlen;
- if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos;
- if ((m_lpszSongComments = new char[szLen + 1]) != NULL)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen);
- m_lpszSongComments[szLen] = 0;
- }
- dwMemPos += pmh1->stlen;
- }
- // Reading orders
- pmh2 = (FARHEADER2 *)(lpStream + dwMemPos);
- dwMemPos += sizeof(FARHEADER2);
- if (dwMemPos >= dwMemLength) return TRUE;
- for (UINT iorder=0; iorder<MAX_ORDERS; iorder++)
- {
- Order[iorder] = (iorder <= pmh2->snglen) ? pmh2->orders[iorder] : 0xFF;
- }
- m_nRestartPos = pmh2->loopto;
- // Reading Patterns
- dwMemPos += headerlen - (869 + pmh1->stlen);
- if (dwMemPos >= dwMemLength) return TRUE;
-
- WORD *patsiz = (WORD *)pmh2->patsiz;
- for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat])
- {
- UINT patlen = patsiz[ipat];
- if ((ipat >= MAX_PATTERNS) || (patsiz[ipat] < 2))
- {
- dwMemPos += patlen;
- continue;
- }
- if (dwMemPos + patlen >= dwMemLength) return TRUE;
- UINT rows = (patlen - 2) >> 6;
- if (!rows)
- {
- dwMemPos += patlen;
- continue;
- }
- if (rows > 256) rows = 256;
- if (rows < 16) rows = 16;
- PatternSize[ipat] = rows;
- if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
- MODCOMMAND *m = Patterns[ipat];
- UINT patbrk = lpStream[dwMemPos];
- const BYTE *p = lpStream + dwMemPos + 2;
- UINT max = rows*16*4;
- if (max > patlen-2) max = patlen-2;
- for (UINT len=0; len<max; len += 4, m++)
- {
- BYTE note = p[len];
- BYTE ins = p[len+1];
- BYTE vol = p[len+2];
- BYTE eff = p[len+3];
- if (note)
- {
- m->instr = ins + 1;
- m->note = note + 36;
- }
- if (vol & 0x0F)
- {
- m->volcmd = VOLCMD_VOLUME;
- m->vol = (vol & 0x0F) << 2;
- if (m->vol <= 4) m->vol = 0;
- }
- switch(eff & 0xF0)
- {
- // 1.x: Portamento Up
- case 0x10:
- m->command = CMD_PORTAMENTOUP;
- m->param = eff & 0x0F;
- break;
- // 2.x: Portamento Down
- case 0x20:
- m->command = CMD_PORTAMENTODOWN;
- m->param = eff & 0x0F;
- break;
- // 3.x: Tone-Portamento
- case 0x30:
- m->command = CMD_TONEPORTAMENTO;
- m->param = (eff & 0x0F) << 2;
- break;
- // 4.x: Retrigger
- case 0x40:
- m->command = CMD_RETRIG;
- m->param = 6 / (1+(eff&0x0F)) + 1;
- break;
- // 5.x: Set Vibrato Depth
- case 0x50:
- m->command = CMD_VIBRATO;
- m->param = (eff & 0x0F);
- break;
- // 6.x: Set Vibrato Speed
- case 0x60:
- m->command = CMD_VIBRATO;
- m->param = (eff & 0x0F) << 4;
- break;
- // 7.x: Vol Slide Up
- case 0x70:
- m->command = CMD_VOLUMESLIDE;
- m->param = (eff & 0x0F) << 4;
- break;
- // 8.x: Vol Slide Down
- case 0x80:
- m->command = CMD_VOLUMESLIDE;
- m->param = (eff & 0x0F);
- break;
- // A.x: Port to vol
- case 0xA0:
- m->volcmd = VOLCMD_VOLUME;
- m->vol = ((eff & 0x0F) << 2) + 4;
- break;
- // B.x: Set Balance
- case 0xB0:
- m->command = CMD_PANNING8;
- m->param = (eff & 0x0F) << 4;
- break;
- // F.x: Set Speed
- case 0xF0:
- m->command = CMD_SPEED;
- m->param = eff & 0x0F;
- break;
- default:
- if ((patbrk) && (patbrk+1 == (len >> 6)) && (patbrk+1 != rows-1))
- {
- m->command = CMD_PATTERNBREAK;
- patbrk = 0;
- }
- }
- }
- dwMemPos += patlen;
- }
- // Reading samples
- if (dwMemPos + 8 >= dwMemLength) return TRUE;
- memcpy(samplemap, lpStream+dwMemPos, 8);
- dwMemPos += 8;
- MODINSTRUMENT *pins = &Ins[1];
- for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7)))
- {
- if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE;
- FARSAMPLE *pfs = (FARSAMPLE *)(lpStream + dwMemPos);
- dwMemPos += sizeof(FARSAMPLE);
- m_nSamples = ismp + 1;
- memcpy(m_szNames[ismp+1], pfs->samplename, 32);
- pins->nLength = pfs->length;
- pins->nLoopStart = pfs->reppos;
- pins->nLoopEnd = pfs->repend;
- pins->nFineTune = 0;
- pins->nC4Speed = 8363*2;
- pins->nGlobalVol = 64;
- pins->nVolume = pfs->volume << 4;
- pins->uFlags = 0;
- if ((pins->nLength > 3) && (dwMemPos + 4 < dwMemLength))
- {
- if (pfs->type & 1)
- {
- pins->uFlags |= CHN_16BIT;
- pins->nLength >>= 1;
- pins->nLoopStart >>= 1;
- pins->nLoopEnd >>= 1;
- }
- if ((pfs->loop & 8) && (pins->nLoopEnd > 4)) pins->uFlags |= CHN_LOOP;
- ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S,
- (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
- }
- dwMemPos += pfs->length;
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-#include "it_defs.h"
-
-#ifdef MSC_VER
-#pragma warning(disable:4244)
-#endif
-
-BYTE autovibit2xm[8] =
-{ 0, 3, 1, 4, 2, 0, 0, 0 };
-
-BYTE autovibxm2it[8] =
-{ 0, 2, 4, 1, 3, 0, 0, 0 };
-
-//////////////////////////////////////////////////////////
-// Impulse Tracker IT file support (import only)
-
-
-static inline UINT ConvertVolParam(UINT value)
-//--------------------------------------------
-{
- return (value > 9) ? 9 : value;
-}
-
-
-BOOL CSoundFile::ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers)
-//--------------------------------------------------------------------------------
-{
- if (trkvers < 0x0200)
- {
- const ITOLDINSTRUMENT *pis = (const ITOLDINSTRUMENT *)p;
- memcpy(penv->name, pis->name, 26);
- memcpy(penv->filename, pis->filename, 12);
- penv->nFadeOut = bswapLE16(pis->fadeout) << 6;
- penv->nGlobalVol = 64;
- for (UINT j=0; j<120; j++)
- {
- UINT note = pis->keyboard[j*2];
- UINT ins = pis->keyboard[j*2+1];
- if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
- if (note < 128) penv->NoteMap[j] = note+1;
- else if (note >= 0xFE) penv->NoteMap[j] = note;
- }
- if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME;
- if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP;
- if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN;
- penv->nVolLoopStart = pis->vls;
- penv->nVolLoopEnd = pis->vle;
- penv->nVolSustainBegin = pis->sls;
- penv->nVolSustainEnd = pis->sle;
- penv->nVolEnv = 25;
- for (UINT ev=0; ev<25; ev++)
- {
- if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF)
- {
- penv->nVolEnv = ev;
- break;
- }
- penv->VolEnv[ev] = pis->nodes[ev*2+1];
- }
- penv->nNNA = pis->nna;
- penv->nDCT = pis->dnc;
- penv->nPan = 0x80;
- } else
- {
- const ITINSTRUMENT *pis = (const ITINSTRUMENT *)p;
- memcpy(penv->name, pis->name, 26);
- memcpy(penv->filename, pis->filename, 12);
- penv->nMidiProgram = pis->mpr;
- penv->nMidiChannel = pis->mch;
- penv->wMidiBank = bswapLE16(pis->mbank);
- penv->nFadeOut = bswapLE16(pis->fadeout) << 5;
- penv->nGlobalVol = pis->gbv >> 1;
- if (penv->nGlobalVol > 64) penv->nGlobalVol = 64;
- for (UINT j=0; j<120; j++)
- {
- UINT note = pis->keyboard[j*2];
- UINT ins = pis->keyboard[j*2+1];
- if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
- if (note < 128) penv->NoteMap[j] = note+1;
- else if (note >= 0xFE) penv->NoteMap[j] = note;
- }
- // Volume Envelope
- if (pis->volenv.flags & 1) penv->dwFlags |= ENV_VOLUME;
- if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP;
- if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY;
- penv->nVolEnv = pis->volenv.num;
- if (penv->nVolEnv > 25) penv->nVolEnv = 25;
-
- penv->nVolLoopStart = pis->volenv.lpb;
- penv->nVolLoopEnd = pis->volenv.lpe;
- penv->nVolSustainBegin = pis->volenv.slb;
- penv->nVolSustainEnd = pis->volenv.sle;
- // Panning Envelope
- if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING;
- if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP;
- if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN;
- if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY;
- penv->nPanEnv = pis->panenv.num;
- if (penv->nPanEnv > 25) penv->nPanEnv = 25;
- penv->nPanLoopStart = pis->panenv.lpb;
- penv->nPanLoopEnd = pis->panenv.lpe;
- penv->nPanSustainBegin = pis->panenv.slb;
- penv->nPanSustainEnd = pis->panenv.sle;
- // Pitch Envelope
- if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH;
- if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP;
- if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN;
- if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY;
- if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER;
- penv->nPitchEnv = pis->pitchenv.num;
- if (penv->nPitchEnv > 25) penv->nPitchEnv = 25;
- penv->nPitchLoopStart = pis->pitchenv.lpb;
- penv->nPitchLoopEnd = pis->pitchenv.lpe;
- penv->nPitchSustainBegin = pis->pitchenv.slb;
- penv->nPitchSustainEnd = pis->pitchenv.sle;
- // Envelopes Data
- for (UINT ev=0; ev<25; ev++)
- {
- penv->VolEnv[ev] = pis->volenv.data[ev*3];
- penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
- penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32;
- penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
- penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32;
- penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
- }
- penv->nNNA = pis->nna;
- penv->nDCT = pis->dct;
- penv->nDNA = pis->dca;
- penv->nPPS = pis->pps;
- penv->nPPC = pis->ppc;
- penv->nIFC = pis->ifc;
- penv->nIFR = pis->ifr;
- penv->nVolSwing = pis->rv;
- penv->nPanSwing = pis->rp;
- penv->nPan = (pis->dfp & 0x7F) << 2;
- if (penv->nPan > 256) penv->nPan = 128;
- if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING;
- }
- if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
- if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
- return TRUE;
-}
-
-
-BOOL CSoundFile::ReadIT(const BYTE *lpStream, DWORD dwMemLength)
-//--------------------------------------------------------------
-{
- ITFILEHEADER pifh = *(ITFILEHEADER *)lpStream;
- DWORD dwMemPos = sizeof(ITFILEHEADER);
- DWORD inspos[MAX_INSTRUMENTS];
- DWORD smppos[MAX_SAMPLES];
- DWORD patpos[MAX_PATTERNS];
- BYTE chnmask[64], channels_used[64];
- MODCOMMAND lastvalue[64];
-
- pifh.id = bswapLE32(pifh.id);
- pifh.reserved1 = bswapLE16(pifh.reserved1);
- pifh.ordnum = bswapLE16(pifh.ordnum);
- pifh.insnum = bswapLE16(pifh.insnum);
- pifh.smpnum = bswapLE16(pifh.smpnum);
- pifh.patnum = bswapLE16(pifh.patnum);
- pifh.cwtv = bswapLE16(pifh.cwtv);
- pifh.cmwt = bswapLE16(pifh.cmwt);
- pifh.flags = bswapLE16(pifh.flags);
- pifh.special = bswapLE16(pifh.special);
- pifh.msglength = bswapLE16(pifh.msglength);
- pifh.msgoffset = bswapLE32(pifh.msgoffset);
- pifh.reserved2 = bswapLE32(pifh.reserved2);
-
- if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
- if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS)
- || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE;
- if (dwMemPos + pifh.ordnum + pifh.insnum*4
- + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE;
- m_nType = MOD_TYPE_IT;
- if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES;
- if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS;
- if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE;
- if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG;
- if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
- memcpy(m_szNames[0], pifh.songname, 26);
- m_szNames[0][26] = 0;
- // Global Volume
- if (pifh.globalvol)
- {
- m_nDefaultGlobalVolume = pifh.globalvol << 1;
- if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256;
- if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
- }
- if (pifh.speed) m_nDefaultSpeed = pifh.speed;
- if (pifh.tempo) m_nDefaultTempo = pifh.tempo;
- m_nSongPreAmp = pifh.mv & 0x7F;
- // Reading Channels Pan Positions
- for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF)
- {
- ChnSettings[ipan].nVolume = pifh.chnvol[ipan];
- ChnSettings[ipan].nPan = 128;
- if (pifh.chnpan[ipan] & 0x80) ChnSettings[ipan].dwFlags |= CHN_MUTE;
- UINT n = pifh.chnpan[ipan] & 0x7F;
- if (n <= 64) ChnSettings[ipan].nPan = n << 2;
- if (n == 100) ChnSettings[ipan].dwFlags |= CHN_SURROUND;
- }
- if (m_nChannels < 4) m_nChannels = 4;
- // Reading Song Message
- if ((pifh.special & 0x01) && (pifh.msglength) && (pifh.msgoffset + pifh.msglength < dwMemLength))
- {
- m_lpszSongComments = new char[pifh.msglength+1];
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+pifh.msgoffset, pifh.msglength);
- m_lpszSongComments[pifh.msglength] = 0;
- }
- }
- // Reading orders
- UINT nordsize = pifh.ordnum;
- if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS;
- memcpy(Order, lpStream+dwMemPos, nordsize);
- dwMemPos += pifh.ordnum;
- // Reading Instrument Offsets
- memset(inspos, 0, sizeof(inspos));
- UINT inspossize = pifh.insnum;
- if (inspossize > MAX_INSTRUMENTS) inspossize = MAX_INSTRUMENTS;
- inspossize <<= 2;
- memcpy(inspos, lpStream+dwMemPos, inspossize);
- for (UINT j=0; j < (inspossize>>2); j++)
- {
- inspos[j] = bswapLE32(inspos[j]);
- }
- dwMemPos += pifh.insnum * 4;
- // Reading Samples Offsets
- memset(smppos, 0, sizeof(smppos));
- UINT smppossize = pifh.smpnum;
- if (smppossize > MAX_SAMPLES) smppossize = MAX_SAMPLES;
- smppossize <<= 2;
- memcpy(smppos, lpStream+dwMemPos, smppossize);
- for (UINT j=0; j < (smppossize>>2); j++)
- {
- smppos[j] = bswapLE32(smppos[j]);
- }
- dwMemPos += pifh.smpnum * 4;
- // Reading Patterns Offsets
- memset(patpos, 0, sizeof(patpos));
- UINT patpossize = pifh.patnum;
- if (patpossize > MAX_PATTERNS) patpossize = MAX_PATTERNS;
- patpossize <<= 2;
- memcpy(patpos, lpStream+dwMemPos, patpossize);
- for (UINT j=0; j < (patpossize>>2); j++)
- {
- patpos[j] = bswapLE32(patpos[j]);
- }
- dwMemPos += pifh.patnum * 4;
- // Reading IT Extra Info
- if (dwMemPos + 2 < dwMemLength)
- {
- UINT nflt = bswapLE16(*((WORD *)(lpStream + dwMemPos)));
- dwMemPos += 2;
- if (dwMemPos + nflt * 8 < dwMemLength) dwMemPos += nflt * 8;
- }
- // Reading Midi Output & Macros
- if (m_dwSongFlags & SONG_EMBEDMIDICFG)
- {
- if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength)
- {
- memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG));
- dwMemPos += sizeof(MODMIDICFG);
- }
- }
- // Read pattern names: "PNAM"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
- {
- UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
- dwMemPos += 8;
- if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
- {
- m_lpszPatternNames = new char[len];
- if (m_lpszPatternNames)
- {
- m_nPatternNames = len / MAX_PATTERNNAME;
- memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
- }
- dwMemPos += len;
- }
- }
- // 4-channels minimum
- m_nChannels = 4;
- // Read channel names: "CNAM"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
- {
- UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
- dwMemPos += 8;
- if ((dwMemPos + len <= dwMemLength) && (len <= 64*MAX_CHANNELNAME))
- {
- UINT n = len / MAX_CHANNELNAME;
- if (n > m_nChannels) m_nChannels = n;
- for (UINT i=0; i<n; i++)
- {
- memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
- ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
- }
- dwMemPos += len;
- }
- }
- // Read mix plugins information
- if (dwMemPos + 8 < dwMemLength)
- {
- dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
- }
- // Checking for unused channels
- UINT npatterns = pifh.patnum;
- if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
- for (UINT patchk=0; patchk<npatterns; patchk++)
- {
- memset(chnmask, 0, sizeof(chnmask));
- if ((!patpos[patchk]) || ((DWORD)patpos[patchk] + 4 >= dwMemLength)) continue;
- UINT len = bswapLE16(*((WORD *)(lpStream+patpos[patchk])));
- UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[patchk]+2)));
- if ((rows < 4) || (rows > 256)) continue;
- if (patpos[patchk]+8+len > dwMemLength) continue;
- UINT i = 0;
- const BYTE *p = lpStream+patpos[patchk]+8;
- UINT nrow = 0;
- while (nrow<rows)
- {
- if (i >= len) break;
- BYTE b = p[i++];
- if (!b)
- {
- nrow++;
- continue;
- }
- UINT ch = b & 0x7F;
- if (ch) ch = (ch - 1) & 0x3F;
- if (b & 0x80)
- {
- if (i >= len) break;
- chnmask[ch] = p[i++];
- }
- // Channel used
- if (chnmask[ch] & 0x0F)
- {
- if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1;
- }
- // Note
- if (chnmask[ch] & 1) i++;
- // Instrument
- if (chnmask[ch] & 2) i++;
- // Volume
- if (chnmask[ch] & 4) i++;
- // Effect
- if (chnmask[ch] & 8) i += 2;
- if (i >= len) break;
- }
- }
- // Reading Instruments
- m_nInstruments = 0;
- if (pifh.flags & 0x04) m_nInstruments = pifh.insnum;
- if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1;
- for (UINT nins=0; nins<m_nInstruments; nins++)
- {
- if ((inspos[nins] > 0) && (inspos[nins] < dwMemLength - sizeof(ITOLDINSTRUMENT)))
- {
- INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
- if (!penv) continue;
- Headers[nins+1] = penv;
- memset(penv, 0, sizeof(INSTRUMENTHEADER));
- ITInstrToMPT(lpStream + inspos[nins], penv, pifh.cmwt);
- }
- }
- // Reading Samples
- m_nSamples = pifh.smpnum;
- if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
- for (UINT nsmp=0; nsmp<pifh.smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] + sizeof(ITSAMPLESTRUCT) <= dwMemLength))
- {
- ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+smppos[nsmp]);
- pis.id = bswapLE32(pis.id);
- pis.length = bswapLE32(pis.length);
- pis.loopbegin = bswapLE32(pis.loopbegin);
- pis.loopend = bswapLE32(pis.loopend);
- pis.C5Speed = bswapLE32(pis.C5Speed);
- pis.susloopbegin = bswapLE32(pis.susloopbegin);
- pis.susloopend = bswapLE32(pis.susloopend);
- pis.samplepointer = bswapLE32(pis.samplepointer);
-
- if (pis.id == 0x53504D49)
- {
- MODINSTRUMENT *pins = &Ins[nsmp+1];
- memcpy(pins->name, pis.filename, 12);
- pins->uFlags = 0;
- pins->nLength = 0;
- pins->nLoopStart = pis.loopbegin;
- pins->nLoopEnd = pis.loopend;
- pins->nSustainStart = pis.susloopbegin;
- pins->nSustainEnd = pis.susloopend;
- pins->nC4Speed = pis.C5Speed;
- if (!pins->nC4Speed) pins->nC4Speed = 8363;
- if (pis.C5Speed < 256) pins->nC4Speed = 256;
- pins->nVolume = pis.vol << 2;
- if (pins->nVolume > 256) pins->nVolume = 256;
- pins->nGlobalVol = pis.gvl;
- if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
- if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP;
- if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP;
- if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP;
- if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN;
- pins->nPan = (pis.dfp & 0x7F) << 2;
- if (pins->nPan > 256) pins->nPan = 256;
- if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING;
- pins->nVibType = autovibit2xm[pis.vit & 7];
- pins->nVibRate = pis.vis;
- pins->nVibDepth = pis.vid & 0x7F;
- pins->nVibSweep = (pis.vir + 3) / 4;
- if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
- {
- pins->nLength = pis.length;
- if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH;
- UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U;
- if (pis.flags & 2)
- {
- flags += 5;
- if (pis.flags & 4) flags |= RSF_STEREO;
- pins->uFlags |= CHN_16BIT;
- // IT 2.14 16-bit packed sample ?
- if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416;
- } else
- {
- if (pis.flags & 4) flags |= RSF_STEREO;
- if (pis.cvt == 0xFF) flags = RS_ADPCM4; else
- // IT 2.14 8-bit packed sample ?
- if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148;
- }
- ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer);
- }
- }
- memcpy(m_szNames[nsmp+1], pis.name, 26);
- }
- // Reading Patterns
- for (UINT npat=0; npat<npatterns; npat++)
- {
- if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength))
- {
- PatternSize[npat] = 64;
- Patterns[npat] = AllocatePattern(64, m_nChannels);
- continue;
- }
-
- UINT len = bswapLE16(*((WORD *)(lpStream+patpos[npat])));
- UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[npat]+2)));
- if ((rows < 4) || (rows > 256)) continue;
- if (patpos[npat]+8+len > dwMemLength) continue;
- PatternSize[npat] = rows;
- if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue;
- memset(lastvalue, 0, sizeof(lastvalue));
- memset(chnmask, 0, sizeof(chnmask));
- MODCOMMAND *m = Patterns[npat];
- UINT i = 0;
- const BYTE *p = lpStream+patpos[npat]+8;
- UINT nrow = 0;
- while (nrow<rows)
- {
- if (i >= len) break;
- BYTE b = p[i++];
- if (!b)
- {
- nrow++;
- m+=m_nChannels;
- continue;
- }
- UINT ch = b & 0x7F;
- if (ch) ch = (ch - 1) & 0x3F;
- if (b & 0x80)
- {
- if (i >= len) break;
- chnmask[ch] = p[i++];
- }
- if ((chnmask[ch] & 0x10) && (ch < m_nChannels))
- {
- m[ch].note = lastvalue[ch].note;
- }
- if ((chnmask[ch] & 0x20) && (ch < m_nChannels))
- {
- m[ch].instr = lastvalue[ch].instr;
- }
- if ((chnmask[ch] & 0x40) && (ch < m_nChannels))
- {
- m[ch].volcmd = lastvalue[ch].volcmd;
- m[ch].vol = lastvalue[ch].vol;
- }
- if ((chnmask[ch] & 0x80) && (ch < m_nChannels))
- {
- m[ch].command = lastvalue[ch].command;
- m[ch].param = lastvalue[ch].param;
- }
- if (chnmask[ch] & 1) // Note
- {
- if (i >= len) break;
- UINT note = p[i++];
- if (ch < m_nChannels)
- {
- if (note < 0x80) note++;
- m[ch].note = note;
- lastvalue[ch].note = note;
- channels_used[ch] = TRUE;
- }
- }
- if (chnmask[ch] & 2)
- {
- if (i >= len) break;
- UINT instr = p[i++];
- if (ch < m_nChannels)
- {
- m[ch].instr = instr;
- lastvalue[ch].instr = instr;
- }
- }
- if (chnmask[ch] & 4)
- {
- if (i >= len) break;
- UINT vol = p[i++];
- if (ch < m_nChannels)
- {
- // 0-64: Set Volume
- if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else
- // 128-192: Set Panning
- if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else
- // 65-74: Fine Volume Up
- if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else
- // 75-84: Fine Volume Down
- if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else
- // 85-94: Volume Slide Up
- if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else
- // 95-104: Volume Slide Down
- if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else
- // 105-114: Pitch Slide Up
- if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else
- // 115-124: Pitch Slide Down
- if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else
- // 193-202: Portamento To
- if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else
- // 203-212: Vibrato
- if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; }
- lastvalue[ch].volcmd = m[ch].volcmd;
- lastvalue[ch].vol = m[ch].vol;
- }
- }
- // Reading command/param
- if (chnmask[ch] & 8)
- {
- if (i > len - 2) break;
- UINT cmd = p[i++];
- UINT param = p[i++];
- if (ch < m_nChannels)
- {
- if (cmd)
- {
- m[ch].command = cmd;
- m[ch].param = param;
- S3MConvert(&m[ch], TRUE);
- lastvalue[ch].command = m[ch].command;
- lastvalue[ch].param = m[ch].param;
- }
- }
- }
- }
- }
- for (UINT ncu=0; ncu<MAX_BASECHANNELS; ncu++)
- {
- if (ncu>=m_nChannels)
- {
- ChnSettings[ncu].nVolume = 64;
- ChnSettings[ncu].dwFlags &= ~CHN_MUTE;
- }
- }
- m_nMinPeriod = 8;
- m_nMaxPeriod = 0xF000;
- return TRUE;
-}
-
-
-#ifndef MODPLUG_NO_FILESAVE
-//#define SAVEITTIMESTAMP
-#pragma warning(disable:4100)
-
-BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking)
-//---------------------------------------------------------
-{
- DWORD dwPatNamLen, dwChnNamLen;
- ITFILEHEADER header;
- ITINSTRUMENT iti;
- ITSAMPLESTRUCT itss;
- BYTE smpcount[MAX_SAMPLES];
- DWORD inspos[MAX_INSTRUMENTS];
- DWORD patpos[MAX_PATTERNS];
- DWORD smppos[MAX_SAMPLES];
- DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2;
- WORD patinfo[4];
- BYTE chnmask[64];
- BYTE buf[512];
- MODCOMMAND lastvalue[64];
- FILE *f;
-
-
- if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE;
- memset(inspos, 0, sizeof(inspos));
- memset(patpos, 0, sizeof(patpos));
- memset(smppos, 0, sizeof(smppos));
- // Writing Header
- memset(&header, 0, sizeof(header));
- dwPatNamLen = 0;
- dwChnNamLen = 0;
- header.id = 0x4D504D49;
- lstrcpyn(header.songname, m_szNames[0], 27);
- header.reserved1 = 0x1004;
- header.ordnum = 0;
- while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++;
- if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF;
- header.insnum = m_nInstruments;
- header.smpnum = m_nSamples;
- header.patnum = MAX_PATTERNS;
- while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--;
- header.cwtv = 0x217;
- header.cmwt = 0x200;
- header.flags = 0x0001;
- header.special = 0x0006;
- if (m_nInstruments) header.flags |= 0x04;
- if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08;
- if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10;
- if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20;
- if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
- header.globalvol = m_nDefaultGlobalVolume >> 1;
- header.mv = m_nSongPreAmp;
- if (header.mv < 0x20) header.mv = 0x20;
- if (header.mv > 0x7F) header.mv = 0x7F;
- header.speed = m_nDefaultSpeed;
- header.tempo = m_nDefaultTempo;
- header.sep = 128;
- dwHdrPos = sizeof(header) + header.ordnum;
- // Channel Pan and Volume
- memset(header.chnpan, 0xFF, 64);
- memset(header.chnvol, 64, 64);
- for (UINT ich=0; ich<m_nChannels; ich++)
- {
- header.chnpan[ich] = ChnSettings[ich].nPan >> 2;
- if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100;
- header.chnvol[ich] = ChnSettings[ich].nVolume;
- if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80;
- if (ChnSettings[ich].szName[0])
- {
- dwChnNamLen = (ich+1) * MAX_CHANNELNAME;
- }
- }
- if (dwChnNamLen) dwExtra += dwChnNamLen + 8;
-#ifdef SAVEITTIMESTAMP
- dwExtra += 8; // Time Stamp
-#endif
- if (m_dwSongFlags & SONG_EMBEDMIDICFG)
- {
- header.flags |= 0x80;
- header.special |= 0x08;
- dwExtra += sizeof(MODMIDICFG);
- }
- // Pattern Names
- if ((m_nPatternNames) && (m_lpszPatternNames))
- {
- dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME;
- while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME;
- if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0;
- if (dwPatNamLen) dwExtra += dwPatNamLen + 8;
- }
- // Mix Plugins
- dwExtra += SaveMixPlugins(NULL, TRUE);
- // Comments
- if (m_lpszSongComments)
- {
- header.special |= 1;
- header.msglength = strlen(m_lpszSongComments)+1;
- header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4;
- }
- // Write file header
- fwrite(&header, 1, sizeof(header), f);
- fwrite(Order, 1, header.ordnum, f);
- if (header.insnum) fwrite(inspos, 4, header.insnum, f);
- if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
- if (header.patnum) fwrite(patpos, 4, header.patnum, f);
- // Writing editor history information
- {
-#ifdef SAVEITTIMESTAMP
- SYSTEMTIME systime;
- FILETIME filetime;
- WORD timestamp[4];
- WORD nInfoEx = 1;
- memset(timestamp, 0, sizeof(timestamp));
- fwrite(&nInfoEx, 1, 2, f);
- GetSystemTime(&systime);
- SystemTimeToFileTime(&systime, &filetime);
- FileTimeToDosDateTime(&filetime, ×tamp[0], ×tamp[1]);
- fwrite(timestamp, 1, 8, f);
-#else
- WORD nInfoEx = 0;
- fwrite(&nInfoEx, 1, 2, f);
-#endif
- }
- // Writing midi cfg
- if (header.flags & 0x80)
- {
- fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
- }
- // Writing pattern names
- if (dwPatNamLen)
- {
- DWORD d = 0x4d414e50;
- fwrite(&d, 1, 4, f);
- fwrite(&dwPatNamLen, 1, 4, f);
- fwrite(m_lpszPatternNames, 1, dwPatNamLen, f);
- }
- // Writing channel Names
- if (dwChnNamLen)
- {
- DWORD d = 0x4d414e43;
- fwrite(&d, 1, 4, f);
- fwrite(&dwChnNamLen, 1, 4, f);
- UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME;
- for (UINT inam=0; inam<nChnNames; inam++)
- {
- fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
- }
- }
- // Writing mix plugins info
- SaveMixPlugins(f, FALSE);
- // Writing song message
- dwPos = dwHdrPos + dwExtra + (header.insnum + header.smpnum + header.patnum) * 4;
- if (header.special & 1)
- {
- dwPos += strlen(m_lpszSongComments) + 1;
- fwrite(m_lpszSongComments, 1, strlen(m_lpszSongComments)+1, f);
- }
- // Writing instruments
- for (UINT nins=1; nins<=header.insnum; nins++)
- {
- memset(&iti, 0, sizeof(iti));
- iti.id = 0x49504D49; // "IMPI"
- iti.trkvers = 0x211;
- if (Headers[nins])
- {
- INSTRUMENTHEADER *penv = Headers[nins];
- memset(smpcount, 0, sizeof(smpcount));
- memcpy(iti.filename, penv->filename, 12);
- memcpy(iti.name, penv->name, 26);
- iti.mbank = penv->wMidiBank;
- iti.mpr = penv->nMidiProgram;
- iti.mch = penv->nMidiChannel;
- iti.nna = penv->nNNA;
- iti.dct = penv->nDCT;
- iti.dca = penv->nDNA;
- iti.fadeout = penv->nFadeOut >> 5;
- iti.pps = penv->nPPS;
- iti.ppc = penv->nPPC;
- iti.gbv = (BYTE)(penv->nGlobalVol << 1);
- iti.dfp = (BYTE)penv->nPan >> 2;
- if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80;
- iti.rv = penv->nVolSwing;
- iti.rp = penv->nPanSwing;
- iti.ifc = penv->nIFC;
- iti.ifr = penv->nIFR;
- iti.nos = 0;
- for (UINT i=0; i<120; i++) if (penv->Keyboard[i] < MAX_SAMPLES)
- {
- UINT smp = penv->Keyboard[i];
- if ((smp) && (!smpcount[smp]))
- {
- smpcount[smp] = 1;
- iti.nos++;
- }
- iti.keyboard[i*2] = penv->NoteMap[i] - 1;
- iti.keyboard[i*2+1] = smp;
- }
- // Writing Volume envelope
- if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01;
- if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02;
- if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04;
- if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08;
- iti.volenv.num = (BYTE)penv->nVolEnv;
- iti.volenv.lpb = (BYTE)penv->nVolLoopStart;
- iti.volenv.lpe = (BYTE)penv->nVolLoopEnd;
- iti.volenv.slb = penv->nVolSustainBegin;
- iti.volenv.sle = penv->nVolSustainEnd;
- // Writing Panning envelope
- if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01;
- if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02;
- if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04;
- if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08;
- iti.panenv.num = (BYTE)penv->nPanEnv;
- iti.panenv.lpb = (BYTE)penv->nPanLoopStart;
- iti.panenv.lpe = (BYTE)penv->nPanLoopEnd;
- iti.panenv.slb = penv->nPanSustainBegin;
- iti.panenv.sle = penv->nPanSustainEnd;
- // Writing Pitch Envelope
- if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01;
- if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02;
- if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04;
- if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08;
- if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80;
- iti.pitchenv.num = (BYTE)penv->nPitchEnv;
- iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart;
- iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd;
- iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin;
- iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd;
- // Writing Envelopes data
- for (UINT ev=0; ev<25; ev++)
- {
- iti.volenv.data[ev*3] = penv->VolEnv[ev];
- iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF;
- iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8;
- iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32;
- iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF;
- iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8;
- iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32;
- iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF;
- iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8;
- }
- } else
- // Save Empty Instrument
- {
- for (UINT i=0; i<120; i++) iti.keyboard[i*2] = i;
- iti.ppc = 5*12;
- iti.gbv = 128;
- iti.dfp = 0x20;
- iti.ifc = 0xFF;
- }
- if (!iti.nos) iti.trkvers = 0;
- // Writing instrument
- inspos[nins-1] = dwPos;
- dwPos += sizeof(ITINSTRUMENT);
- fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
- }
- // Writing sample headers
- memset(&itss, 0, sizeof(itss));
- for (UINT hsmp=0; hsmp<header.smpnum; hsmp++)
- {
- smppos[hsmp] = dwPos;
- dwPos += sizeof(ITSAMPLESTRUCT);
- fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
- }
- // Writing Patterns
- for (UINT npat=0; npat<header.patnum; npat++)
- {
- DWORD dwPatPos = dwPos;
- UINT len;
- if (!Patterns[npat]) continue;
- patpos[npat] = dwPos;
- patinfo[0] = 0;
- patinfo[1] = PatternSize[npat];
- patinfo[2] = 0;
- patinfo[3] = 0;
- // Check for empty pattern
- if (PatternSize[npat] == 64)
- {
- MODCOMMAND *pzc = Patterns[npat];
- UINT nz = PatternSize[npat] * m_nChannels;
- INT iz;
- for (iz=0; iz<nz; iz++)
- {
- if ((pzc[iz].note) || (pzc[iz].instr)
- || (pzc[iz].volcmd) || (pzc[iz].command)) break;
- }
- if (iz == nz)
- {
- patpos[npat] = 0;
- continue;
- }
- }
- fwrite(patinfo, 8, 1, f);
- dwPos += 8;
- memset(chnmask, 0xFF, sizeof(chnmask));
- memset(lastvalue, 0, sizeof(lastvalue));
- MODCOMMAND *m = Patterns[npat];
- for (UINT row=0; row<PatternSize[npat]; row++)
- {
- len = 0;
- for (UINT ch=0; ch<m_nChannels; ch++, m++)
- {
- BYTE b = 0;
- UINT command = m->command;
- UINT param = m->param;
- UINT vol = 0xFF;
- UINT note = m->note;
- if (note) b |= 1;
- if ((note) && (note < 0xFE)) note--;
- if (m->instr) b |= 2;
- if (m->volcmd)
- {
- UINT volcmd = m->volcmd;
- switch(volcmd)
- {
- case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break;
- case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break;
- case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break;
- case VOLCMD_VOLSLIDEDOWN: vol = 95 + ConvertVolParam(m->vol); break;
- case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break;
- case VOLCMD_FINEVOLDOWN: vol = 75 + ConvertVolParam(m->vol); break;
- case VOLCMD_VIBRATO: vol = 203; break;
- case VOLCMD_VIBRATOSPEED: vol = 203 + ConvertVolParam(m->vol); break;
- case VOLCMD_TONEPORTAMENTO: vol = 193 + ConvertVolParam(m->vol); break;
- case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break;
- case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break;
- default: vol = 0xFF;
- }
- }
- if (vol != 0xFF) b |= 4;
- if (command)
- {
- S3MSaveConvert(&command, ¶m, TRUE);
- if (command) b |= 8;
- }
- // Packing information
- if (b)
- {
- // Same note ?
- if (b & 1)
- {
- if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1))
- {
- b &= ~1;
- b |= 0x10;
- } else
- {
- lastvalue[ch].note = note;
- lastvalue[ch].volcmd |= 1;
- }
- }
- // Same instrument ?
- if (b & 2)
- {
- if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2))
- {
- b &= ~2;
- b |= 0x20;
- } else
- {
- lastvalue[ch].instr = m->instr;
- lastvalue[ch].volcmd |= 2;
- }
- }
- // Same volume column byte ?
- if (b & 4)
- {
- if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4))
- {
- b &= ~4;
- b |= 0x40;
- } else
- {
- lastvalue[ch].vol = vol;
- lastvalue[ch].volcmd |= 4;
- }
- }
- // Same command / param ?
- if (b & 8)
- {
- if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8))
- {
- b &= ~8;
- b |= 0x80;
- } else
- {
- lastvalue[ch].command = command;
- lastvalue[ch].param = param;
- lastvalue[ch].volcmd |= 8;
- }
- }
- if (b != chnmask[ch])
- {
- chnmask[ch] = b;
- buf[len++] = (ch+1) | 0x80;
- buf[len++] = b;
- } else
- {
- buf[len++] = ch+1;
- }
- if (b & 1) buf[len++] = note;
- if (b & 2) buf[len++] = m->instr;
- if (b & 4) buf[len++] = vol;
- if (b & 8)
- {
- buf[len++] = command;
- buf[len++] = param;
- }
- }
- }
- buf[len++] = 0;
- dwPos += len;
- patinfo[0] += len;
- fwrite(buf, 1, len, f);
- }
- fseek(f, dwPatPos, SEEK_SET);
- fwrite(patinfo, 8, 1, f);
- fseek(f, dwPos, SEEK_SET);
- }
- // Writing Sample Data
- for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++)
- {
- MODINSTRUMENT *psmp = &Ins[nsmp];
- memset(&itss, 0, sizeof(itss));
- memcpy(itss.filename, psmp->name, 12);
- memcpy(itss.name, m_szNames[nsmp], 26);
- itss.id = 0x53504D49;
- itss.gvl = (BYTE)psmp->nGlobalVol;
- if (m_nInstruments)
- {
- for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu])
- {
- INSTRUMENTHEADER *penv = Headers[iu];
- for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp)
- {
- itss.flags = 0x01;
- break;
- }
- }
- } else
- {
- itss.flags = 0x01;
- }
- if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10;
- if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20;
- if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40;
- if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80;
- itss.C5Speed = psmp->nC4Speed;
- if (!itss.C5Speed) itss.C5Speed = 8363;
- itss.length = psmp->nLength;
- itss.loopbegin = psmp->nLoopStart;
- itss.loopend = psmp->nLoopEnd;
- itss.susloopbegin = psmp->nSustainStart;
- itss.susloopend = psmp->nSustainEnd;
- itss.vol = psmp->nVolume >> 2;
- itss.dfp = psmp->nPan >> 2;
- itss.vit = autovibxm2it[psmp->nVibType & 7];
- itss.vis = psmp->nVibRate;
- itss.vid = psmp->nVibDepth;
- itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255;
- if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
- if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
- UINT flags = RS_PCM8S;
-#ifndef NO_PACKING
- if (nPacking)
- {
- if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO)))
- && (CanPackSample(psmp->pSample, psmp->nLength, nPacking)))
- {
- flags = RS_ADPCM4;
- itss.cvt = 0xFF;
- }
- } else
-#endif // NO_PACKING
- {
- if (psmp->uFlags & CHN_STEREO)
- {
- flags = RS_STPCM8S;
- itss.flags |= 0x04;
- }
- if (psmp->uFlags & CHN_16BIT)
- {
- itss.flags |= 0x02;
- flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S;
- }
- }
- itss.samplepointer = dwPos;
- fseek(f, smppos[nsmp-1], SEEK_SET);
- fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
- fseek(f, dwPos, SEEK_SET);
- if ((psmp->pSample) && (psmp->nLength))
- {
- dwPos += WriteSample(f, psmp, flags);
- }
- }
- // Updating offsets
- fseek(f, dwHdrPos, SEEK_SET);
- if (header.insnum) fwrite(inspos, 4, header.insnum, f);
- if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
- if (header.patnum) fwrite(patpos, 4, header.patnum, f);
- fclose(f);
- return TRUE;
-}
-
-#pragma warning(default:4100)
-#endif // MODPLUG_NO_FILESAVE
-
-//////////////////////////////////////////////////////////////////////////////
-// IT 2.14 compression
-
-DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
-//-----------------------------------------------------------------
-{
- DWORD retval = 0;
- UINT i = n;
-
- if (n > 0)
- {
- do
- {
- if (!bitnum)
- {
- bitbuf = *ibuf++;
- bitnum = 8;
- }
- retval >>= 1;
- retval |= bitbuf << 31;
- bitbuf >>= 1;
- bitnum--;
- i--;
- } while (i);
- i = n;
- }
- return (retval >> (32-i));
-}
-
-#define IT215_SUPPORT
-void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
-//-------------------------------------------------------------------------------------------
-{
- signed char *pDst = pSample;
- LPBYTE pSrc = lpMemFile;
- DWORD wHdr = 0;
- DWORD wCount = 0;
- DWORD bitbuf = 0;
- UINT bitnum = 0;
- BYTE bLeft = 0, bTemp = 0, bTemp2 = 0;
-
- while (dwLen)
- {
- if (!wCount)
- {
- wCount = 0x8000;
- wHdr = bswapLE16(*((LPWORD)pSrc));
- pSrc += 2;
- bLeft = 9;
- bTemp = bTemp2 = 0;
- bitbuf = bitnum = 0;
- }
- DWORD d = wCount;
- if (d > dwLen) d = dwLen;
- // Unpacking
- DWORD dwPos = 0;
- do
- {
- WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft);
- if (bLeft < 7)
- {
- DWORD i = 1 << (bLeft-1);
- DWORD j = wBits & 0xFFFF;
- if (i != j) goto UnpackByte;
- wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF;
- bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF);
- goto Next;
- }
- if (bLeft < 9)
- {
- WORD i = (0xFF >> (9 - bLeft)) + 4;
- WORD j = i - 8;
- if ((wBits <= j) || (wBits > i)) goto UnpackByte;
- wBits -= j;
- bLeft = ((BYTE)(wBits & 0xFF) < bLeft) ? (BYTE)(wBits & 0xFF) : (BYTE)((wBits+1) & 0xFF);
- goto Next;
- }
- if (bLeft >= 10) goto SkipByte;
- if (wBits >= 256)
- {
- bLeft = (BYTE)(wBits + 1) & 0xFF;
- goto Next;
- }
- UnpackByte:
- if (bLeft < 8)
- {
- BYTE shift = 8 - bLeft;
- signed char c = (signed char)(wBits << shift);
- c >>= shift;
- wBits = (WORD)c;
- }
- wBits += bTemp;
- bTemp = (BYTE)wBits;
- bTemp2 += bTemp;
-#ifdef IT215_SUPPORT
- pDst[dwPos] = (b215) ? bTemp2 : bTemp;
-#else
- pDst[dwPos] = bTemp;
-#endif
- SkipByte:
- dwPos++;
- Next:
- if (pSrc >= lpMemFile+dwMemLength+1) return;
- } while (dwPos < d);
- // Move On
- wCount -= d;
- dwLen -= d;
- pDst += d;
- }
-}
-
-
-void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
-//--------------------------------------------------------------------------------------------
-{
- signed short *pDst = (signed short *)pSample;
- LPBYTE pSrc = lpMemFile;
- DWORD wHdr = 0;
- DWORD wCount = 0;
- DWORD bitbuf = 0;
- UINT bitnum = 0;
- BYTE bLeft = 0;
- signed short wTemp = 0, wTemp2 = 0;
-
- while (dwLen)
- {
- if (!wCount)
- {
- wCount = 0x4000;
- wHdr = bswapLE16(*((LPWORD)pSrc));
- pSrc += 2;
- bLeft = 17;
- wTemp = wTemp2 = 0;
- bitbuf = bitnum = 0;
- }
- DWORD d = wCount;
- if (d > dwLen) d = dwLen;
- // Unpacking
- DWORD dwPos = 0;
- do
- {
- DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft);
- if (bLeft < 7)
- {
- DWORD i = 1 << (bLeft-1);
- DWORD j = dwBits;
- if (i != j) goto UnpackByte;
- dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1;
- bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
- goto Next;
- }
- if (bLeft < 17)
- {
- DWORD i = (0xFFFF >> (17 - bLeft)) + 8;
- DWORD j = (i - 16) & 0xFFFF;
- if ((dwBits <= j) || (dwBits > (i & 0xFFFF))) goto UnpackByte;
- dwBits -= j;
- bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
- goto Next;
- }
- if (bLeft >= 18) goto SkipByte;
- if (dwBits >= 0x10000)
- {
- bLeft = (BYTE)(dwBits + 1) & 0xFF;
- goto Next;
- }
- UnpackByte:
- if (bLeft < 16)
- {
- BYTE shift = 16 - bLeft;
- signed short c = (signed short)(dwBits << shift);
- c >>= shift;
- dwBits = (DWORD)c;
- }
- dwBits += wTemp;
- wTemp = (signed short)dwBits;
- wTemp2 += wTemp;
-#ifdef IT215_SUPPORT
- pDst[dwPos] = (b215) ? wTemp2 : wTemp;
-#else
- pDst[dwPos] = wTemp;
-#endif
- SkipByte:
- dwPos++;
- Next:
- if (pSrc >= lpMemFile+dwMemLength+1) return;
- } while (dwPos < d);
- // Move On
- wCount -= d;
- dwLen -= d;
- pDst += d;
- if (pSrc >= lpMemFile+dwMemLength) break;
- }
-}
-
-#ifndef MODPLUG_NO_FILESAVE
-
-UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate)
-//----------------------------------------------------
-{
- DWORD chinfo[64];
- CHAR s[32];
- DWORD nPluginSize;
- UINT nTotalSize = 0;
- UINT nChInfo = 0;
-
- for (UINT i=0; i<MAX_MIXPLUGINS; i++)
- {
- PSNDMIXPLUGIN p = &m_MixPlugins[i];
- if ((p->Info.dwPluginId1) || (p->Info.dwPluginId2))
- {
- nPluginSize = sizeof(SNDMIXPLUGININFO)+4; // plugininfo+4 (datalen)
- if ((p->pMixPlugin) && (bUpdate))
- {
- p->pMixPlugin->SaveAllParameters();
- }
- if (p->pPluginData)
- {
- nPluginSize += p->nPluginDataSize;
- }
- if (f)
- {
- s[0] = 'F';
- s[1] = 'X';
- s[2] = '0' + (i/10);
- s[3] = '0' + (i%10);
- fwrite(s, 1, 4, f);
- fwrite(&nPluginSize, 1, 4, f);
- fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f);
- fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f);
- if (m_MixPlugins[i].pPluginData)
- {
- fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f);
- }
- }
- nTotalSize += nPluginSize + 8;
- }
- }
- for (UINT j=0; j<m_nChannels; j++)
- {
- if (j < 64)
- {
- if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0)
- {
- nChInfo = j+1;
- }
- }
- }
- if (nChInfo)
- {
- if (f)
- {
- nPluginSize = 0x58464843;
- fwrite(&nPluginSize, 1, 4, f);
- nPluginSize = nChInfo*4;
- fwrite(&nPluginSize, 1, 4, f);
- fwrite(chinfo, 1, nPluginSize, f);
- }
- nTotalSize += nChInfo*4 + 8;
- }
- return nTotalSize;
-}
-
-#endif /* MODPLUG_NO_FILESAVE */
-
-UINT CSoundFile::LoadMixPlugins(const void *pData, UINT nLen)
-//-----------------------------------------------------------
-{
- const BYTE *p = (const BYTE *)pData;
- UINT nPos = 0;
-
- while (nPos+8 < nLen)
- {
- DWORD nPluginSize;
- UINT nPlugin;
-
- nPluginSize = bswapLE32(*(DWORD *)(p+nPos+4));
- if (nPluginSize > nLen-nPos-8) break;;
- if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843)
- {
- for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize)
- {
- ChnSettings[ch].nMixPlugin = bswapLE32(*(DWORD *)(p+nPos+8+ch*4));
- }
- } else
- {
- if ((p[nPos] != 'F') || (p[nPos+1] != 'X')
- || (p[nPos+2] < '0') || (p[nPos+3] < '0'))
- {
- break;
- }
- nPlugin = (p[nPos+2]-'0')*10 + (p[nPos+3]-'0');
- if ((nPlugin < MAX_MIXPLUGINS) && (nPluginSize >= sizeof(SNDMIXPLUGININFO)+4))
- {
- DWORD dwExtra = bswapLE32(*(DWORD *)(p+nPos+8+sizeof(SNDMIXPLUGININFO)));
- m_MixPlugins[nPlugin].Info = *(const SNDMIXPLUGININFO *)(p+nPos+8);
- m_MixPlugins[nPlugin].Info.dwPluginId1 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId1);
- m_MixPlugins[nPlugin].Info.dwPluginId2 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId2);
- m_MixPlugins[nPlugin].Info.dwInputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwInputRouting);
- m_MixPlugins[nPlugin].Info.dwOutputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwOutputRouting);
- for (UINT j=0; j<4; j++)
- {
- m_MixPlugins[nPlugin].Info.dwReserved[j] = bswapLE32(m_MixPlugins[nPlugin].Info.dwReserved[j]);
- }
- if ((dwExtra) && (dwExtra <= nPluginSize-sizeof(SNDMIXPLUGININFO)-4))
- {
- m_MixPlugins[nPlugin].nPluginDataSize = 0;
- m_MixPlugins[nPlugin].pPluginData = new signed char [dwExtra];
- if (m_MixPlugins[nPlugin].pPluginData)
- {
- m_MixPlugins[nPlugin].nPluginDataSize = dwExtra;
- memcpy(m_MixPlugins[nPlugin].pPluginData, p+nPos+8+sizeof(SNDMIXPLUGININFO)+4, dwExtra);
- }
- }
- }
- }
- nPos += nPluginSize + 8;
- }
- return nPos;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-
-///////////////////////////////////////////////////
-//
-// J2B module loader
-//
-///////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-//////////////////////////////////////////////
-// DigiTracker (MDL) module loader //
-//////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-typedef struct MDLSONGHEADER
-{
- DWORD id; // "DMDL" = 0x4C444D44
- BYTE version;
-} MDLSONGHEADER;
-
-
-typedef struct MDLINFOBLOCK
-{
- CHAR songname[32];
- CHAR composer[20];
- WORD norders;
- WORD repeatpos;
- BYTE globalvol;
- BYTE speed;
- BYTE tempo;
- BYTE channelinfo[32];
- BYTE seq[256];
-} MDLINFOBLOCK;
-
-
-typedef struct MDLPATTERNDATA
-{
- BYTE channels;
- BYTE lastrow; // nrows = lastrow+1
- CHAR name[16];
- WORD data[1];
-} MDLPATTERNDATA;
-
-
-void ConvertMDLCommand(MODCOMMAND *m, UINT eff, UINT data)
-//--------------------------------------------------------
-{
- UINT command = 0, param = data;
- switch(eff)
- {
- case 0x01: command = CMD_PORTAMENTOUP; break;
- case 0x02: command = CMD_PORTAMENTODOWN; break;
- case 0x03: command = CMD_TONEPORTAMENTO; break;
- case 0x04: command = CMD_VIBRATO; break;
- case 0x05: command = CMD_ARPEGGIO; break;
- case 0x07: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
- case 0x08: command = CMD_PANNING8; param <<= 1; break;
- case 0x0B: command = CMD_POSITIONJUMP; break;
- case 0x0C: command = CMD_GLOBALVOLUME; break;
- case 0x0D: command = CMD_PATTERNBREAK; param = (data & 0x0F) + (data>>4)*10; break;
- case 0x0E:
- command = CMD_S3MCMDEX;
- switch(data & 0xF0)
- {
- case 0x00: command = 0; break; // What is E0x in MDL (there is a bunch) ?
- case 0x10: if (param & 0x0F) { param |= 0xF0; command = CMD_PANNINGSLIDE; } else command = 0; break;
- case 0x20: if (param & 0x0F) { param = (param << 4) | 0x0F; command = CMD_PANNINGSLIDE; } else command = 0; break;
- case 0x30: param = (data & 0x0F) | 0x10; break; // glissando
- case 0x40: param = (data & 0x0F) | 0x30; break; // vibrato waveform
- case 0x60: param = (data & 0x0F) | 0xB0; break;
- case 0x70: param = (data & 0x0F) | 0x40; break; // tremolo waveform
- case 0x90: command = CMD_RETRIG; param &= 0x0F; break;
- case 0xA0: param = (data & 0x0F) << 4; command = CMD_GLOBALVOLSLIDE; break;
- case 0xB0: param = data & 0x0F; command = CMD_GLOBALVOLSLIDE; break;
- case 0xF0: param = ((data >> 8) & 0x0F) | 0xA0; break;
- }
- break;
- case 0x0F: command = CMD_SPEED; break;
- case 0x10: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break;
- case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break;
- case 0x30: command = CMD_RETRIG; break;
- case 0x40: command = CMD_TREMOLO; break;
- case 0x50: command = CMD_TREMOR; break;
- case 0xEF: if (param > 0xFF) param = 0xFF; command = CMD_OFFSET; break;
- }
- if (command)
- {
- m->command = command;
- m->param = param;
- }
-}
-
-
-void UnpackMDLTrack(MODCOMMAND *pat, UINT nChannels, UINT nRows, UINT nTrack, const BYTE *lpTracks)
-//-------------------------------------------------------------------------------------------------
-{
- MODCOMMAND cmd, *m = pat;
- UINT len = *((WORD *)lpTracks);
- UINT pos = 0, row = 0, i;
- lpTracks += 2;
- for (UINT ntrk=1; ntrk<nTrack; ntrk++)
- {
- lpTracks += len;
- len = *((WORD *)lpTracks);
- lpTracks += 2;
- }
- cmd.note = cmd.instr = 0;
- cmd.volcmd = cmd.vol = 0;
- cmd.command = cmd.param = 0;
- while ((row < nRows) && (pos < len))
- {
- UINT xx;
- BYTE b = lpTracks[pos++];
- xx = b >> 2;
- switch(b & 0x03)
- {
- case 0x01:
- for (i=0; i<=xx; i++)
- {
- if (row) *m = *(m-nChannels);
- m += nChannels;
- row++;
- if (row >= nRows) break;
- }
- break;
-
- case 0x02:
- if (xx < row) *m = pat[nChannels*xx];
- m += nChannels;
- row++;
- break;
-
- case 0x03:
- {
- cmd.note = (xx & 0x01) ? lpTracks[pos++] : 0;
- cmd.instr = (xx & 0x02) ? lpTracks[pos++] : 0;
- cmd.volcmd = cmd.vol = 0;
- cmd.command = cmd.param = 0;
- if ((cmd.note < 120-12) && (cmd.note)) cmd.note += 12;
- UINT volume = (xx & 0x04) ? lpTracks[pos++] : 0;
- UINT commands = (xx & 0x08) ? lpTracks[pos++] : 0;
- UINT command1 = commands & 0x0F;
- UINT command2 = commands & 0xF0;
- UINT param1 = (xx & 0x10) ? lpTracks[pos++] : 0;
- UINT param2 = (xx & 0x20) ? lpTracks[pos++] : 0;
- if ((command1 == 0x0E) && ((param1 & 0xF0) == 0xF0) && (!command2))
- {
- param1 = ((param1 & 0x0F) << 8) | param2;
- command1 = 0xEF;
- command2 = param2 = 0;
- }
- if (volume)
- {
- cmd.volcmd = VOLCMD_VOLUME;
- cmd.vol = (volume+1) >> 2;
- }
- ConvertMDLCommand(&cmd, command1, param1);
- if ((cmd.command != CMD_SPEED)
- && (cmd.command != CMD_TEMPO)
- && (cmd.command != CMD_PATTERNBREAK))
- ConvertMDLCommand(&cmd, command2, param2);
- *m = cmd;
- m += nChannels;
- row++;
- }
- break;
-
- // Empty Slots
- default:
- row += xx+1;
- m += (xx+1)*nChannels;
- if (row >= nRows) break;
- }
- }
-}
-
-
-
-BOOL CSoundFile::ReadMDL(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- DWORD dwMemPos, dwPos, blocklen, dwTrackPos;
- const MDLSONGHEADER *pmsh = (const MDLSONGHEADER *)lpStream;
- MDLINFOBLOCK *pmib;
- MDLPATTERNDATA *pmpd;
- UINT i,j, norders = 0, npatterns = 0, ntracks = 0;
- UINT ninstruments = 0, nsamples = 0;
- WORD block;
- WORD patterntracks[MAX_PATTERNS*32];
- BYTE smpinfo[MAX_SAMPLES];
- BYTE insvolenv[MAX_INSTRUMENTS];
- BYTE inspanenv[MAX_INSTRUMENTS];
- LPCBYTE pvolenv, ppanenv, ppitchenv;
- UINT nvolenv, npanenv, npitchenv;
-
- if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
- if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE;
- memset(patterntracks, 0, sizeof(patterntracks));
- memset(smpinfo, 0, sizeof(smpinfo));
- memset(insvolenv, 0, sizeof(insvolenv));
- memset(inspanenv, 0, sizeof(inspanenv));
- dwMemPos = 5;
- dwTrackPos = 0;
- pvolenv = ppanenv = ppitchenv = NULL;
- nvolenv = npanenv = npitchenv = 0;
- m_nSamples = m_nInstruments = 0;
- while (dwMemPos+6 < dwMemLength)
- {
- block = *((WORD *)(lpStream+dwMemPos));
- blocklen = *((DWORD *)(lpStream+dwMemPos+2));
- dwMemPos += 6;
- if (dwMemPos + blocklen > dwMemLength)
- {
- if (dwMemPos == 11) return FALSE;
- break;
- }
- switch(block)
- {
- // IN: infoblock
- case 0x4E49:
- pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos);
- memcpy(m_szNames[0], pmib->songname, 32);
- norders = pmib->norders;
- if (norders > MAX_ORDERS) norders = MAX_ORDERS;
- m_nRestartPos = pmib->repeatpos;
- m_nDefaultGlobalVolume = pmib->globalvol;
- m_nDefaultTempo = pmib->tempo;
- m_nDefaultSpeed = pmib->speed;
- m_nChannels = 4;
- for (i=0; i<32; i++)
- {
- ChnSettings[i].nVolume = 64;
- ChnSettings[i].nPan = (pmib->channelinfo[i] & 0x7F) << 1;
- if (pmib->channelinfo[i] & 0x80)
- ChnSettings[i].dwFlags |= CHN_MUTE;
- else
- m_nChannels = i+1;
- }
- for (j=0; j<norders; j++) Order[j] = pmib->seq[j];
- break;
- // ME: song message
- case 0x454D:
- if (blocklen)
- {
- if (m_lpszSongComments) delete m_lpszSongComments;
- m_lpszSongComments = new char[blocklen];
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen);
- m_lpszSongComments[blocklen-1] = 0;
- }
- }
- break;
- // PA: Pattern Data
- case 0x4150:
- npatterns = lpStream[dwMemPos];
- if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
- dwPos = dwMemPos + 1;
- for (i=0; i<npatterns; i++)
- {
- if (dwPos+18 >= dwMemLength) break;
- pmpd = (MDLPATTERNDATA *)(lpStream + dwPos);
- if (pmpd->channels > 32) break;
- PatternSize[i] = pmpd->lastrow+1;
- if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels;
- dwPos += 18 + 2*pmpd->channels;
- for (j=0; j<pmpd->channels; j++)
- {
- patterntracks[i*32+j] = pmpd->data[j];
- }
- }
- break;
- // TR: Track Data
- case 0x5254:
- if (dwTrackPos) break;
- ntracks = *((WORD *)(lpStream+dwMemPos));
- dwTrackPos = dwMemPos+2;
- break;
- // II: Instruments
- case 0x4949:
- ninstruments = lpStream[dwMemPos];
- dwPos = dwMemPos+1;
- for (i=0; i<ninstruments; i++)
- {
- UINT nins = lpStream[dwPos];
- if ((nins >= MAX_INSTRUMENTS) || (!nins)) break;
- if (m_nInstruments < nins) m_nInstruments = nins;
- if (!Headers[nins])
- {
- UINT note = 12;
- if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break;
- INSTRUMENTHEADER *penv = Headers[nins];
- memset(penv, 0, sizeof(INSTRUMENTHEADER));
- memcpy(penv->name, lpStream+dwPos+2, 32);
- penv->nGlobalVol = 64;
- penv->nPPC = 5*12;
- for (j=0; j<lpStream[dwPos+1]; j++)
- {
- const BYTE *ps = lpStream+dwPos+34+14*j;
- while ((note < (UINT)(ps[1]+12)) && (note < 120))
- {
- penv->NoteMap[note] = note+1;
- if (ps[0] < MAX_SAMPLES)
- {
- int ismp = ps[0];
- penv->Keyboard[note] = ps[0];
- Ins[ismp].nVolume = ps[2];
- Ins[ismp].nPan = ps[4] << 1;
- Ins[ismp].nVibType = ps[11];
- Ins[ismp].nVibSweep = ps[10];
- Ins[ismp].nVibDepth = ps[9];
- Ins[ismp].nVibRate = ps[8];
- }
- penv->nFadeOut = (ps[7] << 8) | ps[6];
- if (penv->nFadeOut == 0xFFFF) penv->nFadeOut = 0;
- note++;
- }
- // Use volume envelope ?
- if (ps[3] & 0x80)
- {
- penv->dwFlags |= ENV_VOLUME;
- insvolenv[nins] = (ps[3] & 0x3F) + 1;
- }
- // Use panning envelope ?
- if (ps[5] & 0x80)
- {
- penv->dwFlags |= ENV_PANNING;
- inspanenv[nins] = (ps[5] & 0x3F) + 1;
- }
- }
- }
- dwPos += 34 + 14*lpStream[dwPos+1];
- }
- for (j=1; j<=m_nInstruments; j++) if (!Headers[j])
- {
- Headers[j] = new INSTRUMENTHEADER;
- if (Headers[j]) memset(Headers[j], 0, sizeof(INSTRUMENTHEADER));
- }
- break;
- // VE: Volume Envelope
- case 0x4556:
- if ((nvolenv = lpStream[dwMemPos]) == 0) break;
- if (dwMemPos + nvolenv*32 + 1 <= dwMemLength) pvolenv = lpStream + dwMemPos + 1;
- break;
- // PE: Panning Envelope
- case 0x4550:
- if ((npanenv = lpStream[dwMemPos]) == 0) break;
- if (dwMemPos + npanenv*32 + 1 <= dwMemLength) ppanenv = lpStream + dwMemPos + 1;
- break;
- // FE: Pitch Envelope
- case 0x4546:
- if ((npitchenv = lpStream[dwMemPos]) == 0) break;
- if (dwMemPos + npitchenv*32 + 1 <= dwMemLength) ppitchenv = lpStream + dwMemPos + 1;
- break;
- // IS: Sample Infoblock
- case 0x5349:
- nsamples = lpStream[dwMemPos];
- dwPos = dwMemPos+1;
- for (i=0; i<nsamples; i++, dwPos += 59)
- {
- UINT nins = lpStream[dwPos];
- if ((nins >= MAX_SAMPLES) || (!nins)) continue;
- if (m_nSamples < nins) m_nSamples = nins;
- MODINSTRUMENT *pins = &Ins[nins];
- memcpy(m_szNames[nins], lpStream+dwPos+1, 32);
- memcpy(pins->name, lpStream+dwPos+33, 8);
- pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41));
- pins->nLength = *((DWORD *)(lpStream+dwPos+45));
- pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49));
- pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53));
- if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP;
- pins->nGlobalVol = 64;
- if (lpStream[dwPos+58] & 0x01)
- {
- pins->uFlags |= CHN_16BIT;
- pins->nLength >>= 1;
- pins->nLoopStart >>= 1;
- pins->nLoopEnd >>= 1;
- }
- if (lpStream[dwPos+58] & 0x02) pins->uFlags |= CHN_PINGPONGLOOP;
- smpinfo[nins] = (lpStream[dwPos+58] >> 2) & 3;
- }
- break;
- // SA: Sample Data
- case 0x4153:
- dwPos = dwMemPos;
- for (i=1; i<=m_nSamples; i++) if ((Ins[i].nLength) && (!Ins[i].pSample) && (smpinfo[i] != 3) && (dwPos < dwMemLength))
- {
- MODINSTRUMENT *pins = &Ins[i];
- UINT flags = (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
- if (!smpinfo[i])
- {
- dwPos += ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwMemLength - dwPos);
- } else
- {
- DWORD dwLen = *((DWORD *)(lpStream+dwPos));
- dwPos += 4;
- if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4))
- {
- flags = (pins->uFlags & CHN_16BIT) ? RS_MDL16 : RS_MDL8;
- ReadSample(pins, flags, (LPSTR)(lpStream+dwPos), dwLen);
- }
- dwPos += dwLen;
- }
- }
- break;
- }
- dwMemPos += blocklen;
- }
- // Unpack Patterns
- if ((dwTrackPos) && (npatterns) && (m_nChannels) && (ntracks))
- {
- for (UINT ipat=0; ipat<npatterns; ipat++)
- {
- if ((Patterns[ipat] = AllocatePattern(PatternSize[ipat], m_nChannels)) == NULL) break;
- for (UINT chn=0; chn<m_nChannels; chn++) if ((patterntracks[ipat*32+chn]) && (patterntracks[ipat*32+chn] <= ntracks))
- {
- MODCOMMAND *m = Patterns[ipat] + chn;
- UnpackMDLTrack(m, m_nChannels, PatternSize[ipat], patterntracks[ipat*32+chn], lpStream+dwTrackPos);
- }
- }
- }
- // Set up envelopes
- for (UINT iIns=1; iIns<=m_nInstruments; iIns++) if (Headers[iIns])
- {
- INSTRUMENTHEADER *penv = Headers[iIns];
- // Setup volume envelope
- if ((nvolenv) && (pvolenv) && (insvolenv[iIns]))
- {
- LPCBYTE pve = pvolenv;
- for (UINT nve=0; nve<nvolenv; nve++, pve+=33) if (pve[0]+1 == insvolenv[iIns])
- {
- WORD vtick = 1;
- penv->nVolEnv = 15;
- for (UINT iv=0; iv<15; iv++)
- {
- if (iv) vtick += pve[iv*2+1];
- penv->VolPoints[iv] = vtick;
- penv->VolEnv[iv] = pve[iv*2+2];
- if (!pve[iv*2+1])
- {
- penv->nVolEnv = iv+1;
- break;
- }
- }
- penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F;
- if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP;
- penv->nVolLoopStart = pve[32] & 0x0F;
- penv->nVolLoopEnd = pve[32] >> 4;
- }
- }
- // Setup panning envelope
- if ((npanenv) && (ppanenv) && (inspanenv[iIns]))
- {
- LPCBYTE ppe = ppanenv;
- for (UINT npe=0; npe<npanenv; npe++, ppe+=33) if (ppe[0]+1 == inspanenv[iIns])
- {
- WORD vtick = 1;
- penv->nPanEnv = 15;
- for (UINT iv=0; iv<15; iv++)
- {
- if (iv) vtick += ppe[iv*2+1];
- penv->PanPoints[iv] = vtick;
- penv->PanEnv[iv] = ppe[iv*2+2];
- if (!ppe[iv*2+1])
- {
- penv->nPanEnv = iv+1;
- break;
- }
- }
- if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN;
- if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP;
- penv->nPanLoopStart = ppe[32] & 0x0F;
- penv->nPanLoopEnd = ppe[32] >> 4;
- }
- }
- }
- m_dwSongFlags |= SONG_LINEARSLIDES;
- m_nType = MOD_TYPE_MDL;
- return TRUE;
-}
-
-
-/////////////////////////////////////////////////////////////////////////
-// MDL Sample Unpacking
-
-// MDL Huffman ReadBits compression
-WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
-//-----------------------------------------------------------------
-{
- WORD v = (WORD)(bitbuf & ((1 << n) - 1) );
- bitbuf >>= n;
- bitnum -= n;
- if (bitnum <= 24)
- {
- bitbuf |= (((DWORD)(*ibuf++)) << bitnum);
- bitnum += 8;
- }
- return v;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#define MED_LOG
-
-#ifdef MED_LOG
-extern void Log(LPCSTR s, ...);
-#endif
-
-//////////////////////////////////////////////////////////
-// OctaMed MED file support (import only)
-
-// flags
-#define MMD_FLAG_FILTERON 0x1
-#define MMD_FLAG_JUMPINGON 0x2
-#define MMD_FLAG_JUMP8TH 0x4
-#define MMD_FLAG_INSTRSATT 0x8 // instruments are attached (this is a module)
-#define MMD_FLAG_VOLHEX 0x10
-#define MMD_FLAG_STSLIDE 0x20 // SoundTracker mode for slides
-#define MMD_FLAG_8CHANNEL 0x40 // OctaMED 8 channel song
-#define MMD_FLAG_SLOWHQ 0x80 // HQ slows playing speed (V2-V4 compatibility)
-// flags2
-#define MMD_FLAG2_BMASK 0x1F
-#define MMD_FLAG2_BPM 0x20
-#define MMD_FLAG2_MIX 0x80 // uses Mixing (V7+)
-// flags3:
-#define MMD_FLAG3_STEREO 0x1 // mixing in Stereo mode
-#define MMD_FLAG3_FREEPAN 0x2 // free panning
-#define MMD_FLAG3_GM 0x4 // module designed for GM/XG compatibility
-
-
-// generic MMD tags
-#define MMDTAG_END 0
-#define MMDTAG_PTR 0x80000000 // data needs relocation
-#define MMDTAG_MUSTKNOW 0x40000000 // loader must fail if this isn't recognized
-#define MMDTAG_MUSTWARN 0x20000000 // loader must warn if this isn't recognized
-
-// ExpData tags
-// # of effect groups, including the global group (will
-// override settings in MMDSong struct), default = 1
-#define MMDTAG_EXP_NUMFXGROUPS 1
-#define MMDTAG_TRK_NAME (MMDTAG_PTR|1) // trackinfo tags
-#define MMDTAG_TRK_NAMELEN 2 // namelen includes zero term.
-#define MMDTAG_TRK_FXGROUP 3
-// effectinfo tags
-#define MMDTAG_FX_ECHOTYPE 1
-#define MMDTAG_FX_ECHOLEN 2
-#define MMDTAG_FX_ECHODEPTH 3
-#define MMDTAG_FX_STEREOSEP 4
-#define MMDTAG_FX_GROUPNAME (MMDTAG_PTR|5) // the Global Effects group shouldn't have name saved!
-#define MMDTAG_FX_GRPNAMELEN 6 // namelen includes zero term.
-
-#pragma pack(1)
-
-typedef struct tagMEDMODULEHEADER
-{
- DWORD id; // MMD1-MMD3
- DWORD modlen; // Size of file
- DWORD song; // Position in file for this song
- WORD psecnum;
- WORD pseq;
- DWORD blockarr; // Position in file for blocks
- DWORD mmdflags;
- DWORD smplarr; // Position in file for samples
- DWORD reserved;
- DWORD expdata; // Absolute offset in file for ExpData (0 if not present)
- DWORD reserved2;
- WORD pstate;
- WORD pblock;
- WORD pline;
- WORD pseqnum;
- WORD actplayline;
- BYTE counter;
- BYTE extra_songs; // # of songs - 1
-} MEDMODULEHEADER;
-
-
-typedef struct tagMMD0SAMPLE
-{
- WORD rep, replen;
- BYTE midich;
- BYTE midipreset;
- BYTE svol;
- signed char strans;
-} MMD0SAMPLE;
-
-
-// Sample header is immediately followed by sample data...
-typedef struct tagMMDSAMPLEHEADER
-{
- DWORD length; // length of *one* *unpacked* channel in *bytes*
- WORD type;
- // if non-negative
- // bits 0-3 reserved for multi-octave instruments, not supported on the PC
- // 0x10: 16 bit (otherwise 8 bit)
- // 0x20: Stereo (otherwise mono)
- // 0x40: Uses DeltaCode
- // 0x80: Packed data
- // -1: Synth
- // -2: Hybrid
- // if type indicates packed data, these fields follow, otherwise we go right to the data
- WORD packtype; // Only 1 = ADPCM is supported
- WORD subtype; // Packing subtype
- // ADPCM subtype
- // 1: g723_40
- // 2: g721
- // 3: g723_24
- BYTE commonflags; // flags common to all packtypes (none defined so far)
- BYTE packerflags; // flags for the specific packtype
- ULONG leftchlen; // packed length of left channel in bytes
- ULONG rightchlen; // packed length of right channel in bytes (ONLY PRESENT IN STEREO SAMPLES)
- BYTE SampleData[1]; // Sample Data
-} MMDSAMPLEHEADER;
-
-
-// MMD0/MMD1 song header
-typedef struct tagMMD0SONGHEADER
-{
- MMD0SAMPLE sample[63];
- WORD numblocks; // # of blocks
- WORD songlen; // # of entries used in playseq
- BYTE playseq[256]; // Play sequence
- WORD deftempo; // BPM tempo
- signed char playtransp; // Play transpose
- BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song
- BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on
- BYTE tempo2; // tempo TPL
- BYTE trkvol[16]; // track volumes
- BYTE mastervol; // master volume
- BYTE numsamples; // # of samples (max=63)
-} MMD0SONGHEADER;
-
-
-// MMD2/MMD3 song header
-typedef struct tagMMD2SONGHEADER
-{
- MMD0SAMPLE sample[63];
- WORD numblocks; // # of blocks
- WORD numsections; // # of sections
- DWORD playseqtable; // filepos of play sequence
- DWORD sectiontable; // filepos of sections table (WORD array)
- DWORD trackvols; // filepos of tracks volume (BYTE array)
- WORD numtracks; // # of tracks (max 64)
- WORD numpseqs; // # of play sequences
- DWORD trackpans; // filepos of tracks pan values (BYTE array)
- LONG flags3; // 0x1:stereo_mix, 0x2:free_panning, 0x4:GM/XG compatibility
- WORD voladj; // vol_adjust (set to 100 if 0)
- WORD channels; // # of channels (4 if =0)
- BYTE mix_echotype; // 1:normal,2:xecho
- BYTE mix_echodepth; // 1..6
- WORD mix_echolen; // > 0
- signed char mix_stereosep; // -4..4
- BYTE pad0[223];
- WORD deftempo; // BPM tempo
- signed char playtransp; // play transpose
- BYTE flags; // 0x1:filteron, 0x2:jumpingon, 0x4:jump8th, 0x8:instr_attached, 0x10:hex_vol, 0x20:PT_slides, 0x40:8ch_conv,0x80:hq slows playing speed
- BYTE flags2; // 0x80:mix_conv=on, [b4-b0]+1:tempo LPB, 0x20:tempo_mode
- BYTE tempo2; // tempo TPL
- BYTE pad1[16];
- BYTE mastervol; // master volume
- BYTE numsamples; // # of samples (max 63)
-} MMD2SONGHEADER;
-
-// For MMD0 the note information is held in 3 bytes, byte0, byte1, byte2. For reference we
-// number the bits in each byte 0..7, where 0 is the low bit.
-// The note is held as bits 5..0 of byte0
-// The instrument is encoded in 6 bits, bits 7 and 6 of byte0 and bits 7,6,5,4 of byte1
-// The command number is bits 3,2,1,0 of byte1, command data is in byte2:
-// For command 0, byte2 represents the second data byte, otherwise byte2
-// represents the first data byte.
-typedef struct tagMMD0BLOCK
-{
- BYTE numtracks;
- BYTE lines; // File value is 1 less than actual, so 0 -> 1 line
-} MMD0BLOCK; // BYTE data[lines+1][tracks][3];
-
-
-// For MMD1,MMD2,MMD3 the note information is carried in 4 bytes, byte0, byte1,
-// byte2 and byte3
-// The note is held as byte0 (values above 0x84 are ignored)
-// The instrument is held as byte1
-// The command number is held as byte2, command data is in byte3
-// For commands 0 and 0x19 byte3 represents the second data byte,
-// otherwise byte2 represents the first data byte.
-typedef struct tagMMD1BLOCK
-{
- WORD numtracks; // Number of tracks, may be > 64, but then that data is skipped.
- WORD lines; // Stored value is 1 less than actual, so 0 -> 1 line
- DWORD info; // Offset of BlockInfo (if 0, no block_info is present)
-} MMD1BLOCK;
-
-
-typedef struct tagMMD1BLOCKINFO
-{
- DWORD hlmask; // Unimplemented - ignore
- DWORD blockname; // file offset of block name
- DWORD blocknamelen; // length of block name (including term. 0)
- DWORD pagetable; // file offset of command page table
- DWORD cmdexttable; // file offset of command extension table
- DWORD reserved[4]; // future expansion
-} MMD1BLOCKINFO;
-
-
-// A set of play sequences is stored as an array of ULONG files offsets
-// Each offset points to the play sequence itself.
-typedef struct tagMMD2PLAYSEQ
-{
- CHAR name[32];
- DWORD command_offs; // filepos of command table
- DWORD reserved;
- WORD length;
- WORD seq[512]; // skip if > 0x8000
-} MMD2PLAYSEQ;
-
-
-// A command table contains commands that effect a particular play sequence
-// entry. The only commands read in are STOP or POSJUMP, all others are ignored
-// POSJUMP is presumed to have extra bytes containing a WORD for the position
-typedef struct tagMMDCOMMAND
-{
- WORD offset; // Offset within current sequence entry
- BYTE cmdnumber; // STOP (537) or POSJUMP (538) (others skipped)
- BYTE extra_count;
- BYTE extra_bytes[4];// [extra_count];
-} MMDCOMMAND; // Last entry has offset == 0xFFFF, cmd_number == 0 and 0 extrabytes
-
-
-typedef struct tagMMD0EXP
-{
- DWORD nextmod; // File offset of next Hdr
- DWORD exp_smp; // Pointer to extra instrument data
- WORD s_ext_entries; // Number of extra instrument entries
- WORD s_ext_entrsz; // Size of extra instrument data
- DWORD annotxt;
- DWORD annolen;
- DWORD iinfo; // Instrument names
- WORD i_ext_entries;
- WORD i_ext_entrsz;
- DWORD jumpmask;
- DWORD rgbtable;
- BYTE channelsplit[4]; // Only used if 8ch_conv (extra channel for every nonzero entry)
- DWORD n_info;
- DWORD songname; // Song name
- DWORD songnamelen;
- DWORD dumps;
- DWORD mmdinfo;
- DWORD mmdrexx;
- DWORD mmdcmd3x;
- DWORD trackinfo_ofs; // ptr to song->numtracks ptrs to tag lists
- DWORD effectinfo_ofs; // ptr to group ptrs
- DWORD tag_end;
-} MMD0EXP;
-
-#pragma pack()
-
-
-
-static void MedConvert(MODCOMMAND *p, const MMD0SONGHEADER *pmsh)
-//---------------------------------------------------------------
-{
- const BYTE bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
-
- UINT command = p->command;
- UINT param = p->param;
- switch(command)
- {
- case 0x00: if (param) command = CMD_ARPEGGIO; else command = 0; break;
- case 0x01: command = CMD_PORTAMENTOUP; break;
- case 0x02: command = CMD_PORTAMENTODOWN; break;
- case 0x03: command = CMD_TONEPORTAMENTO; break;
- case 0x04: command = CMD_VIBRATO; break;
- case 0x05: command = CMD_TONEPORTAVOL; break;
- case 0x06: command = CMD_VIBRATOVOL; break;
- case 0x07: command = CMD_TREMOLO; break;
- case 0x0A: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
- case 0x0B: command = CMD_POSITIONJUMP; break;
- case 0x0C: command = CMD_VOLUME;
- if (pmsh->flags & MMD_FLAG_VOLHEX)
- {
- if (param < 0x80)
- {
- param = (param+1) / 2;
- } else command = 0;
- } else
- {
- if (param <= 0x99)
- {
- param = (param >> 4)*10+((param & 0x0F) % 10);
- if (param > 64) param = 64;
- } else command = 0;
- }
- break;
- case 0x09: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
- case 0x0D: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
- case 0x0F: // Set Tempo / Special
- // F.00 = Pattern Break
- if (!param) command = CMD_PATTERNBREAK; else
- // F.01 - F.F0: Set tempo/speed
- if (param <= 0xF0)
- {
- if (pmsh->flags & MMD_FLAG_8CHANNEL)
- {
- param = (param > 10) ? 99 : bpmvals[param-1];
- } else
- // F.01 - F.0A: Set Speed
- if (param <= 0x0A)
- {
- command = CMD_SPEED;
- } else
- // Old tempo
- if (!(pmsh->flags2 & MMD_FLAG2_BPM))
- {
- param = _muldiv(param, 5*715909, 2*474326);
- }
- // F.0B - F.F0: Set Tempo (assumes LPB=4)
- if (param > 0x0A)
- {
- command = CMD_TEMPO;
- if (param < 0x21) param = 0x21;
- if (param > 240) param = 240;
- }
- } else
- switch(param)
- {
- // F.F1: Retrig 2x
- case 0xF1:
- command = CMD_MODCMDEX;
- param = 0x93;
- break;
- // F.F2: Note Delay 2x
- case 0xF2:
- command = CMD_MODCMDEX;
- param = 0xD3;
- break;
- // F.F3: Retrig 3x
- case 0xF3:
- command = CMD_MODCMDEX;
- param = 0x92;
- break;
- // F.F4: Note Delay 1/3
- case 0xF4:
- command = CMD_MODCMDEX;
- param = 0xD2;
- break;
- // F.F5: Note Delay 2/3
- case 0xF5:
- command = CMD_MODCMDEX;
- param = 0xD4;
- break;
- // F.F8: Filter Off
- case 0xF8:
- command = CMD_MODCMDEX;
- param = 0x00;
- break;
- // F.F9: Filter On
- case 0xF9:
- command = CMD_MODCMDEX;
- param = 0x01;
- break;
- // F.FD: Very fast tone-portamento
- case 0xFD:
- command = CMD_TONEPORTAMENTO;
- param = 0xFF;
- break;
- // F.FE: End Song
- case 0xFE:
- command = CMD_SPEED;
- param = 0;
- break;
- // F.FF: Note Cut
- case 0xFF:
- command = CMD_MODCMDEX;
- param = 0xC0;
- break;
- default:
-#ifdef MED_LOG
- Log("Unknown Fxx command: cmd=0x%02X param=0x%02X\n", command, param);
-#endif
- param = command = 0;
- }
- break;
- // 11.0x: Fine Slide Up
- case 0x11:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0x10;
- break;
- // 12.0x: Fine Slide Down
- case 0x12:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0x20;
- break;
- // 14.xx: Vibrato
- case 0x14:
- command = CMD_VIBRATO;
- break;
- // 15.xx: FineTune
- case 0x15:
- command = CMD_MODCMDEX;
- param &= 0x0F;
- param |= 0x50;
- break;
- // 16.xx: Pattern Loop
- case 0x16:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0x60;
- break;
- // 18.xx: Note Cut
- case 0x18:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0xC0;
- break;
- // 19.xx: Sample Offset
- case 0x19:
- command = CMD_OFFSET;
- break;
- // 1A.0x: Fine Volume Up
- case 0x1A:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0xA0;
- break;
- // 1B.0x: Fine Volume Down
- case 0x1B:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0xB0;
- break;
- // 1D.xx: Pattern Break
- case 0x1D:
- command = CMD_PATTERNBREAK;
- break;
- // 1E.0x: Pattern Delay
- case 0x1E:
- command = CMD_MODCMDEX;
- if (param > 0x0F) param = 0x0F;
- param |= 0xE0;
- break;
- // 1F.xy: Retrig
- case 0x1F:
- command = CMD_RETRIG;
- param &= 0x0F;
- break;
- // 2E.xx: set panning
- case 0x2E:
- command = CMD_MODCMDEX;
- param = ((param + 0x10) & 0xFF) >> 1;
- if (param > 0x0F) param = 0x0F;
- param |= 0x80;
- break;
- default:
-#ifdef MED_LOG
- // 0x2E ?
- Log("Unknown command: cmd=0x%02X param=0x%02X\n", command, param);
-#endif
- command = param = 0;
- }
- p->command = command;
- p->param = param;
-}
-
-
-BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- const MEDMODULEHEADER *pmmh;
- const MMD0SONGHEADER *pmsh;
- const MMD2SONGHEADER *pmsh2;
- const MMD0EXP *pmex;
- DWORD dwBlockArr, dwSmplArr, dwExpData, wNumBlocks;
- LPDWORD pdwTable;
- CHAR version;
- UINT deftempo;
- int playtransp = 0;
-
- if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
- pmmh = (MEDMODULEHEADER *)lpStream;
- if (((pmmh->id & 0x00FFFFFF) != 0x444D4D) || (!pmmh->song)) return FALSE;
- // Check for 'MMDx'
- DWORD dwSong = bswapBE32(pmmh->song);
- if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE;
- version = (signed char)((pmmh->id >> 24) & 0xFF);
- if ((version < '0') || (version > '3')) return FALSE;
-#ifdef MED_LOG
- Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, bswapBE32(pmmh->mmdflags));
- Log(" modlen = %d\n", bswapBE32(pmmh->modlen));
- Log(" song = 0x%08X\n", bswapBE32(pmmh->song));
- Log(" psecnum = %d\n", bswapBE16(pmmh->psecnum));
- Log(" pseq = %d\n", bswapBE16(pmmh->pseq));
- Log(" blockarr = 0x%08X\n", bswapBE32(pmmh->blockarr));
- Log(" mmdflags = 0x%08X\n", bswapBE32(pmmh->mmdflags));
- Log(" smplarr = 0x%08X\n", bswapBE32(pmmh->smplarr));
- Log(" reserved = 0x%08X\n", bswapBE32(pmmh->reserved));
- Log(" expdata = 0x%08X\n", bswapBE32(pmmh->expdata));
- Log(" reserved2= 0x%08X\n", bswapBE32(pmmh->reserved2));
- Log(" pstate = %d\n", bswapBE16(pmmh->pstate));
- Log(" pblock = %d\n", bswapBE16(pmmh->pblock));
- Log(" pline = %d\n", bswapBE16(pmmh->pline));
- Log(" pseqnum = %d\n", bswapBE16(pmmh->pseqnum));
- Log(" actplayline=%d\n", bswapBE16(pmmh->actplayline));
- Log(" counter = %d\n", pmmh->counter);
- Log(" extra_songs = %d\n", pmmh->extra_songs);
- Log("\n");
-#endif
- m_nType = MOD_TYPE_MED;
- m_nSongPreAmp = 0x20;
- dwBlockArr = bswapBE32(pmmh->blockarr);
- dwSmplArr = bswapBE32(pmmh->smplarr);
- dwExpData = bswapBE32(pmmh->expdata);
- if ((dwExpData) && (dwExpData+sizeof(MMD0EXP) < dwMemLength))
- pmex = (MMD0EXP *)(lpStream+dwExpData);
- else
- pmex = NULL;
- pmsh = (MMD0SONGHEADER *)(lpStream + dwSong);
- pmsh2 = (MMD2SONGHEADER *)pmsh;
-#ifdef MED_LOG
- if (version < '2')
- {
- Log("MMD0 Header:\n");
- Log(" numblocks = %d\n", bswapBE16(pmsh->numblocks));
- Log(" songlen = %d\n", bswapBE16(pmsh->songlen));
- Log(" playseq = ");
- for (UINT idbg1=0; idbg1<16; idbg1++) Log("%2d, ", pmsh->playseq[idbg1]);
- Log("...\n");
- Log(" deftempo = 0x%04X\n", bswapBE16(pmsh->deftempo));
- Log(" playtransp = %d\n", (signed char)pmsh->playtransp);
- Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh->flags, pmsh->flags2);
- Log(" tempo2 = %d\n", pmsh->tempo2);
- Log(" trkvol = ");
- for (UINT idbg2=0; idbg2<16; idbg2++) Log("0x%02X, ", pmsh->trkvol[idbg2]);
- Log("...\n");
- Log(" mastervol = 0x%02X\n", pmsh->mastervol);
- Log(" numsamples = %d\n", pmsh->numsamples);
- } else
- {
- Log("MMD2 Header:\n");
- Log(" numblocks = %d\n", bswapBE16(pmsh2->numblocks));
- Log(" numsections= %d\n", bswapBE16(pmsh2->numsections));
- Log(" playseqptr = 0x%04X\n", bswapBE32(pmsh2->playseqtable));
- Log(" sectionptr = 0x%04X\n", bswapBE32(pmsh2->sectiontable));
- Log(" trackvols = 0x%04X\n", bswapBE32(pmsh2->trackvols));
- Log(" numtracks = %d\n", bswapBE16(pmsh2->numtracks));
- Log(" numpseqs = %d\n", bswapBE16(pmsh2->numpseqs));
- Log(" trackpans = 0x%04X\n", bswapBE32(pmsh2->trackpans));
- Log(" flags3 = 0x%08X\n", bswapBE32(pmsh2->flags3));
- Log(" voladj = %d\n", bswapBE16(pmsh2->voladj));
- Log(" channels = %d\n", bswapBE16(pmsh2->channels));
- Log(" echotype = %d\n", pmsh2->mix_echotype);
- Log(" echodepth = %d\n", pmsh2->mix_echodepth);
- Log(" echolen = %d\n", bswapBE16(pmsh2->mix_echolen));
- Log(" stereosep = %d\n", (signed char)pmsh2->mix_stereosep);
- Log(" deftempo = 0x%04X\n", bswapBE16(pmsh2->deftempo));
- Log(" playtransp = %d\n", (signed char)pmsh2->playtransp);
- Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh2->flags, pmsh2->flags2);
- Log(" tempo2 = %d\n", pmsh2->tempo2);
- Log(" mastervol = 0x%02X\n", pmsh2->mastervol);
- Log(" numsamples = %d\n", pmsh->numsamples);
- }
- Log("\n");
-#endif
- wNumBlocks = bswapBE16(pmsh->numblocks);
- m_nChannels = 4;
- m_nSamples = pmsh->numsamples;
- if (m_nSamples > 63) m_nSamples = 63;
- // Tempo
- m_nDefaultTempo = 125;
- deftempo = bswapBE16(pmsh->deftempo);
- if (!deftempo) deftempo = 125;
- if (pmsh->flags2 & MMD_FLAG2_BPM)
- {
- UINT tempo_tpl = (pmsh->flags2 & MMD_FLAG2_BMASK) + 1;
- if (!tempo_tpl) tempo_tpl = 4;
- deftempo *= tempo_tpl;
- deftempo /= 4;
- #ifdef MED_LOG
- Log("newtempo: %3d bpm (bpm=%3d lpb=%2d)\n", deftempo, bswapBE16(pmsh->deftempo), (pmsh->flags2 & MMD_FLAG2_BMASK)+1);
- #endif
- } else
- {
- deftempo = _muldiv(deftempo, 5*715909, 2*474326);
- #ifdef MED_LOG
- Log("oldtempo: %3d bpm (bpm=%3d)\n", deftempo, bswapBE16(pmsh->deftempo));
- #endif
- }
- // Speed
- m_nDefaultSpeed = pmsh->tempo2;
- if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
- if (deftempo < 0x21) deftempo = 0x21;
- if (deftempo > 255)
- {
- while ((m_nDefaultSpeed > 3) && (deftempo > 260))
- {
- deftempo = (deftempo * (m_nDefaultSpeed - 1)) / m_nDefaultSpeed;
- m_nDefaultSpeed--;
- }
- if (deftempo > 255) deftempo = 255;
- }
- m_nDefaultTempo = deftempo;
- // Reading Samples
- for (UINT iSHdr=0; iSHdr<m_nSamples; iSHdr++)
- {
- MODINSTRUMENT *pins = &Ins[iSHdr+1];
- pins->nLoopStart = bswapBE16(pmsh->sample[iSHdr].rep) << 1;
- pins->nLoopEnd = pins->nLoopStart + (bswapBE16(pmsh->sample[iSHdr].replen) << 1);
- pins->nVolume = (pmsh->sample[iSHdr].svol << 2);
- pins->nGlobalVol = 64;
- if (pins->nVolume > 256) pins->nVolume = 256;
- pins->RelativeTone = -12 * pmsh->sample[iSHdr].strans;
- pins->nPan = 128;
- if (pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
- }
- // Common Flags
- if (!(pmsh->flags & 0x20)) m_dwSongFlags |= SONG_FASTVOLSLIDES;
- // Reading play sequence
- if (version < '2')
- {
- UINT nbo = pmsh->songlen >> 8;
- if (nbo >= MAX_ORDERS) nbo = MAX_ORDERS-1;
- if (!nbo) nbo = 1;
- memcpy(Order, pmsh->playseq, nbo);
- playtransp = pmsh->playtransp;
- } else
- {
- UINT nOrders, nSections;
- UINT nTrks = bswapBE16(pmsh2->numtracks);
- if ((nTrks >= 4) && (nTrks <= 32)) m_nChannels = nTrks;
- DWORD playseqtable = bswapBE32(pmsh2->playseqtable);
- UINT numplayseqs = bswapBE16(pmsh2->numpseqs);
- if (!numplayseqs) numplayseqs = 1;
- nOrders = 0;
- nSections = bswapBE16(pmsh2->numsections);
- DWORD sectiontable = bswapBE32(pmsh2->sectiontable);
- if ((!nSections) || (!sectiontable) || (sectiontable >= dwMemLength-2)) nSections = 1;
- nOrders = 0;
- for (UINT iSection=0; iSection<nSections; iSection++)
- {
- UINT nplayseq = 0;
- if ((sectiontable) && (sectiontable < dwMemLength-2))
- {
- nplayseq = lpStream[sectiontable+1];
- sectiontable += 2; // WORDs
- } else
- {
- nSections = 0;
- }
- UINT pseq = 0;
-
- if ((playseqtable) && (playseqtable + nplayseq*4 < dwMemLength))
- {
- pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]);
- }
- if ((pseq) && (pseq < dwMemLength - sizeof(MMD2PLAYSEQ)))
- {
- MMD2PLAYSEQ *pmps = (MMD2PLAYSEQ *)(lpStream + pseq);
- if (!m_szNames[0][0]) memcpy(m_szNames[0], pmps->name, 31);
- UINT n = bswapBE16(pmps->length);
- if (pseq+n <= dwMemLength)
- {
- for (UINT i=0; i<n; i++)
- {
- UINT seqval = pmps->seq[i] >> 8;
- if ((seqval < wNumBlocks) && (nOrders < MAX_ORDERS-1))
- {
- Order[nOrders++] = seqval;
- }
- }
- }
- }
- }
- playtransp = pmsh2->playtransp;
- while (nOrders < MAX_ORDERS) Order[nOrders++] = 0xFF;
- }
- // Reading Expansion structure
- if (pmex)
- {
- // Channel Split
- if ((m_nChannels == 4) && (pmsh->flags & 0x40))
- {
- for (UINT i8ch=0; i8ch<4; i8ch++)
- {
- if (pmex->channelsplit[i8ch]) m_nChannels++;
- }
- }
- // Song Comments
- UINT annotxt = bswapBE32(pmex->annotxt);
- UINT annolen = bswapBE32(pmex->annolen);
- if ((annotxt) && (annolen) && (annotxt+annolen <= dwMemLength))
- {
- m_lpszSongComments = new char[annolen+1];
- memcpy(m_lpszSongComments, lpStream+annotxt, annolen);
- m_lpszSongComments[annolen] = 0;
- }
- // Song Name
- UINT songname = bswapBE32(pmex->songname);
- UINT songnamelen = bswapBE32(pmex->songnamelen);
- if ((songname) && (songnamelen) && (songname+songnamelen <= dwMemLength))
- {
- if (songnamelen > 31) songnamelen = 31;
- memcpy(m_szNames[0], lpStream+songname, songnamelen);
- }
- // Sample Names
- DWORD smpinfoex = bswapBE32(pmex->iinfo);
- if (smpinfoex)
- {
- DWORD iinfoptr = bswapBE32(pmex->iinfo);
- UINT ientries = bswapBE16(pmex->i_ext_entries);
- UINT ientrysz = bswapBE16(pmex->i_ext_entrsz);
-
- if ((iinfoptr) && (ientrysz < 256) && (iinfoptr + ientries*ientrysz < dwMemLength))
- {
- LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr);
- UINT maxnamelen = ientrysz;
- if (maxnamelen > 32) maxnamelen = 32;
- for (UINT i=0; i<ientries; i++) if (i < m_nSamples)
- {
- lstrcpyn(m_szNames[i+1], psznames + i*ientrysz, maxnamelen);
- }
- }
- }
- // Track Names
- DWORD trackinfo_ofs = bswapBE32(pmex->trackinfo_ofs);
- if ((trackinfo_ofs) && (trackinfo_ofs + m_nChannels * 4 < dwMemLength))
- {
- DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs);
- for (UINT i=0; i<m_nChannels; i++)
- {
- DWORD trknameofs = 0, trknamelen = 0;
- DWORD trktagofs = bswapBE32(ptrktags[i]);
- if (trktagofs)
- {
- while (trktagofs+8 < dwMemLength)
- {
- DWORD ntag = bswapBE32(*(DWORD *)(lpStream + trktagofs));
- if (ntag == MMDTAG_END) break;
- DWORD tagdata = bswapBE32(*(DWORD *)(lpStream + trktagofs + 4));
- switch(ntag)
- {
- case MMDTAG_TRK_NAMELEN: trknamelen = tagdata; break;
- case MMDTAG_TRK_NAME: trknameofs = tagdata; break;
- }
- trktagofs += 8;
- }
- if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME;
- if ((trknameofs) && (trknameofs + trknamelen < dwMemLength))
- {
- lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME);
- }
- }
- }
- }
- }
- // Reading samples
- if (dwSmplArr > dwMemLength - 4*m_nSamples) return TRUE;
- pdwTable = (LPDWORD)(lpStream + dwSmplArr);
- for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (pdwTable[iSmp])
- {
- UINT dwPos = bswapBE32(pdwTable[iSmp]);
- if ((dwPos >= dwMemLength) || (dwPos + sizeof(MMDSAMPLEHEADER) >= dwMemLength)) continue;
- MMDSAMPLEHEADER *psdh = (MMDSAMPLEHEADER *)(lpStream + dwPos);
- UINT len = bswapBE32(psdh->length);
- #ifdef MED_LOG
- Log("SampleData %d: stype=0x%02X len=%d\n", iSmp, bswapBE16(psdh->type), len);
- #endif
- if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0;
- UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type);
- LPSTR psdata = (LPSTR)(lpStream + dwPos + 6);
- if (stype & 0x80)
- {
- psdata += (stype & 0x20) ? 14 : 6;
- } else
- {
- if (stype & 0x10)
- {
- Ins[iSmp+1].uFlags |= CHN_16BIT;
- len /= 2;
- flags = (stype & 0x20) ? RS_STPCM16M : RS_PCM16M;
- } else
- {
- flags = (stype & 0x20) ? RS_STPCM8S : RS_PCM8S;
- }
- if (stype & 0x20) len /= 2;
- }
- Ins[iSmp+1].nLength = len;
- ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6);
- }
- // Reading patterns (blocks)
- if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS;
- if ((!dwBlockArr) || (dwBlockArr > dwMemLength - 4*wNumBlocks)) return TRUE;
- pdwTable = (LPDWORD)(lpStream + dwBlockArr);
- playtransp += (version == '3') ? 24 : 48;
- for (UINT iBlk=0; iBlk<wNumBlocks; iBlk++)
- {
- UINT dwPos = bswapBE32(pdwTable[iBlk]);
- if ((!dwPos) || (dwPos >= dwMemLength) || (dwPos >= dwMemLength - 8)) continue;
- UINT lines = 64, tracks = 4;
- if (version == '0')
- {
- const MMD0BLOCK *pmb = (const MMD0BLOCK *)(lpStream + dwPos);
- lines = pmb->lines + 1;
- tracks = pmb->numtracks;
- if (!tracks) tracks = m_nChannels;
- if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
- PatternSize[iBlk] = lines;
- MODCOMMAND *p = Patterns[iBlk];
- LPBYTE s = (LPBYTE)(lpStream + dwPos + 2);
- UINT maxlen = tracks*lines*3;
- if (maxlen + dwPos > dwMemLength - 2) break;
- for (UINT y=0; y<lines; y++)
- {
- for (UINT x=0; x<tracks; x++, s+=3) if (x < m_nChannels)
- {
- BYTE note = s[0] & 0x3F;
- BYTE instr = s[1] >> 4;
- if (s[0] & 0x80) instr |= 0x10;
- if (s[0] & 0x40) instr |= 0x20;
- if ((note) && (note <= 132)) p->note = note + playtransp;
- p->instr = instr;
- p->command = s[1] & 0x0F;
- p->param = s[2];
- // if (!iBlk) Log("%02X.%02X.%02X | ", s[0], s[1], s[2]);
- MedConvert(p, pmsh);
- p++;
- }
- //if (!iBlk) Log("\n");
- }
- } else
- {
- MMD1BLOCK *pmb = (MMD1BLOCK *)(lpStream + dwPos);
- #ifdef MED_LOG
- Log("MMD1BLOCK: lines=%2d, tracks=%2d, offset=0x%04X\n",
- bswapBE16(pmb->lines), bswapBE16(pmb->numtracks), bswapBE32(pmb->info));
- #endif
- MMD1BLOCKINFO *pbi = NULL;
- BYTE *pcmdext = NULL;
- lines = (pmb->lines >> 8) + 1;
- tracks = pmb->numtracks >> 8;
- if (!tracks) tracks = m_nChannels;
- if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
- PatternSize[iBlk] = (WORD)lines;
- DWORD dwBlockInfo = bswapBE32(pmb->info);
- if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO)))
- {
- pbi = (MMD1BLOCKINFO *)(lpStream + dwBlockInfo);
- #ifdef MED_LOG
- Log(" BLOCKINFO: blockname=0x%04X namelen=%d pagetable=0x%04X &cmdexttable=0x%04X\n",
- bswapBE32(pbi->blockname), bswapBE32(pbi->blocknamelen), bswapBE32(pbi->pagetable), bswapBE32(pbi->cmdexttable));
- #endif
- if ((pbi->blockname) && (pbi->blocknamelen))
- {
- DWORD nameofs = bswapBE32(pbi->blockname);
- UINT namelen = bswapBE32(pbi->blocknamelen);
- if ((nameofs < dwMemLength) && (nameofs+namelen < dwMemLength))
- {
- SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs));
- }
- }
- if (pbi->cmdexttable)
- {
- DWORD cmdexttable = bswapBE32(pbi->cmdexttable);
- if (cmdexttable < dwMemLength - 4)
- {
- cmdexttable = bswapBE32(*(DWORD *)(lpStream + cmdexttable));
- if ((cmdexttable) && (cmdexttable <= dwMemLength - lines*tracks))
- {
- pcmdext = (BYTE *)(lpStream + cmdexttable);
- }
- }
- }
- }
- MODCOMMAND *p = Patterns[iBlk];
- LPBYTE s = (LPBYTE)(lpStream + dwPos + 8);
- UINT maxlen = tracks*lines*4;
- if (maxlen + dwPos > dwMemLength - 8) break;
- for (UINT y=0; y<lines; y++)
- {
- for (UINT x=0; x<tracks; x++, s+=4) if (x < m_nChannels)
- {
- BYTE note = s[0];
- if ((note) && (note <= 132))
- {
- int rnote = note + playtransp;
- if (rnote < 1) rnote = 1;
- if (rnote > 120) rnote = 120;
- p->note = (BYTE)rnote;
- }
- p->instr = s[1];
- p->command = s[2];
- p->param = s[3];
- if (pcmdext) p->vol = pcmdext[x];
- MedConvert(p, pmsh);
- p++;
- }
- if (pcmdext) pcmdext += tracks;
- }
- }
- }
- // Setup channel pan positions
- for (UINT iCh=0; iCh<m_nChannels; iCh++)
- {
- ChnSettings[iCh].nPan = (((iCh&3) == 1) || ((iCh&3) == 2)) ? 0xC0 : 0x40;
- ChnSettings[iCh].nVolume = 64;
- }
- return TRUE;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-extern WORD ProTrackerPeriodTable[6*12];
-
-//////////////////////////////////////////////////////////
-// ProTracker / NoiseTracker MOD/NST file support
-
-void CSoundFile::ConvertModCommand(MODCOMMAND *m) const
-//-----------------------------------------------------
-{
- UINT command = m->command, param = m->param;
-
- switch(command)
- {
- case 0x00: if (param) command = CMD_ARPEGGIO; break;
- case 0x01: command = CMD_PORTAMENTOUP; break;
- case 0x02: command = CMD_PORTAMENTODOWN; break;
- case 0x03: command = CMD_TONEPORTAMENTO; break;
- case 0x04: command = CMD_VIBRATO; break;
- case 0x05: command = CMD_TONEPORTAVOL; if (param & 0xF0) param &= 0xF0; break;
- case 0x06: command = CMD_VIBRATOVOL; if (param & 0xF0) param &= 0xF0; break;
- case 0x07: command = CMD_TREMOLO; break;
- case 0x08: command = CMD_PANNING8; break;
- case 0x09: command = CMD_OFFSET; break;
- case 0x0A: command = CMD_VOLUMESLIDE; if (param & 0xF0) param &= 0xF0; break;
- case 0x0B: command = CMD_POSITIONJUMP; break;
- case 0x0C: command = CMD_VOLUME; break;
- case 0x0D: command = CMD_PATTERNBREAK; param = ((param >> 4) * 10) + (param & 0x0F); break;
- case 0x0E: command = CMD_MODCMDEX; break;
- case 0x0F: command = (param <= (UINT)((m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? 0x1F : 0x20)) ? CMD_SPEED : CMD_TEMPO;
- if ((param == 0xFF) && (m_nSamples == 15)) command = 0; break;
- // Extension for XM extended effects
- case 'G' - 55: command = CMD_GLOBALVOLUME; break;
- case 'H' - 55: command = CMD_GLOBALVOLSLIDE; if (param & 0xF0) param &= 0xF0; break;
- case 'K' - 55: command = CMD_KEYOFF; break;
- case 'L' - 55: command = CMD_SETENVPOSITION; break;
- case 'M' - 55: command = CMD_CHANNELVOLUME; break;
- case 'N' - 55: command = CMD_CHANNELVOLSLIDE; break;
- case 'P' - 55: command = CMD_PANNINGSLIDE; if (param & 0xF0) param &= 0xF0; break;
- case 'R' - 55: command = CMD_RETRIG; break;
- case 'T' - 55: command = CMD_TREMOR; break;
- case 'X' - 55: command = CMD_XFINEPORTAUPDOWN; break;
- case 'Y' - 55: command = CMD_PANBRELLO; break;
- case 'Z' - 55: command = CMD_MIDI; break;
- default: command = 0;
- }
- m->command = command;
- m->param = param;
-}
-
-
-WORD CSoundFile::ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const
-//------------------------------------------------------------------
-{
- UINT command = m->command & 0x3F, param = m->param;
-
- switch(command)
- {
- case 0: command = param = 0; break;
- case CMD_ARPEGGIO: command = 0; break;
- case CMD_PORTAMENTOUP:
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
- {
- if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x10; break; }
- else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x10; break; }
- }
- command = 0x01;
- break;
- case CMD_PORTAMENTODOWN:
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
- {
- if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x20; break; }
- else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x20; break; }
- }
- command = 0x02;
- break;
- case CMD_TONEPORTAMENTO: command = 0x03; break;
- case CMD_VIBRATO: command = 0x04; break;
- case CMD_TONEPORTAVOL: command = 0x05; break;
- case CMD_VIBRATOVOL: command = 0x06; break;
- case CMD_TREMOLO: command = 0x07; break;
- case CMD_PANNING8:
- command = 0x08;
- if (bXM)
- {
- if ((m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM) && (param <= 0x80))
- {
- param <<= 1;
- if (param > 255) param = 255;
- }
- } else
- {
- if ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM)) param >>= 1;
- }
- break;
- case CMD_OFFSET: command = 0x09; break;
- case CMD_VOLUMESLIDE: command = 0x0A; break;
- case CMD_POSITIONJUMP: command = 0x0B; break;
- case CMD_VOLUME: command = 0x0C; break;
- case CMD_PATTERNBREAK: command = 0x0D; param = ((param / 10) << 4) | (param % 10); break;
- case CMD_MODCMDEX: command = 0x0E; break;
- case CMD_SPEED: command = 0x0F; if (param > 0x20) param = 0x20; break;
- case CMD_TEMPO: if (param > 0x20) { command = 0x0F; break; }
- case CMD_GLOBALVOLUME: command = 'G' - 55; break;
- case CMD_GLOBALVOLSLIDE: command = 'H' - 55; break;
- case CMD_KEYOFF: command = 'K' - 55; break;
- case CMD_SETENVPOSITION: command = 'L' - 55; break;
- case CMD_CHANNELVOLUME: command = 'M' - 55; break;
- case CMD_CHANNELVOLSLIDE: command = 'N' - 55; break;
- case CMD_PANNINGSLIDE: command = 'P' - 55; break;
- case CMD_RETRIG: command = 'R' - 55; break;
- case CMD_TREMOR: command = 'T' - 55; break;
- case CMD_XFINEPORTAUPDOWN: command = 'X' - 55; break;
- case CMD_PANBRELLO: command = 'Y' - 55; break;
- case CMD_MIDI: command = 'Z' - 55; break;
- case CMD_S3MCMDEX:
- switch(param & 0xF0)
- {
- case 0x10: command = 0x0E; param = (param & 0x0F) | 0x30; break;
- case 0x20: command = 0x0E; param = (param & 0x0F) | 0x50; break;
- case 0x30: command = 0x0E; param = (param & 0x0F) | 0x40; break;
- case 0x40: command = 0x0E; param = (param & 0x0F) | 0x70; break;
- case 0x90: command = 'X' - 55; break;
- case 0xB0: command = 0x0E; param = (param & 0x0F) | 0x60; break;
- case 0xA0:
- case 0x50:
- case 0x70:
- case 0x60: command = param = 0; break;
- default: command = 0x0E; break;
- }
- break;
- default: command = param = 0;
- }
- return (WORD)((command << 8) | (param));
-}
-
-
-#pragma pack(1)
-
-typedef struct _MODSAMPLE
-{
- CHAR name[22];
- WORD length;
- BYTE finetune;
- BYTE volume;
- WORD loopstart;
- WORD looplen;
-} MODSAMPLE, *PMODSAMPLE;
-
-typedef struct _MODMAGIC
-{
- BYTE nOrders;
- BYTE nRestartPos;
- BYTE Orders[128];
- char Magic[4]; // changed from CHAR
-} MODMAGIC, *PMODMAGIC;
-
-#pragma pack()
-
-BOOL IsMagic(LPCSTR s1, LPCSTR s2)
-{
- return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE;
-}
-
-
-BOOL CSoundFile::ReadMod(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- char s[1024]; // changed from CHAR
- DWORD dwMemPos, dwTotalSampleLen;
- PMODMAGIC pMagic;
- UINT nErr;
-
- if ((!lpStream) || (dwMemLength < 0x600)) return FALSE;
- dwMemPos = 20;
- m_nSamples = 31;
- m_nChannels = 4;
- pMagic = (PMODMAGIC)(lpStream+dwMemPos+sizeof(MODSAMPLE)*31);
- // Check Mod Magic
- memcpy(s, pMagic->Magic, 4);
- if ((IsMagic(s, "M.K.")) || (IsMagic(s, "M!K!"))
- || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else
- if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else
- if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
- if ((s[0]>='4') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else
- if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else
- if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else
- if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else
- if ((s[0]=='T') && (s[1]=='D') && (s[2]=='Z') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
- if (IsMagic(s,"16CN")) m_nChannels = 16; else
- if (IsMagic(s,"32CN")) m_nChannels = 32; else m_nSamples = 15;
- // Load Samples
- nErr = 0;
- dwTotalSampleLen = 0;
- for (UINT i=1; i<=m_nSamples; i++)
- {
- PMODSAMPLE pms = (PMODSAMPLE)(lpStream+dwMemPos);
- MODINSTRUMENT *psmp = &Ins[i];
- UINT loopstart, looplen;
-
- memcpy(m_szNames[i], pms->name, 22);
- m_szNames[i][22] = 0;
- psmp->uFlags = 0;
- psmp->nLength = bswapBE16(pms->length)*2;
- dwTotalSampleLen += psmp->nLength;
- psmp->nFineTune = MOD2XMFineTune(pms->finetune & 0x0F);
- psmp->nVolume = 4*pms->volume;
- if (psmp->nVolume > 256) { psmp->nVolume = 256; nErr++; }
- psmp->nGlobalVol = 64;
- psmp->nPan = 128;
- loopstart = bswapBE16(pms->loopstart)*2;
- looplen = bswapBE16(pms->looplen)*2;
- // Fix loops
- if ((looplen > 2) && (loopstart+looplen > psmp->nLength)
- && (loopstart/2+looplen <= psmp->nLength))
- {
- loopstart /= 2;
- }
- psmp->nLoopStart = loopstart;
- psmp->nLoopEnd = loopstart + looplen;
- if (psmp->nLength < 4) psmp->nLength = 0;
- if (psmp->nLength)
- {
- UINT derr = 0;
- if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; }
- if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; }
- if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1;
- if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8)
- || (psmp->nLoopEnd - psmp->nLoopStart <= 4))
- {
- psmp->nLoopStart = 0;
- psmp->nLoopEnd = 0;
- }
- if (psmp->nLoopEnd > psmp->nLoopStart)
- {
- psmp->uFlags |= CHN_LOOP;
- }
- }
- dwMemPos += sizeof(MODSAMPLE);
- }
- if ((m_nSamples == 15) && (dwTotalSampleLen > dwMemLength * 4)) return FALSE;
- pMagic = (PMODMAGIC)(lpStream+dwMemPos);
- dwMemPos += sizeof(MODMAGIC);
- if (m_nSamples == 15) dwMemPos -= 4;
- memset(Order, 0,sizeof(Order));
- memcpy(Order, pMagic->Orders, 128);
-
- UINT nbp, nbpbuggy, nbpbuggy2, norders;
-
- norders = pMagic->nOrders;
- if ((!norders) || (norders > 0x80))
- {
- norders = 0x80;
- while ((norders > 1) && (!Order[norders-1])) norders--;
- }
- nbpbuggy = 0;
- nbpbuggy2 = 0;
- nbp = 0;
- for (UINT iord=0; iord<128; iord++)
- {
- UINT i = Order[iord];
- if ((i < 0x80) && (nbp <= i))
- {
- nbp = i+1;
- if (iord<norders) nbpbuggy = nbp;
- }
- if (i >= nbpbuggy2) nbpbuggy2 = i+1;
- }
- for (UINT iend=norders; iend<MAX_ORDERS; iend++) Order[iend] = 0xFF;
- norders--;
- m_nRestartPos = pMagic->nRestartPos;
- if (m_nRestartPos >= 0x78) m_nRestartPos = 0;
- if (m_nRestartPos + 1 >= (UINT)norders) m_nRestartPos = 0;
- if (!nbp) return FALSE;
- DWORD dwWowTest = dwTotalSampleLen+dwMemPos;
- if ((IsMagic(pMagic->Magic, "M.K.")) && (dwWowTest + nbp*8*256 == dwMemLength)) m_nChannels = 8;
- if ((nbp != nbpbuggy) && (dwWowTest + nbp*m_nChannels*256 != dwMemLength))
- {
- if (dwWowTest + nbpbuggy*m_nChannels*256 == dwMemLength) nbp = nbpbuggy;
- else nErr += 8;
- } else
- if ((nbpbuggy2 > nbp) && (dwWowTest + nbpbuggy2*m_nChannels*256 == dwMemLength))
- {
- nbp = nbpbuggy2;
- }
- if ((dwWowTest < 0x600) || (dwWowTest > dwMemLength)) nErr += 8;
- if ((m_nSamples == 15) && (nErr >= 16)) return FALSE;
- // Default settings
- m_nType = MOD_TYPE_MOD;
- m_nDefaultSpeed = 6;
- m_nDefaultTempo = 125;
- m_nMinPeriod = 14 << 2;
- m_nMaxPeriod = 3424 << 2;
- memcpy(m_szNames, lpStream, 20);
- // Setting channels pan
- for (UINT ich=0; ich<m_nChannels; ich++)
- {
- ChnSettings[ich].nVolume = 64;
- if (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN)
- ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0;
- else
- ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 0xC0 : 0x40;
- }
- // Reading channels
- for (UINT ipat=0; ipat<nbp; ipat++)
- {
- if (ipat < MAX_PATTERNS)
- {
- if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break;
- PatternSize[ipat] = 64;
- if (dwMemPos + m_nChannels*256 >= dwMemLength) break;
- MODCOMMAND *m = Patterns[ipat];
- LPCBYTE p = lpStream + dwMemPos;
- for (UINT j=m_nChannels*64; j; m++,p+=4,j--)
- {
- BYTE A0=p[0], A1=p[1], A2=p[2], A3=p[3];
- UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1));
- if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2);
- m->instr = ((UINT)A2 >> 4) | (A0 & 0x10);
- m->command = A2 & 0x0F;
- m->param = A3;
- if ((m->command) || (m->param)) ConvertModCommand(m);
- }
- }
- dwMemPos += m_nChannels*256;
- }
- // Reading instruments
- DWORD dwErrCheck = 0;
- for (UINT ismp=1; ismp<=m_nSamples; ismp++) if (Ins[ismp].nLength)
- {
- LPSTR p = (LPSTR)(lpStream+dwMemPos);
- UINT flags = 0;
- if (dwMemPos + 5 >= dwMemLength) break;
- if (!strnicmp(p, "ADPCM", 5))
- {
- flags = 3;
- p += 5;
- dwMemPos += 5;
- }
- DWORD dwSize = ReadSample(&Ins[ismp], flags, p, dwMemLength - dwMemPos);
- if (dwSize)
- {
- dwMemPos += dwSize;
- dwErrCheck++;
- }
- }
-#ifdef MODPLUG_TRACKER
- return TRUE;
-#else
- return (dwErrCheck) ? TRUE : FALSE;
-#endif
-}
-
-
-#ifndef MODPLUG_NO_FILESAVE
-#pragma warning(disable:4100)
-
-BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking)
-//----------------------------------------------------------
-{
- BYTE insmap[32];
- UINT inslen[32];
- BYTE bTab[32];
- BYTE ord[128];
- FILE *f;
-
- if ((!m_nChannels) || (!lpszFileName)) return FALSE;
- if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
- memset(ord, 0, sizeof(ord));
- memset(inslen, 0, sizeof(inslen));
- if (m_nInstruments)
- {
- memset(insmap, 0, sizeof(insmap));
- for (UINT i=1; i<32; i++) if (Headers[i])
- {
- for (UINT j=0; j<128; j++) if (Headers[i]->Keyboard[j])
- {
- insmap[i] = Headers[i]->Keyboard[j];
- break;
- }
- }
- } else
- {
- for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i;
- }
- // Writing song name
- fwrite(m_szNames, 20, 1, f);
- // Writing instrument definition
- for (UINT iins=1; iins<=31; iins++)
- {
- MODINSTRUMENT *pins = &Ins[insmap[iins]];
- memcpy(bTab, m_szNames[iins],22);
- inslen[iins] = pins->nLength;
- if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0;
- bTab[22] = inslen[iins] >> 9;
- bTab[23] = inslen[iins] >> 1;
- if (pins->RelativeTone < 0) bTab[24] = 0x08; else
- if (pins->RelativeTone > 0) bTab[24] = 0x07; else
- bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune);
- bTab[25] = pins->nVolume >> 2;
- bTab[26] = pins->nLoopStart >> 9;
- bTab[27] = pins->nLoopStart >> 1;
- bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9;
- bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1;
- fwrite(bTab, 30, 1, f);
- }
- // Writing number of patterns
- UINT nbp=0, norders=128;
- for (UINT iord=0; iord<128; iord++)
- {
- if (Order[iord] == 0xFF)
- {
- norders = iord;
- break;
- }
- if ((Order[iord] < 0x80) && (nbp<=Order[iord])) nbp = Order[iord]+1;
- }
- bTab[0] = norders;
- bTab[1] = m_nRestartPos;
- fwrite(bTab, 2, 1, f);
- // Writing pattern list
- if (norders) memcpy(ord, Order, norders);
- fwrite(ord, 128, 1, f);
- // Writing signature
- if (m_nChannels == 4)
- lstrcpy((LPSTR)&bTab, "M.K.");
- else
- wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels);
- fwrite(bTab, 4, 1, f);
- // Writing patterns
- for (UINT ipat=0; ipat<nbp; ipat++) if (Patterns[ipat])
- {
- BYTE s[64*4];
- MODCOMMAND *m = Patterns[ipat];
- for (UINT i=0; i<64; i++) if (i < PatternSize[ipat])
- {
- LPBYTE p=s;
- for (UINT c=0; c<m_nChannels; c++,p+=4,m++)
- {
- UINT param = ModSaveCommand(m, FALSE);
- UINT command = param >> 8;
- param &= 0xFF;
- if (command > 0x0F) command = param = 0;
- if ((m->vol >= 0x10) && (m->vol <= 0x50) && (!command) && (!param)) { command = 0x0C; param = m->vol - 0x10; }
- UINT period = m->note;
- if (period)
- {
- if (period < 37) period = 37;
- period -= 37;
- if (period >= 6*12) period = 6*12-1;
- period = ProTrackerPeriodTable[period];
- }
- UINT instr = (m->instr > 31) ? 0 : m->instr;
- p[0] = ((period >> 8) & 0x0F) | (instr & 0x10);
- p[1] = period & 0xFF;
- p[2] = ((instr & 0x0F) << 4) | (command & 0x0F);
- p[3] = param;
- }
- fwrite(s, m_nChannels, 4, f);
- } else
- {
- memset(s, 0, m_nChannels*4);
- fwrite(s, m_nChannels, 4, f);
- }
- }
- // Writing instruments
- for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd])
- {
- MODINSTRUMENT *pins = &Ins[insmap[ismpd]];
- UINT flags = RS_PCM8S;
-#ifndef NO_PACKING
- if (!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
- {
- if ((nPacking) && (CanPackSample(pins->pSample, inslen[ismpd], nPacking)))
- {
- fwrite("ADPCM", 1, 5, f);
- flags = RS_ADPCM4;
- }
- }
-#endif
- WriteSample(f, pins, flags, inslen[ismpd]);
- }
- fclose(f);
- return TRUE;
-}
-
-#pragma warning(default:4100)
-#endif // MODPLUG_NO_FILESAVE
+++ /dev/null
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#define MT2DEBUG
-
-#pragma pack(1)
-
-typedef struct _MT2FILEHEADER
-{
- DWORD dwMT20; // 0x3032544D "MT20"
- DWORD dwSpecial;
- WORD wVersion;
- CHAR szTrackerName[32]; // "MadTracker 2.0"
- CHAR szSongName[64];
- WORD nOrders;
- WORD wRestart;
- WORD wPatterns;
- WORD wChannels;
- WORD wSamplesPerTick;
- BYTE bTicksPerLine;
- BYTE bLinesPerBeat;
- DWORD fulFlags; // b0=packed patterns
- WORD wInstruments;
- WORD wSamples;
- BYTE Orders[256];
-} MT2FILEHEADER;
-
-typedef struct _MT2PATTERN
-{
- WORD wLines;
- DWORD wDataLen;
-} MT2PATTERN;
-
-typedef struct _MT2COMMAND
-{
- BYTE note; // 0=nothing, 97=note off
- BYTE instr;
- BYTE vol;
- BYTE pan;
- BYTE fxcmd;
- BYTE fxparam1;
- BYTE fxparam2;
-} MT2COMMAND;
-
-typedef struct _MT2DRUMSDATA
-{
- WORD wDrumPatterns;
- WORD wDrumSamples[8];
- BYTE DrumPatternOrder[256];
-} MT2DRUMSDATA;
-
-typedef struct _MT2AUTOMATION
-{
- DWORD dwFlags;
- DWORD dwEffectId;
- DWORD nEnvPoints;
-} MT2AUTOMATION;
-
-typedef struct _MT2INSTRUMENT
-{
- CHAR szName[32];
- DWORD dwDataLen;
- WORD wSamples;
- BYTE GroupsMapping[96];
- BYTE bVibType;
- BYTE bVibSweep;
- BYTE bVibDepth;
- BYTE bVibRate;
- WORD wFadeOut;
- WORD wNNA;
- WORD wInstrFlags;
- WORD wEnvFlags1;
- WORD wEnvFlags2;
-} MT2INSTRUMENT;
-
-typedef struct _MT2ENVELOPE
-{
- BYTE nFlags;
- BYTE nPoints;
- BYTE nSustainPos;
- BYTE nLoopStart;
- BYTE nLoopEnd;
- BYTE bReserved[3];
- BYTE EnvData[64];
-} MT2ENVELOPE;
-
-typedef struct _MT2SYNTH
-{
- BYTE nSynthId;
- BYTE nFxId;
- WORD wCutOff;
- BYTE nResonance;
- BYTE nAttack;
- BYTE nDecay;
- BYTE bReserved[25];
-} MT2SYNTH;
-
-typedef struct _MT2SAMPLE
-{
- CHAR szName[32];
- DWORD dwDataLen;
- DWORD dwLength;
- DWORD dwFrequency;
- BYTE nQuality;
- BYTE nChannels;
- BYTE nFlags;
- BYTE nLoop;
- DWORD dwLoopStart;
- DWORD dwLoopEnd;
- WORD wVolume;
- BYTE nPan;
- BYTE nBaseNote;
- WORD wSamplesPerBeat;
-} MT2SAMPLE;
-
-typedef struct _MT2GROUP
-{
- BYTE nSmpNo;
- BYTE nVolume; // 0-128
- BYTE nFinePitch;
- BYTE Reserved[5];
-} MT2GROUP;
-
-#pragma pack()
-
-
-static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, MT2COMMAND *p)
-//---------------------------------------------------------------------------
-{
- // Note
- m->note = 0;
- if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12;
- // Instrument
- m->instr = p->instr;
- // Volume Column
- if ((p->vol >= 0x10) && (p->vol <= 0x90))
- {
- m->volcmd = VOLCMD_VOLUME;
- m->vol = (p->vol - 0x10) >> 1;
- } else
- if ((p->vol >= 0xA0) && (p->vol <= 0xAF))
- {
- m->volcmd = VOLCMD_VOLSLIDEDOWN;
- m->vol = (p->vol & 0x0f);
- } else
- if ((p->vol >= 0xB0) && (p->vol <= 0xBF))
- {
- m->volcmd = VOLCMD_VOLSLIDEUP;
- m->vol = (p->vol & 0x0f);
- } else
- if ((p->vol >= 0xC0) && (p->vol <= 0xCF))
- {
- m->volcmd = VOLCMD_FINEVOLDOWN;
- m->vol = (p->vol & 0x0f);
- } else
- if ((p->vol >= 0xD0) && (p->vol <= 0xDF))
- {
- m->volcmd = VOLCMD_FINEVOLUP;
- m->vol = (p->vol & 0x0f);
- } else
- {
- m->volcmd = 0;
- m->vol = 0;
- }
- // Effects
- m->command = 0;
- m->param = 0;
- if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2))
- {
- if (!p->fxcmd)
- {
- m->command = p->fxparam2;
- m->param = p->fxparam1;
- that->ConvertModCommand(m);
- } else
- {
- // TODO: MT2 Effects
- }
- }
-}
-
-
-BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream;
- DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos;
- UINT nDrumDataLen, nExtraDataLen;
- MT2DRUMSDATA *pdd;
- MT2INSTRUMENT *InstrMap[255];
- MT2SAMPLE *SampleMap[256];
-
- if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER))
- || (pfh->dwMT20 != 0x3032544D)
- || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300)
- || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE;
- pdd = NULL;
- m_nType = MOD_TYPE_MT2;
- m_nChannels = pfh->wChannels;
- m_nRestartPos = pfh->wRestart;
- m_nDefaultSpeed = pfh->bTicksPerLine;
- m_nDefaultTempo = 125;
- if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000))
- {
- m_nDefaultTempo = 110250 / pfh->wSamplesPerTick;
- }
- for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
- {
- Order[iOrd] = (BYTE)((iOrd < pfh->nOrders) ? pfh->Orders[iOrd] : 0xFF);
- }
- memcpy(m_szNames[0], pfh->szSongName, 32);
- m_szNames[0][31] = 0;
- dwMemPos = sizeof(MT2FILEHEADER);
- nDrumDataLen = *(WORD *)(lpStream + dwMemPos);
- dwDrumDataPos = dwMemPos + 2;
- if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos);
- dwMemPos += 2 + nDrumDataLen;
-#ifdef MT2DEBUG
-
- Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags);
- Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples);
- Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos);
-#endif
- if (dwMemPos >= dwMemLength-12) return TRUE;
- if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
- if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
- nExtraDataLen = *(DWORD *)(lpStream+dwMemPos);
- dwExtraDataPos = dwMemPos + 4;
- dwMemPos += 4;
-#ifdef MT2DEBUG
- Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos);
-#endif
- if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE;
- while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen)
- {
- DWORD dwId = *(DWORD *)(lpStream+dwMemPos);
- DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4);
- dwMemPos += 8;
- if (dwMemPos + dwLen > dwMemLength) return TRUE;
-#ifdef MT2DEBUG
- CHAR s[5];
- memcpy(s, &dwId, 4);
- s[4] = 0;
- Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen);
-#endif
- switch(dwId)
- {
- // MSG
- case 0x0047534D:
- if ((dwLen > 3) && (!m_lpszSongComments))
- {
- DWORD nTxtLen = dwLen;
- if (nTxtLen > 32000) nTxtLen = 32000;
- m_lpszSongComments = new char[nTxtLen]; // changed from CHAR
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1);
- m_lpszSongComments[nTxtLen-1] = 0;
- }
- }
- break;
- // SUM -> author name (or "Unregistered")
- // TMAP
- // TRKS
- case 0x534b5254:
- break;
- }
- dwMemPos += dwLen;
- }
- // Load Patterns
- dwMemPos = dwExtraDataPos + nExtraDataLen;
- for (UINT iPat=0; iPat<pfh->wPatterns; iPat++) if (dwMemPos < dwMemLength-6)
- {
- MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos);
- UINT wDataLen = (pmp->wDataLen + 1) & ~1;
- dwMemPos += 6;
- if (dwMemPos + wDataLen > dwMemLength) break;
- UINT nLines = pmp->wLines;
- if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256))
- {
- #ifdef MT2DEBUG
- Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen);
- #endif
- PatternSize[iPat] = nLines;
- Patterns[iPat] = AllocatePattern(nLines, m_nChannels);
- if (!Patterns[iPat]) return TRUE;
- MODCOMMAND *m = Patterns[iPat];
- UINT len = wDataLen;
- if (pfh->fulFlags & 1) // Packed Patterns
- {
- BYTE *p = (BYTE *)(lpStream+dwMemPos);
- UINT pos = 0, row=0, ch=0;
- while (pos < len)
- {
- MT2COMMAND cmd;
- UINT infobyte = p[pos++];
- UINT rptcount = 0;
- if (infobyte == 0xff)
- {
- rptcount = p[pos++];
- infobyte = p[pos++];
- #if 0
- Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte);
- } else
- {
- Log("(%d.%d) %02X\n", row, ch, infobyte);
- #endif
- }
- if (infobyte & 0x7f)
- {
- UINT patpos = row*m_nChannels+ch;
- cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0;
- if (infobyte & 1) cmd.note = p[pos++];
- if (infobyte & 2) cmd.instr = p[pos++];
- if (infobyte & 4) cmd.vol = p[pos++];
- if (infobyte & 8) cmd.pan = p[pos++];
- if (infobyte & 16) cmd.fxcmd = p[pos++];
- if (infobyte & 32) cmd.fxparam1 = p[pos++];
- if (infobyte & 64) cmd.fxparam2 = p[pos++];
- #ifdef MT2DEBUG
- if (cmd.fxcmd)
- {
- Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2);
- }
- #endif
- ConvertMT2Command(this, &m[patpos], &cmd);
- }
- row += rptcount+1;
- while (row >= nLines) { row-=nLines; ch++; }
- if (ch >= m_nChannels) break;
- }
- } else
- {
- MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos);
- UINT n = 0;
- while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines))
- {
- ConvertMT2Command(this, m, p);
- len -= sizeof(MT2COMMAND);
- n++;
- p++;
- m++;
- }
- }
- }
- dwMemPos += wDataLen;
- }
- // Skip Drum Patterns
- if (pdd)
- {
- #ifdef MT2DEBUG
- Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos);
- #endif
- for (UINT iDrm=0; iDrm<pdd->wDrumPatterns; iDrm++)
- {
- if (dwMemPos > dwMemLength-2) return TRUE;
- UINT nLines = *(WORD *)(lpStream+dwMemPos);
- #ifdef MT2DEBUG
- if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos);
- #endif
- dwMemPos += 2 + nLines * 32;
- }
- }
- // Automation
- if (pfh->fulFlags & 2)
- {
- #ifdef MT2DEBUG
- Log("Automation at offset 0x%08X\n", dwMemPos);
- #endif
- UINT nAutoCount = m_nChannels;
- if (pfh->fulFlags & 0x10) nAutoCount++; // Master Automation
- if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8; // Drums Automation
- nAutoCount *= pfh->wPatterns;
- for (UINT iAuto=0; iAuto<nAutoCount; iAuto++)
- {
- if (dwMemPos+12 >= dwMemLength) return TRUE;
- MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos);
- dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8;
- for (UINT iEnv=0; iEnv<14; iEnv++)
- {
- if (pma->dwFlags & (1 << iEnv))
- {
- #ifdef MT2DEBUG
- UINT nPoints = *(DWORD *)(lpStream+dwMemPos);
- Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints);
- #endif
- dwMemPos += 260;
- }
- }
- }
- }
- // Load Instruments
-#ifdef MT2DEBUG
- Log("Loading instruments at offset 0x%08X\n", dwMemPos);
-#endif
- memset(InstrMap, 0, sizeof(InstrMap));
- m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1;
- for (UINT iIns=1; iIns<=255; iIns++)
- {
- if (dwMemPos+36 > dwMemLength) return TRUE;
- MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos);
- INSTRUMENTHEADER *penv = NULL;
- if (iIns <= m_nInstruments)
- {
- penv = new INSTRUMENTHEADER;
- Headers[iIns] = penv;
- if (penv)
- {
- memset(penv, 0, sizeof(INSTRUMENTHEADER));
- memcpy(penv->name, pmi->szName, 32);
- penv->nGlobalVol = 64;
- penv->nPan = 128;
- for (UINT i=0; i<120; i++)
- {
- penv->NoteMap[i] = i+1;
- }
- }
- }
- #ifdef MT2DEBUG
- if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen);
- #endif
- if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength))
- {
- InstrMap[iIns-1] = pmi;
- if (penv)
- {
- penv->nFadeOut = pmi->wFadeOut;
- penv->nNNA = pmi->wNNA & 3;
- penv->nDCT = (pmi->wNNA>>8) & 3;
- penv->nDNA = (pmi->wNNA>>12) & 3;
- MT2ENVELOPE *pehdr[4];
- WORD *pedata[4];
- if (pfh->wVersion <= 0x201)
- {
- DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4;
- pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
- pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8);
- pehdr[2] = pehdr[3] = NULL;
- pedata[0] = (WORD *)(lpStream+dwEnvPos+16);
- pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64);
- pedata[2] = pedata[3] = NULL;
- } else
- {
- DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT);
- for (UINT i=0; i<4; i++)
- {
- if (pmi->wEnvFlags1 & (1<<i))
- {
- pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
- pedata[i] = (WORD *)pehdr[i]->EnvData;
- dwEnvPos += sizeof(MT2ENVELOPE);
- } else
- {
- pehdr[i] = NULL;
- pedata[i] = NULL;
- }
- }
- }
- // Load envelopes
- for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv])
- {
- MT2ENVELOPE *pme = pehdr[iEnv];
- WORD *pEnvPoints = NULL;
- BYTE *pEnvData = NULL;
- #ifdef MT2DEBUG
- Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints);
- #endif
- switch(iEnv)
- {
- // Volume Envelope
- case 0:
- if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME;
- if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP;
- penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
- penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos;
- penv->nVolLoopStart = pme->nLoopStart;
- penv->nVolLoopEnd = pme->nLoopEnd;
- pEnvPoints = penv->VolPoints;
- pEnvData = penv->VolEnv;
- break;
-
- // Panning Envelope
- case 1:
- if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING;
- if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN;
- if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP;
- penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
- penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos;
- penv->nPanLoopStart = pme->nLoopStart;
- penv->nPanLoopEnd = pme->nLoopEnd;
- pEnvPoints = penv->PanPoints;
- pEnvData = penv->PanEnv;
- break;
-
- // Pitch/Filter envelope
- default:
- if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH;
- if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN;
- if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP;
- penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
- penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos;
- penv->nPitchLoopStart = pme->nLoopStart;
- penv->nPitchLoopEnd = pme->nLoopEnd;
- pEnvPoints = penv->PitchPoints;
- pEnvData = penv->PitchEnv;
- }
- // Envelope data
- if ((pEnvPoints) && (pEnvData) && (pedata[iEnv]))
- {
- WORD *psrc = pedata[iEnv];
- for (UINT i=0; i<16; i++)
- {
- pEnvPoints[i] = psrc[i*2];
- pEnvData[i] = (BYTE)psrc[i*2+1];
- }
- }
- }
- }
- dwMemPos += pmi->dwDataLen + 36;
- if (pfh->wVersion > 0x201) dwMemPos += 4; // ?
- } else
- {
- dwMemPos += 36;
- }
- }
-#ifdef MT2DEBUG
- Log("Loading samples at offset 0x%08X\n", dwMemPos);
-#endif
- memset(SampleMap, 0, sizeof(SampleMap));
- m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1;
- for (UINT iSmp=1; iSmp<=256; iSmp++)
- {
- if (dwMemPos+36 > dwMemLength) return TRUE;
- MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos);
- #ifdef MT2DEBUG
- if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen);
- #endif
- if (iSmp < MAX_SAMPLES)
- {
- memcpy(m_szNames[iSmp], pms->szName, 32);
- }
- if (pms->dwDataLen > 0)
- {
- SampleMap[iSmp-1] = pms;
- if (iSmp < MAX_SAMPLES)
- {
- MODINSTRUMENT *psmp = &Ins[iSmp];
- psmp->nGlobalVol = 64;
- psmp->nVolume = (pms->wVolume >> 7);
- psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80);
- psmp->nLength = pms->dwLength;
- psmp->nC4Speed = pms->dwFrequency;
- psmp->nLoopStart = pms->dwLoopStart;
- psmp->nLoopEnd = pms->dwLoopEnd;
- FrequencyToTranspose(psmp);
- psmp->RelativeTone -= pms->nBaseNote - 49;
- psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune);
- if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; }
- if (pms->nChannels == 2) { psmp->nLength >>= 1; }
- if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP;
- if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP;
- }
- dwMemPos += pms->dwDataLen + 36;
- } else
- {
- dwMemPos += 36;
- }
- }
-#ifdef MT2DEBUG
- Log("Loading groups at offset 0x%08X\n", dwMemPos);
-#endif
- for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap])
- {
- if (dwMemPos+8 > dwMemLength) return TRUE;
- MT2INSTRUMENT *pmi = InstrMap[iMap];
- INSTRUMENTHEADER *penv = NULL;
- if (iMap<m_nInstruments) penv = Headers[iMap+1];
- for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++)
- {
- if (penv)
- {
- MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos);
- for (UINT i=0; i<96; i++)
- {
- if (pmi->GroupsMapping[i] == iGrp)
- {
- UINT nSmp = pmg->nSmpNo+1;
- penv->Keyboard[i+12] = (BYTE)nSmp;
- if (nSmp <= m_nSamples)
- {
- Ins[nSmp].nVibType = pmi->bVibType;
- Ins[nSmp].nVibSweep = pmi->bVibSweep;
- Ins[nSmp].nVibDepth = pmi->bVibDepth;
- Ins[nSmp].nVibRate = pmi->bVibRate;
- }
- }
- }
- }
- dwMemPos += 8;
- }
- }
-#ifdef MT2DEBUG
- Log("Loading sample data at offset 0x%08X\n", dwMemPos);
-#endif
- for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData]))
- {
- MT2SAMPLE *pms = SampleMap[iData];
- MODINSTRUMENT *psmp = &Ins[iData+1];
- if (!(pms->nFlags & 5))
- {
- if (psmp->nLength > 0)
- {
- #ifdef MT2DEBUG
- Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength);
- #endif
- UINT rsflags;
-
- if (pms->nChannels == 2)
- rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
- else
- rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D;
-
- dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
- }
- } else
- if (dwMemPos+4 < dwMemLength)
- {
- UINT nNameLen = *(DWORD *)(lpStream+dwMemPos);
- dwMemPos += nNameLen + 16;
- }
- if (dwMemPos+4 >= dwMemLength) break;
- }
- return TRUE;
-}
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-//////////////////////////////////////////////////////////
-// MTM file support (import only)
-
-#pragma pack(1)
-
-
-typedef struct tagMTMSAMPLE
-{
- char samplename[22]; // changed from CHAR
- DWORD length;
- DWORD reppos;
- DWORD repend;
- CHAR finetune;
- BYTE volume;
- BYTE attribute;
-} MTMSAMPLE;
-
-
-typedef struct tagMTMHEADER
-{
- char id[4]; // MTM file marker + version // changed from CHAR
- char songname[20]; // ASCIIZ songname // changed from CHAR
- WORD numtracks; // number of tracks saved
- BYTE lastpattern; // last pattern number saved
- BYTE lastorder; // last order number to play (songlength-1)
- WORD commentsize; // length of comment field
- BYTE numsamples; // number of samples saved
- BYTE attribute; // attribute byte (unused)
- BYTE beatspertrack;
- BYTE numchannels; // number of channels used
- BYTE panpos[32]; // voice pan positions
-} MTMHEADER;
-
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadMTM(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- MTMHEADER *pmh = (MTMHEADER *)lpStream;
- DWORD dwMemPos = 66;
-
- if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
- if ((strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32)
- || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples)
- || (!pmh->numtracks) || (!pmh->numchannels)
- || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) return FALSE;
- strncpy(m_szNames[0], pmh->songname, 20);
- m_szNames[0][20] = 0;
- if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks
- + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) return FALSE;
- m_nType = MOD_TYPE_MTM;
- m_nSamples = pmh->numsamples;
- m_nChannels = pmh->numchannels;
- // Reading instruments
- for (UINT i=1; i<=m_nSamples; i++)
- {
- MTMSAMPLE *pms = (MTMSAMPLE *)(lpStream + dwMemPos);
- strncpy(m_szNames[i], pms->samplename, 22);
- m_szNames[i][22] = 0;
- Ins[i].nVolume = pms->volume << 2;
- Ins[i].nGlobalVol = 64;
- DWORD len = pms->length;
- if ((len > 4) && (len <= MAX_SAMPLE_LENGTH))
- {
- Ins[i].nLength = len;
- Ins[i].nLoopStart = pms->reppos;
- Ins[i].nLoopEnd = pms->repend;
- if (Ins[i].nLoopEnd > Ins[i].nLength) Ins[i].nLoopEnd = Ins[i].nLength;
- if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) Ins[i].nLoopStart = Ins[i].nLoopEnd = 0;
- if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP;
- Ins[i].nFineTune = MOD2XMFineTune(pms->finetune);
- if (pms->attribute & 0x01)
- {
- Ins[i].uFlags |= CHN_16BIT;
- Ins[i].nLength >>= 1;
- Ins[i].nLoopStart >>= 1;
- Ins[i].nLoopEnd >>= 1;
- }
- Ins[i].nPan = 128;
- }
- dwMemPos += 37;
- }
- // Setting Channel Pan Position
- for (UINT ich=0; ich<m_nChannels; ich++)
- {
- ChnSettings[ich].nPan = ((pmh->panpos[ich] & 0x0F) << 4) + 8;
- ChnSettings[ich].nVolume = 64;
- }
- // Reading pattern order
- memcpy(Order, lpStream + dwMemPos, pmh->lastorder+1);
- dwMemPos += 128;
- // Reading Patterns
- LPCBYTE pTracks = lpStream + dwMemPos;
- dwMemPos += 192 * pmh->numtracks;
- LPWORD pSeq = (LPWORD)(lpStream + dwMemPos);
- for (UINT pat=0; pat<=pmh->lastpattern; pat++)
- {
- PatternSize[pat] = 64;
- if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break;
- for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels))
- {
- LPCBYTE p = pTracks + 192 * (pSeq[n]-1);
- MODCOMMAND *m = Patterns[pat] + n;
- for (UINT i=0; i<64; i++, m+=m_nChannels, p+=3)
- {
- if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37;
- m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
- UINT cmd = p[1] & 0x0F;
- UINT param = p[2];
- if (cmd == 0x0A)
- {
- if (param & 0xF0) param &= 0xF0; else param &= 0x0F;
- }
- m->command = cmd;
- m->param = param;
- if ((cmd) || (param)) ConvertModCommand(m);
- }
- }
- pSeq += 32;
- }
- dwMemPos += 64*(pmh->lastpattern+1);
- if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength))
- {
- UINT n = pmh->commentsize;
- m_lpszSongComments = new char[n+1];
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos, n);
- m_lpszSongComments[n] = 0;
- for (UINT i=0; i<n; i++)
- {
- if (!m_lpszSongComments[i])
- {
- m_lpszSongComments[i] = ((i+1) % 40) ? 0x20 : 0x0D;
- }
- }
- }
- }
- dwMemPos += pmh->commentsize;
- // Reading Samples
- for (UINT ismp=1; ismp<=m_nSamples; ismp++)
- {
- if (dwMemPos >= dwMemLength) break;
- dwMemPos += ReadSample(&Ins[ismp], (Ins[ismp].uFlags & CHN_16BIT) ? RS_PCM16U : RS_PCM8U,
- (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
- }
- m_nMinPeriod = 64;
- m_nMaxPeriod = 32767;
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-//////////////////////////////////////////////
-// Oktalyzer (OKT) module loader //
-//////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-typedef struct OKTFILEHEADER
-{
- DWORD okta; // "OKTA"
- DWORD song; // "SONG"
- DWORD cmod; // "CMOD"
- DWORD fixed8;
- BYTE chnsetup[8];
- DWORD samp; // "SAMP"
- DWORD samplen;
-} OKTFILEHEADER;
-
-
-typedef struct OKTSAMPLE
-{
- CHAR name[20];
- DWORD length;
- WORD loopstart;
- WORD looplen;
- BYTE pad1;
- BYTE volume;
- BYTE pad2;
- BYTE pad3;
-} OKTSAMPLE;
-
-
-BOOL CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream;
- DWORD dwMemPos = sizeof(OKTFILEHEADER);
- UINT nsamples = 0, npatterns = 0, norders = 0;
-
- if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
- if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53)
- || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2])
- || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000)
- || (pfh->samp != 0x504D4153)) return FALSE;
- m_nType = MOD_TYPE_OKT;
- m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7];
- if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS;
- nsamples = bswapBE32(pfh->samplen) >> 5;
- m_nSamples = nsamples;
- if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
- // Reading samples
- for (UINT smp=1; smp <= nsamples; smp++)
- {
- if (dwMemPos >= dwMemLength) return TRUE;
- if (smp < MAX_SAMPLES)
- {
- OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos);
- MODINSTRUMENT *pins = &Ins[smp];
-
- memcpy(m_szNames[smp], psmp->name, 20);
- pins->uFlags = 0;
- pins->nLength = bswapBE32(psmp->length) & ~1;
- pins->nLoopStart = bswapBE16(psmp->loopstart);
- pins->nLoopEnd = pins->nLoopStart + bswapBE16(psmp->looplen);
- if (pins->nLoopStart + 2 < pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
- pins->nGlobalVol = 64;
- pins->nVolume = psmp->volume << 2;
- pins->nC4Speed = 8363;
- }
- dwMemPos += sizeof(OKTSAMPLE);
- }
- // SPEE
- if (dwMemPos >= dwMemLength) return TRUE;
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053)
- {
- m_nDefaultSpeed = lpStream[dwMemPos+9];
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- }
- // SLEN
- if (dwMemPos >= dwMemLength) return TRUE;
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53)
- {
- npatterns = lpStream[dwMemPos+9];
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- }
- // PLEN
- if (dwMemPos >= dwMemLength) return TRUE;
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50)
- {
- norders = lpStream[dwMemPos+9];
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- }
- // PATT
- if (dwMemPos >= dwMemLength) return TRUE;
- if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150)
- {
- UINT orderlen = norders;
- if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1;
- for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i];
- for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; }
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- }
- // PBOD
- UINT npat = 0;
- while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250))
- {
- DWORD dwPos = dwMemPos + 10;
- UINT rows = lpStream[dwMemPos+9];
- if (!rows) rows = 64;
- if (npat < MAX_PATTERNS)
- {
- if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
- MODCOMMAND *m = Patterns[npat];
- PatternSize[npat] = rows;
- UINT imax = m_nChannels*rows;
- for (UINT i=0; i<imax; i++, m++, dwPos+=4)
- {
- if (dwPos+4 > dwMemLength) break;
- const BYTE *p = lpStream+dwPos;
- UINT note = p[0];
- if (note)
- {
- m->note = note + 48;
- m->instr = p[1] + 1;
- }
- UINT command = p[2];
- UINT param = p[3];
- m->param = param;
- switch(command)
- {
- // 0: no effect
- case 0:
- break;
- // 1: Portamento Up
- case 1:
- case 17:
- case 30:
- if (param) m->command = CMD_PORTAMENTOUP;
- break;
- // 2: Portamento Down
- case 2:
- case 13:
- case 21:
- if (param) m->command = CMD_PORTAMENTODOWN;
- break;
- // 10: Arpeggio
- case 10:
- case 11:
- case 12:
- m->command = CMD_ARPEGGIO;
- break;
- // 15: Filter
- case 15:
- m->command = CMD_MODCMDEX;
- m->param = param & 0x0F;
- break;
- // 25: Position Jump
- case 25:
- m->command = CMD_POSITIONJUMP;
- break;
- // 28: Set Speed
- case 28:
- m->command = CMD_SPEED;
- break;
- // 31: Volume Control
- case 31:
- if (param <= 0x40) m->command = CMD_VOLUME; else
- if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else
- if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else
- if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else
- if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; }
- break;
- }
- }
- }
- npat++;
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- }
- // SBOD
- UINT nsmp = 1;
- while ((dwMemPos+10 < dwMemLength) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253))
- {
- if (nsmp < MAX_SAMPLES) ReadSample(&Ins[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8);
- dwMemPos += bswapBE32(*((DWORD *)(lpStream + dwMemPos + 4))) + 8;
- nsmp++;
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-
-///////////////////////////////////////////////////
-//
-// PSM module loader
-//
-///////////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#define PSM_LOG
-
-#define PSM_ID_NEW 0x204d5350
-#define PSM_ID_OLD 0xfe4d5350
-#define IFFID_FILE 0x454c4946
-#define IFFID_TITL 0x4c544954
-#define IFFID_SDFT 0x54464453
-#define IFFID_PBOD 0x444f4250
-#define IFFID_SONG 0x474e4f53
-#define IFFID_PATT 0x54544150
-#define IFFID_DSMP 0x504d5344
-#define IFFID_OPLH 0x484c504f
-
-#pragma pack(1)
-
-typedef struct _PSMCHUNK
-{
- DWORD id;
- DWORD len;
- DWORD listid;
-} PSMCHUNK;
-
-typedef struct _PSMSONGHDR
-{
- CHAR songname[8]; // "MAINSONG"
- BYTE reserved1;
- BYTE reserved2;
- BYTE channels;
-} PSMSONGHDR;
-
-typedef struct _PSMPATTERN
-{
- DWORD size;
- DWORD name;
- WORD rows;
- WORD reserved1;
- BYTE data[4];
-} PSMPATTERN;
-
-typedef struct _PSMSAMPLE
-{
- BYTE flags;
- CHAR songname[8];
- DWORD smpid;
- CHAR samplename[34];
- DWORD reserved1;
- BYTE reserved2;
- BYTE insno;
- BYTE reserved3;
- DWORD length;
- DWORD loopstart;
- DWORD loopend;
- WORD reserved4;
- BYTE defvol;
- DWORD reserved5;
- DWORD samplerate;
- BYTE reserved6[19];
-} PSMSAMPLE;
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
-{
- PSMCHUNK *pfh = (PSMCHUNK *)lpStream;
- DWORD dwMemPos, dwSongPos;
- DWORD smpnames[MAX_SAMPLES];
- DWORD patptrs[MAX_PATTERNS];
- BYTE samplemap[MAX_SAMPLES];
- UINT nPatterns;
-
- // Chunk0: "PSM ",filesize,"FILE"
- if (dwMemLength < 256) return FALSE;
- if (pfh->id == PSM_ID_OLD)
- {
- #ifdef PSM_LOG
- Log("Old PSM format not supported\n");
- #endif
- return FALSE;
- }
- if ((pfh->id != PSM_ID_NEW) || (pfh->len+12 > dwMemLength) || (pfh->listid != IFFID_FILE)) return FALSE;
- m_nType = MOD_TYPE_PSM;
- m_nChannels = 16;
- m_nSamples = 0;
- nPatterns = 0;
- dwMemPos = 12;
- dwSongPos = 0;
- for (UINT iChPan=0; iChPan<16; iChPan++)
- {
- UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40;
- ChnSettings[iChPan].nPan = pan;
- }
- while (dwMemPos+8 < dwMemLength)
- {
- PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
- if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break;
- dwMemPos += 8;
- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
- ULONG len = pchunk->len;
- if (len) switch(pchunk->id)
- {
- // "TITL": Song title
- case IFFID_TITL:
- if (!pdata[0]) { pdata++; len--; }
- memcpy(m_szNames[0], pdata, (len>31) ? 31 : len);
- m_szNames[0][31] = 0;
- break;
- // "PBOD": Pattern
- case IFFID_PBOD:
- if ((len >= 12) && (nPatterns < MAX_PATTERNS))
- {
- patptrs[nPatterns++] = dwMemPos-8;
- }
- break;
- // "SONG": Song description
- case IFFID_SONG:
- if ((len >= sizeof(PSMSONGHDR)+8) && (!dwSongPos))
- {
- dwSongPos = dwMemPos - 8;
- }
- break;
- // "DSMP": Sample Data
- case IFFID_DSMP:
- if ((len >= sizeof(PSMSAMPLE)) && (m_nSamples+1 < MAX_SAMPLES))
- {
- m_nSamples++;
- MODINSTRUMENT *pins = &Ins[m_nSamples];
- PSMSAMPLE *psmp = (PSMSAMPLE *)pdata;
- smpnames[m_nSamples] = psmp->smpid;
- memcpy(m_szNames[m_nSamples], psmp->samplename, 31);
- m_szNames[m_nSamples][31] = 0;
- samplemap[m_nSamples-1] = (BYTE)m_nSamples;
- // Init sample
- pins->nGlobalVol = 0x40;
- pins->nC4Speed = psmp->samplerate;
- pins->nLength = psmp->length;
- pins->nLoopStart = psmp->loopstart;
- pins->nLoopEnd = psmp->loopend;
- pins->nPan = 128;
- pins->nVolume = (psmp->defvol+1) * 2;
- pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0;
- if (pins->nLoopStart > 0) pins->nLoopStart--;
- // Point to sample data
- pdata += 0x60;
- len -= 0x60;
- // Load sample data
- if ((pins->nLength > 3) && (len > 3))
- {
- ReadSample(pins, RS_PCM8D, (LPCSTR)pdata, len);
- } else
- {
- pins->nLength = 0;
- }
- }
- break;
- #if 0
- default:
- {
- CHAR s[8], s2[64];
- *(DWORD *)s = pchunk->id;
- s[4] = 0;
- wsprintf(s2, "%s: %4d bytes @ %4d\n", s, pchunk->len, dwMemPos);
- OutputDebugString(s2);
- }
- #endif
- }
- dwMemPos += pchunk->len;
- }
- // Step #1: convert song structure
- PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8);
- if ((!dwSongPos) || (pSong->channels < 2) || (pSong->channels > 32)) return TRUE;
- m_nChannels = pSong->channels;
- // Valid song header -> convert attached chunks
- {
- DWORD dwSongEnd = dwSongPos + 8 + *(DWORD *)(lpStream+dwSongPos+4);
- dwMemPos = dwSongPos + 8 + 11; // sizeof(PSMCHUNK)+sizeof(PSMSONGHDR)
- while (dwMemPos + 8 < dwSongEnd)
- {
- PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
- dwMemPos += 8;
- if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break;
- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
- ULONG len = pchunk->len;
- switch(pchunk->id)
- {
- case IFFID_OPLH:
- if (len >= 0x20)
- {
- UINT pos = len - 3;
- while (pos > 5)
- {
- BOOL bFound = FALSE;
- pos -= 5;
- DWORD dwName = *(DWORD *)(pdata+pos);
- for (UINT i=0; i<nPatterns; i++)
- {
- DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name;
- if (dwName == dwPatName)
- {
- bFound = TRUE;
- break;
- }
- }
- if ((!bFound) && (pdata[pos+1] > 0) && (pdata[pos+1] <= 0x10)
- && (pdata[pos+3] > 0x40) && (pdata[pos+3] < 0xC0))
- {
- m_nDefaultSpeed = pdata[pos+1];
- m_nDefaultTempo = pdata[pos+3];
- break;
- }
- }
- UINT iOrd = 0;
- while ((pos+5<len) && (iOrd < MAX_ORDERS))
- {
- DWORD dwName = *(DWORD *)(pdata+pos);
- for (UINT i=0; i<nPatterns; i++)
- {
- DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name;
- if (dwName == dwPatName)
- {
- Order[iOrd++] = i;
- break;
- }
- }
- pos += 5;
- }
- }
- break;
- }
- dwMemPos += pchunk->len;
- }
- }
-
- // Step #2: convert patterns
- for (UINT nPat=0; nPat<nPatterns; nPat++)
- {
- PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8);
- ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12;
- UINT nRows = pPsmPat->rows;
- if (len > pPsmPat->size) len = pPsmPat->size;
- if ((nRows < 64) || (nRows > 256)) nRows = 64;
- PatternSize[nPat] = nRows;
- if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break;
- MODCOMMAND *m = Patterns[nPat];
- BYTE *p = pPsmPat->data;
- UINT pos = 0;
- UINT row = 0;
- UINT oldch = 0;
- BOOL bNewRow = FALSE;
- #ifdef PSM_LOG
- Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream));
- #endif
- while ((row < nRows) && (pos+1 < len))
- {
- UINT flags = p[pos++];
- UINT ch = p[pos++];
-
- #ifdef PSM_LOG
- //Log("flags+ch: %02X.%02X\n", flags, ch);
- #endif
- if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/)
- {
- if ((pos+1<len) && (!(p[pos] & 0x0f)) && (p[pos+1] < m_nChannels))
- {
- #ifdef PSM_LOG
- //if (!nPat) Log("Continuing on new row\n");
- #endif
- row++;
- m += m_nChannels;
- oldch = ch;
- continue;
- }
- }
- if ((pos >= len) || (row >= nRows)) break;
- if (!(flags & 0xf0))
- {
- #ifdef PSM_LOG
- //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]);
- #endif
- row++;
- m += m_nChannels;
- bNewRow = TRUE;
- oldch = ch;
- continue;
- }
- bNewRow = FALSE;
- if (ch >= m_nChannels)
- {
- #ifdef PSM_LOG
- if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch);
- #endif
- ch = 0;
- }
- // Note + Instr
- if ((flags & 0x40) && (pos+1 < len))
- {
- UINT note = p[pos++];
- UINT nins = p[pos++];
- #ifdef PSM_LOG
- //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins);
- if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins);
- #endif
- if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1;
- m[ch].instr = samplemap[nins];
- m[ch].note = note;
- }
- // Volume
- if ((flags & 0x20) && (pos < len))
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = p[pos++] / 2;
- }
- // Effect
- if ((flags & 0x10) && (pos+1 < len))
- {
- UINT command = p[pos++];
- UINT param = p[pos++];
- // Convert effects
- switch(command)
- {
- // 01: fine volslide up
- case 0x01: command = CMD_VOLUMESLIDE; param |= 0x0f; break;
- // 04: fine volslide down
- case 0x04: command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break;
- // 0C: portamento up
- case 0x0C: command = CMD_PORTAMENTOUP; param = (param+1)/2; break;
- // 0E: portamento down
- case 0x0E: command = CMD_PORTAMENTODOWN; param = (param+1)/2; break;
- // 33: Position Jump
- case 0x33: command = CMD_POSITIONJUMP; break;
- // 34: Pattern break
- case 0x34: command = CMD_PATTERNBREAK; break;
- // 3D: speed
- case 0x3D: command = CMD_SPEED; break;
- // 3E: tempo
- case 0x3E: command = CMD_TEMPO; break;
- // Unknown
- default:
- #ifdef PSM_LOG
- Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param);
- #endif
- command = param = 0;
- }
- m[ch].command = (BYTE)command;
- m[ch].param = (BYTE)param;
- }
- oldch = ch;
- }
- #ifdef PSM_LOG
- if (pos < len)
- {
- Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos);
- }
- #endif
- }
-
- // Done (finally!)
- return TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////
-//
-// PSM Old Format
-//
-
-/*
-
-CONST
- c_PSM_MaxOrder = $FF;
- c_PSM_MaxSample = $FF;
- c_PSM_MaxChannel = $0F;
-
- TYPE
- PPSM_Header = ^TPSM_Header;
- TPSM_Header = RECORD
- PSM_Sign : ARRAY[01..04] OF CHAR; { PSM + #254 }
- PSM_SongName : ARRAY[01..58] OF CHAR;
- PSM_Byte00 : BYTE;
- PSM_Byte1A : BYTE;
- PSM_Unknown00 : BYTE;
- PSM_Unknown01 : BYTE;
- PSM_Unknown02 : BYTE;
- PSM_Speed : BYTE;
- PSM_Tempo : BYTE;
- PSM_Unknown03 : BYTE;
- PSM_Unknown04 : WORD;
- PSM_OrderLength : WORD;
- PSM_PatternNumber : WORD;
- PSM_SampleNumber : WORD;
- PSM_ChannelNumber : WORD;
- PSM_ChannelUsed : WORD;
- PSM_OrderPosition : LONGINT;
- PSM_ChannelSettingPosition : LONGINT;
- PSM_PatternPosition : LONGINT;
- PSM_SamplePosition : LONGINT;
- { *** perhaps there are some more infos in a larger header,
- but i have not decoded it and so it apears here NOT }
- END;
-
- PPSM_Sample = ^TPSM_Sample;
- TPSM_Sample = RECORD
- PSM_SampleFileName : ARRAY[01..12] OF CHAR;
- PSM_SampleByte00 : BYTE;
- PSM_SampleName : ARRAY[01..22] OF CHAR;
- PSM_SampleUnknown00 : ARRAY[01..02] OF BYTE;
- PSM_SamplePosition : LONGINT;
- PSM_SampleUnknown01 : ARRAY[01..04] OF BYTE;
- PSM_SampleNumber : BYTE;
- PSM_SampleFlags : WORD;
- PSM_SampleLength : LONGINT;
- PSM_SampleLoopBegin : LONGINT;
- PSM_SampleLoopEnd : LONGINT;
- PSM_Unknown03 : BYTE;
- PSM_SampleVolume : BYTE;
- PSM_SampleC5Speed : WORD;
- END;
-
- PPSM_SampleList = ^TPSM_SampleList;
- TPSM_SampleList = ARRAY[01..c_PSM_MaxSample] OF TPSM_Sample;
-
- PPSM_Order = ^TPSM_Order;
- TPSM_Order = ARRAY[00..c_PSM_MaxOrder] OF BYTE;
-
- PPSM_ChannelSettings = ^TPSM_ChannelSettings;
- TPSM_ChannelSettings = ARRAY[00..c_PSM_MaxChannel] OF BYTE;
-
- CONST
- PSM_NotesInPattern : BYTE = $00;
- PSM_ChannelInPattern : BYTE = $00;
-
- CONST
- c_PSM_SetSpeed = 60;
-
- FUNCTION PSM_Size(FileName : STRING;FilePosition : LONGINT) : LONGINT;
- BEGIN
- END;
-
- PROCEDURE PSM_UnpackPattern(VAR Source,Destination;PatternLength : WORD);
- VAR
- Witz : ARRAY[00..04] OF WORD;
- I1,I2 : WORD;
- I3,I4 : WORD;
- TopicalByte : ^BYTE;
- Pattern : PUnpackedPattern;
- ChannelP : BYTE;
- NoteP : BYTE;
- InfoByte : BYTE;
- CodeByte : BYTE;
- InfoWord : WORD;
- Effect : BYTE;
- Opperand : BYTE;
- Panning : BYTE;
- Volume : BYTE;
- PrevInfo : BYTE;
- InfoIndex : BYTE;
- BEGIN
- Pattern := @Destination;
- TopicalByte := @Source;
- { *** Initialize patttern }
- FOR I2 := 0 TO c_Maximum_NoteIndex DO
- FOR I3 := 0 TO c_Maximum_ChannelIndex DO
- BEGIN
- Pattern^[I2,I3,c_Pattern_NoteIndex] := $FF;
- Pattern^[I2,I3,c_Pattern_SampleIndex] := $00;
- Pattern^[I2,I3,c_Pattern_VolumeIndex] := $FF;
- Pattern^[I2,I3,c_Pattern_PanningIndex] := $FF;
- Pattern^[I2,I3,c_Pattern_EffectIndex] := $00;
- Pattern^[I2,I3,c_Pattern_OpperandIndex] := $00;
- END;
- { *** Byte-pointer on first pattern-entry }
- ChannelP := $00;
- NoteP := $00;
- InfoByte := $00;
- PrevInfo := $00;
- InfoIndex := $02;
- { *** read notes in pattern }
- PSM_NotesInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex);
- PSM_ChannelInPattern := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex);
- { *** unpack pattern }
- WHILE (INTEGER(PatternLength) > 0) AND (NoteP < c_Maximum_NoteIndex) DO
- BEGIN
- { *** Read info-byte }
- InfoByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength); INC(InfoIndex);
- IF InfoByte <> $00 THEN
- BEGIN
- ChannelP := InfoByte AND $0F;
- IF InfoByte AND 128 = 128 THEN { note and sample }
- BEGIN
- { *** read note }
- CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength);
- DEC(CodeByte);
- CodeByte := CodeByte MOD 12 * 16 + CodeByte DIV 12 + 2;
- Pattern^[NoteP,ChannelP,c_Pattern_NoteIndex] := CodeByte;
- { *** read sample }
- CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength);
- Pattern^[NoteP,ChannelP,c_Pattern_SampleIndex] := CodeByte;
- END;
- IF InfoByte AND 64 = 64 THEN { Volume }
- BEGIN
- CodeByte := TopicalByte^; INC(TopicalByte); DEC(PatternLength);
- Pattern^[NoteP,ChannelP,c_Pattern_VolumeIndex] := CodeByte;
- END;
- IF InfoByte AND 32 = 32 THEN { effect AND opperand }
- BEGIN
- Effect := TopicalByte^; INC(TopicalByte); DEC(PatternLength);
- Opperand := TopicalByte^; INC(TopicalByte); DEC(PatternLength);
- CASE Effect OF
- c_PSM_SetSpeed:
- BEGIN
- Effect := c_I_Set_Speed;
- END;
- ELSE
- BEGIN
- Effect := c_I_NoEffect;
- Opperand := $00;
- END;
- END;
- Pattern^[NoteP,ChannelP,c_Pattern_EffectIndex] := Effect;
- Pattern^[NoteP,ChannelP,c_Pattern_OpperandIndex] := Opperand;
- END;
- END ELSE INC(NoteP);
- END;
- END;
-
- PROCEDURE PSM_Load(FileName : STRING;FilePosition : LONGINT;VAR Module : PModule;VAR ErrorCode : WORD);
- { *** caution : Module has to be inited before!!!! }
- VAR
- Header : PPSM_Header;
- Sample : PPSM_SampleList;
- Order : PPSM_Order;
- ChannelSettings : PPSM_ChannelSettings;
- MultiPurposeBuffer : PByteArray;
- PatternBuffer : PUnpackedPattern;
- TopicalParaPointer : WORD;
-
- InFile : FILE;
- I1,I2 : WORD;
- I3,I4 : WORD;
- TempW : WORD;
- TempB : BYTE;
- TempP : PByteArray;
- TempI : INTEGER;
- { *** copy-vars for loop-extension }
- CopySource : LONGINT;
- CopyDestination : LONGINT;
- CopyLength : LONGINT;
- BEGIN
- { *** try to open file }
- ASSIGN(InFile,FileName);
-{$I-}
- RESET(InFile,1);
-{$I+}
- IF IORESULT <> $00 THEN
- BEGIN
- EXIT;
- END;
-{$I-}
- { *** seek start of module }
- IF FILESIZE(InFile) < FilePosition THEN
- BEGIN
- EXIT;
- END;
- SEEK(InFile,FilePosition);
- { *** look for enough memory for temporary variables }
- IF MEMAVAIL < SIZEOF(TPSM_Header) + SIZEOF(TPSM_SampleList) +
- SIZEOF(TPSM_Order) + SIZEOF(TPSM_ChannelSettings) +
- SIZEOF(TByteArray) + SIZEOF(TUnpackedPattern)
- THEN
- BEGIN
- EXIT;
- END;
- { *** init dynamic variables }
- NEW(Header);
- NEW(Sample);
- NEW(Order);
- NEW(ChannelSettings);
- NEW(MultiPurposeBuffer);
- NEW(PatternBuffer);
- { *** read header }
- BLOCKREAD(InFile,Header^,SIZEOF(TPSM_Header));
- { *** test if this is a DSM-file }
- IF NOT ((Header^.PSM_Sign[1] = 'P') AND (Header^.PSM_Sign[2] = 'S') AND
- (Header^.PSM_Sign[3] = 'M') AND (Header^.PSM_Sign[4] = #254)) THEN
- BEGIN
- ErrorCode := c_NoValidFileFormat;
- CLOSE(InFile);
- EXIT;
- END;
- { *** read order }
- SEEK(InFile,FilePosition + Header^.PSM_OrderPosition);
- BLOCKREAD(InFile,Order^,Header^.PSM_OrderLength);
- { *** read channelsettings }
- SEEK(InFile,FilePosition + Header^.PSM_ChannelSettingPosition);
- BLOCKREAD(InFile,ChannelSettings^,SIZEOF(TPSM_ChannelSettings));
- { *** read samplelist }
- SEEK(InFile,FilePosition + Header^.PSM_SamplePosition);
- BLOCKREAD(InFile,Sample^,Header^.PSM_SampleNumber * SIZEOF(TPSM_Sample));
- { *** copy header to intern NTMIK-structure }
- Module^.Module_Sign := 'MF';
- Module^.Module_FileFormatVersion := $0100;
- Module^.Module_SampleNumber := Header^.PSM_SampleNumber;
- Module^.Module_PatternNumber := Header^.PSM_PatternNumber;
- Module^.Module_OrderLength := Header^.PSM_OrderLength;
- Module^.Module_ChannelNumber := Header^.PSM_ChannelNumber+1;
- Module^.Module_Initial_GlobalVolume := 64;
- Module^.Module_Initial_MasterVolume := $C0;
- Module^.Module_Initial_Speed := Header^.PSM_Speed;
- Module^.Module_Initial_Tempo := Header^.PSM_Tempo;
-{ *** paragraph 01 start }
- Module^.Module_Flags := c_Module_Flags_ZeroVolume * BYTE(1) +
- c_Module_Flags_Stereo * BYTE(1) +
- c_Module_Flags_ForceAmigaLimits * BYTE(0) +
- c_Module_Flags_Panning * BYTE(1) +
- c_Module_Flags_Surround * BYTE(1) +
- c_Module_Flags_QualityMixing * BYTE(1) +
- c_Module_Flags_FastVolumeSlides * BYTE(0) +
- c_Module_Flags_SpecialCustomData * BYTE(0) +
- c_Module_Flags_SongName * BYTE(1);
- I1 := $01;
- WHILE (Header^.PSM_SongName[I1] > #00) AND (I1 < c_Module_SongNameLength) DO
- BEGIN
- Module^.Module_Name[I1] := Header^.PSM_SongName[I1];
- INC(I1);
- END;
- Module^.Module_Name[c_Module_SongNameLength] := #00;
- { *** Init channelsettings }
- FOR I1 := 0 TO c_Maximum_ChannelIndex DO
- BEGIN
- IF I1 < Header^.PSM_ChannelUsed THEN
- BEGIN
- { *** channel enabled }
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := 64;
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := (ChannelSettings^[I1]) * $08;
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := I1 + $10 * BYTE(ChannelSettings^[I1] > $08) +
- c_ChannelSettings_Code_ChannelEnabled * BYTE(1) +
- c_ChannelSettings_Code_ChannelDigital * BYTE(1);
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls :=
- c_ChannelSettings_Controls_EnhancedMode * BYTE(1) +
- c_ChannelSettings_Controls_SurroundMode * BYTE(0);
- END
- ELSE
- BEGIN
- { *** channel disabled }
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_GlobalVolume := $00;
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Panning := $00;
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Code := $00;
- Module^.Module_ChannelSettingPointer^[I1].ChannelSettings_Controls := $00;
- END;
- END;
- { *** init and copy order }
- FILLCHAR(Module^.Module_OrderPointer^,c_Maximum_OrderIndex+1,$FF);
- MOVE(Order^,Module^.Module_OrderPointer^,Header^.PSM_OrderLength);
- { *** read pattern }
- SEEK(InFile,FilePosition + Header^.PSM_PatternPosition);
- NTMIK_LoaderPatternNumber := Header^.PSM_PatternNumber-1;
- FOR I1 := 0 TO Header^.PSM_PatternNumber-1 DO
- BEGIN
- NTMIK_LoadPatternProcedure;
- { *** read length }
- BLOCKREAD(InFile,TempW,2);
- { *** read pattern }
- BLOCKREAD(InFile,MultiPurposeBuffer^,TempW-2);
- { *** unpack pattern and set notes per channel to 64 }
- PSM_UnpackPattern(MultiPurposeBuffer^,PatternBuffer^,TempW);
- NTMIK_PackPattern(MultiPurposeBuffer^,PatternBuffer^,PSM_NotesInPattern);
- TempW := WORD(256) * MultiPurposeBuffer^[01] + MultiPurposeBuffer^[00];
- GETMEM(Module^.Module_PatternPointer^[I1],TempW);
- MOVE(MultiPurposeBuffer^,Module^.Module_PatternPointer^[I1]^,TempW);
- { *** next pattern }
- END;
- { *** read samples }
- NTMIK_LoaderSampleNumber := Header^.PSM_SampleNumber;
- FOR I1 := 1 TO Header^.PSM_SampleNumber DO
- BEGIN
- NTMIK_LoadSampleProcedure;
- { *** get index for sample }
- I3 := Sample^[I1].PSM_SampleNumber;
- { *** clip PSM-sample }
- IF Sample^[I1].PSM_SampleLoopEnd > Sample^[I1].PSM_SampleLength
- THEN Sample^[I1].PSM_SampleLoopEnd := Sample^[I1].PSM_SampleLength;
- { *** init intern sample }
- NEW(Module^.Module_SamplePointer^[I3]);
- FILLCHAR(Module^.Module_SamplePointer^[I3]^,SIZEOF(TSample),$00);
- FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_SampleName,c_Sample_SampleNameLength,#32);
- FILLCHAR(Module^.Module_SamplePointer^[I3]^.Sample_FileName,c_Sample_FileNameLength,#32);
- { *** copy informations to intern sample }
- I2 := $01;
- WHILE (Sample^[I1].PSM_SampleName[I2] > #00) AND (I2 < c_Sample_SampleNameLength) DO
- BEGIN
- Module^.Module_SamplePointer^[I3]^.Sample_SampleName[I2] := Sample^[I1].PSM_SampleName[I2];
- INC(I2);
- END;
- Module^.Module_SamplePointer^[I3]^.Sample_Sign := 'DF';
- Module^.Module_SamplePointer^[I3]^.Sample_FileFormatVersion := $00100;
- Module^.Module_SamplePointer^[I3]^.Sample_Position := $00000000;
- Module^.Module_SamplePointer^[I3]^.Sample_Selector := $0000;
- Module^.Module_SamplePointer^[I3]^.Sample_Volume := Sample^[I1].PSM_SampleVolume;
- Module^.Module_SamplePointer^[I3]^.Sample_LoopCounter := $00;
- Module^.Module_SamplePointer^[I3]^.Sample_C5Speed := Sample^[I1].PSM_SampleC5Speed;
- Module^.Module_SamplePointer^[I3]^.Sample_Length := Sample^[I1].PSM_SampleLength;
- Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin := Sample^[I1].PSM_SampleLoopBegin;
- Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd := Sample^[I1].PSM_SampleLoopEnd;
- { *** now it's time for the flags }
- Module^.Module_SamplePointer^[I3]^.Sample_Flags :=
- c_Sample_Flags_DigitalSample * BYTE(1) +
- c_Sample_Flags_8BitSample * BYTE(1) +
- c_Sample_Flags_UnsignedSampleData * BYTE(1) +
- c_Sample_Flags_Packed * BYTE(0) +
- c_Sample_Flags_LoopCounter * BYTE(0) +
- c_Sample_Flags_SampleName * BYTE(1) +
- c_Sample_Flags_LoopActive *
- BYTE(Sample^[I1].PSM_SampleFlags AND (LONGINT(1) SHL 15) = (LONGINT(1) SHL 15));
- { *** alloc memory for sample-data }
- E_Getmem(Module^.Module_SamplePointer^[I3]^.Sample_Selector,
- Module^.Module_SamplePointer^[I3]^.Sample_Position,
- Module^.Module_SamplePointer^[I3]^.Sample_Length + c_LoopExtensionSize);
- { *** read out data }
- EPT(TempP).p_Selector := Module^.Module_SamplePointer^[I3]^.Sample_Selector;
- EPT(TempP).p_Offset := $0000;
- SEEK(InFile,Sample^[I1].PSM_SamplePosition);
- E_BLOCKREAD(InFile,TempP^,Module^.Module_SamplePointer^[I3]^.Sample_Length);
- { *** 'coz the samples are signed in a DSM-file -> PC-fy them }
- IF Module^.Module_SamplePointer^[I3]^.Sample_Length > 4 THEN
- BEGIN
- CopyLength := Module^.Module_SamplePointer^[I3]^.Sample_Length;
- { *** decode sample }
- ASM
- DB 066h; MOV CX,WORD PTR CopyLength
- { *** load sample selector }
- MOV ES,WORD PTR TempP[00002h]
- DB 066h; XOR SI,SI
- DB 066h; XOR DI,DI
- XOR AH,AH
- { *** conert all bytes }
- @@MainLoop:
- DB 026h; DB 067h; LODSB
- ADD AL,AH
- MOV AH,AL
- DB 067h; STOSB
- DB 066h; LOOP @@MainLoop
- END;
- { *** make samples unsigned }
- ASM
- DB 066h; MOV CX,WORD PTR CopyLength
- { *** load sample selector }
- MOV ES,WORD PTR TempP[00002h]
- DB 066h; XOR SI,SI
- DB 066h; XOR DI,DI
- { *** conert all bytes }
- @@MainLoop:
- DB 026h; DB 067h; LODSB
- SUB AL,080h
- DB 067h; STOSB
- DB 066h; LOOP @@MainLoop
- END;
- { *** Create Loop-Extension }
- IF Module^.Module_SamplePointer^[I3]^.Sample_Flags AND c_Sample_Flags_LoopActive = c_Sample_Flags_LoopActive THEN
- BEGIN
- CopySource := Module^.Module_SamplePointer^[I3]^.Sample_LoopBegin;
- CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_LoopEnd;
- CopyLength := CopyDestination - CopySource;
- ASM
- { *** load sample-selector }
- MOV ES,WORD PTR TempP[00002h]
- DB 066h; MOV DI,WORD PTR CopyDestination
- { *** calculate number of full sample-loops to copy }
- XOR DX,DX
- MOV AX,c_LoopExtensionSize
- MOV BX,WORD PTR CopyLength
- DIV BX
- OR AX,AX
- JE @@NoFullLoop
- { *** copy some full-loops (size=bx) }
- MOV CX,AX
- @@InnerLoop:
- PUSH CX
- DB 066h; MOV SI,WORD PTR CopySource
- MOV CX,BX
- DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] }
- POP CX
- LOOP @@InnerLoop
- @@NoFullLoop:
- { *** calculate number of rest-bytes to copy }
- DB 066h; MOV SI,WORD PTR CopySource
- MOV CX,DX
- DB 0F3h; DB 026h,067h,0A4h { REP MOVS BYTE PTR ES:[EDI],ES:[ESI] }
- END;
- END
- ELSE
- BEGIN
- CopyDestination := Module^.Module_SamplePointer^[I3]^.Sample_Length;
- ASM
- { *** load sample-selector }
- MOV ES,WORD PTR TempP[00002h]
- DB 066h; MOV DI,WORD PTR CopyDestination
- { *** clear extension }
- MOV CX,c_LoopExtensionSize
- MOV AL,080h
- DB 0F3h; DB 067h,0AAh { REP STOS BYTE PTR ES:[EDI] }
- END;
- END;
- END;
- { *** next sample }
- END;
- { *** init period-ranges }
- NTMIK_MaximumPeriod := $0000D600 SHR 1;
- NTMIK_MinimumPeriod := $0000D600 SHR 8;
- { *** close file }
- CLOSE(InFile);
- { *** dispose all dynamic variables }
- DISPOSE(Header);
- DISPOSE(Sample);
- DISPOSE(Order);
- DISPOSE(ChannelSettings);
- DISPOSE(MultiPurposeBuffer);
- DISPOSE(PatternBuffer);
- { *** set errorcode to noerror }
- ErrorCode := c_NoError;
- END;
-
-*/
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-//////////////////////////////////////////////
-// PTM PolyTracker module loader //
-//////////////////////////////////////////////
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#pragma pack(1)
-
-typedef struct PTMFILEHEADER
-{
- CHAR songname[28]; // name of song, asciiz string
- CHAR eof; // 26
- BYTE version_lo; // 03 version of file, currently 0203h
- BYTE version_hi; // 02
- BYTE reserved1; // reserved, set to 0
- WORD norders; // number of orders (0..256)
- WORD nsamples; // number of instruments (1..255)
- WORD npatterns; // number of patterns (1..128)
- WORD nchannels; // number of channels (voices) used (1..32)
- WORD fileflags; // set to 0
- WORD reserved2; // reserved, set to 0
- DWORD ptmf_id; // song identification, 'PTMF' or 0x464d5450
- BYTE reserved3[16]; // reserved, set to 0
- BYTE chnpan[32]; // channel panning settings, 0..15, 0 = left, 7 = middle, 15 = right
- BYTE orders[256]; // order list, valid entries 0..nOrders-1
- WORD patseg[128]; // pattern offsets (*16)
-} PTMFILEHEADER, *LPPTMFILEHEADER;
-
-#define SIZEOF_PTMFILEHEADER 608
-
-
-typedef struct PTMSAMPLE
-{
- BYTE sampletype; // sample type (bit array)
- CHAR filename[12]; // name of external sample file
- BYTE volume; // default volume
- WORD nC4Spd; // C4 speed
- WORD sampleseg; // sample segment (used internally)
- WORD fileofs[2]; // offset of sample data
- WORD length[2]; // sample size (in bytes)
- WORD loopbeg[2]; // start of loop
- WORD loopend[2]; // end of loop
- WORD gusdata[8];
- char samplename[28]; // name of sample, asciiz // changed from CHAR
- DWORD ptms_id; // sample identification, 'PTMS' or 0x534d5450
-} PTMSAMPLE;
-
-#define SIZEOF_PTMSAMPLE 80
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadPTM(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- PTMFILEHEADER pfh = *(LPPTMFILEHEADER)lpStream;
- DWORD dwMemPos;
- UINT nOrders;
-
- pfh.norders = bswapLE16(pfh.norders);
- pfh.nsamples = bswapLE16(pfh.nsamples);
- pfh.npatterns = bswapLE16(pfh.npatterns);
- pfh.nchannels = bswapLE16(pfh.nchannels);
- pfh.fileflags = bswapLE16(pfh.fileflags);
- pfh.reserved2 = bswapLE16(pfh.reserved2);
- pfh.ptmf_id = bswapLE32(pfh.ptmf_id);
- for (UINT j=0; j<128; j++)
- {
- pfh.patseg[j] = bswapLE16(pfh.patseg[j]);
- }
-
- if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
- if ((pfh.ptmf_id != 0x464d5450) || (!pfh.nchannels)
- || (pfh.nchannels > 32)
- || (pfh.norders > 256) || (!pfh.norders)
- || (!pfh.nsamples) || (pfh.nsamples > 255)
- || (!pfh.npatterns) || (pfh.npatterns > 128)
- || (SIZEOF_PTMFILEHEADER+pfh.nsamples*SIZEOF_PTMSAMPLE >= (int)dwMemLength)) return FALSE;
- memcpy(m_szNames[0], pfh.songname, 28);
- m_szNames[0][28] = 0;
- m_nType = MOD_TYPE_PTM;
- m_nChannels = pfh.nchannels;
- m_nSamples = (pfh.nsamples < MAX_SAMPLES) ? pfh.nsamples : MAX_SAMPLES-1;
- dwMemPos = SIZEOF_PTMFILEHEADER;
- nOrders = (pfh.norders < MAX_ORDERS) ? pfh.norders : MAX_ORDERS-1;
- memcpy(Order, pfh.orders, nOrders);
- for (UINT ipan=0; ipan<m_nChannels; ipan++)
- {
- ChnSettings[ipan].nVolume = 64;
- ChnSettings[ipan].nPan = ((pfh.chnpan[ipan] & 0x0F) << 4) + 4;
- }
- for (UINT ismp=0; ismp<m_nSamples; ismp++, dwMemPos += SIZEOF_PTMSAMPLE)
- {
- MODINSTRUMENT *pins = &Ins[ismp+1];
- PTMSAMPLE *psmp = (PTMSAMPLE *)(lpStream+dwMemPos);
-
- lstrcpyn(m_szNames[ismp+1], psmp->samplename, 28);
- memcpy(pins->name, psmp->filename, 12);
- pins->name[12] = 0;
- pins->nGlobalVol = 64;
- pins->nPan = 128;
- pins->nVolume = psmp->volume << 2;
- pins->nC4Speed = bswapLE16(psmp->nC4Spd) << 1;
- pins->uFlags = 0;
- if ((psmp->sampletype & 3) == 1)
- {
- UINT smpflg = RS_PCM8D;
- DWORD samplepos;
- DWORD psmp_length, psmp_loopbeg, psmp_loopend, psmp_fileofs;
- memcpy (&psmp_length, (void *) psmp->length, sizeof (DWORD));
- memcpy (&psmp_loopbeg, (void *) psmp->loopbeg, sizeof (DWORD));
- memcpy (&psmp_loopend, (void *) psmp->loopend, sizeof (DWORD));
- memcpy (&psmp_fileofs, (void *) psmp->fileofs, sizeof (DWORD));
- pins->nLength = bswapLE32(psmp_length);
- pins->nLoopStart = bswapLE32(psmp_loopbeg);
- pins->nLoopEnd = bswapLE32(psmp_loopend);
- samplepos = bswapLE32(psmp_fileofs);
- if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP;
- if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP;
- if (psmp->sampletype & 16)
- {
- pins->uFlags |= CHN_16BIT;
- pins->nLength >>= 1;
- pins->nLoopStart >>= 1;
- pins->nLoopEnd >>= 1;
- smpflg = RS_PTM8DTO16;
- }
- if ((pins->nLength) && (samplepos) && (samplepos < dwMemLength))
- {
- ReadSample(pins, smpflg, (LPSTR)(lpStream+samplepos), dwMemLength-samplepos);
- }
- }
- }
- // Reading Patterns
- for (UINT ipat=0; ipat<pfh.npatterns; ipat++)
- {
- dwMemPos = ((UINT)pfh.patseg[ipat]) << 4;
- if ((!dwMemPos) || (dwMemPos >= dwMemLength)) continue;
- PatternSize[ipat] = 64;
- if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break;
- //
- MODCOMMAND *m = Patterns[ipat];
- for (UINT row=0; ((row < 64) && (dwMemPos < dwMemLength)); )
- {
- UINT b = lpStream[dwMemPos++];
-
- if (dwMemPos >= dwMemLength) break;
- if (b)
- {
- UINT nChn = b & 0x1F;
-
- if (b & 0x20)
- {
- if (dwMemPos + 2 > dwMemLength) break;
- m[nChn].note = lpStream[dwMemPos++];
- m[nChn].instr = lpStream[dwMemPos++];
- }
- if (b & 0x40)
- {
- if (dwMemPos + 2 > dwMemLength) break;
- m[nChn].command = lpStream[dwMemPos++];
- m[nChn].param = lpStream[dwMemPos++];
- if ((m[nChn].command == 0x0E) && ((m[nChn].param & 0xF0) == 0x80))
- {
- m[nChn].command = CMD_S3MCMDEX;
- } else
- if (m[nChn].command < 0x10)
- {
- ConvertModCommand(&m[nChn]);
- } else
- {
- switch(m[nChn].command)
- {
- case 16:
- m[nChn].command = CMD_GLOBALVOLUME;
- break;
- case 17:
- m[nChn].command = CMD_RETRIG;
- break;
- case 18:
- m[nChn].command = CMD_FINEVIBRATO;
- break;
- default:
- m[nChn].command = 0;
- }
- }
- }
- if (b & 0x80)
- {
- if (dwMemPos >= dwMemLength) break;
- m[nChn].volcmd = VOLCMD_VOLUME;
- m[nChn].vol = lpStream[dwMemPos++];
- }
- } else
- {
- row++;
- m += m_nChannels;
- }
- }
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-extern WORD S3MFineTuneTable[16];
-
-//////////////////////////////////////////////////////
-// ScreamTracker S3M file support
-
-typedef struct tagS3MSAMPLESTRUCT
-{
- BYTE type;
- CHAR dosname[12];
- BYTE hmem;
- WORD memseg;
- DWORD length;
- DWORD loopbegin;
- DWORD loopend;
- BYTE vol;
- BYTE bReserved;
- BYTE pack;
- BYTE flags;
- DWORD finetune;
- DWORD dwReserved;
- WORD intgp;
- WORD int512;
- DWORD lastused;
- CHAR name[28];
- CHAR scrs[4];
-} S3MSAMPLESTRUCT;
-
-
-typedef struct tagS3MFILEHEADER
-{
- CHAR name[28];
- BYTE b1A;
- BYTE type;
- WORD reserved1;
- WORD ordnum;
- WORD insnum;
- WORD patnum;
- WORD flags;
- WORD cwtv;
- WORD version;
- DWORD scrm; // "SCRM" = 0x4D524353
- BYTE globalvol;
- BYTE speed;
- BYTE tempo;
- BYTE mastervol;
- BYTE ultraclicks;
- BYTE panning_present;
- BYTE reserved2[8];
- WORD special;
- BYTE channels[32];
-} S3MFILEHEADER;
-
-
-void CSoundFile::S3MConvert(MODCOMMAND *m, BOOL bIT) const
-//--------------------------------------------------------
-{
- UINT command = m->command;
- UINT param = m->param;
- switch (command + 0x40)
- {
- case 'A': command = CMD_SPEED; break;
- case 'B': command = CMD_POSITIONJUMP; break;
- case 'C': command = CMD_PATTERNBREAK; if (!bIT) param = (param >> 4) * 10 + (param & 0x0F); break;
- case 'D': command = CMD_VOLUMESLIDE; break;
- case 'E': command = CMD_PORTAMENTODOWN; break;
- case 'F': command = CMD_PORTAMENTOUP; break;
- case 'G': command = CMD_TONEPORTAMENTO; break;
- case 'H': command = CMD_VIBRATO; break;
- case 'I': command = CMD_TREMOR; break;
- case 'J': command = CMD_ARPEGGIO; break;
- case 'K': command = CMD_VIBRATOVOL; break;
- case 'L': command = CMD_TONEPORTAVOL; break;
- case 'M': command = CMD_CHANNELVOLUME; break;
- case 'N': command = CMD_CHANNELVOLSLIDE; break;
- case 'O': command = CMD_OFFSET; break;
- case 'P': command = CMD_PANNINGSLIDE; break;
- case 'Q': command = CMD_RETRIG; break;
- case 'R': command = CMD_TREMOLO; break;
- case 'S': command = CMD_S3MCMDEX; break;
- case 'T': command = CMD_TEMPO; break;
- case 'U': command = CMD_FINEVIBRATO; break;
- case 'V': command = CMD_GLOBALVOLUME; break;
- case 'W': command = CMD_GLOBALVOLSLIDE; break;
- case 'X': command = CMD_PANNING8; break;
- case 'Y': command = CMD_PANBRELLO; break;
- case 'Z': command = CMD_MIDI; break;
- default: command = 0;
- }
- m->command = command;
- m->param = param;
-}
-
-
-void CSoundFile::S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const
-//---------------------------------------------------------------------
-{
- UINT command = *pcmd;
- UINT param = *pprm;
- switch(command)
- {
- case CMD_SPEED: command = 'A'; break;
- case CMD_POSITIONJUMP: command = 'B'; break;
- case CMD_PATTERNBREAK: command = 'C'; if (!bIT) param = ((param / 10) << 4) + (param % 10); break;
- case CMD_VOLUMESLIDE: command = 'D'; break;
- case CMD_PORTAMENTODOWN: command = 'E'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break;
- case CMD_PORTAMENTOUP: command = 'F'; if ((param >= 0xE0) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM))) param = 0xDF; break;
- case CMD_TONEPORTAMENTO: command = 'G'; break;
- case CMD_VIBRATO: command = 'H'; break;
- case CMD_TREMOR: command = 'I'; break;
- case CMD_ARPEGGIO: command = 'J'; break;
- case CMD_VIBRATOVOL: command = 'K'; break;
- case CMD_TONEPORTAVOL: command = 'L'; break;
- case CMD_CHANNELVOLUME: command = 'M'; break;
- case CMD_CHANNELVOLSLIDE: command = 'N'; break;
- case CMD_OFFSET: command = 'O'; break;
- case CMD_PANNINGSLIDE: command = 'P'; break;
- case CMD_RETRIG: command = 'Q'; break;
- case CMD_TREMOLO: command = 'R'; break;
- case CMD_S3MCMDEX: command = 'S'; break;
- case CMD_TEMPO: command = 'T'; break;
- case CMD_FINEVIBRATO: command = 'U'; break;
- case CMD_GLOBALVOLUME: command = 'V'; break;
- case CMD_GLOBALVOLSLIDE: command = 'W'; break;
- case CMD_PANNING8:
- command = 'X';
- if ((bIT) && (m_nType != MOD_TYPE_IT) && (m_nType != MOD_TYPE_XM))
- {
- if (param == 0xA4) { command = 'S'; param = 0x91; } else
- if (param <= 0x80) { param <<= 1; if (param > 255) param = 255; } else
- command = param = 0;
- } else
- if ((!bIT) && ((m_nType == MOD_TYPE_IT) || (m_nType == MOD_TYPE_XM)))
- {
- param >>= 1;
- }
- break;
- case CMD_PANBRELLO: command = 'Y'; break;
- case CMD_MIDI: command = 'Z'; break;
- case CMD_XFINEPORTAUPDOWN:
- if (param & 0x0F) switch(param & 0xF0)
- {
- case 0x10: command = 'F'; param = (param & 0x0F) | 0xE0; break;
- case 0x20: command = 'E'; param = (param & 0x0F) | 0xE0; break;
- case 0x90: command = 'S'; break;
- default: command = param = 0;
- } else command = param = 0;
- break;
- case CMD_MODCMDEX:
- command = 'S';
- switch(param & 0xF0)
- {
- case 0x00: command = param = 0; break;
- case 0x10: command = 'F'; param |= 0xF0; break;
- case 0x20: command = 'E'; param |= 0xF0; break;
- case 0x30: param = (param & 0x0F) | 0x10; break;
- case 0x40: param = (param & 0x0F) | 0x30; break;
- case 0x50: param = (param & 0x0F) | 0x20; break;
- case 0x60: param = (param & 0x0F) | 0xB0; break;
- case 0x70: param = (param & 0x0F) | 0x40; break;
- case 0x90: command = 'Q'; param &= 0x0F; break;
- case 0xA0: if (param & 0x0F) { command = 'D'; param = (param << 4) | 0x0F; } else command=param=0; break;
- case 0xB0: if (param & 0x0F) { command = 'D'; param |= 0xF0; } else command=param=0; break;
- }
- break;
- default: command = param = 0;
- }
- command &= ~0x40;
- *pcmd = command;
- *pprm = param;
-}
-
-
-BOOL CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- UINT insnum,patnum,nins,npat;
- DWORD insfile[128];
- WORD ptr[256];
- BYTE s[1024];
- DWORD dwMemPos;
- BYTE insflags[128], inspack[128];
- S3MFILEHEADER psfh = *(S3MFILEHEADER *)lpStream;
-
- psfh.reserved1 = bswapLE16(psfh.reserved1);
- psfh.ordnum = bswapLE16(psfh.ordnum);
- psfh.insnum = bswapLE16(psfh.insnum);
- psfh.patnum = bswapLE16(psfh.patnum);
- psfh.flags = bswapLE16(psfh.flags);
- psfh.cwtv = bswapLE16(psfh.cwtv);
- psfh.version = bswapLE16(psfh.version);
- psfh.scrm = bswapLE32(psfh.scrm);
- psfh.special = bswapLE16(psfh.special);
-
- if ((!lpStream) || (dwMemLength <= sizeof(S3MFILEHEADER)+sizeof(S3MSAMPLESTRUCT)+64)) return FALSE;
- if (psfh.scrm != 0x4D524353) return FALSE;
- dwMemPos = 0x60;
- m_nType = MOD_TYPE_S3M;
- memset(m_szNames,0,sizeof(m_szNames));
- memcpy(m_szNames[0], psfh.name, 28);
- // Speed
- m_nDefaultSpeed = psfh.speed;
- if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 6;
- if (m_nDefaultSpeed > 0x1F) m_nDefaultSpeed = 0x1F;
- // Tempo
- m_nDefaultTempo = psfh.tempo;
- if (m_nDefaultTempo < 40) m_nDefaultTempo = 40;
- if (m_nDefaultTempo > 240) m_nDefaultTempo = 240;
- // Global Volume
- m_nDefaultGlobalVolume = psfh.globalvol << 2;
- if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256;
- m_nSongPreAmp = psfh.mastervol & 0x7F;
- // Channels
- m_nChannels = 4;
- for (UINT ich=0; ich<32; ich++)
- {
- ChnSettings[ich].nPan = 128;
- ChnSettings[ich].nVolume = 64;
-
- ChnSettings[ich].dwFlags = CHN_MUTE;
- if (psfh.channels[ich] != 0xFF)
- {
- m_nChannels = ich+1;
- UINT b = psfh.channels[ich] & 0x0F;
- ChnSettings[ich].nPan = (b & 8) ? 0xC0 : 0x40;
- ChnSettings[ich].dwFlags = 0;
- }
- }
- if (m_nChannels < 4) m_nChannels = 4;
- if ((psfh.cwtv < 0x1320) || (psfh.flags & 0x40)) m_dwSongFlags |= SONG_FASTVOLSLIDES;
- // Reading pattern order
- UINT iord = psfh.ordnum;
- if (iord<1) iord = 1;
- if (iord > MAX_ORDERS) iord = MAX_ORDERS;
- if (iord)
- {
- memcpy(Order, lpStream+dwMemPos, iord);
- dwMemPos += iord;
- }
- if ((iord & 1) && (lpStream[dwMemPos] == 0xFF)) dwMemPos++;
- // Reading file pointers
- insnum = nins = psfh.insnum;
- if (insnum >= MAX_SAMPLES) insnum = MAX_SAMPLES-1;
- m_nSamples = insnum;
- patnum = npat = psfh.patnum;
- if (patnum > MAX_PATTERNS) patnum = MAX_PATTERNS;
- memset(ptr, 0, sizeof(ptr));
- if (nins+npat)
- {
- memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat));
- dwMemPos += 2*(nins+npat);
- for (UINT j = 0; j < (nins+npat); ++j) {
- ptr[j] = bswapLE16(ptr[j]);
- }
- if (psfh.panning_present == 252)
- {
- const BYTE *chnpan = lpStream+dwMemPos;
- for (UINT i=0; i<32; i++) if (chnpan[i] & 0x20)
- {
- ChnSettings[i].nPan = ((chnpan[i] & 0x0F) << 4) + 8;
- }
- }
- }
- if (!m_nChannels) return TRUE;
- // Reading instrument headers
- memset(insfile, 0, sizeof(insfile));
- for (UINT iSmp=1; iSmp<=insnum; iSmp++)
- {
- UINT nInd = ((DWORD)ptr[iSmp-1])*16;
- if ((!nInd) || (nInd + 0x50 > dwMemLength)) continue;
- memcpy(s, lpStream+nInd, 0x50);
- memcpy(Ins[iSmp].name, s+1, 12);
- insflags[iSmp-1] = s[0x1F];
- inspack[iSmp-1] = s[0x1E];
- s[0x4C] = 0;
- lstrcpy(m_szNames[iSmp], (LPCSTR)&s[0x30]);
- if ((s[0]==1) && (s[0x4E]=='R') && (s[0x4F]=='S'))
- {
- UINT j = bswapLE32(*((LPDWORD)(s+0x10)));
- if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH;
- if (j < 4) j = 0;
- Ins[iSmp].nLength = j;
- j = bswapLE32(*((LPDWORD)(s+0x14)));
- if (j >= Ins[iSmp].nLength) j = Ins[iSmp].nLength - 1;
- Ins[iSmp].nLoopStart = j;
- j = bswapLE32(*((LPDWORD)(s+0x18)));
- if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH;
- if (j < 4) j = 0;
- if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength;
- Ins[iSmp].nLoopEnd = j;
- j = s[0x1C];
- if (j > 64) j = 64;
- Ins[iSmp].nVolume = j << 2;
- Ins[iSmp].nGlobalVol = 64;
- if (s[0x1F]&1) Ins[iSmp].uFlags |= CHN_LOOP;
- j = bswapLE32(*((LPDWORD)(s+0x20)));
- if (!j) j = 8363;
- if (j < 1024) j = 1024;
- Ins[iSmp].nC4Speed = j;
- insfile[iSmp] = ((DWORD)bswapLE16(*((LPWORD)(s+0x0E)))) << 4;
- insfile[iSmp] += ((DWORD)(BYTE)s[0x0D]) << 20;
- if (insfile[iSmp] > dwMemLength) insfile[iSmp] &= 0xFFFF;
- if ((Ins[iSmp].nLoopStart >= Ins[iSmp].nLoopEnd) || (Ins[iSmp].nLoopEnd - Ins[iSmp].nLoopStart < 8))
- Ins[iSmp].nLoopStart = Ins[iSmp].nLoopEnd = 0;
- Ins[iSmp].nPan = 0x80;
- }
- }
- // Reading patterns
- for (UINT iPat=0; iPat<patnum; iPat++)
- {
- UINT nInd = ((DWORD)ptr[nins+iPat]) << 4;
- if (nInd + 0x40 > dwMemLength) continue;
- WORD len = bswapLE16(*((WORD *)(lpStream+nInd)));
- nInd += 2;
- PatternSize[iPat] = 64;
- if ((!len) || (nInd + len > dwMemLength - 6)
- || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue;
- LPBYTE src = (LPBYTE)(lpStream+nInd);
- // Unpacking pattern
- MODCOMMAND *p = Patterns[iPat];
- UINT row = 0;
- UINT j = 0;
- while (j < len)
- {
- BYTE b = src[j++];
- if (!b)
- {
- if (++row >= 64) break;
- } else
- {
- UINT chn = b & 0x1F;
- if (chn < m_nChannels)
- {
- MODCOMMAND *m = &p[row*m_nChannels+chn];
- if (b & 0x20)
- {
- m->note = src[j++];
- if (m->note < 0xF0) m->note = (m->note & 0x0F) + 12*(m->note >> 4) + 13;
- else if (m->note == 0xFF) m->note = 0;
- m->instr = src[j++];
- }
- if (b & 0x40)
- {
- UINT vol = src[j++];
- if ((vol >= 128) && (vol <= 192))
- {
- vol -= 128;
- m->volcmd = VOLCMD_PANNING;
- } else
- {
- if (vol > 64) vol = 64;
- m->volcmd = VOLCMD_VOLUME;
- }
- m->vol = vol;
- }
- if (b & 0x80)
- {
- m->command = src[j++];
- m->param = src[j++];
- if (m->command) S3MConvert(m, FALSE);
- }
- } else
- {
- if (b & 0x20) j += 2;
- if (b & 0x40) j++;
- if (b & 0x80) j += 2;
- }
- if (j >= len) break;
- }
- }
- }
- // Reading samples
- for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw]))
- {
- UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
- if (insflags[iRaw-1] & 4) flags += 5;
- if (insflags[iRaw-1] & 2) flags |= RSF_STEREO;
- if (inspack[iRaw-1] == 4) flags = RS_ADPCM4;
- dwMemPos = insfile[iRaw];
- dwMemPos += ReadSample(&Ins[iRaw], flags, (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
- }
- m_nMinPeriod = 64;
- m_nMaxPeriod = 32767;
- if (psfh.flags & 0x10) m_dwSongFlags |= SONG_AMIGALIMITS;
- return TRUE;
-}
-
-
-#ifndef MODPLUG_NO_FILESAVE
-#pragma warning(disable:4100)
-
-static BYTE S3MFiller[16] =
-{
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
-};
-
-
-BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking)
-//----------------------------------------------------------
-{
- FILE *f;
- BYTE header[0x60];
- UINT nbo,nbi,nbp,i;
- WORD patptr[128];
- WORD insptr[128];
- BYTE buffer[5*1024];
- S3MSAMPLESTRUCT insex[128];
-
- if ((!m_nChannels) || (!lpszFileName)) return FALSE;
- if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
- // Writing S3M header
- memset(header, 0, sizeof(header));
- memset(insex, 0, sizeof(insex));
- memcpy(header, m_szNames[0], 0x1C);
- header[0x1B] = 0;
- header[0x1C] = 0x1A;
- header[0x1D] = 0x10;
- nbo = (GetNumPatterns() + 15) & 0xF0;
- if (!nbo) nbo = 16;
- header[0x20] = nbo & 0xFF;
- header[0x21] = nbo >> 8;
- nbi = m_nInstruments;
- if (!nbi) nbi = m_nSamples;
- if (nbi > 99) nbi = 99;
- header[0x22] = nbi & 0xFF;
- header[0x23] = nbi >> 8;
- nbp = 0;
- for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; }
- for (i=0; i<MAX_ORDERS; i++) if ((Order[i] < MAX_PATTERNS) && (Order[i] >= nbp)) nbp = Order[i] + 1;
- header[0x24] = nbp & 0xFF;
- header[0x25] = nbp >> 8;
- if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40;
- if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10;
- header[0x28] = 0x20;
- header[0x29] = 0x13;
- header[0x2A] = 0x02; // Version = 1 => Signed samples
- header[0x2B] = 0x00;
- header[0x2C] = 'S';
- header[0x2D] = 'C';
- header[0x2E] = 'R';
- header[0x2F] = 'M';
- header[0x30] = m_nDefaultGlobalVolume >> 2;
- header[0x31] = m_nDefaultSpeed;
- header[0x32] = m_nDefaultTempo;
- header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80; // Stereo
- header[0x35] = 0xFC;
- for (i=0; i<32; i++)
- {
- if (i < m_nChannels)
- {
- UINT tmp = (i & 0x0F) >> 1;
- header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp);
- } else header[0x40+i] = 0xFF;
- }
- fwrite(header, 0x60, 1, f);
- fwrite(Order, nbo, 1, f);
- memset(patptr, 0, sizeof(patptr));
- memset(insptr, 0, sizeof(insptr));
- UINT ofs0 = 0x60 + nbo;
- UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20;
- UINT ofs = ofs1;
-
- for (i=0; i<nbi; i++) insptr[i] = (WORD)((ofs + i*0x50) / 16);
- for (i=0; i<nbp; i++) patptr[i] = (WORD)((ofs + nbi*0x50) / 16);
- fwrite(insptr, nbi, 2, f);
- fwrite(patptr, nbp, 2, f);
- if (header[0x35] == 0xFC)
- {
- BYTE chnpan[32];
- for (i=0; i<32; i++)
- {
- chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4);
- }
- fwrite(chnpan, 0x20, 1, f);
- }
- if ((nbi*2+nbp*2) & 0x0F)
- {
- fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f);
- }
- ofs1 = ftell(f);
- fwrite(insex, nbi, 0x50, f);
- // Packing patterns
- ofs += nbi*0x50;
- for (i=0; i<nbp; i++)
- {
- WORD len = 64;
- memset(buffer, 0, sizeof(buffer));
- patptr[i] = ofs / 16;
- if (Patterns[i])
- {
- len = 2;
- MODCOMMAND *p = Patterns[i];
- for (int row=0; row<64; row++) if (row < PatternSize[i])
- {
- for (UINT j=0; j<m_nChannels; j++)
- {
- UINT b = j;
- MODCOMMAND *m = &p[row*m_nChannels+j];
- UINT note = m->note;
- UINT volcmd = m->volcmd;
- UINT vol = m->vol;
- UINT command = m->command;
- UINT param = m->param;
-
- if ((note) || (m->instr)) b |= 0x20;
- if (!note) note = 0xFF; else
- if (note >= 0xFE) note = 0xFE; else
- if (note < 13) note = 0; else note -= 13;
- if (note < 0xFE) note = (note % 12) + ((note / 12) << 4);
- if (command == CMD_VOLUME)
- {
- command = 0;
- if (param > 64) param = 64;
- volcmd = VOLCMD_VOLUME;
- vol = param;
- }
- if (volcmd == VOLCMD_VOLUME) b |= 0x40; else
- if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; }
- if (command)
- {
- S3MSaveConvert(&command, ¶m, FALSE);
- if (command) b |= 0x80;
- }
- if (b & 0xE0)
- {
- buffer[len++] = b;
- if (b & 0x20)
- {
- buffer[len++] = note;
- buffer[len++] = m->instr;
- }
- if (b & 0x40)
- {
- buffer[len++] = vol;
- }
- if (b & 0x80)
- {
- buffer[len++] = command;
- buffer[len++] = param;
- }
- if (len > sizeof(buffer) - 20) break;
- }
- }
- buffer[len++] = 0;
- if (len > sizeof(buffer) - 20) break;
- }
- }
- buffer[0] = (len - 2) & 0xFF;
- buffer[1] = (len - 2) >> 8;
- len = (len+15) & (~0x0F);
- fwrite(buffer, len, 1, f);
- ofs += len;
- }
- // Writing samples
- for (i=1; i<=nbi; i++)
- {
- MODINSTRUMENT *pins = &Ins[i];
- if (m_nInstruments)
- {
- pins = Ins;
- if (Headers[i])
- {
- for (UINT j=0; j<128; j++)
- {
- UINT n = Headers[i]->Keyboard[j];
- if ((n) && (n < MAX_INSTRUMENTS))
- {
- pins = &Ins[n];
- break;
- }
- }
- }
- }
- memcpy(insex[i-1].dosname, pins->name, 12);
- memcpy(insex[i-1].name, m_szNames[i], 28);
- memcpy(insex[i-1].scrs, "SCRS", 4);
- insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20);
- insex[i-1].memseg = (WORD)((DWORD)ofs >> 4);
- if (pins->pSample)
- {
- insex[i-1].type = 1;
- insex[i-1].length = pins->nLength;
- insex[i-1].loopbegin = pins->nLoopStart;
- insex[i-1].loopend = pins->nLoopEnd;
- insex[i-1].vol = pins->nVolume / 4;
- insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0;
- if (pins->nC4Speed)
- insex[i-1].finetune = pins->nC4Speed;
- else
- insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune);
- UINT flags = RS_PCM8U;
-#ifndef NO_PACKING
- if (nPacking)
- {
- if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
- && (CanPackSample(pins->pSample, pins->nLength, nPacking)))
- {
- insex[i-1].pack = 4;
- flags = RS_ADPCM4;
- }
- } else
-#endif // NO_PACKING
- {
- if (pins->uFlags & CHN_16BIT)
- {
- insex[i-1].flags |= 4;
- flags = RS_PCM16U;
- }
- if (pins->uFlags & CHN_STEREO)
- {
- insex[i-1].flags |= 2;
- flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U;
- }
- }
- DWORD len = WriteSample(f, pins, flags);
- if (len & 0x0F)
- {
- fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f);
- }
- ofs += (len + 15) & (~0x0F);
- } else
- {
- insex[i-1].length = 0;
- }
- }
- // Updating parapointers
- fseek(f, ofs0, SEEK_SET);
- fwrite(insptr, nbi, 2, f);
- fwrite(patptr, nbp, 2, f);
- fseek(f, ofs1, SEEK_SET);
- fwrite(insex, 0x50, nbi, f);
- fclose(f);
- return TRUE;
-}
-
-#pragma warning(default:4100)
-#endif // MODPLUG_NO_FILESAVE
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#pragma pack(1)
-
-typedef struct tagSTMNOTE
-{
- BYTE note;
- BYTE insvol;
- BYTE volcmd;
- BYTE cmdinf;
-} STMNOTE;
-
-
-// Raw STM sampleinfo struct:
-typedef struct tagSTMSAMPLE
-{
- CHAR filename[14]; // Can't have long comments - just filename comments :)
- WORD reserved; // ISA in memory when in ST 2
- WORD length; // Sample length
- WORD loopbeg; // Loop start point
- WORD loopend; // Loop end point
- BYTE volume; // Volume
- BYTE reserved2; // More reserved crap
- WORD c2spd; // Good old c2spd
- BYTE reserved3[6]; // Yet more of PSi's reserved crap
-} STMSAMPLE;
-
-
-// Raw STM header struct:
-typedef struct tagSTMHEADER
-{
- char songname[20]; // changed from CHAR
- char trackername[8]; // !SCREAM! for ST 2.xx // changed from CHAR
- CHAR unused; // 0x1A
- CHAR filetype; // 1=song, 2=module (only 2 is supported, of course) :)
- CHAR ver_major; // Like 2
- CHAR ver_minor; // "ditto"
- BYTE inittempo; // initspeed= stm inittempo>>4
- BYTE numpat; // number of patterns
- BYTE globalvol; // <- WoW! a RiGHT TRiANGLE =8*)
- BYTE reserved[13]; // More of PSi's internal crap
- STMSAMPLE sample[31]; // STM sample data
- BYTE patorder[128]; // Docs say 64 - actually 128
-} STMHEADER;
-
-#pragma pack()
-
-
-
-BOOL CSoundFile::ReadSTM(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- STMHEADER *phdr = (STMHEADER *)lpStream;
- DWORD dwMemPos = 0;
-
- if ((!lpStream) || (dwMemLength < sizeof(STMHEADER))) return FALSE;
- if ((phdr->filetype != 2) || (phdr->unused != 0x1A)
- || ((strnicmp(phdr->trackername, "!SCREAM!", 8))
- && (strnicmp(phdr->trackername, "BMOD2STM", 8)))) return FALSE;
- memcpy(m_szNames[0], phdr->songname, 20);
- // Read STM header
- m_nType = MOD_TYPE_STM;
- m_nSamples = 31;
- m_nChannels = 4;
- m_nInstruments = 0;
- m_nMinPeriod = 64;
- m_nMaxPeriod = 0x7FFF;
- m_nDefaultSpeed = phdr->inittempo >> 4;
- if (m_nDefaultSpeed < 1) m_nDefaultSpeed = 1;
- m_nDefaultTempo = 125;
- m_nDefaultGlobalVolume = phdr->globalvol << 2;
- if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
- memcpy(Order, phdr->patorder, 128);
- // Setting up channels
- for (UINT nSet=0; nSet<4; nSet++)
- {
- ChnSettings[nSet].dwFlags = 0;
- ChnSettings[nSet].nVolume = 64;
- ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
- }
- // Reading samples
- for (UINT nIns=0; nIns<31; nIns++)
- {
- MODINSTRUMENT *pIns = &Ins[nIns+1];
- STMSAMPLE *pStm = &phdr->sample[nIns]; // STM sample data
- memcpy(pIns->name, pStm->filename, 13);
- memcpy(m_szNames[nIns+1], pStm->filename, 12);
- pIns->nC4Speed = pStm->c2spd;
- pIns->nGlobalVol = 64;
- pIns->nVolume = pStm->volume << 2;
- if (pIns->nVolume > 256) pIns->nVolume = 256;
- pIns->nLength = pStm->length;
- if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0;
- pIns->nLoopStart = pStm->loopbeg;
- pIns->nLoopEnd = pStm->loopend;
- if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP;
- }
- dwMemPos = sizeof(STMHEADER);
- for (UINT nOrd=0; nOrd<MAX_ORDERS; nOrd++) if (Order[nOrd] >= 99) Order[nOrd] = 0xFF;
- UINT nPatterns = phdr->numpat;
- for (UINT nPat=0; nPat<nPatterns; nPat++)
- {
- if (dwMemPos + 64*4*4 > dwMemLength) return TRUE;
- PatternSize[nPat] = 64;
- if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE;
- MODCOMMAND *m = Patterns[nPat];
- STMNOTE *p = (STMNOTE *)(lpStream + dwMemPos);
- for (UINT n=0; n<64*4; n++, p++, m++)
- {
- UINT note,ins,vol,cmd;
- // extract the various information from the 4 bytes that
- // make up a single note
- note = p->note;
- ins = p->insvol >> 3;
- vol = (p->insvol & 0x07) + (p->volcmd >> 1);
- cmd = p->volcmd & 0x0F;
- if ((ins) && (ins < 32)) m->instr = ins;
- // special values of [SBYTE0] are handled here ->
- // we have no idea if these strange values will ever be encountered
- // but it appears as though stms sound correct.
- if ((note == 0xFE) || (note == 0xFC)) m->note = 0xFE; else
- // if note < 251, then all three bytes are stored in the file
- if (note < 0xFC) m->note = (note >> 4)*12 + (note&0xf) + 37;
- if (vol <= 64) { m->volcmd = VOLCMD_VOLUME; m->vol = vol; }
- m->param = p->cmdinf;
- switch(cmd)
- {
- // Axx set speed to xx
- case 1: m->command = CMD_SPEED; m->param >>= 4; break;
- // Bxx position jump
- case 2: m->command = CMD_POSITIONJUMP; break;
- // Cxx patternbreak to row xx
- case 3: m->command = CMD_PATTERNBREAK; m->param = (m->param & 0xF0) * 10 + (m->param & 0x0F); break;
- // Dxy volumeslide
- case 4: m->command = CMD_VOLUMESLIDE; break;
- // Exy toneslide down
- case 5: m->command = CMD_PORTAMENTODOWN; break;
- // Fxy toneslide up
- case 6: m->command = CMD_PORTAMENTOUP; break;
- // Gxx Tone portamento,speed xx
- case 7: m->command = CMD_TONEPORTAMENTO; break;
- // Hxy vibrato
- case 8: m->command = CMD_VIBRATO; break;
- // Ixy tremor, ontime x, offtime y
- case 9: m->command = CMD_TREMOR; break;
- // Jxy arpeggio
- case 10: m->command = CMD_ARPEGGIO; break;
- // Kxy Dual command H00 & Dxy
- case 11: m->command = CMD_VIBRATOVOL; break;
- // Lxy Dual command G00 & Dxy
- case 12: m->command = CMD_TONEPORTAVOL; break;
- // Xxx amiga command 8xx
- case 0x18: m->command = CMD_PANNING8; break;
- default:
- m->command = m->param = 0;
- }
- }
- dwMemPos += 64*4*4;
- }
- // Reading Samples
- for (UINT nSmp=1; nSmp<=31; nSmp++)
- {
- MODINSTRUMENT *pIns = &Ins[nSmp];
- dwMemPos = (dwMemPos + 15) & (~15);
- if (pIns->nLength)
- {
- UINT nPos = ((UINT)phdr->sample[nSmp-1].reserved) << 4;
- if ((nPos >= sizeof(STMHEADER)) && (nPos+pIns->nLength <= dwMemLength)) dwMemPos = nPos;
- if (dwMemPos < dwMemLength)
- {
- dwMemPos += ReadSample(pIns, RS_PCM8S, (LPSTR)(lpStream+dwMemPos),dwMemLength-dwMemPos);
- }
- }
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-//#pragma warning(disable:4244)
-
-#define ULT_16BIT 0x04
-#define ULT_LOOP 0x08
-#define ULT_BIDI 0x10
-
-#pragma pack(1)
-
-// Raw ULT header struct:
-typedef struct tagULTHEADER
-{
- char id[15]; // changed from CHAR
- char songtitle[32]; // changed from CHAR
- BYTE reserved;
-} ULTHEADER;
-
-
-// Raw ULT sampleinfo struct:
-typedef struct tagULTSAMPLE
-{
- CHAR samplename[32];
- CHAR dosname[12];
- LONG loopstart;
- LONG loopend;
- LONG sizestart;
- LONG sizeend;
- BYTE volume;
- BYTE flags;
- WORD finetune;
-} ULTSAMPLE;
-
-#pragma pack()
-
-
-BOOL CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- ULTHEADER *pmh = (ULTHEADER *)lpStream;
- ULTSAMPLE *pus;
- UINT nos, nop;
- DWORD dwMemPos = 0;
-
- // try to read module header
- if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
- if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return FALSE;
- // Warning! Not supported ULT format, trying anyway
- // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return FALSE;
- m_nType = MOD_TYPE_ULT;
- m_nDefaultSpeed = 6;
- m_nDefaultTempo = 125;
- memcpy(m_szNames[0], pmh->songtitle, 32);
- // read songtext
- dwMemPos = sizeof(ULTHEADER);
- if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength))
- {
- UINT len = pmh->reserved * 32;
- m_lpszSongComments = new char[len + 1 + pmh->reserved];
- if (m_lpszSongComments)
- {
- for (UINT l=0; l<pmh->reserved; l++)
- {
- memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32);
- m_lpszSongComments[l*33+32] = 0x0D;
- }
- m_lpszSongComments[len] = 0;
- }
- dwMemPos += len;
- }
- if (dwMemPos >= dwMemLength) return TRUE;
- nos = lpStream[dwMemPos++];
- m_nSamples = nos;
- if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
- UINT smpsize = 64;
- if (pmh->id[14] >= '4') smpsize += 2;
- if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return TRUE;
- for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples)
- {
- pus = (ULTSAMPLE *)(lpStream+dwMemPos);
- MODINSTRUMENT *pins = &Ins[ins];
- memcpy(m_szNames[ins], pus->samplename, 32);
- memcpy(pins->name, pus->dosname, 12);
- pins->nLoopStart = pus->loopstart;
- pins->nLoopEnd = pus->loopend;
- pins->nLength = pus->sizeend - pus->sizestart;
- pins->nVolume = pus->volume;
- pins->nGlobalVol = 64;
- pins->nC4Speed = 8363;
- if (pmh->id[14] >= '4')
- {
- pins->nC4Speed = pus->finetune;
- }
- if (pus->flags & ULT_LOOP) pins->uFlags |= CHN_LOOP;
- if (pus->flags & ULT_BIDI) pins->uFlags |= CHN_PINGPONGLOOP;
- if (pus->flags & ULT_16BIT)
- {
- pins->uFlags |= CHN_16BIT;
- pins->nLoopStart >>= 1;
- pins->nLoopEnd >>= 1;
- }
- }
- memcpy(Order, lpStream+dwMemPos, 256);
- dwMemPos += 256;
- m_nChannels = lpStream[dwMemPos] + 1;
- nop = lpStream[dwMemPos+1] + 1;
- dwMemPos += 2;
- if (m_nChannels > 32) m_nChannels = 32;
- // Default channel settings
- for (UINT nSet=0; nSet<m_nChannels; nSet++)
- {
- ChnSettings[nSet].nVolume = 64;
- ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
- }
- // read pan position table for v1.5 and higher
- if(pmh->id[14]>='3')
- {
- if (dwMemPos + m_nChannels > dwMemLength) return TRUE;
- for(UINT t=0; t<m_nChannels; t++)
- {
- ChnSettings[t].nPan = (lpStream[dwMemPos++] << 4) + 8;
- if (ChnSettings[t].nPan > 256) ChnSettings[t].nPan = 256;
- }
- }
- // Allocating Patterns
- for (UINT nAllocPat=0; nAllocPat<nop; nAllocPat++)
- {
- if (nAllocPat < MAX_PATTERNS)
- {
- PatternSize[nAllocPat] = 64;
- Patterns[nAllocPat] = AllocatePattern(64, m_nChannels);
- }
- }
- // Reading Patterns
- for (UINT nChn=0; nChn<m_nChannels; nChn++)
- {
- for (UINT nPat=0; nPat<nop; nPat++)
- {
- MODCOMMAND *pat = NULL;
-
- if (nPat < MAX_PATTERNS)
- {
- pat = Patterns[nPat];
- if (pat) pat += nChn;
- }
- UINT row = 0;
- while (row < 64)
- {
- if (dwMemPos + 6 > dwMemLength) return TRUE;
- UINT rep = 1;
- UINT note = lpStream[dwMemPos++];
- if (note == 0xFC)
- {
- rep = lpStream[dwMemPos];
- note = lpStream[dwMemPos+1];
- dwMemPos += 2;
- }
- UINT instr = lpStream[dwMemPos++];
- UINT eff = lpStream[dwMemPos++];
- UINT dat1 = lpStream[dwMemPos++];
- UINT dat2 = lpStream[dwMemPos++];
- UINT cmd1 = eff & 0x0F;
- UINT cmd2 = eff >> 4;
- if (cmd1 == 0x0C) dat1 >>= 2; else
- if (cmd1 == 0x0B) { cmd1 = dat1 = 0; }
- if (cmd2 == 0x0C) dat2 >>= 2; else
- if (cmd2 == 0x0B) { cmd2 = dat2 = 0; }
- while ((rep != 0) && (row < 64))
- {
- if (pat)
- {
- pat->instr = instr;
- if (note) pat->note = note + 36;
- if (cmd1 | dat1)
- {
- if (cmd1 == 0x0C)
- {
- pat->volcmd = VOLCMD_VOLUME;
- pat->vol = dat1;
- } else
- {
- pat->command = cmd1;
- pat->param = dat1;
- ConvertModCommand(pat);
- }
- }
- if (cmd2 == 0x0C)
- {
- pat->volcmd = VOLCMD_VOLUME;
- pat->vol = dat2;
- } else
- if ((cmd2 | dat2) && (!pat->command))
- {
- pat->command = cmd2;
- pat->param = dat2;
- ConvertModCommand(pat);
- }
- pat += m_nChannels;
- }
- row++;
- rep--;
- }
- }
- }
- }
- // Reading Instruments
- for (UINT smp=1; smp<=m_nSamples; smp++) if (Ins[smp].nLength)
- {
- if (dwMemPos >= dwMemLength) return TRUE;
- UINT flags = (Ins[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
- dwMemPos += ReadSample(&Ins[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
- }
- return TRUE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#define MODMAGIC_OFFSET (20+31*30+130)
-
-
-BOOL CSoundFile::ReadUMX(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- if ((!lpStream) || (dwMemLength < 0x800)) return FALSE;
- // Rip Mods from UMX
- if ((bswapLE32(*((DWORD *)(lpStream+0x20))) < dwMemLength)
- && (bswapLE32(*((DWORD *)(lpStream+0x18))) <= dwMemLength - 0x10)
- && (bswapLE32(*((DWORD *)(lpStream+0x18))) >= dwMemLength - 0x200))
- {
- for (UINT uscan=0x40; uscan<0x500; uscan++)
- {
- DWORD dwScan = bswapLE32(*((DWORD *)(lpStream+uscan)));
- // IT
- if (dwScan == 0x4D504D49)
- {
- DWORD dwRipOfs = uscan;
- return ReadIT(lpStream + dwRipOfs, dwMemLength - dwRipOfs);
- }
- // S3M
- if (dwScan == 0x4D524353)
- {
- DWORD dwRipOfs = uscan - 44;
- return ReadS3M(lpStream + dwRipOfs, dwMemLength - dwRipOfs);
- }
- // XM
- if (!strnicmp((LPCSTR)(lpStream+uscan), "Extended Module", 15))
- {
- DWORD dwRipOfs = uscan;
- return ReadXM(lpStream + dwRipOfs, dwMemLength - dwRipOfs);
- }
- // MOD
- if ((uscan > MODMAGIC_OFFSET) && (dwScan == 0x2e4b2e4d))
- {
- DWORD dwRipOfs = uscan - MODMAGIC_OFFSET;
- return ReadMod(lpStream+dwRipOfs, dwMemLength-dwRipOfs);
- }
- }
- }
- return FALSE;
-}
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#ifndef WAVE_FORMAT_EXTENSIBLE
-#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
-#endif
-
-/////////////////////////////////////////////////////////////
-// WAV file support
-
-BOOL CSoundFile::ReadWav(const BYTE *lpStream, DWORD dwMemLength)
-//---------------------------------------------------------------
-{
- DWORD dwMemPos = 0;
- WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream;
- WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER));
- if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE;
- if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE)
- || (pfmt->id_fmt != IFFID_fmt)) return FALSE;
- dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen;
- if ((dwMemPos + 8 >= dwMemLength)
- || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE))
- || (pfmt->channels > 4)
- || (!pfmt->channels)
- || (!pfmt->freqHz)
- || (pfmt->bitspersample & 7)
- || (pfmt->bitspersample < 8)
- || (pfmt->bitspersample > 32)) return FALSE;
- WAVEDATAHEADER *pdata;
- for (;;)
- {
- pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos);
- if (pdata->id_data == IFFID_data) break;
- dwMemPos += pdata->length + 8;
- if (dwMemPos + 8 >= dwMemLength) return FALSE;
- }
- m_nType = MOD_TYPE_WAV;
- m_nSamples = 0;
- m_nInstruments = 0;
- m_nChannels = 4;
- m_nDefaultSpeed = 8;
- m_nDefaultTempo = 125;
- m_dwSongFlags |= SONG_LINEARSLIDES; // For no resampling
- Order[0] = 0;
- Order[1] = 0xFF;
- PatternSize[0] = PatternSize[1] = 64;
- if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE;
- if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE;
- UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3;
- UINT len = pdata->length, bytelen;
- if (dwMemPos + len > dwMemLength - 8) len = dwMemLength - dwMemPos - 8;
- len /= samplesize;
- bytelen = len;
- if (pfmt->bitspersample >= 16) bytelen *= 2;
- if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
- if (!len) return TRUE;
- // Setting up module length
- DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1;
- DWORD framesperrow = (dwTime + 63) / 63;
- if (framesperrow < 4) framesperrow = 4;
- UINT norders = 1;
- while (framesperrow >= 0x20)
- {
- Order[norders++] = 1;
- Order[norders] = 0xFF;
- framesperrow = (dwTime + (64 * norders - 1)) / (64 * norders);
- if (norders >= MAX_ORDERS-1) break;
- }
- m_nDefaultSpeed = framesperrow;
- for (UINT iChn=0; iChn<4; iChn++)
- {
- ChnSettings[iChn].nPan = (iChn & 1) ? 256 : 0;
- ChnSettings[iChn].nVolume = 64;
- ChnSettings[iChn].dwFlags = 0;
- }
- // Setting up speed command
- MODCOMMAND *pcmd = Patterns[0];
- pcmd[0].command = CMD_SPEED;
- pcmd[0].param = (BYTE)m_nDefaultSpeed;
- pcmd[0].note = 5*12+1;
- pcmd[0].instr = 1;
- pcmd[1].note = pcmd[0].note;
- pcmd[1].instr = pcmd[0].instr;
- m_nSamples = pfmt->channels;
- // Support for Multichannel Wave
- for (UINT nChn=0; nChn<m_nSamples; nChn++)
- {
- MODINSTRUMENT *pins = &Ins[nChn+1];
- pcmd[nChn].note = pcmd[0].note;
- pcmd[nChn].instr = (BYTE)(nChn+1);
- pins->nLength = len;
- pins->nC4Speed = pfmt->freqHz;
- pins->nVolume = 256;
- pins->nPan = 128;
- pins->nGlobalVol = 64;
- pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0);
- pins->uFlags |= CHN_PANNING;
- if (m_nSamples > 1)
- {
- switch(nChn)
- {
- case 0: pins->nPan = 0; break;
- case 1: pins->nPan = 256; break;
- case 2: pins->nPan = (WORD)((m_nSamples == 3) ? 128 : 64); pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break;
- case 3: pins->nPan = 192; pcmd[nChn].command = CMD_S3MCMDEX; pcmd[nChn].param = 0x91; break;
- default: pins->nPan = 128; break;
- }
- }
- if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE;
- if (pfmt->bitspersample >= 16)
- {
- int slsize = pfmt->bitspersample >> 3;
- signed short *p = (signed short *)pins->pSample;
- signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2);
- for (UINT i=0; i<len; i++)
- {
- p[i] = *((signed short *)psrc);
- psrc += samplesize;
- }
- p[len+1] = p[len] = p[len-1];
- } else
- {
- signed char *p = (signed char *)pins->pSample;
- signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn);
- for (UINT i=0; i<len; i++)
- {
- p[i] = (signed char)((*psrc) + 0x80);
- psrc += samplesize;
- }
- p[len+1] = p[len] = p[len-1];
- }
- }
- return TRUE;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-// IMA ADPCM Support
-
-#pragma pack(1)
-
-typedef struct IMAADPCMBLOCK
-{
- WORD sample;
- BYTE index;
- BYTE Reserved;
-} DVI_ADPCMBLOCKHEADER;
-
-#pragma pack()
-
-static const int gIMAUnpackTable[90] =
-{
- 7, 8, 9, 10, 11, 12, 13, 14,
- 16, 17, 19, 21, 23, 25, 28, 31,
- 34, 37, 41, 45, 50, 55, 60, 66,
- 73, 80, 88, 97, 107, 118, 130, 143,
- 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658,
- 724, 796, 876, 963, 1060, 1166, 1282, 1411,
- 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
- 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
- 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
- 32767, 0
-};
-
-
-BOOL IMAADPCMUnpack16(signed short *pdest, UINT nLen, LPBYTE psrc, DWORD dwBytes, UINT pkBlkAlign)
-//------------------------------------------------------------------------------------------------
-{
- static const int gIMAIndexTab[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
- UINT nPos;
- int value;
-
- if ((nLen < 4) || (!pdest) || (!psrc)
- || (pkBlkAlign < 5) || (pkBlkAlign > dwBytes)) return FALSE;
- nPos = 0;
- while ((nPos < nLen) && (dwBytes > 4))
- {
- int nIndex;
- value = *((short int *)psrc);
- nIndex = psrc[2];
- psrc += 4;
- dwBytes -= 4;
- pdest[nPos++] = (short int)value;
- for (UINT i=0; ((i<(pkBlkAlign-4)*2) && (nPos < nLen) && (dwBytes)); i++)
- {
- BYTE delta;
- if (i & 1)
- {
- delta = (BYTE)(((*(psrc++)) >> 4) & 0x0F);
- dwBytes--;
- } else
- {
- delta = (BYTE)((*psrc) & 0x0F);
- }
- int v = gIMAUnpackTable[nIndex] >> 3;
- if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2;
- if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1;
- if (delta & 4) v += gIMAUnpackTable[nIndex];
- if (delta & 8) value -= v; else value += v;
- nIndex += gIMAIndexTab[delta & 7];
- if (nIndex < 0) nIndex = 0; else
- if (nIndex > 88) nIndex = 88;
- if (value > 32767) value = 32767; else
- if (value < -32768) value = -32768;
- pdest[nPos++] = (short int)value;
- }
- }
- return TRUE;
-}
-
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-////////////////////////////////////////////////////////
-// FastTracker II XM file support
-
-#ifdef MSC_VER
-#pragma warning(disable:4244)
-#endif
-
-#pragma pack(1)
-typedef struct tagXMFILEHEADER
-{
- DWORD size;
- WORD norder;
- WORD restartpos;
- WORD channels;
- WORD patterns;
- WORD instruments;
- WORD flags;
- WORD speed;
- WORD tempo;
- BYTE order[256];
-} XMFILEHEADER;
-
-
-typedef struct tagXMINSTRUMENTHEADER
-{
- DWORD size;
- CHAR name[22];
- BYTE type;
- BYTE samples;
- BYTE samplesh;
-} XMINSTRUMENTHEADER;
-
-
-typedef struct tagXMSAMPLEHEADER
-{
- DWORD shsize;
- BYTE snum[96];
- WORD venv[24];
- WORD penv[24];
- BYTE vnum, pnum;
- BYTE vsustain, vloops, vloope, psustain, ploops, ploope;
- BYTE vtype, ptype;
- BYTE vibtype, vibsweep, vibdepth, vibrate;
- WORD volfade;
- WORD res;
- BYTE reserved1[20];
-} XMSAMPLEHEADER;
-
-typedef struct tagXMSAMPLESTRUCT
-{
- DWORD samplen;
- DWORD loopstart;
- DWORD looplen;
- BYTE vol;
- signed char finetune;
- BYTE type;
- BYTE pan;
- signed char relnote;
- BYTE res;
- char name[22];
-} XMSAMPLESTRUCT;
-#pragma pack()
-
-
-BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength)
-//--------------------------------------------------------------
-{
- XMSAMPLEHEADER xmsh;
- XMSAMPLESTRUCT xmss;
- DWORD dwMemPos, dwHdrSize;
- WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0;
- WORD xmflags=0, deftempo=125, defspeed=6;
- BOOL InstUsed[256];
- BYTE channels_used[MAX_CHANNELS];
- BYTE pattern_map[256];
- BOOL samples_used[MAX_SAMPLES];
- UINT unused_samples;
-
- m_nChannels = 0;
- if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
- if (strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE;
-
- memcpy(m_szNames[0], lpStream+17, 20);
- dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60)));
- norders = bswapLE16(*((WORD *)(lpStream+64)));
- if ((!norders) || (norders > MAX_ORDERS)) return FALSE;
- restartpos = bswapLE16(*((WORD *)(lpStream+66)));
- channels = bswapLE16(*((WORD *)(lpStream+68)));
- if ((!channels) || (channels > 64)) return FALSE;
- m_nType = MOD_TYPE_XM;
- m_nMinPeriod = 27;
- m_nMaxPeriod = 54784;
- m_nChannels = channels;
- if (restartpos < norders) m_nRestartPos = restartpos;
- patterns = bswapLE16(*((WORD *)(lpStream+70)));
- if (patterns > 256) patterns = 256;
- instruments = bswapLE16(*((WORD *)(lpStream+72)));
- if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1;
- m_nInstruments = instruments;
- m_nSamples = 0;
- memcpy(&xmflags, lpStream+74, 2);
- xmflags = bswapLE16(xmflags);
- if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES;
- if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
- defspeed = bswapLE16(*((WORD *)(lpStream+76)));
- deftempo = bswapLE16(*((WORD *)(lpStream+78)));
- if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo;
- if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed;
- memcpy(Order, lpStream+80, norders);
- memset(InstUsed, 0, sizeof(InstUsed));
- if (patterns > MAX_PATTERNS)
- {
- UINT i, j;
- for (i=0; i<norders; i++)
- {
- if (Order[i] < patterns) InstUsed[Order[i]] = TRUE;
- }
- j = 0;
- for (i=0; i<256; i++)
- {
- if (InstUsed[i]) pattern_map[i] = j++;
- }
- for (i=0; i<256; i++)
- {
- if (!InstUsed[i])
- {
- pattern_map[i] = (j < MAX_PATTERNS) ? j : 0xFE;
- j++;
- }
- }
- for (i=0; i<norders; i++)
- {
- Order[i] = pattern_map[Order[i]];
- }
- } else
- {
- for (UINT i=0; i<256; i++) pattern_map[i] = i;
- }
- memset(InstUsed, 0, sizeof(InstUsed));
- dwMemPos = dwHdrSize + 60;
- if (dwMemPos + 8 >= dwMemLength) return TRUE;
- // Reading patterns
- memset(channels_used, 0, sizeof(channels_used));
- for (UINT ipat=0; ipat<patterns; ipat++)
- {
- UINT ipatmap = pattern_map[ipat];
- DWORD dwSize = 0;
- WORD rows=64, packsize=0;
- dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
- while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00))
- {
- if (dwMemPos + 4 >= dwMemLength) break;
- dwMemPos++;
- dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
- }
- rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5)));
- if ((!rows) || (rows > 256)) rows = 64;
- packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7)));
- if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE;
- dwMemPos += dwSize;
- if (dwMemPos + packsize + 4 > dwMemLength) return TRUE;
- MODCOMMAND *p;
- if (ipatmap < MAX_PATTERNS)
- {
- PatternSize[ipatmap] = rows;
- if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
- if (!packsize) continue;
- p = Patterns[ipatmap];
- } else p = NULL;
- const BYTE *src = lpStream+dwMemPos;
- UINT j=0;
- for (UINT row=0; row<rows; row++)
- {
- for (UINT chn=0; chn<m_nChannels; chn++)
- {
- if ((p) && (j < packsize))
- {
- BYTE b = src[j++];
- UINT vol = 0;
- if (b & 0x80)
- {
- if (b & 1) p->note = src[j++];
- if (b & 2) p->instr = src[j++];
- if (b & 4) vol = src[j++];
- if (b & 8) p->command = src[j++];
- if (b & 16) p->param = src[j++];
- } else
- {
- p->note = b;
- p->instr = src[j++];
- vol = src[j++];
- p->command = src[j++];
- p->param = src[j++];
- }
- if (p->note == 97) p->note = 0xFF; else
- if ((p->note) && (p->note < 97)) p->note += 12;
- if (p->note) channels_used[chn] = 1;
- if (p->command | p->param) ConvertModCommand(p);
- if (p->instr == 0xff) p->instr = 0;
- if (p->instr) InstUsed[p->instr] = TRUE;
- if ((vol >= 0x10) && (vol <= 0x50))
- {
- p->volcmd = VOLCMD_VOLUME;
- p->vol = vol - 0x10;
- } else
- if (vol >= 0x60)
- {
- UINT v = vol & 0xF0;
- vol &= 0x0F;
- p->vol = vol;
- switch(v)
- {
- // 60-6F: Volume Slide Down
- case 0x60: p->volcmd = VOLCMD_VOLSLIDEDOWN; break;
- // 70-7F: Volume Slide Up:
- case 0x70: p->volcmd = VOLCMD_VOLSLIDEUP; break;
- // 80-8F: Fine Volume Slide Down
- case 0x80: p->volcmd = VOLCMD_FINEVOLDOWN; break;
- // 90-9F: Fine Volume Slide Up
- case 0x90: p->volcmd = VOLCMD_FINEVOLUP; break;
- // A0-AF: Set Vibrato Speed
- case 0xA0: p->volcmd = VOLCMD_VIBRATOSPEED; break;
- // B0-BF: Vibrato
- case 0xB0: p->volcmd = VOLCMD_VIBRATO; break;
- // C0-CF: Set Panning
- case 0xC0: p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break;
- // D0-DF: Panning Slide Left
- case 0xD0: p->volcmd = VOLCMD_PANSLIDELEFT; break;
- // E0-EF: Panning Slide Right
- case 0xE0: p->volcmd = VOLCMD_PANSLIDERIGHT; break;
- // F0-FF: Tone Portamento
- case 0xF0: p->volcmd = VOLCMD_TONEPORTAMENTO; break;
- }
- }
- p++;
- } else
- if (j < packsize)
- {
- BYTE b = src[j++];
- if (b & 0x80)
- {
- if (b & 1) j++;
- if (b & 2) j++;
- if (b & 4) j++;
- if (b & 8) j++;
- if (b & 16) j++;
- } else j += 4;
- } else break;
- }
- }
- dwMemPos += packsize;
- }
- // Wrong offset check
- while (dwMemPos + 4 < dwMemLength)
- {
- DWORD d = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
- if (d < 0x300) break;
- dwMemPos++;
- }
- memset(samples_used, 0, sizeof(samples_used));
- unused_samples = 0;
- // Reading instruments
- for (UINT iIns=1; iIns<=instruments; iIns++)
- {
- XMINSTRUMENTHEADER *pih;
- BYTE flags[32];
- DWORD samplesize[32];
- UINT samplemap[32];
- WORD nsamples;
-
- if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE;
- pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos);
- if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE;
- if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue;
- memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER));
- memcpy(Headers[iIns]->name, pih->name, 22);
- if ((nsamples = pih->samples) > 0)
- {
- if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE;
- memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER));
- xmsh.shsize = bswapLE32(xmsh.shsize);
- for (int i = 0; i < 24; ++i) {
- xmsh.venv[i] = bswapLE16(xmsh.venv[i]);
- xmsh.penv[i] = bswapLE16(xmsh.penv[i]);
- }
- xmsh.volfade = bswapLE16(xmsh.volfade);
- xmsh.res = bswapLE16(xmsh.res);
- dwMemPos += bswapLE32(pih->size);
- } else
- {
- if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size);
- else dwMemPos += sizeof(XMINSTRUMENTHEADER);
- continue;
- }
- memset(samplemap, 0, sizeof(samplemap));
- if (nsamples > 32) return TRUE;
- UINT newsamples = m_nSamples;
- for (UINT nmap=0; nmap<nsamples; nmap++)
- {
- UINT n = m_nSamples+nmap+1;
- if (n >= MAX_SAMPLES)
- {
- n = m_nSamples;
- while (n > 0)
- {
- if (!Ins[n].pSample)
- {
- for (UINT xmapchk=0; xmapchk < nmap; xmapchk++)
- {
- if (samplemap[xmapchk] == n) goto alreadymapped;
- }
- for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
- {
- INSTRUMENTHEADER *pks = Headers[clrs];
- for (UINT ks=0; ks<128; ks++)
- {
- if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
- }
- }
- break;
- }
- alreadymapped:
- n--;
- }
-#ifndef FASTSOUNDLIB
- // Damn! more than 200 samples: look for duplicates
- if (!n)
- {
- if (!unused_samples)
- {
- unused_samples = DetectUnusedSamples(samples_used);
- if (!unused_samples) unused_samples = 0xFFFF;
- }
- if ((unused_samples) && (unused_samples != 0xFFFF))
- {
- for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext])
- {
- unused_samples--;
- samples_used[iext] = TRUE;
- DestroySample(iext);
- n = iext;
- for (UINT mapchk=0; mapchk<nmap; mapchk++)
- {
- if (samplemap[mapchk] == n) samplemap[mapchk] = 0;
- }
- for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
- {
- INSTRUMENTHEADER *pks = Headers[clrs];
- for (UINT ks=0; ks<128; ks++)
- {
- if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
- }
- }
- memset(&Ins[n], 0, sizeof(Ins[0]));
- break;
- }
- }
- }
-#endif // FASTSOUNDLIB
- }
- if (newsamples < n) newsamples = n;
- samplemap[nmap] = n;
- }
- m_nSamples = newsamples;
- // Reading Volume Envelope
- INSTRUMENTHEADER *penv = Headers[iIns];
- penv->nMidiProgram = pih->type;
- penv->nFadeOut = xmsh.volfade;
- penv->nPan = 128;
- penv->nPPC = 5*12;
- if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME;
- if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
- if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP;
- if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING;
- if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN;
- if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP;
- if (xmsh.vnum > 12) xmsh.vnum = 12;
- if (xmsh.pnum > 12) xmsh.pnum = 12;
- penv->nVolEnv = xmsh.vnum;
- if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME;
- if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING;
- penv->nPanEnv = xmsh.pnum;
- penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain;
- if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN;
- penv->nVolLoopStart = xmsh.vloops;
- penv->nVolLoopEnd = xmsh.vloope;
- if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0;
- if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
- penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain;
- if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN;
- penv->nPanLoopStart = xmsh.ploops;
- penv->nPanLoopEnd = xmsh.ploope;
- if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0;
- if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
- penv->nGlobalVol = 64;
- for (UINT ienv=0; ienv<12; ienv++)
- {
- penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2];
- penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1];
- penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2];
- penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1];
- if (ienv)
- {
- if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1])
- {
- penv->VolPoints[ienv] &= 0xFF;
- penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00;
- if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100;
- }
- if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1])
- {
- penv->PanPoints[ienv] &= 0xFF;
- penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00;
- if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100;
- }
- }
- }
- for (UINT j=0; j<96; j++)
- {
- penv->NoteMap[j+12] = j+1+12;
- if (xmsh.snum[j] < nsamples)
- penv->Keyboard[j+12] = samplemap[xmsh.snum[j]];
- }
- // Reading samples
- for (UINT ins=0; ins<nsamples; ins++)
- {
- if ((dwMemPos + sizeof(xmss) > dwMemLength)
- || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE;
- memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss));
- xmss.samplen = bswapLE32(xmss.samplen);
- xmss.loopstart = bswapLE32(xmss.loopstart);
- xmss.looplen = bswapLE32(xmss.looplen);
- dwMemPos += xmsh.shsize;
- flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D;
- if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D;
- samplesize[ins] = xmss.samplen;
- if (!samplemap[ins]) continue;
- if (xmss.type & 0x10)
- {
- xmss.looplen >>= 1;
- xmss.loopstart >>= 1;
- xmss.samplen >>= 1;
- }
- if (xmss.type & 0x20)
- {
- xmss.looplen >>= 1;
- xmss.loopstart >>= 1;
- xmss.samplen >>= 1;
- }
- if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH;
- if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3;
- xmss.looplen += xmss.loopstart;
- if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen;
- if (!xmss.looplen) xmss.type &= ~3;
- UINT imapsmp = samplemap[ins];
- memcpy(m_szNames[imapsmp], xmss.name, 22);
- m_szNames[imapsmp][22] = 0;
- MODINSTRUMENT *pins = &Ins[imapsmp];
- pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen;
- pins->nLoopStart = xmss.loopstart;
- pins->nLoopEnd = xmss.looplen;
- if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
- if (pins->nLoopStart >= pins->nLoopEnd)
- {
- pins->nLoopStart = pins->nLoopEnd = 0;
- }
- if (xmss.type & 3) pins->uFlags |= CHN_LOOP;
- if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP;
- pins->nVolume = xmss.vol << 2;
- if (pins->nVolume > 256) pins->nVolume = 256;
- pins->nGlobalVol = 64;
- if ((xmss.res == 0xAD) && (!(xmss.type & 0x30)))
- {
- flags[ins] = RS_ADPCM4;
- samplesize[ins] = (samplesize[ins]+1)/2 + 16;
- }
- pins->nFineTune = xmss.finetune;
- pins->RelativeTone = (int)xmss.relnote;
- pins->nPan = xmss.pan;
- pins->uFlags |= CHN_PANNING;
- pins->nVibType = xmsh.vibtype;
- pins->nVibSweep = xmsh.vibsweep;
- pins->nVibDepth = xmsh.vibdepth;
- pins->nVibRate = xmsh.vibrate;
- memcpy(pins->name, xmss.name, 22);
- pins->name[21] = 0;
- }
-#if 0
- if ((xmsh.reserved2 > nsamples) && (xmsh.reserved2 <= 16))
- {
- dwMemPos += (((UINT)xmsh.reserved2) - nsamples) * xmsh.shsize;
- }
-#endif
- for (UINT ismpd=0; ismpd<nsamples; ismpd++)
- {
- if ((samplemap[ismpd]) && (samplesize[ismpd]) && (dwMemPos < dwMemLength))
- {
- ReadSample(&Ins[samplemap[ismpd]], flags[ismpd], (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
- }
- dwMemPos += samplesize[ismpd];
- if (dwMemPos >= dwMemLength) break;
- }
- }
- // Read song comments: "TEXT"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574))
- {
- UINT len = *((DWORD *)(lpStream+dwMemPos+4));
- dwMemPos += 8;
- if ((dwMemPos + len <= dwMemLength) && (len < 16384))
- {
- m_lpszSongComments = new char[len+1];
- if (m_lpszSongComments)
- {
- memcpy(m_lpszSongComments, lpStream+dwMemPos, len);
- m_lpszSongComments[len] = 0;
- }
- dwMemPos += len;
- }
- }
- // Read midi config: "MIDI"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D))
- {
- UINT len = *((DWORD *)(lpStream+dwMemPos+4));
- dwMemPos += 8;
- if (len == sizeof(MODMIDICFG))
- {
- memcpy(&m_MidiCfg, lpStream+dwMemPos, len);
- m_dwSongFlags |= SONG_EMBEDMIDICFG;
- }
- }
- // Read pattern names: "PNAM"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
- {
- UINT len = *((DWORD *)(lpStream+dwMemPos+4));
- dwMemPos += 8;
- if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
- {
- m_lpszPatternNames = new char[len];
-
- if (m_lpszPatternNames)
- {
- m_nPatternNames = len / MAX_PATTERNNAME;
- memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
- }
- dwMemPos += len;
- }
- }
- // Read channel names: "CNAM"
- if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
- {
- UINT len = *((DWORD *)(lpStream+dwMemPos+4));
- dwMemPos += 8;
- if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME))
- {
- UINT n = len / MAX_CHANNELNAME;
- for (UINT i=0; i<n; i++)
- {
- memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
- ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
- }
- dwMemPos += len;
- }
- }
- // Read mix plugins information
- if (dwMemPos + 8 < dwMemLength)
- {
- dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
- }
- return TRUE;
-}
-
-
-#ifndef MODPLUG_NO_FILESAVE
-
-BOOL CSoundFile::SaveXM(LPCSTR lpszFileName, UINT nPacking)
-//---------------------------------------------------------
-{
- BYTE s[64*64*5];
- XMFILEHEADER header;
- XMINSTRUMENTHEADER xmih;
- XMSAMPLEHEADER xmsh;
- XMSAMPLESTRUCT xmss;
- BYTE smptable[32];
- BYTE xmph[9];
- FILE *f;
- int i;
-
- if ((!m_nChannels) || (!lpszFileName)) return FALSE;
- if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
- fwrite("Extended Module: ", 17, 1, f);
- fwrite(m_szNames[0], 20, 1, f);
- s[0] = 0x1A;
- lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "FastTracker v2.00 ");
- s[21] = 0x04;
- s[22] = 0x01;
- fwrite(s, 23, 1, f);
- // Writing song header
- memset(&header, 0, sizeof(header));
- header.size = sizeof(XMFILEHEADER);
- header.norder = 0;
- header.restartpos = m_nRestartPos;
- header.channels = m_nChannels;
- header.patterns = 0;
- for (i=0; i<MAX_ORDERS; i++)
- {
- if (Order[i] == 0xFF) break;
- header.norder++;
- if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1;
- }
- header.instruments = m_nInstruments;
- if (!header.instruments) header.instruments = m_nSamples;
- header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00;
- if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
- header.tempo = m_nDefaultTempo;
- header.speed = m_nDefaultSpeed;
- memcpy(header.order, Order, header.norder);
- fwrite(&header, 1, sizeof(header), f);
- // Writing patterns
- for (i=0; i<header.patterns; i++) if (Patterns[i])
- {
- MODCOMMAND *p = Patterns[i];
- UINT len = 0;
-
- memset(&xmph, 0, sizeof(xmph));
- xmph[0] = 9;
- xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
- xmph[6] = (BYTE)(PatternSize[i] >> 8);
- for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++)
- {
- UINT note = p->note;
- UINT param = ModSaveCommand(p, TRUE);
- UINT command = param >> 8;
- param &= 0xFF;
- if (note >= 0xFE) note = 97; else
- if ((note <= 12) || (note > 96+12)) note = 0; else
- note -= 12;
- UINT vol = 0;
- if (p->volcmd)
- {
- UINT volcmd = p->volcmd;
- switch(volcmd)
- {
- case VOLCMD_VOLUME: vol = 0x10 + p->vol; break;
- case VOLCMD_VOLSLIDEDOWN: vol = 0x60 + (p->vol & 0x0F); break;
- case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break;
- case VOLCMD_FINEVOLDOWN: vol = 0x80 + (p->vol & 0x0F); break;
- case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break;
- case VOLCMD_VIBRATOSPEED: vol = 0xA0 + (p->vol & 0x0F); break;
- case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break;
- case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break;
- case VOLCMD_PANSLIDELEFT: vol = 0xD0 + (p->vol & 0x0F); break;
- case VOLCMD_PANSLIDERIGHT: vol = 0xE0 + (p->vol & 0x0F); break;
- case VOLCMD_TONEPORTAMENTO: vol = 0xF0 + (p->vol & 0x0F); break;
- }
- }
- if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param))
- {
- s[len++] = note;
- s[len++] = p->instr;
- s[len++] = vol;
- s[len++] = command;
- s[len++] = param;
- } else
- {
- BYTE b = 0x80;
- if (note) b |= 0x01;
- if (p->instr) b |= 0x02;
- if (vol >= 0x10) b |= 0x04;
- if (command) b |= 0x08;
- if (param) b |= 0x10;
- s[len++] = b;
- if (b & 1) s[len++] = note;
- if (b & 2) s[len++] = p->instr;
- if (b & 4) s[len++] = vol;
- if (b & 8) s[len++] = command;
- if (b & 16) s[len++] = param;
- }
- if (len > sizeof(s) - 5) break;
- }
- xmph[7] = (BYTE)(len & 0xFF);
- xmph[8] = (BYTE)(len >> 8);
- fwrite(xmph, 1, 9, f);
- fwrite(s, 1, len, f);
- } else
- {
- memset(&xmph, 0, sizeof(xmph));
- xmph[0] = 9;
- xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
- xmph[6] = (BYTE)(PatternSize[i] >> 8);
- fwrite(xmph, 1, 9, f);
- }
- // Writing instruments
- for (i=1; i<=header.instruments; i++)
- {
- MODINSTRUMENT *pins;
- BYTE flags[32];
-
- memset(&xmih, 0, sizeof(xmih));
- memset(&xmsh, 0, sizeof(xmsh));
- xmih.size = sizeof(xmih) + sizeof(xmsh);
- memcpy(xmih.name, m_szNames[i], 22);
- xmih.type = 0;
- xmih.samples = 0;
- if (m_nInstruments)
- {
- INSTRUMENTHEADER *penv = Headers[i];
- if (penv)
- {
- memcpy(xmih.name, penv->name, 22);
- xmih.type = penv->nMidiProgram;
- xmsh.volfade = penv->nFadeOut;
- xmsh.vnum = (BYTE)penv->nVolEnv;
- xmsh.pnum = (BYTE)penv->nPanEnv;
- if (xmsh.vnum > 12) xmsh.vnum = 12;
- if (xmsh.pnum > 12) xmsh.pnum = 12;
- for (UINT ienv=0; ienv<12; ienv++)
- {
- xmsh.venv[ienv*2] = penv->VolPoints[ienv];
- xmsh.venv[ienv*2+1] = penv->VolEnv[ienv];
- xmsh.penv[ienv*2] = penv->PanPoints[ienv];
- xmsh.penv[ienv*2+1] = penv->PanEnv[ienv];
- }
- if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1;
- if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2;
- if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4;
- if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1;
- if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2;
- if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4;
- xmsh.vsustain = (BYTE)penv->nVolSustainBegin;
- xmsh.vloops = (BYTE)penv->nVolLoopStart;
- xmsh.vloope = (BYTE)penv->nVolLoopEnd;
- xmsh.psustain = (BYTE)penv->nPanSustainBegin;
- xmsh.ploops = (BYTE)penv->nPanLoopStart;
- xmsh.ploope = (BYTE)penv->nPanLoopEnd;
- for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12])
- {
- UINT k;
- for (k=0; k<xmih.samples; k++) if (smptable[k] == penv->Keyboard[j+12]) break;
- if (k == xmih.samples)
- {
- smptable[xmih.samples++] = penv->Keyboard[j+12];
- }
- if (xmih.samples >= 32) break;
- xmsh.snum[j] = k;
- }
-// xmsh.reserved2 = xmih.samples;
- }
- } else
- {
- xmih.samples = 1;
-// xmsh.reserved2 = 1;
- smptable[0] = i;
- }
- xmsh.shsize = (xmih.samples) ? 40 : 0;
- fwrite(&xmih, 1, sizeof(xmih), f);
- if (smptable[0])
- {
- MODINSTRUMENT *pvib = &Ins[smptable[0]];
- xmsh.vibtype = pvib->nVibType;
- xmsh.vibsweep = pvib->nVibSweep;
- xmsh.vibdepth = pvib->nVibDepth;
- xmsh.vibrate = pvib->nVibRate;
- }
- fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f);
- if (!xmih.samples) continue;
- for (UINT ins=0; ins<xmih.samples; ins++)
- {
- memset(&xmss, 0, sizeof(xmss));
- if (smptable[ins]) memcpy(xmss.name, m_szNames[smptable[ins]], 22);
- pins = &Ins[smptable[ins]];
- xmss.samplen = pins->nLength;
- xmss.loopstart = pins->nLoopStart;
- xmss.looplen = pins->nLoopEnd - pins->nLoopStart;
- xmss.vol = pins->nVolume / 4;
- xmss.finetune = (char)pins->nFineTune;
- xmss.type = 0;
- if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1;
- flags[ins] = RS_PCM8D;
-#ifndef NO_PACKING
- if (nPacking)
- {
- if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
- && (CanPackSample(pins->pSample, pins->nLength, nPacking)))
- {
- flags[ins] = RS_ADPCM4;
- xmss.res = 0xAD;
- }
- } else
-#endif
- {
- if (pins->uFlags & CHN_16BIT)
- {
- flags[ins] = RS_PCM16D;
- xmss.type |= 0x10;
- xmss.looplen *= 2;
- xmss.loopstart *= 2;
- xmss.samplen *= 2;
- }
- if (pins->uFlags & CHN_STEREO)
- {
- flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
- xmss.type |= 0x20;
- xmss.looplen *= 2;
- xmss.loopstart *= 2;
- xmss.samplen *= 2;
- }
- }
- xmss.pan = 255;
- if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan;
- xmss.relnote = (signed char)pins->RelativeTone;
- fwrite(&xmss, 1, xmsh.shsize, f);
- }
- for (UINT ismpd=0; ismpd<xmih.samples; ismpd++)
- {
- pins = &Ins[smptable[ismpd]];
- if (pins->pSample)
- {
-#ifndef NO_PACKING
- if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample(pins->pSample, pins->nLength, nPacking);
-#endif // NO_PACKING
- WriteSample(f, pins, flags[ismpd]);
- }
- }
- }
- // Writing song comments
- if ((m_lpszSongComments) && (m_lpszSongComments[0]))
- {
- DWORD d = 0x74786574;
- fwrite(&d, 1, 4, f);
- d = strlen(m_lpszSongComments);
- fwrite(&d, 1, 4, f);
- fwrite(m_lpszSongComments, 1, d, f);
- }
- // Writing midi cfg
- if (m_dwSongFlags & SONG_EMBEDMIDICFG)
- {
- DWORD d = 0x4944494D;
- fwrite(&d, 1, 4, f);
- d = sizeof(MODMIDICFG);
- fwrite(&d, 1, 4, f);
- fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
- }
- // Writing Pattern Names
- if ((m_nPatternNames) && (m_lpszPatternNames))
- {
- DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME;
- while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME;
- if (dwLen >= MAX_PATTERNNAME)
- {
- DWORD d = 0x4d414e50;
- fwrite(&d, 1, 4, f);
- fwrite(&dwLen, 1, 4, f);
- fwrite(m_lpszPatternNames, 1, dwLen, f);
- }
- }
- // Writing Channel Names
- {
- UINT nChnNames = 0;
- for (UINT inam=0; inam<m_nChannels; inam++)
- {
- if (ChnSettings[inam].szName[0]) nChnNames = inam+1;
- }
- // Do it!
- if (nChnNames)
- {
- DWORD dwLen = nChnNames * MAX_CHANNELNAME;
- DWORD d = 0x4d414e43;
- fwrite(&d, 1, 4, f);
- fwrite(&dwLen, 1, 4, f);
- for (UINT inam=0; inam<nChnNames; inam++)
- {
- fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
- }
- }
- }
- // Save mix plugins information
- SaveMixPlugins(f);
- fclose(f);
- return TRUE;
-}
-
-#endif // MODPLUG_NO_FILESAVE
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
-
-typedef struct MMCMPFILEHEADER
-{
- DWORD id_ziRC; // "ziRC"
- DWORD id_ONia; // "ONia"
- WORD hdrsize;
-} MMCMPFILEHEADER, *LPMMCMPFILEHEADER;
-
-typedef struct MMCMPHEADER
-{
- WORD version;
- WORD nblocks;
- DWORD filesize;
- DWORD blktable;
- BYTE glb_comp;
- BYTE fmt_comp;
-} MMCMPHEADER, *LPMMCMPHEADER;
-
-typedef struct MMCMPBLOCK
-{
- DWORD unpk_size;
- DWORD pk_size;
- DWORD xor_chk;
- WORD sub_blk;
- WORD flags;
- WORD tt_entries;
- WORD num_bits;
-} MMCMPBLOCK, *LPMMCMPBLOCK;
-
-typedef struct MMCMPSUBBLOCK
-{
- DWORD unpk_pos;
- DWORD unpk_size;
-} MMCMPSUBBLOCK, *LPMMCMPSUBBLOCK;
-
-#define MMCMP_COMP 0x0001
-#define MMCMP_DELTA 0x0002
-#define MMCMP_16BIT 0x0004
-#define MMCMP_STEREO 0x0100
-#define MMCMP_ABS16 0x0200
-#define MMCMP_ENDIAN 0x0400
-
-typedef struct MMCMPBITBUFFER
-{
- UINT bitcount;
- DWORD bitbuffer;
- LPCBYTE pSrc;
- LPCBYTE pEnd;
-
- DWORD GetBits(UINT nBits);
-} MMCMPBITBUFFER;
-
-
-DWORD MMCMPBITBUFFER::GetBits(UINT nBits)
-//---------------------------------------
-{
- DWORD d;
- if (!nBits) return 0;
- while (bitcount < 24)
- {
- bitbuffer |= ((pSrc < pEnd) ? *pSrc++ : 0) << bitcount;
- bitcount += 8;
- }
- d = bitbuffer & ((1 << nBits) - 1);
- bitbuffer >>= nBits;
- bitcount -= nBits;
- return d;
-}
-
-//#define MMCMP_LOG
-
-#ifdef MMCMP_LOG
-extern void Log(LPCSTR s, ...);
-#endif
-
-const DWORD MMCMP8BitCommands[8] =
-{
- 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8
-};
-
-const UINT MMCMP8BitFetch[8] =
-{
- 3, 3, 3, 3, 2, 1, 0, 0
-};
-
-const DWORD MMCMP16BitCommands[16] =
-{
- 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF0,
- 0x1F0, 0x3F0, 0x7F0, 0xFF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
-};
-
-const UINT MMCMP16BitFetch[16] =
-{
- 4, 4, 4, 4, 3, 2, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-
-BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
-//---------------------------------------------------------
-{
- DWORD dwMemLength = *pdwMemLength;
- LPCBYTE lpMemFile = *ppMemFile;
- LPBYTE pBuffer;
- LPMMCMPFILEHEADER pmfh = (LPMMCMPFILEHEADER)(lpMemFile);
- LPMMCMPHEADER pmmh = (LPMMCMPHEADER)(lpMemFile+10);
- LPDWORD pblk_table;
- DWORD dwFileSize;
-
- if (PP20_Unpack(ppMemFile, pdwMemLength))
- {
- return TRUE;
- }
- if ((dwMemLength < 256) || (!pmfh) || (pmfh->id_ziRC != 0x4352697A) || (pmfh->id_ONia != 0x61694e4f) || (pmfh->hdrsize < 14)
- || (!pmmh->nblocks) || (pmmh->filesize < 16) || (pmmh->filesize > 0x8000000)
- || (pmmh->blktable >= dwMemLength) || (pmmh->blktable + 4*pmmh->nblocks > dwMemLength)) return FALSE;
- dwFileSize = pmmh->filesize;
- if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwFileSize + 31) & ~15)) == NULL) return FALSE;
- pblk_table = (LPDWORD)(lpMemFile+pmmh->blktable);
- for (UINT nBlock=0; nBlock<pmmh->nblocks; nBlock++)
- {
- DWORD dwMemPos = pblk_table[nBlock];
- LPMMCMPBLOCK pblk = (LPMMCMPBLOCK)(lpMemFile+dwMemPos);
- LPMMCMPSUBBLOCK psubblk = (LPMMCMPSUBBLOCK)(lpMemFile+dwMemPos+20);
-
- if ((dwMemPos + 20 >= dwMemLength) || (dwMemPos + 20 + pblk->sub_blk*8 >= dwMemLength)) break;
- dwMemPos += 20 + pblk->sub_blk*8;
-#ifdef MMCMP_LOG
- Log("block %d: flags=%04X sub_blocks=%d", nBlock, (UINT)pblk->flags, (UINT)pblk->sub_blk);
- Log(" pksize=%d unpksize=%d", pblk->pk_size, pblk->unpk_size);
- Log(" tt_entries=%d num_bits=%d\n", pblk->tt_entries, pblk->num_bits);
-#endif
- // Data is not packed
- if (!(pblk->flags & MMCMP_COMP))
- {
- for (UINT i=0; i<pblk->sub_blk; i++)
- {
- if ((psubblk->unpk_pos > dwFileSize) || (psubblk->unpk_pos + psubblk->unpk_size > dwFileSize)) break;
-#ifdef MMCMP_LOG
- Log(" Unpacked sub-block %d: offset %d, size=%d\n", i, psubblk->unpk_pos, psubblk->unpk_size);
-#endif
- memcpy(pBuffer+psubblk->unpk_pos, lpMemFile+dwMemPos, psubblk->unpk_size);
- dwMemPos += psubblk->unpk_size;
- psubblk++;
- }
- } else
- // Data is 16-bit packed
- if (pblk->flags & MMCMP_16BIT)
- {
- MMCMPBITBUFFER bb;
- LPWORD pDest = (LPWORD)(pBuffer + psubblk->unpk_pos);
- DWORD dwSize = psubblk->unpk_size >> 1;
- DWORD dwPos = 0;
- UINT numbits = pblk->num_bits;
- UINT subblk = 0, oldval = 0;
-
-#ifdef MMCMP_LOG
- Log(" 16-bit block: pos=%d size=%d ", psubblk->unpk_pos, psubblk->unpk_size);
- if (pblk->flags & MMCMP_DELTA) Log("DELTA ");
- if (pblk->flags & MMCMP_ABS16) Log("ABS16 ");
- Log("\n");
-#endif
- bb.bitcount = 0;
- bb.bitbuffer = 0;
- bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
- bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
- while (subblk < pblk->sub_blk)
- {
- UINT newval = 0x10000;
- DWORD d = bb.GetBits(numbits+1);
-
- if (d >= MMCMP16BitCommands[numbits])
- {
- UINT nFetch = MMCMP16BitFetch[numbits];
- UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP16BitCommands[numbits]) << nFetch);
- if (newbits != numbits)
- {
- numbits = newbits & 0x0F;
- } else
- {
- if ((d = bb.GetBits(4)) == 0x0F)
- {
- if (bb.GetBits(1)) break;
- newval = 0xFFFF;
- } else
- {
- newval = 0xFFF0 + d;
- }
- }
- } else
- {
- newval = d;
- }
- if (newval < 0x10000)
- {
- newval = (newval & 1) ? (UINT)(-(LONG)((newval+1) >> 1)) : (UINT)(newval >> 1);
- if (pblk->flags & MMCMP_DELTA)
- {
- newval += oldval;
- oldval = newval;
- } else
- if (!(pblk->flags & MMCMP_ABS16))
- {
- newval ^= 0x8000;
- }
- pDest[dwPos++] = (WORD)newval;
- }
- if (dwPos >= dwSize)
- {
- subblk++;
- dwPos = 0;
- dwSize = psubblk[subblk].unpk_size >> 1;
- pDest = (LPWORD)(pBuffer + psubblk[subblk].unpk_pos);
- }
- }
- } else
- // Data is 8-bit packed
- {
- MMCMPBITBUFFER bb;
- LPBYTE pDest = pBuffer + psubblk->unpk_pos;
- DWORD dwSize = psubblk->unpk_size;
- DWORD dwPos = 0;
- UINT numbits = pblk->num_bits;
- UINT subblk = 0, oldval = 0;
- LPCBYTE ptable = lpMemFile+dwMemPos;
-
- bb.bitcount = 0;
- bb.bitbuffer = 0;
- bb.pSrc = lpMemFile+dwMemPos+pblk->tt_entries;
- bb.pEnd = lpMemFile+dwMemPos+pblk->pk_size;
- while (subblk < pblk->sub_blk)
- {
- UINT newval = 0x100;
- DWORD d = bb.GetBits(numbits+1);
-
- if (d >= MMCMP8BitCommands[numbits])
- {
- UINT nFetch = MMCMP8BitFetch[numbits];
- UINT newbits = bb.GetBits(nFetch) + ((d - MMCMP8BitCommands[numbits]) << nFetch);
- if (newbits != numbits)
- {
- numbits = newbits & 0x07;
- } else
- {
- if ((d = bb.GetBits(3)) == 7)
- {
- if (bb.GetBits(1)) break;
- newval = 0xFF;
- } else
- {
- newval = 0xF8 + d;
- }
- }
- } else
- {
- newval = d;
- }
- if (newval < 0x100)
- {
- int n = ptable[newval];
- if (pblk->flags & MMCMP_DELTA)
- {
- n += oldval;
- oldval = n;
- }
- pDest[dwPos++] = (BYTE)n;
- }
- if (dwPos >= dwSize)
- {
- subblk++;
- dwPos = 0;
- dwSize = psubblk[subblk].unpk_size;
- pDest = pBuffer + psubblk[subblk].unpk_pos;
- }
- }
- }
- }
- *ppMemFile = pBuffer;
- *pdwMemLength = dwFileSize;
- return TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// PowerPack PP20 Unpacker
-//
-
-typedef struct _PPBITBUFFER
-{
- UINT bitcount;
- ULONG bitbuffer;
- LPCBYTE pStart;
- LPCBYTE pSrc;
-
- ULONG GetBits(UINT n);
-} PPBITBUFFER;
-
-
-ULONG PPBITBUFFER::GetBits(UINT n)
-{
- ULONG result = 0;
-
- for (UINT i=0; i<n; i++)
- {
- if (!bitcount)
- {
- bitcount = 8;
- if (pSrc != pStart) pSrc--;
- bitbuffer = *pSrc;
- }
- result = (result<<1) | (bitbuffer&1);
- bitbuffer >>= 1;
- bitcount--;
- }
- return result;
-}
-
-
-VOID PP20_DoUnpack(const BYTE *pSrc, UINT nSrcLen, BYTE *pDst, UINT nDstLen)
-{
- PPBITBUFFER BitBuffer;
- ULONG nBytesLeft;
-
- BitBuffer.pStart = pSrc;
- BitBuffer.pSrc = pSrc + nSrcLen - 4;
- BitBuffer.bitbuffer = 0;
- BitBuffer.bitcount = 0;
- BitBuffer.GetBits(pSrc[nSrcLen-1]);
- nBytesLeft = nDstLen;
- while (nBytesLeft > 0)
- {
- if (!BitBuffer.GetBits(1))
- {
- UINT n = 1;
- while (n < nBytesLeft)
- {
- UINT code = BitBuffer.GetBits(2);
- n += code;
- if (code != 3) break;
- }
- for (UINT i=0; i<n; i++)
- {
- pDst[--nBytesLeft] = (BYTE)BitBuffer.GetBits(8);
- }
- if (!nBytesLeft) break;
- }
- {
- UINT n = BitBuffer.GetBits(2)+1;
- UINT nbits = pSrc[n-1];
- UINT nofs;
- if (n==4)
- {
- nofs = BitBuffer.GetBits( (BitBuffer.GetBits(1)) ? nbits : 7 );
- while (n < nBytesLeft)
- {
- UINT code = BitBuffer.GetBits(3);
- n += code;
- if (code != 7) break;
- }
- } else
- {
- nofs = BitBuffer.GetBits(nbits);
- }
- for (UINT i=0; i<=n; i++)
- {
- pDst[nBytesLeft-1] = (nBytesLeft+nofs < nDstLen) ? pDst[nBytesLeft+nofs] : 0;
- if (!--nBytesLeft) break;
- }
- }
- }
-}
-
-
-BOOL PP20_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength)
-{
- DWORD dwMemLength = *pdwMemLength;
- LPCBYTE lpMemFile = *ppMemFile;
- DWORD dwDstLen;
- LPBYTE pBuffer;
-
- if ((!lpMemFile) || (dwMemLength < 256) || (*(DWORD *)lpMemFile != 0x30325050)) return FALSE;
- dwDstLen = (lpMemFile[dwMemLength-4]<<16) | (lpMemFile[dwMemLength-3]<<8) | (lpMemFile[dwMemLength-2]);
- //Log("PP20 detected: Packed length=%d, Unpacked length=%d\n", dwMemLength, dwDstLen);
- if ((dwDstLen < 512) || (dwDstLen > 0x400000) || (dwDstLen > 16*dwMemLength)) return FALSE;
- if ((pBuffer = (LPBYTE)GlobalAllocPtr(GHND, (dwDstLen + 31) & ~15)) == NULL) return FALSE;
- PP20_DoUnpack(lpMemFile+4, dwMemLength-4, pBuffer, dwDstLen);
- *ppMemFile = pBuffer;
- *pdwMemLength = dwDstLen;
- return TRUE;
-}
-
-
-
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Kenton Varda <temporal@gauge3d.org> (C interface wrapper)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "modplug.h"
-#include "stdafx.h"
-#include "sndfile.h"
-
-struct _ModPlugFile
-{
- CSoundFile mSoundFile;
-};
-
-namespace ModPlug
-{
- ModPlug_Settings gSettings =
- {
- MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION,
-
- 2,
- 16,
- 44100,
- MODPLUG_RESAMPLE_LINEAR,
-
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- };
-
- int gSampleSize;
-
- void UpdateSettings(bool updateBasicConfig)
- {
- if(gSettings.mFlags & MODPLUG_ENABLE_REVERB)
- {
- CSoundFile::SetReverbParameters(gSettings.mReverbDepth,
- gSettings.mReverbDelay);
- }
-
- if(gSettings.mFlags & MODPLUG_ENABLE_MEGABASS)
- {
- CSoundFile::SetXBassParameters(gSettings.mBassAmount,
- gSettings.mBassRange);
- }
- else // modplug seems to ignore the SetWaveConfigEx() setting for bass boost
- CSoundFile::SetXBassParameters(0, 0);
-
- if(gSettings.mFlags & MODPLUG_ENABLE_SURROUND)
- {
- CSoundFile::SetSurroundParameters(gSettings.mSurroundDepth,
- gSettings.mSurroundDelay);
- }
-
- if(updateBasicConfig)
- {
- CSoundFile::SetWaveConfig(gSettings.mFrequency,
- gSettings.mBits,
- gSettings.mChannels);
-
- gSampleSize = gSettings.mBits / 8 * gSettings.mChannels;
- }
-
- CSoundFile::SetWaveConfigEx(gSettings.mFlags & MODPLUG_ENABLE_SURROUND,
- !(gSettings.mFlags & MODPLUG_ENABLE_OVERSAMPLING),
- gSettings.mFlags & MODPLUG_ENABLE_REVERB,
- true,
- gSettings.mFlags & MODPLUG_ENABLE_MEGABASS,
- gSettings.mFlags & MODPLUG_ENABLE_NOISE_REDUCTION,
- false);
- CSoundFile::SetResamplingMode(gSettings.mResamplingMode);
- }
-}
-
-ModPlugFile* ModPlug_Load(const void* data, int size)
-{
- ModPlugFile* result = new ModPlugFile;
- ModPlug::UpdateSettings(true);
- if(result->mSoundFile.Create((const BYTE*)data, size))
- {
- result->mSoundFile.SetRepeatCount(ModPlug::gSettings.mLoopCount);
- return result;
- }
- else
- {
- delete result;
- return NULL;
- }
-}
-
-void ModPlug_Unload(ModPlugFile* file)
-{
- file->mSoundFile.Destroy();
- delete file;
-}
-
-int ModPlug_Read(ModPlugFile* file, void* buffer, int size)
-{
- return file->mSoundFile.Read(buffer, size) * ModPlug::gSampleSize;
-}
-
-const char* ModPlug_GetName(ModPlugFile* file)
-{
- return file->mSoundFile.GetTitle();
-}
-
-int ModPlug_GetLength(ModPlugFile* file)
-{
- return file->mSoundFile.GetSongTime() * 1000;
-}
-
-void ModPlug_Seek(ModPlugFile* file, int millisecond)
-{
- int maxpos;
- int maxtime = file->mSoundFile.GetSongTime() * 1000;
- float postime;
-
- if(millisecond > maxtime)
- millisecond = maxtime;
- maxpos = file->mSoundFile.GetMaxPosition();
- postime = (float)maxpos / (float)maxtime;
-
- file->mSoundFile.SetCurrentPos((int)(millisecond * postime));
-}
-
-void ModPlug_GetSettings(ModPlug_Settings* settings)
-{
- memcpy(settings, &ModPlug::gSettings, sizeof(ModPlug_Settings));
-}
-
-void ModPlug_SetSettings(const ModPlug_Settings* settings)
-{
- memcpy(&ModPlug::gSettings, settings, sizeof(ModPlug_Settings));
- ModPlug::UpdateSettings(false);
-}
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Kenton Varda <temporal@gauge3d.org> (C interface wrapper)
- */
-
-#ifndef MODPLUG_H__INCLUDED
-#define MODPLUG_H__INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _ModPlugFile;
-typedef struct _ModPlugFile ModPlugFile;
-
-/* Load a mod file. [data] should point to a block of memory containing the complete
- * file, and [size] should be the size of that block.
- * Return the loaded mod file on success, or NULL on failure. */
-ModPlugFile* ModPlug_Load(const void* data, int size);
-/* Unload a mod file. */
-void ModPlug_Unload(ModPlugFile* file);
-
-/* Read sample data into the buffer. Returns the number of bytes read. If the end
- * of the mod has been reached, zero is returned. */
-int ModPlug_Read(ModPlugFile* file, void* buffer, int size);
-
-/* Get the name of the mod. The returned buffer is stored within the ModPlugFile
- * structure and will remain valid until you unload the file. */
-const char* ModPlug_GetName(ModPlugFile* file);
-
-/* Get the length of the mod, in milliseconds. Note that this result is not always
- * accurate, especially in the case of mods with loops. */
-int ModPlug_GetLength(ModPlugFile* file);
-
-/* Seek to a particular position in the song. Note that seeking and MODs don't mix very
- * well. Some mods will be missing instruments for a short time after a seek, as ModPlug
- * does not scan the sequence backwards to find out which instruments were supposed to be
- * playing at that time. (Doing so would be difficult and not very reliable.) Also,
- * note that seeking is not very exact in some mods -- especially those for which
- * ModPlug_GetLength() does not report the full length. */
-void ModPlug_Seek(ModPlugFile* file, int millisecond);
-
-enum _ModPlug_Flags
-{
- MODPLUG_ENABLE_OVERSAMPLING = 1 << 0, /* Enable oversampling (*highly* recommended) */
- MODPLUG_ENABLE_NOISE_REDUCTION = 1 << 1, /* Enable noise reduction */
- MODPLUG_ENABLE_REVERB = 1 << 2, /* Enable reverb */
- MODPLUG_ENABLE_MEGABASS = 1 << 3, /* Enable megabass */
- MODPLUG_ENABLE_SURROUND = 1 << 4 /* Enable surround sound. */
-};
-
-enum _ModPlug_ResamplingMode
-{
- MODPLUG_RESAMPLE_NEAREST = 0, /* No interpolation (very fast, extremely bad sound quality) */
- MODPLUG_RESAMPLE_LINEAR = 1, /* Linear interpolation (fast, good quality) */
- MODPLUG_RESAMPLE_SPLINE = 2, /* Cubic spline interpolation (high quality) */
- MODPLUG_RESAMPLE_FIR = 3 /* 8-tap fir filter (extremely high quality) */
-};
-
-typedef struct _ModPlug_Settings
-{
- int mFlags; /* One or more of the MODPLUG_ENABLE_* flags above, bitwise-OR'ed */
-
- /* Note that ModPlug always decodes sound at 44100kHz, 32 bit, stereo and then
- * down-mixes to the settings you choose. */
- int mChannels; /* Number of channels - 1 for mono or 2 for stereo */
- int mBits; /* Bits per sample - 8, 16, or 32 */
- int mFrequency; /* Sampling rate - 11025, 22050, or 44100 */
- int mResamplingMode; /* One of MODPLUG_RESAMPLE_*, above */
-
- int mReverbDepth; /* Reverb level 0(quiet)-100(loud) */
- int mReverbDelay; /* Reverb delay in ms, usually 40-200ms */
- int mBassAmount; /* XBass level 0(quiet)-100(loud) */
- int mBassRange; /* XBass cutoff in Hz 10-100 */
- int mSurroundDepth; /* Surround level 0(quiet)-100(heavy) */
- int mSurroundDelay; /* Surround delay in ms, usually 5-40ms */
- int mLoopCount; /* Number of times to loop. Zero prevents looping.
- -1 loops forever. */
-} ModPlug_Settings;
-
-/* Get and set the mod decoder settings. All options, except for channels, bits-per-sample,
- * sampling rate, and loop count, will take effect immediately. Those options which don't
- * take effect immediately will take effect the next time you load a mod. */
-void ModPlug_GetSettings(ModPlug_Settings* settings);
-void ModPlug_SetSettings(const ModPlug_Settings* settings);
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#ifdef FASTSOUNDLIB
-#define NO_REVERB
-#endif
-
-
-// Delayed Surround Filters
-#ifndef FASTSOUNDLIB
-#define nDolbyHiFltAttn 6
-#define nDolbyHiFltMask 3
-#define DOLBYATTNROUNDUP 31
-#else
-#define nDolbyHiFltAttn 3
-#define nDolbyHiFltMask 3
-#define DOLBYATTNROUNDUP 3
-#endif
-
-// Bass Expansion
-#define XBASS_DELAY 14 // 2.5 ms
-
-// Buffer Sizes
-#define XBASSBUFFERSIZE 64 // 2 ms at 50KHz
-#define FILTERBUFFERSIZE 64 // 1.25 ms
-#define SURROUNDBUFFERSIZE ((MAX_SAMPLE_RATE * 50) / 1000)
-#define REVERBBUFFERSIZE ((MAX_SAMPLE_RATE * 200) / 1000)
-#define REVERBBUFFERSIZE2 ((REVERBBUFFERSIZE*13) / 17)
-#define REVERBBUFFERSIZE3 ((REVERBBUFFERSIZE*7) / 13)
-#define REVERBBUFFERSIZE4 ((REVERBBUFFERSIZE*7) / 19)
-
-
-// DSP Effects: PUBLIC members
-UINT CSoundFile::m_nXBassDepth = 6;
-UINT CSoundFile::m_nXBassRange = XBASS_DELAY;
-UINT CSoundFile::m_nReverbDepth = 1;
-UINT CSoundFile::m_nReverbDelay = 100;
-UINT CSoundFile::m_nProLogicDepth = 12;
-UINT CSoundFile::m_nProLogicDelay = 20;
-
-////////////////////////////////////////////////////////////////////
-// DSP Effects internal state
-
-// Bass Expansion: low-pass filter
-static LONG nXBassSum = 0;
-static LONG nXBassBufferPos = 0;
-static LONG nXBassDlyPos = 0;
-static LONG nXBassMask = 0;
-
-// Noise Reduction: simple low-pass filter
-static LONG nLeftNR = 0;
-static LONG nRightNR = 0;
-
-// Surround Encoding: 1 delay line + low-pass filter + high-pass filter
-static LONG nSurroundSize = 0;
-static LONG nSurroundPos = 0;
-static LONG nDolbyDepth = 0;
-static LONG nDolbyLoDlyPos = 0;
-static LONG nDolbyLoFltPos = 0;
-static LONG nDolbyLoFltSum = 0;
-static LONG nDolbyHiFltPos = 0;
-static LONG nDolbyHiFltSum = 0;
-
-// Reverb: 4 delay lines + high-pass filter + low-pass filter
-#ifndef NO_REVERB
-static LONG nReverbSize = 0;
-static LONG nReverbBufferPos = 0;
-static LONG nReverbSize2 = 0;
-static LONG nReverbBufferPos2 = 0;
-static LONG nReverbSize3 = 0;
-static LONG nReverbBufferPos3 = 0;
-static LONG nReverbSize4 = 0;
-static LONG nReverbBufferPos4 = 0;
-static LONG nReverbLoFltSum = 0;
-static LONG nReverbLoFltPos = 0;
-static LONG nReverbLoDlyPos = 0;
-static LONG nFilterAttn = 0;
-static LONG gRvbLowPass[8];
-static LONG gRvbLPPos = 0;
-static LONG gRvbLPSum = 0;
-static LONG ReverbLoFilterBuffer[XBASSBUFFERSIZE];
-static LONG ReverbLoFilterDelay[XBASSBUFFERSIZE];
-static LONG ReverbBuffer[REVERBBUFFERSIZE];
-static LONG ReverbBuffer2[REVERBBUFFERSIZE2];
-static LONG ReverbBuffer3[REVERBBUFFERSIZE3];
-static LONG ReverbBuffer4[REVERBBUFFERSIZE4];
-#endif
-static LONG XBassBuffer[XBASSBUFFERSIZE];
-static LONG XBassDelay[XBASSBUFFERSIZE];
-static LONG DolbyLoFilterBuffer[XBASSBUFFERSIZE];
-static LONG DolbyLoFilterDelay[XBASSBUFFERSIZE];
-static LONG DolbyHiFilterBuffer[FILTERBUFFERSIZE];
-static LONG SurroundBuffer[SURROUNDBUFFERSIZE];
-
-// Access the main temporary mix buffer directly: avoids an extra pointer
-extern int MixSoundBuffer[MIXBUFFERSIZE*2];
-//cextern int MixReverbBuffer[MIXBUFFERSIZE*2];
-extern int MixReverbBuffer[MIXBUFFERSIZE*2];
-
-static UINT GetMaskFromSize(UINT len)
-//-----------------------------------
-{
- UINT n = 2;
- while (n <= len) n <<= 1;
- return ((n >> 1) - 1);
-}
-
-
-void CSoundFile::InitializeDSP(BOOL bReset)
-//-----------------------------------------
-{
- if (!m_nReverbDelay) m_nReverbDelay = 100;
- if (!m_nXBassRange) m_nXBassRange = XBASS_DELAY;
- if (!m_nProLogicDelay) m_nProLogicDelay = 20;
- if (m_nXBassDepth > 8) m_nXBassDepth = 8;
- if (m_nXBassDepth < 2) m_nXBassDepth = 2;
- if (bReset)
- {
- // Noise Reduction
- nLeftNR = nRightNR = 0;
- }
- // Pro-Logic Surround
- nSurroundPos = nSurroundSize = 0;
- nDolbyLoFltPos = nDolbyLoFltSum = nDolbyLoDlyPos = 0;
- nDolbyHiFltPos = nDolbyHiFltSum = 0;
- if (gdwSoundSetup & SNDMIX_SURROUND)
- {
- memset(DolbyLoFilterBuffer, 0, sizeof(DolbyLoFilterBuffer));
- memset(DolbyHiFilterBuffer, 0, sizeof(DolbyHiFilterBuffer));
- memset(DolbyLoFilterDelay, 0, sizeof(DolbyLoFilterDelay));
- memset(SurroundBuffer, 0, sizeof(SurroundBuffer));
- nSurroundSize = (gdwMixingFreq * m_nProLogicDelay) / 1000;
- if (nSurroundSize > SURROUNDBUFFERSIZE) nSurroundSize = SURROUNDBUFFERSIZE;
- if (m_nProLogicDepth < 8) nDolbyDepth = (32 >> m_nProLogicDepth) + 32;
- else nDolbyDepth = (m_nProLogicDepth < 16) ? (8 + (m_nProLogicDepth - 8) * 7) : 64;
- nDolbyDepth >>= 2;
- }
- // Reverb Setup
-#ifndef NO_REVERB
- if (gdwSoundSetup & SNDMIX_REVERB)
- {
- UINT nrs = (gdwMixingFreq * m_nReverbDelay) / 1000;
- UINT nfa = m_nReverbDepth+1;
- if (nrs > REVERBBUFFERSIZE) nrs = REVERBBUFFERSIZE;
- if ((bReset) || (nrs != (UINT)nReverbSize) || (nfa != (UINT)nFilterAttn))
- {
- nFilterAttn = nfa;
- nReverbSize = nrs;
- nReverbBufferPos = nReverbBufferPos2 = nReverbBufferPos3 = nReverbBufferPos4 = 0;
- nReverbLoFltSum = nReverbLoFltPos = nReverbLoDlyPos = 0;
- gRvbLPSum = gRvbLPPos = 0;
- nReverbSize2 = (nReverbSize * 13) / 17;
- if (nReverbSize2 > REVERBBUFFERSIZE2) nReverbSize2 = REVERBBUFFERSIZE2;
- nReverbSize3 = (nReverbSize * 7) / 13;
- if (nReverbSize3 > REVERBBUFFERSIZE3) nReverbSize3 = REVERBBUFFERSIZE3;
- nReverbSize4 = (nReverbSize * 7) / 19;
- if (nReverbSize4 > REVERBBUFFERSIZE4) nReverbSize4 = REVERBBUFFERSIZE4;
- memset(ReverbLoFilterBuffer, 0, sizeof(ReverbLoFilterBuffer));
- memset(ReverbLoFilterDelay, 0, sizeof(ReverbLoFilterDelay));
- memset(ReverbBuffer, 0, sizeof(ReverbBuffer));
- memset(ReverbBuffer2, 0, sizeof(ReverbBuffer2));
- memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3));
- memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4));
- memset(gRvbLowPass, 0, sizeof(gRvbLowPass));
- }
- } else nReverbSize = 0;
-#endif
- BOOL bResetBass = FALSE;
- // Bass Expansion Reset
- if (gdwSoundSetup & SNDMIX_MEGABASS)
- {
- UINT nXBassSamples = (gdwMixingFreq * m_nXBassRange) / 10000;
- if (nXBassSamples > XBASSBUFFERSIZE) nXBassSamples = XBASSBUFFERSIZE;
- UINT mask = GetMaskFromSize(nXBassSamples);
- if ((bReset) || (mask != (UINT)nXBassMask))
- {
- nXBassMask = mask;
- bResetBass = TRUE;
- }
- } else
- {
- nXBassMask = 0;
- bResetBass = TRUE;
- }
- if (bResetBass)
- {
- nXBassSum = nXBassBufferPos = nXBassDlyPos = 0;
- memset(XBassBuffer, 0, sizeof(XBassBuffer));
- memset(XBassDelay, 0, sizeof(XBassDelay));
- }
-}
-
-
-void CSoundFile::ProcessStereoDSP(int count)
-//------------------------------------------
-{
-#ifndef NO_REVERB
- // Reverb
- if (gdwSoundSetup & SNDMIX_REVERB)
- {
- int *pr = MixSoundBuffer, *pin = MixReverbBuffer, rvbcount = count;
- do
- {
- int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
- + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal
- // Delay line and remove Low Frequencies // v = original signal
- int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal
- ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
- nReverbLoDlyPos++;
- nReverbLoDlyPos &= 0x1F;
- int n = nReverbLoFltPos;
- nReverbLoFltSum -= ReverbLoFilterBuffer[n];
- int tmp = echo / 128;
- ReverbLoFilterBuffer[n] = tmp;
- nReverbLoFltSum += tmp;
- echodly -= nReverbLoFltSum;
- nReverbLoFltPos = (n + 1) & 0x3F;
- // Reverb
- int v = (pin[0]+pin[1]) >> nFilterAttn;
- pr[0] += pin[0] + echodly;
- pr[1] += pin[1] + echodly;
- v += echodly >> 2;
- ReverbBuffer3[nReverbBufferPos3] = v;
- ReverbBuffer4[nReverbBufferPos4] = v;
- v += echodly >> 4;
- v >>= 1;
- gRvbLPSum -= gRvbLowPass[gRvbLPPos];
- gRvbLPSum += v;
- gRvbLowPass[gRvbLPPos] = v;
- gRvbLPPos++;
- gRvbLPPos &= 7;
- int vlp = gRvbLPSum >> 2;
- ReverbBuffer[nReverbBufferPos] = vlp;
- ReverbBuffer2[nReverbBufferPos2] = vlp;
- if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
- if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
- if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
- if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
- pr += 2;
- pin += 2;
- } while (--rvbcount);
- }
-#endif
- // Dolby Pro-Logic Surround
- if (gdwSoundSetup & SNDMIX_SURROUND)
- {
- int *pr = MixSoundBuffer, n = nDolbyLoFltPos;
- for (int r=count; r; r--)
- {
- int v = (pr[0]+pr[1]+DOLBYATTNROUNDUP) >> (nDolbyHiFltAttn+1);
-#ifndef FASTSOUNDLIB
- v *= (int)nDolbyDepth;
-#endif
- // Low-Pass Filter
- nDolbyHiFltSum -= DolbyHiFilterBuffer[nDolbyHiFltPos];
- DolbyHiFilterBuffer[nDolbyHiFltPos] = v;
- nDolbyHiFltSum += v;
- v = nDolbyHiFltSum;
- nDolbyHiFltPos++;
- nDolbyHiFltPos &= nDolbyHiFltMask;
- // Surround
- int secho = SurroundBuffer[nSurroundPos];
- SurroundBuffer[nSurroundPos] = v;
- // Delay line and remove low frequencies
- v = DolbyLoFilterDelay[nDolbyLoDlyPos]; // v = delayed signal
- DolbyLoFilterDelay[nDolbyLoDlyPos] = secho; // secho = signal
- nDolbyLoDlyPos++;
- nDolbyLoDlyPos &= 0x1F;
- nDolbyLoFltSum -= DolbyLoFilterBuffer[n];
- int tmp = secho / 64;
- DolbyLoFilterBuffer[n] = tmp;
- nDolbyLoFltSum += tmp;
- v -= nDolbyLoFltSum;
- n++;
- n &= 0x3F;
- // Add echo
- pr[0] += v;
- pr[1] -= v;
- if (++nSurroundPos >= nSurroundSize) nSurroundPos = 0;
- pr += 2;
- }
- nDolbyLoFltPos = n;
- }
- // Bass Expansion
- if (gdwSoundSetup & SNDMIX_MEGABASS)
- {
- int *px = MixSoundBuffer;
- int xba = m_nXBassDepth+1, xbamask = (1 << xba) - 1;
- int n = nXBassBufferPos;
- for (int x=count; x; x--)
- {
- nXBassSum -= XBassBuffer[n];
- int tmp0 = px[0] + px[1];
- int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
- XBassBuffer[n] = tmp;
- nXBassSum += tmp;
- int v = XBassDelay[nXBassDlyPos];
- XBassDelay[nXBassDlyPos] = px[0];
- px[0] = v + nXBassSum;
- v = XBassDelay[nXBassDlyPos+1];
- XBassDelay[nXBassDlyPos+1] = px[1];
- px[1] = v + nXBassSum;
- nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
- px += 2;
- n++;
- n &= nXBassMask;
- }
- nXBassBufferPos = n;
- }
- // Noise Reduction
- if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
- {
- int n1 = nLeftNR, n2 = nRightNR;
- int *pnr = MixSoundBuffer;
- for (int nr=count; nr; nr--)
- {
- int vnr = pnr[0] >> 1;
- pnr[0] = vnr + n1;
- n1 = vnr;
- vnr = pnr[1] >> 1;
- pnr[1] = vnr + n2;
- n2 = vnr;
- pnr += 2;
- }
- nLeftNR = n1;
- nRightNR = n2;
- }
-}
-
-
-void CSoundFile::ProcessMonoDSP(int count)
-//----------------------------------------
-{
-#ifndef NO_REVERB
- // Reverb
- if (gdwSoundSetup & SNDMIX_REVERB)
- {
- int *pr = MixSoundBuffer, rvbcount = count, *pin = MixReverbBuffer;
- do
- {
- int echo = ReverbBuffer[nReverbBufferPos] + ReverbBuffer2[nReverbBufferPos2]
- + ReverbBuffer3[nReverbBufferPos3] + ReverbBuffer4[nReverbBufferPos4]; // echo = reverb signal
- // Delay line and remove Low Frequencies // v = original signal
- int echodly = ReverbLoFilterDelay[nReverbLoDlyPos]; // echodly = delayed signal
- ReverbLoFilterDelay[nReverbLoDlyPos] = echo >> 1;
- nReverbLoDlyPos++;
- nReverbLoDlyPos &= 0x1F;
- int n = nReverbLoFltPos;
- nReverbLoFltSum -= ReverbLoFilterBuffer[n];
- int tmp = echo / 128;
- ReverbLoFilterBuffer[n] = tmp;
- nReverbLoFltSum += tmp;
- echodly -= nReverbLoFltSum;
- nReverbLoFltPos = (n + 1) & 0x3F;
- // Reverb
- int v = pin[0] >> (nFilterAttn-1);
- *pr++ += pin[0] + echodly;
- pin++;
- v += echodly >> 2;
- ReverbBuffer3[nReverbBufferPos3] = v;
- ReverbBuffer4[nReverbBufferPos4] = v;
- v += echodly >> 4;
- v >>= 1;
- gRvbLPSum -= gRvbLowPass[gRvbLPPos];
- gRvbLPSum += v;
- gRvbLowPass[gRvbLPPos] = v;
- gRvbLPPos++;
- gRvbLPPos &= 7;
- int vlp = gRvbLPSum >> 2;
- ReverbBuffer[nReverbBufferPos] = vlp;
- ReverbBuffer2[nReverbBufferPos2] = vlp;
- if (++nReverbBufferPos >= nReverbSize) nReverbBufferPos = 0;
- if (++nReverbBufferPos2 >= nReverbSize2) nReverbBufferPos2 = 0;
- if (++nReverbBufferPos3 >= nReverbSize3) nReverbBufferPos3 = 0;
- if (++nReverbBufferPos4 >= nReverbSize4) nReverbBufferPos4 = 0;
- } while (--rvbcount);
- }
-#endif
- // Bass Expansion
- if (gdwSoundSetup & SNDMIX_MEGABASS)
- {
- int *px = MixSoundBuffer;
- int xba = m_nXBassDepth, xbamask = (1 << xba)-1;
- int n = nXBassBufferPos;
- for (int x=count; x; x--)
- {
- nXBassSum -= XBassBuffer[n];
- int tmp0 = *px;
- int tmp = (tmp0 + ((tmp0 >> 31) & xbamask)) >> xba;
- XBassBuffer[n] = tmp;
- nXBassSum += tmp;
- int v = XBassDelay[nXBassDlyPos];
- XBassDelay[nXBassDlyPos] = *px;
- *px++ = v + nXBassSum;
- nXBassDlyPos = (nXBassDlyPos + 2) & nXBassMask;
- n++;
- n &= nXBassMask;
- }
- nXBassBufferPos = n;
- }
- // Noise Reduction
- if (gdwSoundSetup & SNDMIX_NOISEREDUCTION)
- {
- int n = nLeftNR;
- int *pnr = MixSoundBuffer;
- for (int nr=count; nr; pnr++, nr--)
- {
- int vnr = *pnr >> 1;
- *pnr = vnr + n;
- n = vnr;
- }
- nLeftNR = n;
- }
-}
-
-
-/////////////////////////////////////////////////////////////////
-// Clean DSP Effects interface
-
-// [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms]
-BOOL CSoundFile::SetReverbParameters(UINT nDepth, UINT nDelay)
-//------------------------------------------------------------
-{
- if (nDepth > 100) nDepth = 100;
- UINT gain = nDepth / 20;
- if (gain > 4) gain = 4;
- m_nReverbDepth = 4 - gain;
- if (nDelay < 40) nDelay = 40;
- if (nDelay > 250) nDelay = 250;
- m_nReverbDelay = nDelay;
- return TRUE;
-}
-
-
-// [XBass level 0(quiet)-100(loud)], [cutoff in Hz 20-100]
-BOOL CSoundFile::SetXBassParameters(UINT nDepth, UINT nRange)
-//-----------------------------------------------------------
-{
- if (nDepth > 100) nDepth = 100;
- UINT gain = nDepth / 20;
- if (gain > 4) gain = 4;
- m_nXBassDepth = 8 - gain; // filter attenuation 1/256 .. 1/16
- UINT range = nRange / 5;
- if (range > 5) range -= 5; else range = 0;
- if (nRange > 16) nRange = 16;
- m_nXBassRange = 21 - range; // filter average on 0.5-1.6ms
- return TRUE;
-}
-
-
-// [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-50ms]
-BOOL CSoundFile::SetSurroundParameters(UINT nDepth, UINT nDelay)
-//--------------------------------------------------------------
-{
- UINT gain = (nDepth * 16) / 100;
- if (gain > 16) gain = 16;
- if (gain < 1) gain = 1;
- m_nProLogicDepth = gain;
- if (nDelay < 4) nDelay = 4;
- if (nDelay > 50) nDelay = 50;
- m_nProLogicDelay = nDelay;
- return TRUE;
-}
-
-BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ)
-//----------------------------------------------------------------------------------------------------------------------------
-{
- DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ);
- if (bSurround) d |= SNDMIX_SURROUND;
- if (bNoOverSampling) d |= SNDMIX_NORESAMPLING;
- if (bReverb) d |= SNDMIX_REVERB;
- if (hqido) d |= SNDMIX_HQRESAMPLER;
- if (bMegaBass) d |= SNDMIX_MEGABASS;
- if (bNR) d |= SNDMIX_NOISEREDUCTION;
- if (bEQ) d |= SNDMIX_EQ;
- gdwSoundSetup = d;
- InitPlayer(FALSE);
- return TRUE;
-}
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-// AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz]
-// EMU10K1 docs: cutoff = reg[0-127]*62+100
-#define FILTER_PRECISION 8192
-
-#ifndef NO_FILTER
-
-#ifdef MSC_VER
-#define _ASM_MATH
-#endif
-
-#ifdef _ASM_MATH
-
-// pow(a,b) returns a^^b -> 2^^(b.log2(a))
-static float pow(float a, float b)
-{
- long tmpint;
- float result;
- _asm {
- fld b // Load b
- fld a // Load a
- fyl2x // ST(0) = b.log2(a)
- fist tmpint // Store integer exponent
- fisub tmpint // ST(0) = -1 <= (b*log2(a)) <= 1
- f2xm1 // ST(0) = 2^(x)-1
- fild tmpint // load integer exponent
- fld1 // Load 1
- fscale // ST(0) = 2^ST(1)
- fstp ST(1) // Remove the integer from the stack
- fmul ST(1), ST(0) // multiply with fractional part
- faddp ST(1), ST(0) // add integer_part
- fstp result // Store the result
- }
- return result;
-}
-
-
-#else
-
-#include <math.h>
-
-#endif // _ASM_MATH
-
-
-DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const
-//-----------------------------------------------------------------------
-{
- float Fc;
-
- if (m_dwSongFlags & SONG_EXFILTERRANGE)
- Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f));
- else
- Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f));
- LONG freq = (LONG)Fc;
- if (freq < 120) return 120;
- if (freq > 10000) return 10000;
- if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1;
- return (DWORD)freq;
-}
-
-
-// Simple 2-poles resonant filter
-void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const
-//----------------------------------------------------------------------------------------
-{
- float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
- float fs = (float)gdwMixingFreq;
- float fg, fb0, fb1;
-
- fc *= (float)(2.0*3.14159265358/fs);
- float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
- float d = (1.0f-2.0f*dmpfac)* fc;
- if (d>2.0) d = 2.0;
- d = (2.0f*dmpfac - d)/fc;
- float e = pow(1.0f/fc, 2);
-
- fg=1/(1+d+e);
- fb0=(d+e+e)/(1+d+e);
- fb1=-e/(1+d+e);
-
- pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION);
- pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION);
- pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION);
-
- if (bReset)
- {
- pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
- pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
- }
- pChn->dwFlags |= CHN_FILTER;
-}
-
-#endif // NO_FILTER
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#ifdef MSC_VER
-#pragma warning(disable:4244)
-#endif
-
-// Tables defined in tables.cpp
-extern BYTE ImpulseTrackerPortaVolCmd[16];
-extern WORD S3MFineTuneTable[16];
-extern WORD ProTrackerPeriodTable[6*12];
-extern WORD ProTrackerTunedPeriods[15*12];
-extern WORD FreqS3MTable[];
-extern WORD XMPeriodTable[96+8];
-extern UINT XMLinearTable[768];
-extern DWORD FineLinearSlideUpTable[16];
-extern DWORD FineLinearSlideDownTable[16];
-extern DWORD LinearSlideUpTable[256];
-extern DWORD LinearSlideDownTable[256];
-extern signed char retrigTable1[16];
-extern signed char retrigTable2[16];
-extern short int ModRandomTable[64];
-
-
-////////////////////////////////////////////////////////////
-// Length
-
-DWORD CSoundFile::GetLength(BOOL bAdjust, BOOL bTotal)
-//----------------------------------------------------
-{
- UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=Order[0];
- UINT nMusicSpeed=m_nDefaultSpeed, nMusicTempo=m_nDefaultTempo, nNextRow=0;
- UINT nMaxRow = 0, nMaxPattern = 0;
- LONG nGlbVol = m_nDefaultGlobalVolume, nOldGlbVolSlide = 0;
- BYTE samples[MAX_CHANNELS];
- BYTE instr[MAX_CHANNELS];
- BYTE notes[MAX_CHANNELS];
- BYTE vols[MAX_CHANNELS];
- BYTE oldparam[MAX_CHANNELS];
- BYTE chnvols[MAX_CHANNELS];
- DWORD patloop[MAX_CHANNELS];
-
- memset(instr, 0, sizeof(instr));
- memset(notes, 0, sizeof(notes));
- memset(vols, 0xFF, sizeof(vols));
- memset(patloop, 0, sizeof(patloop));
- memset(oldparam, 0, sizeof(oldparam));
- memset(chnvols, 64, sizeof(chnvols));
- memset(samples, 0, sizeof(samples));
- for (UINT icv=0; icv<m_nChannels; icv++) chnvols[icv] = ChnSettings[icv].nVolume;
- nMaxRow = m_nNextRow;
- nMaxPattern = m_nNextPattern;
- nCurrentPattern = nNextPattern = 0;
- nPattern = Order[0];
- nRow = nNextRow = 0;
- for (;;)
- {
- UINT nSpeedCount = 0;
- nRow = nNextRow;
- nCurrentPattern = nNextPattern;
- // Check if pattern is valid
- nPattern = Order[nCurrentPattern];
- while (nPattern >= MAX_PATTERNS)
- {
- // End of song ?
- if ((nPattern == 0xFF) || (nCurrentPattern >= MAX_ORDERS))
- {
- goto EndMod;
- } else
- {
- nCurrentPattern++;
- nPattern = (nCurrentPattern < MAX_ORDERS) ? Order[nCurrentPattern] : 0xFF;
- }
- nNextPattern = nCurrentPattern;
- }
- // Weird stuff?
- if ((nPattern >= MAX_PATTERNS) || (!Patterns[nPattern])) break;
- // Should never happen
- if (nRow >= PatternSize[nPattern]) nRow = 0;
- // Update next position
- nNextRow = nRow + 1;
- if (nNextRow >= PatternSize[nPattern])
- {
- nNextPattern = nCurrentPattern + 1;
- nNextRow = 0;
- }
- if (!nRow)
- {
- for (UINT ipck=0; ipck<m_nChannels; ipck++) patloop[ipck] = dwElapsedTime;
- }
- if (!bTotal)
- {
- if ((nCurrentPattern > nMaxPattern) || ((nCurrentPattern == nMaxPattern) && (nRow >= nMaxRow)))
- {
- if (bAdjust)
- {
- m_nMusicSpeed = nMusicSpeed;
- m_nMusicTempo = nMusicTempo;
- }
- break;
- }
- }
- MODCHANNEL *pChn = Chn;
- MODCOMMAND *p = Patterns[nPattern] + nRow * m_nChannels;
- for (UINT nChn=0; nChn<m_nChannels; p++,pChn++, nChn++) if (*((DWORD *)p))
- {
- UINT command = p->command;
- UINT param = p->param;
- UINT note = p->note;
- if (p->instr) { instr[nChn] = p->instr; notes[nChn] = 0; vols[nChn] = 0xFF; }
- if ((note) && (note <= 120)) notes[nChn] = note;
- if (p->volcmd == VOLCMD_VOLUME) { vols[nChn] = p->vol; }
- if (command) switch (command)
- {
- // Position Jump
- case CMD_POSITIONJUMP:
- if (param <= nCurrentPattern) goto EndMod;
- nNextPattern = param;
- nNextRow = 0;
- if (bAdjust)
- {
- pChn->nPatternLoopCount = 0;
- pChn->nPatternLoop = 0;
- }
- break;
- // Pattern Break
- case CMD_PATTERNBREAK:
- nNextRow = param;
- nNextPattern = nCurrentPattern + 1;
- if (bAdjust)
- {
- pChn->nPatternLoopCount = 0;
- pChn->nPatternLoop = 0;
- }
- break;
- // Set Speed
- case CMD_SPEED:
- if (!param) break;
- if ((param <= 0x20) || (m_nType != MOD_TYPE_MOD))
- {
- if (param < 128) nMusicSpeed = param;
- }
- break;
- // Set Tempo
- case CMD_TEMPO:
- if ((bAdjust) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))
- {
- if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
- }
- if (param >= 0x20) nMusicTempo = param; else
- // Tempo Slide
- if ((param & 0xF0) == 0x10)
- {
- nMusicTempo += param & 0x0F;
- if (nMusicTempo > 255) nMusicTempo = 255;
- } else
- {
- nMusicTempo -= param & 0x0F;
- if (nMusicTempo < 32) nMusicTempo = 32;
- }
- break;
- // Pattern Delay
- case CMD_S3MCMDEX:
- if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else
- if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; }
- case CMD_MODCMDEX:
- if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else
- if ((param & 0xF0) == 0x60)
- {
- if (param & 0x0F) dwElapsedTime += (dwElapsedTime - patloop[nChn]) * (param & 0x0F);
- else patloop[nChn] = dwElapsedTime;
- }
- break;
- }
- if (!bAdjust) continue;
- switch(command)
- {
- // Portamento Up/Down
- case CMD_PORTAMENTOUP:
- case CMD_PORTAMENTODOWN:
- if (param) pChn->nOldPortaUpDown = param;
- break;
- // Tone-Portamento
- case CMD_TONEPORTAMENTO:
- if (param) pChn->nPortamentoSlide = param << 2;
- break;
- // Offset
- case CMD_OFFSET:
- if (param) pChn->nOldOffset = param;
- break;
- // Volume Slide
- case CMD_VOLUMESLIDE:
- case CMD_TONEPORTAVOL:
- case CMD_VIBRATOVOL:
- if (param) pChn->nOldVolumeSlide = param;
- break;
- // Set Volume
- case CMD_VOLUME:
- vols[nChn] = param;
- break;
- // Global Volume
- case CMD_GLOBALVOLUME:
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- if (param > 128) param = 128;
- nGlbVol = param << 1;
- break;
- // Global Volume Slide
- case CMD_GLOBALVOLSLIDE:
- if (param) nOldGlbVolSlide = param; else param = nOldGlbVolSlide;
- if (((param & 0x0F) == 0x0F) && (param & 0xF0))
- {
- param >>= 4;
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- nGlbVol += param << 1;
- } else
- if (((param & 0xF0) == 0xF0) && (param & 0x0F))
- {
- param = (param & 0x0F) << 1;
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- nGlbVol -= param;
- } else
- if (param & 0xF0)
- {
- param >>= 4;
- param <<= 1;
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- nGlbVol += param * nMusicSpeed;
- } else
- {
- param = (param & 0x0F) << 1;
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- nGlbVol -= param * nMusicSpeed;
- }
- if (nGlbVol < 0) nGlbVol = 0;
- if (nGlbVol > 256) nGlbVol = 256;
- break;
- case CMD_CHANNELVOLUME:
- if (param <= 64) chnvols[nChn] = param;
- break;
- case CMD_CHANNELVOLSLIDE:
- if (param) oldparam[nChn] = param; else param = oldparam[nChn];
- pChn->nOldChnVolSlide = param;
- if (((param & 0x0F) == 0x0F) && (param & 0xF0))
- {
- param = (param >> 4) + chnvols[nChn];
- } else
- if (((param & 0xF0) == 0xF0) && (param & 0x0F))
- {
- if (chnvols[nChn] > (int)(param & 0x0F)) param = chnvols[nChn] - (param & 0x0F);
- else param = 0;
- } else
- if (param & 0x0F)
- {
- param = (param & 0x0F) * nMusicSpeed;
- param = (chnvols[nChn] > param) ? chnvols[nChn] - param : 0;
- } else param = ((param & 0xF0) >> 4) * nMusicSpeed + chnvols[nChn];
- if (param > 64) param = 64;
- chnvols[nChn] = param;
- break;
- }
- }
- nSpeedCount += nMusicSpeed;
- dwElapsedTime += (2500 * nSpeedCount) / nMusicTempo;
- }
-EndMod:
- if ((bAdjust) && (!bTotal))
- {
- m_nGlobalVolume = nGlbVol;
- m_nOldGlbVolSlide = nOldGlbVolSlide;
- for (UINT n=0; n<m_nChannels; n++)
- {
- Chn[n].nGlobalVol = chnvols[n];
- if (notes[n]) Chn[n].nNewNote = notes[n];
- if (instr[n]) Chn[n].nNewIns = instr[n];
- if (vols[n] != 0xFF)
- {
- if (vols[n] > 64) vols[n] = 64;
- Chn[n].nVolume = vols[n] << 2;
- }
- }
- }
- return (dwElapsedTime+500) / 1000;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-// Effects
-
-void CSoundFile::InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv)
-//--------------------------------------------------------------------------------------------------------
-{
- BOOL bInstrumentChanged = FALSE;
-
- if (instr >= MAX_INSTRUMENTS) return;
- INSTRUMENTHEADER *penv = Headers[instr];
- MODINSTRUMENT *psmp = &Ins[instr];
- UINT note = pChn->nNewNote;
- if ((penv) && (note) && (note <= 128))
- {
- if (penv->NoteMap[note-1] >= 0xFE) return;
- UINT n = penv->Keyboard[note-1];
- psmp = ((n) && (n < MAX_SAMPLES)) ? &Ins[n] : NULL;
- } else
- if (m_nInstruments)
- {
- if (note >= 0xFE) return;
- psmp = NULL;
- }
- // Update Volume
- if (bUpdVol) pChn->nVolume = (psmp) ? psmp->nVolume : 0;
- // bInstrumentChanged is used for IT carry-on env option
- if (penv != pChn->pHeader)
- {
- bInstrumentChanged = TRUE;
- pChn->pHeader = penv;
- } else
- // Special XM hack
- if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (penv)
- && (pChn->pInstrument) && (psmp != pChn->pInstrument))
- {
- // FT2 doesn't change the sample in this case,
- // but still uses the sample info from the old one (bug?)
- return;
- }
- // Instrument adjust
- pChn->nNewIns = 0;
- if (psmp)
- {
- if (penv)
- {
- pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6;
- if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan;
- pChn->nNNA = penv->nNNA;
- } else
- {
- pChn->nInsVol = psmp->nGlobalVol;
- }
- if (psmp->uFlags & CHN_PANNING) pChn->nPan = psmp->nPan;
- }
- // Reset envelopes
- if (bResetEnv)
- {
- if ((!bPorta) || (!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITCOMPATMODE)
- || (!pChn->nLength) || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol)))
- {
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- if ((m_nType & MOD_TYPE_IT) && (!bInstrumentChanged) && (penv) && (!(pChn->dwFlags & (CHN_KEYOFF|CHN_NOTEFADE))))
- {
- if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
- if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
- if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
- } else
- {
- pChn->nVolEnvPosition = 0;
- pChn->nPanEnvPosition = 0;
- pChn->nPitchEnvPosition = 0;
- }
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- } else
- if ((penv) && (!(penv->dwFlags & ENV_VOLUME)))
- {
- pChn->nVolEnvPosition = 0;
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- }
- }
- // Invalid sample ?
- if (!psmp)
- {
- pChn->pInstrument = NULL;
- pChn->nInsVol = 0;
- return;
- }
- // Tone-Portamento doesn't reset the pingpong direction flag
- if ((bPorta) && (psmp == pChn->pInstrument))
- {
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)) return;
- pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE);
- pChn->dwFlags = (pChn->dwFlags & (0xFFFFFF00 | CHN_PINGPONGFLAG)) | (psmp->uFlags);
- } else
- {
- pChn->dwFlags &= ~(CHN_KEYOFF|CHN_NOTEFADE|CHN_VOLENV|CHN_PANENV|CHN_PITCHENV);
- pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (psmp->uFlags);
- if (penv)
- {
- if (penv->dwFlags & ENV_VOLUME) pChn->dwFlags |= CHN_VOLENV;
- if (penv->dwFlags & ENV_PANNING) pChn->dwFlags |= CHN_PANENV;
- if (penv->dwFlags & ENV_PITCH) pChn->dwFlags |= CHN_PITCHENV;
- if ((penv->dwFlags & ENV_PITCH) && (penv->dwFlags & ENV_FILTER))
- {
- if (!pChn->nCutOff) pChn->nCutOff = 0x7F;
- }
- if (penv->nIFC & 0x80) pChn->nCutOff = penv->nIFC & 0x7F;
- if (penv->nIFR & 0x80) pChn->nResonance = penv->nIFR & 0x7F;
- }
- pChn->nVolSwing = pChn->nPanSwing = 0;
- }
- pChn->pInstrument = psmp;
- pChn->nLength = psmp->nLength;
- pChn->nLoopStart = psmp->nLoopStart;
- pChn->nLoopEnd = psmp->nLoopEnd;
- pChn->nC4Speed = psmp->nC4Speed;
- pChn->pSample = psmp->pSample;
- pChn->nTranspose = psmp->RelativeTone;
- pChn->nFineTune = psmp->nFineTune;
- if (pChn->dwFlags & CHN_SUSTAINLOOP)
- {
- pChn->nLoopStart = psmp->nSustainStart;
- pChn->nLoopEnd = psmp->nSustainEnd;
- pChn->dwFlags |= CHN_LOOP;
- if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
- }
- if ((pChn->dwFlags & CHN_LOOP) && (pChn->nLoopEnd < pChn->nLength)) pChn->nLength = pChn->nLoopEnd;
-}
-
-
-void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv)
-//---------------------------------------------------------------------------
-{
- if (note < 1) return;
- MODCHANNEL * const pChn = &Chn[nChn];
- MODINSTRUMENT *pins = pChn->pInstrument;
- INSTRUMENTHEADER *penv = pChn->pHeader;
- if ((penv) && (note <= 0x80))
- {
- UINT n = penv->Keyboard[note - 1];
- if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n];
- note = penv->NoteMap[note-1];
- }
- // Key Off
- if (note >= 0x80) // 0xFE or invalid note => key off
- {
- // Key Off
- KeyOff(nChn);
- // Note Cut
- if (note == 0xFE)
- {
- pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
- if ((!(m_nType & MOD_TYPE_IT)) || (m_nInstruments)) pChn->nVolume = 0;
- pChn->nFadeOutVol = 0;
- }
- return;
- }
- if (!pins) return;
- if ((!bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MT2)))
- {
- pChn->nTranspose = pins->RelativeTone;
- pChn->nFineTune = pins->nFineTune;
- }
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2|MOD_TYPE_MED)) note += pChn->nTranspose;
- if (note < 1) note = 1;
- if (note > 132) note = 132;
- pChn->nNote = note;
- if ((!bPorta) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) pChn->nNewIns = 0;
- UINT period = GetPeriodFromNote(note, pChn->nFineTune, pChn->nC4Speed);
- if (period)
- {
- if ((!bPorta) || (!pChn->nPeriod)) pChn->nPeriod = period;
- pChn->nPortamentoDest = period;
- if ((!bPorta) || ((!pChn->nLength) && (!(m_nType & MOD_TYPE_S3M))))
- {
- pChn->pInstrument = pins;
- pChn->pSample = pins->pSample;
- pChn->nLength = pins->nLength;
- pChn->nLoopEnd = pins->nLength;
- pChn->nLoopStart = 0;
- pChn->dwFlags = (pChn->dwFlags & 0xFFFFFF00) | (pins->uFlags);
- if (pChn->dwFlags & CHN_SUSTAINLOOP)
- {
- pChn->nLoopStart = pins->nSustainStart;
- pChn->nLoopEnd = pins->nSustainEnd;
- pChn->dwFlags &= ~CHN_PINGPONGLOOP;
- pChn->dwFlags |= CHN_LOOP;
- if (pChn->dwFlags & CHN_PINGPONGSUSTAIN) pChn->dwFlags |= CHN_PINGPONGLOOP;
- if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
- } else
- if (pChn->dwFlags & CHN_LOOP)
- {
- pChn->nLoopStart = pins->nLoopStart;
- pChn->nLoopEnd = pins->nLoopEnd;
- if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
- }
- pChn->nPos = 0;
- pChn->nPosLo = 0;
- if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0;
- if (pChn->nTremoloType < 4) pChn->nTremoloPos = 0;
- }
- if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart;
- } else bPorta = FALSE;
- if ((!bPorta) || (!(m_nType & MOD_TYPE_IT))
- || ((pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
- || ((m_dwSongFlags & SONG_ITCOMPATMODE) && (pChn->nRowInstr)))
- {
- if ((m_nType & MOD_TYPE_IT) && (pChn->dwFlags & CHN_NOTEFADE) && (!pChn->nFadeOutVol))
- {
- pChn->nVolEnvPosition = 0;
- pChn->nPanEnvPosition = 0;
- pChn->nPitchEnvPosition = 0;
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- pChn->dwFlags &= ~CHN_NOTEFADE;
- pChn->nFadeOutVol = 65536;
- }
- if ((!bPorta) || (!(m_dwSongFlags & SONG_ITCOMPATMODE)) || (pChn->nRowInstr))
- {
- if ((!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) || (pChn->nRowInstr))
- {
- pChn->dwFlags &= ~CHN_NOTEFADE;
- pChn->nFadeOutVol = 65536;
- }
- }
- }
- pChn->dwFlags &= ~(CHN_EXTRALOUD|CHN_KEYOFF);
- // Enable Ramping
- if (!bPorta)
- {
- pChn->nVUMeter = 0x100;
- pChn->nLeftVU = pChn->nRightVU = 0xFF;
- pChn->dwFlags &= ~CHN_FILTER;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- pChn->nRetrigCount = 0;
- pChn->nTremorCount = 0;
- if (bResetEnv)
- {
- pChn->nVolSwing = pChn->nPanSwing = 0;
- if (penv)
- {
- if (!(penv->dwFlags & ENV_VOLCARRY)) pChn->nVolEnvPosition = 0;
- if (!(penv->dwFlags & ENV_PANCARRY)) pChn->nPanEnvPosition = 0;
- if (!(penv->dwFlags & ENV_PITCHCARRY)) pChn->nPitchEnvPosition = 0;
- if (m_nType & MOD_TYPE_IT)
- {
- // Volume Swing
- if (penv->nVolSwing)
- {
- int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
- pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
- }
- // Pan Swing
- if (penv->nPanSwing)
- {
- int d = ((LONG)penv->nPanSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
- pChn->nPanSwing = (signed short)d;
- }
- }
- }
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- }
- pChn->nLeftVol = pChn->nRightVol = 0;
- BOOL bFlt = (m_dwSongFlags & SONG_MPTFILTERMODE) ? FALSE : TRUE;
- // Setup Initial Filter for this note
- if (penv)
- {
- if (penv->nIFR & 0x80) { pChn->nResonance = penv->nIFR & 0x7F; bFlt = TRUE; }
- if (penv->nIFC & 0x80) { pChn->nCutOff = penv->nIFC & 0x7F; bFlt = TRUE; }
- } else
- {
- pChn->nVolSwing = pChn->nPanSwing = 0;
- }
-#ifndef NO_FILTER
- if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, TRUE);
-#endif // NO_FILTER
- }
-}
-
-
-UINT CSoundFile::GetNNAChannel(UINT nChn) const
-//---------------------------------------------
-{
- const MODCHANNEL *pChn = &Chn[nChn];
- // Check for empty channel
- const MODCHANNEL *pi = &Chn[m_nChannels];
- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, pi++) if (!pi->nLength) return i;
- if (!pChn->nFadeOutVol) return 0;
- // All channels are used: check for lowest volume
- UINT result = 0;
- DWORD vol = 64*65536; // 25%
- DWORD envpos = 0xFFFFFF;
- const MODCHANNEL *pj = &Chn[m_nChannels];
- for (UINT j=m_nChannels; j<MAX_CHANNELS; j++, pj++)
- {
- if (!pj->nFadeOutVol) return j;
- DWORD v = pj->nVolume;
- if (pj->dwFlags & CHN_NOTEFADE)
- v = v * pj->nFadeOutVol;
- else
- v <<= 16;
- if (pj->dwFlags & CHN_LOOP) v >>= 1;
- if ((v < vol) || ((v == vol) && (pj->nVolEnvPosition > envpos)))
- {
- envpos = pj->nVolEnvPosition;
- vol = v;
- result = j;
- }
- }
- return result;
-}
-
-
-void CSoundFile::CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut)
-//------------------------------------------------------------------------
-{
- MODCHANNEL *pChn = &Chn[nChn];
- INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader;
- signed char *pSample;
- if (note > 0x80) note = 0;
- if (note < 1) return;
- // Always NNA cut - using
- if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut))
- {
- if ((m_dwSongFlags & SONG_CPUVERYHIGH)
- || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE)
- || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return;
- UINT n = GetNNAChannel(nChn);
- if (!n) return;
- MODCHANNEL *p = &Chn[n];
- // Copy Channel
- *p = *pChn;
- p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
- p->nMasterChn = nChn+1;
- p->nCommand = 0;
- // Cut the note
- p->nFadeOutVol = 0;
- p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
- // Stop this channel
- pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
- pChn->nROfs = pChn->nLOfs = 0;
- pChn->nLeftVol = pChn->nRightVol = 0;
- return;
- }
- if (instr >= MAX_INSTRUMENTS) instr = 0;
- pSample = pChn->pSample;
- pHeader = pChn->pHeader;
- if ((instr) && (note))
- {
- pHeader = Headers[instr];
- if (pHeader)
- {
- UINT n = 0;
- if (note <= 0x80)
- {
- n = pHeader->Keyboard[note-1];
- note = pHeader->NoteMap[note-1];
- if ((n) && (n < MAX_SAMPLES)) pSample = Ins[n].pSample;
- }
- } else pSample = NULL;
- }
- if (!penv) return;
- MODCHANNEL *p = pChn;
- for (UINT i=nChn; i<MAX_CHANNELS; p++, i++)
- if ((i >= m_nChannels) || (p == pChn))
- {
- if (((p->nMasterChn == nChn+1) || (p == pChn)) && (p->pHeader))
- {
- BOOL bOk = FALSE;
- // Duplicate Check Type
- switch(p->pHeader->nDCT)
- {
- // Note
- case DCT_NOTE:
- if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE;
- break;
- // Sample
- case DCT_SAMPLE:
- if ((pSample) && (pSample == p->pSample)) bOk = TRUE;
- break;
- // Instrument
- case DCT_INSTRUMENT:
- if (pHeader == p->pHeader) bOk = TRUE;
- break;
- }
- // Duplicate Note Action
- if (bOk)
- {
- switch(p->pHeader->nDNA)
- {
- // Cut
- case DNA_NOTECUT:
- KeyOff(i);
- p->nVolume = 0;
- break;
- // Note Off
- case DNA_NOTEOFF:
- KeyOff(i);
- break;
- // Note Fade
- case DNA_NOTEFADE:
- p->dwFlags |= CHN_NOTEFADE;
- break;
- }
- if (!p->nVolume)
- {
- p->nFadeOutVol = 0;
- p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
- }
- }
- }
- }
- if (pChn->dwFlags & CHN_MUTE) return;
- // New Note Action
- if ((pChn->nVolume) && (pChn->nLength))
- {
- UINT n = GetNNAChannel(nChn);
- if (n)
- {
- MODCHANNEL *p = &Chn[n];
- // Copy Channel
- *p = *pChn;
- p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
- p->nMasterChn = nChn+1;
- p->nCommand = 0;
- // Key Off the note
- switch(pChn->nNNA)
- {
- case NNA_NOTEOFF: KeyOff(n); break;
- case NNA_NOTECUT:
- p->nFadeOutVol = 0;
- case NNA_NOTEFADE: p->dwFlags |= CHN_NOTEFADE; break;
- }
- if (!p->nVolume)
- {
- p->nFadeOutVol = 0;
- p->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
- }
- // Stop this channel
- pChn->nLength = pChn->nPos = pChn->nPosLo = 0;
- pChn->nROfs = pChn->nLOfs = 0;
- }
- }
-}
-
-
-BOOL CSoundFile::ProcessEffects()
-//-------------------------------
-{
- int nBreakRow = -1, nPosJump = -1, nPatLoopRow = -1;
- MODCHANNEL *pChn = Chn;
- for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++)
- {
- UINT instr = pChn->nRowInstr;
- UINT volcmd = pChn->nRowVolCmd;
- UINT vol = pChn->nRowVolume;
- UINT cmd = pChn->nRowCommand;
- UINT param = pChn->nRowParam;
- BOOL bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE;
- UINT nStartTick = 0;
-
- pChn->dwFlags &= ~CHN_FASTVOLRAMP;
- // Process special effects (note delay, pattern delay, pattern loop)
- if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX))
- {
- if ((!param) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param;
- // Note Delay ?
- if ((param & 0xF0) == 0xD0)
- {
- nStartTick = param & 0x0F;
- } else
- if (!m_nTickCount)
- {
- // Pattern Loop ?
- if ((((param & 0xF0) == 0x60) && (cmd == CMD_MODCMDEX))
- || (((param & 0xF0) == 0xB0) && (cmd == CMD_S3MCMDEX)))
- {
- int nloop = PatternLoop(pChn, param & 0x0F);
- if (nloop >= 0) nPatLoopRow = nloop;
- } else
- // Pattern Delay
- if ((param & 0xF0) == 0xE0)
- {
- m_nPatternDelay = param & 0x0F;
- }
- }
- }
-
- // Handles note/instrument/volume changes
- if (m_nTickCount == nStartTick) // can be delayed by a note delay effect
- {
- UINT note = pChn->nRowNote;
- if (instr) pChn->nNewIns = instr;
- // XM: Key-Off + Sample == Note Cut
- if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if ((note == 0xFF) && ((!pChn->pHeader) || (!(pChn->pHeader->dwFlags & ENV_VOLUME))))
- {
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- pChn->nVolume = 0;
- note = instr = 0;
- }
- }
- if ((!note) && (instr))
- {
- if (m_nInstruments)
- {
- if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume;
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- pChn->nVolEnvPosition = 0;
- pChn->nPanEnvPosition = 0;
- pChn->nPitchEnvPosition = 0;
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- pChn->dwFlags &= ~CHN_NOTEFADE;
- pChn->nFadeOutVol = 65536;
- }
- } else
- {
- if (instr < MAX_SAMPLES) pChn->nVolume = Ins[instr].nVolume;
- }
- if (!(m_nType & MOD_TYPE_IT)) instr = 0;
- }
- // Invalid Instrument ?
- if (instr >= MAX_INSTRUMENTS) instr = 0;
- // Note Cut/Off => ignore instrument
- if (note >= 0xFE) instr = 0;
- if ((note) && (note <= 128)) pChn->nNewNote = note;
- // New Note Action ?
- if ((note) && (note <= 128) && (!bPorta))
- {
- CheckNNA(nChn, instr, note, FALSE);
- }
- // Instrument Change ?
- if (instr)
- {
- MODINSTRUMENT *psmp = pChn->pInstrument;
- InstrumentChange(pChn, instr, bPorta, TRUE);
- pChn->nNewIns = 0;
- // Special IT case: portamento+note causes sample change -> ignore portamento
- if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
- && (psmp != pChn->pInstrument) && (note) && (note < 0x80))
- {
- bPorta = FALSE;
- }
- }
- // New Note ?
- if (note)
- {
- if ((!instr) && (pChn->nNewIns) && (note < 0x80))
- {
- InstrumentChange(pChn, pChn->nNewIns, bPorta, FALSE, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
- pChn->nNewIns = 0;
- }
- NoteChange(nChn, note, bPorta, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
- if ((bPorta) && (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) && (instr))
- {
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- pChn->nVolEnvPosition = 0;
- pChn->nPanEnvPosition = 0;
- pChn->nPitchEnvPosition = 0;
- pChn->nAutoVibDepth = 0;
- pChn->nAutoVibPos = 0;
- }
- }
- // Tick-0 only volume commands
- if (volcmd == VOLCMD_VOLUME)
- {
- if (vol > 64) vol = 64;
- pChn->nVolume = vol << 2;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- } else
- if (volcmd == VOLCMD_PANNING)
- {
- if (vol > 64) vol = 64;
- pChn->nPan = vol << 2;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- }
-
- // Volume Column Effect (except volume & panning)
- if ((volcmd > VOLCMD_PANNING) && (m_nTickCount >= nStartTick))
- {
- if (volcmd == VOLCMD_TONEPORTAMENTO)
- {
- if (m_nType & MOD_TYPE_IT)
- TonePortamento(pChn, ImpulseTrackerPortaVolCmd[vol & 0x0F]);
- else
- TonePortamento(pChn, vol * 16);
- } else
- {
- if (vol) pChn->nOldVolParam = vol; else vol = pChn->nOldVolParam;
- switch(volcmd)
- {
- case VOLCMD_VOLSLIDEUP:
- VolumeSlide(pChn, vol << 4);
- break;
-
- case VOLCMD_VOLSLIDEDOWN:
- VolumeSlide(pChn, vol);
- break;
-
- case VOLCMD_FINEVOLUP:
- if (m_nType & MOD_TYPE_IT)
- {
- if (m_nTickCount == nStartTick) VolumeSlide(pChn, (vol << 4) | 0x0F);
- } else
- FineVolumeUp(pChn, vol);
- break;
-
- case VOLCMD_FINEVOLDOWN:
- if (m_nType & MOD_TYPE_IT)
- {
- if (m_nTickCount == nStartTick) VolumeSlide(pChn, 0xF0 | vol);
- } else
- FineVolumeDown(pChn, vol);
- break;
-
- case VOLCMD_VIBRATOSPEED:
- Vibrato(pChn, vol << 4);
- break;
-
- case VOLCMD_VIBRATO:
- Vibrato(pChn, vol);
- break;
-
- case VOLCMD_PANSLIDELEFT:
- PanningSlide(pChn, vol);
- break;
-
- case VOLCMD_PANSLIDERIGHT:
- PanningSlide(pChn, vol << 4);
- break;
-
- case VOLCMD_PORTAUP:
- PortamentoUp(pChn, vol << 2);
- break;
-
- case VOLCMD_PORTADOWN:
- PortamentoDown(pChn, vol << 2);
- break;
- }
- }
- }
-
- // Effects
- if (cmd) switch (cmd)
- {
- // Set Volume
- case CMD_VOLUME:
- if (!m_nTickCount)
- {
- pChn->nVolume = (param < 64) ? param*4 : 256;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- break;
-
- // Portamento Up
- case CMD_PORTAMENTOUP:
- if ((!param) && (m_nType & MOD_TYPE_MOD)) break;
- PortamentoUp(pChn, param);
- break;
-
- // Portamento Down
- case CMD_PORTAMENTODOWN:
- if ((!param) && (m_nType & MOD_TYPE_MOD)) break;
- PortamentoDown(pChn, param);
- break;
-
- // Volume Slide
- case CMD_VOLUMESLIDE:
- if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param);
- break;
-
- // Tone-Portamento
- case CMD_TONEPORTAMENTO:
- TonePortamento(pChn, param);
- break;
-
- // Tone-Portamento + Volume Slide
- case CMD_TONEPORTAVOL:
- if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param);
- TonePortamento(pChn, 0);
- break;
-
- // Vibrato
- case CMD_VIBRATO:
- Vibrato(pChn, param);
- break;
-
- // Vibrato + Volume Slide
- case CMD_VIBRATOVOL:
- if ((param) || (m_nType != MOD_TYPE_MOD)) VolumeSlide(pChn, param);
- Vibrato(pChn, 0);
- break;
-
- // Set Speed
- case CMD_SPEED:
- if (!m_nTickCount) SetSpeed(param);
- break;
-
- // Set Tempo
- case CMD_TEMPO:
- if (!m_nTickCount)
- {
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
- {
- if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
- }
- SetTempo(param);
- }
- break;
-
- // Set Offset
- case CMD_OFFSET:
- if (m_nTickCount) break;
- if (param) pChn->nOldOffset = param; else param = pChn->nOldOffset;
- param <<= 8;
- param |= (UINT)(pChn->nOldHiOffset) << 16;
- if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
- {
- if (bPorta)
- pChn->nPos = param;
- else
- pChn->nPos += param;
- if (pChn->nPos >= pChn->nLength)
- {
- if (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)))
- {
- pChn->nPos = pChn->nLoopStart;
- if ((m_dwSongFlags & SONG_ITOLDEFFECTS) && (pChn->nLength > 4))
- {
- pChn->nPos = pChn->nLength - 2;
- }
- }
- }
- } else
- if ((param < pChn->nLength) && (m_nType & (MOD_TYPE_MTM|MOD_TYPE_DMF)))
- {
- pChn->nPos = param;
- }
- break;
-
- // Arpeggio
- case CMD_ARPEGGIO:
- if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break;
- if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break;
- pChn->nCommand = CMD_ARPEGGIO;
- if (param) pChn->nArpeggio = param;
- break;
-
- // Retrig
- case CMD_RETRIG:
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (!(param & 0xF0)) param |= pChn->nRetrigParam & 0xF0;
- if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F;
- param |= 0x100; // increment retrig count on first row
- }
- if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
- RetrigNote(nChn, param);
- break;
-
- // Tremor
- case CMD_TREMOR:
- if (m_nTickCount) break;
- pChn->nCommand = CMD_TREMOR;
- if (param) pChn->nTremorParam = param;
- break;
-
- // Set Global Volume
- case CMD_GLOBALVOLUME:
- if (m_nTickCount) break;
- if (m_nType != MOD_TYPE_IT) param <<= 1;
- if (param > 128) param = 128;
- m_nGlobalVolume = param << 1;
- break;
-
- // Global Volume Slide
- case CMD_GLOBALVOLSLIDE:
- GlobalVolSlide(param);
- break;
-
- // Set 8-bit Panning
- case CMD_PANNING8:
- if (m_nTickCount) break;
- if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND;
- if (m_nType & (MOD_TYPE_IT|MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- pChn->nPan = param;
- } else
- if (param <= 0x80)
- {
- pChn->nPan = param << 1;
- } else
- if (param == 0xA4)
- {
- pChn->dwFlags |= CHN_SURROUND;
- pChn->nPan = 0x80;
- }
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- break;
-
- // Panning Slide
- case CMD_PANNINGSLIDE:
- PanningSlide(pChn, param);
- break;
-
- // Tremolo
- case CMD_TREMOLO:
- Tremolo(pChn, param);
- break;
-
- // Fine Vibrato
- case CMD_FINEVIBRATO:
- FineVibrato(pChn, param);
- break;
-
- // MOD/XM Exx Extended Commands
- case CMD_MODCMDEX:
- ExtendedMODCommands(nChn, param);
- break;
-
- // S3M/IT Sxx Extended Commands
- case CMD_S3MCMDEX:
- ExtendedS3MCommands(nChn, param);
- break;
-
- // Key Off
- case CMD_KEYOFF:
- if (!m_nTickCount) KeyOff(nChn);
- break;
-
- // Extra-fine porta up/down
- case CMD_XFINEPORTAUPDOWN:
- switch(param & 0xF0)
- {
- case 0x10: ExtraFinePortamentoUp(pChn, param & 0x0F); break;
- case 0x20: ExtraFinePortamentoDown(pChn, param & 0x0F); break;
- // Modplug XM Extensions
- case 0x50:
- case 0x60:
- case 0x70:
- case 0x90:
- case 0xA0: ExtendedS3MCommands(nChn, param); break;
- }
- break;
-
- // Set Channel Global Volume
- case CMD_CHANNELVOLUME:
- if (m_nTickCount) break;
- if (param <= 64)
- {
- pChn->nGlobalVol = param;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- break;
-
- // Channel volume slide
- case CMD_CHANNELVOLSLIDE:
- ChannelVolSlide(pChn, param);
- break;
-
- // Panbrello (IT)
- case CMD_PANBRELLO:
- Panbrello(pChn, param);
- break;
-
- // Set Envelope Position
- case CMD_SETENVPOSITION:
- if (!m_nTickCount)
- {
- pChn->nVolEnvPosition = param;
- pChn->nPanEnvPosition = param;
- pChn->nPitchEnvPosition = param;
- if (pChn->pHeader)
- {
- INSTRUMENTHEADER *penv = pChn->pHeader;
- if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1]))
- {
- pChn->dwFlags &= ~CHN_PANENV;
- }
- }
- }
- break;
-
- // Position Jump
- case CMD_POSITIONJUMP:
- nPosJump = param;
- break;
-
- // Pattern Break
- case CMD_PATTERNBREAK:
- nBreakRow = param;
- break;
-
- // Midi Controller
- case CMD_MIDI:
- if (m_nTickCount) break;
- if (param < 0x80)
- {
- ProcessMidiMacro(nChn, &m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param);
- } else
- {
- ProcessMidiMacro(nChn, &m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0);
- }
- break;
- }
- }
-
- // Navigation Effects
- if (!m_nTickCount)
- {
- // Pattern Loop
- if (nPatLoopRow >= 0)
- {
- m_nNextPattern = m_nCurrentPattern;
- m_nNextRow = nPatLoopRow;
- if (m_nPatternDelay) m_nNextRow++;
- } else
- // Pattern Break / Position Jump only if no loop running
- if ((nBreakRow >= 0) || (nPosJump >= 0))
- {
- BOOL bNoLoop = FALSE;
- if (nPosJump < 0) nPosJump = m_nCurrentPattern+1;
- if (nBreakRow < 0) nBreakRow = 0;
- // Modplug Tracker & ModPlugin allow backward jumps
- #ifndef FASTSOUNDLIB
- if ((nPosJump < (int)m_nCurrentPattern)
- || ((nPosJump == (int)m_nCurrentPattern) && (nBreakRow <= (int)m_nRow)))
- {
- if (!IsValidBackwardJump(m_nCurrentPattern, m_nRow, nPosJump, nBreakRow))
- {
- if (m_nRepeatCount)
- {
- if (m_nRepeatCount > 0) m_nRepeatCount--;
- } else
- {
- #ifdef MODPLUG_TRACKER
- if (gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS)
- #endif
- // Backward jump disabled
- bNoLoop = TRUE;
- //reset repeat count incase there are multiple loops.
- //(i.e. Unreal tracks)
- m_nRepeatCount = m_nInitialRepeatCount;
- }
- }
- }
- #endif // FASTSOUNDLIB
- if (((!bNoLoop) && (nPosJump < MAX_ORDERS))
- && ((nPosJump != (int)m_nCurrentPattern) || (nBreakRow != (int)m_nRow)))
- {
- if (nPosJump != (int)m_nCurrentPattern)
- {
- for (UINT i=0; i<m_nChannels; i++) Chn[i].nPatternLoopCount = 0;
- }
- m_nNextPattern = nPosJump;
- m_nNextRow = (UINT)nBreakRow;
- }
- }
- }
- return TRUE;
-}
-
-
-////////////////////////////////////////////////////////////
-// Channels effects
-
-void CSoundFile::PortamentoUp(MODCHANNEL *pChn, UINT param)
-//---------------------------------------------------------
-{
- if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
- if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
- {
- if (param & 0x0F)
- {
- if ((param & 0xF0) == 0xF0)
- {
- FinePortamentoUp(pChn, param & 0x0F);
- } else
- if ((param & 0xF0) == 0xE0)
- {
- ExtraFinePortamentoUp(pChn, param & 0x0F);
- }
- }
- return;
- }
- // Regular Slide
- if (!(m_dwSongFlags & SONG_FIRSTTICK))
- {
- DoFreqSlide(pChn, -(int)(param * 4));
- }
-}
-
-
-void CSoundFile::PortamentoDown(MODCHANNEL *pChn, UINT param)
-//-----------------------------------------------------------
-{
- if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
- if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
- {
- if (param & 0x0F)
- {
- if ((param & 0xF0) == 0xF0)
- {
- FinePortamentoDown(pChn, param & 0x0F);
- } else
- if ((param & 0xF0) == 0xE0)
- {
- ExtraFinePortamentoDown(pChn, param & 0x0F);
- }
- }
- return;
- }
- if (!(m_dwSongFlags & SONG_FIRSTTICK)) DoFreqSlide(pChn, (int)(param << 2));
-}
-
-
-void CSoundFile::FinePortamentoUp(MODCHANNEL *pChn, UINT param)
-//-------------------------------------------------------------
-{
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
- }
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- if ((pChn->nPeriod) && (param))
- {
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[param & 0x0F], 65536);
- } else
- {
- pChn->nPeriod -= (int)(param * 4);
- }
- if (pChn->nPeriod < 1) pChn->nPeriod = 1;
- }
- }
-}
-
-
-void CSoundFile::FinePortamentoDown(MODCHANNEL *pChn, UINT param)
-//---------------------------------------------------------------
-{
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
- }
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- if ((pChn->nPeriod) && (param))
- {
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[param & 0x0F], 65536);
- } else
- {
- pChn->nPeriod += (int)(param * 4);
- }
- if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
- }
- }
-}
-
-
-void CSoundFile::ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param)
-//------------------------------------------------------------------
-{
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
- }
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- if ((pChn->nPeriod) && (param))
- {
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideDownTable[param & 0x0F], 65536);
- } else
- {
- pChn->nPeriod -= (int)(param);
- }
- if (pChn->nPeriod < 1) pChn->nPeriod = 1;
- }
- }
-}
-
-
-void CSoundFile::ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param)
-//--------------------------------------------------------------------
-{
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (param) pChn->nOldFinePortaUpDown = param; else param = pChn->nOldFinePortaUpDown;
- }
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- if ((pChn->nPeriod) && (param))
- {
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- pChn->nPeriod = _muldivr(pChn->nPeriod, FineLinearSlideUpTable[param & 0x0F], 65536);
- } else
- {
- pChn->nPeriod += (int)(param);
- }
- if (pChn->nPeriod > 0xFFFF) pChn->nPeriod = 0xFFFF;
- }
- }
-}
-
-
-// Portamento Slide
-void CSoundFile::TonePortamento(MODCHANNEL *pChn, UINT param)
-//-----------------------------------------------------------
-{
- if (param) pChn->nPortamentoSlide = param * 4;
- pChn->dwFlags |= CHN_PORTAMENTO;
- if ((pChn->nPeriod) && (pChn->nPortamentoDest) && (!(m_dwSongFlags & SONG_FIRSTTICK)))
- {
- if (pChn->nPeriod < pChn->nPortamentoDest)
- {
- LONG delta = (int)pChn->nPortamentoSlide;
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- UINT n = pChn->nPortamentoSlide >> 2;
- if (n > 255) n = 255;
- delta = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536) - pChn->nPeriod;
- if (delta < 1) delta = 1;
- }
- pChn->nPeriod += delta;
- if (pChn->nPeriod > pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
- } else
- if (pChn->nPeriod > pChn->nPortamentoDest)
- {
- LONG delta = - (int)pChn->nPortamentoSlide;
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- UINT n = pChn->nPortamentoSlide >> 2;
- if (n > 255) n = 255;
- delta = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536) - pChn->nPeriod;
- if (delta > -1) delta = -1;
- }
- pChn->nPeriod += delta;
- if (pChn->nPeriod < pChn->nPortamentoDest) pChn->nPeriod = pChn->nPortamentoDest;
- }
- }
-}
-
-
-void CSoundFile::Vibrato(MODCHANNEL *p, UINT param)
-//-------------------------------------------------
-{
- if (param & 0x0F) p->nVibratoDepth = (param & 0x0F) * 4;
- if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
- p->dwFlags |= CHN_VIBRATO;
-}
-
-
-void CSoundFile::FineVibrato(MODCHANNEL *p, UINT param)
-//-----------------------------------------------------
-{
- if (param & 0x0F) p->nVibratoDepth = param & 0x0F;
- if (param & 0xF0) p->nVibratoSpeed = (param >> 4) & 0x0F;
- p->dwFlags |= CHN_VIBRATO;
-}
-
-
-void CSoundFile::Panbrello(MODCHANNEL *p, UINT param)
-//---------------------------------------------------
-{
- if (param & 0x0F) p->nPanbrelloDepth = param & 0x0F;
- if (param & 0xF0) p->nPanbrelloSpeed = (param >> 4) & 0x0F;
- p->dwFlags |= CHN_PANBRELLO;
-}
-
-
-void CSoundFile::VolumeSlide(MODCHANNEL *pChn, UINT param)
-//--------------------------------------------------------
-{
- if (param) pChn->nOldVolumeSlide = param; else param = pChn->nOldVolumeSlide;
- LONG newvolume = pChn->nVolume;
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_AMF))
- {
- if ((param & 0x0F) == 0x0F)
- {
- if (param & 0xF0)
- {
- FineVolumeUp(pChn, (param >> 4));
- return;
- } else
- {
- if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES)))
- {
- newvolume -= 0x0F * 4;
- }
- }
- } else
- if ((param & 0xF0) == 0xF0)
- {
- if (param & 0x0F)
- {
- FineVolumeDown(pChn, (param & 0x0F));
- return;
- } else
- {
- if ((m_dwSongFlags & SONG_FIRSTTICK) && (!(m_dwSongFlags & SONG_FASTVOLSLIDES)))
- {
- newvolume += 0x0F * 4;
- }
- }
- }
- }
- if ((!(m_dwSongFlags & SONG_FIRSTTICK)) || (m_dwSongFlags & SONG_FASTVOLSLIDES))
- {
- if (param & 0x0F) newvolume -= (int)((param & 0x0F) * 4);
- else newvolume += (int)((param & 0xF0) >> 2);
- if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- if (newvolume < 0) newvolume = 0;
- if (newvolume > 256) newvolume = 256;
- pChn->nVolume = newvolume;
-}
-
-
-void CSoundFile::PanningSlide(MODCHANNEL *pChn, UINT param)
-//---------------------------------------------------------
-{
- LONG nPanSlide = 0;
- if (param) pChn->nOldPanSlide = param; else param = pChn->nOldPanSlide;
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM))
- {
- if (((param & 0x0F) == 0x0F) && (param & 0xF0))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- param = (param & 0xF0) >> 2;
- nPanSlide = - (int)param;
- }
- } else
- if (((param & 0xF0) == 0xF0) && (param & 0x0F))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- nPanSlide = (param & 0x0F) << 2;
- }
- } else
- {
- if (!(m_dwSongFlags & SONG_FIRSTTICK))
- {
- if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2);
- else nPanSlide = -(int)((param & 0xF0) >> 2);
- }
- }
- } else
- {
- if (!(m_dwSongFlags & SONG_FIRSTTICK))
- {
- if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2);
- else nPanSlide = (int)((param & 0xF0) >> 2);
- }
- }
- if (nPanSlide)
- {
- nPanSlide += pChn->nPan;
- if (nPanSlide < 0) nPanSlide = 0;
- if (nPanSlide > 256) nPanSlide = 256;
- pChn->nPan = nPanSlide;
- }
-}
-
-
-void CSoundFile::FineVolumeUp(MODCHANNEL *pChn, UINT param)
-//---------------------------------------------------------
-{
- if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- pChn->nVolume += param * 4;
- if (pChn->nVolume > 256) pChn->nVolume = 256;
- if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
-}
-
-
-void CSoundFile::FineVolumeDown(MODCHANNEL *pChn, UINT param)
-//-----------------------------------------------------------
-{
- if (param) pChn->nOldFineVolUpDown = param; else param = pChn->nOldFineVolUpDown;
- if (m_dwSongFlags & SONG_FIRSTTICK)
- {
- pChn->nVolume -= param * 4;
- if (pChn->nVolume < 0) pChn->nVolume = 0;
- if (m_nType & MOD_TYPE_MOD) pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
-}
-
-
-void CSoundFile::Tremolo(MODCHANNEL *p, UINT param)
-//-------------------------------------------------
-{
- if (param & 0x0F) p->nTremoloDepth = (param & 0x0F) << 2;
- if (param & 0xF0) p->nTremoloSpeed = (param >> 4) & 0x0F;
- p->dwFlags |= CHN_TREMOLO;
-}
-
-
-void CSoundFile::ChannelVolSlide(MODCHANNEL *pChn, UINT param)
-//------------------------------------------------------------
-{
- LONG nChnSlide = 0;
- if (param) pChn->nOldChnVolSlide = param; else param = pChn->nOldChnVolSlide;
- if (((param & 0x0F) == 0x0F) && (param & 0xF0))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = param >> 4;
- } else
- if (((param & 0xF0) == 0xF0) && (param & 0x0F))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK) nChnSlide = - (int)(param & 0x0F);
- } else
- {
- if (!(m_dwSongFlags & SONG_FIRSTTICK))
- {
- if (param & 0x0F) nChnSlide = -(int)(param & 0x0F);
- else nChnSlide = (int)((param & 0xF0) >> 4);
- }
- }
- if (nChnSlide)
- {
- nChnSlide += pChn->nGlobalVol;
- if (nChnSlide < 0) nChnSlide = 0;
- if (nChnSlide > 64) nChnSlide = 64;
- pChn->nGlobalVol = nChnSlide;
- }
-}
-
-
-void CSoundFile::ExtendedMODCommands(UINT nChn, UINT param)
-//---------------------------------------------------------
-{
- MODCHANNEL *pChn = &Chn[nChn];
- UINT command = param & 0xF0;
- param &= 0x0F;
- switch(command)
- {
- // E0x: Set Filter
- // E1x: Fine Portamento Up
- case 0x10: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoUp(pChn, param); break;
- // E2x: Fine Portamento Down
- case 0x20: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FinePortamentoDown(pChn, param); break;
- // E3x: Set Glissando Control
- case 0x30: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
- // E4x: Set Vibrato WaveForm
- case 0x40: pChn->nVibratoType = param & 0x07; break;
- // E5x: Set FineTune
- case 0x50: if (m_nTickCount) break;
- pChn->nC4Speed = S3MFineTuneTable[param];
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- pChn->nFineTune = param*2;
- else
- pChn->nFineTune = MOD2XMFineTune(param);
- if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
- break;
- // E6x: Pattern Loop
- // E7x: Set Tremolo WaveForm
- case 0x70: pChn->nTremoloType = param & 0x07; break;
- // E8x: Set 4-bit Panning
- case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
- // E9x: Retrig
- case 0x90: RetrigNote(nChn, param); break;
- // EAx: Fine Volume Up
- case 0xA0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeUp(pChn, param); break;
- // EBx: Fine Volume Down
- case 0xB0: if ((param) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) FineVolumeDown(pChn, param); break;
- // ECx: Note Cut
- case 0xC0: NoteCut(nChn, param); break;
- // EDx: Note Delay
- // EEx: Pattern Delay
- // EFx: MOD: Invert Loop, XM: Set Active Midi Macro
- case 0xF0: pChn->nActiveMacro = param; break;
- }
-}
-
-
-void CSoundFile::ExtendedS3MCommands(UINT nChn, UINT param)
-//---------------------------------------------------------
-{
- MODCHANNEL *pChn = &Chn[nChn];
- UINT command = param & 0xF0;
- param &= 0x0F;
- switch(command)
- {
- // S0x: Set Filter
- // S1x: Set Glissando Control
- case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
- // S2x: Set FineTune
- case 0x20: if (m_nTickCount) break;
- pChn->nC4Speed = S3MFineTuneTable[param & 0x0F];
- pChn->nFineTune = MOD2XMFineTune(param);
- if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC4Speed);
- break;
- // S3x: Set Vibrato WaveForm
- case 0x30: pChn->nVibratoType = param & 0x07; break;
- // S4x: Set Tremolo WaveForm
- case 0x40: pChn->nTremoloType = param & 0x07; break;
- // S5x: Set Panbrello WaveForm
- case 0x50: pChn->nPanbrelloType = param & 0x07; break;
- // S6x: Pattern Delay for x frames
- case 0x60: m_nFrameDelay = param; break;
- // S7x: Envelope Control
- case 0x70: if (m_nTickCount) break;
- switch(param)
- {
- case 0:
- case 1:
- case 2:
- {
- MODCHANNEL *bkp = &Chn[m_nChannels];
- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, bkp++)
- {
- if (bkp->nMasterChn == nChn+1)
- {
- if (param == 1) KeyOff(i); else
- if (param == 2) bkp->dwFlags |= CHN_NOTEFADE; else
- { bkp->dwFlags |= CHN_NOTEFADE; bkp->nFadeOutVol = 0; }
- }
- }
- }
- break;
- case 3: pChn->nNNA = NNA_NOTECUT; break;
- case 4: pChn->nNNA = NNA_CONTINUE; break;
- case 5: pChn->nNNA = NNA_NOTEOFF; break;
- case 6: pChn->nNNA = NNA_NOTEFADE; break;
- case 7: pChn->dwFlags &= ~CHN_VOLENV; break;
- case 8: pChn->dwFlags |= CHN_VOLENV; break;
- case 9: pChn->dwFlags &= ~CHN_PANENV; break;
- case 10: pChn->dwFlags |= CHN_PANENV; break;
- case 11: pChn->dwFlags &= ~CHN_PITCHENV; break;
- case 12: pChn->dwFlags |= CHN_PITCHENV; break;
- }
- break;
- // S8x: Set 4-bit Panning
- case 0x80: if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
- // S9x: Set Surround
- case 0x90: ExtendedChannelEffect(pChn, param & 0x0F); break;
- // SAx: Set 64k Offset
- case 0xA0: if (!m_nTickCount)
- {
- pChn->nOldHiOffset = param;
- if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
- {
- DWORD pos = param << 16;
- if (pos < pChn->nLength) pChn->nPos = pos;
- }
- }
- break;
- // SBx: Pattern Loop
- // SCx: Note Cut
- case 0xC0: NoteCut(nChn, param); break;
- // SDx: Note Delay
- // case 0xD0: break;
- // SEx: Pattern Delay for x rows
- // SFx: S3M: Funk Repeat, IT: Set Active Midi Macro
- case 0xF0: pChn->nActiveMacro = param; break;
- }
-}
-
-
-void CSoundFile::ExtendedChannelEffect(MODCHANNEL *pChn, UINT param)
-//------------------------------------------------------------------
-{
- // S9x and X9x commands (S3M/XM/IT only)
- if (m_nTickCount) return;
- switch(param & 0x0F)
- {
- // S90: Surround Off
- case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break;
- // S91: Surround On
- case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break;
- ////////////////////////////////////////////////////////////
- // Modplug Extensions
- // S98: Reverb Off
- case 0x08:
- pChn->dwFlags &= ~CHN_REVERB;
- pChn->dwFlags |= CHN_NOREVERB;
- break;
- // S99: Reverb On
- case 0x09:
- pChn->dwFlags &= ~CHN_NOREVERB;
- pChn->dwFlags |= CHN_REVERB;
- break;
- // S9A: 2-Channels surround mode
- case 0x0A:
- m_dwSongFlags &= ~SONG_SURROUNDPAN;
- break;
- // S9B: 4-Channels surround mode
- case 0x0B:
- m_dwSongFlags |= SONG_SURROUNDPAN;
- break;
- // S9C: IT Filter Mode
- case 0x0C:
- m_dwSongFlags &= ~SONG_MPTFILTERMODE;
- break;
- // S9D: MPT Filter Mode
- case 0x0D:
- m_dwSongFlags |= SONG_MPTFILTERMODE;
- break;
- // S9E: Go forward
- case 0x0E:
- pChn->dwFlags &= ~(CHN_PINGPONGFLAG);
- break;
- // S9F: Go backward (set position at the end for non-looping samples)
- case 0x0F:
- if ((!(pChn->dwFlags & CHN_LOOP)) && (!pChn->nPos) && (pChn->nLength))
- {
- pChn->nPos = pChn->nLength - 1;
- pChn->nPosLo = 0xFFFF;
- }
- pChn->dwFlags |= CHN_PINGPONGFLAG;
- break;
- }
-}
-
-
-void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param)
-//---------------------------------------------------------------------------
-{
- MODCHANNEL *pChn = &Chn[nChn];
- DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F;
- // Not Internal Device ?
- if (dwMacro != 0x30463046)
- {
- UINT pos = 0, nNib = 0, nBytes = 0;
- DWORD dwMidiCode = 0, dwByteCode = 0;
- while (pos+6 <= 32)
- {
- CHAR cData = pszMidiMacro[pos++];
- if (!cData) break;
- if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else
- if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else
- if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else
- if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else
- if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else
- if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else
- if (nNib >= 2)
- {
- nNib = 0;
- dwMidiCode |= dwByteCode << (nBytes*8);
- dwByteCode = 0;
- nBytes++;
- if (nBytes >= 3)
- {
- UINT nMasterCh = (nChn < m_nChannels) ? nChn+1 : pChn->nMasterChn;
- if ((nMasterCh) && (nMasterCh <= m_nChannels))
- {
- UINT nPlug = ChnSettings[nMasterCh-1].nMixPlugin;
- if ((nPlug) && (nPlug <= MAX_MIXPLUGINS))
- {
- IMixPlugin *pPlugin = m_MixPlugins[nPlug-1].pMixPlugin;
- if ((pPlugin) && (m_MixPlugins[nPlug-1].pMixState))
- {
- pPlugin->MidiSend(dwMidiCode);
- }
- }
- }
- nBytes = 0;
- dwMidiCode = 0;
- }
- }
-
- }
- return;
- }
- // Internal device
- pszMidiMacro += 4;
- // Filter ?
- if (pszMidiMacro[0] == '0')
- {
- CHAR cData1 = pszMidiMacro[2];
- DWORD dwParam = 0;
- if ((cData1 == 'z') || (cData1 == 'Z'))
- {
- dwParam = param;
- } else
- {
- CHAR cData2 = pszMidiMacro[3];
- if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else
- if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4;
- if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else
- if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A);
- }
- switch(pszMidiMacro[1])
- {
- // F0.F0.00.xx: Set CutOff
- case '0':
- {
- int oldcutoff = pChn->nCutOff;
- if (dwParam < 0x80) pChn->nCutOff = dwParam;
-#ifndef NO_FILTER
- oldcutoff -= pChn->nCutOff;
-
- if (oldcutoff < 0) oldcutoff = -oldcutoff;
- if ((pChn->nVolume > 0) || (oldcutoff < 0x10)
- || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol)))
- SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
-#endif // NO_FILTER
- }
- break;
-
- // F0.F0.01.xx: Set Resonance
- case '1':
- if (dwParam < 0x80) pChn->nResonance = dwParam;
-#ifndef NO_FILTER
- SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
-#endif // NO_FILTER
-
- break;
- }
-
- }
-}
-
-
-void CSoundFile::RetrigNote(UINT nChn, UINT param)
-//------------------------------------------------
-{
- // Retrig: bit 8 is set if it's the new XM retrig
- MODCHANNEL *pChn = &Chn[nChn];
- UINT nRetrigSpeed = param & 0x0F;
- UINT nRetrigCount = pChn->nRetrigCount;
- BOOL bDoRetrig = FALSE;
-
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
- {
- if (!nRetrigSpeed) nRetrigSpeed = 1;
- if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE;
- nRetrigCount++;
- } else
- {
- UINT realspeed = nRetrigSpeed;
- if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++;
- if ((m_nTickCount) || (param & 0x100))
- {
- if (!realspeed) realspeed = 1;
- if ((!(param & 0x100)) && (m_nMusicSpeed) && (!(m_nTickCount % realspeed))) bDoRetrig = TRUE;
- nRetrigCount++;
- } else if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) nRetrigCount = 0;
- if (nRetrigCount >= realspeed)
- {
- if ((m_nTickCount) || ((param & 0x100) && (!pChn->nRowNote))) bDoRetrig = TRUE;
- }
- }
- if (bDoRetrig)
- {
- UINT dv = (param >> 4) & 0x0F;
- if (dv)
- {
- int vol = pChn->nVolume;
- if (retrigTable1[dv])
- vol = (vol * retrigTable1[dv]) >> 4;
- else
- vol += ((int)retrigTable2[dv]) << 2;
- if (vol < 0) vol = 0;
- if (vol > 256) vol = 256;
- pChn->nVolume = vol;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- UINT nNote = pChn->nNewNote;
- LONG nOldPeriod = pChn->nPeriod;
- if ((nNote) && (nNote <= 120) && (pChn->nLength)) CheckNNA(nChn, 0, nNote, TRUE);
- BOOL bResetEnv = FALSE;
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if ((pChn->nRowInstr) && (param < 0x100)) { InstrumentChange(pChn, pChn->nRowInstr, FALSE, FALSE); bResetEnv = TRUE; }
- if (param < 0x100) bResetEnv = TRUE;
- }
- NoteChange(nChn, nNote, FALSE, bResetEnv);
- if ((m_nType & MOD_TYPE_IT) && (!pChn->nRowNote) && (nOldPeriod)) pChn->nPeriod = nOldPeriod;
- if (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) nRetrigCount = 0;
- }
- pChn->nRetrigCount = (BYTE)nRetrigCount;
-}
-
-
-void CSoundFile::DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide)
-//-------------------------------------------------------------
-{
- // IT Linear slides
- if (!pChn->nPeriod) return;
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (!(m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))))
- {
- if (nFreqSlide < 0)
- {
- UINT n = (- nFreqSlide) >> 2;
- if (n > 255) n = 255;
- pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideDownTable[n], 65536);
- } else
- {
- UINT n = (nFreqSlide) >> 2;
-
- if (n > 255) n = 255;
- pChn->nPeriod = _muldivr(pChn->nPeriod, LinearSlideUpTable[n], 65536);
- }
- } else
- {
- pChn->nPeriod += nFreqSlide;
- }
- if (pChn->nPeriod < 1)
- {
- pChn->nPeriod = 1;
- if (m_nType & MOD_TYPE_IT)
- {
- pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nFadeOutVol = 0;
- }
- }
-}
-
-
-void CSoundFile::NoteCut(UINT nChn, UINT nTick)
-//---------------------------------------------
-{
- if (m_nTickCount == nTick)
- {
- MODCHANNEL *pChn = &Chn[nChn];
- // if (m_nInstruments) KeyOff(pChn); ?
- pChn->nVolume = 0;
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
-}
-
-
-void CSoundFile::KeyOff(UINT nChn)
-//--------------------------------
-{
- MODCHANNEL *pChn = &Chn[nChn];
- BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE;
- pChn->dwFlags |= CHN_KEYOFF;
- //if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV)))
- if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV)))
- {
- pChn->dwFlags |= CHN_NOTEFADE;
- }
- if (!pChn->nLength) return;
- if ((pChn->dwFlags & CHN_SUSTAINLOOP) && (pChn->pInstrument) && (bKeyOn))
- {
- MODINSTRUMENT *psmp = pChn->pInstrument;
- if (psmp->uFlags & CHN_LOOP)
- {
- if (psmp->uFlags & CHN_PINGPONGLOOP)
- pChn->dwFlags |= CHN_PINGPONGLOOP;
- else
- pChn->dwFlags &= ~(CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
- pChn->dwFlags |= CHN_LOOP;
- pChn->nLength = psmp->nLength;
- pChn->nLoopStart = psmp->nLoopStart;
- pChn->nLoopEnd = psmp->nLoopEnd;
- if (pChn->nLength > pChn->nLoopEnd) pChn->nLength = pChn->nLoopEnd;
- } else
- {
- pChn->dwFlags &= ~(CHN_LOOP|CHN_PINGPONGLOOP|CHN_PINGPONGFLAG);
- pChn->nLength = psmp->nLength;
- }
- }
- if (pChn->pHeader)
- {
- INSTRUMENTHEADER *penv = pChn->pHeader;
- if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut))
- pChn->dwFlags |= CHN_NOTEFADE;
- }
-}
-
-
-//////////////////////////////////////////////////////////
-// CSoundFile: Global Effects
-
-
-void CSoundFile::SetSpeed(UINT param)
-//-----------------------------------
-{
- UINT max = (m_nType == MOD_TYPE_IT) ? 256 : 128;
- // Modplug Tracker and Mod-Plugin don't do this check
-#ifndef MODPLUG_TRACKER
-#ifndef FASTSOUNDLIB
- // Big Hack!!!
- if ((!param) || (param >= 0x80) || ((m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E)))
- {
- if (IsSongFinished(m_nCurrentPattern, m_nRow+1))
- {
- GlobalFadeSong(1000);
- }
- }
-#endif // FASTSOUNDLIB
-#endif // MODPLUG_TRACKER
- if ((m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80;
- if ((param) && (param <= max)) m_nMusicSpeed = param;
-}
-
-
-void CSoundFile::SetTempo(UINT param)
-//-----------------------------------
-{
- if (param < 0x20)
- {
- // Tempo Slide
- if ((param & 0xF0) == 0x10)
- {
- m_nMusicTempo += (param & 0x0F) * 2;
- if (m_nMusicTempo > 255) m_nMusicTempo = 255;
- } else
- {
- m_nMusicTempo -= (param & 0x0F) * 2;
- if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32;
- }
- } else
- {
- m_nMusicTempo = param;
- }
-}
-
-
-int CSoundFile::PatternLoop(MODCHANNEL *pChn, UINT param)
-//-------------------------------------------------------
-{
- if (param)
- {
- if (pChn->nPatternLoopCount)
- {
- pChn->nPatternLoopCount--;
- if (!pChn->nPatternLoopCount) return -1;
- } else
- {
- MODCHANNEL *p = Chn;
- for (UINT i=0; i<m_nChannels; i++, p++) if (p != pChn)
- {
- // Loop already done
- if (p->nPatternLoopCount) return -1;
- }
- pChn->nPatternLoopCount = param;
- }
- return pChn->nPatternLoop;
- } else
- {
- pChn->nPatternLoop = m_nRow;
- }
- return -1;
-}
-
-
-void CSoundFile::GlobalVolSlide(UINT param)
-//-----------------------------------------
-{
- LONG nGlbSlide = 0;
- if (param) m_nOldGlbVolSlide = param; else param = m_nOldGlbVolSlide;
- if (((param & 0x0F) == 0x0F) && (param & 0xF0))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = (param >> 4) * 2;
- } else
- if (((param & 0xF0) == 0xF0) && (param & 0x0F))
- {
- if (m_dwSongFlags & SONG_FIRSTTICK) nGlbSlide = - (int)((param & 0x0F) * 2);
- } else
- {
- if (!(m_dwSongFlags & SONG_FIRSTTICK))
- {
- if (param & 0xF0) nGlbSlide = (int)((param & 0xF0) >> 4) * 2;
- else nGlbSlide = -(int)((param & 0x0F) * 2);
- }
- }
- if (nGlbSlide)
- {
- if (m_nType != MOD_TYPE_IT) nGlbSlide *= 2;
- nGlbSlide += m_nGlobalVolume;
- if (nGlbSlide < 0) nGlbSlide = 0;
- if (nGlbSlide > 256) nGlbSlide = 256;
- m_nGlobalVolume = nGlbSlide;
- }
-}
-
-
-DWORD CSoundFile::IsSongFinished(UINT nStartOrder, UINT nStartRow) const
-//----------------------------------------------------------------------
-{
- UINT nOrd;
-
- for (nOrd=nStartOrder; nOrd<MAX_ORDERS; nOrd++)
- {
- UINT nPat = Order[nOrd];
- if (nPat != 0xFE)
- {
- MODCOMMAND *p;
-
- if (nPat >= MAX_PATTERNS) break;
- p = Patterns[nPat];
- if (p)
- {
- UINT len = PatternSize[nPat] * m_nChannels;
- UINT pos = (nOrd == nStartOrder) ? nStartRow : 0;
- pos *= m_nChannels;
- while (pos < len)
- {
- UINT cmd;
- if ((p[pos].note) || (p[pos].volcmd)) return 0;
- cmd = p[pos].command;
- if (cmd == CMD_MODCMDEX)
- {
- UINT cmdex = p[pos].param & 0xF0;
- if ((!cmdex) || (cmdex == 0x60) || (cmdex == 0xE0) || (cmdex == 0xF0)) cmd = 0;
- }
- if ((cmd) && (cmd != CMD_SPEED) && (cmd != CMD_TEMPO)) return 0;
- pos++;
- }
- }
- }
- }
- return (nOrd < MAX_ORDERS) ? nOrd : MAX_ORDERS-1;
-}
-
-
-BOOL CSoundFile::IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const
-//----------------------------------------------------------------------------------------------------------
-{
- while ((nJumpOrder < MAX_PATTERNS) && (Order[nJumpOrder] == 0xFE)) nJumpOrder++;
- if ((nStartOrder >= MAX_PATTERNS) || (nJumpOrder >= MAX_PATTERNS)) return FALSE;
- // Treat only case with jumps in the same pattern
- if (nJumpOrder > nStartOrder) return TRUE;
- if ((nJumpOrder < nStartOrder) || (nJumpRow >= PatternSize[nStartOrder])
- || (!Patterns[nStartOrder]) || (nStartRow >= 256) || (nJumpRow >= 256)) return FALSE;
- // See if the pattern is being played backward
- BYTE row_hist[256];
- memset(row_hist, 0, sizeof(row_hist));
- UINT nRows = PatternSize[nStartOrder], row = nJumpRow;
- if (nRows > 256) nRows = 256;
- row_hist[nStartRow] = TRUE;
- while ((row < 256) && (!row_hist[row]))
- {
- if (row >= nRows) return TRUE;
- row_hist[row] = TRUE;
- MODCOMMAND *p = Patterns[nStartOrder] + row * m_nChannels;
- row++;
- int breakrow = -1, posjump = 0;
- for (UINT i=0; i<m_nChannels; i++, p++)
- {
- if (p->command == CMD_POSITIONJUMP)
- {
- if (p->param < nStartOrder) return FALSE;
- if (p->param > nStartOrder) return TRUE;
- posjump = TRUE;
- } else
- if (p->command == CMD_PATTERNBREAK)
- {
- breakrow = p->param;
- }
- }
- if (breakrow >= 0)
- {
- if (!posjump) return TRUE;
- row = breakrow;
- }
- if (row >= nRows) return TRUE;
- }
- return FALSE;
-}
-
-
-//////////////////////////////////////////////////////
-// Note/Period/Frequency functions
-
-UINT CSoundFile::GetNoteFromPeriod(UINT period) const
-//---------------------------------------------------
-{
- if (!period) return 0;
- if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
- {
- period >>= 2;
- for (UINT i=0; i<6*12; i++)
- {
- if (period >= ProTrackerPeriodTable[i])
- {
- if ((period != ProTrackerPeriodTable[i]) && (i))
- {
- UINT p1 = ProTrackerPeriodTable[i-1];
- UINT p2 = ProTrackerPeriodTable[i];
- if (p1 - period < (period - p2)) return i+36;
- }
- return i+1+36;
- }
- }
- return 6*12+36;
- } else
- {
- for (UINT i=1; i<120; i++)
- {
- LONG n = GetPeriodFromNote(i, 0, 0);
- if ((n > 0) && (n <= (LONG)period)) return i;
- }
- return 120;
- }
-}
-
-
-
-UINT CSoundFile::GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const
-//-------------------------------------------------------------------------------
-{
- if ((!note) || (note > 0xF0)) return 0;
- if (m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV
- |MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM))
- {
- note--;
- if (m_dwSongFlags & SONG_LINEARSLIDES)
- {
- return (FreqS3MTable[note % 12] << 5) >> (note / 12);
- } else
- {
- if (!nC4Speed) nC4Speed = 8363;
- return _muldiv(8363, (FreqS3MTable[note % 12] << 5), nC4Speed << (note / 12));
- }
- } else
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (note < 13) note = 13;
- note -= 13;
- if (m_dwSongFlags & SONG_LINEARSLIDES)
- {
- LONG l = ((120 - note) << 6) - (nFineTune / 2);
- if (l < 1) l = 1;
- return (UINT)l;
- } else
- {
- int finetune = nFineTune;
- UINT rnote = (note % 12) << 3;
- UINT roct = note / 12;
- int rfine = finetune / 16;
- int i = rnote + rfine + 8;
- if (i < 0) i = 0;
- if (i >= 104) i = 103;
- UINT per1 = XMPeriodTable[i];
- if ( finetune < 0 )
- {
- rfine--;
- finetune = -finetune;
- } else rfine++;
- i = rnote+rfine+8;
- if (i < 0) i = 0;
- if (i >= 104) i = 103;
- UINT per2 = XMPeriodTable[i];
- rfine = finetune & 0x0F;
- per1 *= 16-rfine;
- per2 *= rfine;
- return ((per1 + per2) << 1) >> roct;
- }
- } else
- {
- note--;
- nFineTune = XM2MODFineTune(nFineTune);
- if ((nFineTune) || (note < 36) || (note >= 36+6*12))
- return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12);
- else
- return (ProTrackerPeriodTable[note-36] << 2);
- }
-}
-
-
-UINT CSoundFile::GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac) const
-//-----------------------------------------------------------------------------------
-{
- if (!period) return 0;
- if (m_nType & (MOD_TYPE_MED|MOD_TYPE_MOD|MOD_TYPE_MTM|MOD_TYPE_669|MOD_TYPE_OKT|MOD_TYPE_AMF0))
- {
- return (3546895L*4) / period;
- } else
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
- {
- if (m_dwSongFlags & SONG_LINEARSLIDES)
- return XMLinearTable[period % 768] >> (period / 768);
- else
- return 8363 * 1712L / period;
- } else
- {
- if (m_dwSongFlags & SONG_LINEARSLIDES)
- {
- if (!nC4Speed) nC4Speed = 8363;
- return _muldiv(nC4Speed, 1712L << 8, (period << 8)+nPeriodFrac);
- } else
- {
- return _muldiv(8363, 1712L << 8, (period << 8)+nPeriodFrac);
- }
- }
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h> //for GCCFIX
-#include "stdafx.h"
-#include "sndfile.h"
-
-#define MMCMP_SUPPORT
-
-#ifdef MMCMP_SUPPORT
-extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
-#endif
-
-// External decompressors
-extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter);
-extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
-extern int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen);
-extern DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
-extern void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
-extern void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
-
-
-#define MAX_PACK_TABLES 3
-
-
-// Compression table
-static signed char UnpackTable[MAX_PACK_TABLES][16] =
-//--------------------------------------------
-{
- // CPU-generated dynamic table
- {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
- // u-Law table
- {0, 1, 2, 4, 8, 16, 32, 64,
- -1, -2, -4, -8, -16, -32, -48, -64},
- // Linear table
- {0, 1, 2, 3, 5, 7, 12, 19,
- -1, -2, -3, -5, -7, -12, -19, -31}
-};
-
-
-//////////////////////////////////////////////////////////
-// CSoundFile
-
-CSoundFile::CSoundFile()
-//----------------------
-{
- m_nType = MOD_TYPE_NONE;
- m_dwSongFlags = 0;
- m_nChannels = 0;
- m_nMixChannels = 0;
- m_nSamples = 0;
- m_nInstruments = 0;
- m_nPatternNames = 0;
- m_lpszPatternNames = NULL;
- m_lpszSongComments = NULL;
- m_nFreqFactor = m_nTempoFactor = 128;
- m_nMasterVolume = 128;
- m_nMinPeriod = 0x20;
- m_nMaxPeriod = 0x7FFF;
- m_nRepeatCount = 0;
- memset(Chn, 0, sizeof(Chn));
- memset(ChnMix, 0, sizeof(ChnMix));
- memset(Ins, 0, sizeof(Ins));
- memset(ChnSettings, 0, sizeof(ChnSettings));
- memset(Headers, 0, sizeof(Headers));
- memset(Order, 0xFF, sizeof(Order));
- memset(Patterns, 0, sizeof(Patterns));
- memset(m_szNames, 0, sizeof(m_szNames));
- memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
-}
-
-
-CSoundFile::~CSoundFile()
-//-----------------------
-{
- Destroy();
-}
-
-
-BOOL CSoundFile::Create(LPCBYTE lpStream, DWORD dwMemLength)
-//----------------------------------------------------------
-{
- int i;
-
- m_nType = MOD_TYPE_NONE;
- m_dwSongFlags = 0;
- m_nChannels = 0;
- m_nMixChannels = 0;
- m_nSamples = 0;
- m_nInstruments = 0;
- m_nFreqFactor = m_nTempoFactor = 128;
- m_nMasterVolume = 128;
- m_nDefaultGlobalVolume = 256;
- m_nGlobalVolume = 256;
- m_nOldGlbVolSlide = 0;
- m_nDefaultSpeed = 6;
- m_nDefaultTempo = 125;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- m_nNextRow = 0;
- m_nRow = 0;
- m_nPattern = 0;
- m_nCurrentPattern = 0;
- m_nNextPattern = 0;
- m_nRestartPos = 0;
- m_nMinPeriod = 16;
- m_nMaxPeriod = 32767;
- m_nSongPreAmp = 0x30;
- m_nPatternNames = 0;
- m_nMaxOrderPosition = 0;
- m_lpszPatternNames = NULL;
- m_lpszSongComments = NULL;
- memset(Ins, 0, sizeof(Ins));
- memset(ChnMix, 0, sizeof(ChnMix));
- memset(Chn, 0, sizeof(Chn));
- memset(Headers, 0, sizeof(Headers));
- memset(Order, 0xFF, sizeof(Order));
- memset(Patterns, 0, sizeof(Patterns));
- memset(m_szNames, 0, sizeof(m_szNames));
- memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
- ResetMidiCfg();
- for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64;
- for (UINT nch=0; nch<MAX_BASECHANNELS; nch++)
- {
- ChnSettings[nch].nPan = 128;
- ChnSettings[nch].nVolume = 64;
- ChnSettings[nch].dwFlags = 0;
- ChnSettings[nch].szName[0] = 0;
- }
- if (lpStream)
- {
-#ifdef MMCMP_SUPPORT
- BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength);
-#endif
- if ((!ReadXM(lpStream, dwMemLength))
- && (!ReadIT(lpStream, dwMemLength))
- && (!ReadS3M(lpStream, dwMemLength))
- && (!ReadWav(lpStream, dwMemLength))
-#ifndef MODPLUG_BASIC_SUPPORT
- && (!ReadSTM(lpStream, dwMemLength))
- && (!ReadMed(lpStream, dwMemLength))
- && (!ReadMTM(lpStream, dwMemLength))
- && (!ReadMDL(lpStream, dwMemLength))
- && (!ReadDBM(lpStream, dwMemLength))
- && (!Read669(lpStream, dwMemLength))
- && (!ReadFAR(lpStream, dwMemLength))
- && (!ReadAMS(lpStream, dwMemLength))
- && (!ReadOKT(lpStream, dwMemLength))
- && (!ReadPTM(lpStream, dwMemLength))
- && (!ReadUlt(lpStream, dwMemLength))
- && (!ReadDMF(lpStream, dwMemLength))
- && (!ReadDSM(lpStream, dwMemLength))
- && (!ReadUMX(lpStream, dwMemLength))
- && (!ReadAMF(lpStream, dwMemLength))
- && (!ReadPSM(lpStream, dwMemLength))
- && (!ReadMT2(lpStream, dwMemLength))
-#endif // MODPLUG_BASIC_SUPPORT
- && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE;
-#ifdef MMCMP_SUPPORT
- if (bMMCmp)
- {
- GlobalFreePtr(lpStream);
- lpStream = NULL;
- }
-#endif
- }
- // Adjust song names
- for (i=0; i<MAX_SAMPLES; i++)
- {
- LPSTR p = m_szNames[i];
- int j = 31;
- p[j] = 0;
- while ((j>=0) && (p[j]<=' ')) p[j--] = 0;
- while (j>=0)
- {
- if (((BYTE)p[j]) < ' ') p[j] = ' ';
- j--;
- }
- }
- // Adjust channels
- for (i=0; i<MAX_BASECHANNELS; i++)
- {
- if (ChnSettings[i].nVolume > 64) ChnSettings[i].nVolume = 64;
- if (ChnSettings[i].nPan > 256) ChnSettings[i].nPan = 128;
- Chn[i].nPan = ChnSettings[i].nPan;
- Chn[i].nGlobalVol = ChnSettings[i].nVolume;
- Chn[i].dwFlags = ChnSettings[i].dwFlags;
- Chn[i].nVolume = 256;
- Chn[i].nCutOff = 0x7F;
- }
- // Checking instruments
- MODINSTRUMENT *pins = Ins;
-
- for (i=0; i<MAX_INSTRUMENTS; i++, pins++)
- {
- if (pins->pSample)
- {
- if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
- if (pins->nLoopStart + 3 >= pins->nLoopEnd)
- {
- pins->nLoopStart = 0;
- pins->nLoopEnd = 0;
- }
- if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength;
- if (pins->nSustainStart + 3 >= pins->nSustainEnd)
- {
- pins->nSustainStart = 0;
- pins->nSustainEnd = 0;
- }
- } else
- {
- pins->nLength = 0;
- pins->nLoopStart = 0;
- pins->nLoopEnd = 0;
- pins->nSustainStart = 0;
- pins->nSustainEnd = 0;
- }
- if (!pins->nLoopEnd) pins->uFlags &= ~CHN_LOOP;
- if (!pins->nSustainEnd) pins->uFlags &= ~CHN_SUSTAINLOOP;
- if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
- }
- // Check invalid instruments
- while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--;
- // Set default values
- if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20;
- if (m_nDefaultTempo < 32) m_nDefaultTempo = 125;
- if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
- m_nMusicSpeed = m_nDefaultSpeed;
- m_nMusicTempo = m_nDefaultTempo;
- m_nGlobalVolume = m_nDefaultGlobalVolume;
- m_nNextPattern = 0;
- m_nCurrentPattern = 0;
- m_nPattern = 0;
- m_nBufferCount = 0;
- m_nTickCount = m_nMusicSpeed;
- m_nNextRow = 0;
- m_nRow = 0;
- if ((m_nRestartPos >= MAX_ORDERS) || (Order[m_nRestartPos] >= MAX_PATTERNS)) m_nRestartPos = 0;
- // Load plugins
- if (gpMixPluginCreateProc)
- {
- for (UINT iPlug=0; iPlug<MAX_MIXPLUGINS; iPlug++)
- {
- if ((m_MixPlugins[iPlug].Info.dwPluginId1)
- || (m_MixPlugins[iPlug].Info.dwPluginId2))
- {
- gpMixPluginCreateProc(&m_MixPlugins[iPlug]);
- if (m_MixPlugins[iPlug].pMixPlugin)
- {
- m_MixPlugins[iPlug].pMixPlugin->RestoreAllParameters();
- }
- }
- }
- }
- if (m_nType)
- {
- UINT maxpreamp = 0x10+(m_nChannels*8);
- if (maxpreamp > 100) maxpreamp = 100;
- if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp;
- return TRUE;
- }
- return FALSE;
-}
-
-
-BOOL CSoundFile::Destroy()
-
-//------------------------
-{
- int i;
- for (i=0; i<MAX_PATTERNS; i++) if (Patterns[i])
- {
- FreePattern(Patterns[i]);
- Patterns[i] = NULL;
- }
- m_nPatternNames = 0;
- if (m_lpszPatternNames)
- {
- delete m_lpszPatternNames;
- m_lpszPatternNames = NULL;
- }
- if (m_lpszSongComments)
- {
- delete m_lpszSongComments;
- m_lpszSongComments = NULL;
- }
- for (i=1; i<MAX_SAMPLES; i++)
- {
- MODINSTRUMENT *pins = &Ins[i];
- if (pins->pSample)
- {
- FreeSample(pins->pSample);
- pins->pSample = NULL;
- }
- }
- for (i=0; i<MAX_INSTRUMENTS; i++)
- {
- if (Headers[i])
- {
- delete Headers[i];
- Headers[i] = NULL;
- }
- }
- for (i=0; i<MAX_MIXPLUGINS; i++)
- {
- if ((m_MixPlugins[i].nPluginDataSize) && (m_MixPlugins[i].pPluginData))
- {
- m_MixPlugins[i].nPluginDataSize = 0;
- delete [] (signed char*)m_MixPlugins[i].pPluginData;
- m_MixPlugins[i].pPluginData = NULL;
- }
- m_MixPlugins[i].pMixState = NULL;
- if (m_MixPlugins[i].pMixPlugin)
- {
- m_MixPlugins[i].pMixPlugin->Release();
- m_MixPlugins[i].pMixPlugin = NULL;
- }
- }
- m_nType = MOD_TYPE_NONE;
- m_nChannels = m_nSamples = m_nInstruments = 0;
- return TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// Memory Allocation
-
-MODCOMMAND *CSoundFile::AllocatePattern(UINT rows, UINT nchns)
-//------------------------------------------------------------
-{
- MODCOMMAND *p = new MODCOMMAND[rows*nchns];
- if (p) memset(p, 0, rows*nchns*sizeof(MODCOMMAND));
- return p;
-}
-
-
-void CSoundFile::FreePattern(LPVOID pat)
-//--------------------------------------
-{
- if (pat) delete [] (signed char*)pat;
-}
-
-
-signed char* CSoundFile::AllocateSample(UINT nbytes)
-//-------------------------------------------
-{
- signed char * p = (signed char *)GlobalAllocPtr(GHND, (nbytes+39) & ~7);
- if (p) p += 16;
- return p;
-}
-
-
-void CSoundFile::FreeSample(LPVOID p)
-//-----------------------------------
-{
- if (p)
- {
- GlobalFreePtr(((LPSTR)p)-16);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// Misc functions
-
-void CSoundFile::ResetMidiCfg()
-//-----------------------------
-{
- memset(&m_MidiCfg, 0, sizeof(m_MidiCfg));
- lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF");
- lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC");
- lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v");
- lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0");
- lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p");
- lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z");
- for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8);
-}
-
-
-UINT CSoundFile::GetNumChannels() const
-//-------------------------------------
-{
- UINT n = 0;
- for (UINT i=0; i<m_nChannels; i++) if (ChnSettings[i].nVolume) n++;
- return n;
-}
-
-
-UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize)
-//----------------------------------------------------------------
-{
- LPCSTR p = m_lpszSongComments;
- if (!p) return 0;
- UINT i = 2, ln=0;
- if ((len) && (s)) s[0] = '\x0D';
- if ((len > 1) && (s)) s[1] = '\x0A';
- while ((*p) && (i+2 < len))
- {
- BYTE c = (BYTE)*p++;
- if ((c == 0x0D) || ((c == ' ') && (ln >= linesize)))
- { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; }
- else
- if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; }
- }
- if (s) s[i] = 0;
- return i;
-}
-
-
-UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize)
-//-------------------------------------------------------------------
-{
- LPCSTR p = m_lpszSongComments;
- if (!p) return 0;
- UINT i = 0, ln=0;
- while ((*p) && (i < len-1))
- {
- BYTE c = (BYTE)*p++;
- if ((c == 0x0D) || (c == 0x0A))
- {
- if (ln)
- {
- while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; }
- ln = 0;
- }
- } else
- if ((c == ' ') && (!ln))
- {
- UINT k=0;
- while ((p[k]) && (p[k] >= ' ')) k++;
- if (k <= linesize)
- {
- if (s) s[i] = ' ';
- i++;
- ln++;
- }
- } else
- {
- if (s) s[i] = c;
- i++;
- ln++;
- if (ln == linesize) ln = 0;
- }
- }
- if (ln)
- {
- while ((ln < linesize) && (i < len))
- {
- if (s) s[i] = ' ';
- i++;
- ln++;
- }
- }
- if (s) s[i] = 0;
- return i;
-}
-
-
-BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX)
-//----------------------------------------------------------------------------
-{
- BOOL bReset = FALSE;
- DWORD d = gdwSoundSetup & ~SNDMIX_ENABLEMMX;
- if (bMMX) d |= SNDMIX_ENABLEMMX;
- if ((gdwMixingFreq != nRate) || (gnBitsPerSample != nBits) || (gnChannels != nChannels) || (d != gdwSoundSetup)) bReset = TRUE;
- gnChannels = nChannels;
- gdwSoundSetup = d;
- gdwMixingFreq = nRate;
- gnBitsPerSample = nBits;
- InitPlayer(bReset);
- return TRUE;
-}
-
-
-BOOL CSoundFile::SetResamplingMode(UINT nMode)
-//--------------------------------------------
-{
- DWORD d = gdwSoundSetup & ~(SNDMIX_NORESAMPLING|SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE);
- switch(nMode)
- {
- case SRCMODE_NEAREST: d |= SNDMIX_NORESAMPLING; break;
- case SRCMODE_LINEAR: break;
- case SRCMODE_SPLINE: d |= SNDMIX_HQRESAMPLER; break;
- case SRCMODE_POLYPHASE: d |= (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE); break;
- default:
- return FALSE;
- }
- gdwSoundSetup = d;
- return TRUE;
-}
-
-
-BOOL CSoundFile::SetMasterVolume(UINT nVol, BOOL bAdjustAGC)
-//----------------------------------------------------------
-{
- if (nVol < 1) nVol = 1;
- if (nVol > 0x200) nVol = 0x200; // x4 maximum
- if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC))
- {
- gnAGC = gnAGC * m_nMasterVolume / nVol;
- if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY;
- }
- m_nMasterVolume = nVol;
- return TRUE;
-}
-
-
-void CSoundFile::SetAGC(BOOL b)
-//-----------------------------
-{
- if (b)
- {
- if (!(gdwSoundSetup & SNDMIX_AGC))
- {
- gdwSoundSetup |= SNDMIX_AGC;
- gnAGC = AGC_UNITY;
- }
- } else gdwSoundSetup &= ~SNDMIX_AGC;
-}
-
-
-UINT CSoundFile::GetNumPatterns() const
-//-------------------------------------
-{
- UINT i = 0;
- while ((i < MAX_ORDERS) && (Order[i] < 0xFF)) i++;
- return i;
-}
-
-
-UINT CSoundFile::GetNumInstruments() const
-//----------------------------------------
-{
- UINT n=0;
- for (UINT i=0; i<MAX_INSTRUMENTS; i++) if (Ins[i].pSample) n++;
- return n;
-}
-
-
-UINT CSoundFile::GetMaxPosition() const
-//-------------------------------------
-{
- UINT max = 0;
- UINT i = 0;
-
- while ((i < MAX_ORDERS) && (Order[i] != 0xFF))
- {
- if (Order[i] < MAX_PATTERNS) max += PatternSize[Order[i]];
- i++;
- }
- return max;
-}
-
-
-UINT CSoundFile::GetCurrentPos() const
-//------------------------------------
-{
- UINT pos = 0;
-
- for (UINT i=0; i<m_nCurrentPattern; i++) if (Order[i] < MAX_PATTERNS)
- pos += PatternSize[Order[i]];
- return pos + m_nRow;
-}
-
-
-void CSoundFile::SetCurrentPos(UINT nPos)
-//---------------------------------------
-{
- UINT i, nPattern;
-
- for (i=0; i<MAX_CHANNELS; i++)
- {
- Chn[i].nNote = Chn[i].nNewNote = Chn[i].nNewIns = 0;
- Chn[i].pInstrument = NULL;
- Chn[i].pHeader = NULL;
- Chn[i].nPortamentoDest = 0;
- Chn[i].nCommand = 0;
- Chn[i].nPatternLoopCount = 0;
- Chn[i].nPatternLoop = 0;
- Chn[i].nFadeOutVol = 0;
- Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE;
- Chn[i].nTremorCount = 0;
- }
- if (!nPos)
- {
- for (i=0; i<MAX_CHANNELS; i++)
- {
- Chn[i].nPeriod = 0;
- Chn[i].nPos = Chn[i].nLength = 0;
- Chn[i].nLoopStart = 0;
- Chn[i].nLoopEnd = 0;
- Chn[i].nROfs = Chn[i].nLOfs = 0;
- Chn[i].pSample = NULL;
- Chn[i].pInstrument = NULL;
- Chn[i].pHeader = NULL;
- Chn[i].nCutOff = 0x7F;
- Chn[i].nResonance = 0;
- Chn[i].nLeftVol = Chn[i].nRightVol = 0;
- Chn[i].nNewLeftVol = Chn[i].nNewRightVol = 0;
- Chn[i].nLeftRamp = Chn[i].nRightRamp = 0;
- Chn[i].nVolume = 256;
- if (i < MAX_BASECHANNELS)
- {
- Chn[i].dwFlags = ChnSettings[i].dwFlags;
- Chn[i].nPan = ChnSettings[i].nPan;
- Chn[i].nGlobalVol = ChnSettings[i].nVolume;
- } else
- {
- Chn[i].dwFlags = 0;
- Chn[i].nPan = 128;
- Chn[i].nGlobalVol = 64;
- }
- }
- m_nGlobalVolume = m_nDefaultGlobalVolume;
- m_nMusicSpeed = m_nDefaultSpeed;
- m_nMusicTempo = m_nDefaultTempo;
- }
- m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
- for (nPattern = 0; nPattern < MAX_ORDERS; nPattern++)
- {
- UINT ord = Order[nPattern];
- if (ord == 0xFE) continue;
- if (ord == 0xFF) break;
- if (ord < MAX_PATTERNS)
- {
- if (nPos < (UINT)PatternSize[ord]) break;
- nPos -= PatternSize[ord];
- }
- }
- // Buggy position ?
- if ((nPattern >= MAX_ORDERS)
- || (Order[nPattern] >= MAX_PATTERNS)
- || (nPos >= PatternSize[Order[nPattern]]))
- {
- nPos = 0;
- nPattern = 0;
- }
- UINT nRow = nPos;
- if ((nRow) && (Order[nPattern] < MAX_PATTERNS))
- {
- MODCOMMAND *p = Patterns[Order[nPattern]];
- if ((p) && (nRow < PatternSize[Order[nPattern]]))
- {
- BOOL bOk = FALSE;
- while ((!bOk) && (nRow > 0))
- {
- UINT n = nRow * m_nChannels;
- for (UINT k=0; k<m_nChannels; k++, n++)
- {
- if (p[n].note)
- {
- bOk = TRUE;
- break;
- }
- }
- if (!bOk) nRow--;
- }
- }
- }
- m_nNextPattern = nPattern;
- m_nNextRow = nRow;
- m_nTickCount = m_nMusicSpeed;
- m_nBufferCount = 0;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
-}
-
-
-void CSoundFile::SetCurrentOrder(UINT nPos)
-//-----------------------------------------
-{
- while ((nPos < MAX_ORDERS) && (Order[nPos] == 0xFE)) nPos++;
- if ((nPos >= MAX_ORDERS) || (Order[nPos] >= MAX_PATTERNS)) return;
- for (UINT j=0; j<MAX_CHANNELS; j++)
- {
- Chn[j].nPeriod = 0;
- Chn[j].nNote = 0;
- Chn[j].nPortamentoDest = 0;
- Chn[j].nCommand = 0;
- Chn[j].nPatternLoopCount = 0;
- Chn[j].nPatternLoop = 0;
- Chn[j].nTremorCount = 0;
- }
- if (!nPos)
- {
- SetCurrentPos(0);
- } else
- {
- m_nNextPattern = nPos;
- m_nRow = m_nNextRow = 0;
- m_nPattern = 0;
- m_nTickCount = m_nMusicSpeed;
- m_nBufferCount = 0;
- m_nTotalCount = 0;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- }
- m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
-}
-
-
-void CSoundFile::ResetChannels()
-//------------------------------
-{
- m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
- m_nBufferCount = 0;
- for (UINT i=0; i<MAX_CHANNELS; i++)
- {
- Chn[i].nROfs = Chn[i].nLOfs = 0;
- }
-}
-
-
-void CSoundFile::LoopPattern(int nPat, int nRow)
-//----------------------------------------------
-{
- if ((nPat < 0) || (nPat >= MAX_PATTERNS) || (!Patterns[nPat]))
- {
- m_dwSongFlags &= ~SONG_PATTERNLOOP;
- } else
- {
- if ((nRow < 0) || (nRow >= PatternSize[nPat])) nRow = 0;
- m_nPattern = nPat;
- m_nRow = m_nNextRow = nRow;
- m_nTickCount = m_nMusicSpeed;
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- m_nBufferCount = 0;
- m_dwSongFlags |= SONG_PATTERNLOOP;
- }
-}
-
-
-UINT CSoundFile::GetBestSaveFormat() const
-//----------------------------------------
-{
- if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE;
- if (!m_nType) return MOD_TYPE_NONE;
- if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT))
- return MOD_TYPE_MOD;
- if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM))
- return MOD_TYPE_S3M;
- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MED|MOD_TYPE_MTM|MOD_TYPE_MT2))
- return MOD_TYPE_XM;
- return MOD_TYPE_IT;
-}
-
-
-UINT CSoundFile::GetSaveFormats() const
-//-------------------------------------
-{
- UINT n = 0;
- if ((!m_nSamples) || (!m_nChannels) || (m_nType == MOD_TYPE_NONE)) return 0;
- switch(m_nType)
- {
- case MOD_TYPE_MOD: n = MOD_TYPE_MOD;
- case MOD_TYPE_S3M: n = MOD_TYPE_S3M;
- }
- n |= MOD_TYPE_XM | MOD_TYPE_IT;
- if (!m_nInstruments)
- {
- if (m_nSamples < 32) n |= MOD_TYPE_MOD;
- n |= MOD_TYPE_S3M;
- }
- return n;
-}
-
-
-UINT CSoundFile::GetSampleName(UINT nSample,LPSTR s) const
-//--------------------------------------------------------
-{
- char sztmp[40] = ""; // changed from CHAR
- memcpy(sztmp, m_szNames[nSample],32);
- sztmp[31] = 0;
- if (s) strcpy(s, sztmp);
- return strlen(sztmp);
-}
-
-
-UINT CSoundFile::GetInstrumentName(UINT nInstr,LPSTR s) const
-//-----------------------------------------------------------
-{
- char sztmp[40] = ""; // changed from CHAR
- if ((nInstr >= MAX_INSTRUMENTS) || (!Headers[nInstr]))
- {
- if (s) *s = 0;
- return 0;
- }
- INSTRUMENTHEADER *penv = Headers[nInstr];
- memcpy(sztmp, penv->name, 32);
- sztmp[31] = 0;
- if (s) strcpy(s, sztmp);
- return strlen(sztmp);
-}
-
-
-#ifndef NO_PACKING
-UINT CSoundFile::PackSample(int &sample, int next)
-//------------------------------------------------
-{
- UINT i = 0;
- int delta = next - sample;
- if (delta >= 0)
- {
- for (i=0; i<7; i++) if (delta <= (int)CompressionTable[i+1]) break;
- } else
- {
- for (i=8; i<15; i++) if (delta >= (int)CompressionTable[i+1]) break;
- }
- sample += (int)CompressionTable[i];
- return i;
-}
-
-
-BOOL CSoundFile::CanPackSample(signed char * pSample, UINT nLen, UINT nPacking, BYTE *result)
-//-----------------------------------------------------------------------------------
-{
- int pos, old, oldpos, besttable = 0;
- DWORD dwErr, dwTotal, dwResult;
- int i,j;
-
- if (result) *result = 0;
- if ((!pSample) || (nLen < 1024)) return FALSE;
- // Try packing with different tables
- dwResult = 0;
- for (j=1; j<MAX_PACK_TABLES; j++)
- {
- memcpy(CompressionTable, UnpackTable[j], 16);
- dwErr = 0;
- dwTotal = 1;
- old = pos = oldpos = 0;
- for (i=0; i<(int)nLen; i++)
- {
- int s = (int)pSample[i];
- PackSample(pos, s);
- dwErr += abs(pos - oldpos);
- dwTotal += abs(s - old);
- old = s;
- oldpos = pos;
- }
- dwErr = _muldiv(dwErr, 100, dwTotal);
- if (dwErr >= dwResult)
- {
- dwResult = dwErr;
- besttable = j;
- }
- }
- memcpy(CompressionTable, UnpackTable[besttable], 16);
- if (result)
- {
- if (dwResult > 100) *result = 100; else *result = (BYTE)dwResult;
- }
- return (dwResult >= nPacking) ? TRUE : FALSE;
-}
-#endif // NO_PACKING
-
-#ifndef MODPLUG_NO_FILESAVE
-
-UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen)
-//-----------------------------------------------------------------------------------
-{
- UINT len = 0, bufcount;
- signed char buffer[4096];
- signed char *pSample = (signed char *)pins->pSample;
- UINT nLen = pins->nLength;
-
- if ((nMaxLen) && (nLen > nMaxLen)) nLen = nMaxLen;
- if ((!pSample) || (f == NULL) || (!nLen)) return 0;
- switch(nFlags)
- {
-#ifndef NO_PACKING
- // 3: 4-bit ADPCM data
- case RS_ADPCM4:
- {
- int pos;
- len = (nLen + 1) / 2;
- fwrite(CompressionTable, 16, 1, f);
- bufcount = 0;
- pos = 0;
- for (UINT j=0; j<len; j++)
- {
- BYTE b;
- // Sample #1
- b = PackSample(pos, (int)pSample[j*2]);
- // Sample #2
- b |= PackSample(pos, (int)pSample[j*2+1]) << 4;
- buffer[bufcount++] = (signed char)b;
- if (bufcount >= sizeof(buffer))
- {
- fwrite(buffer, 1, bufcount, f);
- bufcount = 0;
- }
- }
- if (bufcount) fwrite(buffer, 1, bufcount, f);
- len += 16;
- }
- break;
-#endif // NO_PACKING
-
- // 16-bit samples
- case RS_PCM16U:
- case RS_PCM16D:
- case RS_PCM16S:
- {
- short int *p = (short int *)pSample;
- int s_old = 0, s_ofs;
- len = nLen * 2;
- bufcount = 0;
- s_ofs = (nFlags == RS_PCM16U) ? 0x8000 : 0;
- for (UINT j=0; j<nLen; j++)
- {
- int s_new = *p;
- p++;
- if (pins->uFlags & CHN_STEREO)
- {
- s_new = (s_new + (*p) + 1) >> 1;
- p++;
- }
- if (nFlags == RS_PCM16D)
- {
- *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
- s_old = s_new;
- } else
- {
- *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
- }
- bufcount += 2;
- if (bufcount >= sizeof(buffer) - 1)
- {
- fwrite(buffer, 1, bufcount, f);
- bufcount = 0;
- }
- }
- if (bufcount) fwrite(buffer, 1, bufcount, f);
- }
- break;
-
-
- // 8-bit Stereo samples (not interleaved)
- case RS_STPCM8S:
- case RS_STPCM8U:
- case RS_STPCM8D:
- {
- int s_ofs = (nFlags == RS_STPCM8U) ? 0x80 : 0;
- for (UINT iCh=0; iCh<2; iCh++)
- {
- signed char *p = pSample + iCh;
- int s_old = 0;
-
- bufcount = 0;
- for (UINT j=0; j<nLen; j++)
- {
- int s_new = *p;
- p += 2;
- if (nFlags == RS_STPCM8D)
- {
- buffer[bufcount++] = (signed char)(s_new - s_old);
- s_old = s_new;
- } else
- {
- buffer[bufcount++] = (signed char)(s_new + s_ofs);
- }
- if (bufcount >= sizeof(buffer))
- {
- fwrite(buffer, 1, bufcount, f);
- bufcount = 0;
- }
- }
- if (bufcount) fwrite(buffer, 1, bufcount, f);
- }
- }
- len = nLen * 2;
- break;
-
- // 16-bit Stereo samples (not interleaved)
- case RS_STPCM16S:
- case RS_STPCM16U:
- case RS_STPCM16D:
- {
- int s_ofs = (nFlags == RS_STPCM16U) ? 0x8000 : 0;
- for (UINT iCh=0; iCh<2; iCh++)
- {
- signed short *p = ((signed short *)pSample) + iCh;
- int s_old = 0;
-
- bufcount = 0;
- for (UINT j=0; j<nLen; j++)
- {
- int s_new = *p;
- p += 2;
- if (nFlags == RS_STPCM16D)
- {
- *((short *)(&buffer[bufcount])) = (short)(s_new - s_old);
- s_old = s_new;
- } else
- {
- *((short *)(&buffer[bufcount])) = (short)(s_new + s_ofs);
- }
- bufcount += 2;
- if (bufcount >= sizeof(buffer))
- {
- fwrite(buffer, 1, bufcount, f);
- bufcount = 0;
- }
- }
- if (bufcount) fwrite(buffer, 1, bufcount, f);
- }
- }
- len = nLen*4;
- break;
-
- // Stereo signed interleaved
- case RS_STIPCM8S:
- case RS_STIPCM16S:
- len = nLen * 2;
- if (nFlags == RS_STIPCM16S) len *= 2;
- fwrite(pSample, 1, len, f);
- break;
-
- // Default: assume 8-bit PCM data
- default:
- len = nLen;
- bufcount = 0;
- {
- signed char *p = pSample;
- int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1;
- int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0;
- if (pins->uFlags & CHN_16BIT) p++;
- for (UINT j=0; j<len; j++)
- {
- int s_new = (signed char)(*p);
- p += sinc;
- if (pins->uFlags & CHN_STEREO)
- {
- s_new = (s_new + ((int)*p) + 1) >> 1;
- p += sinc;
- }
- if (nFlags == RS_PCM8D)
- {
- buffer[bufcount++] = (signed char)(s_new - s_old);
- s_old = s_new;
- } else
- {
- buffer[bufcount++] = (signed char)(s_new + s_ofs);
- }
- if (bufcount >= sizeof(buffer))
- {
- fwrite(buffer, 1, bufcount, f);
- bufcount = 0;
- }
- }
- if (bufcount) fwrite(buffer, 1, bufcount, f);
- }
- }
- return len;
-}
-
-#endif // MODPLUG_NO_FILESAVE
-
-
-// Flags:
-// 0 = signed 8-bit PCM data (default)
-// 1 = unsigned 8-bit PCM data
-// 2 = 8-bit ADPCM data with linear table
-// 3 = 4-bit ADPCM data
-// 4 = 16-bit ADPCM data with linear table
-// 5 = signed 16-bit PCM data
-// 6 = unsigned 16-bit PCM data
-
-
-UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength)
-//------------------------------------------------------------------------------------------------
-{
- UINT len = 0, mem = pIns->nLength+6;
-
- if ((!pIns) || ((int)pIns->nLength < 4) || (!lpMemFile)) return 0;
- if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH;
- pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO);
- if (nFlags & RSF_16BIT)
- {
- mem *= 2;
- pIns->uFlags |= CHN_16BIT;
- }
- if (nFlags & RSF_STEREO)
- {
- mem *= 2;
- pIns->uFlags |= CHN_STEREO;
- }
- if ((pIns->pSample = AllocateSample(mem)) == NULL)
- {
- pIns->nLength = 0;
- return 0;
- }
- switch(nFlags)
- {
- // 1: 8-bit unsigned PCM data
- case RS_PCM8U:
- {
- len = pIns->nLength;
- if (len > dwMemLength) len = pIns->nLength = dwMemLength;
- signed char *pSample = pIns->pSample;
- for (UINT j=0; j<len; j++) pSample[j] = (signed char)(lpMemFile[j] - 0x80);
- }
- break;
-
- // 2: 8-bit ADPCM data with linear table
- case RS_PCM8D:
- {
- len = pIns->nLength;
- if (len > dwMemLength) break;
- signed char *pSample = pIns->pSample;
- const signed char *p = (const signed char *)lpMemFile;
- int delta = 0;
-
- for (UINT j=0; j<len; j++)
- {
- delta += p[j];
- *pSample++ = (signed char)delta;
- }
- }
- break;
-
- // 3: 4-bit ADPCM data
- case RS_ADPCM4:
- {
- len = (pIns->nLength + 1) / 2;
- if (len > dwMemLength - 16) break;
- memcpy(CompressionTable, lpMemFile, 16);
- lpMemFile += 16;
- signed char *pSample = pIns->pSample;
- signed char delta = 0;
- for (UINT j=0; j<len; j++)
- {
- BYTE b0 = (BYTE)lpMemFile[j];
- BYTE b1 = (BYTE)(lpMemFile[j] >> 4);
- delta = (signed char)GetDeltaValue((int)delta, b0);
- pSample[0] = delta;
- delta = (signed char)GetDeltaValue((int)delta, b1);
- pSample[1] = delta;
- pSample += 2;
- }
- len += 16;
- }
- break;
-
- // 4: 16-bit ADPCM data with linear table
- case RS_PCM16D:
- {
- len = pIns->nLength * 2;
- if (len > dwMemLength) break;
- short int *pSample = (short int *)pIns->pSample;
- short int *p = (short int *)lpMemFile;
- int delta16 = 0;
- for (UINT j=0; j<len; j+=2)
- {
- delta16 += bswapLE16(*p++);
- *pSample++ = (short int)delta16;
- }
- }
- break;
-
- // 5: 16-bit signed PCM data
- case RS_PCM16S:
- {
- len = pIns->nLength * 2;
- if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len);
- short int *pSample = (short int *)pIns->pSample;
- for (UINT j=0; j<len; j+=2)
- {
- short int s = bswapLE16(*pSample);
- *pSample++ = s;
- }
- }
- break;
-
- // 16-bit signed mono PCM motorola byte order
- case RS_PCM16M:
- len = pIns->nLength * 2;
- if (len > dwMemLength) len = dwMemLength & ~1;
- if (len > 1)
- {
- signed char *pSample = (signed char *)pIns->pSample;
- signed char *pSrc = (signed char *)lpMemFile;
- for (UINT j=0; j<len; j+=2)
- {
- // pSample[j] = pSrc[j+1];
- // pSample[j+1] = pSrc[j];
- *((unsigned short *)(pSample+j)) = bswapBE16(*((unsigned short *)(pSrc+j)));
- }
- }
- break;
-
- // 6: 16-bit unsigned PCM data
- case RS_PCM16U:
- {
- len = pIns->nLength * 2;
- if (len > dwMemLength) break;
- short int *pSample = (short int *)pIns->pSample;
- short int *pSrc = (short int *)lpMemFile;
- for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000;
- }
- break;
-
- // 16-bit signed stereo big endian
- case RS_STPCM16M:
- len = pIns->nLength * 2;
- if (len*2 <= dwMemLength)
- {
- signed char *pSample = (signed char *)pIns->pSample;
- signed char *pSrc = (signed char *)lpMemFile;
- for (UINT j=0; j<len; j+=2)
- {
- // pSample[j*2] = pSrc[j+1];
- // pSample[j*2+1] = pSrc[j];
- // pSample[j*2+2] = pSrc[j+1+len];
- // pSample[j*2+3] = pSrc[j+len];
- *((unsigned short *)(pSample+j*2)) = bswapBE16(*((unsigned short *)(pSrc+j)));
- *((unsigned short *)(pSample+j*2+2)) = bswapBE16(*((unsigned short *)(pSrc+j+len)));
- }
- len *= 2;
- }
- break;
-
- // 8-bit stereo samples
- case RS_STPCM8S:
- case RS_STPCM8U:
- case RS_STPCM8D:
- {
- int iadd_l = 0, iadd_r = 0;
- if (nFlags == RS_STPCM8U) { iadd_l = iadd_r = -128; }
- len = pIns->nLength;
- signed char *psrc = (signed char *)lpMemFile;
- signed char *pSample = (signed char *)pIns->pSample;
- if (len*2 > dwMemLength) break;
- for (UINT j=0; j<len; j++)
- {
- pSample[j*2] = (signed char)(psrc[0] + iadd_l);
- pSample[j*2+1] = (signed char)(psrc[len] + iadd_r);
- psrc++;
- if (nFlags == RS_STPCM8D)
- {
- iadd_l = pSample[j*2];
- iadd_r = pSample[j*2+1];
- }
- }
- len *= 2;
- }
- break;
-
- // 16-bit stereo samples
- case RS_STPCM16S:
- case RS_STPCM16U:
- case RS_STPCM16D:
- {
- int iadd_l = 0, iadd_r = 0;
- if (nFlags == RS_STPCM16U) { iadd_l = iadd_r = -0x8000; }
- len = pIns->nLength;
- short int *psrc = (short int *)lpMemFile;
- short int *pSample = (short int *)pIns->pSample;
- if (len*4 > dwMemLength) break;
- for (UINT j=0; j<len; j++)
- {
- pSample[j*2] = (short int) (bswapLE16(psrc[0]) + iadd_l);
- pSample[j*2+1] = (short int) (bswapLE16(psrc[len]) + iadd_r);
- psrc++;
- if (nFlags == RS_STPCM16D)
- {
- iadd_l = pSample[j*2];
- iadd_r = pSample[j*2+1];
- }
- }
- len *= 4;
- }
- break;
-
- // IT 2.14 compressed samples
- case RS_IT2148:
- case RS_IT21416:
- case RS_IT2158:
- case RS_IT21516:
- len = dwMemLength;
- if (len < 4) break;
- if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158))
- ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158));
- else
- ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516));
- break;
-
-#ifndef MODPLUG_BASIC_SUPPORT
-#ifndef FASTSOUNDLIB
- // 8-bit interleaved stereo samples
- case RS_STIPCM8S:
- case RS_STIPCM8U:
- {
- int iadd = 0;
- if (nFlags == RS_STIPCM8U) { iadd = -0x80; }
- len = pIns->nLength;
- if (len*2 > dwMemLength) len = dwMemLength >> 1;
- LPBYTE psrc = (LPBYTE)lpMemFile;
- LPBYTE pSample = (LPBYTE)pIns->pSample;
- for (UINT j=0; j<len; j++)
- {
- pSample[j*2] = (signed char)(psrc[0] + iadd);
- pSample[j*2+1] = (signed char)(psrc[1] + iadd);
- psrc+=2;
- }
- len *= 2;
- }
- break;
-
- // 16-bit interleaved stereo samples
- case RS_STIPCM16S:
- case RS_STIPCM16U:
- {
- int iadd = 0;
- if (nFlags == RS_STIPCM16U) iadd = -32768;
- len = pIns->nLength;
- if (len*4 > dwMemLength) len = dwMemLength >> 2;
- short int *psrc = (short int *)lpMemFile;
- short int *pSample = (short int *)pIns->pSample;
- for (UINT j=0; j<len; j++)
- {
- pSample[j*2] = (short int)(bswapLE16(psrc[0]) + iadd);
- pSample[j*2+1] = (short int)(bswapLE16(psrc[1]) + iadd);
- psrc += 2;
- }
- len *= 4;
- }
- break;
-
- // AMS compressed samples
- case RS_AMS8:
- case RS_AMS16:
- len = 9;
- if (dwMemLength > 9)
- {
- const char *psrc = lpMemFile;
- char packcharacter = lpMemFile[8], *pdest = (char *)pIns->pSample;
- len += bswapLE32(*((LPDWORD)(lpMemFile+4)));
- if (len > dwMemLength) len = dwMemLength;
- UINT dmax = pIns->nLength;
- if (pIns->uFlags & CHN_16BIT) dmax <<= 1;
- AMSUnpack(psrc+9, len-9, pdest, dmax, packcharacter);
- }
- break;
-
- // PTM 8bit delta to 16-bit sample
- case RS_PTM8DTO16:
- {
- len = pIns->nLength * 2;
- if (len > dwMemLength) break;
- signed char *pSample = (signed char *)pIns->pSample;
- signed char delta8 = 0;
- for (UINT j=0; j<len; j++)
- {
- delta8 += lpMemFile[j];
- *pSample++ = delta8;
- }
- WORD *pSampleW = (WORD *)pIns->pSample;
- for (UINT j=0; j<len; j+=2) // swaparoni!
- {
- WORD s = bswapLE16(*pSampleW);
- *pSampleW++ = s;
- }
- }
- break;
-
- // Huffman MDL compressed samples
- case RS_MDL8:
- case RS_MDL16:
- len = dwMemLength;
- if (len >= 4)
- {
- LPBYTE pSample = (LPBYTE)pIns->pSample;
- LPBYTE ibuf = (LPBYTE)lpMemFile;
- DWORD bitbuf = bswapLE32(*((DWORD *)ibuf));
- UINT bitnum = 32;
- BYTE dlt = 0, lowbyte = 0;
- ibuf += 4;
- for (UINT j=0; j<pIns->nLength; j++)
- {
- BYTE hibyte;
- BYTE sign;
- if (nFlags == RS_MDL16) lowbyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 8);
- sign = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 1);
- if (MDLReadBits(bitbuf, bitnum, ibuf, 1))
- {
- hibyte = (BYTE)MDLReadBits(bitbuf, bitnum, ibuf, 3);
- } else
- {
- hibyte = 8;
- while (!MDLReadBits(bitbuf, bitnum, ibuf, 1)) hibyte += 0x10;
- hibyte += MDLReadBits(bitbuf, bitnum, ibuf, 4);
- }
- if (sign) hibyte = ~hibyte;
- dlt += hibyte;
- if (nFlags != RS_MDL16)
- pSample[j] = dlt;
- else
- {
- pSample[j<<1] = lowbyte;
- pSample[(j<<1)+1] = dlt;
- }
- }
- }
- break;
-
- case RS_DMF8:
- case RS_DMF16:
- len = dwMemLength;
- if (len >= 4)
- {
- UINT maxlen = pIns->nLength;
- if (pIns->uFlags & CHN_16BIT) maxlen <<= 1;
- LPBYTE ibuf = (LPBYTE)lpMemFile, ibufmax = (LPBYTE)(lpMemFile+dwMemLength);
- len = DMFUnpack((LPBYTE)pIns->pSample, ibuf, ibufmax, maxlen);
- }
- break;
-
-#ifdef MODPLUG_TRACKER
- // PCM 24-bit signed -> load sample, and normalize it to 16-bit
- case RS_PCM24S:
- case RS_PCM32S:
- len = pIns->nLength * 3;
- if (nFlags == RS_PCM32S) len += pIns->nLength;
- if (len > dwMemLength) break;
- if (len > 4*8)
- {
- UINT slsize = (nFlags == RS_PCM32S) ? 4 : 3;
- LPBYTE pSrc = (LPBYTE)lpMemFile;
- LONG max = 255;
- if (nFlags == RS_PCM32S) pSrc++;
- for (UINT j=0; j<len; j+=slsize)
- {
- LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
- l /= 256;
- if (l > max) max = l;
- if (-l > max) max = -l;
- }
- max = (max / 128) + 1;
- signed short *pDest = (signed short *)pIns->pSample;
- for (UINT k=0; k<len; k+=slsize)
- {
- LONG l = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
- *pDest++ = (signed short)(l / max);
- }
- }
- break;
-
- // Stereo PCM 24-bit signed -> load sample, and normalize it to 16-bit
- case RS_STIPCM24S:
- case RS_STIPCM32S:
- len = pIns->nLength * 6;
- if (nFlags == RS_STIPCM32S) len += pIns->nLength * 2;
- if (len > dwMemLength) break;
- if (len > 8*8)
- {
- UINT slsize = (nFlags == RS_STIPCM32S) ? 4 : 3;
- LPBYTE pSrc = (LPBYTE)lpMemFile;
- LONG max = 255;
- if (nFlags == RS_STIPCM32S) pSrc++;
- for (UINT j=0; j<len; j+=slsize)
- {
- LONG l = ((((pSrc[j+2] << 8) + pSrc[j+1]) << 8) + pSrc[j]) << 8;
- l /= 256;
- if (l > max) max = l;
- if (-l > max) max = -l;
- }
- max = (max / 128) + 1;
- signed short *pDest = (signed short *)pIns->pSample;
- for (UINT k=0; k<len; k+=slsize)
- {
- LONG lr = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
- k += slsize;
- LONG ll = ((((pSrc[k+2] << 8) + pSrc[k+1]) << 8) + pSrc[k]) << 8;
- pDest[0] = (signed short)ll;
- pDest[1] = (signed short)lr;
- pDest += 2;
- }
- }
- break;
-
- // 16-bit signed big endian interleaved stereo
- case RS_STIPCM16M:
- {
- len = pIns->nLength;
- if (len*4 > dwMemLength) len = dwMemLength >> 2;
- LPCBYTE psrc = (LPCBYTE)lpMemFile;
- short int *pSample = (short int *)pIns->pSample;
- for (UINT j=0; j<len; j++)
- {
- pSample[j*2] = (signed short)(((UINT)psrc[0] << 8) | (psrc[1]));
- pSample[j*2+1] = (signed short)(((UINT)psrc[2] << 8) | (psrc[3]));
- psrc += 4;
- }
- len *= 4;
- }
- break;
-
-#endif // MODPLUG_TRACKER
-#endif // !FASTSOUNDLIB
-#endif // !MODPLUG_BASIC_SUPPORT
-
- // Default: 8-bit signed PCM data
- default:
- len = pIns->nLength;
- if (len > dwMemLength) len = pIns->nLength = dwMemLength;
- memcpy(pIns->pSample, lpMemFile, len);
- }
- if (len > dwMemLength)
- {
- if (pIns->pSample)
- {
- pIns->nLength = 0;
- FreeSample(pIns->pSample);
- pIns->pSample = NULL;
- }
- return 0;
- }
- AdjustSampleLoop(pIns);
- return len;
-}
-
-
-void CSoundFile::AdjustSampleLoop(MODINSTRUMENT *pIns)
-//----------------------------------------------------
-{
- if (!pIns->pSample) return;
- if (pIns->nLoopEnd > pIns->nLength) pIns->nLoopEnd = pIns->nLength;
- if (pIns->nLoopStart+2 >= pIns->nLoopEnd)
- {
- pIns->nLoopStart = pIns->nLoopEnd = 0;
- pIns->uFlags &= ~CHN_LOOP;
- }
- UINT len = pIns->nLength;
- if (pIns->uFlags & CHN_16BIT)
- {
- short int *pSample = (short int *)pIns->pSample;
- // Adjust end of sample
- if (pIns->uFlags & CHN_STEREO)
- {
- pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
- pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
- } else
- {
- pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
- }
- if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
- {
- // Fix bad loops
- if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & MOD_TYPE_S3M))
- {
- pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
- pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
- pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
- pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
- pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
- }
- }
- } else
- {
- signed char *pSample = pIns->pSample;
-#ifndef FASTSOUNDLIB
- // Crappy samples (except chiptunes) ?
- if ((pIns->nLength > 0x100) && (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M))
- && (!(pIns->uFlags & CHN_STEREO)))
- {
- int smpend = pSample[pIns->nLength-1], smpfix = 0, kscan;
- for (kscan=pIns->nLength-1; kscan>0; kscan--)
- {
- smpfix = pSample[kscan-1];
- if (smpfix != smpend) break;
- }
- int delta = smpfix - smpend;
- if (((!(pIns->uFlags & CHN_LOOP)) || (kscan > (int)pIns->nLoopEnd))
- && ((delta < -8) || (delta > 8)))
- {
- while (kscan<(int)pIns->nLength)
- {
- if (!(kscan & 7))
- {
- if (smpfix > 0) smpfix--;
- if (smpfix < 0) smpfix++;
- }
- pSample[kscan] = (signed char)smpfix;
- kscan++;
- }
- }
- }
-#endif
- // Adjust end of sample
- if (pIns->uFlags & CHN_STEREO)
- {
- pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
- pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
- } else
- {
- pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
- }
- if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
- {
- if ((pIns->nLoopEnd+3 >= pIns->nLength) || (m_nType & (MOD_TYPE_MOD|MOD_TYPE_S3M)))
- {
- pSample[pIns->nLoopEnd] = pSample[pIns->nLoopStart];
- pSample[pIns->nLoopEnd+1] = pSample[pIns->nLoopStart+1];
- pSample[pIns->nLoopEnd+2] = pSample[pIns->nLoopStart+2];
- pSample[pIns->nLoopEnd+3] = pSample[pIns->nLoopStart+3];
- pSample[pIns->nLoopEnd+4] = pSample[pIns->nLoopStart+4];
- }
- }
- }
-}
-
-
-/////////////////////////////////////////////////////////////
-// Transpose <-> Frequency conversions
-
-// returns 8363*2^((transp*128+ftune)/(12*128))
-DWORD CSoundFile::TransposeToFrequency(int transp, int ftune)
-//-----------------------------------------------------------
-{
- //---GCCFIX: Removed assembly.
- return (DWORD)(8363*pow(2.0, (transp*128+ftune)/(1536)));
-
-#ifdef MSC_VER
- const float _fbase = 8363;
- const float _factor = 1.0f/(12.0f*128.0f);
- int result;
- DWORD freq;
-
- transp = (transp << 7) + ftune;
- _asm {
- fild transp
- fld _factor
- fmulp st(1), st(0)
- fist result
- fisub result
- f2xm1
- fild result
- fld _fbase
- fscale
- fstp st(1)
- fmul st(1), st(0)
- faddp st(1), st(0)
- fistp freq
- }
- UINT derr = freq % 11025;
- if (derr <= 8) freq -= derr;
- if (derr >= 11015) freq += 11025-derr;
- derr = freq % 1000;
- if (derr <= 5) freq -= derr;
- if (derr >= 995) freq += 1000-derr;
- return freq;
-#endif
-}
-
-
-// returns 12*128*log2(freq/8363)
-int CSoundFile::FrequencyToTranspose(DWORD freq)
-//----------------------------------------------
-{
- //---GCCFIX: Removed assembly.
- return int(1536*(log(freq/8363.0)/log(2.0)));
-
-#ifdef MSC_VER
- const float _f1_8363 = 1.0f / 8363.0f;
- const float _factor = 128 * 12;
- LONG result;
-
- if (!freq) return 0;
- _asm {
- fld _factor
- fild freq
- fld _f1_8363
- fmulp st(1), st(0)
- fyl2x
- fistp result
- }
- return result;
-#endif
-}
-
-
-void CSoundFile::FrequencyToTranspose(MODINSTRUMENT *psmp)
-//--------------------------------------------------------
-{
- int f2t = FrequencyToTranspose(psmp->nC4Speed);
- int transp = f2t >> 7;
- int ftune = f2t & 0x7F;
- if (ftune > 80)
- {
- transp++;
- ftune -= 128;
- }
- if (transp > 127) transp = 127;
- if (transp < -127) transp = -127;
- psmp->RelativeTone = transp;
- psmp->nFineTune = ftune;
-}
-
-
-void CSoundFile::CheckCPUUsage(UINT nCPU)
-//---------------------------------------
-{
- if (nCPU > 100) nCPU = 100;
- gnCPUUsage = nCPU;
- if (nCPU < 90)
- {
- m_dwSongFlags &= ~SONG_CPUVERYHIGH;
- } else
- if ((m_dwSongFlags & SONG_CPUVERYHIGH) && (nCPU >= 94))
- {
- UINT i=MAX_CHANNELS;
- while (i >= 8)
- {
- i--;
- if (Chn[i].nLength)
- {
- Chn[i].nLength = Chn[i].nPos = 0;
- nCPU -= 2;
- if (nCPU < 94) break;
- }
- }
- } else
- if (nCPU > 90)
- {
- m_dwSongFlags |= SONG_CPUVERYHIGH;
- }
-}
-
-
-BOOL CSoundFile::SetPatternName(UINT nPat, LPCSTR lpszName)
-//---------------------------------------------------------
-{
- char szName[MAX_PATTERNNAME] = ""; // changed from CHAR
- if (nPat >= MAX_PATTERNS) return FALSE;
- if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME);
- szName[MAX_PATTERNNAME-1] = 0;
- if (!m_lpszPatternNames) m_nPatternNames = 0;
- if (nPat >= m_nPatternNames)
- {
- if (!lpszName[0]) return TRUE;
- UINT len = (nPat+1)*MAX_PATTERNNAME;
- char *p = new char[len]; // changed from CHAR
- if (!p) return FALSE;
- memset(p, 0, len);
- if (m_lpszPatternNames)
- {
- memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME);
- delete m_lpszPatternNames;
- m_lpszPatternNames = NULL;
- }
- m_lpszPatternNames = p;
- m_nPatternNames = nPat + 1;
- }
- memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME);
- return TRUE;
-}
-
-
-BOOL CSoundFile::GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize) const
-//---------------------------------------------------------------------------
-{
- if ((!lpszName) || (!cbSize)) return FALSE;
- lpszName[0] = 0;
- if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME;
- if ((m_lpszPatternNames) && (nPat < m_nPatternNames))
- {
- memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize);
- lpszName[cbSize-1] = 0;
- return TRUE;
- }
- return FALSE;
-}
-
-
-#ifndef FASTSOUNDLIB
-
-UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns)
-//-----------------------------------------------
-{
- UINT nExt = 0;
-
- if (!pbIns) return 0;
- if (m_nInstruments)
- {
- memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL));
- for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++)
- {
- MODCOMMAND *p = Patterns[ipat];
- if (p)
- {
- UINT jmax = PatternSize[ipat] * m_nChannels;
- for (UINT j=0; j<jmax; j++, p++)
- {
- if ((p->note) && (p->note <= 120))
- {
- if ((p->instr) && (p->instr < MAX_INSTRUMENTS))
- {
- INSTRUMENTHEADER *penv = Headers[p->instr];
- if (penv)
- {
- UINT n = penv->Keyboard[p->note-1];
- if (n < MAX_SAMPLES) pbIns[n] = TRUE;
- }
- } else
- {
- for (UINT k=1; k<=m_nInstruments; k++)
- {
- INSTRUMENTHEADER *penv = Headers[k];
- if (penv)
- {
- UINT n = penv->Keyboard[p->note-1];
- if (n < MAX_SAMPLES) pbIns[n] = TRUE;
- }
- }
- }
- }
- }
- }
- }
- for (UINT ichk=1; ichk<=m_nSamples; ichk++)
- {
- if ((!pbIns[ichk]) && (Ins[ichk].pSample)) nExt++;
- }
- }
- return nExt;
-}
-
-
-BOOL CSoundFile::RemoveSelectedSamples(BOOL *pbIns)
-//-------------------------------------------------
-{
- if (!pbIns) return FALSE;
- for (UINT j=1; j<MAX_SAMPLES; j++)
- {
- if ((!pbIns[j]) && (Ins[j].pSample))
- {
- DestroySample(j);
- if ((j == m_nSamples) && (j > 1)) m_nSamples--;
- }
- }
- return TRUE;
-}
-
-
-BOOL CSoundFile::DestroySample(UINT nSample)
-//------------------------------------------
-{
- if ((!nSample) || (nSample >= MAX_SAMPLES)) return FALSE;
- if (!Ins[nSample].pSample) return TRUE;
- MODINSTRUMENT *pins = &Ins[nSample];
- signed char *pSample = pins->pSample;
- pins->pSample = NULL;
- pins->nLength = 0;
- pins->uFlags &= ~(CHN_16BIT);
- for (UINT i=0; i<MAX_CHANNELS; i++)
- {
- if (Chn[i].pSample == pSample)
- {
- Chn[i].nPos = Chn[i].nLength = 0;
- Chn[i].pSample = Chn[i].pCurrentSample = NULL;
- }
- }
- FreeSample(pSample);
- return TRUE;
-}
-
-#endif // FASTSOUNDLIB
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifndef __SNDFILE_H
-#define __SNDFILE_H
-
-#ifndef LPCBYTE
-typedef const BYTE * LPCBYTE;
-#endif
-
-#define MOD_AMIGAC2 0x1AB
-#define MAX_SAMPLE_LENGTH 16000000
-#define MAX_SAMPLE_RATE 50000
-#define MAX_ORDERS 256
-#define MAX_PATTERNS 240
-#define MAX_SAMPLES 240
-#define MAX_INSTRUMENTS MAX_SAMPLES
-#ifdef FASTSOUNDLIB
-#define MAX_CHANNELS 80
-#else
-#define MAX_CHANNELS 128
-#endif
-#define MAX_BASECHANNELS 64
-#define MAX_ENVPOINTS 32
-#define MIN_PERIOD 0x0020
-#define MAX_PERIOD 0xFFFF
-#define MAX_PATTERNNAME 32
-#define MAX_CHANNELNAME 20
-#define MAX_INFONAME 80
-#define MAX_EQ_BANDS 6
-#define MAX_MIXPLUGINS 8
-
-
-#define MOD_TYPE_NONE 0x00
-#define MOD_TYPE_MOD 0x01
-#define MOD_TYPE_S3M 0x02
-#define MOD_TYPE_XM 0x04
-#define MOD_TYPE_MED 0x08
-#define MOD_TYPE_MTM 0x10
-#define MOD_TYPE_IT 0x20
-#define MOD_TYPE_669 0x40
-#define MOD_TYPE_ULT 0x80
-#define MOD_TYPE_STM 0x100
-#define MOD_TYPE_FAR 0x200
-#define MOD_TYPE_WAV 0x400
-#define MOD_TYPE_AMF 0x800
-#define MOD_TYPE_AMS 0x1000
-#define MOD_TYPE_DSM 0x2000
-#define MOD_TYPE_MDL 0x4000
-#define MOD_TYPE_OKT 0x8000
-#define MOD_TYPE_MID 0x10000
-#define MOD_TYPE_DMF 0x20000
-#define MOD_TYPE_PTM 0x40000
-#define MOD_TYPE_DBM 0x80000
-#define MOD_TYPE_MT2 0x100000
-#define MOD_TYPE_AMF0 0x200000
-#define MOD_TYPE_PSM 0x400000
-#define MOD_TYPE_J2B 0x800000
-#define MOD_TYPE_UMX 0x80000000 /* Fake type */
-#define MAX_MODTYPE 23
-
-
-
-/* Channel flags: */
-/* Bits 0-7: Sample Flags */
-#define CHN_16BIT 0x01
-#define CHN_LOOP 0x02
-#define CHN_PINGPONGLOOP 0x04
-#define CHN_SUSTAINLOOP 0x08
-#define CHN_PINGPONGSUSTAIN 0x10
-#define CHN_PANNING 0x20
-#define CHN_STEREO 0x40
-#define CHN_PINGPONGFLAG 0x80
-/* Bits 8-31: Channel Flags */
-#define CHN_MUTE 0x100
-#define CHN_KEYOFF 0x200
-#define CHN_NOTEFADE 0x400
-#define CHN_SURROUND 0x800
-#define CHN_NOIDO 0x1000
-#define CHN_HQSRC 0x2000
-#define CHN_FILTER 0x4000
-#define CHN_VOLUMERAMP 0x8000
-#define CHN_VIBRATO 0x10000
-#define CHN_TREMOLO 0x20000
-#define CHN_PANBRELLO 0x40000
-#define CHN_PORTAMENTO 0x80000
-#define CHN_GLISSANDO 0x100000
-#define CHN_VOLENV 0x200000
-#define CHN_PANENV 0x400000
-#define CHN_PITCHENV 0x800000
-#define CHN_FASTVOLRAMP 0x1000000
-#define CHN_EXTRALOUD 0x2000000
-#define CHN_REVERB 0x4000000
-#define CHN_NOREVERB 0x8000000
-
-
-#define ENV_VOLUME 0x0001
-#define ENV_VOLSUSTAIN 0x0002
-#define ENV_VOLLOOP 0x0004
-#define ENV_PANNING 0x0008
-#define ENV_PANSUSTAIN 0x0010
-#define ENV_PANLOOP 0x0020
-#define ENV_PITCH 0x0040
-#define ENV_PITCHSUSTAIN 0x0080
-#define ENV_PITCHLOOP 0x0100
-#define ENV_SETPANNING 0x0200
-#define ENV_FILTER 0x0400
-#define ENV_VOLCARRY 0x0800
-#define ENV_PANCARRY 0x1000
-#define ENV_PITCHCARRY 0x2000
-
-#define CMD_NONE 0
-#define CMD_ARPEGGIO 1
-#define CMD_PORTAMENTOUP 2
-#define CMD_PORTAMENTODOWN 3
-#define CMD_TONEPORTAMENTO 4
-#define CMD_VIBRATO 5
-#define CMD_TONEPORTAVOL 6
-#define CMD_VIBRATOVOL 7
-#define CMD_TREMOLO 8
-#define CMD_PANNING8 9
-#define CMD_OFFSET 10
-#define CMD_VOLUMESLIDE 11
-#define CMD_POSITIONJUMP 12
-#define CMD_VOLUME 13
-#define CMD_PATTERNBREAK 14
-#define CMD_RETRIG 15
-#define CMD_SPEED 16
-#define CMD_TEMPO 17
-#define CMD_TREMOR 18
-#define CMD_MODCMDEX 19
-#define CMD_S3MCMDEX 20
-#define CMD_CHANNELVOLUME 21
-#define CMD_CHANNELVOLSLIDE 22
-#define CMD_GLOBALVOLUME 23
-#define CMD_GLOBALVOLSLIDE 24
-#define CMD_KEYOFF 25
-#define CMD_FINEVIBRATO 26
-#define CMD_PANBRELLO 27
-#define CMD_XFINEPORTAUPDOWN 28
-#define CMD_PANNINGSLIDE 29
-#define CMD_SETENVPOSITION 30
-#define CMD_MIDI 31
-
-
-/* Volume Column commands */
-#define VOLCMD_VOLUME 1
-#define VOLCMD_PANNING 2
-#define VOLCMD_VOLSLIDEUP 3
-#define VOLCMD_VOLSLIDEDOWN 4
-#define VOLCMD_FINEVOLUP 5
-#define VOLCMD_FINEVOLDOWN 6
-#define VOLCMD_VIBRATOSPEED 7
-#define VOLCMD_VIBRATO 8
-#define VOLCMD_PANSLIDELEFT 9
-#define VOLCMD_PANSLIDERIGHT 10
-#define VOLCMD_TONEPORTAMENTO 11
-#define VOLCMD_PORTAUP 12
-#define VOLCMD_PORTADOWN 13
-
-#define RSF_16BIT 0x04
-#define RSF_STEREO 0x08
-
-#define RS_PCM8S 0 /* 8-bit signed */
-#define RS_PCM8U 1 /* 8-bit unsigned */
-#define RS_PCM8D 2 /* 8-bit delta values */
-#define RS_ADPCM4 3 /* 4-bit ADPCM-packed */
-#define RS_PCM16D 4 /* 16-bit delta values */
-#define RS_PCM16S 5 /* 16-bit signed */
-#define RS_PCM16U 6 /* 16-bit unsigned */
-#define RS_PCM16M 7 /* 16-bit motorola order */
-#define RS_STPCM8S (RS_PCM8S|RSF_STEREO) /* stereo 8-bit signed */
-#define RS_STPCM8U (RS_PCM8U|RSF_STEREO) /* stereo 8-bit unsigned */
-#define RS_STPCM8D (RS_PCM8D|RSF_STEREO) /* stereo 8-bit delta values */
-#define RS_STPCM16S (RS_PCM16S|RSF_STEREO) /* stereo 16-bit signed */
-#define RS_STPCM16U (RS_PCM16U|RSF_STEREO) /* stereo 16-bit unsigned */
-#define RS_STPCM16D (RS_PCM16D|RSF_STEREO) /* stereo 16-bit delta values */
-#define RS_STPCM16M (RS_PCM16M|RSF_STEREO) /* stereo 16-bit signed big endian */
-/* IT 2.14 compressed samples */
-#define RS_IT2148 0x10
-#define RS_IT21416 0x14
-#define RS_IT2158 0x12
-#define RS_IT21516 0x16
-/* AMS Packed Samples */
-#define RS_AMS8 0x11
-#define RS_AMS16 0x15
-/* DMF Huffman compression */
-#define RS_DMF8 0x13
-#define RS_DMF16 0x17
-/* MDL Huffman compression */
-#define RS_MDL8 0x20
-#define RS_MDL16 0x24
-#define RS_PTM8DTO16 0x25
-/* Stereo Interleaved Samples */
-#define RS_STIPCM8S (RS_PCM8S|0x40|RSF_STEREO) /* stereo 8-bit signed */
-#define RS_STIPCM8U (RS_PCM8U|0x40|RSF_STEREO) /* stereo 8-bit unsigned */
-#define RS_STIPCM16S (RS_PCM16S|0x40|RSF_STEREO) /* stereo 16-bit signed */
-#define RS_STIPCM16U (RS_PCM16U|0x40|RSF_STEREO) /* stereo 16-bit unsigned */
-#define RS_STIPCM16M (RS_PCM16M|0x40|RSF_STEREO) /* stereo 16-bit signed big endian */
-/* 24-bit signed */
-#define RS_PCM24S (RS_PCM16S|0x80) /* mono 24-bit signed */
-#define RS_STIPCM24S (RS_PCM16S|0x80|RSF_STEREO) /* stereo 24-bit signed */
-#define RS_PCM32S (RS_PCM16S|0xC0) /* mono 24-bit signed */
-#define RS_STIPCM32S (RS_PCM16S|0xC0|RSF_STEREO) /* stereo 24-bit signed */
-
-/* NNA types */
-#define NNA_NOTECUT 0
-#define NNA_CONTINUE 1
-#define NNA_NOTEOFF 2
-#define NNA_NOTEFADE 3
-
-/* DCT types */
-#define DCT_NONE 0
-#define DCT_NOTE 1
-#define DCT_SAMPLE 2
-#define DCT_INSTRUMENT 3
-
-/* DNA types */
-#define DNA_NOTECUT 0
-#define DNA_NOTEOFF 1
-#define DNA_NOTEFADE 2
-
-/* Mixer Hardware-Dependent features */
-#define SYSMIX_ENABLEMMX 0x01
-#define SYSMIX_WINDOWSNT 0x02
-#define SYSMIX_SLOWCPU 0x04
-#define SYSMIX_FASTCPU 0x08
-
-/* Module flags */
-#define SONG_EMBEDMIDICFG 0x0001
-#define SONG_FASTVOLSLIDES 0x0002
-#define SONG_ITOLDEFFECTS 0x0004
-#define SONG_ITCOMPATMODE 0x0008
-#define SONG_LINEARSLIDES 0x0010
-#define SONG_PATTERNLOOP 0x0020
-#define SONG_STEP 0x0040
-#define SONG_PAUSED 0x0080
-#define SONG_FADINGSONG 0x0100
-#define SONG_ENDREACHED 0x0200
-#define SONG_GLOBALFADE 0x0400
-#define SONG_CPUVERYHIGH 0x0800
-#define SONG_FIRSTTICK 0x1000
-#define SONG_MPTFILTERMODE 0x2000
-#define SONG_SURROUNDPAN 0x4000
-#define SONG_EXFILTERRANGE 0x8000
-#define SONG_AMIGALIMITS 0x10000
-
-/* Global Options (Renderer) */
-#define SNDMIX_REVERSESTEREO 0x0001
-#define SNDMIX_NOISEREDUCTION 0x0002
-#define SNDMIX_AGC 0x0004
-#define SNDMIX_NORESAMPLING 0x0008
-#define SNDMIX_HQRESAMPLER 0x0010
-#define SNDMIX_MEGABASS 0x0020
-#define SNDMIX_SURROUND 0x0040
-#define SNDMIX_REVERB 0x0080
-#define SNDMIX_EQ 0x0100
-#define SNDMIX_SOFTPANNING 0x0200
-#define SNDMIX_ULTRAHQSRCMODE 0x0400
-/* Misc Flags (can safely be turned on or off) */
-#define SNDMIX_DIRECTTODISK 0x10000
-#define SNDMIX_ENABLEMMX 0x20000
-#define SNDMIX_NOBACKWARDJUMPS 0x40000
-#define SNDMIX_MAXDEFAULTPAN 0x80000 /* Used by the MOD loader */
-
-
-/* Reverb Types (GM2 Presets) */
-enum {
- REVERBTYPE_SMALLROOM,
- REVERBTYPE_MEDIUMROOM,
- REVERBTYPE_LARGEROOM,
- REVERBTYPE_SMALLHALL,
- REVERBTYPE_MEDIUMHALL,
- REVERBTYPE_LARGEHALL,
- NUM_REVERBTYPES
-};
-
-
-enum {
- SRCMODE_NEAREST,
- SRCMODE_LINEAR,
- SRCMODE_SPLINE,
- SRCMODE_POLYPHASE,
- NUM_SRC_MODES
-};
-
-
-/* Sample Struct */
-typedef struct _MODINSTRUMENT
-{
- UINT nLength,nLoopStart,nLoopEnd;
- UINT nSustainStart, nSustainEnd;
- signed char *pSample;
- UINT nC4Speed;
- WORD nPan;
- WORD nVolume;
- WORD nGlobalVol;
- WORD uFlags;
- signed char RelativeTone;
- signed char nFineTune;
- BYTE nVibType;
- BYTE nVibSweep;
- BYTE nVibDepth;
- BYTE nVibRate;
- CHAR name[22];
-} MODINSTRUMENT;
-
-
-/* Instrument Struct */
-typedef struct _INSTRUMENTHEADER
-{
- UINT nFadeOut;
- DWORD dwFlags;
- WORD nGlobalVol;
- WORD nPan;
- WORD VolPoints[MAX_ENVPOINTS];
- WORD PanPoints[MAX_ENVPOINTS];
- WORD PitchPoints[MAX_ENVPOINTS];
- BYTE VolEnv[MAX_ENVPOINTS];
- BYTE PanEnv[MAX_ENVPOINTS];
- BYTE PitchEnv[MAX_ENVPOINTS];
- BYTE Keyboard[128];
- BYTE NoteMap[128];
-
- BYTE nVolEnv;
- BYTE nPanEnv;
- BYTE nPitchEnv;
- BYTE nVolLoopStart;
- BYTE nVolLoopEnd;
- BYTE nVolSustainBegin;
- BYTE nVolSustainEnd;
- BYTE nPanLoopStart;
- BYTE nPanLoopEnd;
- BYTE nPanSustainBegin;
- BYTE nPanSustainEnd;
- BYTE nPitchLoopStart;
- BYTE nPitchLoopEnd;
- BYTE nPitchSustainBegin;
- BYTE nPitchSustainEnd;
- BYTE nNNA;
- BYTE nDCT;
- BYTE nDNA;
- BYTE nPanSwing;
- BYTE nVolSwing;
- BYTE nIFC;
- BYTE nIFR;
- WORD wMidiBank;
- BYTE nMidiProgram;
- BYTE nMidiChannel;
- BYTE nMidiDrumKey;
- signed char nPPS;
- unsigned char nPPC;
- CHAR name[32];
- CHAR filename[12];
-} INSTRUMENTHEADER;
-
-
-/* Channel Struct */
-typedef struct _MODCHANNEL
-{
- /* First 32-bytes: Most used mixing information: don't change it */
- signed char * pCurrentSample;
- DWORD nPos;
- DWORD nPosLo; /* actually 16-bit */
- LONG nInc; /* 16.16 */
- LONG nRightVol;
- LONG nLeftVol;
- LONG nRightRamp;
- LONG nLeftRamp;
- /* 2nd cache line */
- DWORD nLength;
- DWORD dwFlags;
- DWORD nLoopStart;
- DWORD nLoopEnd;
- LONG nRampRightVol;
- LONG nRampLeftVol;
- LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4;
- LONG nFilter_A0, nFilter_B0, nFilter_B1;
- LONG nROfs, nLOfs;
- LONG nRampLength;
- /* Information not used in the mixer */
- signed char * pSample;
- LONG nNewRightVol, nNewLeftVol;
- LONG nRealVolume, nRealPan;
- LONG nVolume, nPan, nFadeOutVol;
- LONG nPeriod, nC4Speed, nPortamentoDest;
- INSTRUMENTHEADER *pHeader;
- MODINSTRUMENT *pInstrument;
- DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition;
- DWORD nMasterChn, nVUMeter;
- LONG nGlobalVol, nInsVol;
- LONG nFineTune, nTranspose;
- LONG nPortamentoSlide, nAutoVibDepth;
- UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos;
- /* 16-bit members */
- signed short nVolSwing, nPanSwing;
- /* 8-bit members */
- BYTE nNote, nNNA;
- BYTE nNewNote, nNewIns, nCommand, nArpeggio;
- BYTE nOldVolumeSlide, nOldFineVolUpDown;
- BYTE nOldPortaUpDown, nOldFinePortaUpDown;
- BYTE nOldPanSlide, nOldChnVolSlide;
- BYTE nVibratoType, nVibratoSpeed, nVibratoDepth;
- BYTE nTremoloType, nTremoloSpeed, nTremoloDepth;
- BYTE nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth;
- BYTE nOldCmdEx, nOldVolParam, nOldTempo;
- BYTE nOldOffset, nOldHiOffset;
- BYTE nCutOff, nResonance;
- BYTE nRetrigCount, nRetrigParam;
- BYTE nTremorCount, nTremorParam;
- BYTE nPatternLoop, nPatternLoopCount;
- BYTE nRowNote, nRowInstr;
- BYTE nRowVolCmd, nRowVolume;
- BYTE nRowCommand, nRowParam;
- BYTE nLeftVU, nRightVU;
- BYTE nActiveMacro, nPadding;
-} MODCHANNEL;
-
-
-typedef struct _MODCHANNELSETTINGS
-{
- UINT nPan;
- UINT nVolume;
- DWORD dwFlags;
- UINT nMixPlugin;
- char szName[MAX_CHANNELNAME]; /* changed from CHAR */
-} MODCHANNELSETTINGS;
-
-
-typedef struct _MODCOMMAND
-{
- BYTE note;
- BYTE instr;
- BYTE volcmd;
- BYTE command;
- BYTE vol;
- BYTE param;
-} MODCOMMAND, *LPMODCOMMAND;
-
-/*////////////////////////////////////////////////////////////////// */
-/* Mix Plugins */
-#define MIXPLUG_MIXREADY 0x01 /* Set when cleared */
-
-class IMixPlugin
-{
-public:
- virtual ~IMixPlugin() {};
- virtual int AddRef() = 0;
- virtual int Release() = 0;
- virtual void SaveAllParameters() = 0;
- virtual void RestoreAllParameters() = 0;
- virtual void Process(float *pOutL, float *pOutR, unsigned long nSamples) = 0;
- virtual void Init(unsigned long nFreq, int bReset) = 0;
- virtual void MidiSend(DWORD dwMidiCode) = 0;
- virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0;
-};
-
-
-#define MIXPLUG_INPUTF_MASTEREFFECT 0x01 /* Apply to master mix */
-#define MIXPLUG_INPUTF_BYPASS 0x02 /* Bypass effect */
-#define MIXPLUG_INPUTF_WETMIX 0x04 /* Wet Mix (dry added) */
-
-typedef struct _SNDMIXPLUGINSTATE
-{
- DWORD dwFlags; /* MIXPLUG_XXXX */
- LONG nVolDecayL, nVolDecayR; /* Buffer click removal */
- int *pMixBuffer; /* Stereo effect send buffer */
- float *pOutBufferL; /* Temp storage for int -> float conversion */
- float *pOutBufferR;
-} SNDMIXPLUGINSTATE, *PSNDMIXPLUGINSTATE;
-
-typedef struct _SNDMIXPLUGININFO
-{
- DWORD dwPluginId1;
- DWORD dwPluginId2;
- DWORD dwInputRouting; /* MIXPLUG_INPUTF_XXXX */
- DWORD dwOutputRouting; /* 0=mix 0x80+=fx */
- DWORD dwReserved[4]; /* Reserved for routing info */
- CHAR szName[32];
- CHAR szLibraryName[64]; /* original DLL name */
-} SNDMIXPLUGININFO, *PSNDMIXPLUGININFO; /* Size should be 128 */
-
-typedef struct _SNDMIXPLUGIN
-{
- IMixPlugin *pMixPlugin;
- PSNDMIXPLUGINSTATE pMixState;
- ULONG nPluginDataSize;
- PVOID pPluginData;
- SNDMIXPLUGININFO Info;
-} SNDMIXPLUGIN, *PSNDMIXPLUGIN;
-
-typedef BOOL (*PMIXPLUGINCREATEPROC)(PSNDMIXPLUGIN);
-
-/*////////////////////////////////////////////////////////////////// */
-
-enum {
- MIDIOUT_START=0,
- MIDIOUT_STOP,
- MIDIOUT_TICK,
- MIDIOUT_NOTEON,
- MIDIOUT_NOTEOFF,
- MIDIOUT_VOLUME,
- MIDIOUT_PAN,
- MIDIOUT_BANKSEL,
- MIDIOUT_PROGRAM
-};
-
-
-typedef struct MODMIDICFG
-{
- char szMidiGlb[9*32]; /* changed from CHAR */
- char szMidiSFXExt[16*32]; /* changed from CHAR */
- char szMidiZXXExt[128*32]; /* changed from CHAR */
-} MODMIDICFG, *LPMODMIDICFG;
-
-
-typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); /* buffer, samples, channels */
-
-
-
-/*============== */
-class CSoundFile
-/*============== */
-{
-public: /* Static Members */
- static UINT m_nXBassDepth, m_nXBassRange;
- static UINT m_nReverbDepth, m_nReverbDelay, gnReverbType;
- static UINT m_nProLogicDepth, m_nProLogicDelay;
- static UINT m_nStereoSeparation;
- static UINT m_nMaxMixChannels;
- static LONG m_nStreamVolume;
- static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels;
- static UINT gnAGC, gnVolumeRampSamples, gnVUMeter, gnCPUUsage;
- static LPSNDMIXHOOKPROC gpSndMixHook;
- static PMIXPLUGINCREATEPROC gpMixPluginCreateProc;
-
-public: /* for Editing */
- MODCHANNEL Chn[MAX_CHANNELS]; /* Channels */
- UINT ChnMix[MAX_CHANNELS]; /* Channels to be mixed */
- MODINSTRUMENT Ins[MAX_SAMPLES]; /* Instruments */
- INSTRUMENTHEADER *Headers[MAX_INSTRUMENTS]; /* Instrument Headers */
- MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; /* Channels settings */
- MODCOMMAND *Patterns[MAX_PATTERNS]; /* Patterns */
- WORD PatternSize[MAX_PATTERNS]; /* Patterns Lengths */
- BYTE Order[MAX_ORDERS]; /* Pattern Orders */
- MODMIDICFG m_MidiCfg; /* Midi macro config table */
- SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; /* Mix plugins */
- UINT m_nDefaultSpeed, m_nDefaultTempo, m_nDefaultGlobalVolume;
- DWORD m_dwSongFlags; /* Song flags SONG_XXXX */
- UINT m_nChannels, m_nMixChannels, m_nMixStat, m_nBufferCount;
- UINT m_nType, m_nSamples, m_nInstruments;
- UINT m_nTickCount, m_nTotalCount, m_nPatternDelay, m_nFrameDelay;
- UINT m_nMusicSpeed, m_nMusicTempo;
- UINT m_nNextRow, m_nRow;
- UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nRestartPos;
- UINT m_nMasterVolume, m_nGlobalVolume, m_nSongPreAmp;
- UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide;
- LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount, m_nInitialRepeatCount;
- DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples;
- UINT m_nMaxOrderPosition;
- UINT m_nPatternNames;
- LPSTR m_lpszSongComments, m_lpszPatternNames;
- char m_szNames[MAX_INSTRUMENTS][32]; /* changed from CHAR */
- CHAR CompressionTable[16];
-
-public:
- CSoundFile();
- ~CSoundFile();
-
-public:
- BOOL Create(LPCBYTE lpStream, DWORD dwMemLength=0);
- BOOL Destroy();
- UINT GetType() const { return m_nType; }
- UINT GetNumChannels() const;
- UINT GetLogicalChannels() const { return m_nChannels; }
- BOOL SetMasterVolume(UINT vol, BOOL bAdjustAGC=FALSE);
- UINT GetMasterVolume() const { return m_nMasterVolume; }
- UINT GetNumPatterns() const;
- UINT GetNumInstruments() const;
- UINT GetNumSamples() const { return m_nSamples; }
- UINT GetCurrentPos() const;
- UINT GetCurrentPattern() const { return m_nPattern; }
- UINT GetCurrentOrder() const { return m_nCurrentPattern; }
- UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32);
- UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32);
- UINT GetMaxPosition() const;
- void SetCurrentPos(UINT nPos);
- void SetCurrentOrder(UINT nOrder);
- void GetTitle(LPSTR s) const { lstrcpyn(s,m_szNames[0],32); }
- LPCSTR GetTitle() const { return m_szNames[0]; }
- UINT GetSampleName(UINT nSample,LPSTR s=NULL) const;
- UINT GetInstrumentName(UINT nInstr,LPSTR s=NULL) const;
- UINT GetMusicSpeed() const { return m_nMusicSpeed; }
- UINT GetMusicTempo() const { return m_nMusicTempo; }
- DWORD GetLength(BOOL bAdjust, BOOL bTotal=FALSE);
- DWORD GetSongTime() { return GetLength(FALSE, TRUE); }
- void SetRepeatCount(int n) { m_nRepeatCount = n; m_nInitialRepeatCount = n; }
- int GetRepeatCount() const { return m_nRepeatCount; }
- BOOL IsPaused() const { return (m_dwSongFlags & SONG_PAUSED) ? TRUE : FALSE; }
- void LoopPattern(int nPat, int nRow=0);
- void CheckCPUUsage(UINT nCPU);
- BOOL SetPatternName(UINT nPat, LPCSTR lpszName);
- BOOL GetPatternName(UINT nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const;
- /* Module Loaders */
- BOOL ReadXM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadS3M(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadMod(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadMed(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadMTM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadSTM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadIT(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL Read669(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadUlt(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadWav(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadDSM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadFAR(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadAMS(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadMDL(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadOKT(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadDMF(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadPTM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadDBM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength);
- BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength);
- /* Save Functions */
-#ifndef MODPLUG_NO_FILESAVE
- UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0);
- BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0);
- BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0);
- BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0);
- BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0);
-#endif /* MODPLUG_NO_FILESAVE */
- /* MOD Convert function */
- UINT GetBestSaveFormat() const;
- UINT GetSaveFormats() const;
- void ConvertModCommand(MODCOMMAND *) const;
- void S3MConvert(MODCOMMAND *m, BOOL bIT) const;
- void S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const;
- WORD ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const;
-
-public:
- /* Real-time sound functions */
- VOID ResetChannels();
-
- UINT Read(LPVOID lpBuffer, UINT cbBuffer);
- UINT CreateStereoMix(int count);
- BOOL FadeSong(UINT msec);
- BOOL GlobalFadeSong(UINT msec);
- UINT GetTotalTickCount() const { return m_nTotalCount; }
- VOID ResetTotalTickCount() { m_nTotalCount = 0; }
-
-public:
- /* Mixer Config */
- static BOOL InitPlayer(BOOL bReset=FALSE);
- static BOOL SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX=FALSE);
- static BOOL SetResamplingMode(UINT nMode); /* SRCMODE_XXXX */
- static BOOL IsStereo() { return (gnChannels > 1) ? TRUE : FALSE; }
- static DWORD GetSampleRate() { return gdwMixingFreq; }
- static DWORD GetBitsPerSample() { return gnBitsPerSample; }
- static DWORD InitSysInfo();
- static DWORD GetSysInfo() { return gdwSysInfo; }
- /* AGC */
- static BOOL GetAGC() { return (gdwSoundSetup & SNDMIX_AGC) ? TRUE : FALSE; }
- static void SetAGC(BOOL b);
- static void ResetAGC();
- static void ProcessAGC(int count);
-
- /*GCCFIX -- added these functions back in! */
- static BOOL SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ);
- /* DSP Effects */
- static void InitializeDSP(BOOL bReset);
- static void ProcessStereoDSP(int count);
- static void ProcessMonoDSP(int count);
- /* [Reverb level 0(quiet)-100(loud)], [delay in ms, usually 40-200ms] */
- static BOOL SetReverbParameters(UINT nDepth, UINT nDelay);
- /* [XBass level 0(quiet)-100(loud)], [cutoff in Hz 10-100] */
- static BOOL SetXBassParameters(UINT nDepth, UINT nRange);
- /* [Surround level 0(quiet)-100(heavy)] [delay in ms, usually 5-40ms] */
- static BOOL SetSurroundParameters(UINT nDepth, UINT nDelay);
-public:
- BOOL ReadNote();
- BOOL ProcessRow();
- BOOL ProcessEffects();
- UINT GetNNAChannel(UINT nChn) const;
- void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut);
- void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE);
- void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE);
- /* Channel Effects */
- void PortamentoUp(MODCHANNEL *pChn, UINT param);
- void PortamentoDown(MODCHANNEL *pChn, UINT param);
- void FinePortamentoUp(MODCHANNEL *pChn, UINT param);
- void FinePortamentoDown(MODCHANNEL *pChn, UINT param);
- void ExtraFinePortamentoUp(MODCHANNEL *pChn, UINT param);
- void ExtraFinePortamentoDown(MODCHANNEL *pChn, UINT param);
- void TonePortamento(MODCHANNEL *pChn, UINT param);
- void Vibrato(MODCHANNEL *pChn, UINT param);
- void FineVibrato(MODCHANNEL *pChn, UINT param);
- void VolumeSlide(MODCHANNEL *pChn, UINT param);
- void PanningSlide(MODCHANNEL *pChn, UINT param);
- void ChannelVolSlide(MODCHANNEL *pChn, UINT param);
- void FineVolumeUp(MODCHANNEL *pChn, UINT param);
- void FineVolumeDown(MODCHANNEL *pChn, UINT param);
- void Tremolo(MODCHANNEL *pChn, UINT param);
- void Panbrello(MODCHANNEL *pChn, UINT param);
- void RetrigNote(UINT nChn, UINT param);
- void NoteCut(UINT nChn, UINT nTick);
- void KeyOff(UINT nChn);
- int PatternLoop(MODCHANNEL *, UINT param);
- void ExtendedMODCommands(UINT nChn, UINT param);
- void ExtendedS3MCommands(UINT nChn, UINT param);
- void ExtendedChannelEffect(MODCHANNEL *, UINT param);
- void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0);
- void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const;
- /* Low-Level effect processing */
- void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide);
- /* Global Effects */
- void SetTempo(UINT param);
- void SetSpeed(UINT param);
- void GlobalVolSlide(UINT param);
- DWORD IsSongFinished(UINT nOrder, UINT nRow) const;
- BOOL IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const;
- /* Read/Write sample functions */
- signed char GetDeltaValue(signed char prev, UINT n) const { return (signed char)(prev + CompressionTable[n & 0x0F]); }
- UINT PackSample(int &sample, int next);
- BOOL CanPackSample(signed char * pSample, UINT nLen, UINT nPacking, BYTE *result=NULL);
- UINT ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR pMemFile, DWORD dwMemLength);
- BOOL DestroySample(UINT nSample);
- BOOL DestroyInstrument(UINT nInstr);
- BOOL IsSampleUsed(UINT nSample);
- BOOL IsInstrumentUsed(UINT nInstr);
- BOOL RemoveInstrumentSamples(UINT nInstr);
- UINT DetectUnusedSamples(BOOL *);
- BOOL RemoveSelectedSamples(BOOL *);
- void AdjustSampleLoop(MODINSTRUMENT *pIns);
- /* I/O from another sound file */
- BOOL ReadInstrumentFromSong(UINT nInstr, CSoundFile *, UINT nSrcInstrument);
- BOOL ReadSampleFromSong(UINT nSample, CSoundFile *, UINT nSrcSample);
- /* Period/Note functions */
- UINT GetNoteFromPeriod(UINT period) const;
- UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const;
- UINT GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac=0) const;
- /* Misc functions */
- MODINSTRUMENT *GetSample(UINT n) { return Ins+n; }
- void ResetMidiCfg();
- UINT MapMidiInstrument(DWORD dwProgram, UINT nChannel, UINT nNote);
- BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers);
- UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE);
- UINT LoadMixPlugins(const void *pData, UINT nLen);
-#ifndef NO_FILTER
- DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; /* [0-255] => [1-10KHz] */
-#endif
-
- /* Static helper functions */
-public:
- static DWORD TransposeToFrequency(int transp, int ftune=0);
- static int FrequencyToTranspose(DWORD freq);
- static void FrequencyToTranspose(MODINSTRUMENT *psmp);
-
- /* System-Dependant functions */
-public:
- static MODCOMMAND *AllocatePattern(UINT rows, UINT nchns);
- static signed char* AllocateSample(UINT nbytes);
- static void FreePattern(LPVOID pat);
- static void FreeSample(LPVOID p);
- static UINT Normalize24BitBuffer(LPBYTE pbuffer, UINT cbsizebytes, DWORD lmax24, DWORD dwByteInc);
-};
-
-
-/* inline DWORD BigEndian(DWORD x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24); } */
-/* inline WORD BigEndianW(WORD x) { return (WORD)(((x >> 8) & 0xFF) | ((x << 8) & 0xFF00)); } */
-
-
-/*//////////////////////////////////////////////////////// */
-/* WAVE format information */
-
-#pragma pack(1)
-
-/* Standard IFF chunks IDs */
-#define IFFID_FORM 0x4d524f46
-#define IFFID_RIFF 0x46464952
-#define IFFID_WAVE 0x45564157
-#define IFFID_LIST 0x5453494C
-#define IFFID_INFO 0x4F464E49
-
-/* IFF Info fields */
-#define IFFID_ICOP 0x504F4349
-#define IFFID_IART 0x54524149
-#define IFFID_IPRD 0x44525049
-#define IFFID_INAM 0x4D414E49
-#define IFFID_ICMT 0x544D4349
-#define IFFID_IENG 0x474E4549
-#define IFFID_ISFT 0x54465349
-#define IFFID_ISBJ 0x4A425349
-#define IFFID_IGNR 0x524E4749
-#define IFFID_ICRD 0x44524349
-
-/* Wave IFF chunks IDs */
-#define IFFID_wave 0x65766177
-#define IFFID_fmt 0x20746D66
-#define IFFID_wsmp 0x706D7377
-#define IFFID_pcm 0x206d6370
-#define IFFID_data 0x61746164
-#define IFFID_smpl 0x6C706D73
-#define IFFID_xtra 0x61727478
-
-typedef struct WAVEFILEHEADER
-{
- DWORD id_RIFF; /* "RIFF" */
- DWORD filesize; /* file length-8 */
- DWORD id_WAVE;
-} WAVEFILEHEADER;
-
-
-typedef struct WAVEFORMATHEADER
-{
- DWORD id_fmt; /* "fmt " */
- DWORD hdrlen; /* 16 */
- WORD format; /* 1 */
- WORD channels; /* 1:mono, 2:stereo */
- DWORD freqHz; /* sampling freq */
- DWORD bytessec; /* bytes/sec=freqHz*samplesize */
- WORD samplesize; /* sizeof(sample) */
- WORD bitspersample; /* bits per sample (8/16) */
-} WAVEFORMATHEADER;
-
-
-typedef struct WAVEDATAHEADER
-{
- DWORD id_data; /* "data" */
- DWORD length; /* length of data */
-} WAVEDATAHEADER;
-
-
-typedef struct WAVESMPLHEADER
-{
- /* SMPL */
- DWORD smpl_id; /* "smpl" -> 0x6C706D73 */
- DWORD smpl_len; /* length of smpl: 3Ch (54h with sustain loop) */
- DWORD dwManufacturer;
- DWORD dwProduct;
- DWORD dwSamplePeriod; /* 1000000000/freqHz */
- DWORD dwBaseNote; /* 3Ch = C-4 -> 60 + RelativeTone */
- DWORD dwPitchFraction;
- DWORD dwSMPTEFormat;
- DWORD dwSMPTEOffset;
- DWORD dwSampleLoops; /* number of loops */
- DWORD cbSamplerData;
-} WAVESMPLHEADER;
-
-
-typedef struct SAMPLELOOPSTRUCT
-{
- DWORD dwIdentifier;
- DWORD dwLoopType; /* 0=normal, 1=bidi */
- DWORD dwLoopStart;
- DWORD dwLoopEnd; /* Byte offset ? */
- DWORD dwFraction;
- DWORD dwPlayCount; /* Loop Count, 0=infinite */
-} SAMPLELOOPSTRUCT;
-
-
-typedef struct WAVESAMPLERINFO
-{
- WAVESMPLHEADER wsiHdr;
- SAMPLELOOPSTRUCT wsiLoops[2];
-} WAVESAMPLERINFO;
-
-
-typedef struct WAVELISTHEADER
-{
- DWORD list_id; /* "LIST" -> 0x5453494C */
- DWORD list_len;
- DWORD info; /* "INFO" */
-} WAVELISTHEADER;
-
-
-typedef struct WAVEEXTRAHEADER
-{
- DWORD xtra_id; /* "xtra" -> 0x61727478 */
- DWORD xtra_len;
- DWORD dwFlags;
- WORD wPan;
- WORD wVolume;
- WORD wGlobalVol;
- WORD wReserved;
- BYTE nVibType;
- BYTE nVibSweep;
- BYTE nVibDepth;
- BYTE nVibRate;
-} WAVEEXTRAHEADER;
-
-#pragma pack()
-
-/*///////////////////////////////////////////////////////// */
-/* Low-level Mixing functions */
-
-#define MIXBUFFERSIZE 512
-#define MIXING_ATTENUATION 4
-#define MIXING_CLIPMIN (-0x08000000)
-#define MIXING_CLIPMAX (0x07FFFFFF)
-#define VOLUMERAMPPRECISION 12
-#define FADESONGDELAY 100
-#define EQ_BUFFERSIZE (MIXBUFFERSIZE)
-#define AGC_PRECISION 9
-#define AGC_UNITY (1 << AGC_PRECISION)
-
-/* Calling conventions */
-#ifdef MSC_VER
-#define MPPASMCALL __cdecl
-#define MPPFASTCALL __fastcall
-#else
-#define MPPASMCALL
-#define MPPFASTCALL
-#endif
-
-#define MOD2XMFineTune(k) ((int)( (signed char)((k)<<4) ))
-#define XM2MODFineTune(k) ((int)( (k>>4)&0x0f ))
-
-int _muldiv(long a, long b, long c);
-int _muldivr(long a, long b, long c);
-
-
-/* Byte swapping functions from the GNU C Library and libsdl */
-
-/* Swap bytes in 16 bit value. */
-#ifdef __GNUC__
-# define bswap_16(x) \
- (__extension__ \
- ({ unsigned short int __bsx = (x); \
- ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
-#else
-static inline unsigned short int
-bswap_16 (unsigned short int __bsx)
-{
- return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
-}
-#endif
-
-/* Swap bytes in 32 bit value. */
-#ifdef __GNUC__
-# define bswap_32(x) \
- (__extension__ \
- ({ unsigned int __bsx = (x); \
- ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) | \
- (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24)); }))
-#else
-static inline unsigned int
-bswap_32 (unsigned int __bsx)
-{
- return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >> 8) |
- (((__bsx) & 0x0000ff00) << 8) | (((__bsx) & 0x000000ff) << 24));
-}
-#endif
-
-
-/* From libsdl */
-#ifdef WORDS_BIGENDIAN
-#define bswapLE16(X) bswap_16(X)
-#define bswapLE32(X) bswap_32(X)
-#define bswapBE16(X) (X)
-#define bswapBE32(X) (X)
-#else
-#define bswapLE16(X) (X)
-#define bswapLE32(X) (X)
-#define bswapBE16(X) bswap_16(X)
-#define bswapBE32(X) bswap_32(X)
-#endif
-
-
-#endif
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#ifdef MODPLUG_TRACKER
-#define ENABLE_STEREOVU
-#endif
-
-// Volume ramp length, in 1/10 ms
-#define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz
-
-// VU-Meter
-#define VUMETER_DECAY 4
-
-// SNDMIX: These are global flags for playback control
-UINT CSoundFile::m_nStereoSeparation = 128;
-LONG CSoundFile::m_nStreamVolume = 0x8000;
-UINT CSoundFile::m_nMaxMixChannels = 32;
-// Mixing Configuration (SetWaveConfig)
-DWORD CSoundFile::gdwSysInfo = 0;
-DWORD CSoundFile::gnChannels = 1;
-DWORD CSoundFile::gdwSoundSetup = 0;
-DWORD CSoundFile::gdwMixingFreq = 44100;
-DWORD CSoundFile::gnBitsPerSample = 16;
-// Mixing data initialized in
-UINT CSoundFile::gnAGC = AGC_UNITY;
-UINT CSoundFile::gnVolumeRampSamples = 64;
-UINT CSoundFile::gnVUMeter = 0;
-UINT CSoundFile::gnCPUUsage = 0;
-LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL;
-PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL;
-LONG gnDryROfsVol = 0;
-LONG gnDryLOfsVol = 0;
-LONG gnRvbROfsVol = 0;
-LONG gnRvbLOfsVol = 0;
-int gbInitPlugins = 0;
-
-typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG);
-
-extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
-extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC);
-extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits);
-extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
-extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples);
-
-extern short int ModSinusTable[64];
-extern short int ModRampDownTable[64];
-extern short int ModSquareTable[64];
-extern short int ModRandomTable[64];
-extern DWORD LinearSlideUpTable[256];
-extern DWORD LinearSlideDownTable[256];
-extern DWORD FineLinearSlideUpTable[16];
-extern DWORD FineLinearSlideDownTable[16];
-extern signed char ft2VibratoTable[256]; // -64 .. +64
-extern int MixSoundBuffer[MIXBUFFERSIZE*4];
-extern int MixRearBuffer[MIXBUFFERSIZE*2];
-UINT gnReverbSend;
-
-
-// Log tables for pre-amp
-// We don't want the tracker to get too loud
-const UINT PreAmpTable[16] =
-{
- 0x60, 0x60, 0x60, 0x70, // 0-7
- 0x80, 0x88, 0x90, 0x98, // 8-15
- 0xA0, 0xA4, 0xA8, 0xB0, // 16-23
- 0xB4, 0xB8, 0xBC, 0xC0, // 24-31
-};
-
-const UINT PreAmpAGCTable[16] =
-{
- 0x60, 0x60, 0x60, 0x60,
- 0x68, 0x70, 0x78, 0x80,
- 0x84, 0x88, 0x8C, 0x90,
- 0x94, 0x98, 0x9C, 0xA0,
-};
-
-
-// Return (a*b)/c - no divide error
-int _muldiv(long a, long b, long c)
-{
-#ifdef MSC_VER
- int sign, result;
- _asm {
- mov eax, a
- mov ebx, b
- or eax, eax
- mov edx, eax
- jge aneg
- neg eax
-aneg:
- xor edx, ebx
- or ebx, ebx
- mov ecx, c
- jge bneg
- neg ebx
-bneg:
- xor edx, ecx
- or ecx, ecx
- mov sign, edx
- jge cneg
- neg ecx
-cneg:
- mul ebx
- cmp edx, ecx
- jae diverr
- div ecx
- jmp ok
-diverr:
- mov eax, 0x7fffffff
-ok:
- mov edx, sign
- or edx, edx
- jge rneg
- neg eax
-rneg:
- mov result, eax
- }
- return result;
-#else
- return ((unsigned long long) a * (unsigned long long) b ) / c;
-#endif
-}
-
-
-// Return (a*b+c/2)/c - no divide error
-int _muldivr(long a, long b, long c)
-{
-#ifdef MSC_VER
- int sign, result;
- _asm {
- mov eax, a
- mov ebx, b
- or eax, eax
- mov edx, eax
- jge aneg
- neg eax
-aneg:
- xor edx, ebx
- or ebx, ebx
- mov ecx, c
- jge bneg
- neg ebx
-bneg:
- xor edx, ecx
- or ecx, ecx
- mov sign, edx
- jge cneg
- neg ecx
-cneg:
- mul ebx
- mov ebx, ecx
- shr ebx, 1
- add eax, ebx
- adc edx, 0
- cmp edx, ecx
- jae diverr
- div ecx
- jmp ok
-diverr:
- mov eax, 0x7fffffff
-ok:
- mov edx, sign
- or edx, edx
- jge rneg
- neg eax
-rneg:
- mov result, eax
- }
- return result;
-#else
- return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
-#endif
-}
-
-
-BOOL CSoundFile::InitPlayer(BOOL bReset)
-//--------------------------------------
-{
- if (m_nMaxMixChannels > MAX_CHANNELS) m_nMaxMixChannels = MAX_CHANNELS;
- if (gdwMixingFreq < 4000) gdwMixingFreq = 4000;
- if (gdwMixingFreq > MAX_SAMPLE_RATE) gdwMixingFreq = MAX_SAMPLE_RATE;
- gnVolumeRampSamples = (gdwMixingFreq * VOLUMERAMPLEN) / 100000;
- if (gnVolumeRampSamples < 8) gnVolumeRampSamples = 8;
- gnDryROfsVol = gnDryLOfsVol = 0;
- gnRvbROfsVol = gnRvbLOfsVol = 0;
- if (bReset)
- {
- gnVUMeter = 0;
- gnCPUUsage = 0;
- }
- gbInitPlugins = (bReset) ? 3 : 1;
- InitializeDSP(bReset);
- return TRUE;
-}
-
-
-BOOL CSoundFile::FadeSong(UINT msec)
-//----------------------------------
-{
- LONG nsamples = _muldiv(msec, gdwMixingFreq, 1000);
- if (nsamples <= 0) return FALSE;
- if (nsamples > 0x100000) nsamples = 0x100000;
- m_nBufferCount = nsamples;
- LONG nRampLength = m_nBufferCount;
- // Ramp everything down
- for (UINT noff=0; noff < m_nMixChannels; noff++)
- {
- MODCHANNEL *pramp = &Chn[ChnMix[noff]];
- if (!pramp) continue;
- pramp->nNewLeftVol = pramp->nNewRightVol = 0;
- pramp->nRightRamp = (-pramp->nRightVol << VOLUMERAMPPRECISION) / nRampLength;
- pramp->nLeftRamp = (-pramp->nLeftVol << VOLUMERAMPPRECISION) / nRampLength;
- pramp->nRampRightVol = pramp->nRightVol << VOLUMERAMPPRECISION;
- pramp->nRampLeftVol = pramp->nLeftVol << VOLUMERAMPPRECISION;
- pramp->nRampLength = nRampLength;
- pramp->dwFlags |= CHN_VOLUMERAMP;
- }
- m_dwSongFlags |= SONG_FADINGSONG;
- return TRUE;
-}
-
-
-BOOL CSoundFile::GlobalFadeSong(UINT msec)
-//----------------------------------------
-{
- if (m_dwSongFlags & SONG_GLOBALFADE) return FALSE;
- m_nGlobalFadeMaxSamples = _muldiv(msec, gdwMixingFreq, 1000);
- m_nGlobalFadeSamples = m_nGlobalFadeMaxSamples;
- m_dwSongFlags |= SONG_GLOBALFADE;
- return TRUE;
-}
-
-
-UINT CSoundFile::Read(LPVOID lpDestBuffer, UINT cbBuffer)
-//-------------------------------------------------------
-{
- LPBYTE lpBuffer = (LPBYTE)lpDestBuffer;
- LPCONVERTPROC pCvt = X86_Convert32To8;
- UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0;
- LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF;
- UINT nMaxPlugins;
-
- {
- nMaxPlugins = MAX_MIXPLUGINS;
- while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
- }
- m_nMixStat = 0;
- lSampleSize = gnChannels;
- if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; }
-#ifndef FASTSOUNDLIB
- else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; }
- else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; }
-#endif
- lMax = cbBuffer / lSampleSize;
- if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0;
- lRead = lMax;
- if (m_dwSongFlags & SONG_ENDREACHED) goto MixDone;
- while (lRead > 0)
- {
- // Update Channel Data
- if (!m_nBufferCount)
- {
-#ifndef FASTSOUNDLIB
- if (m_dwSongFlags & SONG_FADINGSONG)
- {
- m_dwSongFlags |= SONG_ENDREACHED;
- m_nBufferCount = lRead;
- } else
-#endif
- if (!ReadNote())
- {
-#ifndef FASTSOUNDLIB
- if (!FadeSong(FADESONGDELAY))
-#endif
- {
- m_dwSongFlags |= SONG_ENDREACHED;
- if (lRead == lMax) goto MixDone;
- m_nBufferCount = lRead;
- }
- }
- }
- lCount = m_nBufferCount;
- if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
- if (lCount > lRead) lCount = lRead;
- if (!lCount) break;
- lSampleCount = lCount;
-#ifndef NO_REVERB
- gnReverbSend = 0;
-#endif
- // Resetting sound buffer
- X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
- if (gnChannels >= 2)
- {
- lSampleCount *= 2;
- m_nMixStat += CreateStereoMix(lCount);
- ProcessStereoDSP(lCount);
- } else
- {
- m_nMixStat += CreateStereoMix(lCount);
- if (nMaxPlugins) ProcessPlugins(lCount);
- ProcessStereoDSP(lCount);
- X86_MonoFromStereo(MixSoundBuffer, lCount);
- }
- nStat++;
-#ifndef NO_AGC
- // Automatic Gain Control
- if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
-#endif
- UINT lTotalSampleCount = lSampleCount;
-#ifndef FASTSOUNDLIB
- // Multichannel
- if (gnChannels > 2)
- {
- X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
- lTotalSampleCount *= 2;
- }
- // Hook Function
- if (gpSndMixHook)
- {
- gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
- }
-#endif
- // Perform clipping + VU-Meter
- lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax);
- // Buffer ready
- lRead -= lCount;
- m_nBufferCount -= lCount;
- }
-MixDone:
- if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
- // VU-Meter
- nVUMeterMin >>= (24-MIXING_ATTENUATION);
- nVUMeterMax >>= (24-MIXING_ATTENUATION);
- if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin;
- if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF;
- if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; }
- return lMax - lRead;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Handles navigation/effects
-
-BOOL CSoundFile::ProcessRow()
-//---------------------------
-{
- if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
- {
- m_nPatternDelay = 0;
- m_nFrameDelay = 0;
- m_nTickCount = 0;
- m_nRow = m_nNextRow;
- // Reset Pattern Loop Effect
- if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern;
- // Check if pattern is valid
- if (!(m_dwSongFlags & SONG_PATTERNLOOP))
- {
- m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
- if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
- while (m_nPattern >= MAX_PATTERNS)
- {
- // End of song ?
- if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
- {
- //if (!m_nRepeatCount)
- return FALSE; //never repeat entire song
- if (!m_nRestartPos)
- {
- m_nMusicSpeed = m_nDefaultSpeed;
- m_nMusicTempo = m_nDefaultTempo;
- m_nGlobalVolume = m_nDefaultGlobalVolume;
- for (UINT i=0; i<MAX_CHANNELS; i++)
- {
- Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF;
- Chn[i].nFadeOutVol = 0;
- if (i < m_nChannels)
- {
- Chn[i].nGlobalVol = ChnSettings[i].nVolume;
- Chn[i].nVolume = ChnSettings[i].nVolume;
- Chn[i].nPan = ChnSettings[i].nPan;
- Chn[i].nPanSwing = Chn[i].nVolSwing = 0;
- Chn[i].nOldVolParam = 0;
- Chn[i].nOldOffset = 0;
- Chn[i].nOldHiOffset = 0;
- Chn[i].nPortamentoDest = 0;
- if (!Chn[i].nLength)
- {
- Chn[i].dwFlags = ChnSettings[i].dwFlags;
- Chn[i].nLoopStart = 0;
- Chn[i].nLoopEnd = 0;
- Chn[i].pHeader = NULL;
- Chn[i].pSample = NULL;
- Chn[i].pInstrument = NULL;
- }
- }
- }
- }
-// if (m_nRepeatCount > 0) m_nRepeatCount--;
- m_nCurrentPattern = m_nRestartPos;
- m_nRow = 0;
- if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE;
- } else
- {
- m_nCurrentPattern++;
- }
- m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
- if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
- }
- m_nNextPattern = m_nCurrentPattern;
- }
- // Weird stuff?
- if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE;
- // Should never happen
- if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0;
- m_nNextRow = m_nRow + 1;
- if (m_nNextRow >= PatternSize[m_nPattern])
- {
- if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
- m_nNextRow = 0;
- }
- // Reset channel values
- MODCHANNEL *pChn = Chn;
- MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
- for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++)
- {
- pChn->nRowNote = m->note;
- pChn->nRowInstr = m->instr;
- pChn->nRowVolCmd = m->volcmd;
- pChn->nRowVolume = m->vol;
- pChn->nRowCommand = m->command;
- pChn->nRowParam = m->param;
-
- pChn->nLeftVol = pChn->nNewLeftVol;
- pChn->nRightVol = pChn->nNewRightVol;
- pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO);
- pChn->nCommand = 0;
- }
- }
- // Should we process tick0 effects?
- if (!m_nMusicSpeed) m_nMusicSpeed = 1;
- m_dwSongFlags |= SONG_FIRSTTICK;
- if (m_nTickCount)
- {
- m_dwSongFlags &= ~SONG_FIRSTTICK;
- if ((!(m_nType & MOD_TYPE_XM)) && (m_nTickCount < m_nMusicSpeed * (1 + m_nPatternDelay)))
- {
- if (!(m_nTickCount % m_nMusicSpeed)) m_dwSongFlags |= SONG_FIRSTTICK;
- }
-
- }
- // Update Effects
- return ProcessEffects();
-}
-
-
-////////////////////////////////////////////////////////////////////////////////////////////
-// Handles envelopes & mixer setup
-
-BOOL CSoundFile::ReadNote()
-//-------------------------
-{
- if (!ProcessRow()) return FALSE;
- ////////////////////////////////////////////////////////////////////////////////////
- m_nTotalCount++;
- if (!m_nMusicTempo) return FALSE;
- m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
- // Master Volume + Pre-Amplification / Attenuation setup
- DWORD nMasterVol;
- {
- int nchn32 = (m_nChannels < 32) ? m_nChannels : 31;
- if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6;
- int realmastervol = m_nMasterVolume;
- if (realmastervol > 0x80)
- {
- realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
- }
- UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
- DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6;
- if (mastervol > 0x200) mastervol = 0x200;
- if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples))
- {
- mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
- }
- nMasterVol = (mastervol << 7) / attenuation;
- if (nMasterVol > 0x180) nMasterVol = 0x180;
- }
- ////////////////////////////////////////////////////////////////////////////////////
- // Update channels data
- m_nMixChannels = 0;
- MODCHANNEL *pChn = Chn;
- for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++)
- {
- if ((pChn->dwFlags & CHN_NOTEFADE) && (!(pChn->nFadeOutVol|pChn->nRightVol|pChn->nLeftVol)))
- {
- pChn->nLength = 0;
- pChn->nROfs = pChn->nLOfs = 0;
- }
- // Check for unused channel
- if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength)))
- {
- pChn->nVUMeter = 0;
-#ifdef ENABLE_STEREOVU
- pChn->nLeftVU = pChn->nRightVU = 0;
-#endif
- continue;
- }
- // Reset channel data
- pChn->nInc = 0;
- pChn->nRealVolume = 0;
- pChn->nRealPan = pChn->nPan + pChn->nPanSwing;
- if (pChn->nRealPan < 0) pChn->nRealPan = 0;
- if (pChn->nRealPan > 256) pChn->nRealPan = 256;
- pChn->nRampLength = 0;
- // Calc Frequency
- if ((pChn->nPeriod) && (pChn->nLength))
- {
- int vol = pChn->nVolume + pChn->nVolSwing;
-
- if (vol < 0) vol = 0;
- if (vol > 256) vol = 256;
- // Tremolo
- if (pChn->dwFlags & CHN_TREMOLO)
- {
- UINT trempos = pChn->nTremoloPos & 0x3F;
- if (vol > 0)
- {
- int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6;
- switch (pChn->nTremoloType & 0x03)
- {
- case 1:
- vol += (ModRampDownTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
- break;
- case 2:
- vol += (ModSquareTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
- break;
- case 3:
- vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
- break;
- default:
- vol += (ModSinusTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
- }
- }
- if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
- {
- pChn->nTremoloPos = (trempos + pChn->nTremoloSpeed) & 0x3F;
- }
- }
- // Tremor
- if (pChn->nCommand == CMD_TREMOR)
- {
- UINT n = (pChn->nTremorParam >> 4) + (pChn->nTremorParam & 0x0F);
- UINT ontime = pChn->nTremorParam >> 4;
- if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) { n += 2; ontime++; }
- UINT tremcount = (UINT)pChn->nTremorCount;
- if (tremcount >= n) tremcount = 0;
- if ((m_nTickCount) || (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))
- {
- if (tremcount >= ontime) vol = 0;
- pChn->nTremorCount = (BYTE)(tremcount + 1);
- }
- pChn->dwFlags |= CHN_FASTVOLRAMP;
- }
- // Clip volume
- if (vol < 0) vol = 0;
- if (vol > 0x100) vol = 0x100;
- vol <<= 6;
- // Process Envelopes
- if (pChn->pHeader)
- {
- INSTRUMENTHEADER *penv = pChn->pHeader;
- // Volume Envelope
- if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv))
- {
- int envpos = pChn->nVolEnvPosition;
- UINT pt = penv->nVolEnv - 1;
- for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++)
- {
- if (envpos <= penv->VolPoints[i])
- {
- pt = i;
- break;
- }
- }
- int x2 = penv->VolPoints[pt];
- int x1, envvol;
- if (envpos >= x2)
- {
- envvol = penv->VolEnv[pt] << 2;
- x1 = x2;
- } else
- if (pt)
- {
- envvol = penv->VolEnv[pt-1] << 2;
- x1 = penv->VolPoints[pt-1];
- } else
- {
- envvol = 0;
- x1 = 0;
- }
- if (envpos > x2) envpos = x2;
- if ((x2 > x1) && (envpos > x1))
- {
- envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1);
- }
- if (envvol < 0) envvol = 0;
- if (envvol > 256) envvol = 256;
- vol = (vol * envvol) >> 8;
- }
- // Panning Envelope
- if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv))
- {
- int envpos = pChn->nPanEnvPosition;
- UINT pt = penv->nPanEnv - 1;
- for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++)
- {
- if (envpos <= penv->PanPoints[i])
- {
- pt = i;
- break;
- }
- }
- int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt];
- int x1, envpan;
- if (envpos >= x2)
- {
- envpan = y2;
- x1 = x2;
- } else
- if (pt)
- {
- envpan = penv->PanEnv[pt-1];
- x1 = penv->PanPoints[pt-1];
- } else
- {
- envpan = 128;
- x1 = 0;
- }
- if ((x2 > x1) && (envpos > x1))
- {
- envpan += ((envpos - x1) * (y2 - envpan)) / (x2 - x1);
- }
- if (envpan < 0) envpan = 0;
- if (envpan > 64) envpan = 64;
- int pan = pChn->nPan;
- if (pan >= 128)
- {
- pan += ((envpan - 32) * (256 - pan)) / 32;
- } else
- {
- pan += ((envpan - 32) * (pan)) / 32;
- }
- if (pan < 0) pan = 0;
- if (pan > 256) pan = 256;
- pChn->nRealPan = pan;
- }
- // FadeOut volume
- if (pChn->dwFlags & CHN_NOTEFADE)
- {
- UINT fadeout = penv->nFadeOut;
- if (fadeout)
- {
- pChn->nFadeOutVol -= fadeout << 1;
- if (pChn->nFadeOutVol <= 0) pChn->nFadeOutVol = 0;
- vol = (vol * pChn->nFadeOutVol) >> 16;
- } else
- if (!pChn->nFadeOutVol)
- {
- vol = 0;
- }
- }
- // Pitch/Pan separation
- if ((penv->nPPS) && (pChn->nRealPan) && (pChn->nNote))
- {
- int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - penv->nPPC - 1) * (int)penv->nPPS) / (int)8;
- if (pandelta < 0) pandelta = 0;
- if (pandelta > 256) pandelta = 256;
- pChn->nRealPan = pandelta;
- }
- } else
- {
- // No Envelope: key off => note cut
- if (pChn->dwFlags & CHN_NOTEFADE) // 1.41-: CHN_KEYOFF|CHN_NOTEFADE
- {
- pChn->nFadeOutVol = 0;
- vol = 0;
- }
- }
- // vol is 14-bits
- if (vol)
- {
- // IMPORTANT: pChn->nRealVolume is 14 bits !!!
- // -> _muldiv( 14+8, 6+6, 18); => RealVolume: 14-bit result (22+12-20)
- pChn->nRealVolume = _muldiv(vol * m_nGlobalVolume, pChn->nGlobalVol * pChn->nInsVol, 1 << 20);
- }
- if (pChn->nPeriod < m_nMinPeriod) pChn->nPeriod = m_nMinPeriod;
- int period = pChn->nPeriod;
- if ((pChn->dwFlags & (CHN_GLISSANDO|CHN_PORTAMENTO)) == (CHN_GLISSANDO|CHN_PORTAMENTO))
- {
- period = GetPeriodFromNote(GetNoteFromPeriod(period), pChn->nFineTune, pChn->nC4Speed);
- }
-
- // Arpeggio ?
- if (pChn->nCommand == CMD_ARPEGGIO)
- {
- switch(m_nTickCount % 3)
- {
- case 1: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
- case 2: period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
- }
- }
-
- if (m_dwSongFlags & SONG_AMIGALIMITS)
- {
- if (period < 113*4) period = 113*4;
- if (period > 856*4) period = 856*4;
- }
-
- // Pitch/Filter Envelope
- if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv))
- {
- INSTRUMENTHEADER *penv = pChn->pHeader;
- int envpos = pChn->nPitchEnvPosition;
- UINT pt = penv->nPitchEnv - 1;
- for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++)
- {
- if (envpos <= penv->PitchPoints[i])
- {
- pt = i;
- break;
- }
- }
- int x2 = penv->PitchPoints[pt];
- int x1, envpitch;
- if (envpos >= x2)
- {
- envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8;
- x1 = x2;
- } else
- if (pt)
- {
- envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8;
- x1 = penv->PitchPoints[pt-1];
- } else
- {
- envpitch = 0;
- x1 = 0;
- }
- if (envpos > x2) envpos = x2;
- if ((x2 > x1) && (envpos > x1))
- {
- int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8;
- envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
- }
- if (envpitch < -256) envpitch = -256;
- if (envpitch > 256) envpitch = 256;
- // Filter Envelope: controls cutoff frequency
- if (penv->dwFlags & ENV_FILTER)
- {
-#ifndef NO_FILTER
- SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
-#endif // NO_FILTER
- } else
- // Pitch Envelope
- {
- int l = envpitch;
- if (l < 0)
- {
- l = -l;
- if (l > 255) l = 255;
- period = _muldiv(period, LinearSlideUpTable[l], 0x10000);
- } else
- {
- if (l > 255) l = 255;
- period = _muldiv(period, LinearSlideDownTable[l], 0x10000);
- }
- }
- }
-
- // Vibrato
- if (pChn->dwFlags & CHN_VIBRATO)
- {
- UINT vibpos = pChn->nVibratoPos;
- LONG vdelta;
- switch (pChn->nVibratoType & 0x03)
- {
- case 1:
- vdelta = ModRampDownTable[vibpos];
- break;
- case 2:
- vdelta = ModSquareTable[vibpos];
- break;
- case 3:
- vdelta = ModRandomTable[vibpos];
- break;
- default:
- vdelta = ModSinusTable[vibpos];
- }
- UINT vdepth = ((m_nType != MOD_TYPE_IT) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7;
- vdelta = (vdelta * (int)pChn->nVibratoDepth) >> vdepth;
- if ((m_dwSongFlags & SONG_LINEARSLIDES) && (m_nType & MOD_TYPE_IT))
- {
- LONG l = vdelta;
- if (l < 0)
- {
- l = -l;
- vdelta = _muldiv(period, LinearSlideDownTable[l >> 2], 0x10000) - period;
- if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideDownTable[l & 0x03], 0x10000) - period;
-
- } else
- {
- vdelta = _muldiv(period, LinearSlideUpTable[l >> 2], 0x10000) - period;
- if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period;
-
- }
- }
- period += vdelta;
- if ((m_nTickCount) || ((m_nType & MOD_TYPE_IT) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
- {
- pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F;
- }
- }
- // Panbrello
- if (pChn->dwFlags & CHN_PANBRELLO)
- {
- UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F;
- LONG pdelta;
- switch (pChn->nPanbrelloType & 0x03)
- {
- case 1:
- pdelta = ModRampDownTable[panpos];
- break;
- case 2:
- pdelta = ModSquareTable[panpos];
- break;
- case 3:
- pdelta = ModRandomTable[panpos];
- break;
- default:
- pdelta = ModSinusTable[panpos];
- }
- pChn->nPanbrelloPos += pChn->nPanbrelloSpeed;
- pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> 3;
- pdelta += pChn->nRealPan;
- if (pdelta < 0) pdelta = 0;
- if (pdelta > 256) pdelta = 256;
- pChn->nRealPan = pdelta;
- }
- int nPeriodFrac = 0;
- // Instrument Auto-Vibrato
- if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth))
- {
- MODINSTRUMENT *pins = pChn->pInstrument;
- if (pins->nVibSweep == 0)
- {
- pChn->nAutoVibDepth = pins->nVibDepth << 8;
- } else
- {
- if (m_nType & MOD_TYPE_IT)
- {
- pChn->nAutoVibDepth += pins->nVibSweep << 3;
- } else
- if (!(pChn->dwFlags & CHN_KEYOFF))
- {
- pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep;
- }
- if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
- pChn->nAutoVibDepth = pins->nVibDepth << 8;
- }
- pChn->nAutoVibPos += pins->nVibRate;
- int val;
- switch(pins->nVibType)
- {
- case 4: // Random
- val = ModRandomTable[pChn->nAutoVibPos & 0x3F];
- pChn->nAutoVibPos++;
- break;
- case 3: // Ramp Down
- val = ((0x40 - (pChn->nAutoVibPos >> 1)) & 0x7F) - 0x40;
- break;
- case 2: // Ramp Up
- val = ((0x40 + (pChn->nAutoVibPos >> 1)) & 0x7f) - 0x40;
- break;
- case 1: // Square
- val = (pChn->nAutoVibPos & 128) ? +64 : -64;
- break;
- default: // Sine
- val = ft2VibratoTable[pChn->nAutoVibPos & 255];
- }
- int n = ((val * pChn->nAutoVibDepth) >> 8);
- if (m_nType & MOD_TYPE_IT)
- {
- int df1, df2;
- if (n < 0)
- {
- n = -n;
- UINT n1 = n >> 8;
- df1 = LinearSlideUpTable[n1];
- df2 = LinearSlideUpTable[n1+1];
- } else
- {
- UINT n1 = n >> 8;
- df1 = LinearSlideDownTable[n1];
- df2 = LinearSlideDownTable[n1+1];
- }
- n >>= 2;
- period = _muldiv(period, df1 + ((df2-df1)*(n&0x3F)>>6), 256);
- nPeriodFrac = period & 0xFF;
- period >>= 8;
- } else
- {
- period += (n >> 6);
- }
- }
- // Final Period
- if (period <= m_nMinPeriod)
- {
- if (m_nType & MOD_TYPE_S3M) pChn->nLength = 0;
- period = m_nMinPeriod;
- }
- if (period > m_nMaxPeriod)
- {
- if ((m_nType & MOD_TYPE_IT) || (period >= 0x100000))
- {
- pChn->nFadeOutVol = 0;
- pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nRealVolume = 0;
- }
- period = m_nMaxPeriod;
- nPeriodFrac = 0;
- }
- UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac);
- if ((m_nType & MOD_TYPE_IT) && (freq < 256))
- {
- pChn->nFadeOutVol = 0;
- pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nRealVolume = 0;
- }
- UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq);
- if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000;
- if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7;
- if (ninc > 0xFF0000) ninc = 0xFF0000;
- pChn->nInc = (ninc+1) & ~3;
- }
-
- // Increment envelope position
- if (pChn->pHeader)
- {
- INSTRUMENTHEADER *penv = pChn->pHeader;
- // Volume Envelope
- if (pChn->dwFlags & CHN_VOLENV)
- {
- // Increase position
- pChn->nVolEnvPosition++;
- // Volume Loop ?
- if (penv->dwFlags & ENV_VOLLOOP)
- {
- UINT volloopend = penv->VolPoints[penv->nVolLoopEnd];
- if (m_nType != MOD_TYPE_XM) volloopend++;
- if (pChn->nVolEnvPosition == volloopend)
- {
- pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart];
- if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart])
- && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv)))
- {
- pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nFadeOutVol = 0;
- }
- }
- }
- // Volume Sustain ?
- if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
- {
- if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1)
- pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin];
- } else
- // End of Envelope ?
- if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1])
- {
- if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1];
- if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
- {
- pChn->dwFlags |= CHN_NOTEFADE;
- pChn->nFadeOutVol = 0;
-
- pChn->nRealVolume = 0;
- }
- }
- }
- // Panning Envelope
- if (pChn->dwFlags & CHN_PANENV)
- {
- pChn->nPanEnvPosition++;
- if (penv->dwFlags & ENV_PANLOOP)
- {
- UINT panloopend = penv->PanPoints[penv->nPanLoopEnd];
- if (m_nType != MOD_TYPE_XM) panloopend++;
- if (pChn->nPanEnvPosition == panloopend)
- pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart];
- }
- // Panning Sustain ?
- if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1)
- && (!(pChn->dwFlags & CHN_KEYOFF)))
- {
- // Panning sustained
- pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin];
- } else
- {
- if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1])
- pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1];
- }
- }
- // Pitch Envelope
- if (pChn->dwFlags & CHN_PITCHENV)
- {
- // Increase position
- pChn->nPitchEnvPosition++;
- // Pitch Loop ?
- if (penv->dwFlags & ENV_PITCHLOOP)
- {
- if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd])
- pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart];
- }
- // Pitch Sustain ?
- if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
- {
- if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1)
- pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin];
- } else
- {
- if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1])
- pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1];
- }
- }
- }
-#ifdef MODPLUG_PLAYER
- // Limit CPU -> > 80% -> don't ramp
- if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
- {
- pChn->nLeftVol = pChn->nRightVol = 0;
- }
-#endif // MODPLUG_PLAYER
- // Volume ramping
- pChn->dwFlags &= ~CHN_VOLUMERAMP;
- if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol))
- pChn->dwFlags |= CHN_VOLUMERAMP;
-#ifdef MODPLUG_PLAYER
- // Decrease VU-Meter
- if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0;
-#endif // MODPLUG_PLAYER
-#ifdef ENABLE_STEREOVU
- if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0;
- if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0;
-#endif
- // Check for too big nInc
- if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP;
- pChn->nNewRightVol = pChn->nNewLeftVol = 0;
- pChn->pCurrentSample = ((pChn->pSample) && (pChn->nLength) && (pChn->nInc)) ? pChn->pSample : NULL;
- if (pChn->pCurrentSample)
- {
- // Update VU-Meter (nRealVolume is 14-bit)
-#ifdef MODPLUG_PLAYER
- UINT vutmp = pChn->nRealVolume >> (14 - 8);
- if (vutmp > 0xFF) vutmp = 0xFF;
- if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp;
- vutmp >>= 1;
- if (pChn->nVUMeter < vutmp) pChn->nVUMeter = vutmp;
-#endif // MODPLUG_PLAYER
-#ifdef ENABLE_STEREOVU
- UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14;
- if (vul > 127) vul = 127;
- if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul;
- vul >>= 1;
- if (pChn->nLeftVU < vul) pChn->nLeftVU = (BYTE)vul;
- UINT vur = (pChn->nRealVolume * (256-pChn->nRealPan)) >> 14;
- if (vur > 127) vur = 127;
- if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur;
- vur >>= 1;
- if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur;
-#endif
-#ifdef MODPLUG_TRACKER
- UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol;
-#else
-#define kChnMasterVol nMasterVol
-#endif // MODPLUG_TRACKER
- // Adjusting volumes
- if (gnChannels >= 2)
- {
- int pan = ((int)pChn->nRealPan) - 128;
- pan *= (int)m_nStereoSeparation;
- pan /= 128;
- pan += 128;
-
- if (pan < 0) pan = 0;
- if (pan > 256) pan = 256;
-#ifndef FASTSOUNDLIB
- if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
-#endif
- LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1);
- if (gdwSoundSetup & SNDMIX_SOFTPANNING)
- {
- if (pan < 128)
- {
- pChn->nNewLeftVol = (realvol * pan) >> 8;
- pChn->nNewRightVol = (realvol * 128) >> 8;
- } else
- {
- pChn->nNewLeftVol = (realvol * 128) >> 8;
- pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
- }
- } else
- {
- pChn->nNewLeftVol = (realvol * pan) >> 8;
- pChn->nNewRightVol = (realvol * (256 - pan)) >> 8;
- }
- } else
- {
- pChn->nNewRightVol = (pChn->nRealVolume * kChnMasterVol) >> 8;
- pChn->nNewLeftVol = pChn->nNewRightVol;
- }
- // Clipping volumes
- if (pChn->nNewRightVol > 0xFFFF) pChn->nNewRightVol = 0xFFFF;
- if (pChn->nNewLeftVol > 0xFFFF) pChn->nNewLeftVol = 0xFFFF;
- // Check IDO
- if (gdwSoundSetup & SNDMIX_NORESAMPLING)
- {
- pChn->dwFlags |= CHN_NOIDO;
- } else
- {
- pChn->dwFlags &= ~(CHN_NOIDO|CHN_HQSRC);
- if( pChn->nInc == 0x10000 )
- { pChn->dwFlags |= CHN_NOIDO;
- }
- else
- { if( ((gdwSoundSetup & SNDMIX_HQRESAMPLER) == 0) && ((gdwSoundSetup & SNDMIX_ULTRAHQSRCMODE) == 0) )
- { if (pChn->nInc >= 0xFF00) pChn->dwFlags |= CHN_NOIDO;
- }
- }
- }
- pChn->nNewRightVol >>= MIXING_ATTENUATION;
- pChn->nNewLeftVol >>= MIXING_ATTENUATION;
- pChn->nRightRamp = pChn->nLeftRamp = 0;
- // Dolby Pro-Logic Surround
- if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol;
- // Checking Ping-Pong Loops
- if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc;
- // Setting up volume ramp
- if ((pChn->dwFlags & CHN_VOLUMERAMP)
- && ((pChn->nRightVol != pChn->nNewRightVol)
- || (pChn->nLeftVol != pChn->nNewLeftVol)))
- {
- LONG nRampLength = gnVolumeRampSamples;
- LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION);
- LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION);
-#ifndef FASTSOUNDLIB
- if ((gdwSoundSetup & SNDMIX_DIRECTTODISK)
- || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU))
- && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20)))
- {
- if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP)))
- {
- nRampLength = m_nBufferCount;
- if (nRampLength > (1 << (VOLUMERAMPPRECISION-1))) nRampLength = (1 << (VOLUMERAMPPRECISION-1));
- if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples;
- }
- }
-#endif
- pChn->nRightRamp = nRightDelta / nRampLength;
- pChn->nLeftRamp = nLeftDelta / nRampLength;
- pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION);
- pChn->nLeftVol = pChn->nNewLeftVol - ((pChn->nLeftRamp * nRampLength) >> VOLUMERAMPPRECISION);
- if (pChn->nRightRamp|pChn->nLeftRamp)
- {
- pChn->nRampLength = nRampLength;
- } else
- {
- pChn->dwFlags &= ~CHN_VOLUMERAMP;
- pChn->nRightVol = pChn->nNewRightVol;
- pChn->nLeftVol = pChn->nNewLeftVol;
- }
- } else
- {
- pChn->dwFlags &= ~CHN_VOLUMERAMP;
- pChn->nRightVol = pChn->nNewRightVol;
- pChn->nLeftVol = pChn->nNewLeftVol;
- }
- pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION;
- pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION;
- // Adding the channel in the channel list
- ChnMix[m_nMixChannels++] = nChn;
- if (m_nMixChannels >= MAX_CHANNELS) break;
- } else
- {
-#ifdef ENABLE_STEREOVU
- // Note change but no sample
- if (pChn->nLeftVU > 128) pChn->nLeftVU = 0;
- if (pChn->nRightVU > 128) pChn->nRightVU = 0;
-#endif
- if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0;
- pChn->nLeftVol = pChn->nRightVol = 0;
- pChn->nLength = 0;
- }
- }
- // Checking Max Mix Channels reached: ordering by volume
- if ((m_nMixChannels >= m_nMaxMixChannels) && (!(gdwSoundSetup & SNDMIX_DIRECTTODISK)))
- {
- for (UINT i=0; i<m_nMixChannels; i++)
- {
- UINT j=i;
- while ((j+1<m_nMixChannels) && (Chn[ChnMix[j]].nRealVolume < Chn[ChnMix[j+1]].nRealVolume))
- {
- UINT n = ChnMix[j];
- ChnMix[j] = ChnMix[j+1];
- ChnMix[j+1] = n;
- j++;
- }
- }
- }
- if (m_dwSongFlags & SONG_GLOBALFADE)
- {
- if (!m_nGlobalFadeSamples)
- {
- m_dwSongFlags |= SONG_ENDREACHED;
- return FALSE;
- }
- if (m_nGlobalFadeSamples > m_nBufferCount)
- m_nGlobalFadeSamples -= m_nBufferCount;
- else
- m_nGlobalFadeSamples = 0;
- }
- return TRUE;
-}
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Rani Assaf <rani@magic.metawire.com>,
- * Olivier Lapicque <olivierl@jps.net>,
- * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
-*/
-
-#ifndef _STDAFX_H_
-#define _STDAFX_H_
-
-
-#ifdef _MSC_VER
-
-#pragma warning (disable:4201)
-#pragma warning (disable:4514)
-#include <windows.h>
-#include <windowsx.h>
-#include <mmsystem.h>
-#include <stdio.h>
-
-inline void ProcessPlugins(int n) {}
-
-#else
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-typedef signed char CHAR;
-typedef unsigned char UCHAR;
-typedef unsigned char* PUCHAR;
-typedef unsigned short USHORT;
-#if defined(__x86_64__)
-typedef unsigned int ULONG;
-typedef unsigned int UINT;
-typedef unsigned int DWORD;
-typedef int LONG;
-typedef long LONGLONG;
-typedef int * LPLONG;
-typedef unsigned int * LPDWORD;
-#else
-typedef unsigned long ULONG;
-typedef unsigned long UINT;
-typedef unsigned long DWORD;
-typedef long LONG;
-typedef long long LONGLONG;
-typedef long * LPLONG;
-typedef unsigned long * LPDWORD;
-#endif
-typedef unsigned short WORD;
-typedef unsigned char BYTE;
-typedef unsigned char * LPBYTE;
-typedef bool BOOL;
-typedef char * LPSTR;
-typedef void * LPVOID;
-typedef unsigned short * LPWORD;
-typedef const char * LPCSTR;
-typedef void * PVOID;
-typedef void VOID;
-
-inline LONG MulDiv (long a, long b, long c)
-{
- /* if (!c) return 0; */
- return ((unsigned long long) a * (unsigned long long) b ) / c;
-}
-
-#define MODPLUG_NO_FILESAVE
-#define NO_AGC
-#define LPCTSTR LPCSTR
-#define lstrcpyn strncpy
-#define lstrcpy strcpy
-#define lstrcmp strcmp
-#define WAVE_FORMAT_PCM 1
-/*#define ENABLE_EQ */
-
-#define GHND 0
-
-inline signed char * GlobalAllocPtr(unsigned int, size_t size)
-{
- signed char * p = (signed char *) malloc(size);
-
- if (p != NULL) memset(p, 0, size);
- return p;
-}
-
-inline void ProcessPlugins(int n) {}
-
-#define GlobalFreePtr(p) free((void *)(p))
-
-#define strnicmp(a,b,c) strncasecmp(a,b,c)
-#define wsprintf sprintf
-
-#ifndef FALSE
-#define FALSE false
-#endif
-
-#ifndef TRUE
-#define TRUE true
-#endif
-
-#endif /* MSC_VER */
-
-#endif
-
-
-
+++ /dev/null
-/*
- * This source code is public domain.
- *
- * Authors: Olivier Lapicque <olivierl@jps.net>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "stdafx.h"
-#include "sndfile.h"
-
-#ifndef FASTSOUNDLIB
-//#pragma data_seg(".tables")
-#endif
-
-BYTE ImpulseTrackerPortaVolCmd[16] =
-{
- 0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60,
- 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-// Period table for Protracker octaves 0-5:
-WORD ProTrackerPeriodTable[6*12] =
-{
- 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907,
- 856,808,762,720,678,640,604,570,538,508,480,453,
- 428,404,381,360,339,320,302,285,269,254,240,226,
- 214,202,190,180,170,160,151,143,135,127,120,113,
- 107,101,95,90,85,80,75,71,67,63,60,56,
- 53,50,47,45,42,40,37,35,33,31,30,28
-};
-
-
-WORD ProTrackerTunedPeriods[16*12] =
-{
- 1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907,
- 1700,1604,1514,1430,1348,1274,1202,1134,1070,1010,954,900,
- 1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,894,
- 1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,888,
- 1664,1570,1482,1398,1320,1246,1176,1110,1048,990,934,882,
- 1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,874,
- 1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,868,
- 1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914,862,
- 1814,1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,
- 1800,1700,1604,1514,1430,1350,1272,1202,1134,1070,1010,954,
- 1788,1688,1592,1504,1418,1340,1264,1194,1126,1064,1004,948,
- 1774,1676,1582,1492,1408,1330,1256,1184,1118,1056,996,940,
- 1762,1664,1570,1482,1398,1320,1246,1176,1110,1048,988,934,
- 1750,1652,1558,1472,1388,1310,1238,1168,1102,1040,982,926,
- 1736,1640,1548,1460,1378,1302,1228,1160,1094,1032,974,920,
- 1724,1628,1536,1450,1368,1292,1220,1150,1086,1026,968,914
-};
-
-
-// S3M C-4 periods
-WORD FreqS3MTable[16] =
-{
- 1712,1616,1524,1440,1356,1280,
- 1208,1140,1076,1016,960,907,
- 0,0,0,0
-};
-
-
-// S3M FineTune frequencies
-WORD S3MFineTuneTable[16] =
-{
- 7895,7941,7985,8046,8107,8169,8232,8280,
- 8363,8413,8463,8529,8581,8651,8723,8757, // 8363*2^((i-8)/(12*8))
-};
-
-
-// Sinus table
-short int ModSinusTable[64] =
-{
- 0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126,
- 127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12,
- 0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126,
- -127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12
-};
-
-// Triangle wave table (ramp down)
-short int ModRampDownTable[64] =
-{
- 0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60,
- -64,-68,-72,-76,-80,-84,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124,
- 127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,
- 63,59,55,51,47,43,39,35,31,27,23,19,15,11,7,3
-};
-
-// Square wave table
-short int ModSquareTable[64] =
-{
- 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
- -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
- -127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
-};
-
-// Random wave table
-short int ModRandomTable[64] =
-{
- 98,-127,-43,88,102,41,-65,-94,125,20,-71,-86,-70,-32,-16,-96,
- 17,72,107,-5,116,-69,-62,-40,10,-61,65,109,-18,-38,-13,-76,
- -23,88,21,-94,8,106,21,-112,6,109,20,-88,-30,9,-127,118,
- 42,-34,89,-4,-51,-72,21,-29,112,123,84,-101,-92,98,-54,-95
-};
-
-
-// volume fade tables for Retrig Note:
-signed char retrigTable1[16] =
-{ 0, 0, 0, 0, 0, 0, 10, 8, 0, 0, 0, 0, 0, 0, 24, 32 };
-
-signed char retrigTable2[16] =
-{ 0, -1, -2, -4, -8, -16, 0, 0, 0, 1, 2, 4, 8, 16, 0, 0 };
-
-
-
-
-WORD XMPeriodTable[104] =
-{
- 907,900,894,887,881,875,868,862,856,850,844,838,832,826,820,814,
- 808,802,796,791,785,779,774,768,762,757,752,746,741,736,730,725,
- 720,715,709,704,699,694,689,684,678,675,670,665,660,655,651,646,
- 640,636,632,628,623,619,614,610,604,601,597,592,588,584,580,575,
- 570,567,563,559,555,551,547,543,538,535,532,528,524,520,516,513,
- 508,505,502,498,494,491,487,484,480,477,474,470,467,463,460,457,
- 453,450,447,443,440,437,434,431
-};
-
-
-UINT XMLinearTable[768] =
-{
- 535232,534749,534266,533784,533303,532822,532341,531861,
- 531381,530902,530423,529944,529466,528988,528511,528034,
- 527558,527082,526607,526131,525657,525183,524709,524236,
- 523763,523290,522818,522346,521875,521404,520934,520464,
- 519994,519525,519057,518588,518121,517653,517186,516720,
- 516253,515788,515322,514858,514393,513929,513465,513002,
- 512539,512077,511615,511154,510692,510232,509771,509312,
- 508852,508393,507934,507476,507018,506561,506104,505647,
- 505191,504735,504280,503825,503371,502917,502463,502010,
- 501557,501104,500652,500201,499749,499298,498848,498398,
- 497948,497499,497050,496602,496154,495706,495259,494812,
- 494366,493920,493474,493029,492585,492140,491696,491253,
- 490809,490367,489924,489482,489041,488600,488159,487718,
- 487278,486839,486400,485961,485522,485084,484647,484210,
- 483773,483336,482900,482465,482029,481595,481160,480726,
- 480292,479859,479426,478994,478562,478130,477699,477268,
- 476837,476407,475977,475548,475119,474690,474262,473834,
- 473407,472979,472553,472126,471701,471275,470850,470425,
- 470001,469577,469153,468730,468307,467884,467462,467041,
- 466619,466198,465778,465358,464938,464518,464099,463681,
- 463262,462844,462427,462010,461593,461177,460760,460345,
- 459930,459515,459100,458686,458272,457859,457446,457033,
- 456621,456209,455797,455386,454975,454565,454155,453745,
- 453336,452927,452518,452110,451702,451294,450887,450481,
- 450074,449668,449262,448857,448452,448048,447644,447240,
- 446836,446433,446030,445628,445226,444824,444423,444022,
- 443622,443221,442821,442422,442023,441624,441226,440828,
- 440430,440033,439636,439239,438843,438447,438051,437656,
- 437261,436867,436473,436079,435686,435293,434900,434508,
- 434116,433724,433333,432942,432551,432161,431771,431382,
- 430992,430604,430215,429827,429439,429052,428665,428278,
- 427892,427506,427120,426735,426350,425965,425581,425197,
- 424813,424430,424047,423665,423283,422901,422519,422138,
- 421757,421377,420997,420617,420237,419858,419479,419101,
- 418723,418345,417968,417591,417214,416838,416462,416086,
- 415711,415336,414961,414586,414212,413839,413465,413092,
- 412720,412347,411975,411604,411232,410862,410491,410121,
- 409751,409381,409012,408643,408274,407906,407538,407170,
- 406803,406436,406069,405703,405337,404971,404606,404241,
- 403876,403512,403148,402784,402421,402058,401695,401333,
- 400970,400609,400247,399886,399525,399165,398805,398445,
- 398086,397727,397368,397009,396651,396293,395936,395579,
- 395222,394865,394509,394153,393798,393442,393087,392733,
- 392378,392024,391671,391317,390964,390612,390259,389907,
- 389556,389204,388853,388502,388152,387802,387452,387102,
- 386753,386404,386056,385707,385359,385012,384664,384317,
- 383971,383624,383278,382932,382587,382242,381897,381552,
- 381208,380864,380521,380177,379834,379492,379149,378807,
-
- 378466,378124,377783,377442,377102,376762,376422,376082,
- 375743,375404,375065,374727,374389,374051,373714,373377,
- 373040,372703,372367,372031,371695,371360,371025,370690,
- 370356,370022,369688,369355,369021,368688,368356,368023,
- 367691,367360,367028,366697,366366,366036,365706,365376,
- 365046,364717,364388,364059,363731,363403,363075,362747,
- 362420,362093,361766,361440,361114,360788,360463,360137,
- 359813,359488,359164,358840,358516,358193,357869,357547,
- 357224,356902,356580,356258,355937,355616,355295,354974,
- 354654,354334,354014,353695,353376,353057,352739,352420,
- 352103,351785,351468,351150,350834,350517,350201,349885,
- 349569,349254,348939,348624,348310,347995,347682,347368,
- 347055,346741,346429,346116,345804,345492,345180,344869,
- 344558,344247,343936,343626,343316,343006,342697,342388,
- 342079,341770,341462,341154,340846,340539,340231,339924,
- 339618,339311,339005,338700,338394,338089,337784,337479,
- 337175,336870,336566,336263,335959,335656,335354,335051,
- 334749,334447,334145,333844,333542,333242,332941,332641,
- 332341,332041,331741,331442,331143,330844,330546,330247,
- 329950,329652,329355,329057,328761,328464,328168,327872,
- 327576,327280,326985,326690,326395,326101,325807,325513,
- 325219,324926,324633,324340,324047,323755,323463,323171,
- 322879,322588,322297,322006,321716,321426,321136,320846,
- 320557,320267,319978,319690,319401,319113,318825,318538,
- 318250,317963,317676,317390,317103,316817,316532,316246,
- 315961,315676,315391,315106,314822,314538,314254,313971,
- 313688,313405,313122,312839,312557,312275,311994,311712,
- 311431,311150,310869,310589,310309,310029,309749,309470,
- 309190,308911,308633,308354,308076,307798,307521,307243,
- 306966,306689,306412,306136,305860,305584,305308,305033,
- 304758,304483,304208,303934,303659,303385,303112,302838,
- 302565,302292,302019,301747,301475,301203,300931,300660,
- 300388,300117,299847,299576,299306,299036,298766,298497,
- 298227,297958,297689,297421,297153,296884,296617,296349,
- 296082,295815,295548,295281,295015,294749,294483,294217,
- 293952,293686,293421,293157,292892,292628,292364,292100,
- 291837,291574,291311,291048,290785,290523,290261,289999,
- 289737,289476,289215,288954,288693,288433,288173,287913,
- 287653,287393,287134,286875,286616,286358,286099,285841,
- 285583,285326,285068,284811,284554,284298,284041,283785,
- 283529,283273,283017,282762,282507,282252,281998,281743,
- 281489,281235,280981,280728,280475,280222,279969,279716,
- 279464,279212,278960,278708,278457,278206,277955,277704,
- 277453,277203,276953,276703,276453,276204,275955,275706,
- 275457,275209,274960,274712,274465,274217,273970,273722,
- 273476,273229,272982,272736,272490,272244,271999,271753,
- 271508,271263,271018,270774,270530,270286,270042,269798,
- 269555,269312,269069,268826,268583,268341,268099,267857
-};
-
-
-signed char ft2VibratoTable[256] =
-{
- 0,-2,-3,-5,-6,-8,-9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
- -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,
- -43,-44,-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,
- -56,-57,-58,-59,-59,-60,-60,-61,-61,-62,-62,-62,-63,-63,
- -63,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-63,-63,
- -63,-62,-62,-62,-61,-61,-60,-60,-59,-59,-58,-57,-56,-56,
- -55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42,
- -41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,-24,-23,
- -22,-20,-19,-17,-16,-14,-12,-11,-9,-8,-6,-5,-3,-2,0,
- 2,3,5,6,8,9,11,12,14,16,17,19,20,22,23,24,26,27,29,30,
- 32,33,34,36,37,38,39,41,42,43,44,45,46,47,48,49,50,51,
- 52,53,54,55,56,56,57,58,59,59,60,60,61,61,62,62,62,63,
- 63,63,64,64,64,64,64,64,64,64,64,64,64,63,63,63,62,62,
- 62,61,61,60,60,59,59,58,57,56,56,55,54,53,52,51,50,49,
- 48,47,46,45,44,43,42,41,39,38,37,36,34,33,32,30,29,27,
- 26,24,23,22,20,19,17,16,14,12,11,9,8,6,5,3,2
-};
-
-
-
-DWORD FineLinearSlideUpTable[16] =
-{
- 65536, 65595, 65654, 65714, 65773, 65832, 65892, 65951,
- 66011, 66071, 66130, 66190, 66250, 66309, 66369, 66429
-};
-
-
-DWORD FineLinearSlideDownTable[16] =
-{
- 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65123,
- 65065, 65006, 64947, 64888, 64830, 64772, 64713, 64645
-};
-
-
-DWORD LinearSlideUpTable[256] =
-{
- 65536, 65773, 66010, 66249, 66489, 66729, 66971, 67213,
- 67456, 67700, 67945, 68190, 68437, 68685, 68933, 69182,
- 69432, 69684, 69936, 70189, 70442, 70697, 70953, 71209,
- 71467, 71725, 71985, 72245, 72507, 72769, 73032, 73296,
- 73561, 73827, 74094, 74362, 74631, 74901, 75172, 75444,
- 75717, 75991, 76265, 76541, 76818, 77096, 77375, 77655,
- 77935, 78217, 78500, 78784, 79069, 79355, 79642, 79930,
- 80219, 80509, 80800, 81093, 81386, 81680, 81976, 82272,
- 82570, 82868, 83168, 83469, 83771, 84074, 84378, 84683,
- 84989, 85297, 85605, 85915, 86225, 86537, 86850, 87164,
- 87480, 87796, 88113, 88432, 88752, 89073, 89395, 89718,
- 90043, 90369, 90695, 91023, 91353, 91683, 92015, 92347,
- 92681, 93017, 93353, 93691, 94029, 94370, 94711, 95053,
- 95397, 95742, 96088, 96436, 96785, 97135, 97486, 97839,
- 98193, 98548, 98904, 99262, 99621, 99981, 100343, 100706,
- 101070, 101435, 101802, 102170, 102540, 102911, 103283, 103657,
- 104031, 104408, 104785, 105164, 105545, 105926, 106309, 106694,
- 107080, 107467, 107856, 108246, 108637, 109030, 109425, 109820,
- 110217, 110616, 111016, 111418, 111821, 112225, 112631, 113038,
- 113447, 113857, 114269, 114682, 115097, 115514, 115931, 116351,
- 116771, 117194, 117618, 118043, 118470, 118898, 119328, 119760,
- 120193, 120628, 121064, 121502, 121941, 122382, 122825, 123269,
- 123715, 124162, 124611, 125062, 125514, 125968, 126424, 126881,
- 127340, 127801, 128263, 128727, 129192, 129660, 130129, 130599,
- 131072, 131546, 132021, 132499, 132978, 133459, 133942, 134426,
- 134912, 135400, 135890, 136381, 136875, 137370, 137866, 138365,
- 138865, 139368, 139872, 140378, 140885, 141395, 141906, 142419,
- 142935, 143451, 143970, 144491, 145014, 145538, 146064, 146593,
- 147123, 147655, 148189, 148725, 149263, 149803, 150344, 150888,
- 151434, 151982, 152531, 153083, 153637, 154192, 154750, 155310,
- 155871, 156435, 157001, 157569, 158138, 158710, 159284, 159860,
- 160439, 161019, 161601, 162186, 162772, 163361, 163952, 164545,
-};
-
-
-DWORD LinearSlideDownTable[256] =
-{
- 65536, 65299, 65064, 64830, 64596, 64363, 64131, 63900,
- 63670, 63440, 63212, 62984, 62757, 62531, 62305, 62081,
- 61857, 61634, 61412, 61191, 60970, 60751, 60532, 60314,
- 60096, 59880, 59664, 59449, 59235, 59021, 58809, 58597,
- 58385, 58175, 57965, 57757, 57548, 57341, 57134, 56928,
- 56723, 56519, 56315, 56112, 55910, 55709, 55508, 55308,
- 55108, 54910, 54712, 54515, 54318, 54123, 53928, 53733,
-
- 53540, 53347, 53154, 52963, 52772, 52582, 52392, 52204,
- 52015, 51828, 51641, 51455, 51270, 51085, 50901, 50717,
- 50535, 50353, 50171, 49990, 49810, 49631, 49452, 49274,
- 49096, 48919, 48743, 48567, 48392, 48218, 48044, 47871,
- 47698, 47526, 47355, 47185, 47014, 46845, 46676, 46508,
- 46340, 46173, 46007, 45841, 45676, 45511, 45347, 45184,
- 45021, 44859, 44697, 44536, 44376, 44216, 44056, 43898,
- 43740, 43582, 43425, 43268, 43112, 42957, 42802, 42648,
- 42494, 42341, 42189, 42037, 41885, 41734, 41584, 41434,
- 41285, 41136, 40988, 40840, 40693, 40546, 40400, 40254,
- 40109, 39965, 39821, 39677, 39534, 39392, 39250, 39108,
- 38967, 38827, 38687, 38548, 38409, 38270, 38132, 37995,
- 37858, 37722, 37586, 37450, 37315, 37181, 37047, 36913,
- 36780, 36648, 36516, 36384, 36253, 36122, 35992, 35862,
- 35733, 35604, 35476, 35348, 35221, 35094, 34968, 34842,
- 34716, 34591, 34466, 34342, 34218, 34095, 33972, 33850,
- 33728, 33606, 33485, 33364, 33244, 33124, 33005, 32886,
- 32768, 32649, 32532, 32415, 32298, 32181, 32065, 31950,
- 31835, 31720, 31606, 31492, 31378, 31265, 31152, 31040,
- 30928, 30817, 30706, 30595, 30485, 30375, 30266, 30157,
- 30048, 29940, 29832, 29724, 29617, 29510, 29404, 29298,
- 29192, 29087, 28982, 28878, 28774, 28670, 28567, 28464,
- 28361, 28259, 28157, 28056, 27955, 27854, 27754, 27654,
- 27554, 27455, 27356, 27257, 27159, 27061, 26964, 26866,
- 26770, 26673, 26577, 26481, 26386, 26291, 26196, 26102,
-};
-
-
-int SpectrumSinusTable[256*2] =
-{
- 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11,
- 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23,
- 24, 25, 25, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 34,
- 35, 36, 36, 37, 38, 38, 39, 39, 40, 41, 41, 42, 42, 43, 44, 44,
- 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 52, 52,
- 53, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 57, 58, 58, 58,
- 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 61, 62, 62, 62,
- 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62,
- 62, 62, 62, 62, 61, 61, 61, 61, 61, 60, 60, 60, 60, 59, 59, 59,
- 59, 58, 58, 58, 57, 57, 57, 56, 56, 55, 55, 55, 54, 54, 53, 53,
- 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45,
- 45, 44, 44, 43, 42, 42, 41, 41, 40, 39, 39, 38, 38, 37, 36, 36,
- 35, 34, 34, 33, 32, 32, 31, 30, 30, 29, 28, 28, 27, 26, 25, 25,
- 24, 23, 22, 22, 21, 20, 20, 19, 18, 17, 17, 16, 15, 14, 14, 13,
- 12, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 3, 3, 2, 1, 0,
- 0, -1, -1, -2, -3, -3, -4, -5, -6, -7, -7, -8, -9, -10, -10, -11,
- -12, -13, -14, -14, -15, -16, -17, -17, -18, -19, -20, -20, -21, -22, -22, -23,
- -24, -25, -25, -26, -27, -28, -28, -29, -30, -30, -31, -32, -32, -33, -34, -34,
- -35, -36, -36, -37, -38, -38, -39, -39, -40, -41, -41, -42, -42, -43, -44, -44,
- -45, -45, -46, -46, -47, -47, -48, -48, -49, -49, -50, -50, -51, -51, -52, -52,
- -53, -53, -53, -54, -54, -55, -55, -55, -56, -56, -57, -57, -57, -58, -58, -58,
- -59, -59, -59, -59, -60, -60, -60, -60, -61, -61, -61, -61, -61, -62, -62, -62,
- -62, -62, -62, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63,
- -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -63, -62, -62,
- -62, -62, -62, -62, -61, -61, -61, -61, -61, -60, -60, -60, -60, -59, -59, -59,
- -59, -58, -58, -58, -57, -57, -57, -56, -56, -55, -55, -55, -54, -54, -53, -53,
- -53, -52, -52, -51, -51, -50, -50, -49, -49, -48, -48, -47, -47, -46, -46, -45,
- -45, -44, -44, -43, -42, -42, -41, -41, -40, -39, -39, -38, -38, -37, -36, -36,
- -35, -34, -34, -33, -32, -32, -31, -30, -30, -29, -28, -28, -27, -26, -25, -25,
- -24, -23, -22, -22, -21, -20, -20, -19, -18, -17, -17, -16, -15, -14, -14, -13,
- -12, -11, -10, -10, -9, -8, -7, -7, -6, -5, -4, -3, -3, -2, -1, 0,
-};
-
+++ /dev/null
-tables.o: tables.cpp stdafx.h /usr/include/stdlib.h \
- /usr/include/features.h /usr/include/sys/cdefs.h \
- /usr/include/gnu/stubs.h \
- /usr/lib/gcc-lib/i386-linux/2.95.4/include/stddef.h \
- /usr/include/sys/types.h /usr/include/bits/types.h \
- /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h \
- /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
- /usr/include/sys/select.h /usr/include/bits/select.h \
- /usr/include/bits/sigset.h /usr/include/bits/time.h \
- /usr/include/sys/sysmacros.h /usr/include/alloca.h \
- /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
- /usr/include/wchar.h /usr/include/bits/wchar.h /usr/include/gconv.h \
- /usr/lib/gcc-lib/i386-linux/2.95.4/include/stdarg.h \
- /usr/include/bits/stdio_lim.h /usr/include/bits/stdio.h \
- /usr/include/string.h sndfile.h ../../../config.h