Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/sloader.c @ 6:d14fd386d182
Initial entry of mikmod into the CVS tree.
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:09 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
5:42e11dc15457 | 6:d14fd386d182 |
---|---|
1 /* | |
2 --> Sample Loaders and Sample Processing | |
3 | |
4 Name: sloader.c | |
5 | |
6 Description: | |
7 Routines for loading samples. The sample loader utilizes the routines | |
8 provided by the "registered" sample loader. See SAMPLELOADER in | |
9 MIKMOD.H for the sample loader structure. | |
10 | |
11 Portability: | |
12 All systems - all compilers | |
13 | |
14 */ | |
15 | |
16 #include "mikmod.h" | |
17 | |
18 | |
19 static int sl_rlength; | |
20 static SWORD sl_old; | |
21 static SWORD *sl_buffer = NULL; | |
22 static SAMPLOAD *musiclist = NULL, | |
23 *sndfxlist = NULL; | |
24 | |
25 | |
26 | |
27 BOOL SL_Init(SAMPLOAD *s) // returns 0 on error! | |
28 { | |
29 if(sl_buffer==NULL) | |
30 if((sl_buffer=_mm_malloc(4100)) == NULL) return 0; | |
31 | |
32 sl_rlength = s->length; | |
33 if(s->infmt & SF_16BITS) sl_rlength>>=1; | |
34 sl_old = 0; | |
35 | |
36 return 1; | |
37 } | |
38 | |
39 | |
40 void SL_Exit(SAMPLOAD *s) | |
41 { | |
42 if(sl_rlength > 0) _mm_fseek(s->fp,sl_rlength,SEEK_CUR); | |
43 } | |
44 | |
45 | |
46 void SL_Reset(void) | |
47 { | |
48 sl_old = 0; | |
49 } | |
50 | |
51 | |
52 void SL_Load(void *buffer, SAMPLOAD *smp, int length) | |
53 { | |
54 UWORD infmt = smp->infmt, outfmt = smp->outfmt; | |
55 SBYTE *bptr = (SBYTE *)buffer; | |
56 SWORD *wptr = (SWORD *)buffer; | |
57 int stodo; | |
58 int t, u; | |
59 | |
60 while(length) | |
61 { stodo = (length<2048) ? length : 2048; | |
62 | |
63 if(infmt & SF_16BITS) | |
64 { if(infmt & SF_BIG_ENDIAN) | |
65 _mm_read_M_SWORDS(sl_buffer,stodo,smp->fp); | |
66 else | |
67 _mm_read_I_SWORDS(sl_buffer,stodo,smp->fp); | |
68 } else | |
69 { SBYTE *s; | |
70 SWORD *d; | |
71 | |
72 fread(sl_buffer,sizeof(SBYTE),stodo,smp->fp); | |
73 | |
74 s = (SBYTE *)sl_buffer; | |
75 d = sl_buffer; | |
76 s += stodo; | |
77 d += stodo; | |
78 | |
79 for(t=0; t<stodo; t++) | |
80 { s--; | |
81 d--; | |
82 *d = (*s)<<8; | |
83 } | |
84 } | |
85 | |
86 if(infmt & SF_DELTA) | |
87 { for(t=0; t<stodo; t++) | |
88 { sl_buffer[t] += sl_old; | |
89 sl_old = sl_buffer[t]; | |
90 } | |
91 } | |
92 | |
93 if((infmt^outfmt) & SF_SIGNED) | |
94 { for(t=0; t<stodo; t++) | |
95 sl_buffer[t] ^= 0x8000; | |
96 } | |
97 | |
98 if(smp->scalefactor) | |
99 { int idx = 0; | |
100 SLONG scaleval; | |
101 | |
102 // Sample Scaling... average values for better results. | |
103 t = 0; | |
104 while(t<stodo && length) | |
105 { scaleval = 0; | |
106 for(u=smp->scalefactor; u && t<stodo; u--, t++) | |
107 scaleval += sl_buffer[t]; | |
108 sl_buffer[idx++] = scaleval / (smp->scalefactor-u); | |
109 length--; | |
110 } | |
111 sl_rlength -= stodo; | |
112 stodo = idx; | |
113 } else | |
114 { length -= stodo; | |
115 sl_rlength -= stodo; | |
116 } | |
117 | |
118 if(outfmt & SF_16BITS) | |
119 { for(t=0; t<stodo; t++) *(wptr++) = sl_buffer[t]; | |
120 } else | |
121 { for(t=0; t<stodo; t++) *(bptr++) = sl_buffer[t]>>8; | |
122 } | |
123 } | |
124 } | |
125 | |
126 | |
127 void SL_LoadStream(void *buffer, UWORD infmt, UWORD outfmt, int length, FILE *fp) | |
128 | |
129 // This is like SL_Load, but does not perform sample scaling, and does not | |
130 // require calls to SL_Init / SL_Exit. | |
131 | |
132 { | |
133 SBYTE *bptr = (SBYTE *)buffer; | |
134 SWORD *wptr = (SWORD *)buffer; | |
135 int stodo; | |
136 int t; | |
137 | |
138 // compute number of samples to load | |
139 | |
140 if(sl_buffer==NULL) | |
141 if((sl_buffer=_mm_malloc(4100)) == NULL) return; | |
142 | |
143 while(length) | |
144 { stodo = (length<2048) ? length : 2048; | |
145 | |
146 if(infmt & SF_16BITS) | |
147 { if(infmt & SF_BIG_ENDIAN) | |
148 _mm_read_M_SWORDS(sl_buffer,stodo,fp); | |
149 else | |
150 _mm_read_I_SWORDS(sl_buffer,stodo,fp); | |
151 } else | |
152 { SBYTE *s; | |
153 SWORD *d; | |
154 | |
155 fread(sl_buffer,sizeof(SBYTE),stodo,fp); | |
156 | |
157 s = (SBYTE *)sl_buffer; | |
158 d = sl_buffer; | |
159 s += stodo; | |
160 d += stodo; | |
161 | |
162 for(t=0; t<stodo; t++) | |
163 { s--; | |
164 d--; | |
165 *d = (*s)<<8; | |
166 } | |
167 } | |
168 | |
169 if(infmt & SF_DELTA) | |
170 { for(t=0; t<stodo; t++) | |
171 { sl_buffer[t] += sl_old; | |
172 sl_old = sl_buffer[t]; | |
173 } | |
174 } | |
175 | |
176 if((infmt^outfmt) & SF_SIGNED) | |
177 { for(t=0; t<stodo; t++) | |
178 sl_buffer[t] ^= 0x8000; | |
179 } | |
180 | |
181 length -= stodo; | |
182 | |
183 if((infmt & SF_STEREO) && !(outfmt & SF_STEREO)) | |
184 { // Dither stereo to mono .. average together every two samples | |
185 SLONG avgval; | |
186 int idx = 0; | |
187 | |
188 t = 0; | |
189 while(t<stodo && length) | |
190 { avgval = sl_buffer[t++]; | |
191 avgval += sl_buffer[t++]; | |
192 sl_buffer[idx++] = avgval >> 1; | |
193 length-=2; | |
194 } | |
195 stodo = idx; | |
196 } | |
197 | |
198 if(outfmt & SF_16BITS) | |
199 { for(t=0; t<stodo; t++) *(wptr++) = sl_buffer[t]; | |
200 } else | |
201 { for(t=0; t<stodo; t++) *(bptr++) = sl_buffer[t]>>8; | |
202 } | |
203 } | |
204 } | |
205 | |
206 | |
207 SAMPLOAD *SL_RegisterSample(SAMPLE *s, int type, FILE *fp) // Returns 1 on error! | |
208 | |
209 // Registers a sample for loading when SL_LoadSamples() is called. | |
210 // type - type of sample to be loaded .. | |
211 // MD_MUSIC, MD_SNDFX | |
212 | |
213 { | |
214 SAMPLOAD *news, **samplist, *cruise; | |
215 | |
216 if(type==MD_MUSIC) | |
217 { samplist = & musiclist; | |
218 cruise = musiclist; | |
219 } else | |
220 { samplist = &sndfxlist; | |
221 cruise = sndfxlist; | |
222 } | |
223 | |
224 // Allocate and add structure to the END of the list | |
225 | |
226 if((news=(SAMPLOAD *)_mm_calloc(1,sizeof(SAMPLOAD))) == NULL) return NULL; | |
227 | |
228 if(cruise!=NULL) | |
229 { while(cruise->next!=NULL) cruise = cruise->next; | |
230 cruise->next = news; | |
231 } else | |
232 *samplist = news; | |
233 | |
234 news->infmt = s->flags & 31; | |
235 news->outfmt = news->infmt; | |
236 news->fp = fp; | |
237 news->sample = s; | |
238 news->length = s->length; | |
239 news->loopstart = s->loopstart; | |
240 news->loopend = s->loopend; | |
241 | |
242 return news; | |
243 } | |
244 | |
245 | |
246 static void FreeSampleList(SAMPLOAD *s) | |
247 { | |
248 SAMPLOAD *old; | |
249 | |
250 while(s!=NULL) | |
251 { old = s; | |
252 s = s->next; | |
253 free(old); | |
254 } | |
255 } | |
256 | |
257 | |
258 static ULONG SampleTotal(SAMPLOAD *samplist, int type) | |
259 // Returns the total amount of memory required by the samplelist queue. | |
260 { | |
261 int total = 0; | |
262 | |
263 while(samplist!=NULL) | |
264 { samplist->sample->flags = (samplist->sample->flags&~31) | samplist->outfmt; | |
265 total += MD_SampleLength(type,samplist->sample); | |
266 samplist = samplist->next; | |
267 } | |
268 | |
269 return total; | |
270 } | |
271 | |
272 | |
273 static ULONG RealSpeed(SAMPLOAD *s) | |
274 { | |
275 return(s->sample->speed / ((s->scalefactor==0) ? 1 : s->scalefactor)); | |
276 } | |
277 | |
278 | |
279 static BOOL DitherSamples(SAMPLOAD *samplist, int type) | |
280 { | |
281 SAMPLOAD *c2smp; | |
282 ULONG maxsize, speed; | |
283 SAMPLOAD *s; | |
284 | |
285 if(samplist==NULL) return 0; | |
286 | |
287 // make sure the samples will fit inside available RAM | |
288 if((maxsize = MD_SampleSpace(type)*1024) != 0) | |
289 { while(SampleTotal(samplist, type) > maxsize) | |
290 { // First Pass - check for any 16 bit samples | |
291 s = samplist; | |
292 while(s!=NULL) | |
293 { if(s->outfmt & SF_16BITS) | |
294 { SL_Sample16to8(s); | |
295 break; | |
296 } | |
297 s = s->next; | |
298 } | |
299 | |
300 // Second pass (if no 16bits found above) is to take the sample | |
301 // with the highest speed and dither it by half. | |
302 if(s==NULL) | |
303 { s = samplist; | |
304 speed = 0; | |
305 while(s!=NULL) | |
306 { if((s->sample->length) && (RealSpeed(s) > speed)) | |
307 { speed = RealSpeed(s); | |
308 c2smp = s; | |
309 } | |
310 s = s->next; | |
311 } | |
312 SL_HalveSample(c2smp); | |
313 } | |
314 } | |
315 } | |
316 | |
317 | |
318 // Samples dithered, now load them! | |
319 // ================================ | |
320 | |
321 s = samplist; | |
322 while(s != NULL) | |
323 { // sample has to be loaded ? -> increase number of | |
324 // samples, allocate memory and load sample. | |
325 | |
326 if(s->sample->length) | |
327 { if(s->sample->seekpos) | |
328 _mm_fseek(s->fp, s->sample->seekpos, SEEK_SET); | |
329 | |
330 // Call the sample load routine of the driver module. | |
331 // It has to return a 'handle' (>=0) that identifies | |
332 // the sample. | |
333 | |
334 s->sample->handle = MD_SampleLoad(s, type, s->fp); | |
335 s->sample->flags = (s->sample->flags & ~31) | s->outfmt; | |
336 if(s->sample->handle < 0) | |
337 { FreeSampleList(samplist); | |
338 if(_mm_errorhandler!=NULL) _mm_errorhandler(); | |
339 return 1; | |
340 } | |
341 } | |
342 s = s->next; | |
343 } | |
344 | |
345 FreeSampleList(samplist); | |
346 return 0; | |
347 } | |
348 | |
349 | |
350 BOOL SL_LoadSamples(void) // Returns 1 on error! | |
351 { | |
352 BOOL ok; | |
353 | |
354 _mm_critical = 0; | |
355 | |
356 if((musiclist==NULL) && (sndfxlist==NULL)) return 0; | |
357 // MikMod_Exit(); | |
358 // exit(1); | |
359 ok = DitherSamples(musiclist,MD_MUSIC) || DitherSamples(sndfxlist,MD_SNDFX); | |
360 | |
361 musiclist = sndfxlist = NULL; | |
362 | |
363 return ok; | |
364 } | |
365 | |
366 | |
367 void SL_Sample16to8(SAMPLOAD *s) | |
368 { | |
369 s->outfmt &= ~SF_16BITS; | |
370 s->sample->flags = (s->sample->flags&~31) | s->outfmt; | |
371 } | |
372 | |
373 | |
374 void SL_Sample8to16(SAMPLOAD *s) | |
375 { | |
376 s->outfmt |= SF_16BITS; | |
377 s->sample->flags = (s->sample->flags&~31) | s->outfmt; | |
378 } | |
379 | |
380 | |
381 void SL_SampleSigned(SAMPLOAD *s) | |
382 { | |
383 s->outfmt |= SF_SIGNED; | |
384 s->sample->flags = (s->sample->flags&~31) | s->outfmt; | |
385 } | |
386 | |
387 | |
388 void SL_SampleUnsigned(SAMPLOAD *s) | |
389 { | |
390 s->outfmt &= ~SF_SIGNED; | |
391 s->sample->flags = (s->sample->flags&~31) | s->outfmt; | |
392 } | |
393 | |
394 | |
395 void SL_HalveSample(SAMPLOAD *s) | |
396 { | |
397 if(s->scalefactor) | |
398 s->scalefactor++; | |
399 else | |
400 s->scalefactor = 2; | |
401 | |
402 s->sample->divfactor = s->scalefactor; | |
403 s->sample->length = s->length / s->scalefactor; | |
404 s->sample->loopstart = s->loopstart / s->scalefactor; | |
405 s->sample->loopend = s->loopend / s->scalefactor; | |
406 } | |
407 |