Mercurial > hg > octave-avbm
comparison scripts/audio/wavread.m @ 5567:80e629357483
[project @ 2005-12-07 06:31:28 by jwe]
author | jwe |
---|---|
date | Wed, 07 Dec 2005 06:31:28 +0000 |
parents | 2f5d0d8a7f13 |
children | c45cf76df06f |
comparison
equal
deleted
inserted
replaced
5566:2f5d0d8a7f13 | 5567:80e629357483 |
---|---|
16 ## along with Octave; see the file COPYING. If not, write to the Free | 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 | 17 ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 ## 02110-1301, USA. | 18 ## 02110-1301, USA. |
19 | 19 |
20 ## -*- texinfo -*- | 20 ## -*- texinfo -*- |
21 ## @deftypefn {Function File} {} @var{y} = wavread(@var{filename}) | 21 ## @deftypefn {Function File} {@var{y}} = wavread (@var{filename}) |
22 ## Load the RIFF/WAVE sound file @var{filename}, returning the samples in vector | 22 ## Load the RIFF/WAVE sound file @var{filename}, and return the samples |
23 ## @var{y}. If the file contains multichannel data, then @var{y} is a matrix with the | 23 ## in vector @var{y}. If the file contains multichannel data, then |
24 ## channels represented as columns. | 24 ## @var{y} is a matrix with the channels represented as columns. |
25 ## | 25 ## |
26 ## @deftypefnx {Function File} {} [@var{y},@var{Fs},@var{bits}] = wavread(@var{filename}) | 26 ## @deftypefnx {Function File} {[@var{y}, @var{Fs}, @var{bits}]} = wavread (@var{filename}) |
27 ## Additionally return the sample rate (@var{fs}) in Hz and the number of bits | 27 ## Additionally return the sample rate (@var{fs}) in Hz and the number of bits |
28 ## per sample (@var{bits}). | 28 ## per sample (@var{bits}). |
29 ## | 29 ## |
30 ## @deftypefnx {Function File} {} [...] = wavread(@var{filename},@var{n}) | 30 ## @deftypefnx {Function File} {[@dots{}]} = wavread (@var{filename}, @var{n}) |
31 ## Read only the first @var{n} samples from each channel. | 31 ## Read only the first @var{n} samples from each channel. |
32 ## | 32 ## |
33 ## @deftypefnx {Function File} {} [...] = wavread(@var{filename},[@var{n1} @var{n2}]) | 33 ## @deftypefnx {Function File} {[@dots{}]} = wavread(@var{filename},[@var{n1} @var{n2}]) |
34 ## Read only samples @var{n1} through @var{n2} from each channel. | 34 ## Read only samples @var{n1} through @var{n2} from each channel. |
35 ## | 35 ## |
36 ## @deftypefnx {Function File} {} [@var{samples} @var{channels}] = wavread(@var{filename},'size') | 36 ## @deftypefnx {Function File} {[@var{samples}, @var{channels}]} = wavread (@var{filename}, "size") |
37 ## Return the number of samples (@var{n}) and channels (@var{ch}) instead of the | 37 ## Return the number of samples (@var{n}) and channels (@var{ch}) |
38 ## audio data. | 38 ## instead of the audio data. |
39 ## | |
40 ## @end deftypefn | 39 ## @end deftypefn |
41 ## | 40 ## |
42 ## @seealso{wavwrite} | 41 ## @seealso{wavwrite} |
43 | 42 |
44 ## Author: Michael Zeising <michael.zeising@stud.uni-erlangen.de> | 43 ## Author: Michael Zeising <michael.zeising@stud.uni-erlangen.de> |
45 ## Created: 06 December 2005 | 44 ## Created: 06 December 2005 |
46 | 45 |
47 function [y, samplesPerSec, bitsPerSample] = wavread (filename, param) | 46 function [y, samples_per_sec, bits_per_sample] = wavread (filename, param) |
47 | |
48 FORMAT_PCM = 0x0001; # PCM (8/16/32 bit) | 48 FORMAT_PCM = 0x0001; # PCM (8/16/32 bit) |
49 FORMAT_IEEE_FLOAT = 0x0003; # IEEE float (32/64 bit) | 49 FORMAT_IEEE_FLOAT = 0x0003; # IEEE float (32/64 bit) |
50 FORMAT_ALAW = 0x0006; # 8-bit ITU-T G.711 A-law (not yet supported) | 50 FORMAT_ALAW = 0x0006; # 8-bit ITU-T G.711 A-law (not yet supported) |
51 FORMAT_MULAW = 0x0007; # 8-bit ITU-T G.711 µ-law (not yet supported) | 51 FORMAT_MULAW = 0x0007; # 8-bit ITU-T G.711 µ-law (not yet supported) |
52 FORMAT_IMA_ADPCM = 0x0011; # IMA/ADPCM 4:1 compression (not yet supported) | 52 FORMAT_IMA_ADPCM = 0x0011; # IMA/ADPCM 4:1 compression (not yet supported) |
53 BYTEORDER = "ieee-le"; | 53 BYTEORDER = "ieee-le"; |
54 | 54 |
55 if (nargin < 1 || nargin > 2) | |
56 usage ("wavread (filename, param)"); | |
57 endif | |
58 | |
55 # open file for binary reading | 59 # open file for binary reading |
60 | |
61 if (! ischar (filename)) | |
62 error ("wavwrite: expecting filename to be a character string"); | |
63 endif | |
64 | |
56 [fid, msg] = fopen (filename, "rb"); | 65 [fid, msg] = fopen (filename, "rb"); |
57 if (fid < 0) | 66 if (fid < 0) |
58 error ("wavread: %s", msg) | 67 error ("wavread: %s", msg) |
59 endif | 68 endif |
60 | 69 |
61 # check for RIFF/WAVE header | 70 ## check for RIFF/WAVE header |
62 ckID = char (fread (fid, 4))'; # chunk ID: "RIFF" | 71 ck_id = char (fread (fid, 4))'; |
63 fseek (fid, 4, SEEK_CUR); | 72 fseek (fid, 4, SEEK_CUR); |
64 WAVEID = char (fread (fid, 4))'; # WAVE ID: "WAVE" | 73 wave_id = char (fread (fid, 4))'; |
65 if ((ckID ~= "RIFF") || (WAVEID ~= "WAVE")) | 74 if (ck_id != "RIFF" || wave_id != "WAVE") |
66 fclose (fid); | 75 fclose (fid); |
67 error ("wavread: file contains no RIFF/WAVE signature"); | 76 error ("wavread: file contains no RIFF/WAVE signature"); |
68 endif | 77 endif |
69 | 78 |
70 # find format chunk within the next 256 (4*64) bytes | 79 ## find format chunk within the next 256 (4*64) bytes |
71 i = 1; | 80 i = 1; |
72 while 1 | 81 while (true) |
73 if (char (fread (fid, 4))' == "fmt ") | 82 if (char (fread (fid, 4))' == "fmt "); |
74 break | 83 break; |
75 endif | 84 endif |
76 if (i++ == 64) | 85 if (i++ == 64) |
77 fclose (fid); | 86 fclose (fid); |
78 error ("wavread: file contains no format chunk") | 87 error ("wavread: file contains no format chunk"); |
79 endif | 88 endif |
80 endwhile | 89 endwhile |
81 | 90 |
82 ckSize = fread (fid, 1, "ulong", 0, BYTEORDER); # format chunk size | 91 ## format chunk size |
83 | 92 ck_size = fread (fid, 1, "ulong", 0, BYTEORDER); |
84 formatTag = fread (fid, 1, "short", 0, BYTEORDER); # sample format code | 93 |
85 if ((formatTag ~= FORMAT_PCM) && (formatTag ~= FORMAT_IEEE_FLOAT)) | 94 ## sample format code |
95 format_tag = fread (fid, 1, "short", 0, BYTEORDER); | |
96 if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT) | |
86 fclose (fid); | 97 fclose (fid); |
87 error ("wavread: sample format %#x is not supported", formatTag) | 98 error ("wavread: sample format %#x is not supported", format_tag); |
88 endif | 99 endif |
89 | 100 |
90 channels = fread (fid, 1, "short", 0, BYTEORDER); # number of interleaved channels | 101 ## number of interleaved channels |
91 samplesPerSec = fread (fid, 1, "ulong", 0, BYTEORDER); # sample rate | 102 channels = fread (fid, 1, "short", 0, BYTEORDER); |
103 | |
104 ## sample rate | |
105 samples_per_sec = fread (fid, 1, "ulong", 0, BYTEORDER); | |
106 | |
107 ## bits per sample | |
92 fseek (fid, 6, SEEK_CUR); | 108 fseek (fid, 6, SEEK_CUR); |
93 bitsPerSample = fread (fid, 1, "short", 0, BYTEORDER); # bits per sample | 109 bits_per_sample = fread (fid, 1, "short", 0, BYTEORDER); |
94 # ignore the rest of the chunk | 110 |
95 fseek (fid, ckSize-16, SEEK_CUR); | 111 ## ignore the rest of the chunk |
96 | 112 fseek (fid, ck_size-16, SEEK_CUR); |
97 # find data chunk | 113 |
114 ## find data chunk | |
98 i = 1; | 115 i = 1; |
99 while 1 | 116 while (true) |
100 if (char (fread(fid, 4))' == "data") | 117 if (char (fread (fid, 4))' == "data") |
101 break | 118 break; |
102 endif | 119 endif |
103 if (i++ == 64) | 120 if (i++ == 64) |
104 fclose (fid); | 121 fclose (fid); |
105 error ("wavread: file contains no data chunk") | 122 error ("wavread: file contains no data chunk"); |
106 endif | 123 endif |
107 end | 124 end |
108 | 125 |
109 ckSize = fread (fid, 1, "ulong", 0, BYTEORDER); # data chunk size | 126 ## data chunk size |
110 | 127 ck_size = fread (fid, 1, "ulong", 0, BYTEORDER); |
111 # determine sample data type | 128 |
112 if (formatTag == FORMAT_PCM) | 129 ## determine sample data type |
113 switch bitsPerSample | 130 if (format_tag == FORMAT_PCM) |
131 switch bits_per_sample | |
114 case 8 | 132 case 8 |
115 format = "int8"; | 133 format = "int8"; |
116 case 16 | 134 case 16 |
117 format = "int16"; | 135 format = "int16"; |
118 case 32 | 136 case 32 |
119 format = "int32"; | 137 format = "int32"; |
120 otherwise | 138 otherwise |
121 fclose (fid); | 139 fclose (fid); |
122 error ("wavread: %d bits sample resolution is not supported with PCM", bitsPerSample); | 140 error ("wavread: %d bits sample resolution is not supported with PCM", bits_per_sample); |
123 endswitch | 141 endswitch |
124 else | 142 else |
125 switch bitsPerSample | 143 switch (bits_per_sample) |
126 case 32 | 144 case 32 |
127 format = "float32"; | 145 format = "float32"; |
128 case 64 | 146 case 64 |
129 format = "float64"; | 147 format = "float64"; |
130 otherwise | 148 otherwise |
131 fclose (fid); | 149 fclose (fid); |
132 error ("wavread: %d bits sample resolution is not supported with IEEE float", bitsPerSample); | 150 error ("wavread: %d bits sample resolution is not supported with IEEE float", bits_per_sample); |
133 endswitch | 151 endswitch |
134 endif | 152 endif |
135 | 153 |
136 # parse arguments | 154 ## parse arguments |
137 if (exist ("param","var") < 1) | 155 if (nargin == 1) |
138 length = inf; | 156 length = inf; |
139 else | 157 else |
140 if (size(param)(2) == 1) # number of samples is given | 158 if (size (param, 2) == 1) |
159 ## number of samples is given | |
141 length = param * channels; | 160 length = param * channels; |
142 elseif (size(param)(2) == 2) # sample range is given | 161 elseif (size (param, 2) == 2) |
143 if fseek(fid, param(1) * channels * (bitsPerSample/8), SEEK_CUR) < 0 | 162 ## sample range is given |
144 warning ("wavread: seeking failed") | 163 if (fseek (fid, param(1) * channels * (bits_per_sample/8), SEEK_CUR) < 0) |
164 warning ("wavread: seeking failed"); | |
145 endif | 165 endif |
146 length = (param(2)-param(1)) * channels; | 166 length = (param(2)-param(1)) * channels; |
147 elseif ((size (param)(2) == 4) && (char(param) == "size")) # size of the file is requested | 167 elseif (size (param, 2) == 4 && char (param) == "size") |
148 fclose (fid); | 168 ## size of the file is requested |
149 y = [ckSize/channels/bitsPerSample/8 channels]; | 169 fclose (fid); |
170 y = [ck_size/channels/bits_per_sample/8, channels]; | |
150 return | 171 return |
151 else | 172 else |
152 fclose (fid); | 173 fclose (fid); |
153 error ("wavread: invalid argument 2"); | 174 error ("wavread: invalid argument 2"); |
154 endif | 175 endif |
155 endif | 176 endif |
156 | 177 |
157 # read samples | 178 ## read samples |
158 [yi, n] = fread (fid, length, format, 0, BYTEORDER); | 179 [yi, n] = fread (fid, length, format, 0, BYTEORDER); |
159 | 180 |
160 fclose (fid); | 181 fclose (fid); |
161 | 182 |
162 if (formatTag == FORMAT_PCM) | 183 if (format_tag == FORMAT_PCM) |
163 # normalize samples | 184 ## normalize samples |
164 switch bitsPerSample | 185 switch (bits_per_sample) |
165 case 8 | 186 case 8 |
166 yi = (yi - 127)/127; # 8-bit samples are unsigned | 187 yi = (yi - 127)/127; # 8-bit samples are unsigned |
167 case {16,32} | 188 case {16, 32} |
168 yi = yi/((2 ** bitsPerSample) / 2 - 1); | 189 yi = yi/((2 ** bits_per_sample) / 2 - 1); |
169 endswitch | 190 endswitch |
170 endif | 191 endif |
171 | 192 |
172 # deinterleave | 193 ## deinterleave |
173 y = []; | 194 ## y = []; |
174 for (i = 1:channels) | 195 ## for i = 1:channels |
175 y = [y yi(i:channels:n)]; | 196 ## y = [y, yi(i:channels:n)]; |
176 endfor | 197 ## endfor |
198 | |
199 nr = numel (yi) / channels; | |
200 y = reshape (yi, channels, nr)'; | |
177 | 201 |
178 endfunction | 202 endfunction |