// 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; }