1 ## Copyright (C) 2005-2012 Michael Zeising
3 ## This file is part of Octave.
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>.
20 ## @deftypefn {Function File} {} wavwrite (@var{y}, @var{filename})
21 ## @deftypefnx {Function File} {} wavwrite (@var{y}, @var{Fs}, @var{filename})
22 ## @deftypefnx {Function File} {} wavwrite (@var{y}, @var{Fs}, @var{bps}, @var{filename})
23 ## Write @var{y} to the canonical RIFF/WAVE sound file @var{filename}
24 ## with sample rate @var{Fs} and bits per sample @var{bps}. The
25 ## default sample rate is 8000 Hz with 16-bits per sample. Each column
26 ## of the data represents a separate channel.
30 ## Author: Michael Zeising <michael@michaels-website.de>
31 ## Created: 06 December 2005
33 function wavwrite (y, varargin)
35 BYTEORDER = "ieee-le";
37 if (nargin < 2 || nargin > 4)
42 samples_per_sec = 8000;
45 filename = varargin{end};
47 samples_per_sec = varargin{1};
49 bits_per_sample = varargin{2};
55 error ("wavwrite: Y must have at least one column");
57 if (columns (y) > 0x7FFF)
58 error ("wavwrite: Y has more than 32767 columns (too many for a WAV-file)");
61 ## determine sample format
62 switch (bits_per_sample)
70 error ("wavwrite: sample resolution not supported");
74 [n, channels] = size (y);
77 ck_size = n*channels*(bits_per_sample/8);
79 if (! ischar (filename))
80 error ("wavwrite: expecting FILENAME to be a character string");
83 ## open file for writing binary
84 [fid, msg] = fopen (filename, "wb");
86 error ("wavwrite: %s", msg);
89 ## write RIFF/WAVE header
91 c += fwrite (fid, "RIFF", "uchar");
94 c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER);
95 c += fwrite (fid, "WAVEfmt ", "uchar");
98 c += fwrite (fid, 16, "uint32", 0, BYTEORDER);
100 ## sample format code (PCM)
101 c += fwrite (fid, 1, "uint16", 0, BYTEORDER);
104 c += fwrite (fid, channels, "uint16", 0, BYTEORDER);
107 c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER);
110 byteps = samples_per_sec*channels*bits_per_sample/8;
111 c += fwrite (fid, byteps, "uint32", 0, BYTEORDER);
114 c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER);
116 c += fwrite (fid, bits_per_sample, "uint16", 0, BYTEORDER);
117 c += fwrite (fid, "data", "uchar");
118 c += fwrite (fid, ck_size, "uint32", 0, BYTEORDER);
122 error ("wavwrite: writing to file failed");
125 ## interleave samples
126 yi = reshape (y', n*channels, 1);
129 switch (bits_per_sample)
131 yi = round (yi*128 + 128);
133 yi = round (yi*32768);
135 yi = round (yi*2147483648);
139 c = fwrite (fid, yi, format, 0, BYTEORDER);
147 %! fname = tmpnam ();
150 %! A = [-1:0.1:1; -1:0.1:1];
151 %! wavwrite (A, fname);
152 %! [B, samples_per_sec, bits_per_sample] = wavread (fname);
153 %! assert (A,B, 1/2^15);
154 %! assert (samples_per_sec, 8000);
155 %! assert (bits_per_sample, 16);
159 %! A = [-1:0.1:1; -1:0.1:1];
160 %! wavwrite (A, 4000, fname);
161 %! [B, samples_per_sec, bits_per_sample] = wavread (fname);
162 %! assert (A,B, 1/2^15);
163 %! assert (samples_per_sec, 4000);
164 %! assert (bits_per_sample, 16);
168 %! A = [-1:0.1:1; -1:0.1:1];
169 %! wavwrite (A, 4000, 8, fname);
170 %! [B, samples_per_sec, bits_per_sample] = wavread (fname);
171 %! assert (A,B, 1/128);
172 %! assert (samples_per_sec, 4000);
173 %! assert (bits_per_sample, 8);
178 %! wavwrite (A, fname);
179 %! B = wavread (fname);
181 %! assert (B, [-32768 -32768 0 32767 32767]);