#include "sl.h" #include void slSample::autoMatch ( slDSP *dsp ) { if ( dsp == NULL ) return ; changeRate ( dsp->getRate () ) ; changeBps ( dsp->getBps () ) ; changeStereo ( dsp->getStereo () ) ; } void slSample::adjustVolume ( float vol ) { for ( int i = 0 ; i < length ; i++ ) { int s = (int)(((float) buffer[i] - (float) 0x80) * vol) + 0x80 ; buffer [ i ] = ( s > 255 ) ? 255 : ( s < 0 ) ? 0 : s ; } } void slSample::changeRate ( int r ) { if ( r == rate ) return ; int length1 = length / (getBps ()/8) ; int length2 = (int) ( (float) length1 * ( (float) r / (float) rate ) ) ; Uchar *buffer2 = new Uchar [ length2 ] ; float step = (float) length1 / (float) length2 ; for ( int i = 0 ; i < length2 / (getBps()/8); i++ ) { float pos = (float) i * step ; int p1 = (int) floor ( pos ) ; int p2 = (int) ceil ( pos ) ; if ( stereo ) { if ( ( p1 & 1 ) != ( i & 1 ) ) { pos++ ; p1++ ; p2++ ; } p2++ ; } float ratio = pos - (float) p1 ; float b1 = (getBps()==8) ? (float) buffer [(p1<0)?0:(p1>=length1)?length1-1:p1] : (float) ((Ushort*)buffer)[(p1<0)?0:(p1>=length1)?length1-1:p1] ; float b2 = (getBps()==8) ? (float) buffer [(p2<0)?0:(p2>=length1)?length1-1:p2] : (float) ((Ushort*)buffer)[(p2<0)?0:(p2>=length1)?length1-1:p2] ; float res = b1 * (1.0-ratio) + b2 * ratio ; if ( getBps () == 8 ) buffer2 [ i ] = (Uchar) ( (res < 0) ? 0 : (res > 255) ? 255 : res ) ; else ((Ushort *) buffer2 ) [ i ] = (Ushort) ( (res < 0) ? 0 : (res > 65535) ? 65535 : res ) ; } rate = r ; length = length2 ; delete buffer ; buffer = buffer2 ; } void slSample::changeToUnsigned () { if ( getBps() == 16 ) { int length2 = length / 2 ; Ushort *buffer2 = (Ushort *) buffer ; for ( int i = 0 ; i < length2 ; i++ ) buffer2 [ i ] = buffer2 [ i ] + 32768 ; } else { for ( int i = 0 ; i < length ; i++ ) buffer [ i ] = (buffer [ i ]>0x80) ? (buffer[i]-0x80) : (0xFF-buffer[i]) ; } } void slSample::changeBps ( int b ) { if ( b == getBps () ) return ; if ( b == 8 && getBps() == 16 ) { length /= 2 ; Uchar *buffer2 = new Uchar [ length ] ; for ( int i = 0 ; i < length ; i++ ) buffer2 [ i ] = ((Ushort *)buffer) [ i ] >> 8 ; delete buffer ; buffer = buffer2 ; setBps ( b ) ; } else if ( b == 16 && getBps() == 8 ) { Ushort *buffer2 = new Ushort [ length ] ; for ( int i = 0 ; i < length ; i++ ) buffer2 [ i ] = buffer [ i ] << 8 ; delete buffer ; buffer = (Uchar *) buffer2 ; length *= 2 ; setBps ( b ) ; } } void slSample::changeStereo ( int s ) { if ( s == getStereo () ) return ; if ( s && ! getStereo () ) { if ( getBps () == 8 ) { Uchar *buffer2 = new Uchar [ length * 2 ] ; for ( int i = 0 ; i < length ; i++ ) buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = buffer [ i ] ; delete buffer ; buffer = buffer2 ; length *= 2 ; setStereo ( SL_TRUE ) ; } else { Ushort *buffer2 = new Ushort [ length ] ; for ( int i = 0 ; i < length / 2 ; i++ ) buffer2 [ i*2 ] = buffer2 [ i*2+1 ] = ((Ushort *) buffer) [ i ] ; delete buffer ; buffer = (Uchar *)buffer2 ; length *= 2 ; setStereo ( SL_TRUE ) ; } } else { if ( getBps () == 8 ) { Uchar *buffer2 = new Uchar [ length / 2 ] ; for ( int i = 0 ; i < (length-1)/2 ; i++ ) buffer2 [ i ] = ((int)buffer [ i*2 ] + (int)buffer [ i*2 + 1 ] ) / 2 ; delete buffer ; buffer = buffer2 ; length /= 2 ; setStereo ( SL_FALSE ) ; } else { Ushort *buffer2 = new Ushort [ length / 4 ] ; for ( int i = 0 ; i < (length-3) / 4 ; i++ ) buffer2 [ i ] = ((int)((Ushort *)buffer) [ i*2 ] + (int)((Ushort *)buffer) [ i*2 + 1 ] ) / 2 ; delete buffer ; buffer = (Uchar *)buffer2 ; length /= 4 ; setStereo ( SL_FALSE ) ; } } } static void swap_Ushort ( Ushort *i ) { *i = ((*i << 8) & 0xFF00) + ((*i >> 8) & 0x00FF) ; } static void swap_int ( int *i ) { *i = ((*i << 24) & 0xFF000000) + ((*i << 8) & 0x00FF0000) + ((*i >> 8) & 0x0000FF00) + ((*i >> 24) & 0x000000FF) ; } int slSample::loadFile ( char *fname ) { if ( strcasecmp ( & fname [ strlen ( fname ) - 4 ], ".wav" ) == 0 ) return loadWavFile ( fname ) ; if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".au" ) == 0 ) return loadAUFile ( fname ) ; if ( strcasecmp ( & fname [ strlen ( fname ) - 3 ], ".ub" ) == 0 ) return loadRawFile ( fname ) ; fprintf ( stderr, "slSample:loadFile: Unknown file type for '%s'.\n", fname ) ; return SL_FALSE ; } int slSample::loadWavFile ( char *fname ) { int found_header = SL_FALSE ; int needs_swabbing = SL_FALSE ; delete buffer ; buffer = NULL ; length = 0 ; FILE *fd = fopen ( fname, "rb" ) ; if ( fd == NULL ) { fprintf ( stderr, "slSample: loadWavFile: Cannot open '%s' for reading.\n", fname ) ; return SL_FALSE ; } char magic [ 8 ] ; if ( fread ( magic, 4, 1, fd ) == 0 || magic[0] != 'R' || magic[1] != 'I' || magic[2] != 'F' || magic[3] != 'F' ) { fprintf ( stderr, "slWavSample: File '%s' has wrong magic number\n", fname ) ; fprintf ( stderr, " - it probably isn't in '.wav' format.\n" ) ; fclose ( fd ) ; return SL_FALSE ; } int leng1 ; if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 ) { fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } fread ( magic, 4, 1, fd ) ; if ( magic[0] != 'W' || magic[1] != 'A' || magic[2] != 'V' || magic[3] != 'E' ) { fprintf ( stderr, "slSample: File '%s' has no WAVE tag.\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } while ( ! feof ( fd ) ) { fread ( magic, 4, 1, fd ) ; if ( magic[0] == 'f' && magic[1] == 'm' && magic[2] == 't' && magic[3] == ' ' ) { found_header = SL_TRUE ; if ( fread ( & leng1, sizeof(int), 1, fd ) == 0 ) { fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } if ( leng1 > 65536 ) { needs_swabbing = SL_TRUE ; swap_int ( & leng1 ) ; } Ushort header [ 8 ] ; if ( leng1 != sizeof ( header ) ) fprintf ( stderr, "slSample: File '%s' has unexpectedly long (%d byte) header\n", fname, leng1 ) ; fread ( & header, sizeof(header), 1, fd ) ; for ( int junk = sizeof(header) ; junk < leng1 ; junk++ ) fgetc ( fd ) ; if ( needs_swabbing ) { swap_Ushort ( & header[0] ) ; swap_Ushort ( & header[1] ) ; swap_int ( (int *) & header[2] ) ; swap_int ( (int *) & header[4] ) ; swap_Ushort ( & header[6] ) ; swap_Ushort ( & header[7] ) ; } if ( header [ 0 ] != 0x0001 ) { fprintf ( stderr, "slSample: File '%s' is not WAVE_FORMAT_PCM!\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } setStereo ( header[1] > 1 ) ; setRate ( *((int *) (& header[2])) ) ; setBps ( header[7] ) ; } else if ( magic[0] == 'd' && magic[1] == 'a' && magic[2] == 't' && magic[3] == 'a' ) { if ( ! found_header ) { fprintf ( stderr, "slSample: File '%s' has no data section\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } if ( fread ( & length, sizeof(int), 1, fd ) == 0 ) { fprintf ( stderr, "slSample: File '%s' has premature EOF in data\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } if ( needs_swabbing ) swap_int ( & length ) ; buffer = new Uchar [ length ] ; fread ( buffer, 1, length, fd ) ; if ( getBps () == 16 ) { Ushort *b = (Ushort*) buffer ; for ( int i = 0 ; i < length/2 ; i++ ) b [ i ] = (Ushort) ( (int)((short) b [ i ]) + 32768 ) ; } fclose ( fd ) ; return SL_TRUE ; } } fclose ( fd ) ; return SL_FALSE ; } int slSample::loadAUFile ( char *fname ) { delete buffer ; buffer = NULL ; length = 0 ; FILE *fd = fopen ( fname, "rb" ) ; if ( fd == NULL ) { fprintf ( stderr, "slSample: loadAUFile: Cannot open '%s' for reading.\n", fname ) ; return SL_FALSE ; } char magic [ 4 ] ; if ( fread ( magic, 4, 1, fd ) == 0 || magic[0] != '.' || magic[1] != 's' || magic[2] != 'n' || magic[3] != 'd' ) { fprintf ( stderr, "slSample: File '%s' has wrong magic number\n", fname ) ; fprintf ( stderr, " - it probably isn't in '.au' format.\n" ) ; fclose ( fd ) ; return SL_FALSE ; } int hdr_length ; int dat_length ; int nbytes ; int irate ; int nchans ; if ( fread ( & hdr_length, sizeof(int), 1, fd ) == 0 || fread ( & dat_length, sizeof(int), 1, fd ) == 0 || fread ( & nbytes , sizeof(int), 1, fd ) == 0 || fread ( & irate , sizeof(int), 1, fd ) == 0 || fread ( & nchans , sizeof(int), 1, fd ) == 0 ) { fprintf ( stderr, "slSample: File '%s' has premature EOF in header\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } if ( hdr_length > 65536 ) { swap_int ( & hdr_length ) ; swap_int ( & dat_length ) ; swap_int ( & nbytes ) ; swap_int ( & irate ) ; swap_int ( & nchans ) ; } bps = nbytes * 8 ; stereo = (nchans>1) ; rate = irate ; if ( nbytes > 2 || nbytes <= 0 || hdr_length > 512 || hdr_length < 24 || irate > 65526 || irate <= 1000 || nchans < 1 || nchans > 2 ) { fprintf ( stderr, "slSample: File '%s' has a very strange header\n", fname ) ; fprintf ( stderr, " Header Length = %d\n", hdr_length ) ; fprintf ( stderr, " Data Length = %d\n", dat_length ) ; fprintf ( stderr, " Bytes/sample = %d\n", nbytes ) ; fprintf ( stderr, " Sampling Rate = %dHz\n",irate ) ; fprintf ( stderr, " Num Channels = %d\n", nchans ) ; fprintf ( stderr, "\n" ) ; fclose ( fd ) ; return SL_FALSE ; } if ( hdr_length > 24 ) { delete comment ; comment = new char [ hdr_length - 24 + 1 ] ; fread ( comment, 1, hdr_length - 24, fd ) ; } if ( dat_length > 0 ) { buffer = new Uchar [ dat_length ] ; length = fread ( buffer, 1, dat_length, fd ) ; if ( length != dat_length ) fprintf ( stderr, "slAUSample: File '%s' has premature EOF in data.\n", fname ) ; } fclose ( fd ) ; return SL_TRUE ; } int slSample::loadRawFile ( char *fname ) { delete buffer ; buffer = NULL ; length = 0 ; FILE *fd = fopen ( fname, "rb" ) ; if ( fd == NULL ) { fprintf ( stderr, "slSample: loadRawFile: Cannot open '%s' for reading.\n", fname ) ; return SL_FALSE ; } struct stat stat_buf ; if ( fstat ( fileno ( fd ), & stat_buf ) != 0 ) { fprintf ( stderr, "slSample: loadRawFile: Cannot get status for '%s'.\n", fname ) ; fclose ( fd ) ; return SL_FALSE ; } length = stat_buf . st_size ; if ( length > 0 ) { buffer = new Uchar [ length ] ; length = fread ( buffer, 1, length, fd ) ; } bps = 8 ; stereo = SL_FALSE ; rate = 8000 ; /* Guess */ fclose ( fd ) ; return SL_TRUE ; }