changeset 49:033c660c25f5

Restructure module playing, removing 8bit sample mixing (output can still be 8bit, but samples are internally upconverted to 16bit after module loading.) Also prepare for floating point mixing support.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 01 Oct 2012 02:51:41 +0300
parents ee87513fff15
children 4cbdaa3f5d74
files Makefile.gen config.mak.in jmix_c_in.c jmix_post_c.h jmixtmpl_c.h jssmix.c jssmix.h jssmod.c jssmod.h mod2wav.c testpl.c
diffstat 11 files changed, 265 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Mon Oct 01 01:29:26 2012 +0300
+++ b/Makefile.gen	Mon Oct 01 02:51:41 2012 +0300
@@ -110,6 +110,10 @@
 endif
 endif
 
+ifeq ($(JSS_MIX_FP),yes)
+DM_CFLAGS+=-DJSS_MIX_FP
+endif
+
 ifeq ($(JSS_SUP_THREADS),yes)
 DM_CFLAGS+=-DJSS_SUP_THREADS
 endif
@@ -206,7 +210,7 @@
 ### dmlib rules
 ###
 
-$(DMLIB)jmix_c.c: $(DMLIB)jmix_c.in.c $(DMLIB)jmix_c.h $(DMLIB)jmix_post.h
+$(DMLIB)jmix_c.c: $(DMLIB)jmix_c_in.c $(DMLIB)jmixtmpl_c.h $(DMLIB)jmix_post_c.h
 	(echo "#include \"jssmix.h\"" && cpp $<) | sed "s/^# .*//g" > $@
 
 $(OBJPATH)dmimage.o: $(DMLIB)dmimage.c $(DMLIB)stb_image.c
--- a/config.mak.in	Mon Oct 01 01:29:26 2012 +0300
+++ b/config.mak.in	Mon Oct 01 02:51:41 2012 +0300
@@ -32,6 +32,9 @@
 ###
 JSS=yes
 
+# Use floating point mixing
+JSS_MIX_FP=no
+
 # Build a special "light"/minimized version by removing all
 # error messages and few other things.
 JSS_LIGHT=no
--- a/jmix_c_in.c	Mon Oct 01 01:29:26 2012 +0300
+++ b/jmix_c_in.c	Mon Oct 01 02:51:41 2012 +0300
@@ -4,100 +4,174 @@
  * (C) Copyright 2006-2007 Tecnic Software productions (TNSP)
  */
 
-#define JMIXER_INTERPOLATE
 //#define JMIXER_DEBUG fprintf(stderr, "[%.8x:%.8x / %.8x]: %d\n", FP_GETH(tmpPos), FP_GETL(tmpPos), endPos, sp[FP_GETH(tmpPos)]);
 #define JMIXER_DEBUG
 
 /* Mono / Linear Interpolation
  */
-#define JMIXER_INIT         const Sint32 vol = (chn->chVolume * mixer->globalVol) / 256;
-#ifdef JMIXER_INTERPOLATE
-#define JMIXER_FUNC_16      tr = (((Sint32) sp[FP_GETH(tmpPos)]) * vol + tr) / (256 * 2); *(ap++) += tr;
-#define JMIXER_FUNC_8       tr = ((*volTab8)[vol][sp[FP_GETH(tmpPos)]] + tr) / 2; *(ap++) += tr;
-#else
-#define JMIXER_FUNC_16      *(ap++) += (((Sint32) sp[FP_GETH(tmpPos)]) * vol) / 256;
-#define JMIXER_FUNC_8       *(ap++) += (*volTab8)[vol][sp[FP_GETH(tmpPos)]];
-#endif
+#ifdef JSS_MIX_FP
+#define JMIXER_ADDBUF_TYPE float
+#define JMIXER_SAMPLE_TYPE float
+#define JMIXER_INIT        const float vol = (float) (chn->chVolume * mixer->globalVol) / (256.0f * 64.0f);
+#define JMIXER_FUNC        tr = (sp[FP_GETH(tmpPos)] * vol + tr) / 2.0f; *(ap++) += tr;
+
+
+#define JMIXER_NAME        jvmMix_Mono_C_FW
+#define JMIXER_NEXT        FP_ADD(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) < endPos)
+#include "jmixtmpl_c.h"
+
+
+#define JMIXER_NAME        jvmMix_Mono_C_BW
+#define JMIXER_NEXT        FP_SUB(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) > endPos)
+#include "jmixtmpl_c.h"
+
+#undef JMIXER_ADDBUF_TYPE
+#undef JMIXER_SAMPLE_TYPE
+#undef JMIXER_INIT
+#undef JMIXER_FUNC
 
