|
View:
New views
2 Messages
—
Rating Filter:
Alert me
|
|
|
Update to wavread.m and wavwrite.mHi there,
I've currently noticed that the sample scaling in my WAV functions is wrong and causes asymmetries and DC components (thanks to Denis Sbragion). I've attached an updated version of them and I hope you can include them into the distribution of octave. Thanks in advance! Regards, Michael Zeising ## Copyright (C) 2007 Michael Zeising ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2, or (at your option) ## any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, write to the Free ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ## 02110-1301, USA. ## -*- texinfo -*- ## @deftypefn {Function File} {@var{y} =} wavread (@var{filename}) ## Load the RIFF/WAVE sound file @var{filename}, and return the samples ## in vector @var{y}. If the file contains multichannel data, then ## @var{y} is a matrix with the channels represented as columns. ## ## @deftypefnx {Function File} {[@var{y}, @var{Fs}, @var{bits}] =} wavread (@var{filename}) ## Additionally return the sample rate (@var{fs}) in Hz and the number of bits ## per sample (@var{bits}). ## ## @deftypefnx {Function File} {[@dots{}] =} wavread (@var{filename}, @var{n}) ## Read only the first @var{n} samples from each channel. ## ## @deftypefnx {Function File} {[@dots{}] =} wavread (@var{filename},[@var{n1} @var{n2}]) ## Read only samples @var{n1} through @var{n2} from each channel. ## ## @deftypefnx {Function File} {[@var{samples}, @var{channels}] =} wavread (@var{filename}, "size") ## Return the number of samples (@var{n}) and channels (@var{ch}) ## instead of the audio data. ## @seealso{wavwrite} ## @end deftypefn ## Author: Michael Zeising <michael@...> ## Created: 07 October 2007 function [y, samples_per_sec, bits_per_sample] = wavread (filename, param) FORMAT_PCM = 0x0001; # PCM (8/16/32 bit) FORMAT_IEEE_FLOAT = 0x0003; # IEEE float (32/64 bit) BYTEORDER = "ieee-le"; if (nargin < 1 || nargin > 2) print_usage (); endif if (! ischar (filename)) error ("wavwrite: expecting filename to be a character string"); endif # open file for binary reading [fid, msg] = fopen (filename, "rb"); if (fid < 0) error ("wavread: %s", msg); endif ## check for RIFF/WAVE header ck_id = char (fread (fid, 4))'; fseek (fid, 4, SEEK_CUR); wave_id = char (fread (fid, 4))'; if (ck_id != "RIFF" || wave_id != "WAVE") fclose (fid); error ("wavread: file contains no RIFF/WAVE signature"); endif ## find format chunk within the next 256 (4*64) bytes i = 1; while (true) if (char (fread (fid, 4))' == "fmt "); break; endif if (i++ == 64) fclose (fid); error ("wavread: file contains no format chunk"); endif endwhile ## format chunk size ck_size = fread (fid, 1, "uint32", 0, BYTEORDER); ## sample format code format_tag = fread (fid, 1, "uint16", 0, BYTEORDER); if (format_tag != FORMAT_PCM && format_tag != FORMAT_IEEE_FLOAT) fclose (fid); error ("wavread: sample format %#x is not supported", format_tag); endif ## number of interleaved channels channels = fread (fid, 1, "uint16", 0, BYTEORDER); ## sample rate samples_per_sec = fread (fid, 1, "uint32", 0, BYTEORDER); ## bits per sample fseek (fid, 6, SEEK_CUR); bits_per_sample = fread (fid, 1, "uint16", 0, BYTEORDER); ## ignore the rest of the chunk fseek (fid, ck_size-16, SEEK_CUR); ## find data chunk i = 1; while (true) if (char (fread (fid, 4))' == "data") break; endif if (i++ == 64) fclose (fid); error ("wavread: file contains no data chunk"); endif end ## data chunk size ck_size = fread (fid, 1, "uint32", 0, BYTEORDER); ## determine sample data type if (format_tag == FORMAT_PCM) switch (bits_per_sample) case 8 format = "uint8"; case 16 format = "int16"; case 24 format = "uint8"; case 32 format = "int32"; otherwise fclose (fid); error ("wavread: %d bits sample resolution is not supported with PCM", bits_per_sample); endswitch else switch (bits_per_sample) case 32 format = "float32"; case 64 format = "float64"; otherwise fclose (fid); error ("wavread: %d bits sample resolution is not supported with IEEE float", bits_per_sample); endswitch endif ## parse arguments if (nargin == 1) length = inf; else if (size (param, 2) == 1) ## number of samples is given length = param * channels; elseif (size (param, 2) == 2) ## sample range is given if (fseek (fid, (param(1)-1) * channels * (bits_per_sample/8), SEEK_CUR) < 0) warning ("wavread: seeking failed"); endif length = (param(2)-param(1)+1) * channels; elseif (size (param, 2) == 4 && char (param) == "size") ## size of the file is requested fclose (fid); y = [ck_size/channels/(bits_per_sample/8), channels]; return else fclose (fid); error ("wavread: invalid argument 2"); endif endif ## read samples and close file if (bits_per_sample == 24) length *= 3; endif [yi, n] = fread (fid, length, format, 0, BYTEORDER); fclose (fid); ## check data if (mod (numel (yi), channels) != 0) error ("wavread: data in %s doesn't match the number of channels", filename); endif if (bits_per_sample == 24) yi = reshape (yi, 3, rows(yi)/3)'; yi(yi(:,3) >= 128, 3) -= 256; yi = yi * [1; 256; 65536]; end if (format_tag == FORMAT_PCM) ## normalize samples switch (bits_per_sample) case 8 yi = (yi - 128)/127; case 16 yi /= 32767; case 24 yi /= 8388607; case 32 yi /= 2147483647; endswitch endif ## deinterleave nr = numel (yi) / channels; y = reshape (yi, channels, nr)'; endfunction ## Copyright (C) 2007 Michael Zeising ## ## This file is part of Octave. ## ## Octave is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2, or (at your option) ## any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, write to the Free ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ## 02110-1301, USA. ## -*- texinfo -*- ## @deftypefn {Function File} {} wavwrite (@var{filename}, @var{y}) ## Write @var{y} to the canonical RIFF/WAVE sound file @var{filename}. A sample ## rate of 8000 Hz and 16-bit samples are assumed. Each column of the data ## represents a separate channel. ## ## @deftypefnx {Function File} {} wavwrite (@var{filename}, @var{y}, @var{fs}) ## Set the sample rate to @var{fs} Hz. ## ## @deftypefnx {Function File} {} wavwrite (@var{filename}, @var{y}, @var{fs}, @var{bits}) ## Set the sample rate to @var{fs} Hz and resolution to @var{bits} bits. ## @seealso{wavread} ## @end deftypefn ## Author: Michael Zeising <michael@...> ## Created: 07 October 2007 function wavwrite (filename, y, samples_per_sec, bits_per_sample) BYTEORDER = "ieee-le"; if (nargin < 2 || nargin > 4) print_usage (); endif ## test arguments if (columns (y) < 1) error ("wavwrite: Y must have at least one column"); endif if (columns (y) > 2^15-1) error ("wavwrite: Y has more than 32767 columns (too many for a WAV-file)"); endif ## parse arguments if (nargin < 3) samples_per_sec = 8000; endif if (nargin < 4) bits_per_sample = 16; endif ## determine sample format switch (bits_per_sample) case 8 format = "uint8"; case 16 format = "int16"; case 32 format = "int32"; otherwise error ("wavwrite: sample resolution not supported"); endswitch ## calculate filesize [n, channels] = size(y); ## size of data chunk ck_size = n*channels*(bits_per_sample/8); ## open file for writing binary if (! ischar (filename)) error ("wavwrite: expecting filename to be a character string"); endif [fid, msg] = fopen (filename, "wb"); if (fid < 0) error ("wavwrite: %s", msg) endif ## write RIFF/WAVE header c = 0; c += fwrite (fid, "RIFF", "uchar"); ## file size - 8 c += fwrite (fid, ck_size + 36, "uint32", 0, BYTEORDER); c += fwrite (fid, "WAVEfmt ", "uchar"); ## size of fmt chunk c += fwrite (fid, 16, "uint32", 0, BYTEORDER); ## sample format code (PCM) c += fwrite (fid, 1, "uint16", 0, BYTEORDER); ## channels c += fwrite (fid, channels, "uint16", 0, BYTEORDER); ## sample rate c += fwrite (fid, samples_per_sec, "uint32", 0, BYTEORDER); ## bytes per second bps = samples_per_sec*channels*bits_per_sample/8; c += fwrite (fid, bps, "uint32", 0, BYTEORDER); ## block align c += fwrite (fid, channels*bits_per_sample/8, "uint16", 0, BYTEORDER); c += fwrite (fid, bits_per_sample, "uint16", 0, BYTEORDER); c += fwrite (fid, "data", "uchar"); c += fwrite (fid, ck_size, "uint32", 0, BYTEORDER); if (c < 25) fclose (fid); error ("wavwrite: writing to file failed"); endif ## interleave samples yi = reshape (y', n*channels, 1); ## scale samples switch (bits_per_sample) case 8 yi = round (yi*127 + 128); case 16 yi = round (yi*32767); case 32 yi = round (yi*2147483647); endswitch ## write to file c = fwrite (fid, yi, format, 0, BYTEORDER); fclose (fid); endfunction _______________________________________________ Octave-sources mailing list Octave-sources@... https://www.cae.wisc.edu/mailman/listinfo/octave-sources |
|
|
Update to wavread.m and wavwrite.mOn 7-Oct-2007, Michael Zeising wrote:
| I've currently noticed that the sample scaling in my WAV functions is | wrong and causes asymmetries and DC components (thanks to Denis | Sbragion). I've attached an updated version of them and I hope you can | include them into the distribution of octave. Thanks in advance! Please send context diffs relative to the version you started with to make your modifications. That way, we won't lose any changes that may have been made to the versions of these functions that are already in Octave. Please also use the bug@... list for sending patches to functions that are already a part of Octave. The sources list was originally intended as a place to post add-on functions to Octave and is mostly dead now that Octave Forge exists. Thanks, jwe _______________________________________________ Octave-sources mailing list Octave-sources@... https://www.cae.wisc.edu/mailman/listinfo/octave-sources |
| Free Forum Powered by Nabble | Forum Help |