view jssmod.c @ 0:32250b436bca

Initial re-import.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 28 Sep 2012 01:54:23 +0300
parents
children 048536ad01e0
line wrap: on
line source

/*
 * miniJSS - Module structure and handling routines
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2006-2007 Tecnic Software productions (TNSP)
 */
#include "jssmod.h"
#include <string.h>


#ifndef JSS_LIGHT
/* Take given data until maxlen reached, make a string
 */
char *jssASCIItoStr(char * sdata, const char endByte, const size_t maxLen)
{
    size_t i, k;
    char *res;

    for (i = 0; sdata[i] && i < maxLen; i++);

    res = (char *) dmMalloc(i + 1);
    if (res == NULL)
        return NULL;

    for (k = 0; sdata[k] != endByte && k < i; k++)
        res[k] = sdata[k];

    res[k] = 0;

    return res;
}


/* Encodes a given 8-bit sample
 */
BOOL jssEncodeSample8(Uint8 * sdata, const size_t srcSize, const int ops)
{
    size_t ssize = srcSize;
    Sint8 t, value = 0;
    
    while (ssize--)
    {
        t = *sdata;
        
        if (ops & jsampFlipSign)
            t ^= 0x80;

        if (ops & jsampDelta)
        {
            int n = t - value;
            value = t;
            t = n;
        }
        
        *(sdata++) = t;
    }

    return TRUE;
}


/* Decodes a given 16-bit sample
 */
BOOL jssEncodeSample16(Uint16 * srcData, const size_t srcSize, const int ops)
{
    // "Split" the 16-bit samples into 8-bit halves
    if (ops & jsampSplit)
    {
        // Allocate temporary processing buffer
        size_t ssize, bufSize = srcSize * sizeof(Sint16);
        Uint8 *bp1, *bp2;
        Sint16 t, *sdata, *tmpBuf = dmMalloc(bufSize);
        if (tmpBuf == NULL) return FALSE;

        sdata = tmpBuf;
        bp1 = (Uint8 *) srcData;
        bp2 = bp1 + srcSize;
        ssize = srcSize;

        while (ssize--)
        {
            t = (*sdata++);
            *bp1++ = t >> 8;
            *bp2++ = t & 0xff;
        }
        
        memcpy(srcData, tmpBuf, bufSize);
        dmFree(tmpBuf);
        
        return jssEncodeSample8((Uint8 *) srcData, bufSize, ops);
    }
    else
    {
        Sint16 t, p, value = 0, *sdata = (Sint16 *) srcData;
        size_t ssize = srcSize;
        
        while (ssize--)
        {
            if (ops & jsampSwapEndianess)
            {
                p = *sdata;
                t = ((p >> 8) & 0xff) | ((p & 0xff) << 8);
            } else
                t = *sdata;
            
            if (ops & jsampDelta)
            {
                int n = t - value;
                value = t;
                t = n;
            }
            
            if (ops & jsampFlipSign)
                t ^= 0x8000;
            
            *(sdata++) = t;
        }
    }
    return TRUE;
}
#endif


/* Decodes a given 8-bit sample
 */
BOOL jssDecodeSample8(Uint8 * sdata, const size_t srcSize, const int ops)
{
    size_t ssize = srcSize;
    Sint8 t, value = 0;
    
    while (ssize--)
    {
        t = *sdata;
        
        if (ops & jsampDelta)
            t = value = t + value;
        
        if (ops & jsampFlipSign)
            t ^= 0x80;
        
        *(sdata++) = t;
    }
    return TRUE;
}


/* Decodes a given 16-bit sample
 */
BOOL jssDecodeSample16(Uint16 * srcData, const size_t srcSize, const int ops)
{
    if (ops & jsampSplit)
    {
        size_t ssize, bufSize = srcSize * sizeof(Uint16);
        Uint8 *bp1, *bp2;
        Sint16 *tmpBuf, *sdata;
        
        if (!jssDecodeSample8((Uint8 *) srcData, bufSize, ops))
            return FALSE;
        
        tmpBuf = dmMalloc(bufSize);
        if (tmpBuf == NULL) return FALSE;
        memcpy(tmpBuf, srcData, bufSize);
        
        sdata = (Sint16 *) srcData;
        bp1 = (Uint8 *) tmpBuf;
        bp2 = bp1 + srcSize;
        ssize = srcSize;
        while (ssize--)
        {
            *sdata++ = (*bp1++ << 8) | (*bp2++ & 0xff);
        }
        
        dmFree(tmpBuf);
    }
    else
    {
        Sint16 t, p, value = 0, *sdata = (Sint16 *) srcData;
        size_t ssize = srcSize;
        while (ssize--)
        {
            if (ops & jsampSwapEndianess)
            {
                p = *sdata;
                t = ((p >> 8) & 0xff) | ((p & 0xff) << 8);
            } else
                t = *sdata;
            
            if (ops & jsampDelta)
                t = value = t + value;
            
            if (ops & jsampFlipSign)
                t ^= 0x8000;
            
            *(sdata++) = t;
        }
    }
    return TRUE;
}


