Mercurial > hg > dmlib
diff minijss/jssmod.c @ 658:c430112449a7
Move miniJSS into a subdirectory.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 16 Apr 2013 07:32:29 +0300 |
parents | jssmod.c@a17e54015bd9 |
children | b136ddc4070b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/minijss/jssmod.c Tue Apr 16 07:32:29 2013 +0300 @@ -0,0 +1,447 @@ +/* + * 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 * data, const size_t len, const int ops) +{ + size_t count = len; + Sint8 t, value = 0; + + while (count--) + { + t = *data; + + if (ops & jsampFlipSign) + t ^= 0x80; + + if (ops & jsampDelta) + { + int n = t - value; + value = t; + t = n; + } + + *(data++) = t; + } + + return TRUE; +} + + +/* Decodes a given 16-bit sample + */ +BOOL jssEncodeSample16(Uint16 * data, const size_t len, const int ops) +{ + // "Split" the 16-bit samples into 8-bit halves + if (ops & jsampSplit) + { + // Allocate temporary processing buffer + size_t count, bufSize = len * sizeof(Sint16); + Uint8 *bp1, *bp2; + Sint16 *sdata, *tmpBuf = dmMalloc(bufSize); + if (tmpBuf == NULL) return FALSE; + + sdata = tmpBuf; + bp1 = (Uint8 *) data; + bp2 = bp1 + len; + count = len; + + while (count--) + { + Sint16 t = (*sdata++); + *bp1++ = t >> 8; + *bp2++ = t & 0xff; + } + + memcpy(data, tmpBuf, bufSize); + dmFree(tmpBuf); + + return jssEncodeSample8((Uint8 *) data, bufSize, ops); + } + else + { + Sint16 t, p, value = 0, *sdata = (Sint16 *) data; + size_t count = len; + + while (count--) + { + 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 * data, const size_t len, const int ops) +{ + size_t count = len; + Sint8 t, value = 0; + + while (count--) + { + t = *data; + + if (ops & jsampDelta) + t = value = t + value; + + if (ops & jsampFlipSign) + t ^= 0x80; + + *(data++) = t; + } + return TRUE; +} + + +/* Decodes a given 16-bit sample + */ +BOOL jssDecodeSample16(Uint16 * data, const size_t len, const int ops) +{ + if (ops & jsampSplit) + { + size_t count, bufSize = len * sizeof(Uint16); + Uint8 *bp1, *bp2; + Sint16 *tmpBuf, *sdata; + + if (!jssDecodeSample8((Uint8 *) data, bufSize, ops)) + return FALSE; + + tmpBuf = dmMalloc(bufSize); + if (tmpBuf == NULL) return FALSE; + memcpy(tmpBuf, data, bufSize); + + sdata = (Sint16 *) data; + bp1 = (Uint8 *) tmpBuf; + bp2 = bp1 + len; + count = len; + while (count--) + { + *sdata++ = (*bp1++ << 8) | (*bp2++ & 0xff); + } + + dmFree(tmpBuf); + } + else + { + Sint16 t, p, value = 0, *sdata = (Sint16 *) data; + size_t count = len; + while (count--) + { + 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; +} + + +/* 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, etc.) + * + * 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; + + if (inst->flags & jsf16bit) + continue; + + if ((res = jssConvertSampleTo16(&data, inst->data, inst->size)) != DMERR_OK) + return res; + + inst->flags |= jsf16bit; + dmFree(inst->data); + inst->data = data; + } + } + + return DMERR_OK; +} + + +/* 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 the "empty" pattern + JSSPattern *pat = module->patterns[jsetMaxPatterns]; + if (pat != NULL) + { + 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; +}