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