Reply by Randy Yates May 27, 20072007-05-27
I wrote:

> I'm using octave 2.9.9 on > > [yates@localhost inp]$ uname -a > Linux localhost.localdomain 2.6.20-1.2948.fc6 #1 SMP Fri Apr 27 19:18:54 EDT 2007 x86_64 x86_64 x86_64 GNU/Linux > > and I'm experiencing two problems with wavwrite(): > > 1. The parameter order changed between version 2.9.8 and 2.9.9. This is > not really a problem, but may be noteworthy. > > 2. wavwrite() doesn't seem to be able to create a valid .wav file: > > [yates] octave > >x=2*rand(1,128)-1; > >wavwrite('test.wav',x,64000,16); > >quit > > [yates] play test.wav > sox: Failed reading test.wav: WAVE header not found > > What's up with this?
The problem is caused by bugs in wavwrite.m. Namely, it assumes lengths for the architecture-dependent data types "short" and "ulong". I'm including an updated version that is corrected and seems to work. PS: I believe you have the same problem in ausave() since it gave the exact same error. -- % Randy Yates % "And all that I can do %% Fuquay-Varina, NC % is say I'm sorry, %%% 919-577-9882 % that's the way it goes..." %%%% <yates@ieee.org> % Getting To The Point', *Balance of Power*, ELO http://home.earthlink.net/~yatescr ## Copyright (C) 2005 Michael Zeising ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2, or (at your option) ## any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, write to the Free ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ## 02110-1301, USA. ## -*- texinfo -*- ## @deftypefn {Function File} {} wavwrite(@var{filename}, @var{y}) ## Write @var{y} to the canonical RIFF/WAVE sound file @var{filename}. A sample ## rate of 8000 Hz and 16-bit samples are assumed. Each column of the data ## represents a separate channel. ## ## @deftypefnx {Function File} {} wavwrite(@var{filename}, @var{y}, @var{fs}) ## Set the sample rate to @var{fs} Hz. ## ## @deftypefnx {Function File} {} wavwrite(@var{filename}, @var{y}, @var{fs}, @var{bits}) ## Set the sample rate to @var{fs} Hz and resolution to @var{bits} bits. ## @seealso{wavread} ## @end deftypefn ## Author: Michael Zeising <michael.zeising@stud.uni-erlangen.de> ## Created: 06 December 2005 function wavwrite (filename, y, samples_per_sec, bits_per_sample) BYTEORDER = "ieee-le"; if (nargin < 2 || nargin > 4) usage ("wavwrite (filename, y, samples_per_sec, bits_per_sample)"); endif ## parse arguments if (nargin < 3) warning ("wavwrite: sample rate set to 8000 Hz"); samples_per_sec = 8000; endif if (nargin < 4) warning ("wavwrite: sample resolution set to 16-bit"); bits_per_sample = 16; endif ## determine sample format switch (bits_per_sample) case 8 format = "uint8"; case 16 format = "int16"; case 32 format = "int32"; otherwise error ("wavread: sample resolution not supported"); endswitch ## calculate filesize channels = size(y)(2); n = size(y)(1); ## size of data chunk ck_size = n*channels*(bits_per_sample/8); ## open file for writing binary if (! ischar (filename)) error ("wavwrite: expecting filename to be a character string"); endif [fid, msg] = fopen (filename, "wb"); if (fid < 0) error ("wavwrite: %s", msg) endif ## write RIFF/WAVE header c = 0; c += fwrite (fid, "RIFF", "uchar"); ## file size - 8 c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER); c += fwrite (fid, "WAVEfmt ", "uchar"); ## size of fmt chunk c += fwrite (fid, 16, "uint32", 0, BYTEORDER); ## sample format code (PCM) c += fwrite (fid, 0x0001, "uint16", 0, BYTEORDER); ## channels c += fwrite (fid, channels, "uint16", 0, BYTEORDER); ## sample rate c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER); ## bytes per second bps = samples_per_sec*channels*bits_per_sample/8; c += fwrite (fid, bps, "uint32", 0, BYTEORDER); ## block align c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER); c += fwrite (fid, bits_per_sample, "uint16", 0, BYTEORDER); c += fwrite (fid, "data", "uchar"); c += fwrite (fid, ck_size, "uint32", 0, BYTEORDER); if (c < 25) fclose (fid); error ("wavread: writing to file failed"); endif ## interleave samples yi = reshape (y', n*channels, 1); ## scale samples switch (bits_per_sample) case 8 yi = round (yi*127.5 + 127.5); case 16 yi = floor (yi*32767.5); case 32 yi = floor (yi*2147483647.5); endswitch ## write to file c = fwrite (fid, yi, format, 0, BYTEORDER); fclose (fid); endfunction