audio-1.1.4/ 0000755 0001750 0001750 00000000000 11212722015 010415 5 ustar sh sh audio-1.1.4/DESCRIPTION 0000644 0001750 0001750 00000000406 11212715074 012132 0 ustar sh sh Name: Audio
Version: 1.1.4
Date: 2009-05-03
Author: Paul Kienzle
Maintainer: Paul Kienzle
Title: Audio
Description: Audio recording, processing and playing tools.
Depends: octave (>= 2.9.7)
Autoload: yes
License: GPL version 2 or later
Url: http://octave.sf.net
audio-1.1.4/inst/ 0000755 0001750 0001750 00000000000 11212722015 011372 5 ustar sh sh audio-1.1.4/inst/auload.m 0000644 0001750 0001750 00000030111 11212715074 013020 0 ustar sh sh ## Copyright (C) 1999 Paul Kienzle
##
## This program 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 of the License, or
## (at your option) any later version.
##
## This program 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 this program; If not, see .
## -*- texinfo -*-
## @deftypefn {Function File} {[@var{x},@var{fs},@var{sampleformat}] =} auload (@var{filename})
##
## Reads an audio waveform from a file given by the string @var{filename}.
## Returns the audio samples in data, one column per channel, one row per
## time slice. Also returns the sample rate and stored format (one of ulaw,
## alaw, char, int16, int24, int32, float, double). The sample value will be
## normalized to the range [-1,1] regardless of the stored format.
##
## @example
## [x, fs] = auload(file_in_loadpath("sample.wav"));
## auplot(x,fs);
## @end example
##
## Note that translating the asymmetric range [-2^n,2^n-1] into the
## symmetric range [-1,1] requires a DC offset of 2/2^n. The inverse
## process used by ausave requires a DC offset of -2/2^n, so loading and
## saving a file will not change the contents. Other applications may
## compensate for the asymmetry in a different way (including previous
## versions of auload/ausave) so you may find small differences in
## calculated DC offsets for the same file.
## @end deftypefn
## 2001-09-04 Paul Kienzle
## * skip unknown blocks in WAVE format.
## 2001-09-05 Paul Kienzle
## * remove debugging stuff from AIFF format.
## * use data length if it is given rather than reading to the end of file.
## 2001-12-11 Paul Kienzle
## * use closed interval [-1,1] rather than open interval [-1,1) internally
function [data, rate, sampleformat] = auload(path)
if (nargin != 1)
usage("[x, fs, sampleformat] = auload('filename.ext')");
end
data = []; # if error then read nothing
rate = 8000;
sampleformat = 'ulaw';
ext = rindex(path, '.');
if (ext == 0)
usage('x = auload(filename.ext)');
end
ext = tolower(substr(path, ext+1, length(path)-ext));
[file, msg] = fopen(path, 'rb');
if (file == -1)
error([ msg, ": ", path]);
end
msg = sprintf('Invalid audio header: %s', path);
## Microsoft .wav format
if strcmp(ext,'wav')
## Header format obtained from sox/wav.c
## April 15, 1992
## Copyright 1992 Rick Richardson
## Copyright 1991 Lance Norskog And Sundry Contributors
## This source code is freely redistributable and may be used for
## any purpose. This copyright notice must be maintained.
## Lance Norskog And Sundry Contributors are not responsible for
## the consequences of using this software.
## check the file magic header bytes
arch = 'ieee-le';
str = char(fread(file, 4, 'char')');
if !strcmp(str, 'RIFF')
error(msg);
end
len = fread(file, 1, 'int32', 0, arch);
str = char(fread(file, 4, 'char')');
if !strcmp(str, 'WAVE')
error(msg);
end
## skip to the "fmt " section, ignoring everything else
while (1)
if feof(file)
error(msg);
end
str = char(fread(file, 4, 'char')');
len = fread(file, 1, 'int32', 0, arch);
if strcmp(str, 'fmt ')
break;
end
fseek(file, len, SEEK_CUR);
end
## read the "fmt " section
formatid = fread(file, 1, 'int16', 0, arch);
channels = fread(file, 1, 'int16', 0, arch);
rate = fread(file, 1, 'int32', 0, arch);
fread(file, 1, 'int32', 0, arch);
fread(file, 1, 'int16', 0, arch);
bits = fread(file, 1, 'int16', 0, arch);
fseek(file, len-16, SEEK_CUR);
## skip to the "data" section, ignoring everything else
while (1)
if feof(file)
error(msg);
end
str = char(fread(file, 4, 'char')');
len = fread(file, 1, 'int32', 0, arch);
if strcmp(str, 'data')
break;
end
fseek(file, len, SEEK_CUR);
end
if (formatid == 1)
if bits == 8
sampleformat = 'uchar';
precision = 'uchar';
samples = len;
elseif bits == 16
sampleformat = 'int16';
precision = 'int16';
samples = len/2;
elseif bits == 24
sampleformat = 'int24';
precision = 'int24';
samples = len/3;
elseif bits == 32
sampleformat = 'int32';
precision = 'int32';
samples = len/4;
else
error(msg);
endif
elseif (formatid == 3)
if bits == 32
sampleformat = 'float';
precision = 'float';
samples = len/4;
elseif bits == 64
sampleformat = 'double';
precision = 'double';
samples = len/8;
else
error(msg);
endif
elseif (formatid == 6 && bits == 8)
sampleformat = 'alaw';
precision = 'uchar';
samples = len;
elseif (formatid == 7 && bits == 8)
sampleformat = 'ulaw';
precision = 'uchar';
samples = len;
else
error(msg);
return;
endif
## Sun .au format
elseif strcmp(ext, 'au')
## Header format obtained from sox/au.c
## September 25, 1991
## Copyright 1991 Guido van Rossum And Sundry Contributors
## This source code is freely redistributable and may be used for
## any purpose. This copyright notice must be maintained.
## Guido van Rossum And Sundry Contributors are not responsible for
## the consequences of using this software.
str = char(fread(file, 4, 'char')');
magic=' ds.';
invmagic='ds. ';
magic(1) = char(0);
invmagic(1) = char(0);
if strcmp(str, 'dns.') || strcmp(str, magic)
arch = 'ieee-le';
elseif strcmp(str, '.snd') || strcmp(str, invmagic)
arch = 'ieee-be';
else
error(msg);
end
header = fread(file, 1, 'int32', 0, 'ieee-be');
len = fread(file, 1, 'int32', 0, 'ieee-be');
formatid = fread(file, 1, 'int32', 0, 'ieee-be');
rate = fread(file, 1, 'int32', 0, 'ieee-be');
channels = fread(file, 1, 'int32', 0, 'ieee-be');
fseek(file, header-24, SEEK_CUR); % skip file comment
## interpret the sample format
if formatid == 1
sampleformat = 'ulaw';
precision = 'uchar';
bits = 12;
samples = len;
elseif formatid == 2
sampleformat = 'uchar';
precision = 'uchar';
bits = 8;
samples = len;
elseif formatid == 3
sampleformat = 'int16';
precision = 'int16';
bits = 16;
samples = len/2;
elseif formatid == 5
sampleformat = 'int32';
precision = 'int32';
bits = 32;
samples = len/4;
elseif formatid == 6
sampleformat = 'float';
precision = 'float';
bits = 32;
samples = len/4;
elseif formatid == 7
sampleformat = 'double';
precision = 'double';
bits = 64;
samples = len/8;
else
error(msg);
end
## Apple/SGI .aiff format
elseif strcmp(ext,'aiff') || strcmp(ext,'aif')
## Header format obtained from sox/aiff.c
## September 25, 1991
## Copyright 1991 Guido van Rossum And Sundry Contributors
## This source code is freely redistributable and may be used for
## any purpose. This copyright notice must be maintained.
## Guido van Rossum And Sundry Contributors are not responsible for
## the consequences of using this software.
##
## IEEE 80-bit float I/O taken from
## ftp://ftp.mathworks.com/pub/contrib/signal/osprey.tar
## David K. Mellinger
## dave@mbari.org
## +1-831-775-1805
## fax -1620
## Monterey Bay Aquarium Research Institute
## 7700 Sandholdt Road
## check the file magic header bytes
arch = 'ieee-be';
str = char(fread(file, 4, 'char')');
if !strcmp(str, 'FORM')
error(msg);
end
len = fread(file, 1, 'int32', 0, arch);
str = char(fread(file, 4, 'char')');
if !strcmp(str, 'AIFF')
error(msg);
end
## skip to the "COMM" section, ignoring everything else
while (1)
if feof(file)
error(msg);
end
str = char(fread(file, 4, 'char')');
len = fread(file, 1, 'int32', 0, arch);
if strcmp(str, 'COMM')
break;
end
fseek(file, len, SEEK_CUR);
end
## read the "COMM" section
channels = fread(file, 1, 'int16', 0, arch);
frames = fread(file, 1, 'int32', 0, arch);
bits = fread(file, 1, 'int16', 0, arch);
exp = fread(file, 1, 'uint16', 0, arch); % read a 10-byte float
mant = fread(file, 2, 'uint32', 0, arch);
mant = mant(1) / 2^31 + mant(2) / 2^63;
if (exp >= 32768), mant = -mant; exp = exp - 32768; end
exp = exp - 16383;
rate = mant * 2^exp;
fseek(file, len-18, SEEK_CUR);
## skip to the "SSND" section, ignoring everything else
while (1)
if feof(file)
error(msg);
end
str = char(fread(file, 4, 'char')');
len = fread(file, 1, 'int32', 0, arch);
if strcmp(str, 'SSND')
break;
end
fseek(file, len, SEEK_CUR);
end
offset = fread(file, 1, 'int32', 0, arch);
fread(file, 1, 'int32', 0, arch);
fseek(file, offset, SEEK_CUR);
if bits == 8
precision = 'uchar';
sampleformat = 'uchar';
samples = len - 8;
elseif bits == 16
precision = 'int16';
sampleformat = 'int16';
samples = (len - 8)/2;
elseif bits == 32
precision = 'int32';
sampleformat = 'int32';
samples = (len - 8)/4;
else
error(msg);
endif
## file extension unknown
else
error('auload(filename.ext) understands .wav .au and .aiff only');
end
## suck in all the samples
if (samples <= 0) samples = Inf; end
if (precision == 'int24')
data = fread(file, 3*samples, 'uint8', 0, arch);
if (arch == 'ieee-le')
data = data(1:3:end) + data(2:3:end) * 2^8 + cast(typecast(cast(data(3:3:end), 'uint8'), 'int8'), 'double') * 2^16;
else
data = data(3:3:end) + data(2:3:end) * 2^8 + cast(typecast(cast(data(1:3:end), 'uint8'), 'int8'), 'double') * 2^16;
endif
else
data = fread(file, samples, precision, 0, arch);
endif
fclose(file);
## convert samples into range [-1, 1)
if strcmp(sampleformat, 'alaw')
alaw = [ \
-5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, \
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, \
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, \
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, \
-22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, \
-30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, \
-11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, \
-15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, \
-344, -328, -376, -360, -280, -264, -312, -296, \
-472, -456, -504, -488, -408, -392, -440, -424, \
-88, -72, -120, -104, -24, -8, -56, -40, \
-216, -200, -248, -232, -152, -136, -184, -168, \
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, \
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, \
-688, -656, -752, -720, -560, -528, -624, -592, \
-944, -912, -1008, -976, -816, -784, -880, -848 ];
alaw = ([ alaw,-alaw]+0.5)/32767.5;
data = alaw(data+1);
elseif strcmp(sampleformat, 'ulaw')
data = mu2lin(data, 0);
elseif strcmp(sampleformat, 'uchar')
## [ 0, 255 ] -> [ -1, 1 ]
data = data/127.5 - 1;
elseif strcmp(sampleformat, 'int16')
## [ -32768, 32767 ] -> [ -1, 1 ]
data = (data+0.5)/32767.5;
elseif strcmp(sampleformat, 'int32')
## [ -2^31, 2^31-1 ] -> [ -1, 1 ]
data = (data+0.5)/(2^31-0.5);
end
data = reshape(data, channels, length(data)/channels)';
endfunction
%!demo
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! auplot(x,fs);
audio-1.1.4/inst/soundsc.m 0000644 0001750 0001750 00000004164 11212715074 013242 0 ustar sh sh ## Copyright (C) 2000 Paul Kienzle
##
## This program 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 of the License, or
## (at your option) any later version.
##
## This program 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 this program; If not, see .
## usage: soundsc(x, fs, limit) or soundsc(x, fs, [ lo, hi ])
##
## soundsc(x)
## Scale the signal so that [min(x), max(x)] -> [-1, 1], then
## play it through the speakers at 8000 Hz sampling rate. The
## signal has one column per channel.
##
## soundsc(x,fs)
## Scale the signal and play it at sampling rate fs.
##
## soundsc(x, fs, limit)
## Scale the signal so that [-|limit|, |limit|] -> [-1, 1], then
## play it at sampling rate fs. If fs is empty, then the default
## 8000 Hz sampling rate is used.
##
## soundsc(x, fs, [ lo, hi ])
## Scale the signal so that [lo, hi] -> [-1, 1], then play it
## at sampling rate fs. If fs is empty, then the default 8000 Hz
## sampling rate is used.
##
## y=soundsc(...)
## return the scaled waveform rather than play it.
##
## See sound for more information.
function data_r = soundsc(data, rate, range)
if nargin < 1 || nargin > 3, usage("soundsc(x, fs, [lo, hi])") endif
if nargin < 2, rate = []; endif
if nargin < 3, range = [min(data(:)), max(data(:))]; endif
if isscalar(range), range = [-abs(range), abs(range)]; endif
data=(data - mean(range))/((range(2)-range(1))/2);
if nargout > 0
data_r = data;
else
sound(data, rate);
endif
endfunction
%!demo
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! soundsc(x,fs);
%!shared y
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! y=soundsc(x);
%!assert (min(y(:)), -1, eps)
%!assert (max(y(:)), 1, eps)
audio-1.1.4/inst/clip.m 0000644 0001750 0001750 00000003642 11212715074 012513 0 ustar sh sh ## Copyright (C) 1999 Paul Kienzle
##
## This program 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 of the License, or
## (at your option) any later version.
##
## This program 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 this program; If not, see .
## Clip values outside the range to the value at the boundary of the
## range.
##
## X = clip(X)
## Clip to range [0, 1]
##
## X = clip(X, hi)
## Clip to range [0, hi]
##
## X = clip(X, [lo, hi])
## Clip to range [lo, hi]
## TODO: more clip modes, such as three level clip(X, [lo, mid, hi]), which
## TODO: sends everything above hi to hi, below lo to lo and between to
## TODO: mid; or infinite peak clipping, which sends everything above mid
## TODO: to hi and below mid to lo.
function x = clip (x, range)
if (nargin == 2)
if (length(range) == 1)
range = [0, range];
end
elseif (nargin == 1)
range = [0, 1];
else
usage("X = clip(X [, range])");
end
try wfi = warning("query", "Octave:fortran-indexing").state;
catch wfi = "off";
end
unwind_protect
x (find (x > range (2))) = range (2);
x (find (x < range (1))) = range (1);
unwind_protect_cleanup
warning(wfi, "Octave:fortran-indexing");
end_unwind_protect
endfunction
%!error clip
%!error clip(1,2,3)
%!assert (clip(pi), 1)
%!assert (clip(-pi), 0)
%!assert (clip([-1.5, 0, 1.5], [-1, 1]), [-1, 0, 1]);
%!assert (clip([-1.5, 0, 1.5]', [-1, 1]'), [-1, 0, 1]');
%!assert (clip([-1.5, 1; 0, 1.5], [-1, 1]), [-1, 1; 0, 1]);
%!assert (isempty(clip([],1)));
audio-1.1.4/inst/auplot.m 0000644 0001750 0001750 00000016154 11212715074 013072 0 ustar sh sh ## Copyright (C) 1999 Paul Kienzle
##
## This program 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 of the License, or
## (at your option) any later version.
##
## This program 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 this program; If not, see .
## -*- texinfo -*-
## @deftypefn {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x})
## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x},@var{fs})
## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{x},@var{fs},@var{offset})
## @deftypefnx {Function File} {[@var{y},@var{t},@var{scale}] = } auplot (@var{...},@var{plotstr})
##
## Plot the waveform data, displaying time on the @var{x} axis. If you are
## plotting a slice from the middle of an array, you may want to specify
## the @var{offset} into the array to retain the appropriate time index. If
## the waveform contains multiple channels, then the data are scaled to
## the range [-1,1] and shifted so that they do not overlap. If a @var{plotstr}
## is given, it is passed as the third argument to the plot command. This
## allows you to set the linestyle easily. @var{fs} defaults to 8000 Hz, and
## @var{offset} defaults to 0 samples.
##
## Instead of plotting directly, you can ask for the returned processed
## vectors. If @var{y} has multiple channels, the plot should have the y-range
## [-1 2*size(y,2)-1]. scale specifies how much the matrix was scaled
## so that each signal would fit in the specified range.
##
## Since speech samples can be very long, we need a way to plot them
## rapidly. For long signals, auplot windows the data and keeps the
## minimum and maximum values in the window. Together, these values
## define the minimal polygon which contains the signal. The number of
## points in the polygon is set with the global variable auplot_points.
## The polygon may be either 'filled' or 'outline', as set by the global
## variable auplot_format. For moderately long data, the window does
## not contain enough points to draw an interesting polygon. In this
## case, simply choosing an arbitrary point from the window looks best.
## The global variable auplot_window sets the size of the window
## required for creating polygons. You can turn off the polygons
## entirely by setting auplot_format to 'sampled'. To turn off fast
## plotting entirely, set auplot_format to 'direct', or set
## auplot_points=1. There is no reason to do this since your screen
## resolution is limited and increasing the number of points plotted
## will not add any information. auplot_format, auplot_points and
## auplot_window may be set in .octaverc. By default auplot_format is
## 'outline', auplot_points=1000 and auplot_window=7.
## @end deftypefn
## 2000-03 Paul Kienzle
## accept either row or column data
## implement fast plotting
## 2000-04 Paul Kienzle
## return signal and time vectors if asked
## TODO: test offset and plotstr
## TODO: convert offset to time range in the form used by au
## TODO: rename to au; if nargout return data within time range
## TODO: otherwise plot the data
function [y_r, t_r, scale_r] = auplot(x, fs, offset, plotstr)
global auplot_points=1000;
global auplot_format="outline";
global auplot_window=7;
if nargin<1 || nargin>4
usage("[y, t, scale] = auplot(x [, fs [, offset [, plotstr]]])");
endif
if nargin<2, fs = 8000; offset=0; plotstr = []; endif
if nargin<3, offset=0; plotstr = []; endif
if nargin<4, plotstr = []; endif
if ischar(fs), plotstr=fs; fs=8000; endif
if ischar(offset), plotstr=offset; offset=0; endif
if isempty(plotstr), plotstr=";;"; endif
if (size(x,1)c*r);
if r==1 || strcmp(auplot_format,"direct")
## full plot
t=[0:samples-1]*1000/fs;
y=x;
elseif r 1
scale = max(abs(y(:)));
if (scale > 0) y=y/scale; endif
for i=1:channels
y(:,i) = y(:,i) + 2*(i-1);
end
else
scale = 1;
end
if nargout >= 1, y_r = y; endif
if nargout >= 2, t_r = t; endif
if nargout >= 3, scale_r = scale; endif
if nargout == 0
if channels > 1
unwind_protect ## protect plot state
ylabel(sprintf('signal scaled by %f', scale));
axis([min(t), max(t), -1, 2*channels-1]);
plot(t,y,plotstr);
unwind_protect_cleanup
axis(); ylabel("");
end_unwind_protect
else
plot(t,y,plotstr);
end
endif
end
%!demo
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! subplot(211); title("single channel"); auplot(x,fs);
%! subplot(212); title("2 channels, x and 3x"); auplot([x, 3*x], fs);
%! oneplot(); title("");
%!demo
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! global auplot_points; pts=auplot_points;
%! global auplot_format; fmt=auplot_format;
%! auplot_points=300;
%! subplot(221); title("filled"); auplot_format="filled"; auplot(x,fs);
%! subplot(223); title("outline"); auplot_format="outline"; auplot(x,fs);
%! auplot_points=900;
%! subplot(222); title("sampled"); auplot_format="sampled"; auplot(x,fs);
%! subplot(224); title("direct"); auplot_format="direct"; auplot(x,fs);
%! auplot_format=fmt; auplot_points=pts; title(""); oneplot();
%!demo
%! [x, fs] = auload(file_in_loadpath("sample.wav"));
%! title("subrange example"); auplot(au(x,fs,300,450),fs)
%! title("");
%!error auplot
%!error auplot(1,2,3,4,5)
audio-1.1.4/inst/sample.wav 0000644 0001750 0001750 00000103764 11212715074 013414 0 ustar sh sh RIFF WAVEfmt "V D dataȇ 1 D P 9 ; 5 Q S R S M N H ? @ L @ > 7 3 9 4 ( * 1 K W /
+ {roCYm uSV$):v{dz/ ] p I
2 n / aF I q!2]+HR2
(d F w | O \ i !% P
&