comparison main/audio/ausave.m @ 0:6b33357c7561 octave-forge

Initial revision
author pkienzle
date Wed, 10 Oct 2001 19:54:49 +0000
parents
children 4cad27e73814
comparison
equal deleted inserted replaced
-1:000000000000 0:6b33357c7561
1 ## Copyright (C) 1999 Paul Kienzle
2 ##
3 ## This program is free software; you can redistribute it and/or modify
4 ## it under the terms of the GNU General Public License as published by
5 ## the Free Software Foundation; either version 2 of the License, or
6 ## (at your option) any later version.
7 ##
8 ## This program is distributed in the hope that it will be useful,
9 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ## GNU General Public License for more details.
12 ##
13 ## You should have received a copy of the GNU General Public License
14 ## along with this program; if not, write to the Free Software
15 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17 ## usage: ausave('filename.ext', x, fs, format)
18 ##
19 ## Writes an audio file with the appropriate header. The extension on
20 ## the filename determines the layout of the header. Currently supports
21 ## .wav and .au layouts. Data is a matrix of audio samples, one row
22 ## time step, one column per channel. Fs defaults to 8000 Hz. Format
23 ## is one of ulaw, alaw, char, short, long, float, double
24 function ausave(path, data, rate, sampleformat)
25
26 if nargin < 2 || nargin>4
27 usage("ausave('filename.ext', x [, fs, sampleformat])");
28 end
29 if nargin < 3, rate = 8000; end
30 if nargin < 4, sampleformat = 'short'; end
31
32 ext = rindex(path, '.');
33 if (ext == 0)
34 usage("ausave('filename.ext', x [, fs, sampleformat])");
35 end
36 ext = tolower(substr(path, ext+1, length(path)-ext));
37
38 [samples, channels] = size(data);
39
40 ## Microsoft .wav format
41 if strcmp(ext,'wav')
42
43 ## Header format obtained from sox/wav.c
44 ## April 15, 1992
45 ## Copyright 1992 Rick Richardson
46 ## Copyright 1991 Lance Norskog And Sundry Contributors
47 ## This source code is freely redistributable and may be used for
48 ## any purpose. This copyright notice must be maintained.
49 ## Lance Norskog And Sundry Contributors are not responsible for
50 ## the consequences of using this software.
51
52 if (strcmp(sampleformat,'uchar'))
53 formatid = 1;
54 samplesize = 1;
55 elseif (strcmp(sampleformat,'short'))
56 formatid = 1;
57 samplesize = 2;
58 elseif (strcmp(sampleformat, 'long'))
59 formatid = 1;
60 samplesize = 4;
61 elseif (strcmp(sampleformat, 'alaw'))
62 formatid = 6;
63 samplesize = 1;
64 elseif (strcmp(sampleformat, 'ulaw'))
65 formatid = 7;
66 samplesize = 1;
67 else
68 error("%s is invalid format for .wav file\n", sampleformat);
69 end
70 datasize = channels*samplesize*samples;
71
72 [file, msg] = fopen(path, 'w');
73 if (file == -1)
74 error("%s: %s", msg, path);
75 end
76
77 ## write the magic header
78 arch = 'ieee-le';
79 fwrite(file, toascii('RIFF'), 'char');
80 fwrite(file, datasize+36, 'long', 0, arch);
81 fwrite(file, toascii('WAVE'), 'char');
82
83 ## write the "fmt " section
84 fwrite(file, toascii('fmt '), 'char');
85 fwrite(file, 16, 'long', 0, arch);
86 fwrite(file, formatid, 'short', 0, arch);
87 fwrite(file, channels, 'short', 0, arch);
88 fwrite(file, rate, 'long', 0, arch);
89 fwrite(file, rate*channels*samplesize, 'long', 0, arch);
90 fwrite(file, channels*samplesize, 'short', 0, arch);
91 fwrite(file, samplesize*8, 'short', 0, arch);
92
93 ## write the "data" section
94 fwrite(file, toascii('data'), 'char');
95 fwrite(file, datasize, 'long', 0, arch);
96
97 ## Sun .au format
98 elseif strcmp(ext, 'au')
99
100 ## Header format obtained from sox/au.c
101 ## September 25, 1991
102 ## Copyright 1991 Guido van Rossum And Sundry Contributors
103 ## This source code is freely redistributable and may be used for
104 ## any purpose. This copyright notice must be maintained.
105 ## Guido van Rossum And Sundry Contributors are not responsible for
106 ## the consequences of using this software.
107
108 if (strcmp(sampleformat, 'ulaw'))
109 formatid = 1;
110 samplesize = 1;
111 elseif (strcmp(sampleformat,'uchar'))
112 formatid = 2;
113 samplesize = 1;
114 elseif (strcmp(sampleformat,'short'))
115 formatid = 3;
116 samplesize = 2;
117 elseif (strcmp(sampleformat, 'long'))
118 formatid = 5;
119 samplesize = 4;
120 elseif (strcmp(sampleformat, 'float'))
121 formatid = 6;
122 samplesize = 4;
123 elseif (strcmp(sampleformat, 'double'))
124 formatid = 7;
125 samplesize = 8;
126 else
127 error("%s is invalid format for .au file\n", sampleformat);
128 end
129 datasize = channels*samplesize*samples;
130
131 [file, msg] = fopen(path, 'w');
132 if (file == -1)
133 error("%s: %s", msg, path);
134 end
135
136 arch = 'ieee-be';
137 fwrite(file, toascii('.snd'), 'char');
138 fwrite(file, 24, 'long', 0, arch);
139 fwrite(file, datasize, 'long', 0, arch);
140 fwrite(file, formatid, 'long', 0, arch);
141 fwrite(file, rate, 'long', 0, arch);
142 fwrite(file, channels, 'long', 0, arch);
143
144 ## Apple/SGI .aiff format
145 elseif strcmp(ext,'aiff')
146
147 ## Header format obtained from sox/aiff.c
148 ## September 25, 1991
149 ## Copyright 1991 Guido van Rossum And Sundry Contributors
150 ## This source code is freely redistributable and may be used for
151 ## any purpose. This copyright notice must be maintained.
152 ## Guido van Rossum And Sundry Contributors are not responsible for
153 ## the consequences of using this software.
154 ##
155 ## IEEE 80-bit float I/O taken from
156 ## ftp://ftp.mathworks.com/pub/contrib/signal/osprey.tar
157 ## David K. Mellinger
158 ## dave@mbari.org
159 ## +1-831-775-1805
160 ## fax -1620
161 ## Monterey Bay Aquarium Research Institute
162 ## 7700 Sandholdt Road
163
164 if (strcmp(sampleformat,'uchar'))
165 samplesize = 1;
166 elseif (strcmp(sampleformat,'short'))
167 samplesize = 2;
168 elseif (strcmp(sampleformat, 'long'))
169 samplesize = 4;
170 else
171 error("%s is invalid format for .aiff file\n", sampleformat);
172 end
173 datasize = channels*samplesize*samples;
174
175 [file, msg] = fopen(path, 'w');
176 if (file == -1)
177 error("%s: %s", msg, path);
178 end
179
180 ## write the magic header
181 arch = 'ieee-be';
182 fwrite(file, toascii('FORM'), 'char');
183 fwrite(file, datasize+46, 'long', 0, arch);
184 fwrite(file, toascii('AIFF'), 'char');
185
186 ## write the "COMM" section
187 fwrite(file, toascii('COMM'), 'char');
188 fwrite(file, 18, 'long', 0, arch);
189 fwrite(file, channels, 'short', 0, arch);
190 fwrite(file, samples, 'long', 0, arch);
191 fwrite(file, 8*samplesize, 'short', 0, arch);
192 fwrite(file, 16414, 'ushort', 0, arch); % sample rate exponent
193 fwrite(file, [rate, 0], 'ulong', 0, arch); % sample rate mantissa
194
195 ## write the "SSND" section
196 fwrite(file, toascii('SSND'), 'char');
197 fwrite(file, datasize+8, 'long', 0, arch); # section length
198 fwrite(file, 0, 'long', 0, arch); # block size
199 fwrite(file, 0, 'long', 0, arch); # offset
200
201 ## file extension unknown
202 else
203 error('ausave(filename.ext,...) understands .wav .au and .aiff only');
204 end
205
206 ## convert samples from range [-1, 1)
207 if strcmp(sampleformat, 'alaw')
208 error("FIXME: ausave needs linear to alaw conversion\n");
209 precision = 'uchar';
210 elseif strcmp(sampleformat, 'ulaw')
211 data = lin2mu(data);
212 precision = 'uchar'
213 elseif strcmp(sampleformat, 'uchar')
214 data = data*128 + 128;
215 precision = 'uchar';
216 elseif strcmp(sampleformat, 'short')
217 data = data*32768;
218 precision = 'short';
219 elseif strcmp(sampleformat, 'long')
220 data = data*2^31;
221 precision = 'long';
222 else
223 precision = sampleformat;
224 end
225 fwrite(file, data', precision, 0, arch);
226 fclose(file);
227
228 endfunction