Signal Processing Examples - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

Online Help

All Products    Maple    MapleSim


Signal Processing Examples

The SignalProcessing package features tools for frequency domain analysis, windowing, signal generation and analysis, and more.

Getting Started

While any command in the package can be referred to using the long form, for example, SignalProcessing:-Spectrogram, it is often easier to load the package and then use the short form command names.

restart;

with(SignalProcessing):

Spectrogram, Power Spectrum and Signal Plots

Imaging a Speech Spectrogram

This is a spectrogram, power spectrum and signal plot of a male voice saying MapleSim, recorded at 11 kHz.

maplesim := FileTools:-JoinPath([ kernelopts(datadir), "audio", "maplesim.wav" ]):

Spectrogram(maplesim, colorscheme = ["zgradient", [white, LightSteelBlue, black], markers = [0, .5, 1]], fftsize = 256, includesignal, includepowerspectrum);

Spectrogram of a Violin Note

This is a spectrogram of a violin note played with vibrato, together with the power spectrum and signal plot. Note that the frequency oscillations are at 7 kHz and above,  which is typical of vibrato.

filename := FileTools:-JoinPath([ kernelopts(datadir), "audio", "ViolinThreePosVibrato.wav" ]):

vibrato := AudioTools:-Read(filename):

Spectrogram(vibrato, colorscheme = ["zgradient", [white, LightBlue, red, black], markers = [0, .5, .75, 1]], channel = 1, fftsize = 2^10, includepowerspectrum, includesignal);

Filtering Signals

filename2 := FileTools:-JoinPath([ kernelopts(datadir), "audio", "MapleSimMono11025.wav" ]):

originalSpeech := AudioTools:-Read(filename2):

Plot waveform and power spectrum:

commonPlotOpts2 := labeldirections = [horizontal, vertical], axis = [gridlines = [color = "SteelBlue"]]:

samplingRate := attributes(originalSpeech)[1];

samplingRate11025

(1)

duration := evalf(AudioTools:-Duration(originalSpeech));

duration4.504671202

(2)

p1 := plots:-listplot([seq([i/samplingRate, originalSpeech[i]], i = 1 .. numelems(originalSpeech))], thickness = 0, gridlines, axes = boxed, title = "Original Speech", labels = ["Time (s)", Waveform], commonPlotOpts2):

plots:-display(p1);

fq := FFT(originalSpeech[1 .. 2^15]):

psq := PowerSpectrum(fq):

ps1 := plots:-pointplot([seq([i*samplingRate/2^15, psq[i]], i = 1 .. (1/2)*2^15)], thickness = 0, color = black, gridlines, connect = true, title = "Power Spectrum of Original Speech", labels = ["Frequency (Hz)", Power], view = [100 .. 2000, 0 .. 1.6], axis[1] = [mode = log], commonPlotOpts2):

plots:-display(ps1);

Apply IIR Butterworth or Chebyshev Filter:

fc := 800:

taps := GenerateButterworthTaps(9, fc/samplingRate, 'filtertype' = 'lowpass', 'normalize' = true):

filteredSpeech := InfiniteImpulseResponseFilter(originalSpeech, taps):

View before and after power spectrum and waveform:

FFTfilteredSpeech := FFT(filteredSpeech[1 .. 2^15]):

PSfilteredSpeech := PowerSpectrum(FFTfilteredSpeech):

ps2 := plots:-pointplot([seq([i*samplingRate/2^15, PSfilteredSpeech[i]], i = 1 .. (1/2)*2^15)], thickness = 0, color = black, gridlines, connect = true, title = "Power Spectrum of Filtered Speech", labels = ["Frequency (Hz)", Power], view = [100 .. 2000, 0 .. 1.6], axis[1] = [mode = log], commonPlotOpts2):

plots:-display(Array(<<ps1, ps2>>));

p2 := plots:-listplot([seq([i/samplingRate, filteredSpeech[i]], i = 1 .. numelems(originalSpeech))], thickness = 0, gridlines, axes = boxed, color = black, title = "Filtered Speech", labels = ["Time (s)", Waveform], commonPlotOpts2):