-#define JMIXER_NAME         jvmMix_Mono_C_FW
-#define JMIXER_NEXT         FP_ADD(tmpPos, tmpDelta);
-#define JMIXER_ENDCOND      (FP_GETH(tmpPos) < endPos)
-#include "jmix_c.h"
+#else
+
+#define JMIXER_ADDBUF_TYPE Sint32
+#define JMIXER_SAMPLE_TYPE Sint16
+#define JMIXER_INIT        const Sint32 vol = (chn->chVolume * mixer->globalVol) / 256;
+#define JMIXER_FUNC        tr = (((Sint32) sp[FP_GETH(tmpPos)]) * vol + tr) / (256 * 2); *(ap++) += tr;
+
+#define JMIXER_NAME        jvmMix_Mono_C_FW
+#define JMIXER_NEXT        FP_ADD(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) < endPos)
+#include "jmixtmpl_c.h"
 
-#define JMIXER_NAME         jvmMix_Mono_C_BW
-#define JMIXER_NEXT         FP_SUB(tmpPos, tmpDelta);
-#define JMIXER_ENDCOND      (FP_GETH(tmpPos) > endPos)
-#include "jmix_c.h"
+#define JMIXER_NAME        jvmMix_Mono_C_BW
+#define JMIXER_NEXT        FP_SUB(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) > endPos)
+#include "jmixtmpl_c.h"
 
+#undef JMIXER_ADDBUF_TYPE
+#undef JMIXER_SAMPLE_TYPE
 #undef JMIXER_INIT
-#undef JMIXER_FUNC_16
-#undef JMIXER_FUNC_8
+#undef JMIXER_FUNC
 
+#endif
 
 /* Stereo / Linear Interpolation
  */
-#define JMIXER_INIT         const Sint32    vol_l = (chn->chVolume * mixer->globalVol) / 256, \
-                            vol_r = (chn->chVolume * mixer->globalVol) / 256;
-#ifdef JMIXER_INTERPOLATE
-#define JMIXER_FUNC_16      tl = (((Sint32) sp[FP_GETH(tmpPos)]) * vol_l + tl) / (256 * 2); *(ap++) += tl; \
-                            tr = (((Sint32) sp[FP_GETH(tmpPos)]) * vol_r + tr) / (256 * 2); *(ap++) += tr;
-#define JMIXER_FUNC_8       tl = ((*volTab8)[vol_l][sp[FP_GETH(tmpPos)]] + tl) / 2; *(ap++) += tl; \
-                            tr = ((*volTab8)[vol_r][sp[FP_GETH(tmpPos)]] + tr) / 2; *(ap++) += tr;
-#else
-#define JMIXER_FUNC_16      *(ap++) += (((Sint32) sp[FP_GETH(tmpPos)]) * vol_l) / 256; \
-                            *(ap++) += (((Sint32) sp[FP_GETH(tmpPos)]) * vol_r) / 256;
-#define JMIXER_FUNC_8       *(ap++) += (*volTab8)[vol_l][sp[FP_GETH(tmpPos)]]; \
-                            *(ap++) += (*volTab8)[vol_r][sp[FP_GETH(tmpPos)]];
-#endif
+#ifdef JSS_MIX_FP
+#define JMIXER_ADDBUF_TYPE float
+#define JMIXER_SAMPLE_TYPE float
+#define JMIXER_INIT        const float vol_l = (chn->chVolume * mixer->globalVol) / (256.0f * 64.0f), \
+                                       vol_r = (chn->chVolume * mixer->globalVol) / (256.0f * 64.0f);
+
+#define JMIXER_FUNC        tl = (sp[FP_GETH(tmpPos)] * vol_l + tl) / 2.0f; *(ap++) += tl; \
+                           tr = (sp[FP_GETH(tmpPos)] * vol_r + tr) / 2.0f; *(ap++) += tr;
+
+#define JMIXER_NAME        jvmMix_Stereo_C_FW
+#define JMIXER_NEXT        FP_ADD(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) < endPos)
+#include "jmixtmpl_c.h"
+
+#define JMIXER_NAME        jvmMix_Stereo_C_BW
+#define JMIXER_NEXT        FP_SUB(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) > endPos)
+#include "jmixtmpl_c.h"
+
+#undef JMIXER_ADDBUF_TYPE
+#undef JMIXER_SAMPLE_TYPE
+#undef JMIXER_INIT
+#undef JMIXER_FUNC
 
