]> Creatis software - CreaPhase.git/blob - octave_packages/m/audio/wavwrite.m
update packages
[CreaPhase.git] / octave_packages / m / audio / wavwrite.m
1 ## Copyright (C) 2005-2012 Michael Zeising
2 ##
3 ## This file is part of Octave.
4 ##
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.
9 ##
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.
14 ##
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/>.
18
19 ## -*- texinfo -*-
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.
27 ## @seealso{wavread}
28 ## @end deftypefn
29
30 ## Author: Michael Zeising <michael@michaels-website.de>
31 ## Created: 06 December 2005
32
33 function wavwrite (y, varargin)
34
35   BYTEORDER = "ieee-le";
36
37   if (nargin < 2 || nargin > 4)
38     print_usage ();
39   endif
40
41   ## Defaults.
42   samples_per_sec = 8000;
43   bits_per_sample = 16;
44
45   filename = varargin{end};
46   if (nargin > 2)
47     samples_per_sec = varargin{1};
48     if (nargin > 3)
49       bits_per_sample = varargin{2};
50     endif
51   endif
52
53   ## test arguments
54   if (columns (y) < 1)
55     error ("wavwrite: Y must have at least one column");
56   endif
57   if (columns (y) > 0x7FFF)
58     error ("wavwrite: Y has more than 32767 columns (too many for a WAV-file)");
59   endif
60
61   ## determine sample format
62   switch (bits_per_sample)
63     case 8
64       format = "uint8";
65     case 16
66       format = "int16";
67     case 32
68       format = "int32";
69     otherwise
70       error ("wavwrite: sample resolution not supported");
71   endswitch
72
73   ## calculate filesize
74   [n, channels] = size (y);
75
76   ## size of data chunk
77   ck_size = n*channels*(bits_per_sample/8);
78
79   if (! ischar (filename))
80     error ("wavwrite: expecting FILENAME to be a character string");
81   endif
82
83   ## open file for writing binary
84   [fid, msg] = fopen (filename, "wb");
85   if (fid < 0)
86     error ("wavwrite: %s", msg);
87   endif
88
89   ## write RIFF/WAVE header
90   c = 0;
91   c += fwrite (fid, "RIFF", "uchar");
92
93   ## file size - 8
94   c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER);
95   c += fwrite (fid, "WAVEfmt ", "uchar");
96
97   ## size of fmt chunk
98   c += fwrite (fid, 16, "uint32", 0, BYTEORDER);
99
100   ## sample format code (PCM)
101   c += fwrite (fid, 1, "uint16", 0, BYTEORDER);
102
103   ## channels
104   c += fwrite (fid, channels, "uint16", 0, BYTEORDER);
105
106   ## sample rate
107   c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER);
108
109   ## bytes per second
110   byteps = samples_per_sec*channels*bits_per_sample/8;
111   c += fwrite (fid, byteps, "uint32", 0, BYTEORDER);
112
113   ## block align
114   c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER);
115
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);
119
120   if (c < 25)
121     fclose (fid);
122     error ("wavwrite: writing to file failed");
123   endif
124
125   ## interleave samples
126   yi = reshape (y', n*channels, 1);
127
128   ## scale samples
129   switch (bits_per_sample)
130     case 8
131       yi = round (yi*128 + 128);
132     case 16
133       yi = round (yi*32768);
134     case 32
135       yi = round (yi*2147483648);
136   endswitch
137
138   ## write to file
139   c = fwrite (fid, yi, format, 0, BYTEORDER);
140
141   fclose (fid);
142
143 endfunction
144
145
146 %!shared fname
147 %! fname = tmpnam ();
148
149 %!test
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);
156 %! unlink (fname);
157 %
158 %!test
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);
165 %! unlink (fname);
166 %
167 %!test
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);
174 %! unlink (fname);
175 %
176 %!test
177 %! A = [-2:2];
178 %! wavwrite (A, fname);
179 %! B = wavread (fname);
180 %! B *= 32768;
181 %! assert (B, [-32768 -32768 0 32767 32767]);
182 %! unlink (fname);
183