// File: loadwav.cc // Description: Load WAV file in Octave matrix // Author: Rafael Laboissière // Created on: Sat Jan 23 21:57:00 CET 1999 // Last modified on: Sun Jan 24 23:13:46 CET 1999 // $Id: loadwav.cc 1.3 Sun, 24 Jan 1999 23:14:41 +0100 rafael $ // Copyright (C) 1999 Rafael Laboissiere // This file is free software distributed under the GNU Public License // No warranty. Use it at your own risk. #include #include #include #include DEFUN_DLD( loadwav, args, nargout, "\ SYNOPSIS:\n\ \n\ [Data, Sample_Rate, Sample_Width] = loadwav(\"filename.wav\")\n\ \n\ DESCRIPTION:\n\ \n\ Loads the M$ WAV file \"filename.wav\" into matrix Data. The number\n\ of rows and columns of matrix Data are equal to the number of samples\n\ and the number of channels of the WAV file, respectively. Sample_Rate is\n\ the number of samples per second, and Sample_width the number of bits of\n\ each sample.\n\ \n\ The present version of loadwav can only read files whose Sample_Width\n\ is at most equal to 64. In conformance with the WAV format definition,\n\ when Sample_Width is equal or lesser than 8 the samples are unsigned\n\ (values between 0 and 255). When Sample_width is greater than 8, the\n\ samples are signed." ) { AFfilehandle file; AFframecount frameCount; int sampleFormat, sampleWidth, channelCount; double sampleRate; octave_value_list retval; // Check if argument is string if ( !args(0).is_string() ) { error("loadwav: Arg must be a string!\n"); return retval; } // Convert argument into an ordinary (char *), needed for afOpenFile int filename_len = args(0).string_value().size(); char* filename = new char[filename_len + 1]; args(0).string_value().copy(filename, filename_len); filename[filename_len] = 0; // Open WAV file and check for success file = afOpenFile(filename, "r", AF_NULL_FILESETUP); if (file == NULL) { error("loadwav: Unable to open input file.\n"); return retval; } // Get sample width and test if lesser than 64 afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth); if (sampleWidth > 64 ) { error("loadwav: Cannot cope with sample width greater than 64 bits.\n"); return retval; } // Compute number of bits to shift, in the case where sampleWidth is // not a multiple of 8 int bit_shift = 8*((int) ceil(sampleWidth/8.0)) - sampleWidth; // Get frame and channel counts, and sample rate frameCount = afGetFrameCount(file, AF_DEFAULT_TRACK); channelCount = afGetChannels(file, AF_DEFAULT_TRACK); sampleRate = afGetRate (file, AF_DEFAULT_TRACK); // The following works only in little endian hardware (like i386) // In order to have this function ported to other architectures, // some more elaborated code should be included here. afSetVirtualByteOrder(file, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN); // Create Octave matrix to store the samples Matrix data(frameCount, channelCount); // Read the samples and close the file char* buffer = new char[ frameCount * channelCount * ((int) ceil(sampleWidth/8.0))]; afReadFrames(file, AF_DEFAULT_TRACK, buffer, frameCount); afCloseFile(file); // Now comes the tricky part to get the samples into the Octave // matrix. This is done by checking the sample width and // incrementing the appropriate integer pointer. u_int8_t* int8_p = (u_int8_t *) buffer; int16_t* int16_p = (int16_t *) buffer; int32_t* int32_p = (int32_t *) buffer; int64_t* int64_p = (int64_t *) buffer; for (int i = 0; i < frameCount; i++) for (int j = 0; j < channelCount; j++) data(i,j) = ( sampleWidth <= 8 ) ? *(int8_p++) : ( ( sampleWidth <= 16 ) ? *(int16_p++) : ( ( sampleWidth <= 32 ) ? *(int32_p++) : *(int64_p++) )) >> bit_shift; // Return values (do not bother checking nargout) retval(0) = data; retval(1) = sampleRate; retval(2) = (double) sampleWidth; return retval; }