]> git.mxchange.org Git - simgear.git/blob - src/slSample.cxx
Minor optimization tweaks.
[simgear.git] / src / slSample.cxx
1
2
3 #include "sl.h"
4 #include <math.h>
5
6 void slSample::autoMatch ( slDSP *dsp )
7 {
8   if ( dsp == NULL ) return ;
9
10   changeRate   ( dsp->getRate   () ) ;
11   changeBps    ( dsp->getBps    () ) ;
12   changeStereo ( dsp->getStereo () ) ;
13 }
14
15 void slSample::adjustVolume ( float vol )
16 {
17   for ( int i = 0 ; i < length ; i++ )
18   {
19     int s = (int)(((float) buffer[i] - (float) 0x80) * vol) + 0x80 ;
20
21     buffer [ i ] = ( s > 255 ) ? 255 :
22                      ( s < 0 ) ? 0 : s ;
23   }
24 }
25
26
27 void slSample::changeRate   ( int r )
28 {
29   if ( r == rate ) return ;
30
31   int    length1 = length / (getBps ()/8) ;
32   int    length2 = (int) ( (float) length1 * ( (float) r / (float) rate ) ) ;
33   Uchar *buffer2 = new Uchar [ length2 ] ;
34
35   float step = (float) length1 / (float) length2 ;
36
37   for ( int i = 0 ; i < length2 / (getBps()/8); i++ )
38   {
39     float pos = (float) i * step ;
40
41     int p1 = (int) floor ( pos ) ;
42     int p2 = (int) ceil  ( pos ) ;
43
44     if ( stereo )
45     {
46       if ( ( p1 & 1 ) != ( i & 1 ) ) { pos++ ; p1++ ; p2++ ; }
47       p2++ ;
48     }
49
50     float ratio = pos - (float) p1 ;
51
52     float b1 = (getBps()==8) ?
53         (float)           buffer [(p1<0)?0:(p1>=length1)?length1-1:p1] :
54         (float) ((Ushort*)buffer)[(p1<0)?0:(p1>=length1)?length1-1:p1] ;
55     float b2 = (getBps()==8) ?
56         (float)           buffer [(p2<0)?0:(p2>=length1)?length1-1:p2] :
57         (float) ((Ushort*)buffer)[(p2<0)?0:(p2>=length1)?length1-1:p2] ;
58
59     float res = b1 * (1.0-ratio) + b2 * ratio ;
60
61     if ( getBps () == 8 )
62       buffer2 [ i ] = (Uchar) ( (res < 0) ? 0 : (res > 255) ? 255 : res ) ;
63     else
64       ((Ushort *) buffer2 ) [ i ] = 
65                 (Ushort) ( (res < 0) ? 0 : (res > 65535) ? 65535 : res ) ;
66   }
67
68   rate   = r ;
69   length = length2 ;
70   delete buffer ;
71   buffer = buffer2 ;
72 }
73
74
75 void slSample::changeToUnsigned ()
76 {
77   if ( getBps() == 16 )
78   {
79     int length2 = length / 2 ;
80     Ushort *buffer2 = (Ushort *) buffer ;
81
82     for ( int i = 0 ; i < length2 ; i++ )
83       buffer2 [ i ] = buffer2 [ i ] + 32768 ;
84   }
85   else
86   {
87     for ( int i = 0 ; i < length ; i++ )
88       buffer [ i ] = (buffer [ i ]>0x80) ? (buffer[i]-0x80) :
89                                            (0xFF-buffer[i]) ;
90   }
91 }
92
93
94
95 void slSample::changeBps    ( int b )
96 {
97   if ( b == getBps () ) return ;
98
99   if ( b == 8 && getBps() == 16 )
100   {
101     length /= 2 ;
102     Uchar *buffer2 = new Uchar [ length ] ;
103
104     for ( int i = 0 ; i < length ; i++ )
105       buffer2 [ i ] = ((Ushort *)buffer) [ i ] >> 8 ;
106
107     delete buffer ;
108     buffer = buffer2 ;
109     setBps ( b ) ;
110   }
111   else
112   if ( b == 16 && getBps() == 8 )
113   {
114     Ushort *buffer2 = new Ushort [ length ] ;
115
116     for ( int i = 0 ; i < length ; i++ )
117       buffer2 [ i ] = buffer [ i ] << 8 ;
118
119     delete buffer ;
120     buffer = (Uchar *) buffer2 ;
121     length *= 2 ;
122     setBps ( b ) ;
123   }
124 }
125
126 void slSample::changeStereo ( int s )
127 {
128   if ( s == getStereo () )
129     return ;
130
131   if ( s && ! getStereo () )
132   {
133     if ( getBps () == 8 )
134     {
135        Uchar *buffer2 = new Uchar [ length * 2 ] ;
136
137        for ( int i = 0 ; i < length ; i++ )
138          buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = buffer [ i ] ;
139
140        delete buffer ;
141        buffer = buffer2 ;
142        length *= 2 ;
143        setStereo ( SL_TRUE ) ;
144     }
145     else
146     {
147        Ushort *buffer2 = new Ushort [ length ] ;
148
149        for ( int i = 0 ; i < length / 2 ; i++ )
150          buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = ((Ushort *) buffer) [ i ] ;
151
152        delete buffer ;
153        buffer = (Uchar *)buffer2 ;
154        length *= 2 ;
155        setStereo ( SL_TRUE ) ;
156     }
157   }
158   else
159   {
160     if ( getBps () == 8 )
161     {
162        Uchar *buffer2 = new Uchar [ length / 2 ] ;
163
164        for ( int i = 0 ; i < (length-1)/2 ; i++ )
165          buffer2 [ i ] = ((int)buffer [ i*2 ] + (int)buffer [ i*2 + 1 ] ) / 2 ;
166
167        delete buffer ;
168        buffer = buffer2 ;
169        length /= 2 ;
170        setStereo ( SL_FALSE ) ;
171     }
172     else
173     {
174        Ushort *buffer2 = new Ushort [ length / 4 ] ;
175
176        for ( int i = 0 ; i < (length-3) / 4 ; i++ )
177          buffer2 [ i ] = ((int)((Ushort *)buffer) [ i*2 ] +
178                           (int)((Ushort *)buffer) [ i*2 + 1 ] ) / 2 ;
179
180        delete buffer ;
181        buffer = (Uchar *)buffer2 ;
182        length /= 4 ;
183        setStereo ( SL_FALSE ) ;
184     }
185   }
186 }
187
188
189 static void swap_Ushort ( Ushort *i )
190 {
191   *i = ((*i << 8) & 0xFF00) +
192        ((*i >> 8) & 0x00FF) ;
193 }
194
195 static void swap_int ( int *i )
196 {
197   *i = ((*i << 24) & 0xFF000000) +
198        ((*i <<  8) & 0x00FF0000) +
199        ((*i >>  8) & 0x0000FF00) +
200        ((*i >> 24) & 0x000000FF) ;
201 }
202
203 int slSample::loadFile ( char *fname )
204 {
205   if ( strcasecmp ( & fname [ strlen ( fname ) - 4 ], ".wav" ) == 0 )
206     return loadWavFile ( fname ) ;
207
208   if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".au" ) == 0 )
209     return loadAUFile ( fname ) ;
210
211   if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".ub" ) == 0 )
212     return loadRawFile ( fname ) ;
213
214   fprintf ( stderr, "slSample:loadFile: Unknown file type for '%s'.\n",
215                                     fname ) ;
216   return SL_FALSE ;
217 }
218
219
220 int slSample::loadWavFile ( char *fname )
221 {
222   int found_header   = SL_FALSE ;
223   int needs_swabbing = SL_FALSE ;
224
225   delete buffer ;
226   buffer = NULL ;
227   length = 0 ;
228
229   FILE *fd = fopen ( fname, "rb" ) ;
230
231   if ( fd == NULL )
232   {
233     fprintf ( stderr,
234              "slSample: loadWavFile: Cannot open '%s' for reading.\n",
235              fname ) ;
236     return SL_FALSE ;
237   }
238
239   char magic [ 8 ] ;
240
241   if ( fread ( magic, 4, 1, fd ) == 0 ||
242        magic[0] != 'R' || magic[1] != 'I' ||
243        magic[2] != 'F' || magic[3] != 'F' )
244   {
245     fprintf ( stderr, "slWavSample: File '%s' has wrong magic number\n", fname ) ;
246     fprintf ( stderr, "            - it probably isn't in '.wav' format.\n" ) ;
247     fclose ( fd ) ;
248     return SL_FALSE ;
249   }
250
251   int leng1 ;
252
253   if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 )
254   {
255     fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
256     fclose ( fd ) ;
257     return SL_FALSE ;
258   }
259
260   fread ( magic, 4, 1, fd ) ;
261
262   if ( magic[0] != 'W' || magic[1] != 'A' ||
263        magic[2] != 'V' || magic[3] != 'E' )
264   {
265     fprintf ( stderr, "slSample: File '%s' has no WAVE tag.\n", fname ) ;
266     fclose ( fd ) ;
267     return SL_FALSE ;
268   }
269
270   while ( ! feof ( fd ) )
271   {
272     fread ( magic, 4, 1, fd ) ;
273
274     if ( magic[0] == 'f' && magic[1] == 'm' &&
275          magic[2] == 't' && magic[3] == ' ' )
276     {
277       found_header = SL_TRUE ;
278
279       if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 )
280       {
281         fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
282         fclose ( fd ) ;
283         return SL_FALSE ;
284       }
285
286       if ( leng1 > 65536 )
287       {
288         needs_swabbing = SL_TRUE ;
289         swap_int ( & leng1 ) ;
290       }
291
292       Ushort header [ 8 ] ;
293
294       if ( leng1 != sizeof ( header ) )
295         fprintf ( stderr,
296                "slSample: File '%s' has unexpectedly long (%d byte) header\n",
297                fname, leng1 ) ;
298
299       fread ( & header, sizeof(header), 1, fd ) ;
300
301       for ( int junk = sizeof(header) ; junk < leng1 ; junk++ )
302         fgetc ( fd ) ;
303
304       if ( needs_swabbing )
305       {
306         swap_Ushort ( & header[0] ) ;
307         swap_Ushort ( & header[1] ) ;
308         swap_int    ( (int *) & header[2] ) ;
309         swap_int    ( (int *) & header[4] ) ;
310         swap_Ushort ( & header[6] ) ;
311         swap_Ushort ( & header[7] ) ;
312       }
313
314       if ( header [ 0 ] != 0x0001 )
315       {
316         fprintf ( stderr, "slSample: File '%s' is not WAVE_FORMAT_PCM!\n", fname ) ;
317         fclose ( fd ) ;
318         return SL_FALSE ;
319       }
320
321       setStereo ( header[1] > 1 ) ;
322       setRate   ( *((int *) (& header[2])) ) ;
323       setBps    ( header[7] ) ;
324     }
325     else
326     if ( magic[0] == 'd' && magic[1] == 'a' &&
327          magic[2] == 't' && magic[3] == 'a' )
328     {
329       if ( ! found_header )
330       {
331         fprintf ( stderr, "slSample: File '%s' has no data section\n", fname ) ;
332         fclose ( fd ) ;
333         return SL_FALSE ;
334       }
335
336       if ( fread ( & length, sizeof(int), 1, fd ) == 0 )
337       {
338         fprintf ( stderr, "slSample: File '%s' has premature EOF in data\n", fname ) ;
339         fclose ( fd ) ;
340         return SL_FALSE ;
341       }
342
343       if ( needs_swabbing )
344         swap_int ( & length ) ;
345
346       buffer = new Uchar [ length ] ;
347
348       fread ( buffer, 1, length, fd ) ;
349
350       if ( getBps () == 16 )
351       {
352         Ushort *b = (Ushort*) buffer ;
353
354         for ( int i = 0 ; i < length/2 ; i++ )
355           b [ i ] = (Ushort) ( (int)((short) b [ i ]) + 32768 ) ;
356       }
357
358       fclose ( fd ) ;
359       return SL_TRUE ;
360     }
361   }
362
363   fclose ( fd ) ;
364   return SL_FALSE ;
365 }
366
367 int slSample::loadAUFile ( char *fname )
368 {
369   delete buffer ;
370   buffer = NULL ;
371   length = 0 ;
372
373   FILE *fd = fopen ( fname, "rb" ) ;
374
375   if ( fd == NULL )
376   {
377     fprintf ( stderr,
378              "slSample: loadAUFile: Cannot open '%s' for reading.\n",
379              fname ) ;
380     return SL_FALSE ;
381   }
382
383   char magic [ 4 ] ;
384
385   if ( fread ( magic, 4, 1, fd ) == 0 ||
386        magic[0] != '.' || magic[1] != 's' ||
387        magic[2] != 'n' || magic[3] != 'd' )
388   {
389     fprintf ( stderr, "slSample: File '%s' has wrong magic number\n", fname ) ;
390     fprintf ( stderr, "            - it probably isn't in '.au' format.\n" ) ;
391     fclose ( fd ) ;
392     return SL_FALSE ;
393   }
394
395   int hdr_length ;
396   int dat_length ;
397   int nbytes ;
398   int irate  ;
399   int nchans ;
400
401   if ( fread ( & hdr_length, sizeof(int), 1, fd ) == 0 ||
402        fread ( & dat_length, sizeof(int), 1, fd ) == 0 ||
403        fread ( & nbytes    , sizeof(int), 1, fd ) == 0 ||
404        fread ( & irate     , sizeof(int), 1, fd ) == 0 ||
405        fread ( & nchans    , sizeof(int), 1, fd ) == 0 )
406   {
407     fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ;
408     fclose ( fd ) ;
409     return SL_FALSE ;
410   }
411
412   if ( hdr_length > 65536 )
413   {
414     swap_int ( & hdr_length ) ;
415     swap_int ( & dat_length ) ;
416     swap_int ( & nbytes ) ;
417     swap_int ( & irate  ) ;
418     swap_int ( & nchans ) ;
419   }
420
421   bps    = nbytes * 8 ;
422   stereo = (nchans>1) ;
423   rate   = irate      ;
424
425   if ( nbytes > 2 || nbytes <= 0 || hdr_length > 512 || hdr_length < 24 ||
426        irate > 65526 || irate <= 1000 || nchans < 1 || nchans > 2 )
427   {
428     fprintf ( stderr, "slSample: File '%s' has a very strange header\n", fname ) ;
429
430     fprintf ( stderr, "  Header Length = %d\n", hdr_length ) ;
431     fprintf ( stderr, "  Data   Length = %d\n", dat_length ) ;
432     fprintf ( stderr, "  Bytes/sample  = %d\n", nbytes     ) ;
433     fprintf ( stderr, "  Sampling Rate = %dHz\n",irate     ) ;
434     fprintf ( stderr, "  Num Channels  = %d\n", nchans     ) ;
435     fprintf ( stderr, "\n" ) ;
436     fclose ( fd ) ;
437     return SL_FALSE ;
438   }
439
440   if ( hdr_length > 24 )
441   {
442     delete comment ;
443     comment = new char [ hdr_length - 24 + 1 ] ;
444
445     fread ( comment, 1, hdr_length - 24, fd ) ;
446   }
447
448   if ( dat_length > 0 )
449   {
450     buffer = new Uchar [ dat_length ] ;
451     length = fread ( buffer, 1, dat_length, fd ) ;
452
453     if ( length != dat_length )
454       fprintf ( stderr, "slAUSample: File '%s' has premature EOF in data.\n", fname ) ;
455   }
456
457   fclose ( fd ) ;
458   return SL_TRUE ;
459 }
460
461
462 int slSample::loadRawFile ( char *fname )
463 {
464   delete buffer ;
465   buffer = NULL ;
466   length = 0 ;
467
468   FILE *fd = fopen ( fname, "rb" ) ;
469
470   if ( fd == NULL )
471   {
472     fprintf ( stderr,
473               "slSample: loadRawFile: Cannot open '%s' for reading.\n",
474              fname ) ;
475     return SL_FALSE ;
476   }
477
478   struct stat stat_buf ;
479
480   if ( fstat ( fileno ( fd ), & stat_buf ) != 0 )
481   {
482     fprintf ( stderr,
483              "slSample: loadRawFile: Cannot get status for '%s'.\n",
484              fname ) ;        
485     fclose ( fd ) ;
486     return SL_FALSE ;
487   }
488
489   length = stat_buf . st_size ;
490
491   if ( length > 0 )
492   {
493     buffer = new Uchar [ length ] ;
494     length = fread ( buffer, 1, length, fd ) ;
495   }
496
497   bps    = 8     ;
498   stereo = SL_FALSE ;
499   rate   = 8000  ;  /* Guess */
500
501   fclose ( fd ) ;
502   return SL_TRUE ;
503 }
504
505