-#define JMIXER_NAME         jvmMix_Stereo_C_FW
-#define JMIXER_NEXT         FP_ADD(tmpPos, tmpDelta);
-#define JMIXER_ENDCOND      (FP_GETH(tmpPos) < endPos)
-#include "jmix_c.h"
+#else
+
+#define JMIXER_ADDBUF_TYPE Sint32
+#define JMIXER_SAMPLE_TYPE Sint16
+#define JMIXER_INIT        const Sint32 vol_l = (chn->chVolume * mixer->globalVol) / 256, \
+                                        vol_r = (chn->chVolume * mixer->globalVol) / 256;
+
+#define JMIXER_FUNC        tl = (((Sint32) sp[FP_GETH(tmpPos)]) * vol_l + tl) / (256 * 2); *(ap++) += tl; \
+                           tr = (((Sint32) sp[FP_GETH(tmpPos)]) * vol_r + tr) / (256 * 2); *(ap++) += tr;
 
-#define JMIXER_NAME         jvmMix_Stereo_C_BW
-#define JMIXER_NEXT         FP_SUB(tmpPos, tmpDelta);
-#define JMIXER_ENDCOND      (FP_GETH(tmpPos) > endPos)
-#include "jmix_c.h"
+#define JMIXER_NAME        jvmMix_Stereo_C_FW
+#define JMIXER_NEXT        FP_ADD(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) < endPos)
+#include "jmixtmpl_c.h"
 
+#define JMIXER_NAME        jvmMix_Stereo_C_BW
+#define JMIXER_NEXT        FP_SUB(tmpPos, tmpDelta);
+#define JMIXER_ENDCOND     (FP_GETH(tmpPos) > endPos)
+#include "jmixtmpl_c.h"
+
+#undef JMIXER_ADDBUF_TYPE
+#undef JMIXER_SAMPLE_TYPE
 #undef JMIXER_INIT
-#undef JMIXER_FUNC_16
-#undef JMIXER_FUNC_8
+#undef JMIXER_FUNC
 
+#endif
 
 /* Post processing functions
  */
+#ifdef JSS_MIX_FP
+
+#define JMIXER_ADDBUF_TYPE float
+
+#define JMIXER_CLAMP                  \
+    if (t < -1.0f) t = -1.0f; else    \
+    if (t >  1.0f) t =  1.0f;         \
+
 #define JMIXER_NAME jvmPostProcess_U8_C
 #define JMIXER_TYPE Uint8
