00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00024 #include "korebot.h"
00025
00026 #define print_type(t) printf("%c%c%c%c\n" , t[0], t[1], t[2], t[3])
00027
00028
00037 int kb_wav_play(snd_t * snd, char * filename, unsigned soundbufsize)
00038 {
00039 WAV wav;
00040 int rc;
00041 short buf[soundbufsize];
00042
00043
00044 kb_wav_init( &wav );
00045
00046
00047 if ((rc = kb_wav_open( &wav , filename, 1 )) == -1 ) {
00048 return KB_ERROR("kb_wav_play",KB_ERROR_FILEOPEN, filename);
00049 }
00050
00051
00054 if ( wav.fmt.bit_per_sample != 16 && wav.fmt.nb_channel != 2 ) {
00055 return KB_ERROR("kb_wav_play",KB_ERROR_BADSOUND, filename);
00056 }
00057
00058
00059 for (;;) {
00060 rc = kb_wav_read_data( &wav , buf , soundbufsize);
00061 if ( rc <= 0 ) {
00062 if ( rc < 0 )
00063 kb_warning(KB_WARN_SOUNDIO , filename);
00064 break;
00065 }
00066
00067 do {
00068 rc = kb_snd_play( snd , buf , soundbufsize);
00069 if ( rc < 0 ) {
00070 if ( errno != EAGAIN ) {
00071 kb_warning(KB_WARN_SOUNDSAMPLE, errno);
00072 break;
00073 }
00074 continue;
00075 }
00076 }
00077 while (0);
00078 }
00079
00080
00081 kb_wav_close( &wav );
00082
00083 return 0;
00084 }
00085
00086
00091 void kb_wav_init( WAV * wav )
00092 {
00093 wav->file = NULL;
00094 wav->length = 0;
00095 wav->modified = 0;
00096 }
00097
00098
00107 int kb_wav_open( WAV * wav , const char * file , int read )
00108 {
00109 COMMON_CHUNK_HEADER hdr;
00110 int type;
00111
00112 if ((wav->file = fopen( file , read ? "rb" : "wb" )) == NULL) {
00113 return -1;
00114 }
00115
00116 if ( read ) {
00117 for (;;) {
00118 type = kb_wav_read_hdr( wav , &hdr );
00119 switch( type ) {
00120
00121 case 1:
00122 break;
00123
00124
00125 case 2:
00126 memcpy( &wav->fmt , &hdr.chunk.fmt , sizeof(wav->fmt));
00127 break;
00128
00129
00130 case 3:
00131 wav->length = hdr.length;
00132 return (int)hdr.length;
00133 }
00134 }
00135 }
00136 else {
00137 memcpy( &hdr.type , "RIFF" , 4 );
00138 hdr.length = sizeof( RIFF_CHUNK_HEADER) + 8 +
00139 sizeof( FMT_CHUNK_HEADER) + 8 + 8 + wav->length;
00140 memcpy( &hdr.chunk.riff.chunk_content , "WAVE" , 4 );
00141 kb_wav_write_hdr( wav , &hdr );
00142
00143 memcpy( &hdr.type , "fmt " , 4 );
00144 hdr.length = sizeof( FMT_CHUNK_HEADER ) ;
00145 memcpy( &hdr.chunk.fmt , &wav->fmt , sizeof( FMT_CHUNK_HEADER ));
00146 kb_wav_write_hdr( wav , &hdr );
00147
00148 memcpy( &hdr.type , "data" , 4 );
00149 hdr.length = wav->length;
00150 kb_wav_write_hdr( wav , &hdr );
00151 wav->modified = 0;
00152 }
00153
00154 return 0;
00155 }
00156
00157
00161 void kb_wav_close( WAV * wav )
00162 {
00163 COMMON_CHUNK_HEADER hdr;
00164
00165 if ( wav->modified ) {
00166 rewind( wav->file );
00167 memcpy( &hdr.type , "RIFF" , 4 );
00168 hdr.length = sizeof( RIFF_CHUNK_HEADER) +
00169 sizeof( FMT_CHUNK_HEADER) + 8 + 8 + wav->length;
00170 memcpy( &hdr.chunk.riff.chunk_content , "WAVE" , 4 );
00171 kb_wav_write_hdr( wav , &hdr );
00172
00173 memcpy( &hdr.type , "fmt " , 4 );
00174 hdr.length = sizeof( FMT_CHUNK_HEADER ) ;
00175 memcpy( &hdr.chunk.fmt , &wav->fmt , sizeof( FMT_CHUNK_HEADER ));
00176 kb_wav_write_hdr( wav , &hdr );
00177
00178 memcpy( &hdr.type , "data" , 4 );
00179 hdr.length = wav->length;
00180 kb_wav_write_hdr( wav , &hdr );
00181 wav->modified = 0;
00182 }
00183
00184 fclose(wav->file);
00185 wav->file = NULL;
00186 }
00187
00188
00197 int kb_wav_read_data( WAV * wav ,
00198 void * buf , unsigned int size )
00199 {
00200 int n;
00201
00202 n=fread( buf , sizeof(unsigned char) , size , wav->file );
00203 if ( n>0 ) {
00204 #if BYTE_ORDER == BIG_ENDIAN
00205 unsigned int pos;
00206 unsigned int incr;
00207 unsigned int nsample;
00208 unsigned short *p16;
00209 unsigned long *p32;
00210
00211 incr = wav->fmt.byte_per_sample;
00212 nsample = size / incr;
00213 p16 = (unsigned short *)buf;
00214 p32 = (unsigned long *)buf;
00215 for (pos=0; pos<nsample; pos++) {
00216 switch(incr) {
00217 case 2:
00218 p16[pos] = SWAP_WORD(p16[pos]);
00219 break;
00220
00221 case 4:
00222 p32[pos] = SWAP_LONG(p32[pos]);
00223 break;
00224 }
00225 }
00226 #endif
00227 }
00228 return n;
00229 }
00230
00231
00238 int kb_wav_write_data( WAV * wav ,
00239 void * buf , unsigned int len )
00240 {
00241 int n;
00242
00243 #if BYTE_ORDER == BIG_ENDIAN
00244 unsigned int pos;
00245 unsigned int incr;
00246 unsigned int nsample;
00247 unsigned short * p16;
00248 unsigned long *p32;
00249
00250 incr = wav->fmt.byte_per_sample;
00251 nsample = len / incr;
00252 p16 = (unsigned short *)buf;
00253 p32 = (unsigned long *)buf;
00254
00255 for (pos=0; pos<nsample; pos++) {
00256 switch(incr) {
00257 case 2:
00258 p16[pos] = SWAP_WORD(p16[pos]);
00259 break;
00260
00261 case 4:
00262 p32[pos] = SWAP_LONG(p32[pos]);
00263 break;
00264 }
00265 }
00266 #endif
00267 n=fwrite( buf , sizeof(unsigned char) , len , wav->file );
00268 if ( n > 0 ) {
00269 wav->length += n;
00270 wav->modified = 1;
00271 }
00272
00273 return n;
00274 }
00275
00276
00277
00281 void kb_wav_set_format( WAV * wav ,
00282 unsigned short format ,
00283 unsigned short nb_channel ,
00284 unsigned long sample_rate ,
00285 unsigned short bit_per_sample )
00286 {
00287 unsigned long byte_per_sec;
00288 unsigned short byte_per_sample;
00289
00290 wav->fmt.format = format;
00291 wav->fmt.nb_channel = nb_channel;
00292 wav->fmt.sample_rate = sample_rate;
00293 wav->fmt.bit_per_sample = bit_per_sample;
00294
00295 byte_per_sample = ( bit_per_sample / 8 );
00296 byte_per_sec = ( nb_channel * byte_per_sample * sample_rate );
00297
00298 wav->fmt.byte_per_sample = byte_per_sample;
00299 wav->fmt.byte_per_sec = byte_per_sec;
00300 wav->modified = 1;
00301 }
00302
00303
00306 int kb_wav_read_hdr( WAV * wav , COMMON_CHUNK_HEADER * hdr )
00307 {
00308 fread( (void *)hdr , 8 , 1 , wav->file );
00309
00310 if ( memcmp( hdr->type , "RIFF" , 4 )==0 ||
00311 memcmp( hdr->type , "riff" , 4 )==0) {
00312
00313 fread( (void *)&hdr->chunk.riff , sizeof(RIFF_CHUNK_HEADER) , 1 ,
00314 wav->file );
00315
00316 #if BYTE_ORDER == BIG_ENDIAN
00317 hdr->length = SWAP_LONG(hdr->length);
00318 #endif
00319 return 1;
00320 }
00321
00322 if ( memcmp( hdr->type , "FMT " , 4 )==0 ||
00323 memcmp( hdr->type , "fmt " , 4 )==0) {
00324 fread( (void *)&hdr->chunk.fmt , sizeof(FMT_CHUNK_HEADER) , 1 ,
00325 wav->file );
00326
00327 #if BYTE_ORDER == BIG_ENDIAN
00328 hdr->length =
00329 SWAP_LONG(hdr->length);
00330 hdr->chunk.fmt.format =
00331 SWAP_WORD(hdr->chunk.fmt.format);
00332 hdr->chunk.fmt.nb_channel =
00333 SWAP_WORD(hdr->chunk.fmt.nb_channel);
00334 hdr->chunk.fmt.sample_rate =
00335 SWAP_LONG(hdr->chunk.fmt.sample_rate);
00336 hdr->chunk.fmt.byte_per_sec =
00337 SWAP_LONG(hdr->chunk.fmt.byte_per_sec);
00338 hdr->chunk.fmt.byte_per_sample =
00339 SWAP_WORD(hdr->chunk.fmt.byte_per_sample);
00340 hdr->chunk.fmt.bit_per_sample =
00341 SWAP_WORD(hdr->chunk.fmt.bit_per_sample);
00342 #endif
00343 return 2;
00344 }
00345
00346 if ( memcmp( hdr->type , "DATA" , 4 )==0 ||
00347 memcmp( hdr->type , "data" , 4 )==0) {
00348 #if BYTE_ORDER == BIG_ENDIAN
00349 hdr->length = SWAP_LONG(hdr->length);
00350 #endif
00351 return 3;
00352 }
00353
00354 return -1;
00355 }
00356
00357
00360 int kb_wav_write_hdr( WAV * wav , COMMON_CHUNK_HEADER * hdr )
00361 {
00362 unsigned int hdrlen=8;
00363 if ( memcmp( hdr->type , "RIFF" , 4 ) == 0 ||
00364 memcmp( hdr->type , "riff" , 4 ) == 0 ) {
00365 #if BYTE_ORDER == BIG_ENDIAN
00366 hdr->length = SWAP_LONG(hdr->length);
00367 #endif
00368 hdrlen += sizeof(RIFF_CHUNK_HEADER);
00369 }
00370 else if ( memcmp( hdr->type , "FMT " , 4 ) == 0 ||
00371 memcmp( hdr->type , "fmt " , 4 ) == 0 ) {
00372 #if BYTE_ORDER == BIG_ENDIAN
00373 hdr->length =
00374 SWAP_LONG( hdr->length );
00375
00376 hdr->chunk.fmt.format =
00377 SWAP_WORD( hdr->chunk.fmt.format );
00378
00379 hdr->chunk.fmt.nb_channel =
00380 SWAP_WORD( hdr->chunk.fmt.nb_channel );
00381
00382 hdr->chunk.fmt.sample_rate =
00383 SWAP_LONG( hdr->chunk.fmt.sample_rate );
00384
00385 hdr->chunk.fmt.byte_per_sec =
00386 SWAP_LONG( hdr->chunk.fmt.byte_per_sec );
00387
00388 hdr->chunk.fmt.byte_per_sample =
00389 SWAP_WORD( hdr->chunk.fmt.byte_per_sample );
00390
00391 hdr->chunk.fmt.bit_per_sample =
00392 SWAP_WORD( hdr->chunk.fmt.bit_per_sample );
00393 #endif
00394 hdrlen += sizeof(FMT_CHUNK_HEADER);
00395 }
00396 else if ( memcmp( hdr->type , "DATA" , 4 ) == 0 ||
00397 memcmp( hdr->type , "data" , 4 ) == 0 ) {
00398 #if BYTE_ORDER == BIG_ENDIAN
00399 hdr->length = SWAP_LONG( hdr->length );
00400 #endif
00401 }
00402 return fwrite( (void *)hdr , hdrlen , 1 , wav->file );
00403 }
00404
00405
00406
00407
00411 void kb_wav_dump_format( WAV * wav )
00412 {
00413 printf("%s\n" , (wav->fmt.format==1) ? "mono" : "stereo" );
00414 printf("%u channel(s)\n", wav->fmt.nb_channel);
00415 printf("%lu Hz sample rate \n" , wav->fmt.sample_rate);
00416 printf("%lu byte per second\n", wav->fmt.byte_per_sec);
00417 printf("%u byte per sample\n" , wav->fmt.byte_per_sample);
00418 printf("%u bit per sample\n", wav->fmt.bit_per_sample);
00419 }