From octave-sources-request at bevo dot che dot wisc dot edu Tue Nov 2 05:36:28 1999 Subject: Re: Loading WAV files? From: Rafael Laboissiere To: Gerald Gutierrez , help-octave@bevo.che.wisc.edu Cc: octave-sources at bevo dot che dot wisc dot edu, Michael Pruett Date: Tue, 2 Nov 1999 12:36:15 +0100 --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=us-ascii On Tue, Nov 02, 1999 at 01:24:32AM -0800, Gerald Gutierrez wrote: > Is there any way to load WAV (or AU, or any other audio) file into > Octave? I am attaching below two files that I wrote a while ago to interface Michael Pruett's audiofile library with Octave. You should compile them with: mkoctfile loadwav.cc -laudiofile mkoctfile savewav.cc -laudiofile They work fine in my Debian GNU/Linux system with version 0.1.9 of libaudiofile, available at: http://www.68k.org/~michael/audiofile/ This is a very powerful, GPL'd library. I wished to have more time to polish this stuff and contribute them to Octave's core. As usual, the time budget problem reached me. Enjoy, -- Rafael Laboissiere Institut de la Communication Parlee | Email: rafael at icp dot inpg dot fr UPRESS A CNRS 5009 / INPG | Voice: +33 4.76.57.48.49 46, av. Felix Viallet | Fax: +33 4.76.57.47.10 F-38031 Grenoble CEDEX 1 France | URL: http://www.icp.inpg.fr/~rafael --n8g4imXOkfNTN/H1 Content-Type: text/x-c++src Content-Disposition: attachment; filename="loadwav.cc" Content-Transfer-Encoding: 8bit // 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; } --n8g4imXOkfNTN/H1 Content-Type: text/x-c++src Content-Disposition: attachment; filename="savewav.cc" Content-Transfer-Encoding: 8bit // File: savewav.cc // Description: Save Octave matrix in WAV file // Author: Rafael Laboissière // Created on: Sat Jan 23 21:57:00 CET 1999 // Last modified on: Mon Jan 25 23:40:00 CET 1999 // $Id: savewav.cc 1.2 Mon, 25 Jan 1999 23:40:04 +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( savewav, args, nargout, "\ SYNOPSIS:\n\ \n\ savewav(\"filename.wav\", Sample_Rate, Sample_Width, Data )\n\ \n\ DESCRIPTION:\n\ \n\ Saves matrix Data in the M$ WAV file \"filename.wav\". 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 savewav can only write files whose Sample_Width\n\ are 8, 16 or 32 bits. In conformance with the WAV format definition,\n\ when Sample_Width is equal to 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; AFfilesetup outputSetup; int sampleFormat, sampleWidth, channelCount; double sampleRate; octave_value_list retval; // Check if argument is string if ( !args(0).is_string() ) { error("savewav: 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; // Set sample rate if ( ! args(1).is_real_scalar() ) { error("savewav: Sample Rate should be a real scalar.\n"); return retval; } sampleRate = args(1).double_value(); // Set sample width & sample format if ( ! args(2).is_real_scalar() ) { error("savewav: Sample width should be a real scalar.\n"); return retval; } sampleWidth = (int) args(2).double_value(); if ( sampleWidth == 8 ) sampleFormat = AF_SAMPFMT_UNSIGNED; else if ( (sampleWidth == 16) || (sampleWidth == 32) ) sampleFormat = AF_SAMPFMT_TWOSCOMP; else { error("savewav: Sample width should be equal to 8, 16 or 32.\n"); return retval; } // Get data, as well as frame and channel counts Matrix data = args(3).matrix_value(); frameCount = data.rows(); channelCount = data.cols(); // Transfer samples char* buffer = new char[ frameCount * channelCount * (sampleWidth/8) ]; u_int8_t* int8_p = (u_int8_t *) buffer; int16_t* int16_p = (int16_t *) buffer; int32_t* int32_p = (int32_t *) buffer; for (int i = 0; i < frameCount; i++) for (int j = 0; j < channelCount; j++) if ( sampleWidth == 8 ) *(int8_p++) = (u_int8_t) data(i,j); else if ( sampleWidth == 16 ) *(int16_p++) = (int16_t) data(i,j); else *(int32_p++) = (int32_t) data(i,j); // Initialize output file setup outputSetup = afNewFileSetup(); afInitFileFormat(outputSetup, AF_FILE_WAVE); afInitRate(outputSetup, AF_DEFAULT_TRACK, sampleRate); afInitChannels(outputSetup, AF_DEFAULT_TRACK, channelCount); afInitSampleFormat (outputSetup, AF_DEFAULT_TRACK, sampleFormat, sampleWidth); afInitByteOrder (outputSetup, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN); // Open WAV file and check for success file = afOpenFile(filename, "w", outputSetup); if (file == NULL) { error("savewav: Unable to open output file.\n"); return retval; } afFreeFileSetup(outputSetup); // Write samples afWriteFrames(file, AF_DEFAULT_TRACK, buffer, frameCount); afCloseFile(file); return retval; } --n8g4imXOkfNTN/H1--