Sounds Logical
Send Page To a Friend

Table Of Contents Previous Page Next Page

[M-Pack 1 overview]

M-Pack 1: WAV file processing: MATLAB function reference

waveffect
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)
Syntax:
 

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);
Arguments:
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.

 

  wavin     WAV file reading
  wavout WAV file writing
  wavresample WAV file sample rate conversion
  wavpeakfind WAV file peak determination
  wavnormalize WAV file normalization
  winplaywav WAV file playback from within the MATLAB environment
  playwavgui GUI for convenient access to winplaywav
  simplegain example audio effect function for use with waveffect
Examples:

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!)

Top Of Page Table Of Contents Previous Page Next Page

Send Page To a Friend

home - news - products - store - support - site map - company info
© 2007 Sounds Logical. All rights reserved.
Sounds Logical
legal notice - privacy statement