The audiomath.Signal sub-module
This semi-independent submodule provides various basic
signal-processing tools that can be used with or without
the audiomath.Sound container.
- audiomath.Signal.ApplyWindow(s, func=<function Hann>, axis=0, **kwargs)
If
sis anumpy.ndarray, return a windowed copy of the array. Ifsis anaudiomath.Soundobject (for example, if this is being used a method of that class), then its internal arrays.ywill be replaced by a windowed copy.Windowing means multiplication by the specified window function, along the specified time
axis.funcshould take a single positional argument: length in samples. Additional**kwargs, if any, are passed through. Suitable examples includenumpy.blackman,numpy.kaiser, and friends.
- audiomath.Signal.Click(milliseconds, positivePulseWidth=0.5, negativePulseWidth='symmetric')
A signal function that can be passed as the
waveformargument toGenerateWaveform, to generate periodic clicks. Each click is a positive pulse optionally followed by a negative pulse. IfnegativePulseWidthisNoneor the string'symmetric', then the width of the negative pulse is made the same aspositivePulseWidth. Otherwise, input arguments are all expressed in milliseconds.
- audiomath.Signal.GenerateWaveform(container=None, freq_hz=1.0, phase_rad=None, phase_deg=None, amplitude=1.0, dc=0.0, samplingfreq_hz=None, duration_msec=None, duration_samples=None, axis=None, waveform=<ufunc 'cos'>, waveform_domain='auto', **kwargs)
Create a signal (or multiple signals, if the input arguments are arrays) which is a function of time (time being defined along the specified
axis).If this is being used as a method of an
audiomath.Soundinstance, then thecontainerargument is automatically set to that instance. Otherwise (if used as a global function), thecontainerargument is optional—if supplied, it should be aaudiomath.Soundobject. With acontainer, theaxisargument is set to 0, and the container object’s sampling frequency number of channels and duration (if non-zero) are used as fallback values in case these are not specified elsewhere. The resulting signal is put intocontainer.yand a reference to thecontaineris returned.Default phase is 0, but may be changed by either
phase_degorphase_rad(or both, as long as the values are consistent).Default duration is 1000 msec, but may be changed by either
duration_samplesorduration_msec(or both, as long as the values are consistent).If
duration_samplesis specified andsamplingfreq_hzis not, then the sampling frequency is chosen such that the duration is 1 second—so thenfreq_hzcan be interpreted as cycles per signal.The default
waveformfunction isnumpy.coswhich means that amplitude, phase and frequency arguments can be taken straight from the kind of dictionary returned byfft2ap()for an accurate reconstruction. Awaveformfunction is assumed by default to take an input expressed in radians, unless the first argument in its signature is namedcycles,samples,secondsormilliseconds, in which case the input argument is adjusted accordingly to achieve the named units. (To specify the units explicitly as one of these options, pass one of these words as thewaveform_domainargument.)In this module,
SineWave(),SquareWave(),TriangleWave()andSawtoothWave()are all functions of cycles (i.e. the product of time and frequency), whereasClick()is a function of milliseconds. Any of these can be passed as thewaveformargument.
- audiomath.Signal.Hilbert(x, N=None, axis=0, band=(), samplingfreq_hz=None, return_dict=False)
Compute the analytic signal, just like
scipy.signal.hilbertbut with the differences that (a) the computation can be performed along any axis and (b) a limited band of the signal may be considered. Thebandargument can be a two-, three- or four-element tuple suitable for passing toShoulder(), specifying the edges of the passband (expressed in Hz ifsamplingfreq_hzis explicitly supplied, or relative to Nyquist if not).If
return_dictis True, do not return just the complex analytic signal but rather a dict containing its amplitude, phase, and unwrapped phase difference.
- audiomath.Signal.InverseSpectrum(ap, real=True)
Inverse of
Spectrum(). Takes thedictoutput ofSpectrum()(or of the underlyingfft2ap()) and runsap2fft()followed byifft()on it to return a signal. Ifrealis true, which it is by default, discard the imaginary part of the result.
- audiomath.Signal.ModulateAmplitude(s, freq_hz=1.0, phase_rad=None, phase_deg=None, amplitude=0.5, dc=0.5, samplingfreq_hz=None, duration_msec=None, duration_samples=None, axis=None, waveform=<ufunc 'sin'>, **kwargs)
If
sis anumpy.ndarray, return a modulated copy of the array. Ifsis anaudiomath.Soundobject (for example, if this is being used a method of that class), then its internal arrays.ywill be replaced by a modulated copy.Modulation means multiplication by the specified
waveform, along the specified timeaxis.Default phase is such that amplitude is 0 at time 0, which corresponds to phase_deg=-90 if
waveformfollows sine phase (remember: by default the modulator is a raised waveform, becausedc=0.5by default). To change phase, specify eitherphase_radorphase_deg.Uses
GenerateWaveform()
- audiomath.Signal.Noise(cycles, distribution='uniform', **kwargs)
This function can be passed as the
waveformargument toGenerateWaveform. Thedistributionargument should be a function, or the name of a function withinnumpy.random, that takes asizekeyword argument dictating the shape of its output array. Additional**kwargsare passed through to the function.If the function is
numpy.random.uniform, then thelowargument is set to -1.0 by default instead of the usual 0.0.If the function is
numpy.random.normal, then thescaleargument is set to 0.2 by default instead of the usual 1.0.
- audiomath.Signal.PlotSignal(x, samplingfreq_hz=None, axis=None, axes=None, **kwargs)
Plot
x(an array with time running along the specifiedaxis, or anaudiomath.Soundinstance) against the appropriateTimebase().
- audiomath.Signal.PlotSpectrum(x, samplingfreq_hz=None, axis=None, window_sec=None, psd=True, dB=False, baseValue=None, axes=None, **kwargs)
Input argument
xmay be anumpy.arrayoraudiomath.Sound, in which caseSpectrum()will be called on it. Or it may be thedictoutput of a previousSpectrum()orfft2ap()call.If you supply an array or
Soundinstance, then you also have the option of plotting a Welch averaged short-time spectrum by specifying the length of the window in seconds aswindow_sec.
- audiomath.Signal.Reconstruct(ap, **kwargs)
Check the accuracy of
fft2ap()andGenerateWaveform()by reconstructing a signal as the sum of cosine waves with amplitudes and phases specified in dictap, which is of the form output byfft2ap()and hence also bySpectrum().NB: this is for small toy/debugging examples only. Its space complexity is number-of-samples squared. For real applications, use
InverseSpectrum().
- audiomath.Signal.ReweightSpectrum(s, func, *pargs, **kwargs)
Brutally filter the sound
sby transforming into the Fourier domain, weighting the amplitude spectrum, and transforming back. The filtering is non-causal and (TODO) will have wrap-around artifacts whereby the two ends of the signal may bleed into each other, so use with caution—it is most suitable for noise or for periodic signals. No group delay is introduced.- Args:
- s (numpy.ndarray or audiomath.Sound):
The input sound data. If
sis an array, a new array will be returned. If it is aSoundinstance,swill get changed in-place (the arrays.ywill be replaced by a new array) and returned.- func (callable):
A function that takes a numeric array of frequencies, in Hz, as its first (and only required) argument, and outputs a corresponding array of weights.
- samplingfreq_hz (float):
Sampling frequencym in Hz. Not needed if
sis aSoundinstance.- axis (int):
Axis along which time runs. Not needed if
sis aSoundinstance.
Additional
*pargsand**kwargsare passed straight through tofunc().
- audiomath.Signal.SawtoothWave(cycles, phase_deg=0, maxharm=None, rescale=False)
A sawtooth wave with its polarity and zero-crossings in sine phase. If
maxharmis an integer, then an anti-aliased approximation to the sawtooth wave (containing no components of higher frequency thanmaxharmtimes the fundamental) is returned instead. In this case, therescaleflag can be set to ensure that the waveform does not exceed +/- 1.0This function can be passed as the
waveformargument toGenerateWaveform.
- audiomath.Signal.Shoulder(x, s, complement=False, cosine=True)
Return a (possibly asymmetric) Tukey window function of
x.smay have 1, 2, 3 or 4 elements:raised cosine between
x=s[0]-0.5andx=s[0]+0.5raised cosine between
x=s[0]andx=s[1]raised cosine rise from
s[0]tos[1], and fall froms[1]tos[2]raised cosine rise from
s[0]tos[1], plateau froms[1]tos[2], and fall froms[2]tos[3]
- audiomath.Signal.SineWave(cycles, phase_deg=0, maxharm=None, rescale=False)
A sine wave, but with the input expressed in cycles (0 to 1) instead of radians (0 to 2*pi). Otherwise no different from
numpy.sin, except that the function signature hasmaxharmandrescalearguments (which are ignored) for compatibility withSquareWave(),TriangleWave()andSawtoothWave().This function can be passed as the
waveformargument toGenerateWaveform.
- audiomath.Signal.SlidingWindow(s, window_sec=1.0, overlap=0.5, taper=True, timeAxis=None, stackAxis=None, samplingfreq_hz=None)
Given an array (or
Soundobject) containing sound samples along the specifiedtimeAxis, chop the samples up into segments ofwindow_seclength, overlapping by proportionoverlap. Iftaperis true, taper each window with a Hann function. Stack the resulting segments in the specifiedstackAxisand return the resulting array, and also the time-base in seconds.Example usage:
import audiomath as am y, t = am.Signal.SlidingWindow(x) # for Sound object x s = am.Signal.Spectrum(y, samplingfreq_hz=x)
Now
s['amplitude']is a spectrogram withtannotating its columns in seconds ands['freq_hz']annotating its rows in Hz. And(s['amplitude']**2).mean(axis=1)is a Welch-style short-time power spectrum (divide bys['freq_hz'][1]for PSD). This function is called byPlotSpectrum()if you supply awindow_secargument.
- audiomath.Signal.Spectrum(x, samplingfreq_hz=None, axis=None)
Runs
ffton a signal followed byfft2ap, to return spectral information in “human-readable” format with the annoying corner cases handled.The inverse operation is
InverseSpectrum().
- audiomath.Signal.SquareWave(cycles, phase_deg=0, maxharm=None, rescale=False, duty=0.5, ramp=0, tol=1e-08)
A square wave with its peaks and troughs in sine phase. If
maxharmis an integer, then an anti-aliased approximation to the square wave (containing no components of higher frequency thanmaxharmtimes the fundamental) is returned instead. In this case, therescaleflag can be set to ensure that the sampled waveform does not exceed +/- 1.0This function can be passed as the
waveformargument toGenerateWaveform.
- audiomath.Signal.Timebase(x, samplingfreq_hz=None, axis=None)
Return a discrete time axis in seconds, against which signal
xcan be plotted.xmay be anaudiomath.Soundinstance, or you may supplysamplingfreq_hzexplicitly.
- audiomath.Signal.Toy(nSamples=11, nCycles=None, amplitude=(1.0, 0.1), phase_deg=0)
Toy sinusoidal signals for testing
fft2ap()andap2fft(). Check both odd and evennSamples.
- audiomath.Signal.TriangleWave(cycles, phase_deg=0, maxharm=None, rescale=False)
A triangle wave with its peaks and troughs in sine phase. If
maxharmis an integer, then an anti-aliased approximation to the triangle wave (containing no components of higher frequency thanmaxharmtimes the fundamental) is returned instead. Therescaleflag, included for compatibility withSawtoothWave()andSquareWave(), has no effect.This function can be passed as the
waveformargument toGenerateWaveform.
- audiomath.Signal.UnwrapDiff(x, base=6.283185307179586, axis=None, startval=None, dtype=None)
Assume
Xis a wrapped version of an underlying valueYwe’re interested in. For example, it’s a 16-bit value that wraps around at 65536, or it’s an angle which wraps back to 0 at 2*pi.baseis the value (65536 or 2*pi in the above examples) such thatX = Y % base. The default value ofbaseis 2*pi.Let
dYbe the numeric diff ofYin dimensionaxis, computed fromXby unwrapping in order to avoid jumps larger thanbase/2. Thus, withbase=65536, a jump from 65535 to 1 is considered as a step of +2. Withbase=360, a jump from 10 to 350 is considered as a step of -20.Yis then reconstructed based ondYandstartval(which defaults to the actual initial value(s) ofX).Return value is
(dY,Y).
- audiomath.Signal.ap2fft(amplitude, phase_rad=None, phase_deg=None, samplingfreq_hz=2.0, axis=0, freq_hz=None, fullfreq_hz=None, nSamples=None)
Keyword arguments match the fields of the
dictoutput byfft2ap().The inverse of
d = fft2ap(X)isX = ap2fft(**d)
- audiomath.Signal.fft2ap(X, samplingfreq_hz=2.0, axis=0)
Given discrete Fourier transform(s)
X(with frequency along the specifiedaxis), return a dict containing a properly scaled amplitude spectrum, a phase spectrum in degrees and in radians, and a frequency axis (coping with all the fiddly edge conditions).The inverse of
d = fft2ap(X)isX = ap2fft(**d)
- audiomath.Signal.fftfreqs(nSamples, samplingfreq_hz=1.0)
Return a 1-D numpy.array of length
nSamplescontaining the positive and negative frequency values corresponding to the elements of annSamples-point FFT. Ifsamplingfreq_hzis not supplied, 1.0 is assumed, so the result has 0.5 as its Nyquist frequency.
- audiomath.Signal.msec2samples(msec, samplingfreq_hz)
Converts milliseconds to the nearest integer number of samples given the specified sampling frequency.
- audiomath.Signal.samples2msec(samples, samplingfreq_hz)
Converts samples to milliseconds given the specified sampling frequency.