|
|
|
|
Send Page To a Friend

|
M-Pack
1: WAV file processing: MATLAB function reference
|
| Version 1.2 |
Requires MATLAB
6.0 (R12) or later |
|
|
|
Performs
user-specified audio effect(s) on the input WAV file
and saves the results in the output WAV file. The
audio effects are specified via their function handles.
Multichannel WAV files are fully supported. The computations
are performed chunk by-chunk to avoid the need for
large RAM allocations when processing large files.
Optional overall gain(s) can be applied after the
effects (on a per-channel basis if desired).
See
simplegain
in the AudioEffects
directory for an example of how to write an effect
function for use by waveffect.
Supports
both WAVE_FORMAT_PCM and WAVE_FORMAT_EXTENSIBLE multichannel
uncompressed formats and any bit resolution between
2 and 32 inclusive. As an option, bit-depth conversion
(re-quantization) can be applied between the input
and output. Likewise, dither may be optionally applied
before re-quantisation, with a choice from a variety
of standard dithering methods including noise-shaping
with a user-specified custom FIR shaping filter. |
|
| File
format: |
m-file |
|
Editable
source code:
|
yes
|
| Utilises
non-editable functions: |
no |
|
Platform:
|
PC/Windows
|
| Required
MATLAB Toolboxes: |
none
(except core MATLAB) |
| Demo
version limitations: |
p-code
only (non-editable), 30 second WAV file length limit
(then silence) |
|
|
|
| |
waveffect(InputWavFile,OutputWavFile,AudioEffect);
|
| |
waveffect(InputWavFile,OutputWavFile,AudioEffect,OutputFormat); |
| |
waveffect(InputWavFile,OutputWavFile,AudioEffect,... |
| |
OutputFormat,Scaling);
|
| |
waveffect(InputWavFile,OutputWavFile,AudioEffect,... |
| |
OutputFormat,Scaling,ReadChunkSize);
|
| |
waveffect(InputWavFile,OutputWavFile,AudioEffect,... |
| |
OutputFormat,Scaling,ReadChunkSize,WaitbarActivate);
|
|
|
|
| Inputs: |
| InputWavFile |
name of the input WAV file.
|
| OutputWavFile |
name of the output WAV file. Cannot be the same as
the input filename if both reside in the same directory.
|
| AudioEffect
|
must
be either a structure (for a single effect) or a cell
array of structures (for multiple effects). Can also
be a single-element cell (whose element is a structure)
for the single-effect case. The FunctionHandle field
is mandatory in each structure, i.e:
- AudioEffect.FunctionHandle
(single-effect case),
- AudioEffect{i}.FunctionHandle
(multi-effect case)
This
field must contain the handle of the respective audio
effect function to be applied to the data (on a chunk-by-chunk
basis). Each function should be configured to process
the required number of channels as implied by the
column-dimension of the data passed to it (i.e. in
accordance with the number of channels in the WAV
file).
In
the case of multiple effects, the effects are applied
one after the other (to each chunk of data) in the
same order as implied by the ordering of the structures
containing the respective function handles.
In
addition to the mandatory FunctionHandle field, each
structure may contain any other arbitrary user-defined
field(s) for passing parameter data into the effect.Moreover,
at runtime, each structure is augmented by the following
fields which may be used within the effect function
code (shown here is the multi-effect case for the i'th
effect):
- AudioEffect{i}.DataInfo.SampleRate
(in Hz)
- AudioEffect{i}.DataInfo.NumberOfChannels
(column dimension of data passed to function,
could be obtained using the size
command applied to the input data within the effect,
but by passing it here the additional call is saved)
- AudioEffect{i}.DataInfo.ChunkSamples
(row dimension of data passed to function, could
be obtained using the size
command applied to the input data within the
effect, but by passing it here the additional call
is saved)
- AudioEffect{i}.DataInfo.TotalSamples
(total length of file (per channel))
Within
waveffect,
each effect function is called using feval
with three arguments i.e.
feval(AudioEffect{i}.FunctionHandle,InputData,AudioEffect{i})
where
the OutputData
of the (i-1)'th effect is used as the InputData
to the i'th effect, etc. Note that the first input
argument to the effect function is the array of (audio)
data itself, and the second input argument is the
respective (augmented) AudioEffect structure, thereby
enabling any arbitrary parameter data to be sent to
the function. Each effect function must be written
according to this straightforward convention. (See
simplegain
in the AudioEffects
directory for an example of how to write an effect
function.)
|
| OutputFormat |
Optional argument. Must be a structure with fields
described as follows (see also wavout):
- Format
field (i.e. wavformat.Format) should be a string
with value 'pcm' (for WAVE_FORMAT_PCM) or 'ext'
(for WAVE_FORMAT_EXTENSIBLE).
- ChannelMask
field (i.e. wavformat.ChannelMask) should contain
the "ChannelMask" variable (in decimal format) which
prescribes the multichannel speaker allocation for
WAVE_FORMAT_EXTENSIBLE. (See chnmsk2spkrlist
to read more about the ChannelMask property.)
-
ValidBits field (i.e. bits.ValidBits): as described
in Notes below
- ContainerBits
field (i.e. bits.ContainerBits): as described in
Notes below
- DitherMethod
field (i.e. bits.DitherMethod): numerical value
indicating which type of dithering method is applied
before quantisation. Possible values are:
- 0:
no dither [default]
- 1:
rectangular PDF dither, with a peak-to-peak
amplitude of 1*LSB
- 2:
triangular PDF dither, with a peak-to-peak amplitude
of 2*LSB
- 3:
triangular PDF with first-order high-pass noise
shaping
- 4:
triangular PDF with custom FIR noise shaping
filter
- DitherGain
field (i.e. bits.DitherGain): gain applied to amplitude
of dither [default value of 1] i.e. rectangular
PDF dither has amplitude of LSB*DitherGain, and
triangular PDF dither has amplitude of 2*LSB*DitherGain.
- NoiseShapeGain
field: (i.e. bits.NoiseShapeGain): gain applied
to the feedback path in the case where where noise
shaping is activated (i.e. for DitherMethod values
greater than 2) [default value of 1]
- NoiseShapeFIR
field: (i.e. bits.NoiseShapeFIR): vector of coefficients
for custom noise shaping filter (only valid for
DitherMethod = 4). An arbitrary filter of any order
may be specified. Default value is the following
fifth order filter: [2.033 -2.165 1.959 -1.590 0.6149]
taken from ref [2] p 851 (note:
designed for 44.1 kHz).
Notes: ValidBits refers to the number of bits used
in the quantisation of each sample, and ContainerBits
refers to number of bits used to store each sample.
ValidBits can have any value from 2 up to and including
ContainerBits. Usually the value of ContainerBits
is the nearest integer multiple of 8 above the value
of ValidBits, but this does not need to be the case
(e.g. a 2-bit quantised signal can be stored in a
32-bit container, though this would be highly wasteful
in terms of disk space!)
If
omitted, output format retains attributes of the input.
|
| Scaling |
Optional
argument. Must be a structure with fields described
as follows:
- Input
field: (i.e. Scaling.Input): [default 'full']. Describes
the scaling law applied when reading the input WAV
file. Identical to the scale
argument in wavin. See
wavin for full range of
options.
- Output
field: (i.e. Scaling.Output): [default 'full'].
Describes the scaling law applied when writing the
output WAV file. Identical to the scale argument
in wavout. See wavout
for full range of
options.
- Gain
field: (i.e. Scaling.Gain): An overall gain applied
to the signal. Useful for changing the overall signal
strength from input to output. If Scaling.Gain has
the same (or greater) number of elements as the
number of channels, each output channel is scaled
by the corresponding gain value. If Scaling.Gain
is scalar, all channels are scaled by the same amount.
If Scaling.Gain is non-scalar but has number of
elements less than the number of channels, the gain
vector is padded (using its last value) to have
the same number of elements as number of channels,
then each output channel is scaled by the corresponding
gain value.
NOTE: for mono signals, the gain is ineffective
when the output scaling is selected as 'norm' or
'normc', since the normalization (associated with
'norm', 'normc') eliminates the effect of the gain.
Likewise, for multichannel signals, the gain is
ineffective when the output scaling is selected
as 'normc' since the per-channel normalization eliminates
the effect of the gain (though the gains are generally
effective in a relative sense when output scaling
is set to 'norm').
|
| ReadChunkSize |
Optional
argument [default value 65536]. Represents the length
(in samples per channel) of each successive chunk
to be processed. Can have an arbitrary value, but
if too small, computational efficiency will be compromised
since the file I/O operations are relatively slow.
If too large, memory requirements may be excessive.
(Note: the value is overridden if the file length
happens to be smaller!)
|
| WaitbarActivate |
Optional
argument. If the argument is present (even if empty),
the progress is displayed via a waitbar which can
be customized via the following optional fields:
- Handle
field (i.e. WaitbarActivate.Handle) the handle of
an externally-generated waitbar figure. If omitted
a new locally-generated waitbar is created (then
deleted at the end of the function)
- Label
field (i.e. WaitbarActivate.Label) string containing
the label of the waitbar
If
this input argument is omitted, no waitbar will be
used.
|
| Note:
any of the following input arguments: OutputFormat,
Scaling, ReadChunkSize, WaitbarActivate may be substituted
by [ ] to force their respective default value(s).
|
|
| |
|
|
|
Inspect
the source code of this function for a demonstration
of how to use the wavin and
wavout functions in chunk-by-chunk
mode for creating a disk-based WAV processor.
See
the M-Pack 1 overview
for a detailed discussion of the WAV format, quantization,
dithering, and noise-shaping techniques used in this
m-function.
Note
that waveffect
uses wavin
and wavout
for the WAV file I/O and thereby does not preserve
any peripheral header information (e.g. in the '.info'
field) beyond the basic '.fmt' (audio format information).
Ref[1]:
"Enhanced
Audio Formats For Multi-Channel Configurations And
High Bit Resolution" Windows Multimedia Group Microsoft
Corporation, 1999.
Ref[2]:
"Minimally Audible Noise Shaping", Stanley P. Lipshitz,
John Vanderkooy, and Robert A. Wannamaker, J. Audio
Eng. Soc., Vol. 39, No. 11, November 1991.
|
|
|
|
|
|
|
|
|
The
following examples are contained in the m-script file
entitled xmplwaveffect.m
First
set up the desired audio effect via a (MATLAB 6.x)
function handle (in this case, the example simplegain
from the AudioEffects
subdirectory). Determine the function handle from
the string name of the function, and store it in the
mandatory 'FunctionHandle' field of the first input
argument required by waveffect
(make sure that the AudioEffects
subdirectory is on the MATLAB path before proceeding):
|
| |
DesiredEffect.FunctionHandle=str2func('simplegain');
|
| |
| Now
store the desired gain value in the 'Gain' field of
the structure, as required by the simplegain
function (when used in association with waveffect,
see simplegain
sourcecode): |
| |
DesiredEffect.Gain=0.5; |
| |
| Ex.1 |
Apply the simple gain to the file 'wavewarp.wav',
saving the results in 'mywav.wav',
preserving all other WAV format attributes (i.e. all
other arguments omitted): |
| |
| |
waveffect('wavewarp.wav','mywav.wav',DesiredEffect); |
| |
|
| |
Listen
to the "before" and "after" WAV
files (using winplaywav
), noting the gain reduction as expected: |
| |
winplaywav('wavewarp.wav',2);
%'sync' playback |
| |
winplaywav('mywav.wav'); |
| |
| Ex.2 |
Same
as above example but with the waitbar activated by including
the 7th argument to waveffect (even if empty, [] signifies
the presence of the argument, thereby activating the
waitbar): |
| |
| |
waveffect('wavewarp.wav','mywav.wav',DesiredEffect,... |
| |
[],[],[],[]);
|
| |
| Ex.3 |
Same
as above example but with an external waitbar (which
is not deleted at the end of the function) with a custom
label (overriding the default):: |
| |
| |
ExternalWaitbar.Label='Custom
label...';
|
| |
ExternalWaitbar.Handle=waitbar(0,ExternalWaitbar.Label);
|
| |
waveffect('wavewarp.wav','mywav.wav',... |
| |
DesiredEffect,[],[],[],ExternalWaitbar);
|
| |
|
| Ex.4 |
Same
as Ex 2 but with a manually-selected value (of 1024)
for the read chunk size (overriding the default, and,
in doing so, slowing down the process albeit with lower
RAM consumption!): |
| |
| |
waveffect('wavewarp.wav','mywav.wav',...
|
| |
DesiredEffect,[],[],1024,[]);
|
| |
| Ex.5 |
Same
as above example but with a manually-selected output
WAV format (24-bits, overriding the default which preserves
the input): |
| |
| |
OutputFormat.ValidBits=24;
|
| |
waveffect('wavewarp.wav','mywav.wav',...
|
| |
DesiredEffect,OutputFormat,[],1024,[]);
|
| |
|
| Ex.6 |
Same
as above example but with an overall gain of, say, 0.5
applied after the effect: |
| |
Scaling.Gain=0.5;
|
| |
waveffect('wavewarp.wav','mywav.wav',...
|
| |
DesiredEffect,OutputFormat,Scaling,1024,[]);
|
| |
|
| Ex.7 |
Multi-effect
example. Apply the simplegain
effect twice, with gain values of 0.5 and 2, respectively,
thereby recovering the original file ! First make a
cell array with the appropriate multi-effect information: |
| |
| |
MultiEffect{1}.FunctionHandle=str2func('simplegain'); |
| |
MultiEffect{1}.Gain=0.5; |
| |
MultiEffect{2}.FunctionHandle=str2func('simplegain'); |
| |
MultiEffect{2}.Gain=2.0;
|
| |
|
| |
Now
apply both effects (in succession) via a single call
to waveffect: |
| |
waveffect('wavewarp.wav','mywav.wav',MultiEffect,[],[],[],[]); |
| |
|
| |
(Inspection
of the "before" and "after" WAV
files reveals that they are identical to within machine
precision!) |
|

Send Page To a Friend
|
|