summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/sloader.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/sloader.c')
-rw-r--r--apps/plugins/mikmod/sloader.c519
1 files changed, 519 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/sloader.c b/apps/plugins/mikmod/sloader.c
new file mode 100644
index 0000000000..8b15b0d453
--- /dev/null
+++ b/apps/plugins/mikmod/sloader.c
@@ -0,0 +1,519 @@
1/* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 for complete list.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id: sloader.c,v 1.3 2007/12/06 17:46:08 denis111 Exp $
24
25 Routines for loading samples. The sample loader utilizes the routines
26 provided by the "registered" sample loader.
27
28==============================================================================*/
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37
38#include "mikmod_internals.h"
39
40static int sl_rlength;
41static SWORD sl_old;
42static SWORD *sl_buffer=NULL;
43static SAMPLOAD *musiclist=NULL,*sndfxlist=NULL;
44
45/* size of the loader buffer in words */
46#define SLBUFSIZE 2048
47
48/* IT-Compressed status structure */
49typedef struct ITPACK {
50 UWORD bits; /* current number of bits */
51 UWORD bufbits; /* bits in buffer */
52 SWORD last; /* last output */
53 UBYTE buf; /* bit buffer */
54} ITPACK;
55
56int SL_Init(SAMPLOAD* s)
57{
58 if(!sl_buffer)
59 if(!(sl_buffer=MikMod_malloc(SLBUFSIZE*sizeof(SWORD)))) return 0;
60
61 sl_rlength = s->length;
62 if(s->infmt & SF_16BITS) sl_rlength>>=1;
63 sl_old = 0;
64
65 return 1;
66}
67
68void SL_Exit(SAMPLOAD *s)
69{
70 if(sl_rlength>0) _mm_fseek(s->reader,sl_rlength,SEEK_CUR);
71 if(sl_buffer) {
72 MikMod_free(sl_buffer);
73 sl_buffer=NULL;
74 }
75}
76
77/* unpack a 8bit IT packed sample */
78static int read_itcompr8(ITPACK* status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt)
79{
80 SWORD *dest=sl_buffer,*end=sl_buffer+count;
81 UWORD x,y,needbits,havebits,new_count=0;
82 UWORD bits = status->bits;
83 UWORD bufbits = status->bufbits;
84 SBYTE last = status->last;
85 UBYTE buf = status->buf;
86
87 while (dest<end) {
88 needbits=new_count?3:bits;
89 x=havebits=0;
90 while (needbits) {
91 /* feed buffer */
92 if (!bufbits) {
93 if((*incnt)--)
94 buf=_mm_read_UBYTE(reader);
95 else
96 buf=0;
97 bufbits=8;
98 }
99 /* get as many bits as necessary */
100 y = needbits<bufbits?needbits:bufbits;
101 x|= (buf & ((1<<y)- 1))<<havebits;
102 buf>>=y;
103 bufbits-=y;
104 needbits-=y;
105 havebits+=y;
106 }
107 if (new_count) {
108 new_count = 0;
109 if (++x >= bits)
110 x++;
111 bits = x;
112 continue;
113 }
114 if (bits<7) {
115 if (x==(1<<(bits-1))) {
116 new_count = 1;
117 continue;
118 }
119 }
120 else if (bits<9) {
121 y = (0xff >> (9-bits)) - 4;
122 if ((x>y)&&(x<=y+8)) {
123 if ((x-=y)>=bits)
124 x++;
125 bits = x;
126 continue;
127 }
128 }
129 else if (bits<10) {
130 if (x>=0x100) {
131 bits=x-0x100+1;
132 continue;
133 }
134 } else {
135 /* error in compressed data... */
136 _mm_errno=MMERR_ITPACK_INVALID_DATA;
137 return 0;
138 }
139
140 if (bits<8) /* extend sign */
141 x = ((SBYTE)(x <<(8-bits))) >> (8-bits);
142 *(dest++)= (last+=x) << 8; /* convert to 16 bit */
143 }
144 status->bits = bits;
145 status->bufbits = bufbits;
146 status->last = last;
147 status->buf = buf;
148 return (dest-sl_buffer);
149}
150
151/* unpack a 16bit IT packed sample */
152static int read_itcompr16(ITPACK *status,MREADER *reader,SWORD *sl_buffer,UWORD count,UWORD* incnt)
153{
154 SWORD *dest=sl_buffer,*end=sl_buffer+count;
155 SLONG x,y,needbits,havebits,new_count=0;
156 UWORD bits = status->bits;
157 UWORD bufbits = status->bufbits;
158 SWORD last = status->last;
159 UBYTE buf = status->buf;
160
161 while (dest<end) {
162 needbits=new_count?4:bits;
163 x=havebits=0;
164 while (needbits) {
165 /* feed buffer */
166 if (!bufbits) {
167 if((*incnt)--)
168 buf=_mm_read_UBYTE(reader);
169 else
170 buf=0;
171 bufbits=8;
172 }
173 /* get as many bits as necessary */
174 y=needbits<bufbits?needbits:bufbits;
175 x|=(buf &((1<<y)-1))<<havebits;
176 buf>>=y;
177 bufbits-=(UWORD)y;
178 needbits-=(UWORD)y;
179 havebits+=(UWORD)y;
180 }
181 if (new_count) {
182 new_count = 0;
183 if (++x >= bits)
184 x++;
185 bits = (UWORD)x;
186 continue;
187 }
188 if (bits<7) {
189 if (x==(1<<(bits-1))) {
190 new_count=1;
191 continue;
192 }
193 }
194 else if (bits<17) {
195 y=(0xffff>>(17-bits))-8;
196 if ((x>y)&&(x<=y+16)) {
197 if ((x-=y)>=bits)
198 x++;
199 bits = (UWORD)x;
200 continue;
201 }
202 }
203 else if (bits<18) {
204 if (x>=0x10000) {
205 bits=(UWORD)(x-0x10000+1);
206 continue;
207 }
208 } else {
209 /* error in compressed data... */
210 _mm_errno=MMERR_ITPACK_INVALID_DATA;
211 return 0;
212 }
213
214 if (bits<16) /* extend sign */
215 x = ((SWORD)(x<<(16-bits)))>>(16-bits);
216 *(dest++)=(last+=x);
217 }
218 status->bits = bits;
219 status->bufbits = bufbits;
220 status->last = last;
221 status->buf = buf;
222 return (dest-sl_buffer);
223}
224
225static int SL_LoadInternal(void* buffer,UWORD infmt,UWORD outfmt,int scalefactor,ULONG length,MREADER* reader,int dither)
226{
227 SBYTE *bptr = (SBYTE*)buffer;
228 SWORD *wptr = (SWORD*)buffer;
229 int stodo,t,u;
230
231 int result,c_block=0; /* compression bytes until next block */
232 ITPACK status;
233 UWORD incnt;
234
235 while(length) {
236 stodo=(length<SLBUFSIZE)?length:SLBUFSIZE;
237
238 if(infmt&SF_ITPACKED) {
239 sl_rlength=0;
240 if (!c_block) {
241 status.bits = (infmt & SF_16BITS) ? 17 : 9;
242 status.last = status.bufbits = 0;
243 incnt=_mm_read_I_UWORD(reader);
244 c_block = (infmt & SF_16BITS) ? 0x4000 : 0x8000;
245 if(infmt&SF_DELTA) sl_old=0;
246 }
247 if (infmt & SF_16BITS) {
248 if(!(result=read_itcompr16(&status,reader,sl_buffer,stodo,&incnt)))
249 return 1;
250 } else {
251 if(!(result=read_itcompr8(&status,reader,sl_buffer,stodo,&incnt)))
252 return 1;
253 }
254 if(result!=stodo) {
255 _mm_errno=MMERR_ITPACK_INVALID_DATA;
256 return 1;
257 }
258 c_block -= stodo;
259 } else {
260 if(infmt&SF_16BITS) {
261 if(infmt&SF_BIG_ENDIAN)
262 _mm_read_M_SWORDS(sl_buffer,stodo,reader);
263 else
264 _mm_read_I_SWORDS(sl_buffer,stodo,reader);
265 } else {
266 SBYTE *src;
267 SWORD *dest;
268
269 reader->Read(reader,sl_buffer,sizeof(SBYTE)*stodo);
270 src = (SBYTE*)sl_buffer;
271 dest = sl_buffer;
272 src += stodo;dest += stodo;
273
274 for(t=0;t<stodo;t++) {
275 src--;dest--;
276 *dest = (*src)<<8;
277 }
278 }
279 sl_rlength-=stodo;
280 }
281
282 if(infmt & SF_DELTA)
283 for(t=0;t<stodo;t++) {
284 sl_buffer[t] += sl_old;
285 sl_old = sl_buffer[t];
286 }
287
288 if((infmt^outfmt) & SF_SIGNED)
289 for(t=0;t<stodo;t++)
290 sl_buffer[t]^= 0x8000;
291
292 if(scalefactor) {
293 int idx = 0;
294 SLONG scaleval;
295
296 /* Sample Scaling... average values for better results. */
297 t= 0;
298 while(t<stodo && length) {
299 scaleval = 0;
300 for(u=scalefactor;u && t<stodo;u--,t++)
301 scaleval+=sl_buffer[t];
302 sl_buffer[idx++]=(UWORD)(scaleval/(scalefactor-u));
303 length--;
304 }
305 stodo = idx;
306 } else
307 length -= stodo;
308
309 if (dither) {
310 if((infmt & SF_STEREO) && !(outfmt & SF_STEREO)) {
311 /* dither stereo to mono, average together every two samples */
312 SLONG avgval;
313 int idx = 0;
314
315 t=0;
316 while(t<stodo && length) {
317 avgval=sl_buffer[t++];
318 avgval+=sl_buffer[t++];
319 sl_buffer[idx++]=(SWORD)(avgval>>1);
320 length-=2;
321 }
322 stodo = idx;
323 }
324 }
325
326 if(outfmt & SF_16BITS) {
327 for(t=0;t<stodo;t++)
328 *(wptr++)=sl_buffer[t];
329 } else {
330 for(t=0;t<stodo;t++)
331 *(bptr++)=sl_buffer[t]>>8;
332 }
333 }
334 return 0;
335}
336
337int SL_Load(void* buffer,SAMPLOAD *smp,ULONG length)
338{
339 return SL_LoadInternal(buffer,smp->infmt,smp->outfmt,smp->scalefactor,
340 length,smp->reader,0);
341}
342
343/* Registers a sample for loading when SL_LoadSamples() is called. */
344SAMPLOAD* SL_RegisterSample(SAMPLE* s,int type,MREADER* reader)
345{
346 SAMPLOAD *news,**samplist,*cruise;
347
348 if(type==MD_MUSIC) {
349 samplist = &musiclist;
350 cruise = musiclist;
351 } else
352 if (type==MD_SNDFX) {
353 samplist = &sndfxlist;
354 cruise = sndfxlist;
355 } else
356 return NULL;
357
358 /* Allocate and add structure to the END of the list */
359 if(!(news=(SAMPLOAD*)MikMod_malloc(sizeof(SAMPLOAD)))) return NULL;
360
361 if(cruise) {
362 while(cruise->next) cruise=cruise->next;
363 cruise->next = news;
364 } else
365 *samplist = news;
366
367 news->infmt = s->flags & SF_FORMATMASK;
368 news->outfmt = news->infmt;
369 news->reader = reader;
370 news->sample = s;
371 news->length = s->length;
372 news->loopstart = s->loopstart;
373 news->loopend = s->loopend;
374
375 return news;
376}
377
378static void FreeSampleList(SAMPLOAD* s)
379{
380 SAMPLOAD *old;
381
382 while(s) {
383 old = s;
384 s = s->next;
385 MikMod_free(old);
386 }
387}
388
389/* Returns the total amount of memory required by the samplelist queue. */
390static ULONG SampleTotal(SAMPLOAD* samplist,int type)
391{
392 int total = 0;
393
394 while(samplist) {
395 samplist->sample->flags=
396 (samplist->sample->flags&~SF_FORMATMASK)|samplist->outfmt;
397 total += MD_SampleLength(type,samplist->sample);
398 samplist=samplist->next;
399 }
400
401 return total;
402}
403
404static ULONG RealSpeed(SAMPLOAD *s)
405{
406 return(s->sample->speed/(s->scalefactor?s->scalefactor:1));
407}
408
409static int DitherSamples(SAMPLOAD* samplist,int type)
410{
411 SAMPLOAD *c2smp=NULL;
412 ULONG maxsize, speed;
413 SAMPLOAD *s;
414
415 if(!samplist) return 0;
416
417 if((maxsize=MD_SampleSpace(type)*1024))
418 while(SampleTotal(samplist,type)>maxsize) {
419 /* First Pass - check for any 16 bit samples */
420 s = samplist;
421 while(s) {
422 if(s->outfmt & SF_16BITS) {
423 SL_Sample16to8(s);
424 break;
425 }
426 s=s->next;
427 }
428 /* Second pass (if no 16bits found above) is to take the sample with
429 the highest speed and dither it by half. */
430 if(!s) {
431 s = samplist;
432 speed = 0;
433 while(s) {
434 if((s->sample->length) && (RealSpeed(s)>speed)) {
435 speed=RealSpeed(s);
436 c2smp=s;
437 }
438 s=s->next;
439 }
440 if (c2smp)
441 SL_HalveSample(c2smp,2);
442 }
443 }
444
445 /* Samples dithered, now load them ! */
446 s = samplist;
447 while(s) {
448 /* sample has to be loaded ? -> increase number of samples, allocate
449 memory and load sample. */
450 if(s->sample->length) {
451 if(s->sample->seekpos)
452 _mm_fseek(s->reader, s->sample->seekpos, SEEK_SET);
453
454 /* Call the sample load routine of the driver module. It has to
455 return a 'handle' (>=0) that identifies the sample. */
456 s->sample->handle = MD_SampleLoad(s, type);
457 s->sample->flags = (s->sample->flags & ~SF_FORMATMASK) | s->outfmt;
458 if(s->sample->handle<0) {
459 FreeSampleList(samplist);
460 if(_mm_errorhandler) _mm_errorhandler();
461 return 1;
462 }
463 }
464 s = s->next;
465 }
466
467 FreeSampleList(samplist);
468 return 0;
469}
470
471int SL_LoadSamples(void)
472{
473 int ok;
474
475 _mm_critical = 0;
476
477 if((!musiclist)&&(!sndfxlist)) return 0;
478 ok=DitherSamples(musiclist,MD_MUSIC)||DitherSamples(sndfxlist,MD_SNDFX);
479 musiclist=sndfxlist=NULL;
480
481 return ok;
482}
483
484void SL_Sample16to8(SAMPLOAD* s)
485{
486 s->outfmt &= ~SF_16BITS;
487 s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
488}
489
490void SL_Sample8to16(SAMPLOAD* s)
491{
492 s->outfmt |= SF_16BITS;
493 s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
494}
495
496void SL_SampleSigned(SAMPLOAD* s)
497{
498 s->outfmt |= SF_SIGNED;
499 s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
500}
501
502void SL_SampleUnsigned(SAMPLOAD* s)
503{
504 s->outfmt &= ~SF_SIGNED;
505 s->sample->flags = (s->sample->flags&~SF_FORMATMASK) | s->outfmt;
506}
507
508void SL_HalveSample(SAMPLOAD* s,int factor)
509{
510 s->scalefactor=factor>0?factor:2;
511
512 s->sample->divfactor = s->scalefactor;
513 s->sample->length = s->length / s->scalefactor;
514 s->sample->loopstart = s->loopstart / s->scalefactor;
515 s->sample->loopend = s->loopend / s->scalefactor;
516}
517
518
519/* ex:set ts=4: */