-#define JMIXER_FUNCTION                                     \
-    if (t < JVM_LIMIT_16_NEG) t = JVM_LIMIT_16_NEG; else    \
-    if (t > JVM_LIMIT_16_POS) t = JVM_LIMIT_16_POS;         \
-    *(sp++) = (t + JVM_ADD_16) >> 8;
-#include "jmix_post.h"
+#define JMIXER_FUNCTION *(sp++) = (t + 1.0f) * 127.0f;
+#include "jmix_post_c.h"
 
 
 #define JMIXER_NAME jvmPostProcess_S8_C
 #define JMIXER_TYPE Sint8
-#define JMIXER_FUNCTION                                     \
-    if (t < JVM_LIMIT_16_NEG) t = JVM_LIMIT_16_NEG; else    \
-    if (t > JVM_LIMIT_16_POS) t = JVM_LIMIT_16_POS;         \
-    *(sp++) = t >> 8;
-#include "jmix_post.h"
+#define JMIXER_FUNCTION *(sp++) = t * 127.0f;
+#include "jmix_post_c.h"
 
 
 #define JMIXER_NAME jvmPostProcess_U16_C
 #define JMIXER_TYPE Uint16
-#define JMIXER_FUNCTION                                     \
-    if (t < JVM_LIMIT_16_NEG) t = JVM_LIMIT_16_NEG; else    \
-    if (t > JVM_LIMIT_16_POS) t = JVM_LIMIT_16_POS;         \
-    *(sp++) = t + JVM_ADD_16;
-#include "jmix_post.h"
+#define JMIXER_FUNCTION *(sp++) = (t + 1.0f) * 32767.0f;
+#include "jmix_post_c.h"
 
 
 #define JMIXER_NAME jvmPostProcess_S16_C
 #define JMIXER_TYPE Sint16
-#define JMIXER_FUNCTION                                     \
+#define JMIXER_FUNCTION *(sp++) = t * 32767.0f;
+#include "jmix_post_c.h"
+
+
+#else
+
+#define JMIXER_ADDBUF_TYPE Sint32
+
+#define JMIXER_CLAMP \
     if (t < JVM_LIMIT_16_NEG) t = JVM_LIMIT_16_NEG; else    \
     if (t > JVM_LIMIT_16_POS) t = JVM_LIMIT_16_POS;         \
-    *(sp++) = t;
-#include "jmix_post.h"
+
+#define JMIXER_NAME jvmPostProcess_U8_C
+#define JMIXER_TYPE Uint8
+#define JMIXER_FUNCTION *(sp++) = (t + JVM_ADD_16) >> 8;
+#include "jmix_post_c.h"
+
+
+#define JMIXER_NAME jvmPostProcess_S8_C
+#define JMIXER_TYPE Sint8
+#define JMIXER_FUNCTION *(sp++) = t >> 8;
+#include "jmix_post_c.h"
+
+
+#define JMIXER_NAME jvmPostProcess_U16_C
+#define JMIXER_TYPE Uint16
+#define JMIXER_FUNCTION *(sp++) = t + JVM_ADD_16;
+#include "jmix_post_c.h"
+
+
+#define JMIXER_NAME jvmPostProcess_S16_C
+#define JMIXER_TYPE Sint16
+#define JMIXER_FUNCTION *(sp++) = t;
+#include "jmix_post_c.h"
+
+#endif
--- a/jmix_post_c.h	Mon Oct 01 01:29:26 2012 +0300
+++ b/jmix_post_c.h	Mon Oct 01 02:51:41 2012 +0300
@@ -5,16 +5,18 @@
  */
 
 #ifdef JMIXER_HEADER
-void JMIXER_NAME (Sint32 *, void *, const int);
+void JMIXER_NAME (JMIXER_ADDBUF_TYPE *, void *, const int);
 #else
-void JMIXER_NAME (Sint32 *addBuffer, void *mixBuffer, const int mixLength)
+void JMIXER_NAME (JMIXER_ADDBUF_TYPE *addBuffer, void *mixBuffer, const int mixLength)
 {
     int strideLength = mixLength;
-    Sint32 *ap = addBuffer, t;
+    JMIXER_ADDBUF_TYPE *ap = addBuffer, t;
     JMIXER_TYPE *sp = (JMIXER_TYPE *) mixBuffer;
 
-    while (strideLength--) {
+    while (strideLength--)
+    {
         t = *(ap++);
+        JMIXER_CLAMP
         JMIXER_FUNCTION
     }
 }
--- a/jmixtmpl_c.h	Mon Oct 01 01:29:26 2012 +0300
+++ b/jmixtmpl_c.h	Mon Oct 01 02:51:41 2012 +0300
@@ -7,49 +7,35 @@
 #ifdef JMIXER_HEADER
 int JMIXER_NAME (JSSMixer *, JSSChannel *, Sint32 *, const int, const Sint32);
 #else
-int JMIXER_NAME (JSSMixer *mixer, JSSChannel *chn, Sint32 *addBuffer, const int mixLength, const Sint32 endPos)
+int JMIXER_NAME (JSSMixer *mixer, JSSChannel *chn, JMIXER_ADDBUF_TYPE *addBuffer, const int mixLength, const Sint32 endPos)
 {
-    const JSSVolumeTable *volTab8 = (const JSSVolumeTable *) &(mixer->volTab8);
-    Sint32 *ap = addBuffer;
-    Sint32 tr = chn->chPrevR, tl = chn->chPrevL;
-    DMFixedPoint tmpPos = chn->chPos;
     const DMFixedPoint tmpDelta = chn->chDeltaO;
+    DMFixedPoint tmpPos = chn->chPos;
+    JMIXER_ADDBUF_TYPE
+        *ap = addBuffer,
+        tr = chn->chPrevR,
+        tl = chn->chPrevL;
     int strideLength = 0;
-    
-    if (chn->chFlags & jsf16bit)
-    {
-        Sint16 *sp = (Sint16 *) chn->chData;
-        JMIXER_INIT
+    JMIXER_SAMPLE_TYPE *sp = (JMIXER_SAMPLE_TYPE *) chn->chData;
 
-        while (strideLength < mixLength && JMIXER_ENDCOND)
-        {
-            JMIXER_FUNC_16
-            JMIXER_DEBUG
-            JMIXER_NEXT
-            strideLength++;
-        }
-    }
-    else
+    JMIXER_INIT
+
+    while (strideLength < mixLength && JMIXER_ENDCOND)
     {
-        Uint8 *sp = (Uint8 *) chn->chData;
-        JMIXER_INIT
-
-        while (strideLength < mixLength && JMIXER_ENDCOND)
-        {
-            JMIXER_FUNC_8
-            JMIXER_DEBUG
-            JMIXER_NEXT
-            strideLength++;
-        }
-
+        JMIXER_FUNC
+        JMIXER_DEBUG
+        JMIXER_NEXT
+        strideLength++;
     }
 
     chn->chPos.dw = tmpPos.dw;
-    chn->chPrevR = tr; chn->chPrevL = tl;
+    chn->chPrevR = tr;
+    chn->chPrevL = tl;
     return strideLength;
 }
 #endif
 
-#undef JMIXER_NAME   
-#undef JMIXER_NEXT   
+#undef JMIXER_NAME
+#undef JMIXER_NEXT
 #undef JMIXER_ENDCOND
+
--- a/jssmix.c	Mon Oct 01 01:29:26 2012 +0300
+++ b/jssmix.c	Mon Oct 01 02:51:41 2012 +0300
@@ -9,7 +9,7 @@
 
 #ifdef DM_USE_C
 #define JMIXER_HEADER
-#include "jmix_c.in.c"
+#include "jmix_c_in.c"
 #undef JMIXER_HEADER
 #endif
 
@@ -17,7 +17,7 @@
 
 #ifdef DM_USE_SIMD
 #define JMIXER_HEADER
-#include "jmix_mmx.in.c"
+#include "jmix_mmx_in.c"
 #undef JMIXER_HEADER
 #endif
 
@@ -85,7 +85,7 @@
 JSSMixer *jvmInit(const int outFormat, const int outChannels, const int outFreq, const int mixerID)
 {
     JSSMixer *mixer;
-    int mixerIdx, v, i;
+    int mixerIdx;
 
     // Check settings
     if (outChannels < 1)
@@ -155,15 +155,6 @@
         "Could not allocate mixing addition buffer.\n");
     }
     
