//------------------------------------------------------------------- // waveinfo.cpp // // This utility shows format-chunk information in a .wav file. // // compile using: $ make waveinfo // execute using: $ waneinfo // // References: // "Multimedia Programming Interface and Data Specifications," // IBM Corporation and Microsoft Corporation (1991); note also // Microsoft's "New Multimedia Data Types and Data Techniques" // 1994 and "Multiple Channel Audio Data and WAVE files" 2001. // // programmer: ALLAN CRUSE // written on: 17 AUG 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read(), lseek() #include // for strncpy(), strtok(), strcat() int main( int argc, char **argv ) { // check for the required command-line argument if ( argc == 1 ) { fprintf( stderr, "usage: waveinfo \n" ); exit(1); } // attach '.wav' suffix to the filename-argument char filename[ 80 ] = {0}; strncpy( filename, argv[1], 75 ); strtok( filename, ". \n\t" ); strcat( filename, ".wav" ); // open the '.wav' file and obtain its size (in bytes) int fd = open( filename, O_RDONLY ); if ( fd < 0 ) { perror( filename ); exit(1); } int filesize = lseek( fd, 0, SEEK_END ); lseek( fd, 0, SEEK_SET ); printf( "\n\tFile is \'%s\' (%d bytes) \n", filename, filesize ); // read and verify the RIFF chunk char chunk_name[4], chunk_type[4]; int chunk_size; read( fd, &chunk_name, 4 ); read( fd, &chunk_size, 4 ); read( fd, &chunk_type, 4 ); if ( strncmp( chunk_name, "RIFF", 4 ) ) { fprintf( stderr, "not a RIFF file\n" ); exit(1); } if ( strncmp( chunk_type, "WAVE", 4 ) ) { fprintf( stderr, "not a WAVE file\n" ); exit(1); } // find the file's 'format' chunk int morebytes = filesize - 12; while ( morebytes > 8 ) { read( fd, &chunk_name, 4 ); read( fd, &chunk_size, 4 ); morebytes -= 8; if ( strncmp( chunk_name, "fmt ", 4 ) == 0 ) break; lseek( fd, chunk_size, SEEK_CUR ); morebytes -= chunk_size; } if ( morebytes < 16 ) { fprintf( stderr, "format not found\n" ); exit(1); } // read the format-chunk's parameters short formatTag, nChannels, blockAlignmnt, bitsPerSample; int samplesPerSec, avBytesPerSec; read( fd, &formatTag, 2 ); read( fd, &nChannels, 2 ); read( fd, &samplesPerSec, 4 ); read( fd, &avBytesPerSec, 4 ); read( fd, &blockAlignmnt, 2 ); read( fd, &bitsPerSample, 2 ); // display the standard format-chunk parameters printf( "\n\tformatTag=%d ", formatTag ); printf( "\n\tnChannels=%d ", nChannels ); printf( "\n\tsamplesPerSec=%d ", samplesPerSec ); printf( "\n\tavBytesPerSec=%d ", avBytesPerSec ); printf( "\n\tblockAlignmnt=%d ", blockAlignmnt ); printf( "\n\tbitsPerSample=%d ", bitsPerSample ); // display additional format-chunk information (if any) if ( chunk_size > 16 ) printf( "\n\n\tAdditional format information: " ); for (int i = 16; i < chunk_size; i++) { unsigned char inch = 0; if ( ( i % 16 ) == 0 ) printf( "\n\t" ); read( fd, &inch, 1 ); printf( "%02X ", inch ); } printf( "\n\n" ); }