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