/* Allocates a new module structure or returns errorvalue if failed.
 * Memory is allocated only for the basic structure. Sample- and pattern
 * areas must be allocated separately with appropriate routines.
 */
JSSModule *jssAllocateModule(void)
{
    int i;
    JSSModule *module;

    // Allocate module structure
    module = dmMalloc0(sizeof(JSSModule));
    if (module == NULL)
        return NULL;

    // Initialize structure
    for (i = 0; i < jsetNChannels; i++)
        module->defPanning[i] = jchPanMiddle;

    for (i = 0; i < jsetMaxOrders; i++)
        module->orderList[i] = jsetOrderEnd;

    // Allocate mutex
#ifdef JSS_SUP_THREADS
    module->mutex = dmCreateMutex();
#endif

    return module;
}


/* Frees a given module structure, freeing all memory areas
 * that were allocated for it (including patterns, samples, etc.)
 */
int jssFreeModule(JSSModule * module)
{
    int i;

    if (module == NULL)
        return DMERR_NULLPTR;
    
    // Free strings
#ifndef JSS_LIGHT
    dmFree(module->moduleName);
    dmFree(module->trackerName);
#endif

    // Free patterns
    for (i = 0; i < module->npatterns; i++)
    {
        if (module->patterns[i])
        {
            JSSPattern *pat = module->patterns[i];
            dmFree(pat->data);
            dmFree(pat);
            module->patterns[i] = NULL;
        }
    }

    // Free instruments
    for (i = 0; i < module->ninstruments; i++)
    {
        if (module->instruments[i])
        {
            JSSInstrument *inst = module->instruments[i];
#ifndef JSS_LIGHT
            dmFree(inst->desc);
#endif
            dmFree(inst->data);
            dmFree(inst);
            module->instruments[i] = NULL;
        }
    }

    // Free extended instruments
    for (i = 0; i < module->nextInstruments; i++)
    {
        if (module->extInstruments[i])
        {
            JSSExtInstrument *ext = module->extInstruments[i];
#ifndef JSS_LIGHT
            dmFree(ext->desc);
#endif
            dmFree(ext);
            module->extInstruments[i] = NULL;
        }
    }

    // Free mutex
#ifdef JSS_SUP_THREADS
    dmDestroyMutex(module->mutex);
#endif
    
    // Free the module structure
    memset(module, 0, sizeof(JSSModule));
    dmFree(module);

    return DMERR_OK;
}


/* Allocates and initializes a internal pattern structure.
 */
JSSPattern *jssAllocatePattern(int nrows, int nchannels)
{
    int i, j;
    JSSPattern *res;
    JSSNote *pnote;

    // Check arguments
    if (nrows <= 0 || nchannels <= 0)
        JSSERROR(DMERR_INVALID_ARGS, NULL, "Invalid nrows=%i or nchannels=%i.\n", nrows, nchannels);

    // Allocate a pattern structure
    res = dmMalloc0(sizeof(JSSPattern));
    if (res == NULL)
        JSSERROR(DMERR_MALLOC, NULL, "Could not allocate pattern structure.\n");

    // Allocate notedata
    res->data = dmCalloc(nrows * nchannels, sizeof(JSSNote));
    if (res->data == NULL)
    {
        dmFree(res);
        JSSERROR(DMERR_MALLOC, NULL, "Could not allocate pattern data (nrows=%i, nchannels=%i).\n", nrows,
             nchannels);
    }

    // Initialize
    res->nrows = nrows;
    res->nchannels = nchannels;

    pnote = res->data;
    for (j = 0; j < nrows; j++)
    {
        for (i = 0; i < nchannels; i++)
        {
            pnote->note = pnote->instrument = pnote->volume =
                pnote->effect = pnote->param = jsetNotSet;

            pnote++;
        }
    }

    // OK, return pointer to struct
    return res;
}


/* Allocates and initializes internal "normal" instrument structure.
 */
JSSInstrument *jssAllocateInstrument(void)
{
    JSSInstrument *res;

    // Allocate a instrument structure
    res = dmMalloc0(sizeof(JSSInstrument));
    if (res == NULL)
        return NULL;

    return res;
}


/* Allocates and initializes "extended" instrument structure.
 */
JSSExtInstrument *jssAllocateExtInstrument(void)
{
    int i;
    JSSExtInstrument *res;

    // Allocate a instrument structure
    res = dmMalloc0(sizeof(JSSExtInstrument));
    if (res == NULL)
        return NULL;

    for (i = 0; i < jsetNNotes; i++)
    {
        res->sNumForNotes[i] = jsetNotSet;
    }
    
    return res;
}