📄 mloader.c
字号:
/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//*============================================================================== $Id: mloader.c,v 1.33 1999/10/25 16:31:41 miod Exp $ These routines are used to access the available module loaders==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include "unimod_priv.h"#include <string.h>URL modreader;MODULE of;BOOL ML_8bitsamples;BOOL ML_monosamples;static MLOADER *firstloader = NULL;UWORD finetune[16] ={ 8363, 8413, 8463, 8529, 8581, 8651, 8723, 8757, 7895, 7941, 7985, 8046, 8107, 8169, 8232, 8280};/* This is a handle of sorts attached to any sample registered with SL_RegisterSample. */typedef struct SAMPLOAD { struct SAMPLOAD *next; ULONG length; /* length of sample (in samples!) */ ULONG loopstart; /* repeat position (relative to start, in samples) */ ULONG loopend; /* repeat end */ UWORD infmt, outfmt; int scalefactor; SAMPLE *sample; URL reader; }SAMPLOAD;static int sl_rlength;static SWORD sl_old;static SWORD *sl_buffer = NULL;static SAMPLOAD *musiclist = NULL;/* size of the loader buffer in words */#define SLBUFSIZE 2048/* max # of KB to be devoted to samples *//* #define MAX_SAMPLESPACE 1024 *//* IT-Compressed status structure */typedef struct ITPACK { UWORD bits; /* current number of bits */ UWORD bufbits; /* bits in buffer */ SWORD last; /* last output */ UBYTE buf; /* bit buffer */ }ITPACK;#ifdef MAX_SAMPLESPACEstatic void SL_HalveSample (SAMPLOAD *);#endifstatic void SL_Sample8to16 (SAMPLOAD *);static void SL_Sample16to8 (SAMPLOAD *);static void SL_SampleSigned (SAMPLOAD *);static void SL_SampleUnsigned (SAMPLOAD *);static SAMPLOAD *SL_RegisterSample (SAMPLE *, URL);static SWORD *SL_Load (SAMPLOAD *);static BOOL SL_Init (SAMPLOAD *);static void SL_Exit (SAMPLOAD *);BOOL SL_Init (SAMPLOAD * s){ if (!sl_buffer) if (!(sl_buffer = _mm_malloc (SLBUFSIZE * sizeof (SWORD)))) return 0; sl_rlength = s->length; if (s->infmt & SF_16BITS) sl_rlength >>= 1; sl_old = 0; return 1;}void SL_Exit (SAMPLOAD * s){ if (sl_rlength > 0) _mm_fseek (s->reader, sl_rlength, SEEK_CUR); if (sl_buffer) { free (sl_buffer); sl_buffer = NULL; }}/* unpack a 8bit IT packed sample */static BOOL read_itcompr8 (ITPACK * status, URL reader, SWORD * sl_buffer, UWORD count, UWORD * incnt){ SWORD *dest = sl_buffer, *end = sl_buffer + count; UWORD x, y, needbits, havebits, new_count = 0; UWORD bits = status->bits; UWORD bufbits = status->bufbits; SBYTE last = status->last; UBYTE buf = status->buf; while (dest < end) { needbits = new_count ? 3 : bits; x = havebits = 0; while (needbits) { /* feed buffer */ if (!bufbits) { if ((*incnt)--) buf = _mm_read_UBYTE (reader); else buf = 0; bufbits = 8; } /* get as many bits as necessary */ y = needbits < bufbits ? needbits : bufbits; x |= (buf & ((1 << y) - 1)) << havebits; buf >>= y; bufbits -= y; needbits -= y; havebits += y; } if (new_count) { new_count = 0; if (++x >= bits) x++; bits = x; continue; } if (bits < 7) { if (x == (1 << (bits - 1))) { new_count = 1; continue; } } else if (bits < 9) { y = (0xff >> (9 - bits)) - 4; if ((x > y) && (x <= y + 8)) { if ((x -= y) >= bits) x++; bits = x; continue; } } else if (bits < 10) { if (x >= 0x100) { bits = x - 0x100 + 1; continue; } } else { /* error in compressed data... */ _mm_errno = MMERR_ITPACK_INVALID_DATA; return 0; } if (bits < 8) /* extend sign */ x = ((SBYTE) (x << (8 - bits))) >> (8 - bits); *(dest++) = (last += x) << 8; /* convert to 16 bit */ } status->bits = bits; status->bufbits = bufbits; status->last = last; status->buf = buf; return dest - sl_buffer;}/* unpack a 16bit IT packed sample */static BOOL read_itcompr16 (ITPACK * status, URL reader, SWORD * sl_buffer, UWORD count, UWORD * incnt){ SWORD *dest = sl_buffer, *end = sl_buffer + count; SLONG x, y, needbits, havebits, new_count = 0; UWORD bits = status->bits; UWORD bufbits = status->bufbits; SWORD last = status->last; UBYTE buf = status->buf; while (dest < end) { needbits = new_count ? 4 : bits; x = havebits = 0; while (needbits) { /* feed buffer */ if (!bufbits) { if ((*incnt)--) buf = _mm_read_UBYTE (reader); else buf = 0; bufbits = 8; } /* get as many bits as necessary */ y = needbits < bufbits ? needbits : bufbits; x |= (buf & ((1 << y) - 1)) << havebits; buf >>= y; bufbits -= y; needbits -= y; havebits += y; } if (new_count) { new_count = 0; if (++x >= bits) x++; bits = x; continue; } if (bits < 7) { if (x == (1 << (bits - 1))) { new_count = 1; continue; } } else if (bits < 17) { y = (0xffff >> (17 - bits)) - 8; if ((x > y) && (x <= y + 16)) { if ((x -= y) >= bits) x++; bits = x; continue; } } else if (bits < 18) { if (x >= 0x10000) { bits = x - 0x10000 + 1; continue; } } else { /* error in compressed data... */ _mm_errno = MMERR_ITPACK_INVALID_DATA; return 0; } if (bits < 16) /* extend sign */ x = ((SWORD) (x << (16 - bits))) >> (16 - bits); *(dest++) = (last += x); } status->bits = bits; status->bufbits = bufbits; status->last = last; status->buf = buf; return dest - sl_buffer;}static BOOL SL_LoadInternal (void *buffer, UWORD infmt, UWORD outfmt, int scalefactor, ULONG length, URL reader){ SBYTE *bptr = (SBYTE *) buffer; SWORD *wptr = (SWORD *) buffer; int stodo, t, u; int result, c_block = 0; /* compression bytes until next block */ ITPACK status; UWORD incnt; while (length) { stodo = (length < SLBUFSIZE) ? length : SLBUFSIZE; if (infmt & SF_ITPACKED) { sl_rlength = 0; if (!c_block) { status.bits = (infmt & SF_16BITS) ? 17 : 9; status.last = status.bufbits = 0; incnt = _mm_read_I_UWORD (reader); c_block = (infmt & SF_16BITS) ? 0x4000 : 0x8000; if (infmt & SF_DELTA) sl_old = 0; } if (infmt & SF_16BITS) { if (!(result = read_itcompr16 (&status, reader, sl_buffer, stodo, &incnt))) return 1; } else { if (!(result = read_itcompr8 (&status, reader, sl_buffer, stodo, &incnt))) return 1; } if (result != stodo) { _mm_errno = MMERR_ITPACK_INVALID_DATA; return 1; } c_block -= stodo; } else { if (infmt & SF_16BITS) { if (infmt & SF_BIG_ENDIAN) _mm_read_M_SWORDS (sl_buffer, stodo, reader); else _mm_read_I_SWORDS (sl_buffer, stodo, reader); } else { /* Always convert to 16 bits for internal use */ SBYTE *src; SWORD *dest; _mm_read_UBYTES (sl_buffer, stodo, reader); src = (SBYTE *) sl_buffer; dest = sl_buffer; src += stodo; dest += stodo; for (t = 0; t < stodo; t++) { src--; dest--; *dest = (*src) << 8; } } sl_rlength -= stodo; } if (infmt & SF_DELTA) for (t = 0; t < stodo; t++) { sl_buffer[t] += sl_old; sl_old = sl_buffer[t]; } if ((infmt ^ outfmt) & SF_SIGNED) for (t = 0; t < stodo; t++) sl_buffer[t] ^= 0x8000; /* Dithering... */ if ((infmt & SF_STEREO) && !(outfmt & SF_STEREO)) { /* dither stereo to mono, average together every two samples */ SLONG avgval; int idx = 0; t = 0; while (t < stodo && length) { avgval = sl_buffer[t++]; avgval += sl_buffer[t++]; sl_buffer[idx++] = avgval >> 1; length -= 2; } stodo = idx; } else if (scalefactor) { int idx = 0; SLONG scaleval; /* Sample Scaling... average values for better results. */ t = 0; while (t < stodo && length) { scaleval = 0; for (u = scalefactor; u && t < stodo; u--, t++) scaleval += sl_buffer[t]; sl_buffer[idx++] = scaleval / (scalefactor - u); length--; } stodo = idx; } else length -= stodo; if (outfmt & SF_16BITS) { for (t = 0; t < stodo; t++) *(wptr++) = sl_buffer[t]; } else { for (t = 0; t < stodo; t++) *(bptr++) = sl_buffer[t] >> 8; } } return 0;}static SWORD *SL_Load (struct SAMPLOAD *sload){ SAMPLE *s = sload->sample; SWORD *data; ULONG t, length, loopstart, loopend; length = s->length; loopstart = s->loopstart; loopend = s->loopend; if (!(data = (SWORD *) _mm_malloc ((length + 20) << 1))) { _mm_errno = MMERR_SAMPLE_TOO_BIG; return NULL; } /* read sample into buffer */ if (SL_LoadInternal (data, sload->infmt, sload->outfmt, sload->scalefactor, length, sload->reader)) return NULL; /* Unclick sample */ if (s->flags & SF_LOOP) { if (s->flags & SF_BIDI) for (t = 0; t < 16; t++) data[loopend + t] = data[(loopend - t) - 1]; else for (t = 0; t < 16; t++) data[loopend + t] = data[t + loopstart]; } else for (t = 0; t < 16; t++) data[t + length] = 0; return data;}/* Registers a sample for loading when SL_LoadSamples() is called. */SAMPLOAD *SL_RegisterSample (SAMPLE * s, URL reader){ SAMPLOAD *news, *cruise; cruise = musiclist; /* Allocate and add structure to the END of the list */ if (!(news = (SAMPLOAD *) _mm_malloc (sizeof (SAMPLOAD)))) return NULL; if (cruise) { while (cruise->next) cruise = cruise->next; cruise->next = news; } else musiclist = news; news->infmt = s->flags & SF_FORMATMASK; news->outfmt = news->infmt; news->reader = reader; news->sample = s; news->length = s->length; news->loopstart = s->loopstart; news->loopend = s->loopend; if (ML_monosamples) { news->outfmt &= ~SF_STEREO; } if (ML_8bitsamples) { SL_SampleUnsigned (news); SL_Sample16to8 (news); } else { SL_SampleSigned (news); SL_Sample8to16 (news); } return news;}static void FreeSampleList (){ SAMPLOAD *old, *s = musiclist; while (s) { old = s; s = s->next; free (old); } musiclist = NULL;}/* Returns the total amount of memory required by the musiclist queue. */#ifdef MAX_SAMPLESPACEstatic ULONG SampleTotal (){ int total = 0; SAMPLOAD *samplist = musiclist; SAMPLE *s; while (samplist) { s = samplist->sample; s->flags = (s->flags & ~SF_FORMATMASK) | samplist->outfmt; total += (s->length * ((s->flags & SF_16BITS) ? 2 : 1)) + 16; samplist = samplist->next; } return total;}static ULONG RealSpeed (SAMPLOAD * s){ return (s->sample->speed / (s->scalefactor ? s->scalefactor : 1));}#endifBOOL SL_LoadSamples (void){ SAMPLOAD *s; if (!musiclist) return 0;#ifdef MAX_SAMPLESPACE while (SampleTotal () > (MAX_SAMPLESPACE * 1024)) { /* First Pass - check for any 16 bit samples */ s = musiclist; while (s) { if (s->outfmt & SF_16BITS) { SL_Sample16to8 (s); break; } s = s->next; } /* Second pass (if no 16bits found above) is to take the sample with the highest speed and dither it by half. */ if (!s) { SAMPLOAD *c2smp = NULL; ULONG maxsize, speed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -