[audacious-plugins] Merge changes from pre-3.0.3 git, such as using libmodplug system library (BR libmodplug-devel).
Michael Schwendt
mschwendt at fedoraproject.org
Thu Sep 8 14:58:04 UTC 2011
commit dd0c7012b5bfbf0f7c98eb7ce566ca5935181444
Author: Michael Schwendt <mschwendt at fedoraproject.org>
Date: Thu Sep 8 16:57:46 2011 +0200
Merge changes from pre-3.0.3 git, such as using libmodplug system
library (BR libmodplug-devel).
audacious-plugins-3.0.2-pre3.0.3.patch |20106 ++++++++++++++++++++++++++++++++
audacious-plugins.spec | 14 +-
2 files changed, 20118 insertions(+), 2 deletions(-)
---
diff --git a/audacious-plugins-3.0.2-pre3.0.3.patch b/audacious-plugins-3.0.2-pre3.0.3.patch
new file mode 100644
index 0000000..a841bbc
--- /dev/null
+++ b/audacious-plugins-3.0.2-pre3.0.3.patch
@@ -0,0 +1,20106 @@
+diff -Nur audacious-plugins-3.0.2/aclocal.m4 3.0.3/aclocal.m4
+diff -Nur audacious-plugins-3.0.2/config.h.in 3.0.3/config.h.in
+diff -Nur audacious-plugins-3.0.2/configure 3.0.3/configure
+diff -Nur audacious-plugins-3.0.2/configure.ac 3.0.3/configure.ac
+--- audacious-plugins-3.0.2/configure.ac 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/configure.ac 2011-09-07 22:45:40.000000000 +0200
+@@ -763,17 +763,11 @@
+ )
+
+ if test $enable_modplug = yes ; then
+- AC_CHECK_HEADERS([sys/mman.h], [enable_modplug=yes],
+- [AC_MSG_WARN([Cannot find sys/mman.h; disabling ModPlug plugin])
+- enable_modplug=no])
+-fi
+-
+-if test "x$enable_modplug" = "xyes"; then
+- INPUT_PLUGINS="$INPUT_PLUGINS modplug"
+- have_modplug="yes"
+-else
+- AC_MSG_RESULT([*** ModPlug plugin disabled per user request ***])
+- have_modplug="no"
++ PKG_CHECK_MODULES(MODPLUG, libmodplug,
++ [INPUT_PLUGINS="$INPUT_PLUGINS modplug"
++ have_modplug=yes],
++ [AC_MSG_WARN([*** Cannot find libmodplug; modplug plugin disabled ***])
++ have_modplug=no])
+ fi
+
+ dnl *** FFaudio
+diff -Nur audacious-plugins-3.0.2/extra.mk.in 3.0.3/extra.mk.in
+--- audacious-plugins-3.0.2/extra.mk.in 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/extra.mk.in 2011-09-07 22:45:40.000000000 +0200
+@@ -219,6 +219,8 @@
+ LTLIBOBJS ?= @LTLIBOBJS@
+ MAKEINFO ?= @MAKEINFO@
+ MKINSTALLDIRS ?= @MKINSTALLDIRS@
++MODPLUG_CFLAGS ?= @MODPLUG_CFLAGS@
++MODPLUG_LIBS ?= @MODPLUG_LIBS@
+ MSGFMT ?= @MSGFMT@
+ MSGMERGE ?= @MSGMERGE@
+ MTP_CFLAGS ?= @MTP_CFLAGS@
+@@ -247,8 +249,8 @@
+ PKG_CONFIG ?= @PKG_CONFIG@
+ PLUGIN_LDFLAGS ?= @PLUGIN_LDFLAGS@
+ POSUB ?= @POSUB@
+-PTHREAD_CFLAGS ?= @PTHREAD_CFLAGS@
+-PTHREAD_LIBS ?= @PTHREAD_LIBS@
++PTHREAD_CFLAGS ?= @PTHREAD_CFLAGS@
++PTHREAD_LIBS ?= @PTHREAD_LIBS@
+ RANLIB ?= @RANLIB@
+ RESID_LIBS ?= @RESID_LIBS@
+ SAMPLERATE_CFLAGS ?= @SAMPLERATE_CFLAGS@
+diff -Nur audacious-plugins-3.0.2/po/de.po 3.0.3/po/de.po
+diff -Nur audacious-plugins-3.0.2/src/cairo-spectrum/Makefile 3.0.3/src/cairo-spectrum/Makefile
+diff -Nur audacious-plugins-3.0.2/src/ffaudio/ffaudio-core.c 3.0.3/src/ffaudio/ffaudio-core.c
+diff -Nur audacious-plugins-3.0.2/src/gtkui/layout.c 3.0.3/src/gtkui/layout.c
+--- audacious-plugins-3.0.2/src/gtkui/layout.c 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/gtkui/layout.c 2011-09-07 22:45:40.000000000 +0200
+@@ -304,22 +304,6 @@
+ g_object_get_data ((GObject *) docks[item->dock], "mine");
+ }
+
+-static void item_save_size (Item * item)
+-{
+- g_return_if_fail (item->widget && item->vbox);
+-
+- GtkAllocation rect;
+- gtk_widget_get_allocation (item->vbox, & rect);
+- item->w = rect.width;
+- item->h = rect.height;
+-
+- if (item->dock < 0)
+- {
+- g_return_if_fail (item->window);
+- gtk_window_get_position ((GtkWindow *) item->window, & item->x, & item->y);
+- }
+-}
+-
+ static void item_add (Item * item)
+ {
+ g_return_if_fail (item->name && item->widget && item->vbox && ! item->paned
+@@ -360,7 +344,6 @@
+ swap = TRUE;
+ where = item_get_prev (item);
+ g_return_if_fail (where && ! where->paned);
+- item_save_size (where);
+ }
+
+ parent = item_get_parent (where);
+@@ -400,8 +383,6 @@
+ {
+ g_return_if_fail (item->widget && item->vbox);
+
+- item_save_size (item);
+-
+ if (item->dock < 0)
+ {
+ g_return_if_fail (item->window);
+@@ -453,6 +434,12 @@
+ }
+ }
+
++static void size_changed_cb (GtkWidget * widget, GdkRectangle * rect, Item * item)
++{
++ item->w = rect->width;
++ item->h = rect->height;
++}
++
+ void layout_add (GtkWidget * widget, const gchar * name)
+ {
+ g_return_if_fail (layout && center && widget && name && strlen (name) <= 256
+@@ -475,6 +462,8 @@
+ item->vbox = vbox_new (widget, name);
+ NULL_ON_DESTROY (item->vbox);
+
++ g_signal_connect (item->vbox, "size-allocate", (GCallback) size_changed_cb, item);
++
+ item_add (item);
+ }
+
+@@ -529,9 +518,6 @@
+ Item * item = node->data;
+ g_return_if_fail (item && item->name);
+
+- if (item->widget)
+- item_save_size (item);
+-
+ fprintf (handle, "item %s\npane %d\nx %d\ny %d\nw %d\nh %d\n",
+ item->name, item->dock, item->x, item->y, item->w, item->h);
+ }
+diff -Nur audacious-plugins-3.0.2/src/gtkui/Makefile 3.0.3/src/gtkui/Makefile
+diff -Nur audacious-plugins-3.0.2/src/hotkey/plugin.c 3.0.3/src/hotkey/plugin.c
+--- audacious-plugins-3.0.2/src/hotkey/plugin.c 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/hotkey/plugin.c 2011-09-07 22:45:40.000000000 +0200
+@@ -47,6 +47,7 @@
+ #include <audacious/i18n.h>
+ #include <audacious/plugin.h>
+ #include <libaudcore/hook.h>
++#include <libaudcore/eventqueue.h>
+
+ #include "plugin.h"
+ #include "gui.h"
+@@ -239,7 +240,11 @@
+ /* Toggle Windows */
+ if (event == EVENT_TOGGLE_WIN)
+ {
+- hook_call ("interface toggle visibility", NULL);
++ /* Workaround for AUD-369:
++ * When a hotkey is pressed, the interface temporarily loses keyboard
++ * focus. This causes "interface toggle visibility" to raise the window
++ * when it ought to hide it. The 1/10 second delay prevents this. */
++ event_queue_timed (100, "interface toggle visibility", NULL);
+ return TRUE;
+ }
+
+diff -Nur audacious-plugins-3.0.2/src/modplug/fastmix.cxx 3.0.3/src/modplug/fastmix.cxx
+--- audacious-plugins-3.0.2/src/modplug/fastmix.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/fastmix.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,1852 +0,0 @@
+-/*
+- * This program is free software; you can redistribute it and modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the license or (at your
+- * option) any later version.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+- * Markus Fick <webmaster at mark-f.de> spline + fir-resampler
+-*/
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-#include <math.h>
+-
+-// Front Mix Buffer (Also room for interleaved rear mix)
+-int MixSoundBuffer[MIXBUFFERSIZE*4];
+-
+-// Reverb Mix Buffer
+-#ifndef MODPLUG_NO_REVERB
+-int MixReverbBuffer[MIXBUFFERSIZE*2];
+-extern UINT gnReverbSend;
+-#endif
+-
+-int MixRearBuffer[MIXBUFFERSIZE*2];
+-float MixFloatBuffer[MIXBUFFERSIZE*2];
+-
+-
+-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 \
+- double fy1 = pChannel->nFilter_Y1;\
+- double fy2 = pChannel->nFilter_Y2;\
+- double ta;
+-
+-#define MIX_END_FILTER \
+- pChannel->nFilter_Y1 = fy1;\
+- pChannel->nFilter_Y2 = fy2;
+-
+-#define SNDMIX_PROCESSFILTER \
+-ta = ((double)vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
+-fy2 = fy1;\
+-fy1 = ta;vol=(int)ta;
+-
+-// Stereo
+-#define MIX_BEGIN_STEREO_FILTER \
+-double fy1 = pChannel->nFilter_Y1;\
+-double fy2 = pChannel->nFilter_Y2;\
+-double fy3 = pChannel->nFilter_Y3;\
+-double fy4 = pChannel->nFilter_Y4;\
+-double ta, tb;
+-
+-#define MIX_END_STEREO_FILTER \
+-pChannel->nFilter_Y1 = fy1;\
+-pChannel->nFilter_Y2 = fy2;\
+-pChannel->nFilter_Y3 = fy3;\
+-pChannel->nFilter_Y4 = fy4;\
+-
+-#define SNDMIX_PROCESSSTEREOFILTER \
+-ta = ((double)vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
+-tb = ((double)vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1);\
+-fy2 = fy1; fy1 = ta;vol_l=(int)ta;\
+-fy4 = fy3; fy3 = tb;vol_r=(int)tb;
+-
+-//////////////////////////////////////////////////////////
+-// 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;\
+- }
+-
+-
+-/////////////////////////////////////////////////////
+-//
+-
+-extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc);
+-extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic);
+-extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc);
+-extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic);
+-
+-void InitMixBuffer(int *pBuffer, UINT nSamples);
+-void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
+-void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+-
+-void StereoMixToFloat(const int *, float *, float *, UINT nCount);
+-void 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;
+- if (gnChannels > 2) InitMixBuffer(MixRearBuffer, count*2);
+- nchused = nchmixed = 0;
+- for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
+- {
+- const LPMIXINTERFACE *pMixFuncTable;
+- MODCHANNEL * const pChannel = &Chn[ChnMix[nChn]];
+- UINT nFlags;
+- LONG nSmpCount;
+- int nsamples;
+- int *pbuffer;
+-
+- if (!pChannel->pCurrentSample) continue;
+- 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)
+- && !(gdwSoundSetup & SNDMIX_NORESAMPLING))
+- {
+- // use hq-fir mixer?
+- if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
+- nFlags |= MIXNDX_FIRSRC;
+- else if( (gdwSoundSetup & 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 MODPLUG_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;
+- 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
+- {
+- if (pChannel->nLength) {
+- pChannel->topnote_offset = ((pChannel->nPos << 16) | pChannel->nPosLo) % pChannel->nLength;
+- }
+-
+- // 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;
+-}
+-
+-static float f2ic = (float)(1 << 28);
+-static float i2fc = (float)(1.0 / (1 << 28));
+-
+-VOID CSoundFile::StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount)
+-//-----------------------------------------------------------------------------------------
+-{
+- for (UINT i = 0; i < nCount; i++) {
+- *pOut1++ = *pSrc * i2fc; /*!*/
+- pSrc++;
+-
+- *pOut2++ = *pSrc * i2fc; /*!*/
+- pSrc++;
+- }
+-}
+-
+-
+-VOID CSoundFile::FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount)
+-//---------------------------------------------------------------------------------------------
+-{
+- for (UINT i = 0; i < nCount; i++) {
+- *pOut++ = (int)(*pIn1 * f2ic);
+- *pOut++ = (int)(*pIn2 * f2ic);
+- pIn1++;
+- pIn2++;
+- }
+-}
+-
+-
+-VOID CSoundFile::MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount)
+-//------------------------------------------------------------------------
+-{
+- for (UINT i = 0; i < nCount; i++) {
+- *pOut++ = *pSrc * i2fc; /*!*/
+- pSrc++;
+- }
+-}
+-
+-
+-VOID CSoundFile::FloatToMonoMix(const float *pIn, int *pOut, UINT nCount)
+-//-----------------------------------------------------------------------
+-{
+- for (UINT i = 0; i < nCount; i++) {
+- *pOut++ = (int)(*pIn * f2ic); /*!*/
+- pIn++;
+- }
+-}
+-
+-
+-// Clip and convert to 8 bit
+-//---GCCFIX: Asm replaced with C function
+-// The C version was written by Rani Assaf <rani at magic.metawire.com>, I believe
+-DWORD Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+-{
+- 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 < mins[i&1])
+- mins[i&1]= n;
+- else if (n > maxs[i&1])
+- maxs[i&1] = n;
+- p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80; // 8-bit unsigned
+- }
+- return lSampleCount;
+-}
+-//---GCCFIX: Asm replaced with C function
+-// The C version was written by Rani Assaf <rani at magic.metawire.com>, I believe
+-DWORD Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+-{
+- 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 < mins[i&1])
+- mins[i&1]= n;
+- else if (n > maxs[i&1])
+- maxs[i&1] = n;
+- p[i] = n >> (16-MIXING_ATTENUATION); // 16-bit signed
+- }
+- return lSampleCount * 2;
+-}
+-//---GCCFIX: Asm replaced with C function
+-// 24-bit might not work...
+-DWORD Convert32To24(LPVOID lp24, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+-{
+- /* the inventor of 24bit anything should be shot */
+- unsigned char *p = (unsigned char *)lp24;
+- 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 < mins[i&1])
+- mins[i&1]= n;
+- else if (n > maxs[i&1])
+- maxs[i&1] = n;
+- n = n >> (8-MIXING_ATTENUATION); // 24-bit signed
+- /* err, assume same endian */
+- memcpy(p, &n, 3);
+- p += 3;
+- }
+- return lSampleCount * 2;
+-}
+-//---GCCFIX: Asm replaced with C function
+-// 32-bit might not work...
+-DWORD Convert32To32(LPVOID lp32, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+-{
+- signed int *p = (signed int *)lp32;
+- 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 < mins[i&1])
+- mins[i&1]= n;
+- else if (n > maxs[i&1])
+- maxs[i&1] = n;
+- p[i] = (n >> MIXING_ATTENUATION); // 32-bit signed
+- }
+- return lSampleCount * 2;
+-}
+-//---GCCFIX: Asm replaced with C function
+-// Will fill in later.
+-void InitMixBuffer(int *pBuffer, UINT nSamples)
+-{
+- memset(pBuffer, 0, nSamples * sizeof(int));
+-}
+-
+-//---GCCFIX: Asm replaced with C function
+-void InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
+-{
+- DWORD i=0;
+-
+- pRearBuf[i] = pFrontBuf[1];
+- for (i = 1; i < nSamples; i++) {
+- pRearBuf[i] = pFrontBuf[(i*2)+1];
+- pFrontBuf[i] = pFrontBuf[i*2];
+- }
+-}
+-//---GCCFIX: Asm replaced with C function
+-VOID 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;
+- }
+-}
+-
+-//---GCCFIX: Asm replaced with C function
+-#define OFSDECAYSHIFT 8
+-#define OFSDECAYMASK 0xFF
+-void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
+-//---------------------------------------------------------------------------------------------------------
+-{
+- int rofs = *lpROfs;
+- int lofs = *lpLOfs;
+-
+- if ((!rofs) && (!lofs))
+- {
+- 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;
+-}
+-//---GCCFIX: Asm replaced with C function
+-// Will fill in later.
+-void 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;
+-}
+-
+-
+-
+-
+-
+-//////////////////////////////////////////////////////////////////////////////////
+-// Automatic Gain Control
+-
+-#ifndef NO_AGC
+-
+-// Limiter
+-#define MIXING_LIMITMAX (0x08100000)
+-#define MIXING_LIMITMIN (-MIXING_LIMITMAX)
+-
+-void CSoundFile::ProcessAGC(int count)
+-//------------------------------------
+-{
+- static DWORD gAGCRecoverCount = 0;
+- UINT agc = 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
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/it_defs.h 3.0.3/src/modplug/it_defs.h
+--- audacious-plugins-3.0.2/src/modplug/it_defs.h 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/it_defs.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,135 +0,0 @@
+-#ifndef _ITDEFS_H_
+-#define _ITDEFS_H_
+-
+-#pragma pack(1)
+-
+-typedef struct tagITFILEHEADER
+-{
+- DWORD id; // 0x4D504D49
+- CHAR songname[26];
+- BYTE hilight_minor;
+- BYTE hilight_major;
+- 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 pwd;
+- 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
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_669.cxx 3.0.3/src/modplug/load_669.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_669.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_669.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,193 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-////////////////////////////////////////////////////////////
+-// 669 Composer / UNIS 669 module loader
+-////////////////////////////////////////////////////////////
+-
+-#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;
+-
+-DWORD lengthArrayToDWORD(const BYTE length[4]) {
+- DWORD len = (length[3] << 24) +
+- (length[2] << 16) +
+- (length[1] << 8) +
+- (length[0]);
+-
+- return(len);
+-}
+-
+-
+-BOOL CSoundFile::Read669(const BYTE *lpStream, DWORD dwMemLength)
+-//---------------------------------------------------------------
+-{
+- 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;
+- 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 = lengthArrayToDWORD(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 = lengthArrayToDWORD(psmp->length);
+- DWORD loopstart = lengthArrayToDWORD(psmp->loopstart);
+- DWORD loopend = lengthArrayToDWORD(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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_amf.cxx 3.0.3/src/modplug/load_amf.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_amf.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_amf.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,422 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-///////////////////////////////////////////////////
+-//
+-// AMF module loader
+-//
+-// There is 2 types of AMF files:
+-// - ASYLUM Music Format
+-// - Advanced Music Format(DSM)
+-//
+-///////////////////////////////////////////////////
+-#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 = bswapLE16(*(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)) memcpy(m, &pPat[rowsrc*nChannels],sizeof(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)&0x7F; }
+- 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, const DWORD dwMemLength)
+-//-----------------------------------------------------------
+-{
+- const 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);
+- m_szNames[iSmp+1][21] = '\0';
+- 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 = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+25)));
+- psmp->nLoopStart = bswapLE32(*((LPDWORD)(lpStream+dwMemPos+29)));
+- psmp->nLoopEnd = psmp->nLoopStart + bswapLE32(*((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)
+- {
+- if (dwMemPos > dwMemLength) return FALSE;
+- dwMemPos += ReadSample(psmp, RS_PCM8S, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
+- }
+- }
+- 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) || (!bswapLE16(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);
+- m_szNames[0][31] = '\0';
+- 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] = bswapLE16(*(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);
+- m_szNames[iIns+1][31] = '\0';
+- memcpy(pins->name, psh->filename, 13);
+- pins->name[12] = '\0';
+- pins->nLength = bswapLE32(psh->length);
+- pins->nC4Speed = bswapLE16(psh->c2spd);
+- pins->nGlobalVol = 64;
+- pins->nVolume = psh->volume * 4;
+- if (pfh->version >= 11)
+- {
+- pins->nLoopStart = bswapLE32(*(DWORD *)(lpStream+dwMemPos));
+- pins->nLoopEnd = bswapLE32(*(DWORD *)(lpStream+dwMemPos+4));
+- dwMemPos += 8;
+- } else
+- {
+- pins->nLoopStart = bswapLE16(*(WORD *)(lpStream+dwMemPos));
+- pins->nLoopEnd = pins->nLength;
+- dwMemPos += 2;
+- }
+- sampleseekpos[iIns] = 0;
+- if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1))
+- {
+- sampleseekpos[iIns] = bswapLE32(psh->offset);
+- if (bswapLE32(psh->offset) > maxsampleseekpos)
+- maxsampleseekpos = bswapLE32(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 = bswapLE16(*(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 = bswapLE16(ptracks[iPat][iChn]);
+- if ((nTrack) && (nTrack <= pfh->numtracks))
+- {
+- UINT realtrk = bswapLE16(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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_ams.cxx 3.0.3/src/modplug/load_ams.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_ams.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_ams.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,629 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-//////////////////////////////////////////////
+-// AMS module loader //
+-//////////////////////////////////////////////
+-#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)
+-//-----------------------------------------------------------
+-{
+- 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;
+- }
+- // 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;
+- PatternAllocSize[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;
+- m_dwSongFlags |= SONG_INSTRUMENTMODE;
+- 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->VolEnv.nNodes = (volenv->points > 16) ? 16 : volenv->points;
+- penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = volenv->sustain;
+- penv->VolEnv.nLoopStart = volenv->loopbegin;
+- penv->VolEnv.nLoopEnd = volenv->loopend;
+- for (int i=0; i<penv->VolEnv.nNodes; i++)
+- {
+- penv->VolEnv.Values[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
+- pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
+- penv->VolEnv.Ticks[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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_dbm.cxx 3.0.3/src/modplug/load_dbm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_dbm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_dbm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,370 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-///////////////////////////////////////////////////////////////
+-//
+-// DigiBooster Pro Module Loader (*.dbm)
+-//
+-// Note: this loader doesn't handle multiple songs
+-//
+-///////////////////////////////////////////////////////////////
+-
+-#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 = 128;
+- 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;
+- }
+- m_dwSongFlags |= SONG_INSTRUMENTMODE;
+- } 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->VolEnv.nNodes = peh->numpoints + 1;
+- if (penv->VolEnv.nNodes > MAX_ENVPOINTS) penv->VolEnv.nNodes = MAX_ENVPOINTS;
+- penv->VolEnv.nLoopStart = peh->loopbegin;
+- penv->VolEnv.nLoopEnd = peh->loopend;
+- penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = peh->sustain1;
+- for (int i=0; i<penv->VolEnv.nNodes; i++)
+- {
+- penv->VolEnv.Ticks[i] = bswapBE16(peh->volenv[i*2]);
+- penv->VolEnv.Values[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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_dmf.cxx 3.0.3/src/modplug/load_dmf.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_dmf.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_dmf.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,607 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-///////////////////////////////////////////////////////
+-// DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) //
+-///////////////////////////////////////////////////////
+-#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;
+- PatternAllocSize[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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_dsm.cxx 3.0.3/src/modplug/load_dsm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_dsm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_dsm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,237 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-//////////////////////////////////////////////
+-// DSIK Internal Format (DSM) module loader //
+-//////////////////////////////////////////////
+-#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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_far.cxx 3.0.3/src/modplug/load_far.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_far.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_far.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,271 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-////////////////////////////////////////
+-// Farandole (FAR) module loader //
+-////////////////////////////////////////
+-#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) || (bswapLE32(pmh1->id) != FARFILEMAGIC)
+- || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
+- headerlen = bswapLE16(pmh1->headerlen);
+- pmh1->stlen = bswapLE16( pmh1->stlen ); /* inplace byteswap -- Toad */
+- 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;
+-
+- // byteswap pattern data -- Toad
+- UINT psfix = 0 ;
+- while( psfix++ < 256 )
+- {
+- pmh2->patsiz[psfix] = bswapLE16( pmh2->patsiz[psfix] ) ;
+- }
+- // end byteswap of pattern data
+-
+- 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;
+- PatternAllocSize[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);
+- pfs->length = bswapLE32( pfs->length ) ; /* endian fix - Toad */
+- pins->nLength = pfs->length ;
+- pins->nLoopStart = bswapLE32(pfs->reppos) ;
+- pins->nLoopEnd = bswapLE32(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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_it.cxx 3.0.3/src/modplug/load_it.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_it.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_it.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,975 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-#include "it_defs.h"
+-
+-/* blah, -mrsb.
+-this is a schism header */
+-#include "midi.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 = 128;
+- 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->VolEnv.nLoopStart = pis->vls;
+- penv->VolEnv.nLoopEnd = pis->vle;
+- penv->VolEnv.nSustainStart = pis->sls;
+- penv->VolEnv.nSustainEnd = pis->sle;
+- penv->VolEnv.nNodes = 25;
+- for (UINT ev=0; ev<25; ev++)
+- {
+- if ((penv->VolEnv.Ticks[ev] = pis->nodes[ev*2]) == 0xFF)
+- {
+- penv->VolEnv.nNodes = ev;
+- break;
+- }
+- penv->VolEnv.Values[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;
+- if (penv->nGlobalVol > 128) penv->nGlobalVol = 128;
+- 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->VolEnv.nNodes = pis->volenv.num;
+- if (penv->VolEnv.nNodes > 25) penv->VolEnv.nNodes = 25;
+-
+- penv->VolEnv.nLoopStart = pis->volenv.lpb;
+- penv->VolEnv.nLoopEnd = pis->volenv.lpe;
+- penv->VolEnv.nSustainStart = pis->volenv.slb;
+- penv->VolEnv.nSustainEnd = 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->PanEnv.nNodes = pis->panenv.num;
+- if (penv->PanEnv.nNodes > 25) penv->PanEnv.nNodes = 25;
+- penv->PanEnv.nLoopStart = pis->panenv.lpb;
+- penv->PanEnv.nLoopEnd = pis->panenv.lpe;
+- penv->PanEnv.nSustainStart = pis->panenv.slb;
+- penv->PanEnv.nSustainEnd = 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->PitchEnv.nNodes = pis->pitchenv.num;
+- if (penv->PitchEnv.nNodes > 25) penv->PitchEnv.nNodes = 25;
+- penv->PitchEnv.nLoopStart = pis->pitchenv.lpb;
+- penv->PitchEnv.nLoopEnd = pis->pitchenv.lpe;
+- penv->PitchEnv.nSustainStart = pis->pitchenv.slb;
+- penv->PitchEnv.nSustainEnd = pis->pitchenv.sle;
+- // Envelopes Data
+- for (UINT ev=0; ev<25; ev++)
+- {
+- penv->VolEnv.Values[ev] = pis->volenv.data[ev*3];
+- penv->VolEnv.Ticks[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
+- penv->PanEnv.Values[ev] = pis->panenv.data[ev*3] + 32;
+- penv->PanEnv.Ticks[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
+- penv->PitchEnv.Values[ev] = pis->pitchenv.data[ev*3] + 32;
+- penv->PitchEnv.Ticks[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
+- }
+- penv->nNNA = pis->nna % 4;
+- penv->nDCT = pis->dct % 4;
+- penv->nDNA = pis->dca % 3;
+- 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->VolEnv.nLoopStart >= 25) || (penv->VolEnv.nLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
+- if ((penv->VolEnv.nSustainStart >= 25) || (penv->VolEnv.nSustainEnd >= 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];
+- MODCOMMAND lastvalue[64];
+-
+- if ((!lpStream) || (dwMemLength < 0xc2)) return FALSE;
+-
+- pifh.id = bswapLE32(pifh.id);
+- if (pifh.id == 0x49504D49) {
+- if (dwMemLength < 554) return FALSE;
+-
+- WORD tv;
+- INSTRUMENTHEADER *zenv = new INSTRUMENTHEADER;
+- if (!zenv) return FALSE;
+- memset(zenv, 0, sizeof(INSTRUMENTHEADER));
+- memcpy(&tv, lpStream+0x1C, 2); /* trkvers */
+- if (!ITInstrToMPT(lpStream, zenv, tv)) {
+- delete zenv;
+- return FALSE;
+- }
+-
+- /* okay, we need samples now */
+- unsigned int q = 554;
+- BYTE expect_samples = lpStream[0x1E];
+-
+- m_nType = MOD_TYPE_IT;
+- m_nInstruments = 1;
+- m_nSamples = expect_samples;
+- m_dwSongFlags = SONG_INSTRUMENTMODE | SONG_LINEARSLIDES /* eh? */;
+-
+- memcpy(m_szNames[0], lpStream + 0x20, 26);
+- m_szNames[0][26] = 0;
+-
+- if (q+(80*expect_samples) >= dwMemLength) {
+- delete zenv;
+- return FALSE;
+- }
+-
+- for (UINT nsmp = 0; nsmp < expect_samples; nsmp++) {
+-
+- ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+q);
+- q += 80; /* length of ITS header */
+-
+- 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;
+- 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);
+-
+- }
+-
+- Headers[1] = zenv;
+- return TRUE;
+- }
+-
+-
+- 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 ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS)
+- || (pifh.smpnum >= MAX_INSTRUMENTS)) 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 & 0x01)) m_dwSongFlags |= SONG_NOSTEREO;
+- if (pifh.flags & 0x04) m_dwSongFlags |= SONG_INSTRUMENTMODE;
+- 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 & 0x40) {
+- midi_flags |= MIDI_PITCH_BEND;
+- midi_pitch_depth = pifh.pwd;
+- }
+- 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;
+- if (pifh.cwtv >= 0x0213) {
+- m_rowHighlightMinor = pifh.hilight_minor;
+- m_rowHighlightMajor = pifh.hilight_major;
+- } else {
+- m_rowHighlightMinor = 4;
+- m_rowHighlightMajor = 16;
+- }
+- // Global Volume
+- m_nDefaultGlobalVolume = pifh.globalvol << 1;
+- 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;
+- if (m_nSongPreAmp > 128)
+- m_nSongPreAmp = 128;
+- m_nStereoSeparation = pifh.sep;
+- // 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;
+-
+- for (UINT i = 0; i < pifh.ordnum; i++) {
+- if (Order[i] >= pifh.patnum && Order[i] < MAX_PATTERNS) {
+- pifh.patnum = Order[i];
+- for (UINT j = patpossize; j < (unsigned)(pifh.patnum>>2); j++)
+- patpos[j] = 0;
+- patpossize = pifh.patnum;
+- }
+- }
+-
+-
+- // 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);
+- } else {
+- ResetMidiCfg();
+- }
+- } else {
+- ResetMidiCfg();
+- }
+-#if 0
+- // 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;
+- }
+- }
+-#endif
+- // 4-channels minimum
+- m_nChannels = 4;
+-#if 0
+- // 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);
+- }
+-#endif
+- // 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 = 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;
+- 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;
+- PatternAllocSize[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;
+- PatternAllocSize[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;
+- }
+- }
+- 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_VIBRATO; 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;
+-}
+-
+-
+-//////////////////////////////////////////////////////////////////////////////
+-// 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 wCount = 0;
+- DWORD bitbuf = 0;
+- UINT bitnum = 0;
+- BYTE bLeft = 0, bTemp = 0, bTemp2 = 0;
+-
+- while (dwLen)
+- {
+- if (!wCount)
+- {
+- wCount = 0x8000;
+- 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 wCount = 0;
+- DWORD bitbuf = 0;
+- UINT bitnum = 0;
+- BYTE bLeft = 0;
+- signed short wTemp = 0, wTemp2 = 0;
+-
+- while (dwLen)
+- {
+- if (!wCount)
+- {
+- wCount = 0x4000;
+- 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;
+- }
+-}
+-
+-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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_mdl.cxx 3.0.3/src/modplug/load_mdl.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_mdl.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_mdl.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,538 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-//////////////////////////////////////////////
+-// DigiTracker (MDL) module loader //
+-//////////////////////////////////////////////
+-#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;
+- if (param > 0xF)
+- param = 0xF;
+- param <<= 4;
+- }
+- }
+- break;
+- case 0x20:
+- if ((param & 0xF0) != 0xE0) {
+- command = CMD_VOLUMESLIDE;
+- if ((param & 0xF0) != 0xF0) {
+- param >>= 2;
+- if (param > 0xF)
+- param = 0xF;
+- }
+- }
+- 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 ((bswapLE32(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;
+- m_dwSongFlags |= SONG_INSTRUMENTMODE;
+- while (dwMemPos+6 < dwMemLength)
+- {
+- block = *((WORD *)(lpStream+dwMemPos));
+- blocklen = *((DWORD *)(lpStream+dwMemPos+2));
+- block = bswapLE16(block);
+- blocklen = bswapLE32(blocklen);
+- 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 = bswapLE16(pmib->norders);
+- if (norders > MAX_ORDERS) norders = MAX_ORDERS;
+- m_nRestartPos = bswapLE16(pmib->repeatpos);
+- m_nDefaultGlobalVolume = pmib->globalvol;
+- if (m_nDefaultGlobalVolume == 255)
+- m_nDefaultGlobalVolume++;
+- 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;
+- PatternAllocSize[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] = bswapLE16(pmpd->data[j]);
+- }
+- }
+- break;
+- // TR: Track Data
+- case 0x5254:
+- if (dwTrackPos) break;
+- ntracks = *((WORD *)(lpStream+dwMemPos));
+- ntracks = bswapLE16(ntracks);
+- 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 = 128;
+- 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->nC4Speed = bswapLE32(pins->nC4Speed);
+- pins->nLength = *((DWORD *)(lpStream+dwPos+45));
+- pins->nLength = bswapLE32(pins->nLength);
+- pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49));
+- pins->nLoopStart = bswapLE32(pins->nLoopStart);
+- pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53));
+- pins->nLoopEnd = bswapLE32(pins->nLoopEnd);
+- 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));
+- dwLen = bswapLE32(dwLen);
+- 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->VolEnv.nNodes = 15;
+- for (UINT iv=0; iv<15; iv++)
+- {
+- if (iv) vtick += pve[iv*2+1];
+- penv->VolEnv.Ticks[iv] = vtick;
+- penv->VolEnv.Values[iv] = pve[iv*2+2];
+- if (!pve[iv*2+1])
+- {
+- penv->VolEnv.nNodes = iv+1;
+- break;
+- }
+- }
+- penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pve[31] & 0x0F;
+- if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN;
+- if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP;
+- penv->VolEnv.nLoopStart = pve[32] & 0x0F;
+- penv->VolEnv.nLoopEnd = 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->PanEnv.nNodes = 15;
+- for (UINT iv=0; iv<15; iv++)
+- {
+- if (iv) vtick += ppe[iv*2+1];
+- penv->PanEnv.Ticks[iv] = vtick;
+- penv->PanEnv.Values[iv] = ppe[iv*2+2];
+- if (!ppe[iv*2+1])
+- {
+- penv->PanEnv.nNodes = iv+1;
+- break;
+- }
+- }
+- if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN;
+- if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP;
+- penv->PanEnv.nLoopStart = ppe[32] & 0x0F;
+- penv->PanEnv.nLoopEnd = 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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_med.cxx 3.0.3/src/modplug/load_med.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_med.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_med.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,919 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#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;
+- m_nStereoSeparation = ((pmsh2->mix_stereosep < 0) ? -32 : 32) * pmsh2->mix_stereosep;
+- // 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;
+- PatternAllocSize[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;
+- PatternAllocSize[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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_mod.cxx 3.0.3/src/modplug/load_mod.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_mod.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_mod.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,358 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#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; } return 0;
+- 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 < 2) 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->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;
+- ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0;
+- }
+- m_nStereoSeparation = (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN) ? 128 : 64;
+-
+- // 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;
+- PatternAllocSize[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
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_mt2.cxx 3.0.3/src/modplug/load_mt2.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_mt2.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_mt2.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,637 +0,0 @@
+-#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;
+- PatternAllocSize[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;
+- m_dwSongFlags |= SONG_INSTRUMENTMODE;
+- 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 = 128;
+- 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];
+- int *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->VolEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
+- penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pme->nSustainPos;
+- penv->VolEnv.nLoopStart = pme->nLoopStart;
+- penv->VolEnv.nLoopEnd = pme->nLoopEnd;
+- pEnvPoints = penv->VolEnv.Ticks;
+- pEnvData = penv->VolEnv.Values;
+- 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->PanEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
+- penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = pme->nSustainPos;
+- penv->PanEnv.nLoopStart = pme->nLoopStart;
+- penv->PanEnv.nLoopEnd = pme->nLoopEnd;
+- pEnvPoints = penv->PanEnv.Ticks;
+- pEnvData = penv->PanEnv.Values;
+- 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->PitchEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
+- penv->PitchEnv.nSustainStart = penv->PitchEnv.nSustainEnd = pme->nSustainPos;
+- penv->PitchEnv.nLoopStart = pme->nLoopStart;
+- penv->PitchEnv.nLoopEnd = pme->nLoopEnd;
+- pEnvPoints = penv->PitchEnv.Ticks;
+- pEnvData = penv->PitchEnv.Values;
+- }
+- // 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/4;
+- }
+- }
+- }
+- }
+- 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;
+-}
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_mtm.cxx 3.0.3/src/modplug/load_mtm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_mtm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_mtm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,165 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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*bswapLE16(pmh->numtracks)
+- + 64 * (pmh->lastpattern+1) + bswapLE16(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 = bswapLE32(pms->length);
+- if ((len > 4) && (len <= MAX_SAMPLE_LENGTH))
+- {
+- Ins[i].nLength = len;
+- Ins[i].nLoopStart = bswapLE32(pms->reppos);
+- Ins[i].nLoopEnd = bswapLE32(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 * bswapLE16(pmh->numtracks);
+- LPWORD pSeq = (LPWORD)(lpStream + dwMemPos);
+- for (UINT pat=0; pat<=pmh->lastpattern; pat++)
+- {
+- PatternSize[pat] = 64;
+- PatternAllocSize[pat] = 64;
+- if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break;
+- for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= bswapLE16(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 (bswapLE16(pmh->commentsize) && (dwMemPos + bswapLE16(pmh->commentsize) < dwMemLength))
+- {
+- UINT n = bswapLE16(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 += bswapLE16(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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_okt.cxx 3.0.3/src/modplug/load_okt.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_okt.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_okt.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,197 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-//////////////////////////////////////////////
+-// Oktalyzer (OKT) module loader //
+-//////////////////////////////////////////////
+-#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, 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)
+- {
+- 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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_psm.cxx 3.0.3/src/modplug/load_psm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_psm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_psm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,882 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-
+-///////////////////////////////////////////////////
+-//
+-// PSM module loader
+-//
+-///////////////////////////////////////////////////
+-#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 patptrs[MAX_PATTERNS];
+- BYTE samplemap[MAX_SAMPLES];
+- UINT nPatterns;
+-
+- // Chunk0: "PSM ",filesize,"FILE"
+- if (dwMemLength < 256) return FALSE;
+- if (bswapLE32(pfh->id) == PSM_ID_OLD)
+- {
+- #ifdef PSM_LOG
+- printf("Old PSM format not supported\n");
+- #endif
+- return FALSE;
+- }
+- if ((bswapLE32(pfh->id) != PSM_ID_NEW)
+- || (bswapLE32(pfh->len)+12 > dwMemLength)
+- || (bswapLE32(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;
+- }
+- m_szNames[0][0]=0;
+- while (dwMemPos+8 < dwMemLength)
+- {
+- PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
+- if ((bswapLE32(pchunk->len) >= dwMemLength - 8)
+- || (dwMemPos + bswapLE32(pchunk->len) + 8 > dwMemLength)) break;
+- dwMemPos += 8;
+- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
+- ULONG len = bswapLE32(pchunk->len);
+- if (len) switch(bswapLE32(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;
+- 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 = bswapLE32(psmp->samplerate);
+- pins->nLength = bswapLE32(psmp->length);
+- pins->nLoopStart = bswapLE32(psmp->loopstart);
+- pins->nLoopEnd = bswapLE32(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 += bswapLE32(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 ((bswapLE32(pchunk->len) > dwSongEnd)
+- || (dwMemPos + bswapLE32(pchunk->len) > dwSongEnd)) break;
+- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
+- ULONG len = bswapLE32(pchunk->len);
+- switch(bswapLE32(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 += bswapLE32(pchunk->len);
+- }
+- }
+-
+- // Step #2: convert patterns
+- for (UINT nPat=0; nPat<nPatterns; nPat++)
+- {
+- PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8);
+- ULONG len = bswapLE32(*(DWORD *)(lpStream+patptrs[nPat]+4)) - 12;
+- UINT nRows = bswapLE16(pPsmPat->rows);
+- if (len > bswapLE32(pPsmPat->size)) len = bswapLE32(pPsmPat->size);
+- if ((nRows < 64) || (nRows > 256)) nRows = 64;
+- PatternSize[nPat] = nRows;
+- PatternAllocSize[nPat] = nRows;
+- if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break;
+- MODCOMMAND *m = Patterns[nPat];
+- MODCOMMAND *sp, dummy;
+- BYTE *p = pPsmPat->data;
+- UINT pos = 0;
+- UINT row = 0;
+- UINT rowlim;
+- #ifdef PSM_LOG
+- //printf("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream));
+- #endif
+- rowlim = bswapLE16(pPsmPat->reserved1)-2;
+- while ((row < nRows) && (pos+1 < len))
+- {
+- UINT flags, ch;
+- if ((pos+1) >= rowlim) {
+- pos = rowlim;
+- rowlim = (((int)p[pos+1])<<8)
+- | ((int)p[pos+0]);
+- m += m_nChannels;
+- row++;
+- rowlim += pos;
+- pos += 2;
+- }
+- flags = p[pos++];
+- ch = p[pos++];
+- if (ch >= m_nChannels) {
+- #ifdef PSM_LOG
+- printf("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch);
+- #endif
+- sp = &dummy;
+- } else {
+- sp = &m[ch];
+- }
+- // Note + Instr
+- if ((flags & 0x80) && (pos+1 < len))
+- {
+- UINT note = p[pos++];
+- note = (note>>4)*12+(note&0x0f)+12+1;
+- if (note > 0x80) note = 0;
+- sp->note = note;
+- }
+- if ((flags & 0x40) && (pos+1 < len))
+- {
+- UINT nins = p[pos++];
+- #ifdef PSM_LOG
+- if ((!nPat) && (nins >= m_nSamples)) printf("WARNING: invalid instrument number (%d)\n", nins);
+- #endif
+- sp->instr = samplemap[nins];
+- }
+- // Volume
+- if ((flags & 0x20) && (pos < len))
+- {
+- sp->volcmd = VOLCMD_VOLUME;
+- sp->vol = p[pos++] / 2;
+- }
+- // Effect
+- if ((flags & 0x10) && (pos+1 < len))
+- {
+- UINT command = p[pos++];
+- UINT param = p[pos++];
+- // Convert effects
+- switch(command & 0x3F)
+- {
+- // 01: fine volslide up
+- case 0x01:
+-#if PSM_LOG
+- printf("fvup command pat=%d row=%d ch=%d %02x %02x\n",
+- nPat,
+- row,1+ch,
+- command, param);
+-#endif
+-#if 0
+- if (!sp->volcmd) {
+- sp->volcmd = VOLCMD_FINEVOLUP;
+- sp->vol = (param >> 1) & 0xF;
+- command = CMD_PORTAMENTOUP;
+- param>>=4; param |= 0xf0;
+- if (param == 240) param=241;
+- } else {
+-#endif
+- command = CMD_VOLUMESLIDE;
+- param |= 0x0f;
+- if (param == 15) param=31;
+- break;
+- // 02: volslide up
+- case 0x02: command = CMD_VOLUMESLIDE; param>>=1; param<<=4; break;
+- // 03: fine volslide down
+- case 0x03:
+-#if PSM_LOG
+- printf("fvdown command pat=%d row=%d ch=%d %02x %02x\n",
+- nPat,
+- row,1+ch,
+- command, param);
+-#endif
+-#if 0
+- if (!sp->volcmd) {
+- sp->volcmd = VOLCMD_FINEVOLDOWN;
+- sp->vol = (param >> 2) & 0xF;
+- if (!sp->vol) sp->vol = 1;
+- command = CMD_PORTAMENTODOWN;
+- }
+-#endif
+- command = CMD_VOLUMESLIDE;
+- param>>=4; param |= 0xf0;
+- if (param == 240) param=241;
+- break;
+- // 04: volslide down
+- case 0x04: command = CMD_VOLUMESLIDE; param>>=1; 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;
+- // 0F: tone portamento
+- case 0x0F: command = CMD_TONEPORTAMENTO; param = param/4; break;
+- // 15: vibrato
+- case 0x15: command = CMD_VIBRATO; break;
+- // 29: wtf
+- case 0x29: pos += 2; break;
+- // 2A: retrig
+- case 0x2A: command = CMD_RETRIG; 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;
+- if (!row && !nPat)
+- m_nDefaultSpeed = param;
+- break;
+- // 3E: tempo
+- case 0x3E: command = CMD_TEMPO;
+- if (!row && !nPat)
+- m_nDefaultTempo = param;
+- break;
+- // Unknown
+- default:
+- #ifdef PSM_LOG
+- printf("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param);
+- #endif
+- command = param = 0;
+- }
+- sp->command = (BYTE)command;
+- sp->param = (BYTE)param;
+- }
+- }
+- #ifdef PSM_LOG
+- if (pos < len)
+- {
+-// printf("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;
+-
+-*/
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_ptm.cxx 3.0.3/src/modplug/load_ptm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_ptm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_ptm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,208 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-//////////////////////////////////////////////
+-// PTM PolyTracker module loader //
+-//////////////////////////////////////////////
+-#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;
+- 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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_s3m.cxx 3.0.3/src/modplug/load_s3m.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_s3m.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_s3m.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,406 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#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; if (!bIT) param *= 2; 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'; if (!bIT) param >>= 1;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 < 2) 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 < 2) 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 the parapointer is zero, the pattern is blank (so ignore it)
+- if (nInd == 0)
+- continue;
+- if (nInd + 0x40 > dwMemLength) continue;
+- WORD len = bswapLE16(*((WORD *)(lpStream+nInd)));
+- nInd += 2;
+- PatternSize[iPat] = 64;
+- PatternAllocSize[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;
+- if (insflags[iRaw-1] & 4)
+- flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U;
+- else
+- flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
+- 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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_stm.cxx 3.0.3/src/modplug/load_stm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_stm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_stm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,187 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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 = bswapLE16(pStm->c2spd);
+- pIns->nGlobalVol = 64;
+- pIns->nVolume = pStm->volume << 2;
+- if (pIns->nVolume > 256) pIns->nVolume = 256;
+- pIns->nLength = bswapLE16(pStm->length);
+- if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0;
+- pIns->nLoopStart = bswapLE16(pStm->loopbeg);
+- pIns->nLoopEnd = bswapLE16(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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_ult.cxx 3.0.3/src/modplug/load_ult.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_ult.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_ult.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,223 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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;
+- PatternAllocSize[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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_umx.cxx 3.0.3/src/modplug/load_umx.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_umx.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_umx.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,53 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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;
+-}
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_wav.cxx 3.0.3/src/modplug/load_wav.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_wav.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_wav.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,248 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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;
+- WAVEFORMATHEADER pfmt;
+-
+- if ((!lpStream)
+- || (dwMemLength < (DWORD)(sizeof(WAVEFORMATHEADER)+sizeof(WAVEFILEHEADER))))
+- return FALSE;
+-
+- memcpy(&phdr, lpStream, sizeof(phdr));
+- memcpy(&pfmt, lpStream+sizeof(phdr), sizeof(pfmt));
+-
+- phdr.id_RIFF = bswapLE32(phdr.id_RIFF);
+- phdr.filesize = bswapLE32(phdr.filesize);
+- phdr.id_WAVE = bswapLE32(phdr.id_WAVE);
+-
+- pfmt.id_fmt = bswapLE32(pfmt.id_fmt);
+- pfmt.hdrlen = bswapLE32(pfmt.hdrlen);
+- pfmt.format = bswapLE16(pfmt.format);
+- pfmt.channels = bswapLE16(pfmt.channels);
+- pfmt.freqHz = bswapLE32(pfmt.freqHz);
+- pfmt.bytessec = bswapLE32(pfmt.bytessec);
+- pfmt.samplesize = bswapLE16(pfmt.samplesize);
+- pfmt.bitspersample = bswapLE16(pfmt.bitspersample);
+-
+- 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 (;;)
+- {
+- memcpy(&pdata, lpStream+dwMemPos, sizeof(pdata));
+- pdata.id_data = bswapLE32(pdata.id_data);
+- pdata.length = bswapLE32(pdata.length);
+-
+- 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;
+- PatternAllocSize[0] = PatternAllocSize[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] = bswapLE16(*((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 = bswapLE16(*((short int *)psrc));
+- nIndex = bswapLE16((short int)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 % 90] >> 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;
+-}
+-
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/load_xm.cxx 3.0.3/src/modplug/load_xm.cxx
+--- audacious-plugins-3.0.2/src/modplug/load_xm.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/load_xm.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,529 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#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 > MAX_ORDERS) return FALSE;
+- restartpos = bswapLE16(*((WORD *)(lpStream+66)));
+- channels = bswapLE16(*((WORD *)(lpStream+68)));
+- if (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_dwSongFlags |= SONG_INSTRUMENTMODE;
+- 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;
+- PatternAllocSize[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 MODPLUG_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 // MODPLUG_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->VolEnv.nNodes = xmsh.vnum;
+- if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME;
+- if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING;
+- if (!(penv->dwFlags & ENV_VOLUME) && !penv->nFadeOut) {
+- penv->nFadeOut = 8192;
+- }
+- penv->PanEnv.nNodes = xmsh.pnum;
+- penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = xmsh.vsustain;
+- if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN;
+- penv->VolEnv.nLoopStart = xmsh.vloops;
+- penv->VolEnv.nLoopEnd = xmsh.vloope;
+- if (penv->VolEnv.nLoopEnd >= 12) penv->VolEnv.nLoopEnd = 0;
+- if (penv->VolEnv.nLoopStart >= penv->VolEnv.nLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
+- penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = xmsh.psustain;
+- if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN;
+- penv->PanEnv.nLoopStart = xmsh.ploops;
+- penv->PanEnv.nLoopEnd = xmsh.ploope;
+- if (penv->PanEnv.nLoopEnd >= 12) penv->PanEnv.nLoopEnd = 0;
+- if (penv->PanEnv.nLoopStart >= penv->PanEnv.nLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
+- penv->nGlobalVol = 128;
+- for (UINT ienv=0; ienv<12; ienv++)
+- {
+- penv->VolEnv.Ticks[ienv] = (WORD)xmsh.venv[ienv*2];
+- penv->VolEnv.Values[ienv] = (BYTE)xmsh.venv[ienv*2+1];
+- penv->PanEnv.Ticks[ienv] = (WORD)xmsh.penv[ienv*2];
+- penv->PanEnv.Values[ienv] = (BYTE)xmsh.penv[ienv*2+1];
+- if (ienv)
+- {
+- if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1])
+- {
+- penv->VolEnv.Ticks[ienv] &= 0xFF;
+- penv->VolEnv.Ticks[ienv] += penv->VolEnv.Ticks[ienv-1] & 0xFF00;
+- if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1]) penv->VolEnv.Ticks[ienv] += 0x100;
+- }
+- if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1])
+- {
+- penv->PanEnv.Ticks[ienv] &= 0xFF;
+- penv->PanEnv.Ticks[ienv] += penv->PanEnv.Ticks[ienv-1] & 0xFF00;
+- if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1]) penv->PanEnv.Ticks[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/4;
+- 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;
+- }
+- }
+- /* set these to default */
+- for (UINT in=0; in<m_nChannels; in++)
+- {
+- ChnSettings[in].nVolume = 64;
+- ChnSettings[in].nPan = 128;
+- ChnSettings[in].dwFlags = 0;
+- }
+- return TRUE;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/Makefile 3.0.3/src/modplug/Makefile
+--- audacious-plugins-3.0.2/src/modplug/Makefile 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/Makefile 2011-09-07 22:45:40.000000000 +0200
+@@ -1,41 +1,10 @@
+ PLUGIN = modplug${PLUGIN_SUFFIX}
+
+-SRCS = plugin.cxx \
+- modplugbmp.cxx \
+- tables.cxx \
+- sndmix.cxx \
+- sndfile.cxx \
+- snd_eq.cxx \
+- snd_fx.cxx \
+- snd_flt.cxx \
+- snd_dsp.cxx \
+- fastmix.cxx \
+- mmcmp.cxx \
+- load_xm.cxx \
+- load_wav.cxx \
+- load_umx.cxx \
+- load_ult.cxx \
+- load_stm.cxx \
+- load_s3m.cxx \
+- load_ptm.cxx \
+- load_okt.cxx \
+- load_mtm.cxx \
+- load_mod.cxx \
+- load_med.cxx \
+- load_mdl.cxx \
+- load_it.cxx \
+- load_far.cxx \
+- load_dsm.cxx \
+- load_dmf.cxx \
+- load_dbm.cxx \
+- load_ams.cxx \
+- load_amf.cxx \
+- load_669.cxx \
+- load_mt2.cxx \
+- load_psm.cxx \
+- archive/archive.cxx \
+- archive/open.cxx \
+- archive/arch_raw.cxx \
++SRCS = archive/arch_raw.cxx \
++ archive/archive.cxx \
++ archive/open.cxx \
++ plugin.cxx \
++ modplugbmp.cxx \
+ plugin_main.c
+
+ include ../../buildsys.mk
+@@ -46,5 +15,5 @@
+ LD = ${CXX}
+ CFLAGS += ${PLUGIN_CFLAGS}
+ CXXFLAGS += ${PLUGIN_CFLAGS}
+-CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I.. -I../.. -I../../intl
+-LIBS += ${MOWGLI_LIBS} ${GTK_LIBS} ${GLIB_LIBS} -lstdc++
++CPPFLAGS += ${PLUGIN_CPPFLAGS} ${MOWGLI_CFLAGS} ${MODPLUG_CFLAGS} -I../..
++LIBS += ${MOWGLI_LIBS} ${MODPLUG_LIBS} -lstdc++
+diff -Nur audacious-plugins-3.0.2/src/modplug/midi.h 3.0.3/src/modplug/midi.h
+--- audacious-plugins-3.0.2/src/modplug/midi.h 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/midi.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,185 +0,0 @@
+-/*
+- * Schism Tracker - a cross-platform Impulse Tracker clone
+- * copyright (c) 2003-2005 chisel <schism at chisel.cjb.net>
+- * copyright (c) 2005-2006 Mrs. Brisby <mrs.brisby at nimh.org>
+- * URL: http://nimh.org/schism/
+- * URL: http://rigelseven.com/schism/
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+- */
+-
+-#ifndef MIDI_H
+-#define MIDI_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-struct midi_provider;
+-struct midi_port;
+-
+-struct midi_driver {
+- unsigned int flags;
+-#define MIDI_PORT_CAN_SCHEDULE 1
+-
+- void (*poll)(struct midi_provider *m);
+- int (*thread)(struct midi_provider *m);
+-
+- int (*enable)(struct midi_port *d);
+- int (*disable)(struct midi_port *d);
+-
+- void (*send)(struct midi_port *d,
+- unsigned char *seq, unsigned int len, unsigned int delay);
+- void (*drain)(struct midi_port *d);
+-};
+-
+-struct midi_provider {
+- const char *name;
+- void (*poll)(struct midi_provider *);
+- void *thread; /*actually SDL_Thread* */
+-
+- struct midi_provider *next;
+-
+- /* forwarded; don't touch */
+- int (*enable)(struct midi_port *d);
+- int (*disable)(struct midi_port *d);
+-
+- void (*send_now)(struct midi_port *d,
+- unsigned char *seq, unsigned int len, unsigned int delay);
+- void (*send_later)(struct midi_port *d,
+- unsigned char *seq, unsigned int len, unsigned int delay);
+- void (*drain)(struct midi_port *d);
+-};
+-struct midi_port {
+- int io, iocap;
+-#define MIDI_INPUT 1
+-#define MIDI_OUTPUT 2
+- char *name;
+- int num;
+-
+- void *userdata;
+- int free_userdata;
+- int (*enable)(struct midi_port *d);
+- int (*disable)(struct midi_port *d);
+- void (*send_now)(struct midi_port *d,
+- unsigned char *seq, unsigned int len, unsigned int delay);
+- void (*send_later)(struct midi_port *d,
+- unsigned char *seq, unsigned int len, unsigned int delay);
+- void (*drain)(struct midi_port *d);
+-
+- struct midi_provider *provider;
+-};
+-
+-
+-/* schism calls these directly */
+-int midi_engine_start(void);
+-void midi_engine_reset(void);
+-void midi_engine_stop(void);
+-void midi_engine_poll_ports(void);
+-
+-/* some parts of schism call this; it means "immediately" */
+-void midi_send_now(unsigned char *seq, unsigned int len);
+-
+-/* ... but the player calls this */
+-void midi_send_buffer(unsigned char *data, unsigned int len, unsigned int pos);
+-void midi_send_flush(void);
+-
+-/* from the SDL event mechanism (x is really SDL_Event) */
+-int midi_engine_handle_event(void *x);
+-
+-struct midi_port *midi_engine_port(int n, const char **name);
+-int midi_engine_port_count(void);
+-
+-/* midi engines register a provider (one each!) */
+-struct midi_provider *midi_provider_register(const char *name, struct midi_driver *f);
+-
+-
+-/* midi engines list ports this way */
+-int midi_port_register(struct midi_provider *p,
+-int inout, const char *name, void *userdata, int free_userdata);
+-
+-int midi_port_foreach(struct midi_provider *p, struct midi_port **cursor);
+-void midi_port_unregister(int num);
+-
+-/* only call these if the event isn't really MIDI but you want most of the system
+- to act like it is...
+-
+- midi drivers should never all these...
+-*/
+-enum midi_note {
+- MIDI_NOTEOFF,
+- MIDI_NOTEON,
+- MIDI_KEYPRESS,
+-};
+-void midi_event_note(enum midi_note mnstatus, int channel, int note, int velocity);
+-void midi_event_controller(int channel, int param, int value);
+-void midi_event_program(int channel, int value);
+-void midi_event_aftertouch(int channel, int value);
+-void midi_event_pitchbend(int channel, int value);
+-void midi_event_tick(void);
+-void midi_event_sysex(const unsigned char *data, unsigned int len);
+-void midi_event_system(int argv, int param);
+-
+-/* midi drivers call this when they received an event */
+-void midi_received_cb(struct midi_port *src, unsigned char *data, unsigned int len);
+-
+-
+-#ifdef USE_NETWORK
+-int ip_midi_setup(void);
+-#endif
+-#ifdef USE_OSS
+-int oss_midi_setup(void);
+-#endif
+-#ifdef USE_ALSA
+-int alsa_midi_setup(void);
+-#endif
+-#ifdef USE_WIN32MM
+-int win32mm_midi_setup(void);
+-#endif
+-#ifdef MACOSX
+-int macosx_midi_setup(void);
+-#endif
+-
+-
+-
+-#define MIDI_TICK_QUANTIZE 0x00000001
+-#define MIDI_BASE_PROGRAM1 0x00000002
+-#define MIDI_RECORD_NOTEOFF 0x00000004
+-#define MIDI_RECORD_VELOCITY 0x00000008
+-#define MIDI_RECORD_AFTERTOUCH 0x00000010
+-#define MIDI_CUT_NOTE_OFF 0x00000020
+-#define MIDI_PITCH_BEND 0x00000040
+-#define MIDI_EMBED_DATA 0x00000080
+-#define MIDI_RECORD_SDX 0x00000100
+-#define MIDI_DISABLE_RECORD 0x00010000
+-
+-/* configurable midi stuff */
+-int midi_flags = MIDI_TICK_QUANTIZE | MIDI_RECORD_NOTEOFF
+- | MIDI_RECORD_VELOCITY | MIDI_RECORD_AFTERTOUCH
+- | MIDI_PITCH_BEND;
+-
+-int midi_pitch_depth = 12;
+-int midi_amplification = 100;
+-int midi_c5note = 60;
+-
+-/* only available with networks */
+-void ip_midi_setports(int n);
+-int ip_midi_getports(void);
+-
+-#ifdef __cplusplus
+-};
+-#endif
+-
+-#endif
+diff -Nur audacious-plugins-3.0.2/src/modplug/mmcmp.cxx 3.0.3/src/modplug/mmcmp.cxx
+--- audacious-plugins-3.0.2/src/modplug/mmcmp.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/mmcmp.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,406 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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;
+-}
+-
+-
+-
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/snd_dsp.cxx 3.0.3/src/modplug/snd_dsp.cxx
+--- audacious-plugins-3.0.2/src/modplug/snd_dsp.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/snd_dsp.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,491 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-
+-#ifdef MODPLUG_FASTSOUNDLIB
+-#define MODPLUG_NO_REVERB
+-#endif
+-
+-
+-// Delayed Surround Filters
+-#ifndef MODPLUG_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;
+-
+-void (*CSoundFile::_midi_out_note)(int chan, const MODCOMMAND *m) = NULL;
+-void (*CSoundFile::_midi_out_raw)(unsigned char *,unsigned int, unsigned int) = NULL;
+-
+-////////////////////////////////////////////////////////////////////
+-// 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 MODPLUG_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 MODPLUG_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));
+-/* mrsb: libmodplug bug hahahah */
+- memset(MixSoundBuffer,0,sizeof(MixSoundBuffer));
+- memset(MixReverbBuffer,0,sizeof(MixReverbBuffer));
+- }
+- } 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 MODPLUG_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 MODPLUG_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 MODPLUG_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;
+-}
+diff -Nur audacious-plugins-3.0.2/src/modplug/snd_eq.cxx 3.0.3/src/modplug/snd_eq.cxx
+--- audacious-plugins-3.0.2/src/modplug/snd_eq.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/snd_eq.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,228 +0,0 @@
+-/*
+- * This program is free software; you can redistribute it and modify it
+- * under the terms of the GNU General Public License as published by the
+- * Free Software Foundation; either version 2 of the license or (at your
+- * option) any later version.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+- *
+- * Name Date Description
+- *
+- * Olivier Lapicque --/--/-- Creation
+- * Trevor Nunes 26/01/04 conditional compilation for AMD,MMX calls
+- *
+-*/
+-#include "stdafx.h"
+-#include "sndfile.h"
+-#include <math.h>
+-
+-
+-#define EQ_BANDWIDTH 2.0
+-#define EQ_ZERO 0.000001
+-#define REAL float
+-
+-extern REAL MixFloatBuffer[];
+-
+-extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount);
+-extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
+-extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount);
+-extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount);
+-
+-typedef struct _EQBANDSTRUCT
+-{
+- REAL a0, a1, a2, b1, b2;
+- REAL x1, x2, y1, y2;
+- REAL Gain, CenterFrequency;
+- BOOL bEnable;
+-} EQBANDSTRUCT, *PEQBANDSTRUCT;
+-
+-UINT gEqLinearToDB[33] =
+-{
+- 16, 19, 22, 25, 28, 31, 34, 37,
+- 40, 43, 46, 49, 52, 55, 58, 61,
+- 64, 76, 88, 100, 112, 124, 136, 148,
+- 160, 172, 184, 196, 208, 220, 232, 244, 256
+-};
+-
+-
+-//static REAL f2ic = (REAL)(1 << 28);
+-//static REAL i2fc = (REAL)(1.0 / (1 << 28));
+-
+-static EQBANDSTRUCT gEQ[MAX_EQ_BANDS*2] =
+-{
+- // Default: Flat EQ
+- {0,0,0,0,0, 0,0,0,0, 1, 120, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 600, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 1200, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 3000, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 6000, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 120, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 600, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 1200, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 3000, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 6000, FALSE},
+- {0,0,0,0,0, 0,0,0,0, 1, 10000, FALSE},
+-};
+-
+-void EQFilter(EQBANDSTRUCT *pbs, REAL *pbuffer, UINT nCount)
+-//----------------------------------------------------------
+-{
+- for (UINT i=0; i<nCount; i++)
+- {
+- REAL x = pbuffer[i];
+- REAL y = pbs->a1 * pbs->x1 + pbs->a2 * pbs->x2 + pbs->a0 * x + pbs->b1 * pbs->y1 + pbs->b2 * pbs->y2;
+- pbs->x2 = pbs->x1;
+- pbs->y2 = pbs->y1;
+- pbs->x1 = x;
+- pbuffer[i] = y;
+- pbs->y1 = y;
+- }
+-}
+-
+-void CSoundFile::EQMono(int *pbuffer, UINT nCount)
+-//------------------------------------------------
+-{
+- MonoMixToFloat(pbuffer, MixFloatBuffer, nCount);
+- for (UINT b=0; b<MAX_EQ_BANDS; b++)
+- {
+- if ((gEQ[b].bEnable) && (gEQ[b].Gain != 1.0f))
+- EQFilter(&gEQ[b], MixFloatBuffer, nCount);
+- }
+- FloatToMonoMix(MixFloatBuffer, pbuffer, nCount);
+-}
+-
+-void CSoundFile::EQStereo(int *pbuffer, UINT nCount)
+-//--------------------------------------------------
+-{
+- StereoMixToFloat(pbuffer, MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, nCount);
+-
+- for (UINT bl=0; bl<MAX_EQ_BANDS; bl++)
+- {
+- if ((gEQ[bl].bEnable) && (gEQ[bl].Gain != 1.0f))
+- EQFilter(&gEQ[bl], MixFloatBuffer, nCount);
+- }
+- for (UINT br=MAX_EQ_BANDS; br<MAX_EQ_BANDS*2; br++)
+- {
+- if ((gEQ[br].bEnable) && (gEQ[br].Gain != 1.0f))
+- EQFilter(&gEQ[br], MixFloatBuffer+MIXBUFFERSIZE, nCount);
+- }
+-
+- FloatToStereoMix(MixFloatBuffer, MixFloatBuffer+MIXBUFFERSIZE, pbuffer, nCount);
+-
+-}
+-
+-void CSoundFile::InitializeEQ(BOOL bReset)
+-//----------------------------------------
+-{
+- REAL fMixingFreq = (REAL)gdwMixingFreq;
+- // Gain = 0.5 (-6dB) .. 2 (+6dB)
+- for (UINT band=0; band<MAX_EQ_BANDS*2; band++) if (gEQ[band].bEnable)
+- {
+- REAL k, k2, r, f;
+- REAL v0, v1;
+- BOOL b = bReset;
+-
+- f = gEQ[band].CenterFrequency / fMixingFreq;
+- if (f > 0.45f) gEQ[band].Gain = 1;
+- // if (f > 0.25) f = 0.25;
+- // k = tan(PI*f);
+- k = f * 3.141592654f;
+- k = k + k*f;
+-// if (k > (REAL)0.707) k = (REAL)0.707;
+- k2 = k*k;
+- v0 = gEQ[band].Gain;
+- v1 = 1;
+- if (gEQ[band].Gain < 1.0)
+- {
+- v0 *= (0.5f/EQ_BANDWIDTH);
+- v1 *= (0.5f/EQ_BANDWIDTH);
+- } else
+- {
+- v0 *= (1.0f/EQ_BANDWIDTH);
+- v1 *= (1.0f/EQ_BANDWIDTH);
+- }
+- r = (1 + v0*k + k2) / (1 + v1*k + k2);
+- if (r != gEQ[band].a0)
+- {
+- gEQ[band].a0 = r;
+- b = TRUE;
+- }
+- r = 2 * (k2 - 1) / (1 + v1*k + k2);
+- if (r != gEQ[band].a1)
+- {
+- gEQ[band].a1 = r;
+- b = TRUE;
+- }
+- r = (1 - v0*k + k2) / (1 + v1*k + k2);
+- if (r != gEQ[band].a2)
+- {
+- gEQ[band].a2 = r;
+- b = TRUE;
+- }
+- r = - 2 * (k2 - 1) / (1 + v1*k + k2);
+- if (r != gEQ[band].b1)
+- {
+- gEQ[band].b1 = r;
+- b = TRUE;
+- }
+- r = - (1 - v1*k + k2) / (1 + v1*k + k2);
+- if (r != gEQ[band].b2)
+- {
+- gEQ[band].b2 = r;
+- b = TRUE;
+- }
+- if (b)
+- {
+- gEQ[band].x1 = 0;
+- gEQ[band].x2 = 0;
+- gEQ[band].y1 = 0;
+- gEQ[band].y2 = 0;
+- }
+- } else
+- {
+- gEQ[band].a0 = 0;
+- gEQ[band].a1 = 0;
+- gEQ[band].a2 = 0;
+- gEQ[band].b1 = 0;
+- gEQ[band].b2 = 0;
+- gEQ[band].x1 = 0;
+- gEQ[band].x2 = 0;
+- gEQ[band].y1 = 0;
+- gEQ[band].y2 = 0;
+- }
+-}
+-
+-
+-void CSoundFile::SetEQGains(const UINT *pGains, UINT nGains, const UINT *pFreqs, BOOL bReset)
+-//-------------------------------------------------------------------------------------------
+-{
+- for (UINT i=0; i<MAX_EQ_BANDS; i++)
+- {
+- REAL g, f = 0;
+- if (i < nGains)
+- {
+- UINT n = pGains[i];
+-// if (n > 32) n = 32;
+- g = 1.0 + (((double)n) / 64.0);
+- if (pFreqs) f = (REAL)(int)pFreqs[i];
+- } else
+- {
+- g = 1;
+- }
+- gEQ[i].Gain = g;
+- gEQ[i].CenterFrequency = f;
+- gEQ[i+MAX_EQ_BANDS].Gain = g;
+- gEQ[i+MAX_EQ_BANDS].CenterFrequency = f;
+- if (f > 20.0f && i < nGains) /* don't enable bands outside... */
+- {
+- gEQ[i].bEnable = TRUE;
+- gEQ[i+MAX_EQ_BANDS].bEnable = TRUE;
+- } else
+- {
+- gEQ[i].bEnable = FALSE;
+- gEQ[i+MAX_EQ_BANDS].bEnable = FALSE;
+- }
+- }
+- InitializeEQ(bReset);
+-}
+diff -Nur audacious-plugins-3.0.2/src/modplug/sndfile.cxx 3.0.3/src/modplug/sndfile.cxx
+--- audacious-plugins-3.0.2/src/modplug/sndfile.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/sndfile.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,1690 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#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_nStereoSeparation = 128;
+- 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;
+- m_rowHighlightMajor = 16;
+- m_rowHighlightMinor = 4;
+- 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;
+-
+- // deja vu...
+- m_nType = MOD_TYPE_NONE;
+- m_dwSongFlags = 0;
+- m_nStereoSeparation = 128;
+- 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_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;
+- PatternAllocSize[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))
+- && (!Read669(lpStream, dwMemLength))
+- && (!ReadS3M(lpStream, dwMemLength))
+- && (!ReadIT(lpStream, dwMemLength))
+- && (!ReadWav(lpStream, dwMemLength))
+- && (!ReadSTM(lpStream, dwMemLength))
+- && (!ReadMed(lpStream, dwMemLength))
+- && (!ReadMTM(lpStream, dwMemLength))
+- && (!ReadMDL(lpStream, dwMemLength))
+- && (!ReadDBM(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))
+- && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE;
+-#ifdef MMCMP_SUPPORT
+- if (bMMCmp)
+- {
+- GlobalFreePtr(lpStream);
+- lpStream = NULL;
+- }
+-#endif
+- }
+- // 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->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength;
+- } 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_nDefaultTempo < 31) m_nDefaultTempo = 31;
+- 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();
+- }
+- }
+- }
+- }
+- return m_nType ? TRUE : 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);
+-//printf("Rate=%u Bits=%u Channels=%u MMX=%u\n",gdwMixingFreq,gnBitsPerSample,gnChannels,bMMX);
+- 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 ((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::ResetTimestamps()
+-//--------------------------------
+-{
+- int n;
+-
+- for (n = 1; n < MAX_SAMPLES; n++) {
+- Ins[n].played = 0;
+- }
+- for (n = 1; n < MAX_INSTRUMENTS; n++) {
+- if (Headers[n])
+- Headers[n]->played = 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_dwSongFlags & SONG_INSTRUMENTMODE))
+- {
+- 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(LPSTR 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
+-
+-
+-
+-// 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) || (pIns->nLength < 1) || (!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 *pSample = (short *)pIns->pSample;
+- short *p = (short *)lpMemFile;
+- unsigned short tmp;
+- int delta16 = 0;
+- for (UINT j=0; j<len; j+=2)
+- {
+- tmp = *((unsigned short *)p++);
+- delta16 += bswapLE16(tmp);
+- *pSample++ = (short) 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)
+- {
+- *pSample = bswapLE16(*pSample);
+- pSample++;
+- }
+- }
+- 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) memcpy(pIns->pSample, lpMemFile, len);
+- short int *pSample = (short int *)pIns->pSample;
+- for (UINT j=0; j<len; j+=2)
+- {
+- *pSample = bswapLE16(*pSample) - 0x8000;
+- pSample++;
+- }
+- }
+- 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 < 2) 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_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!
+- {
+- *pSampleW = bswapLE16(*pSampleW);
+- pSampleW++;
+- }
+- }
+- 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 // !MODPLUG_FASTSOUNDLIB
+-
+- // 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 MODPLUG_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.
+-#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;
+-#else
+- return (DWORD) (8363.0 * pow(2, (transp * 128.0 + ftune) / 1536.0));
+-#endif
+-}
+-
+-
+-// returns 12*128*log2(freq/8363)
+-int CSoundFile::FrequencyToTranspose(DWORD freq)
+-//----------------------------------------------
+-{
+- //---GCCFIX: Removed assembly.
+-#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;
+-#else
+- return (int) (1536.0 * (log(freq / 8363.0) / log(2)));
+-#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;
+-}
+-
+-UINT CSoundFile::GetHighestUsedChannel()
+-//------------------------------
+-{
+- UINT highchan = 0;
+-
+- 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 ((j % m_nChannels) > highchan)
+- highchan = j % m_nChannels;
+- }
+- }
+- }
+- }
+-
+- return highchan;
+-}
+-
+-
+-
+-#ifndef MODPLUG_FASTSOUNDLIB
+-
+-UINT CSoundFile::DetectUnusedSamples(BOOL *pbIns)
+-//-----------------------------------------------
+-{
+- UINT nExt = 0;
+-
+- if (!pbIns) return 0;
+- if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+- {
+- 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 // MODPLUG_FASTSOUNDLIB
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/sndfile.h 3.0.3/src/modplug/sndfile.h
+--- audacious-plugins-3.0.2/src/modplug/sndfile.h 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/sndfile.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,1042 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at evdebs.org> (endian and char fixes for PPC)
+-*/
+-
+-#include <config.h>
+-
+-#ifndef __SNDFILE_H
+-#define __SNDFILE_H
+-
+-#define MODPLUG_TRACKER 1
+-#define MODPLUG_PLAYER 1
+-
+-#ifdef UNDER_CE
+-int _strnicmp(const char *str1,const char *str2, int n);
+-#endif
+-
+-#ifndef LPCBYTE
+-typedef const BYTE * LPCBYTE;
+-#endif
+-
+-#define MOD_AMIGAC2 0x1AB
+-#define MAX_SAMPLE_LENGTH 16000000
+-#define MAX_SAMPLE_RATE 192000
+-#define MAX_ORDERS 256
+-#define MAX_PATTERNS 240
+-#define MAX_SAMPLES 240
+-#define MAX_INSTRUMENTS MAX_SAMPLES
+-#ifdef MODPLUG_FASTSOUNDLIB
+-#define MAX_CHANNELS 80
+-#else
+-#define MAX_CHANNELS 256
+-#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_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
+-// used to turn off mute but have it reset later
+-#define CHN_NNAMUTE 0x10000000
+-
+-
+-#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 ENV_MUTE 0x4000
+-
+-#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
+-#define SONG_INSTRUMENTMODE 0x20000
+-#define SONG_ORDERLOCKED 0x40000
+-#define SONG_NOSTEREO 0x80000
+-
+-// 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
+-#define SNDMIX_MUTECHNMODE 0x100000 // Notes are not played on muted channels
+-#define SNDMIX_NOSURROUND 0x200000
+-#define SNDMIX_NOMIXING 0x400000 // don't actually do any mixing (values only)
+-#define SNDMIX_NORAMPING 0x800000
+-
+-// 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;
+- UINT nPan;
+- UINT nVolume;
+- UINT nGlobalVol;
+- UINT uFlags;
+- int RelativeTone;
+- int nFineTune;
+- UINT nVibType;
+- UINT nVibSweep;
+- UINT nVibDepth;
+- UINT nVibRate;
+- CHAR name[22];
+- int played; // for note playback dots
+-} MODINSTRUMENT;
+-
+-typedef struct _INSTRUMENTENVELOPE {
+- int Ticks[32];
+- BYTE Values[32];
+- int nNodes;
+- int nLoopStart;
+- int nLoopEnd;
+- int nSustainStart;
+- int nSustainEnd;
+-} INSTRUMENTENVELOPE;
+-
+-
+-// Instrument Struct
+-typedef struct _INSTRUMENTHEADER
+-{
+- UINT nFadeOut;
+- DWORD dwFlags;
+- unsigned int nGlobalVol;
+- unsigned int nPan;
+- unsigned int Keyboard[128];
+- unsigned int NoteMap[128];
+- INSTRUMENTENVELOPE VolEnv;
+- INSTRUMENTENVELOPE PanEnv;
+- INSTRUMENTENVELOPE PitchEnv;
+- unsigned int nNNA;
+- unsigned int nDCT;
+- unsigned int nDNA;
+- unsigned int nPanSwing;
+- unsigned int nVolSwing;
+- unsigned int nIFC;
+- unsigned int nIFR;
+- unsigned int wMidiBank;
+- unsigned int nMidiProgram;
+- unsigned int nMidiChannel;
+- unsigned int nMidiDrumKey;
+- int nPPS;
+- unsigned int nPPC;
+- CHAR name[32];
+- CHAR filename[12];
+- int played; // for note playback dots
+-} 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
+- unsigned int topnote_offset;
+- 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;
+-
+- double nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4;
+- double 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, sample_freq, nPortamentoDest;
+- INSTRUMENTHEADER *pHeader;
+- MODINSTRUMENT *pInstrument;
+- int nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition;
+- DWORD nMasterChn, nVUMeter;
+- LONG nGlobalVol, nInsVol;
+- LONG nFineTune, nTranspose;
+- LONG nPortamentoSlide, nAutoVibDepth;
+- UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos;
+- // 16-bit members
+- int nVolSwing, nPanSwing;
+-
+- // formally 8-bit members
+- unsigned int nNote, nNNA;
+- unsigned int nNewNote, nNewIns, nCommand, nArpeggio;
+- unsigned int nOldVolumeSlide, nOldFineVolUpDown;
+- unsigned int nOldPortaUpDown, nOldFinePortaUpDown;
+- unsigned int nOldPanSlide, nOldChnVolSlide;
+- unsigned int nVibratoType, nVibratoSpeed, nVibratoDepth;
+- unsigned int nTremoloType, nTremoloSpeed, nTremoloDepth;
+- unsigned int nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth;
+- unsigned int nOldCmdEx, nOldVolParam, nOldTempo;
+- unsigned int nOldOffset, nOldHiOffset;
+- unsigned int nCutOff, nResonance;
+- unsigned int nRetrigCount, nRetrigParam;
+- unsigned int nTremorCount, nTremorParam;
+- unsigned int nPatternLoop, nPatternLoopCount;
+- unsigned int nRowNote, nRowInstr;
+- unsigned int nRowVolCmd, nRowVolume;
+- unsigned int nRowCommand, nRowParam;
+- unsigned int nLeftVU, nRightVU;
+- unsigned int nActiveMacro, nLastInstr;
+- unsigned int nTickStart;
+- unsigned int nRealtime;
+- BYTE stupid_gcc_workaround;
+-
+-} 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() = 0;
+- virtual int AddRef() = 0;
+- virtual int Release() = 0;
+- virtual void SaveAllParameters() = 0;
+- virtual void RestoreAllParameters() = 0;
+- virtual void Process(float *pOutL, float *pOutR, unsigned int nSamples) = 0;
+- virtual void Init(unsigned int 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 int, unsigned int); // 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_nMaxMixChannels;
+- static LONG m_nStreamVolume;
+- static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels;
+- static UINT gnAGC, gnVolumeRampSamples, gnCPUUsage;
+- static UINT gnVULeft, gnVURight;
+- 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
+- WORD PatternAllocSize[MAX_PATTERNS]; // Allocated pattern lengths (for async. resizing/playback)
+- 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_nStereoSeparation;
+- 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_nLockedPattern,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;
+- BYTE m_rowHighlightMajor, m_rowHighlightMinor;
+- 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 GetHighestUsedChannel();
+- 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 ReadUMX(LPCBYTE lpStream, DWORD dwMemLength);
+- // 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:
+- // backhooks :)
+- static void (*_midi_out_note)(int chan, const MODCOMMAND *m);
+- static void (*_midi_out_raw)(unsigned char *,unsigned int, unsigned int);
+-
+-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);
+-
+- // Floats
+- static VOID StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount);
+- static VOID FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
+- static VOID MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount);
+- static VOID FloatToMonoMix(const float *pIn, int *pOut, UINT nCount);
+-
+-
+-
+-
+-
+- // wee...
+- static void InitializeEQ(BOOL bReset=TRUE);
+- static void SetEQGains(const UINT *pGains, UINT nBands, const UINT *pFreqs=NULL, BOOL bReset=FALSE); // 0=-12dB, 32=+12dB
+- /*static*/ void EQStereo(int *pbuffer, UINT nCount);
+- /*static*/ void EQMono(int *pbuffer, UINT nCount);
+-
+-
+- //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);
+- void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut);
+- void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE, BOOL bManual=FALSE);
+- 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 MidiSend(unsigned char *data, unsigned int len, UINT nChn=0, int fake = 0);
+- void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0,
+- UINT note=0, UINT velocity=0, UINT use_instr=0);
+- void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256,int freq=0) 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(LPSTR 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 GetLinearPeriodFromNote(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);
+- void ResetTimestamps(); // for note playback dots
+-
+- // 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 (-0x04000000)
+-#define MIXING_CLIPMAX (0x03FFFFFF)
+-#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 ))
+-
+-// Return (a*b)/c - no divide error
+-static inline int _muldiv(int a, int b, int c)
+-{
+- return ((unsigned long long) a * (unsigned long long) b ) / c;
+-}
+-
+-
+-// Return (a*b+c/2)/c - no divide error
+-static inline int _muldivr(int a, int b, int c)
+-{
+- return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / 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
+-
+-#if (defined ARM) && (defined _WIN32_WCE)
+-static __inline unsigned short int
+-ARM_get16(const void *data)
+-{
+- unsigned short int s;
+- memcpy(&s,data,sizeof(s));
+- return s;
+-}
+-
+-static __inline unsigned int
+-ARM_get32(const void *data)
+-{
+- unsigned int s;
+- memcpy(&s,data,sizeof(s));
+- return s;
+-}
+-
+-#define bswapLE16(X) ARM_get16(&X)
+-#define bswapLE32(X) ARM_get32(&X)
+-#define bswapBE16(X) bswap_16(ARM_get16(&X))
+-#define bswapBE32(X) bswap_32(ARM_get32(&X))
+-
+-// From libsdl
+-#elif 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
+diff -Nur audacious-plugins-3.0.2/src/modplug/snd_flt.cxx 3.0.3/src/modplug/snd_flt.cxx
+--- audacious-plugins-3.0.2/src/modplug/snd_flt.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/snd_flt.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,130 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-
+-// AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz]
+-// EMU10K1 docs: cutoff = reg[0-127]*62+100
+-
+-#ifndef NO_FILTER
+-
+-static int filter_cutoff[] = {
+- 130, 132, 134, 136, 138, 140, 142, 144,
+- 146, 148, 151, 153, 155, 157, 160, 162,
+- 164, 167, 169, 172, 174, 177, 179, 182,
+- 184, 187, 190, 193, 195, 198, 201, 204,
+- 207, 210, 213, 216, 220, 223, 226, 229,
+- 233, 236, 239, 243, 246, 250, 254, 257,
+- 261, 265, 269, 273, 277, 281, 285, 289,
+- 293, 297, 302, 306, 311, 315, 320, 324,
+- 329, 334, 339, 344, 349, 354, 359, 364,
+- 369, 375, 380, 386, 391, 397, 403, 409,
+- 415, 421, 427, 433, 440, 446, 452, 459,
+- 466, 472, 479, 486, 493, 501, 508, 515,
+- 523, 530, 538, 546, 554, 562, 570, 578,
+- 587, 595, 604, 613, 622, 631, 640, 649,
+- 659, 668, 678, 688, 698, 708, 718, 729,
+- 739, 750, 761, 772, 783, 795, 806, 818,
+- 830, 842, 854, 867, 880, 892, 905, 918,
+- 932, 945, 959, 973, 987, 1002, 1016, 1031,
+- 1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157,
+- 1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299,
+- 1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458,
+- 1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637,
+- 1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837,
+- 1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062,
+- 2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315,
+- 2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599,
+- 2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917,
+- 2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274,
+- 3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675,
+- 3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125,
+- 4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631,
+- 4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198
+-};
+-int dmpfac[] = {
+- 131072, 128272, 125533, 122852, 120229, 117661, 115148, 112689,
+- 110283, 107928, 105623, 103367, 101160, 98999, 96885, 94816,
+- 92791, 90810, 88870, 86973, 85115, 83298, 81519, 79778,
+- 78074, 76407, 74775, 73178, 71615, 70086, 68589, 67125,
+- 65691, 64288, 62915, 61572, 60257, 58970, 57711, 56478,
+- 55272, 54092, 52937, 51806, 50700, 49617, 48557, 47520,
+- 46506, 45512, 44540, 43589, 42658, 41747, 40856, 39983,
+- 39130, 38294, 37476, 36676, 35893, 35126, 34376, 33642,
+- 32923, 32220, 31532, 30859, 30200, 29555, 28924, 28306,
+- 27701, 27110, 26531, 25964, 25410, 24867, 24336, 23816,
+- 23308, 22810, 22323, 21846, 21380, 20923, 20476, 20039,
+- 19611, 19192, 18782, 18381, 17989, 17604, 17228, 16861,
+- 16500, 16148, 15803, 15466, 15135, 14812, 14496, 14186,
+- 13883, 13587, 13297, 13013, 12735, 12463, 12197, 11936,
+- 11681, 11432, 11188, 10949, 10715, 10486, 10262, 10043,
+- 9829, 9619, 9413, 9212, 9015, 8823, 8634, 8450,
+- 8270, 8093, 7920, 7751, 7585, 7423, 7265, 7110,
+- 6958, 6809, 6664, 6522, 6382, 6246, 6113, 5982,
+- 5854, 5729, 5607, 5487, 5370, 5255, 5143, 5033,
+- 4926, 4820, 4718, 4617, 4518, 4422, 4327, 4235,
+- 4144, 4056, 3969, 3884, 3801, 3720, 3641, 3563,
+- 3487, 3412, 3340, 3268, 3198, 3130, 3063, 2998,
+- 2934, 2871, 2810, 2750, 2691, 2634, 2577, 2522,
+- 2468, 2416, 2364, 2314, 2264, 2216, 2169, 2122,
+- 2077, 2032, 1989, 1947, 1905, 1864, 1824, 1786,
+- 1747, 1710, 1674, 1638, 1603, 1569, 1535, 1502,
+- 1470, 1439, 1408, 1378, 1348, 1320, 1291, 1264,
+- 1237, 1210, 1185, 1159, 1135, 1110, 1087, 1063,
+- 1041, 1018, 997, 975, 955, 934, 914, 895,
+- 876, 857, 838, 821, 803, 786, 769, 753,
+- 737, 721, 705, 690, 676, 661, 647, 633,
+- 620, 606, 593, 581, 568, 556, 544, 533
+-};
+-
+-
+-#include <math.h>
+-
+-
+-#define PI ((double)3.14159265358979323846)
+-// Simple 2-poles resonant filter
+-void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier, int) const
+-//----------------------------------------------------------------------------------------
+-{
+- int cutoff = pChn->nCutOff * 2;
+- cutoff *= (flt_modifier+256) / 2;
+- cutoff /= 256;
+- if (cutoff>=255) cutoff=255;
+-
+- int resonance = pChn->nResonance;
+- if (resonance>=255) resonance=255;
+-
+- float fc = (float)filter_cutoff[cutoff];
+- float fs = (float)gdwMixingFreq;
+- float fg, fb0, fb1;
+- float d2, d, e;
+-
+- fc *= 3.14159265358979 * 2 / fs;
+- d2 = ((float)dmpfac[resonance]) / 65536.0;
+- d = (1.0 - d2) * fc;
+-
+- if (d > 2.0)
+- d = 2.0;
+-
+- d = (d2 - d) / fc;
+- e = 1.0 / (fc * fc);
+-
+- fg = 1.0 / (1 + d + e);
+- fb0 = (d + e + e) / (1 + d + e);
+- fb1 = -e / (1 + d + e);
+-
+- pChn->nFilter_A0 = (double)fg;
+- pChn->nFilter_B0 = (double)fb0;
+- pChn->nFilter_B1 = (double)fb1;
+-
+- if (bReset) {
+- pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
+- pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
+- }
+- pChn->dwFlags |= CHN_FILTER;
+-}
+-#endif // NO_FILTER
+diff -Nur audacious-plugins-3.0.2/src/modplug/snd_fx.cxx 3.0.3/src/modplug/snd_fx.cxx
+--- audacious-plugins-3.0.2/src/modplug/snd_fx.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/snd_fx.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,2614 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#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
+- // FIXME: this is totally wrong!
+- 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 = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL;
+- 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;
+- pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain
+- } else
+- if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+- {
+- 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)
+- {
+- psmp->played = 1;
+- if (penv)
+- {
+- penv->played = 1;
+- pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 7;
+- 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, BOOL bManual)
+-//-----------------------------------------------------------------------------------------
+-{
+- if (note < 1) return;
+- MODCHANNEL * const pChn = &Chn[nChn];
+- MODINSTRUMENT *pins = pChn->pInstrument;
+- INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL;
+- if ((penv) && (note <= 0x80))
+- {
+- UINT n = penv->Keyboard[note - 1];
+- if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n];
+- note = penv->NoteMap[note-1];
+- pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain
+- }
+- // Key Off
+- if (note >= 0x80) // 0xFE or invalid note => key off
+- {
+- // technically this is "wrong", as anything besides ^^^, ===, and a valid note
+- // should cause a note fade... (oh well, it's just a quick hack anyway.)
+- if (note == 0xFD) {
+- pChn->dwFlags |= CHN_NOTEFADE;
+- return;
+- }
+-
+- // Key Off
+- KeyOff(nChn);
+- // Note Cut
+- if (note == 0xFE)
+- {
+- pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
+- if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_INSTRUMENTMODE))
+- 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)
+- {
+- /* this was wrong */
+- int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 256;
+- pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/256);
+- }
+- // 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
+- }
+- // Special case for MPT
+- if (bManual) pChn->dwFlags &= ~CHN_MUTE;
+- if (((pChn->dwFlags & CHN_MUTE) && (gdwSoundSetup & SNDMIX_MUTECHNMODE))
+- || ((pChn->pInstrument) && (pChn->pInstrument->uFlags & CHN_MUTE) && (!bManual))
+- || ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader)
+- && (pChn->pHeader->dwFlags & ENV_MUTE) && (!bManual)))
+- {
+- if (!bManual) pChn->nPeriod = 0;
+- }
+-}
+-
+-
+-UINT CSoundFile::GetNNAChannel(UINT nChn)
+-//---------------------------------------------
+-{
+- MODCHANNEL *pChn = &Chn[nChn];
+- // Check for empty channel
+- MODCHANNEL *pi = &Chn[m_nChannels];
+- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, pi++) {
+- if (!pi->nLength) {
+- if (pi->dwFlags & CHN_MUTE) {
+- if (pi->dwFlags & CHN_NNAMUTE) {
+- pi->dwFlags &= ~(CHN_NNAMUTE|CHN_MUTE);
+- } else {
+- /* this channel is muted; skip */
+- continue;
+- }
+- }
+- return i;
+- }
+- }
+- if (!pChn->nFadeOutVol) return 0;
+- // All channels are used: check for lowest volume
+- UINT result = 0;
+- DWORD vol = 64*65536; // 25%
+- int 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;
+- }
+- }
+- if (result) {
+- /* unmute new nna channel */
+- Chn[result].dwFlags &= ~(CHN_MUTE|CHN_NNAMUTE);
+- }
+- return result;
+-}
+-
+-
+-void CSoundFile::CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut)
+-//------------------------------------------------------------------------
+-{
+- MODCHANNEL *p;
+- MODCHANNEL *pChn = &Chn[nChn];
+- INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL;
+- INSTRUMENTHEADER *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_dwSongFlags & SONG_INSTRUMENTMODE)) || (bForceCut))
+- {
+- if ((m_dwSongFlags & SONG_CPUVERYHIGH)
+- || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE)
+- || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return;
+- UINT n = GetNNAChannel(nChn);
+- if (!n) return;
+- p = &Chn[n];
+- // Copy Channel
+- *p = *pChn;
+- p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|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 = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL;
+- 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;
+- 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) && ((int)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)
+- {
+- p = &Chn[n];
+- // Copy Channel
+- *p = *pChn;
+- p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|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++)
+- {
+- pChn->nCommand=0;
+-
+- 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 = pChn->nTickStart;
+-
+- 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_dwSongFlags & SONG_INSTRUMENTMODE)
+- {
+- 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 ? (not when paused!!!)
+- 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;
+- pChn->dwFlags &= ~CHN_SURROUND;
+- }
+- }
+-
+- // 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;
+- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
+- {
+- MODCHANNEL *c = &Chn[i];
+- if (c->nMasterChn == (nChn+1)) {
+- c->nVolume = pChn->nVolume;
+- c->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);
+- } else {
+- param = pChn->nOldTempo; // this just got set on tick zero
+-
+- switch (param >> 4) {
+- case 0:
+- m_nMusicTempo -= param & 0xf;
+- if (m_nMusicTempo < 32)
+- m_nMusicTempo = 32;
+- break;
+- case 1:
+- m_nMusicTempo += param & 0xf;
+- if (m_nMusicTempo > 255)
+- m_nMusicTempo = 255;
+- break;
+- }
+- }
+- 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:
+- pChn->nCommand = CMD_ARPEGGIO;
+- if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break;
+- if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break;
+- 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
+- }
+- // various bits of retriggery commented out here & below, reverting to old method...
+- // -Storlek 04aug07
+- // if (pChn->nRowNote && !m_nTickCount) pChn->nRetrigCount = 0;
+- if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
+- // pChn->nCommand = CMD_RETRIG;
+- RetrigNote(nChn, param);
+- break;
+-
+- // Tremor
+- case CMD_TREMOR:
+- pChn->nCommand = CMD_TREMOR;
+- if (m_nTickCount) break;
+- 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;
+- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
+- {
+- MODCHANNEL *c = &Chn[i];
+- if (c->nMasterChn == (nChn+1)) {
+- c->nGlobalVol = param;
+- c->dwFlags |= CHN_FASTVOLRAMP;
+- }
+- }
+- }
+- break;
+-
+- // Channel volume slide
+- case CMD_CHANNELVOLSLIDE:
+- {
+- int saw_self = 0;
+-
+- for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
+- {
+- MODCHANNEL *c = &Chn[i];
+- if (c->nMasterChn == (nChn+1)) {
+- if (c == pChn) saw_self = 1;
+- ChannelVolSlide(c, param);
+- }
+- }
+- if (!saw_self) {
+- 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 ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+- {
+- INSTRUMENTHEADER *penv = pChn->pHeader;
+- if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes) && ((int)param > penv->PanEnv.Ticks[penv->PanEnv.nNodes-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 MODPLUG_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 // MODPLUG_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_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4;
+- else pChn->nPortamentoDest=0;
+- 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_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4;
+- else pChn->nPortamentoDest=0;
+- 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;
+- }
+- pChn->dwFlags &= ~CHN_SURROUND;
+-}
+-
+-
+-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:
+- pChn->dwFlags &= ~CHN_SURROUND;
+- 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)
+- {
+- if (m_nType & MOD_TYPE_S3M) {
+- pChn->nPan = ((param ^ 8) << 4) + 8;
+- pChn->dwFlags &= ~CHN_SURROUND;
+- pChn->dwFlags |= CHN_FASTVOLRAMP;
+- } else {
+- 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)
+- {
+- // S91: Surround On
+- case 0x01: pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break;
+- ////////////////////////////////////////////////////////////
+- // Modplug Extensions
+- // S90: Surround Off
+- case 0x00: pChn->dwFlags &= ~CHN_SURROUND; break;
+- // 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;
+- }
+-}
+-
+-// this is all brisby
+-void CSoundFile::MidiSend(unsigned char *data, unsigned int len, UINT nChn, int fake)
+-{
+- MODCHANNEL *pChn = &Chn[nChn];
+- int oldcutoff;
+-
+- if (len > 2 && data[0] == 0xF0 && data[1] == 0xF0) {
+- /* impulse tracker filter control (mfg. 0xF0) */
+- if (len == 5) {
+- switch (data[2]) {
+- case 0x00: /* set cutoff */
+- oldcutoff = pChn->nCutOff;
+- if (data[3] < 0x80) pChn->nCutOff = data[3];
+-#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;
+- case 0x01: /* set resonance */
+- if (data[3] < 0x80) pChn->nResonance = data[3];
+-#ifndef NO_FILTER
+- SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
+-#endif // NO_FILTER
+- break;
+- };
+- }
+- }
+-
+- if (!fake && _midi_out_raw) {
+- /* okay, this is kind of how it works.
+- we pass m_nBufferCount as here because while
+- 1000 * ((8((buffer_size/2) - m_nBufferCount)) / sample_rate)
+- is the number of msec we need to delay by, libmodplug simply doesn't know
+- what the buffer size is at this point so m_nBufferCount simply has no
+- frame of reference.
+-
+- fortunately, schism does and can complete this (tags: _schism_midi_out_raw )
+-
+- */
+- _midi_out_raw(data, len, m_nBufferCount);
+- }
+-}
+-
+-static int _was_complete_midi(unsigned char *q, unsigned int len, int nextc)
+-{
+- if (len == 0) return 0;
+- if (*q == 0xF0) return (q[len-1] == 0xF7 ? 1 : 0);
+- return ((nextc & 0x80) ? 1 : 0);
+-}
+-
+-void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param,
+- UINT note, UINT velocity, UINT use_instr)
+-//---------------------------------------------------------------------------
+-{
+-/* this was all wrong. -mrsb */
+- MODCHANNEL *pChn = &Chn[nChn];
+- INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE)
+- ? Headers[use_instr
+- ?use_instr
+- :pChn->nLastInstr]
+- : NULL;
+- unsigned char outbuffer[64];
+- unsigned char cx;
+- int mc, fake = 0;
+- int saw_c;
+- int i, j, x;
+-
+- saw_c = 0;
+- if (!penv || penv->nMidiChannel == 0) {
+- /* okay, there _IS_ no real midi channel. forget this for now... */
+- mc = 15;
+- fake = 1;
+-
+- } else if (penv->nMidiChannel > 16) {
+- mc = (nChn-1) % 16;
+- } else {
+- mc = (penv->nMidiChannel-1);
+- }
+-
+- for (i = j = x = 0, cx =0; i <= 32 && pszMidiMacro[i]; i++) {
+- int c, cw;
+- if (pszMidiMacro[i] >= '0' && pszMidiMacro[i] <= '9') {
+- c = pszMidiMacro[i] - '0';
+- cw = 1;
+- } else if (pszMidiMacro[i] >= 'A' && pszMidiMacro[i] <= 'F') {
+- c = (pszMidiMacro[i] - 'A') + 10;
+- cw = 1;
+- } else if (pszMidiMacro[i] == 'c') {
+- c = mc;
+- cw = 1;
+- saw_c = 1;
+- } else if (pszMidiMacro[i] == 'n') {
+- c = (note-1);
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'v') {
+- c = velocity;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'u') {
+- c = (pChn->nVolume >> 1);
+- if (c > 127) c = 127;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'x') {
+- c = pChn->nPan;
+- if (c > 127) c = 127;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'y') {
+- c = pChn->nRealPan;
+- if (c > 127) c = 127;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'a') {
+- if (!penv)
+- c = 0;
+- else
+- c = (penv->wMidiBank >> 7) & 127;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'b') {
+- if (!penv)
+- c = 0;
+- else
+- c = penv->wMidiBank & 127;
+- cw = 2;
+- } else if (pszMidiMacro[i] == 'z' || pszMidiMacro[i] == 'p') {
+- c = param & 0x7F;
+- cw = 2;
+- } else {
+- continue;
+- }
+- if (j == 0 && cw == 1) {
+- cx = c;
+- j = 1;
+- continue;
+- } else if (j == 1 && cw == 1) {
+- cx = (cx << 4) | c;
+- j = 0;
+- } else if (j == 0) {
+- cx = c;
+- } else if (j == 1) {
+- outbuffer[x] = cx;
+- x++;
+-
+- cx = c;
+- j = 0;
+- }
+- // start of midi message
+- if (_was_complete_midi(outbuffer,x,cx)) {
+- MidiSend(outbuffer, x, nChn,saw_c && fake);
+- x = 0;
+- }
+- outbuffer[x] = cx;
+- x++;
+- }
+- if (j == 1) {
+- outbuffer[x] = cx;
+- x++;
+- }
+- if (x) {
+- // terminate sysex
+- if (!_was_complete_midi(outbuffer,x,0xFF)) {
+- if (*outbuffer == 0xF0) {
+- outbuffer[x] = 0xF7;
+- x++;
+- }
+- }
+- MidiSend(outbuffer, x, nChn,saw_c && fake);
+- }
+-}
+-
+-
+-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 (m_nMusicSpeed < nRetrigSpeed) {
+- if (nRetrigCount >= nRetrigSpeed) {
+- bDoRetrig = TRUE;
+- nRetrigCount = 0;
+- } else {
+- nRetrigCount++;
+- }
+- } else {
+- 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_dwSongFlags & SONG_INSTRUMENTMODE) KeyOff(pChn); ?
+- pChn->nVolume = 0;
+- pChn->dwFlags |= CHN_FASTVOLRAMP;
+- pChn->nLength = 0;
+- }
+-}
+-
+-
+-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 ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (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 ((m_dwSongFlags & SONG_INSTRUMENTMODE) && 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)
+-//-----------------------------------
+-{
+- if (param)
+- m_nMusicSpeed = param;
+-}
+-
+-
+-void CSoundFile::SetTempo(UINT param)
+-//-----------------------------------
+-{
+- if (param < 0x20)
+- {
+-#if 0 // argh... this is completely wrong
+- // 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;
+- }
+-#endif
+- } else
+- {
+- m_nMusicTempo = param;
+- }
+-}
+-
+-
+-int CSoundFile::PatternLoop(MODCHANNEL *pChn, UINT param)
+-//-------------------------------------------------------
+-{
+- if (param)
+- {
+- if (pChn->nPatternLoopCount)
+- {
+- pChn->nPatternLoopCount--;
+- if (!pChn->nPatternLoopCount) {
+- // this should get rid of that nasty infinite loop for cases like
+- // ... .. .. SB0
+- // ... .. .. SB1
+- // ... .. .. SB1
+- // it still doesn't work right in a few strange cases, but oh well :P
+- pChn->nPatternLoop = m_nRow + 1;
+- return -1;
+- }
+- } else
+- {
+- // hmm. the pattern loop shouldn't care about
+- // other channels at all... i'm not really
+- // sure what this code is doing :/
+-#if 0
+- MODCHANNEL *p = Chn;
+- for (UINT i=0; i<m_nChannels; i++, p++) if (p != pChn)
+- {
+- // Loop already done
+- if (p->nPatternLoopCount) return -1;
+- }
+-#endif
+- 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;
+- }
+-}
+-
+-// this last param was nC4Speed
+-UINT CSoundFile::GetLinearPeriodFromNote(UINT note, int nFineTune, UINT) 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--;
+- return (FreqS3MTable[note % 12] << 5) >> (note / 12);
+- } else
+- if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
+- {
+- if (note < 13) note = 13;
+- note -= 13;
+- LONG l = ((120 - note) << 6) - (nFineTune / 2);
+- if (l < 1) l = 1;
+- return (UINT)l;
+- } 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::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);
+- }
+- }
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/sndmix.cxx 3.0.3/src/modplug/sndmix.cxx
+--- audacious-plugins-3.0.2/src/modplug/sndmix.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/sndmix.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,1246 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+-*/
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-
+-
+-// Volume ramp length, in 1/10 ms
+-#define VOLUMERAMPLEN 146 // 1.46ms = 64 samples at 44.1kHz
+-
+-// VU-Meter
+-#define VUMETER_DECAY 16
+-
+-// SNDMIX: These are global flags for playback control
+-LONG CSoundFile::m_nStreamVolume = 0x8000;
+-UINT CSoundFile::m_nMaxMixChannels = 256;
+-// Mixing Configuration (SetWaveConfig)
+-DWORD CSoundFile::gdwSysInfo = 0;
+-DWORD CSoundFile::gnChannels = 1;
+-DWORD CSoundFile::gdwSoundSetup = SNDMIX_NOBACKWARDJUMPS; // Do not allow song to loop infinitely
+-DWORD CSoundFile::gdwMixingFreq = 44100;
+-DWORD CSoundFile::gnBitsPerSample = 16;
+-// Mixing data initialized in
+-UINT CSoundFile::gnAGC = AGC_UNITY;
+-UINT CSoundFile::gnVolumeRampSamples = 64;
+-UINT CSoundFile::gnVULeft = 0;
+-UINT CSoundFile::gnVURight = 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 Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+-extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+-extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+-extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
+-extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC);
+-extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits);
+-extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
+-extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+-extern VOID MPPASMCALL 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,
+-};
+-
+-
+-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)
+- {
+- gnVULeft = 0;
+- gnVURight = 0;
+- gnCPUUsage = 0;
+- }
+- gbInitPlugins = (bReset) ? 3 : 1;
+- InitializeDSP(bReset);
+- InitializeEQ(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 = Convert32To8;
+- LONG vu_min[2];
+- LONG vu_max[2];
+- UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0;
+-#if 0
+- UINT nMaxPlugins;
+-#endif
+-
+- vu_min[0] = vu_min[1] = 0x7FFFFFFF;
+- vu_max[0] = vu_max[1] = -0x7FFFFFFF;
+-
+-#if 0
+- {
+- nMaxPlugins = MAX_MIXPLUGINS;
+- while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
+- }
+-#endif
+- m_nMixStat = 0;
+- lSampleSize = gnChannels;
+- if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; }
+- else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; }
+- else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; }
+- 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
+- UINT lTotalSampleCount;
+- if (!m_nBufferCount)
+- {
+- if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
+- m_nBufferCount = lRead;
+- if (!ReadNote()) {
+- m_dwSongFlags |= SONG_ENDREACHED;
+- if (lRead == lMax) goto MixDone;
+- if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
+- m_nBufferCount = lRead;
+- }
+- if (!m_nBufferCount) goto MixDone;
+- }
+- lCount = m_nBufferCount;
+- if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
+- if (lCount > lRead) lCount = lRead;
+- if (!lCount) break;
+- lSampleCount = lCount;
+-#ifndef MODPLUG_NO_REVERB
+- gnReverbSend = 0;
+-#endif
+-
+- // Resetting sound buffer
+- StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
+- if (gnChannels >= 2)
+- {
+- lSampleCount *= 2;
+- m_nMixStat += CreateStereoMix(lCount);
+-#if 0
+- if (nMaxPlugins) ProcessPlugins(lCount);
+-#endif
+- ProcessStereoDSP(lCount);
+- } else
+- {
+- m_nMixStat += CreateStereoMix(lCount);
+-#if 0
+- if (nMaxPlugins) ProcessPlugins(lCount);
+-#endif
+- MonoFromStereo(MixSoundBuffer, lCount);
+- ProcessMonoDSP(lCount);
+- }
+-
+- if (gdwSoundSetup & SNDMIX_EQ)
+- {
+- if (gnChannels >= 2)
+- EQStereo(MixSoundBuffer, lCount);
+- else
+- EQMono(MixSoundBuffer, lCount);
+- }
+-
+-
+- nStat++;
+-#ifndef NO_AGC
+- // Automatic Gain Control
+- if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
+-#endif
+- lTotalSampleCount = lSampleCount;
+- // Multichannel
+- if (gnChannels > 2)
+- {
+- InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
+- lTotalSampleCount *= 2;
+- }
+- // Hook Function
+- if (gpSndMixHook)
+- {
+- gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
+- }
+- // Perform clipping + VU-Meter
+- lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max);
+- // Buffer ready
+- lRead -= lCount;
+- m_nBufferCount -= lCount;
+- }
+-MixDone:
+- if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
+- // VU-Meter
+- vu_min[0] >>= 18;
+- vu_min[1] >>= 18;
+- vu_max[0] >>= 18;
+- vu_max[1] >>= 18;
+- if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0];
+- if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1];
+- if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF)
+- gnVULeft = 0xFF;
+- if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF)
+- gnVURight = 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()
+-//-------------------------
+-{
+- // Checking end of row ?
+- if (m_dwSongFlags & SONG_PAUSED)
+- {
+- /*m_nTickCount = 0;*/
+- if (!m_nMusicSpeed) m_nMusicSpeed = 6;
+- if (!m_nMusicTempo) m_nMusicTempo = 125;
+- m_nPatternDelay = 0;
+- m_nFrameDelay = 0;
+-
+- m_dwSongFlags |= SONG_FIRSTTICK;
+- if (m_nTickCount) {
+- m_dwSongFlags &= ~SONG_FIRSTTICK;
+- }
+-
+- ProcessEffects();
+- m_nTickCount++;
+- if (m_nTickCount >= m_nMusicSpeed) {
+- m_nTickCount = 0;
+- }
+- if (!ProcessEffects()) return FALSE;
+- } else
+- {
+- if (!ProcessRow()) return FALSE;
+- }
+-
+- { /* handle realtime closures */
+- MODCHANNEL *pChn = Chn;
+- for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++) {
+- /* reset end of "row" */
+- if (pChn->nRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) {
+- pChn->nRealtime = 0;
+- pChn->nRowNote = 0;
+- pChn->nRowInstr = 0;
+- //pChn->nMaster
+- pChn->nRowVolCmd = 0;
+- pChn->nRowVolume = 0;
+- pChn->nRowCommand = 0;
+- pChn->nRowParam = 0;
+- pChn->nTickStart = 0;
+- }
+- }
+- };
+-
+- ////////////////////////////////////////////////////////////////////////////////////
+- m_nTotalCount++;
+- if (!m_nMusicTempo) return FALSE;
+- m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
+-#ifdef MODPLUG_TRACKER
+- if (m_dwSongFlags & SONG_PAUSED)
+- {
+- m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds
+- }
+-#endif
+-
+- // Master Volume + Pre-Amplification / Attenuation setup
+- DWORD nMasterVol;
+- {
+- int nchn32 = 0;
+- MODCHANNEL *pChn = Chn;
+- for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) {
+- nchn32++;
+- }
+- if (nchn32 < 1) nchn32 = 1;
+- if (nchn32 > 31) nchn32 = 31;
+-
+- int realmastervol = m_nMasterVolume;
+- if (realmastervol > 0x80)
+- {
+- realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
+- }
+-
+- DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6;
+-// if (mastervol > 0x200) mastervol = 0x200;
+- if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples))
+- {
+- mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
+- }
+-
+- UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
+- if (attenuation < 1) attenuation = 1;
+-
+- nMasterVol = (mastervol << 7) / attenuation;
+- if (nMasterVol > 0x180) nMasterVol = 0x180;
+- }
+- ////////////////////////////////////////////////////////////////////////////////////
+- // Update channels data
+- if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE;
+- 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 ((nChn >= m_nChannels) && (!pChn->nLength))
+- {
+- pChn->nLeftVU = pChn->nRightVU = 0;
+- 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 ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+- {
+- INSTRUMENTHEADER *penv = pChn->pHeader;
+- // Volume Envelope
+- if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes))
+- {
+- int envpos = pChn->nVolEnvPosition;
+- UINT pt = penv->VolEnv.nNodes - 1;
+- for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++)
+- {
+- if (envpos <= penv->VolEnv.Ticks[i])
+- {
+- pt = i;
+- break;
+- }
+- }
+- int x2 = penv->VolEnv.Ticks[pt];
+- int x1, envvol;
+- if (envpos >= x2)
+- {
+- envvol = penv->VolEnv.Values[pt] << 2;
+- x1 = x2;
+- } else
+- if (pt)
+- {
+- envvol = penv->VolEnv.Values[pt-1] << 2;
+- x1 = penv->VolEnv.Ticks[pt-1];
+- } else
+- {
+- envvol = 0;
+- x1 = 0;
+- }
+- if (envpos > x2) envpos = x2;
+- if ((x2 > x1) && (envpos > x1))
+- {
+- envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[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->PanEnv.nNodes))
+- {
+- int envpos = pChn->nPanEnvPosition;
+- UINT pt = penv->PanEnv.nNodes - 1;
+- for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++)
+- {
+- if (envpos <= penv->PanEnv.Ticks[i])
+- {
+- pt = i;
+- break;
+- }
+- }
+- int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt];
+- int x1, envpan;
+- if (envpos >= x2)
+- {
+- envpan = y2;
+- x1 = x2;
+- } else
+- if (pt)
+- {
+- envpan = penv->PanEnv.Values[pt-1];
+- x1 = penv->PanEnv.Ticks[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)
+- {
+-#if 0
+- 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;
+-#else
+- case 1: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
+- case 2: period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
+-#endif
+- }
+- }
+-
+- if (m_dwSongFlags & SONG_AMIGALIMITS)
+- {
+- if (period < 113*4) period = 113*4;
+- if (period > 856*4) period = 856*4;
+- }
+-
+- // Pitch/Filter Envelope
+- int envpitch = 0;
+- if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader)
+- && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes))
+- {
+- INSTRUMENTHEADER *penv = pChn->pHeader;
+- int envpos = pChn->nPitchEnvPosition;
+- UINT pt = penv->PitchEnv.nNodes - 1;
+- for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++)
+- {
+- if (envpos <= penv->PitchEnv.Ticks[i])
+- {
+- pt = i;
+- break;
+- }
+- }
+- int x2 = penv->PitchEnv.Ticks[pt];
+- int x1;
+- if (envpos >= x2)
+- {
+- envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
+- x1 = x2;
+- } else
+- if (pt)
+- {
+- envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8;
+- x1 = penv->PitchEnv.Ticks[pt-1];
+- } else
+- {
+- envpitch = 0;
+- x1 = 0;
+- }
+- if (envpos > x2) envpos = x2;
+- if ((x2 > x1) && (envpos > x1))
+- {
+- int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
+- envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
+- }
+- if (envpitch < -256) envpitch = -256;
+- if (envpitch > 256) envpitch = 256;
+- // Pitch Envelope
+- if (!(penv->dwFlags & ENV_FILTER))
+- {
+- 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;
+- /* this isn't correct, but its better... */
+-
+- if (pins->nVibSweep == 0) {
+- pChn->nAutoVibDepth = pins->nVibDepth << 8;
+- } else {
+- pChn->nAutoVibDepth += pins->nVibSweep;
+- if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth)
+- pChn->nAutoVibDepth = pins->nVibDepth << 8;
+- }
+-#if 0
+- if (pins->nVibSweep == 0)
+- {
+- pChn->nAutoVibDepth = pins->nVibDepth << 8;
+- } else
+- {
+- if (m_nType & MOD_TYPE_IT)
+- {
+- pChn->nAutoVibDepth += pins->nVibSweep;
+- } else
+- if (!(pChn->dwFlags & CHN_KEYOFF))
+- {
+- pChn->nAutoVibDepth += (pins->nVibDepth << 8) / pins->nVibSweep;
+- }
+- if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
+- pChn->nAutoVibDepth = pins->nVibDepth << 8;
+- }
+-#endif
+- pChn->nAutoVibPos += ((int)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);
+- // is this right? -mrsb
+- if (!(m_dwSongFlags & SONG_ITOLDEFFECTS))
+- n >>= 1;
+-
+- 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);
+-
+- // Filter Envelope: controls cutoff frequency
+- if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER)
+- {
+-#ifndef NO_FILTER
+- SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
+-#endif // NO_FILTER
+- }
+-
+-#if 0
+- if ((m_nType & MOD_TYPE_IT) && (freq < 256))
+- {
+- pChn->nFadeOutVol = 0;
+- pChn->dwFlags |= CHN_NOTEFADE;
+- pChn->nRealVolume = 0;
+- }
+-#endif
+- pChn->sample_freq = freq;
+-
+- 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 ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+- {
+- INSTRUMENTHEADER *penv = pChn->pHeader;
+- // Volume Envelope
+- if (pChn->dwFlags & CHN_VOLENV)
+- {
+- // Increase position
+- pChn->nVolEnvPosition++;
+- // Volume Loop ?
+- if (penv->dwFlags & ENV_VOLLOOP)
+- {
+- int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd];
+- if (m_nType != MOD_TYPE_XM) volloopend++;
+- if (pChn->nVolEnvPosition == volloopend)
+- {
+- pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart];
+- if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart])
+- && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes)))
+- {
+- pChn->dwFlags |= CHN_NOTEFADE;
+- pChn->nFadeOutVol = 0;
+- }
+- }
+- }
+- // Volume Sustain ?
+- if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
+- {
+- if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1)
+- pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart];
+- } else
+- // End of Envelope ?
+- if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1])
+- {
+- if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE;
+- pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1];
+- if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-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)
+- {
+- int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd];
+- if (m_nType != MOD_TYPE_XM) panloopend++;
+- if (pChn->nPanEnvPosition == panloopend)
+- pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart];
+- }
+- // Panning Sustain ?
+- if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1)
+- && (!(pChn->dwFlags & CHN_KEYOFF)))
+- {
+- // Panning sustained
+- pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart];
+- } else
+- {
+- if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1])
+- pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1];
+- }
+- }
+- // Pitch Envelope
+- if (pChn->dwFlags & CHN_PITCHENV)
+- {
+- // Increase position
+- pChn->nPitchEnvPosition++;
+- // Pitch Loop ?
+- if (penv->dwFlags & ENV_PITCHLOOP)
+- {
+- if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd])
+- pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart];
+- }
+- // Pitch Sustain ?
+- if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
+- {
+- if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1)
+- pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart];
+- } else
+- {
+- if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1])
+- pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1];
+- }
+- }
+- }
+-#if 0
+- // 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;
+- // Decrease VU-Meter
+- if (pChn->nVUMeter > VUMETER_DECAY) pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0;
+- 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;
+- // 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)
+- 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;
+- 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;
+-#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;
+- if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
+- if (m_dwSongFlags & SONG_NOSTEREO) pan = 128;
+- 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_HQSRC);
+- 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) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0)
+- pChn->nNewLeftVol = -pChn->nNewLeftVol;
+- // Checking Ping-Pong Loops
+- if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc;
+- // Setting up volume ramp
+- if (!(gdwSoundSetup & SNDMIX_NORAMPING)
+- && (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);
+-#if 0
+- if ((gdwSoundSetup & SNDMIX_DIRECTTODISK)
+- || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU))
+- && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20)))
+-#else
+- if (gdwSoundSetup & SNDMIX_HQRESAMPLER)
+-#endif
+- {
+- 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;
+- }
+- }
+- 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
+- if (!(pChn->dwFlags & CHN_MUTE)) {
+- ChnMix[m_nMixChannels++] = nChn;
+- if (m_nMixChannels >= MAX_CHANNELS) break;
+- }
+- } else
+- {
+- // Note change but no sample
+- if (pChn->nLeftVU > 128) pChn->nLeftVU = 0;
+- if (pChn->nRightVU > 128) pChn->nRightVU = 0;
+- 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;
+-}
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/stdafx.h 3.0.3/src/modplug/stdafx.h
+--- audacious-plugins-3.0.2/src/modplug/stdafx.h 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/stdafx.h 1970-01-01 01:00:00.000000000 +0100
+@@ -1,94 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Rani Assaf <rani at magic.metawire.com>,
+- * Olivier Lapicque <olivierl at jps.net>,
+- * Adam Goode <adam at 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;
+-typedef unsigned int ULONG;
+-typedef unsigned int UINT;
+-typedef unsigned int DWORD;
+-typedef int LONG;
+-typedef unsigned short WORD;
+-typedef unsigned char BYTE;
+-typedef unsigned char * LPBYTE;
+-#ifdef __cplusplus
+-typedef bool BOOL;
+-#endif
+-typedef char * LPSTR;
+-typedef void * LPVOID;
+-typedef int * LPLONG;
+-typedef unsigned int * LPDWORD;
+-typedef unsigned short * LPWORD;
+-typedef const char * LPCSTR;
+-typedef long long LONGLONG;
+-typedef void * PVOID;
+-typedef void VOID;
+-
+-
+-#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
+-
+-#ifdef __cplusplus
+-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) {}
+-
+-#define GlobalFreePtr(p) free((void *)(p))
+-
+-#define strnicmp(a,b,c) strncasecmp(a,b,c)
+-#define wsprintf sprintf
+-#endif
+-
+-#ifndef FALSE
+-#define FALSE false
+-#endif
+-
+-#ifndef TRUE
+-#define TRUE true
+-#endif
+-
+-#endif // MSC_VER
+-
+-#endif
+-
+-
+-
+diff -Nur audacious-plugins-3.0.2/src/modplug/tables.cxx 3.0.3/src/modplug/tables.cxx
+--- audacious-plugins-3.0.2/src/modplug/tables.cxx 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/modplug/tables.cxx 1970-01-01 01:00:00.000000000 +0100
+@@ -1,373 +0,0 @@
+-/*
+- * This source code is public domain.
+- *
+- * Authors: Olivier Lapicque <olivierl at jps.net>
+- */
+-
+-#include "stdafx.h"
+-#include "sndfile.h"
+-
+-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,
+-};
+-
+diff -Nur audacious-plugins-3.0.2/src/mpg123/mpg123.c 3.0.3/src/mpg123/mpg123.c
+diff -Nur audacious-plugins-3.0.2/src/notify/libnotify-aosd_event.c 3.0.3/src/notify/libnotify-aosd_event.c
+--- audacious-plugins-3.0.2/src/notify/libnotify-aosd_event.c 2011-08-24 20:52:51.000000000 +0200
++++ 3.0.3/src/notify/libnotify-aosd_event.c 2011-09-07 22:45:40.000000000 +0200
+@@ -75,6 +75,7 @@
+ if (! GPOINTER_TO_INT (explicit) && last_title && last_message && ! strcmp
+ (title, last_title) && ! strcmp (message, last_message))
+ {
++ g_free (title);
+ g_free (message);
+ return;
+ }
+diff -Nur audacious-plugins-3.0.2/src/skins/Makefile 3.0.3/src/skins/Makefile
diff --git a/audacious-plugins.spec b/audacious-plugins.spec
index 9971dbd..1a35d5d 100644
--- a/audacious-plugins.spec
+++ b/audacious-plugins.spec
@@ -10,7 +10,7 @@ Requires: audacious >= %{aud_ver}
Name: audacious-plugins
Version: 3.0.2
-Release: 1%{?dist}
+Release: 2%{?dist}
Summary: Plugins for the Audacious audio player
Group: Applications/Multimedia
URL: http://audacious-media-player.org/
@@ -31,9 +31,12 @@ Patch0: audacious-plugins-3.0-alpha1-xmms-skindir.patch
#Patch1: audacious-plugins-2.4-libdir.patch
# Fedora customization (RFE bz #632388)
Patch2: audacious-plugins-3.0-alpha1-enable-gnomeshortcuts.patch
+# from post-3.0.2 git
+Patch3: audacious-plugins-3.0.2-pre3.0.3.patch
+BuildRequires: autoconf
BuildRequires: audacious-devel >= %{aud_ver}
-BuildRequires: gettext
+BuildRequires: gettext-devel
BuildRequires: desktop-file-utils
BuildRequires: jack-audio-connection-kit-devel
BuildRequires: libsamplerate-devel
@@ -42,6 +45,7 @@ BuildRequires: pulseaudio-libs-devel
BuildRequires: libsndfile-devel
BuildRequires: wavpack-devel
BuildRequires: libsidplay-devel
+BuildRequires: libmodplug-devel
BuildRequires: libogg-devel libvorbis-devel
BuildRequires: flac-devel
BuildRequires: fluidsynth-devel
@@ -157,6 +161,8 @@ providers may build it with libsidplay 2 instead.
%patch0 -p1 -b .xmms-skindir
#patch1 -p1 -b .libdir
%patch2 -p1 -b .enable-gnomeshortcuts
+%patch3 -p1 -b .pre-3.0.3
+autoreconf -I m4
#for i in src/ladspa/ladspa.c
#do
@@ -271,6 +277,10 @@ update-desktop-database &> /dev/null || :
%changelog
+* Thu Sep 8 2011 Michael Schwendt <mschwendt at fedoraproject.org> - 3.0.2-2
+- Merge changes from pre-3.0.3 git, such as using libmodplug system
+ library (BR libmodplug-devel).
+
* Thu Aug 25 2011 Michael Schwendt <mschwendt at fedoraproject.org> - 3.0.2-1
- Update to 3.0.2 (few more fixes, 7k diff).
More information about the scm-commits
mailing list