1
function []=wavwrite(y,Fs,nbits,wavefile)
2
[nargout,nargin] = argn(0)
3
//WAVWRITE Write Microsoft WAVE ("""".wav"""") sound file.
4
// WAVWRITE(Y,WAVEFILE) writes a WAVE file specified by the
5
// string WAVEFILE. The data should be arranged with one channel
6
// per column. Amplitude values outside the range [-1,+1] are
7
// clipped prior to writing.
9
// WAVWRITE(Y,FS,WAVEFILE) specifies the sample rate FS of the data
12
// WAVWRITE(Y,FS,NBITS,WAVEFILE) forces an NBITS-bit file format to
13
// be written, where NBITS<=16.
15
// Supports multi-channel 8- or 16-bit WAVE data.
17
// See also WAVREAD, AUWRITE.
19
// Copyright (c) 1984-98 by The MathWorks, Inc.
20
// $Revision: 5.6 $ $Date: 1997/11/21 23:24:12 $
24
// Get user default preferences:
29
if nargin<2|nargin>4 then
30
error('Incorrect number of input arguments.');
40
// Open file for output:
41
if ~(type(wavefile)==10) then
42
error('wavefile must be a string.');
44
if mtlb_findstr(wavefile,'.')==[] then
45
wavefile = wavefile+'.wav';
47
[fid,%v] = mopen(wavefile,'wb',1)
48
if %v<0 then fid = -1;end
51
error('Can''t open WAVE file for output.');
54
// If input is a vector, force it to be a column:
57
error('Data array must have 1- or 2-dimensions, only.');
59
[samples,channels] = size(y);
62
[samples,channels] = size(y);
65
// Clip data to normalized range [-1,+1]:
66
i = matrix(find(abs(y)>1),1,-1);
69
warning('Data clipped during write to file.');
72
// # bytes per sample to write
73
bytes_per_sample = ceil(nbits/8);
74
total_samples = samples*channels;
75
total_bytes = total_samples*bytes_per_sample;
77
// Determine number of bytes in RIFF chunk
78
// (not including pad bytes, if needed):
79
// ----------------------------------
81
// size 4 bytes (ulong)
84
// size 4 bytes (ulong)
85
// <wave-format> 14 bytes
86
// <format_specific> 2 bytes (PCM)
88
// size 4 bytes (ulong)
89
// <wave-data> N bytes
90
// ----------------------------------
91
riff_cksize = 36+total_bytes;
92
// Don't include 'RIFF' or its size field
94
// Don't include 'fmt ' or its size field
95
data_cksize = total_bytes;
96
// Don't include 'data' or its size field
98
// Determine pad bytes:
99
data_pad = data_cksize-fix(data_cksize./2).*2;
100
riff_cksize = riff_cksize+data_pad;
101
// + fmt_pad, always 0
103
ck= tlist(['ck','fid','Size','ID'])
106
ck('Size')=riff_cksize
116
ck('Size')=fmt_cksize
118
// Write <wave-format>:
119
fmt=tlist(['fmt','wFormatTag','nChannels','nSamplesPerSec','nAvgBytesPerSec','nBlockAlign','nBitsPerSample'])
121
// Data encoding format = PCM
122
fmt('nChannels')=channels
123
// Number of channels
124
fmt('nSamplesPerSec')=Fs
125
// Samples per second
126
fmt('nAvgBytesPerSec')=channels*bytes_per_sample*Fs
128
fmt('nBlockAlign')=channels*bytes_per_sample
130
fmt('nBitsPerSample')=nbits
131
// standard <PCM-format-specific> info
132
status = write_wavefmt(fid,fmt);
136
ck('Size')=data_cksize
139
// Write <wave-data>, and its pad byte if needed:
140
status = write_wavedat(fid,fmt,y);
145
function write_ckinfo(ck,sflg)
146
[nargout,nargin] = argn(0)
147
// WRITE_CKINFO: Writes next RIFF chunk, but not the chunk data.
148
// If optional sflg is set to nonzero, write SUBchunk info instead.
149
// Expects an open FID pointing to first byte of chunk header,
150
// and a chunk structure.
151
// ck.fid, ck.ID, ck.Size, ck.Data
152
if length(ck('ID'))<>4 then error('write_ckinfo: ck has a wrong length');end
153
mput(ascii(ck('ID')),'c',ck('fid'))
156
// Write chunk size (skip if subchunk):
157
mput(ck('Size'),'ui',ck('fid'))
161
function [status]=write_wavedat(fid,fmt,data)
163
// WRITE_WAVEDAT: Write WAVE data chunk
164
// Assumes fid points to the wave-data chunk
165
// Requires <wave-format> structure to be passed.
169
if fmt('wFormatTag')==1 then
171
// Determine # bytes/sample - format requires rounding
172
// to next integer number of bytes:
173
BytesPerSample = ceil(fmt('nBitsPerSample')/8);
174
if BytesPerSample==1 then
177
// Scale data according to bits/samples: [-1,+1] -> [0,255]
178
data = round((data+1)*255/2);
179
elseif BytesPerSample==2 then
182
// Scale data according to bits/samples: [-1,+1] -> [-32768,+32767]
183
data = round((data+1)*65535/2)-32768;
185
error('Cannot write WAVE files with more than 16 bits/sample.');
188
// Write data, one row at a time (one sample from each channel):
189
[samples,channels] = size(data);
190
total_samples = samples*channels;
191
if mput(matrix(data',total_samples,1),dtype,fid)~=0 then
197
// Determine if a pad-byte is appended to data chunk:
198
%v2_1$1 = total_samples*BytesPerSample
199
if %v2_1$1-fix(%v2_1$1./2).*2 then
200
mtlb_fwrite(fid,0,'uchar');
205
// Unknown wave-format for data.
206
error('Unknown data format.');
211
function [status]=write_wavefmt(fid,fmt)
213
// WRITE_WAVEFMT: Write WAVE format chunk.
214
// Assumes fid points to the wave-format subchunk.
215
// Requires chunk structure to be passed, indicating
216
// the length of the chunk.
218
// Create <wave-format> data:
220
mput(fmt('wFormatTag'),'us',fid);
221
mput(fmt('nChannels'),'us',fid);
222
mput(fmt('nSamplesPerSec'),'ui',fid);
223
mput(fmt('nAvgBytesPerSec'),'ui',fid);
224
mput(fmt('nBlockAlign'),'us',fid);
226
// Write format-specific info:
227
if fmt('wFormatTag')==1 then
228
// Write standard <PCM-format-specific> info:
229
mput(fmt('nBitsPerSample'),'us',fid)
231
error('Unknown data format.');