-    // Initialize 8-bit volume table
-    for (v = jsetMinVol; v < jsetMaxVol; v++)
-    {
-        for (i = 0; i < 256; i++)
-        {
-            mixer->volTab8[v][i] = (v * (i - 128));
-        }
-    }
-
     return mixer;
 }
 
--- a/jssmix.h	Mon Oct 01 01:29:26 2012 +0300
+++ b/jssmix.h	Mon Oct 01 02:51:41 2012 +0300
@@ -47,8 +47,6 @@
 // Channel table
 typedef int JSSChannelTable[jsetNChannels];
 
-typedef Sint32 JSSVolumeTable[256][256];
-
 
 // Virtual software mixer "device" structure
 typedef struct _JSSMixer JSSMixer;
@@ -60,7 +58,6 @@
                     outFreq,
                     globalVol;
     JSSChannel      channels[jsetNChannels];
-    JSSVolumeTable  volTab8;
     
     int             addBufSize;
     Sint32         *addBuffer;
--- a/jssmod.c	Mon Oct 01 01:29:26 2012 +0300
+++ b/jssmod.c	Mon Oct 01 02:51:41 2012 +0300
@@ -118,37 +118,6 @@
     return TRUE;
 }
 
-
-int jssConvertSampleFromFP(void **dst, void * src, const size_t len, const int flags)
-{
-    // Convert from floating point to 8/16bit
-    size_t count = len;
-    float *in = (float *) src;
-    
-    if (flags & jsf16bit)
-    {
-        Sint16 *out;
-        *dst = out = dmMalloc(sizeof(sizeof(Sint16)) * len);
-        if (out == NULL)
-            return DMERR_MALLOC;
-
-        while (count--)
-            *(out++) = (*(in++) * 32767.0f);
-    }
-    else
-    {
-        Uint8 *out;
-        *dst = out = dmMalloc(sizeof(sizeof(Uint8)) * len);
-        if (out == NULL)
-            return DMERR_MALLOC;
-
-        while (count--)
-            *(out++) = 128 + (int) (*(in++) * 127.0f);
-    }
-    
-    return DMERR_OK;
-}
-
 #endif
 
 
@@ -228,10 +197,11 @@
     return TRUE;
 }
 
