Mercurial > forge
changeset 74:cb25ba9294f8 octave-forge
Use closed interval [-1,1] rather than open interval [-1,1) internally
author | pkienzle |
---|---|
date | Tue, 11 Dec 2001 20:26:05 +0000 |
parents | 0add478f2afa |
children | 4d103d333f56 |
files | FIXES/lin2mu.m FIXES/mu2lin.m main/audio/auload.m main/audio/ausave.m |
diffstat | 4 files changed, 58 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/FIXES/lin2mu.m Tue Dec 11 15:13:42 2001 +0000 +++ b/FIXES/lin2mu.m Tue Dec 11 20:26:05 2001 +0000 @@ -31,10 +31,12 @@ ## Created: 17 October 1994 ## Adapted-By: jwe -## Paul Kienzle <pkienzle@kienzle.powernet.co.uk> +## Paul Kienzle <pkienzle@users.sf.net> ## handle [-1,1] input range -## 2001-10-22 Paul Kienzle +## 2001-10-22 Paul Kienzle <pkienzle@users.sf.net> ## * restore Octave's guessing behaviour for precision, but issue warning +## 2001-12-11 Paul Kienzle <pkienzle@users.sf.net> +## * convert function y = lin2mu (x, bit) @@ -59,7 +61,8 @@ ## transform real and 8-bit format to 16-bit if (bit == 0) - x = 32768 .* x; + [-1,1] -> [-32768, 32767] + x = round(32767.5 * x - 0.5); elseif (bit == 8) x = 256 .* x; endif
--- a/FIXES/mu2lin.m Tue Dec 11 15:13:42 2001 +0000 +++ b/FIXES/mu2lin.m Tue Dec 11 20:26:05 2001 +0000 @@ -31,10 +31,12 @@ ## Created: 18 October 1994 ## Adapted-By: jwe -## Paul Kienzle <pkienzle@kienzle.powernet.co.uk> +## Paul Kienzle <pkienzle@users.sf.net> ## handle [-1,1] input range ## 2001-10-23 Paul Kienzle <pkienzle@users.sf.net> ## * default to 8-bit as in octave +## 2001-12-11 Paul Kienzle <pkienzle@users.sf.net> +## * use asymmetric transformation [-32768,32767]->[-1,1] for real function y = mu2lin (x, bit) @@ -74,7 +76,8 @@ ## convert to real or 8-bit if (bit == 0) - y = y/32768; + ## [ -32768, 32767 ] -> [ -1, 1 ] + y = (y+0.5)/32767.5; elseif (bit == 8) ld = max (max (abs (y))); if (ld < 16384) #% && ld > 0)
--- a/main/audio/auload.m Tue Dec 11 15:13:42 2001 +0000 +++ b/main/audio/auload.m Tue Dec 11 20:26:05 2001 +0000 @@ -20,18 +20,27 @@ ## data, one column per channel, one row per time slice. Also returns ## the sample rate and stored format (one of ulaw, alaw, char, short, ## long, float, double). The sample value will be normalized to the -## range [-1,1) regardless of the stored format. This does not do any -## level correction or DC offset correction on the samples. +## range [-1,1] regardless of the stored format. ## ## Example ## [x, fs] = auload(file_in_loadpath("sample.wav")); ## auplot(x,fs); +## +## 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. ## 2001-09-04 Paul Kienzle <pkienzle@users.sf.net> ## * skip unknown blocks in WAVE format. ## 2001-09-05 Paul Kienzle <pkienzle@users.sf.net> ## * 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 <pkienzle@users.sf.net> +## * use closed interval [-1,1] rather than open interval [-1,1) internally function [data, rate, sampleformat] = auload(path) @@ -324,16 +333,19 @@ -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]/32768; + alaw = ([ alaw,-alaw]+0.5)/32767.5; data = alaw(data+1); elseif strcmp(sampleformat, 'ulaw') - data = mu2lin(data, 16)/32768; + data = mu2lin(data, 0); elseif strcmp(sampleformat, 'uchar') - data = data/128 - 1; + ## [ 0, 255 ] -> [ -1, 1 ] + data = data/127.5 - 1; elseif strcmp(sampleformat, 'short') - data = data/32768; + ## [ -32768, 32767 ] -> [ -1, 1 ] + data = (data+0.5)/32767.5; elseif strcmp(sampleformat, 'long') - data = data/2^31; + ## [ -2^31, 2^31-1 ] -> [ -1, 1 ] + data = (data+0.5)/(2^31-0.5); end data = reshape(data, channels, length(data)/channels)';
--- a/main/audio/ausave.m Tue Dec 11 15:13:42 2001 +0000 +++ b/main/audio/ausave.m Tue Dec 11 20:26:05 2001 +0000 @@ -18,12 +18,26 @@ ## ## Writes an audio file with the appropriate header. The extension on ## the filename determines the layout of the header. Currently supports -## .wav and .au layouts. Data is a matrix of audio samples, one row -## time step, one column per channel. Fs defaults to 8000 Hz. Format -## is one of ulaw, alaw, char, short, long, float, double +## .wav and .au layouts. Data is a matrix of audio samples in the +## range [-1,1] (inclusive), one row per time step, one column per +## channel. Fs defaults to 8000 Hz. Format is one of ulaw, alaw, char, +## short, long, float, double +## +## Note that translating the symmetric range [-1,1] into the asymmetric +## range [-2^n,2^n-1] requires a DC offset of -2/2^n. The inverse +## process used by auload 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. + ## 2001-10-23 Paul Kienzle ## * force lin2mu to use [-1:1] regardless of its default +## 2001-12-11 Paul Kienzle <pkienzle@users.sf.net> +## * use closed interval [-1,1] rather than open interval [-1,1) internally +## * rescale data if it exceeds the range + function ausave(path, data, rate, sampleformat) if nargin < 2 || nargin>4 @@ -206,7 +220,14 @@ error('ausave(filename.ext,...) understands .wav .au and .aiff only'); end - ## convert samples from range [-1, 1) + ## Make sure the data fits into the sample range + scale = max(abs(data(:))); + if (scale > 1.0) + warning("ausave: audio data exceeds range [-1,1] --- rescaling"); + data = data / scale; + endif + + ## convert samples from range [-1, 1] if strcmp(sampleformat, 'alaw') error("FIXME: ausave needs linear to alaw conversion\n"); precision = 'uchar'; @@ -214,13 +235,13 @@ data = lin2mu(data, 0); precision = 'uchar' elseif strcmp(sampleformat, 'uchar') - data = data*128 + 128; + data = round((data+1)*127.5); precision = 'uchar'; elseif strcmp(sampleformat, 'short') - data = data*32768; + data = round(data*32767.5 - 0.5); precision = 'short'; elseif strcmp(sampleformat, 'long') - data = data*2^31; + data = round(data*(2^31-0.5) - 0.5); precision = 'long'; else precision = sampleformat;