Mercurial > hg > dmlib
view jssmod.c @ 510:43ea59887c69
Start work on making C64 formats encoding possible by changing DMDecodeOps
to DMEncDecOps and adding fields and op enums for custom encode functions, renaming,
etc. Split generic op sanity checking into a separate function in
preparation for its use in generic encoding function.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 19 Nov 2012 15:06:01 +0200 |
parents | a17e54015bd9 |
children |
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 * 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; }