-
+#ifdef JSS_MIX_FP
+/* Convert sample data from S16 or U8 to floating point
+ */
 int jssConvertSampleToFP(void **dst, void * src, const size_t len, const int flags)
 {
-    // Convert from 8/16bit to floating point
     size_t count = len;
     float *out;
 
@@ -243,13 +213,86 @@
     {
         Sint16 *in = (Sint16 *) src;
         while (count--)
+        {
             *(out++) = (float) (*(in++)) / 32768.0f;
+        }
     }
     else
     {
         Uint8 *in = (Uint8 *) src;
         while (count--)
+        {
             *(out++) = (float) (*(in++) - 128) / 128.0f;
+        }
+    }
+    
+    return DMERR_OK;
+}
+
+#endif
+
+/* Convert sample data from U8 to S16
+ */
+int jssConvertSampleTo16(void **dst, void * src, const size_t len)
+{
+    size_t count = len;
+    Uint8 *in = (Uint8 *) src;
+    Sint16 *out;
+
+    *dst = out = dmMalloc(sizeof(Sint16) * len);
+    if (out == NULL)
+        return DMERR_MALLOC;
+    
+    while (count--)
+    {
+        *(out++) = (*(in++) * 256) - 32768;
+    }
+    
+    return DMERR_OK;
+}
+
+/* Converts the given module in preparation for playing it.
+ * This involves sample format conversion (8 to 16 bit, or
+ * if floating point mixing is enabled, 8/16 bit to FP.)
+ *
+ * NOTICE! The converted module can only be saved in JSSMOD
+ * format, but this is not recommended.
+ */
+int jssConvertModuleForPlaying(JSSModule *module)
+{
+    int i;
+    if (module == NULL)
+        return DMERR_NULLPTR;
+
+    // Convert instruments
+    for (i = 0; i < module->ninstruments; i++)
+    {
+        JSSInstrument *inst = module->instruments[i];
+        if (inst != NULL && inst->data != NULL)
+        {
+            int res;
+            void *data = NULL;
+#ifdef JSS_MIX_FP
+            if (inst->flags & jsfFP)
+                continue;
+
+            if ((res = jssConvertSampleToFP(&data, inst->data, inst->size, inst->flags)) != DMERR_OK)
+                return res;
+            
+            inst->flags &= !(jsf16bit);
+            inst->flags |= jfsFP;
+#else
+            if (inst->flags & jsf16bit)
+                continue;
+
+            if ((res = jssConvertSampleTo16(&data, inst->data, inst->size)) != DMERR_OK)
+                return res;
+
+            inst->flags |= jsf16bit;
+#endif
+            dmFree(inst->data);
+            inst->data = data;
+        }
     }
     
     return DMERR_OK;
--- a/jssmod.h	Mon Oct 01 01:29:26 2012 +0300
+++ b/jssmod.h	Mon Oct 01 02:51:41 2012 +0300
@@ -69,7 +69,7 @@
 // Internal instrument structure
 typedef struct
 {
-    size_t size,            // Length in units
+    int size,               // Length in units
         loopS,              // Loop start position in units
         loopE;              // Loop end position in units
     int volume,             // Volume [jsetMinVol...jsetMaxVol]
@@ -287,11 +287,13 @@
 char*               jssASCIItoStr(char *, const char, const size_t);
 BOOL                jssEncodeSample8(Uint8 *, const size_t, const int);
 BOOL                jssEncodeSample16(Uint16 *, const size_t, const int);
-int                 jssConvertSampleFromFP(void **dst, void * src, const size_t len, const int flags);
 #endif
 BOOL                jssDecodeSample8(Uint8 *, const size_t, const int);
 BOOL                jssDecodeSample16(Uint16 *, const size_t, const int);
+#ifdef JSS_MIX_FP
 int                 jssConvertSampleToFP(void **dst, void * src, const size_t len, const int flags);
+#endif
+int                 jssConvertModuleForPlaying(JSSModule *module);
 JSSModule *         jssAllocateModule(void);
 int                 jssFreeModule(JSSModule *);
 JSSPattern *        jssAllocatePattern(int, int);
--- a/mod2wav.c	Mon Oct 01 01:29:26 2012 +0300
+++ b/mod2wav.c	Mon Oct 01 02:51:41 2012 +0300
@@ -278,6 +278,14 @@
         return 3;
     }
 
+    // Try to convert it
+    if ((result = jssConvertModuleForPlaying(m)) != DMERR_OK)
+    {
+        fprintf(stderr, "Could not convert module for playing, %d: %s\n",
+            result, dmErrorStr(result));
+        return 3;
+    }
+
     // Open mixer
     d = jvmInit(optOutFormat, optOutChannels, optOutFreq, JMIX_AUTO);
     if (!d)
--- a/testpl.c	Mon Oct 01 01:29:26 2012 +0300
+++ b/testpl.c	Mon Oct 01 02:51:41 2012 +0300
@@ -167,6 +167,13 @@
         return 3;
     }
 
+    // Try to convert it
+    if ((result = jssConvertModuleForPlaying(m)) != DMERR_OK)
+    {
+        fprintf(stderr, "Could not convert module for playing, %d: %s\n",
+            result, dmErrorStr(result));
+        return 3;
+    }
 
     // Initialize SDL audio
     fprintf(stderr, "Pre-initializing params\n");