plots:-display(Array(<<p1, p2>>), view = [0 .. duration, -1 .. 1]);

Apply FIR filter

flow := 200:

fhigh := 700:

taps := GenerateFiniteImpulseResponseFilterTaps(50, [flow/samplingRate, fhigh/samplingRate], filtertype = bandpass):

filteredSpeech := FiniteImpulseResponseFilter(originalSpeech, taps):

View before and after power spectrum and waveform:

FFTfilteredSpeech := FFT(filteredSpeech[1 .. 2^15]):

PSfilteredSpeech := PowerSpectrum(FFTfilteredSpeech):

ps2 := plots:-pointplot([seq([i*samplingRate/2^15, PSfilteredSpeech[i]], i = 1 .. (1/2)*2^15)], thickness = 0, color = black, gridlines, connect = true, title = "Power Spectrum of Filtered Speech", labels = ["Frequency (Hz)", Power], view = [100 .. 2000, 0 .. 1.6], axis[1] = [mode = log], commonPlotOpts2):

plots:-display(Array(<<ps1, ps2>>));

p2 := plots:-listplot([seq([i/samplingRate, filteredSpeech[i]], i = 1 .. numelems(originalSpeech))], thickness = 0, gridlines, axes = boxed, color = black, title = "Filtered Speech", labels = ["Time (s)", Waveform], commonPlotOpts2):

plots:-display(Array(<<p1, p2>>), view = [0 .. duration, -1 .. 1]);

Windowing Functions

Windowing functions can also be applied to each window of data used to generate an FFT.

freq := 5:

N := 2^8:

samplingRate := 50:

data := Vector(N, proc (i) options operator, arrow; sin(2*evalf(Pi)*freq*i/samplingRate)+(1/1000000000000)*rand() end proc, datatype = float[8]):

Apply a Blackman Nuttall Window:

dataWindow := BlackmanNuttallWindow(data):

Spectrogram(dataWindow, samplerate = samplingRate, includepowerspectrum, includesignal, fftsize = 128, colorscheme = ["zgradient", [SteelBlue, PaleGreen, red, Black], markers = [0, .5, .8, 1]]);

Visualizations using Explore

It is possible to create interactive applications that use commands from the SignalProcessing package using the Explore command. To see another example of using Explore to create For more examples, see the Filtering Frequency Domain Noise application. The following example dynamically illustrates the effects of a filter parameter value on the resulting modified signal.

Generate a known signal:

A := SignalProcessing:-GenerateJaehne( 512, 4095 ):

PA := plots:-listplot( A, 'title' = "Original Signal" ):

Next, construct a reusable container Array C in order to improve performance of the exploration process by leveraging the in-place computational semantics of the InfiniteImpulseResponseFilter command.

C := Array( 1..512, datatype=float[8] ):

F := proc( frequency, filter )
    uses SignalProcessing;
    local PB,taps;
    taps:=GenerateButterworthTaps( 3, frequency, 'filtertype' = filter );
    InfiniteImpulseResponseFilter( A, taps, 'container' = C );
    PB:=plots:-listplot( C,'title'="Filtered Signal" );
    plots:-display( <<PA;PB>>, 'size'=[700,400] );
end proc:

Explore( F( frequency, filter ),
    parameters=[frequency = 0.05..0.49,
               [filter = ["highpass","lowpass"]]],
    placement=left, animate, loop,
    title="Infinite Impulse Response Filter");

frequency

filter

 

 

See Also

applications/SignalGeneration, applications/SunspotPeriodicity, SignalProcessing, SignalProcessing[FFT], SignalProcessing[FiniteImpulseResponseFilter], SignalProcessing[GenerateButterworthTaps], SignalProcessing[GenerateFiniteImpulseResponseFilterTaps], SignalProcessing[InfiniteImpulseResponseFilter], SignalProcessing[PowerSpectrum]