5565
|
1 ## Copyright (C) 2005 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 2, or (at your option) |
|
8 ## 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, write to the Free |
|
17 ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
18 ## 02110-1301, USA. |
|
19 |
|
20 ## -*- texinfo -*- |
6985
|
21 ## @deftypefn {Function File} {} wavwrite (@var{y}, @var{filename}) |
|
22 ## @deftypefnx {Function File} {} wavwrite (@var{y}, @var{fs}, @var{filename}) |
|
23 ## @deftypefnx {Function File} {} wavwrite (@var{y}, @var{fs}, @var{bits}, @var{filename}) |
|
24 ## Write @var{y} to the canonical RIFF/WAVE sound file @var{filename} |
|
25 ## with sample rate @var{fs} and bits per sample @var{bits}. The |
|
26 ## default sample rate is 8000 Hz with 16-bits per sample. Each column |
|
27 ## of the data represents a separate channel. |
5642
|
28 ## @seealso{wavread} |
5565
|
29 ## @end deftypefn |
|
30 |
|
31 ## Author: Michael Zeising <michael.zeising@stud.uni-erlangen.de> |
|
32 ## Created: 06 December 2005 |
|
33 |
6985
|
34 function wavwrite (y, varargin) |
5567
|
35 |
5565
|
36 BYTEORDER = "ieee-le"; |
6985
|
37 |
|
38 ## For backward compatibility with previous versions of Octave, also |
|
39 ## accept the inputs |
|
40 ## |
|
41 ## wavwrite (filename, y) |
|
42 ## wavwrite (filename, y, fs) |
|
43 ## wavwrite (filename, y, fs, bits) |
|
44 |
5567
|
45 if (nargin < 2 || nargin > 4) |
6046
|
46 print_usage (); |
5565
|
47 endif |
5567
|
48 |
6985
|
49 ## Defaults. |
|
50 samples_per_sec = 8000; |
|
51 bits_per_sample = 16; |
|
52 |
|
53 if (ischar (y)) |
|
54 filename = y; |
|
55 y = varargin{1}; |
|
56 if (nargin > 2) |
|
57 samples_per_sec = varargin{2}; |
|
58 if (nargin > 3) |
|
59 bits_per_sample = varargin{3}; |
|
60 endif |
|
61 endif |
|
62 else |
|
63 filename = varargin{end}; |
|
64 if (nargin > 2) |
|
65 samples_per_sec = varargin{1}; |
|
66 if (nargin > 3) |
|
67 bits_per_sample = varargin{2}; |
|
68 endif |
|
69 endif |
|
70 endif |
|
71 |
|
72 samples_per_sec |
|
73 bits_per_sample |
|
74 |
6304
|
75 ## test arguments |
|
76 if (columns (y) < 1) |
|
77 error ("wavwrite: Y must have at least one column"); |
|
78 endif |
|
79 if (columns (y) > 2^15-1) |
|
80 error ("wavwrite: Y has more than 32767 columns (too many for a WAV-file)"); |
|
81 endif |
|
82 |
5567
|
83 ## determine sample format |
|
84 switch (bits_per_sample) |
5565
|
85 case 8 |
5572
|
86 format = "uint8"; |
5565
|
87 case 16 |
|
88 format = "int16"; |
|
89 case 32 |
|
90 format = "int32"; |
|
91 otherwise |
6304
|
92 error ("wavwrite: sample resolution not supported"); |
5565
|
93 endswitch |
|
94 |
5567
|
95 ## calculate filesize |
6304
|
96 [n, channels] = size(y); |
5567
|
97 |
|
98 ## size of data chunk |
|
99 ck_size = n*channels*(bits_per_sample/8); |
5565
|
100 |
5567
|
101 ## open file for writing binary |
|
102 |
|
103 if (! ischar (filename)) |
|
104 error ("wavwrite: expecting filename to be a character string"); |
|
105 endif |
|
106 |
5565
|
107 [fid, msg] = fopen (filename, "wb"); |
|
108 if (fid < 0) |
|
109 error ("wavwrite: %s", msg) |
|
110 endif |
|
111 |
5567
|
112 ## write RIFF/WAVE header |
5565
|
113 c = 0; |
5567
|
114 c += fwrite (fid, "RIFF", "uchar"); |
|
115 |
|
116 ## file size - 8 |
6304
|
117 c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER); |
5567
|
118 c += fwrite (fid, "WAVEfmt ", "uchar"); |
|
119 |
|
120 ## size of fmt chunk |
6304
|
121 c += fwrite (fid, 16, "uint32", 0, BYTEORDER); |
5567
|
122 |
|
123 ## sample format code (PCM) |
6304
|
124 c += fwrite (fid, 1, "uint16", 0, BYTEORDER); |
5567
|
125 |
|
126 ## channels |
6304
|
127 c += fwrite (fid, channels, "uint16", 0, BYTEORDER); |
5567
|
128 |
|
129 ## sample rate |
6304
|
130 c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER); |
5567
|
131 |
|
132 ## bytes per second |
|
133 bps = samples_per_sec*channels*bits_per_sample/8; |
6304
|
134 c += fwrite (fid, bps, "uint32", 0, BYTEORDER); |
5567
|
135 |
|
136 ## block align |
6304
|
137 c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER); |
5567
|
138 |
6304
|
139 c += fwrite (fid, bits_per_sample, "uint16", 0, BYTEORDER); |
5567
|
140 c += fwrite (fid, "data", "uchar"); |
6304
|
141 c += fwrite (fid, ck_size, "uint32", 0, BYTEORDER); |
5565
|
142 |
|
143 if (c < 25) |
|
144 fclose (fid); |
6304
|
145 error ("wavwrite: writing to file failed"); |
5565
|
146 endif |
|
147 |
5572
|
148 ## interleave samples |
|
149 yi = reshape (y', n*channels, 1); |
|
150 |
5567
|
151 ## scale samples |
|
152 switch (bits_per_sample) |
5565
|
153 case 8 |
6304
|
154 yi = round (yi*128 + 128); |
5572
|
155 case 16 |
6304
|
156 yi = round (yi*32768); |
5572
|
157 case 32 |
6304
|
158 yi = round (yi*2147483648); |
5565
|
159 endswitch |
|
160 |
5567
|
161 ## write to file |
5565
|
162 c = fwrite (fid, yi, format, 0, BYTEORDER); |
|
163 |
|
164 fclose (fid); |
|
165 |
|
166 endfunction |
6304
|
167 |
|
168 %!test |
|
169 %! A = [1:10; 1:10]/10; |
|
170 %! wavwrite("a.wav", A); |
|
171 %! [B, samples_per_sec, bits_per_sample] = wavread("a.wav"); |
|
172 %! assert(A,B, 10^(-4)); |
|
173 %! assert(samples_per_sec, 8000); |
|
174 %! assert(bits_per_sample, 16); |
|
175 % |
|
176 %!test |
|
177 %! A=[1:10; 1:10] / 10; |
|
178 %! wavwrite("a.wav", A, 4000); |
|
179 %! [B, samples_per_sec, bits_per_sample] = wavread("a.wav"); |
|
180 %! assert(A,B, 10^(-4)); |
|
181 %! assert(samples_per_sec, 4000); |
|
182 %! assert(bits_per_sample, 16); |
|
183 % |
|
184 %!test |
|
185 %! A=[1:10; 1:10] / 10; |
|
186 %! wavwrite("a.wav", A, 4000, 8); |
|
187 %! [B, samples_per_sec, bits_per_sample] = wavread("a.wav"); |
|
188 %! assert(A,B, 10^(-2)); |
|
189 %! assert(samples_per_sec, 4000); |
|
190 %! assert(bits_per_sample, 8); |