Package: audiolazy
DevelopmentLast releasePyPI statusLaziness and object representationThere are several tools and packages that let the Python use and
expressiveness look like languages such as MatLab and Octave. However, the
eager evaluation done by most of these tools make it difficult, perhaps
impossible, to use them for real time audio processing. To avoid such
eagerness, one can make the calculations only when data is requested, not
when the path to the data is given. This is the core idea in laziness that
allows:Real-time application (you don’t need to wait until all data is
processed to have a result);Endless data sequence representation;Data-flow representation;Task elimination when a reverse task is done: instead of doing something
to then undo, nothing needs to be done, and no conscious optimization
need to be done for that.Another difficulty concerns expressive code creation for audio processing in
blocks through indexes and vectors. Sometimes, that’s unavoidable, or at
least such avoidance would limit the power of the system that works with
sequence data.Block sequences can be found from sample sequences being both objects, where
the latter can be the result of a method or function over the former. The
information needed for such is the block size and where would start the next
block. Although one can think about the last block and the exact index where
it would start, most of the time spent in steps like this one happens to be
an implementation issue that just keep the focus away from the problem being
worked on. To allow a thing like an endless data sequence, there should be
no need to know when something stops.Probably an engineer would find the use of equations and structures from
electrical engineering theory much cleaner to understand than storing
everything into data arrays, mainly when common operations are done to these
representations. What is the product of the filter with numerator[1, 7, 2]and denominator[1, 0.5, 0.2]as its system equation with
the one that has the arrays reversed like[2, 7, 1]? That might be simple,
and the reversed would avoid questions like “what comes first, the zero or the
[minus] two exponent?”, but maybe we could get more efficient ourselves if we
had something easier: multiplication could be written once and for all and
with a representation programmers are used to see. This would be even more
expressive if we could get rid from the asymmetry of a method call likefilt1.multiply_by(filt2), since multiplication in this case should be
commutative. The use of natural operators is possible in a language that
allows operator overloading, but for such we need to describe
those equations and structures as objects and object relationships.The nameHzcan be a number that would allow conversion to a default DSP
internal rad/samples unit, so one can write things likefreq = 440 * Hz.
This isn’t difficult in probably any language, but can help in expressiveness,
already. If (almost) everything would need data in “samples” or “rad/sample”
units, constants for converting these from “second” and “hertz” would help
with the code expressiveness. A comb filtercomb.tau(delay=30*s, tau=40*s)can represent a comb filter with the given delay and time constant, both in
samples, but with a more clear meaning for the reader than it would have with
an expression like[1] + [0] * 239999 + [alpha]. Would it be needed to
store all those zeros while just using the filter to get a frequency response
plot?It’s possible to avoid some of these problems with well-chosen constants,
duck typing, overloaded operators, functions as first-class citizens, object
oriented together with functional style programming, etc.., resources
that the Python language gives us for free.What does it do?Prioritizing code expressiveness, clarity and simplicity, without precluding
the lazy evaluation, and aiming to be used together with Numpy, Scipy and
Matplotlib as well as default Python structures like lists and generators,
AudioLazy is a package written in pure Python proposing digital audio signal
processing (DSP), featuring:AStreamclass for finite and endless signals representation with
elementwise operators (auto-broadcast with non-iterables) in a common
Python iterable container accepting heterogeneous data;Strongly sample-based representation (Stream class) with easy conversion
to block representation using theStream.blocks(size, hop)method;Sample-based interactive processing withControlStream;Streamixmixer for iterables given their starting time deltas;Multi-thread audio I/O integration with PyAudio;Linear filtering with Z-transform filters directly as equations (e.g.filt = 1 / (1 - .3 * z **-1)), including linear time variant filters
(i.e., theaina * z ** kcan be a Stream instance), cascade
filters (behaves as a list of filters), resonators, etc.. EachLinearFilterinstance is compiled just in time when called;Zeros and poles plots and frequency response plotting integration with
MatPlotLib;Linear Predictive Coding (LPC) directly toZFilterinstances, from
which you can find PARCOR coeffs and LSFs;Both sample-based (e.g., zero-cross rate, envelope, moving average,
clipping, unwrapping) and block-based (e.g., window functions, DFT,
autocorrelation, lag matrix) analysis and processing tools;A simple synthesizer (Table lookup, Karplus-Strong) with processing tools
(Linear ADSR envelope, fade in/out, fixed duration line stream) and basic
wave data generation (sinusoid, white noise, impulse);Biological auditory periphery modeling (ERB and gammatone filter models);Multiple implementation organization asStrategyDictinstances:
callable dictionaries that allows the same name to have several different
implementations (e.g.erb,gammatone,lowpass,resonator,lpc,window);Converters among MIDI pitch numbers, strings like “F#4” and frequencies;Polynomials, Stream-based functions from itertools, math, cmath, and more!
Go try yourself! =)InstallingThe package works both on Linux and on Windows. You can find the last stable
version atPyPIand install it with
the usual Python installing mechanism:python setup.py installIf you have pip, you can go directly (use-Ufor update or reinstall):pip install audiolazyfor downloading (from PyPI) and installing the package for you, or:pip install -U .To install from a path that has thesetup.pyfile and the package data
uncompressed previously.For thebleeding-edgeversion, you can install directly from the github
repository (requiresgitfor cloning):pip install -U git+git://github.com/danilobellini/audiolazy.gitFor older versions, you can install from the PyPI link or directly from the
github repository, based on the repository tags. For example, to install the
version 0.04 (requiresgitfor cloning):pip install -U git+git://github.com/danilobellini/audiolazy.git@v0.04The package doesn’t have any strong dependency for its core besides the Python
itself (versions 2.7, 3.2 or newer) as well as its standard library, but you
might need:PyAudio: needed for playing and recording audio (AudioIOclass);NumPy: needed for doing some maths, such as finding the LSFs from a filter
or roots from a polynomial;MatPlotLib: needed for all default plotting, like inLinearFilter.plotmethod and several examples;SciPy (testing and examples only): used as an oracle for LTI filter testing
and for the Butterworth filter example;Sympy (testing only): used for testing linear filters with time-varying
matrices of symbolic coeffs where the Stream samples are these matrices;tox for testing all at once, or pytest, pytest-cov and pytest-timeout for
testing in a single environment (testing only): runs test suite and
shows code coverage status;wxPython (example only): used by one example with FM synthesis in an
interactive GUI;Tkinter (example only): needed for the pitch follower based on the
zero-crossing rate example GUI;Music21 (example only): there’s one example that gets the Bach chorals from
that package corpora for synthesizing and playing;Sphinx (documentation only): it can create the software documentation in
several different file formats.Beside examples and tests, only the filter plotting withplotandzplotmethods needs MatPlotLib. Also, the routines that needs NumPy up to
now are:Root finding withzerosandpolesproperties (filter classes) or
withrootsproperty (Poly class);Some Linear Predictive Coding (lpc) strategies:nautocor,autocorandcovar;Line Spectral Frequencieslsfandlsf_stablefunctions.Getting startedBefore all examples below, it’s easier to get everything from audiolazy
namespace:fromaudiolazyimport*All modules starts with “lazy_”, but their data is already loaded in the main
namespace. These two lines of code do the same thing:fromaudiolazy.lazy_streamimportStreamfromaudiolazyimportStreamEndless iterables with operators (be careful with loops through an endless
iterator!):>>>a=Stream(2,-2,-1)# Periodic>>>b=Stream(3,7,5,4)# Periodic>>>c=a+b# Elementwise sum, periodic>>>c.take(15)# First 15 elements from the Stream object[5,5,4,6,1,6,7,2,2,9,3,3,5,5,4]And also finite iterators (you can think on any Stream as a generator with
elementwise operators):>>>a=Stream([1,2,3,2,1])# Finite, since it's a cast from an iterable>>>b=Stream(3,7,5,4)# Periodic>>>c=a+b# Elementwise sum, finite>>>list(c)[4,9,8,6,4]LTI Filtering from system equations (Z-transform). After this, try summing,
composing, multiplying ZFilter objects:>>>filt=1-z**-1# Diff between a sample and the previous one>>>filt1-z^-1>>>data=filt([.1,.2,.4,.3,.2,-.1,-.3,-.2])# Past memory has 0.0>>>data# This should have internally [.1, .1, .2, -.1, -.1, -.3, -.2, .1]<audiolazy.lazy_stream.Streamobjectat...>>>>data*=10# Elementwise gain>>>[int(round(x))forxindata]# Streams are iterables[1,1,2,-1,-1,-3,-2,1]>>>data_int=filt([1,2,4,3,2,-1,-3,-2],zero=0)# Now zero is int>>>list(data_int)[1,1,2,-1,-1,-3,-2,1]LTI Filter frequency response plot (needs MatPlotLib):(1+z**-2).plot().show()Thematplotlib.figure.Figure.showmethod won’t work unless you’re
using a newer version of MatPlotLib (works on MatPlotLib 1.2.0), but you still
can save the above plot directly to a PDF, PNG, etc. with older versions
(e.g. MatPlotLib 1.0.1):(1+z**-2).plot().savefig("my_plot.pdf")On the other hand, you can always show the figure using MatPlotLib directly:frommatplotlibimportpyplotasplt# Or "import pylab as plt"filt=1+z**-2fig1=filt.plot(plt.figure())# Argument not needed on the first figurefig2=filt.zplot(plt.figure())# The argument ensures a new figureplt.show()CascadeFilter instances and ParallelFilter instances are lists of filters with
the same operator behavior as a list, and also works for plotting linear
filters. Constructors accepts both a filter and an iterable with filters.
For example, a zeros and poles plot (needs MatPlotLib):filt1=CascadeFilter(0.2-z**-3)# 3 zerosfilt2=CascadeFilter(1/(1-.8*z**-1+.6*z**-2))# 2 poles# Here __add__ concatenates and __mul__ by an integer make reference copiesfilt=(filt1*5+filt2*10)# 15 zeros and 20 polesfilt.zplot().show()Linear Predictive Coding (LPC) autocorrelation method analysis filter
frequency response plot (needs MatPlotLib):lpc([1,-2,3,-4,-3,2,-3,2,1],order=3).plot().show()Linear Predictive Coding covariance method analysis and synthesis filter,
followed by the frequency response plot together with block data DFT
(MatPlotLib):>>>data=Stream(-1.,0.,1.,0.)# Periodic>>>blk=data.take(200)>>>analysis_filt=lpc.covar(blk,4)>>>analysis_filt1+0.5*z^-2-0.5*z^-4>>>residual=list(analysis_filt(blk))>>>residual[:10][-1.0,0.0,0.5,0.0,0.0,0.0,0.0,0.0,0.0,0.0]>>>synth_filt=1/analysis_filt>>>synth_filt(residual).take(10)[-1.0,0.0,1.0,0.0,-1.0,0.0,1.0,0.0,-1.0,0.0]>>>amplified_blk=list(Stream(blk)*-200)# For alignment w/ DFT>>>synth_filt.plot(blk=amplified_blk).show()AudioLazy doesn’t need any audio card to process audio, but needs PyAudio to
play some sound:rate=44100# Sampling rate, in samples/seconds,Hz=sHz(rate)# Seconds and hertzms=1e-3*snote1=karplus_strong(440*Hz)# Pluck "digitar" synthnote2=zeros(300*ms).append(karplus_strong(880*Hz))notes=(note1+note2)*.5sound=notes.take(int(2*s))# 2 seconds of a Karplus-Strong notewithAudioIO(True)asplayer:# True means "wait for all sounds to stop"player.play(sound,rate=rate)See also the docstrings and the “examples” directory at the github repository
for more help. Also, the huge test suite might help you understanding how the
package works and how to use it.Project filesThere are several files and directories in the AudioLazy repository (as well
as in the source distribution):File/DirectoryDescriptionaudiolazy/AudioLazy package modules source codeaudiolazy/tests/Testing subpackagedocs/Documentation generation scriptsexamples/Examples for some AudioLazy use casesimages/Images referenced by some reStructuredText documentation filemath/Proof for some formula used by AudioLazy using Sympy CASCHANGES.rstAudioLazy History, a.k.a. change logconftest.pyConfiguration for py.test, to work properly with doctests on
StrategyDict strategies and on an environment missing NumpyCOPYING.txtLicense fileMANIFEST.inList of extra distributed files to be included in the tarball
that doesn’t need to be installed together with the packageREADME.rstSome general information about the AudioLazy projectsetup.pyGeneral Python setup script for installation, testing, etc.tox.iniConfiguration for tox, py.test and pytest-cov.travis.ymlTravis-CI configuration (not in PyPI tarball/”egg” source
distribution)Theexamplesand themathdirectories might be useful for an AudioLazy
user. All Python files in these two directories are scripts intended to run on
both Python 2 and 3 unless they need something not yet available for Python 3
(e.g. wxPython), most of them have some external dependency.AudioLazy changes history* Version 0.6 (Examples, STFT, phon2dB, tox, CI, wave file) *examples:Formant synthesis for voiced “ah-eh-ee-oh-oo”Musical keyboard synth example with a QWERTY keyboard (also via jack!)Random synthesis with saving and memoizationAesthetics for the Tkinter GUI examplesMatplotlib animated plot with mic input data (also works via jack!)Perceptual experiment with butterworth filters (Scipy) applied to white
noise (based on the Demonstrations to Auditory Scene Analysis)Psychoacoustics using ISO/FDIS 226:2003Equal loudness contour curves plottingConstant phon chirp playingPartial recreation of the “Windows and Figures of Merit” F. Harris
comparison table and window plotsPlaying/synthesizing “Ode to Joy” from its “score” written as codeAll recording/playback examples now prepared for using both the default
API and receiving it as an argument like “jack” or “alsa”Realtime STFT (Short Time Fourier Transform) effects:Robotize“Roll” the magnitude spectrum while keeping the phasegeneral:Tox for testing with CPython 2.7, CPython 3.2~3.6 and PyPyContinuous integration wih Travis CI and CoverallsNew_internals.pymodule to avoid exposing package internals together
with the API, which also allowed the new simplified__init__.pyRenewed setup.py in both its internals (e.g. using AST instead of
string manipulation to avoid importing the package before installation)
and its interface (e.g. thetestcommand now callstox)Newconftest.pyfor testing doctests from strategies inside
StrategyDict instances without the need of a__test__in the module
and for skipping doctests known to need Numpy when it’s not availableNewmathdirectory for adding scripts with symbolic math calculations
(with Sympy) done for designing (or as a proof) for parts of the
AudioLazy code. All lowpass and highpass strategies have their design
explicitly explained therelazy_analysis:Newoverlap_addStrategyDict instance, allowing resynth after block
processing/analysis, featuring block size auto-detection and window
normalization to keep the output in the [-1; 1] range. Has 2
implementations keeping the same interface:numpy(default): needs Numpy arrays internallylist: uses lists instead, doesn’t need Numpy and was tested on PypyNewstftStrategyDict instance, allowing Short Time Fourier Transform
block processors / phase vocoder by:Passing a function as the first parameterUsing astftstrategies as a decoratorCreating new strategies by avoiding the only positional parameterIt was created with three Numpy-based strategies:rfft,realorbase(default): needsnumpy.fft.rfftinternally, as well as its inverse, to process a block in the
frequency domain with values up to the Nyquist frequency, by assuming
the input signal is realcfftorcomplex: Alike to the default approach but uses thenumpy.fft.fftfor a full complex-valued block in frequency domain,
which means the output is a complex signalcfftrorcomplex_real: same tostft.cfftstrategy, but
keeps only the real part of the resultParameters allows changing the default zero-phase behavior (beforeandafterfunctions), the transform and inverse transform functions,
the overlap-add strategy (as well as its parameters), and obviously the
block size and hopThewindowStrategyDict now returns the “periodic” window data
instead of the “symmetric” window to be used with the STFT directlyNewwsymmStrategyDict with the same strategies fromwindowbut
returning a “symmetric” windowDefaultwindowstrategy is the Hann window (the same forwsymm)Newcosstrategy forwindowandwsymmimplementing cosine to
the power of alphalazy_auditory:Newphon2dBStrategyDict instance with the ISO/FDIS 226:2003 model
for getting a SPL (Sound Pressure Level) in dBs from a phon valuelazy_core:Add support to the new@matrix multiplication operatorOpMethod.get()now accepts numbers"1"and"2"as strings for
unary and binary query for operators, and"all"is the new default, soOpMethod.get(without="2~")would get all operators but the [reversed
or not] binary ones and the invert operator, which means it would yield
only the unary"+"(pos) and-(neg), as probably was expected;
OpMethod also had a bug fix regarding the shift operatorsStrategy name autocomplete works on IPython since StrategyDict now
changes its instance dictionary (e.g.vars(window)) instead of
depending on the__getattr__methodStrategyDict.strategymethod now allows the strategy function name to
be kept by using the newkeep_namekeyword-only argument. It might be
helpful for adding built-in functions as well as other immutable
callables as multi-name strategies with the same behavior as the item
assignment for adding a strategyThe default strategy in a StrategyDict instance is now removed when all
its keys/names are removed. The new default is the next added strategyStrategies can be removed both by their item name and their attribute,
and removing an attribute that isn’t an strategy recovers the strategy
attribute if its name belongs to a strategyMultiKeyDict methodskey2keysandvalue2keysto help getting a
tuple with all keys that points to the same value, ordered by the
insertion orderlazy_filters:LinearFilter coefficients can now be a Stream of Numpy matrices, as well
as Sympy symbols (including symbolic matrices).New simple lowpass/highpass IIR filter strategies:highpass.z(taken as the newhighpassdefault)lowpass.zhighpass.pole_exphighpass.z_explowpass.z_expWhere the"z"name denotes the presence of a single zero (besides the
single pole) and"_exp"denotes the exponential approximation from
a matched Z-Transform pole value from the equivalent or mirrored analog
filter equation (Laplace). The absence of such suffix denotes it was
designed directly as a digital filter.lazy_io:Newapikeyword argument for AudioIO, allowing e.g. integration with
JACK (for now this needschunks.size = 1)AudioIO.openandAudioIO.recordnow allows keyword arguments, to
be passed directly to PyAudio, including the now default “channels”
keyword (old “nchannels” keyword still works, for backward compatibility)lazy_math:Signal functionsignnow works on Python 3lazy_misc:Newcacheddecorator caching the results for a function without
keyword argumentslazy_poly:Complex numbers and Sympy symbols can now be used as Poly powersPoly instances are now based on OrderedDict (stores the creation order
internally) and Poly.terms now support both asortand areversekeyword arguments to choose the yielding order (sorted by powers, keep
creation order or reverse any of these)Immutable Poly behavior is now based on a cached frozenset (doesn’t depend
on the terms order) and includes Poly.zero as a read-only property (after
the hash is required)The Horner-like polynomial evaluation scheme (which needs sorting) is now
enabled/disabled via a keyword argument. By default, it’s enabled just for
simple polynomials, but optional when powers are sortable (e.g. in a
Laurent polynomial)lazy_text:Newformat_docstringdecorator that use format-style templates to
assign docstrings to functions, intended to avoid docstring copies on
StrategyDict instances.lazy_wav (new!):WavStreamclass for opening Wave files. Can load 24-bit audio files!
Tested with 8 bits files (unsigned int) and 16/24/32 bits (signed int)
mono and stereo files, both casting the data to a float in [-1;1) interval
(default) and keeping the original integer data as it ismultiple modules:(lazy_math and lazy_stream) Renamed the elementwisedabstoabsolute, so no Python built-in name is ever replaced when importing
withfrom audiolazy import *. Also, the built-inabsnow can be
used directly with Stream instances(lazy_analysis and lazy_misc) Renamedfreq2lagandlag2freqto
use2instead of_to_, and moved them to lazy_misc* Version 0.05 (Python 2 & 3, more examples, refactoring, polinomials) *examples:Pitch follower via zero-crossing rate with Tkinter GUIPi with Madhava-Gregory-Leibniz series and Machin formula using StreamLPC plot with DFT, showing two formants (magnitude peaks)A somehow disturbing example based on Shepard “going higher” toneLinear Periodically Time Variant filter exampleNow the Bach choral player can play in loopNew DFT-based pitch follower (guitar tuner like) and better ZCR-based
pitch follower by using a simple limiterButterworth filter from SciPy as a ZFilter instance, with plotsgeneral:Now with 82% code coverage in testsMock testing for audio outputBugfixes (envelope.abs,midi2str,StreamTeeHub.blocks, etc.)Extended domain for some functions by usinginfandnanRemoved deprecatedStream.tee()methodConstantsDEFAULT_CHUNK_SIZEandLATEX_PI_SYMBOLwere removed:
the default values are now changeable and insidechunksandfloat_str, respectively (see docstrings for more details)No more distinction between__div__and__truediv__(Python 2.7)Now AudioLazy works with Python 3.2 and 3.3!Test skipping for tests that depends upon something that is Python
version-specificTest “xfail” using XFailer classes when depending package (e.g. pyaudio)
is unavailable in the testing environmentlazy_compat (new!):Module for Python 2.x and 3.x compatibility resources (constants
and functions) without AudioLazy dependencies (i.e., no Stream here)Common place for iterable-based version of itertools/built-ins in both
Python 2 and 3 starting with “x”:xmap,xfilter,xzip,xrange,xzip_longest. Versions with “i” are kept in lazy_itertools
module to return Stream instances (imap,izip,izip.longest,
etc.), and Python 2 list-based behaviour ofrangeis kept asorange(a fruitful name)Newmetafunction for creating metaclasses always in a “Python 3
look-alike” style, keeping the semantics (including the inheritance
hierarchy, which won’t have any extra “dummy” class)lazy_core:NewOpMethodclass with 33 operator method instances and queryingChangedAbstractOperatorOverloaderMetato the new OpMethod-based
interfaceNow StrategyDict changes the module__test__so that doctests from
strategies are found by the doctest finder.lazy_filters:ZFilter instances are now better prepared for Stream coeffs and
operator-based filter creation, as well as a new copy helper methodFilters are now hashable (e.g., they can be used in sets)lazy_io:New RecStream class for recording Stream instances with astopmethodNow chunks is a StrategyDict here, instead of two lazy_misc functionsNow the default chunk size is stored in chunks.size, and can be changedlazy_itertools:Newaccumulateitertool from Python 3, available also in Python 2
yielding a Stream. This is a new StrategyDict with one more strategy in
Python 3Strategychain.from_iterableis now available (Stream version
itertool), andchainis now a StrategyDictNowizipis a StrategyDict, withizip.smallest(default) andizip.longeststrategieslazy_misc:Newrintfor “round integer” operations as well as other higher step
integer quantizationNowalmost_eqis a single StrategyDict with bothbits(default,
comparison by significand/mantissa bits) anddiff(absolute value
difference) strategieslazy_poly:NewxPoly object (to be used like thezZFilter instance)Waring-Lagrange polynomial interpolator StrategyDictGeneral resample based on Waring-Lagrange interpolators, working with
time-varying sample rateNew methodsPoly.is_polynomial()andPoly.is_laurent()New propertyPoly.orderfor common polynomialsNowPoly.integrate()andPoly.diff()methods returns Poly
instances, and thezerofrom the caller Poly is always kept in
result (this includes many bugfixes)Poly instances are now better prepared for Stream coeffs and evaluation,
including a helperPoly.copy()methodPoly is now hashable and have __setitem__ (using both isn’t allowed for
the same instance)lazy_stream:Stream.take now accepts floats, so with firstsHzoutput ass(for second) you can now usemy_stream.take(20 * s)directly,
as well as a “take all” featuremy_stream.take(inf)NewStream.peek()method, allowing taking items while keeping them
as the next to be yielded by the Stream or StreamTeeHubNewStream.skip()method for neglecting the leading items without
storing themNewStream.limit()method, to enforce a maximum “length”StreamTeeHub methodsskip(),limit(),append(),map()andfilter()returns the modified copy as a Stream instance (i.e., works
likeStream(my_stream_tee_hub).method_name())Control over the module name intostream(needed for lazy_itertools)lazy_synth:Input “dur” inones(),zeros(),white_noise()andimpulse()now can be inf (besides None)Impulse now haveone=1.andzero=0.argumentsNewgauss_noisefor Normal / Gaussian-distributed noiseWhite-noise limits parametrizationlazy_text (new!):Got all text/string formatting functions from lazy_miscNamespace clean-up: new StrategyDictfloat_strembraces older
rational/pi/auto formatters in one instance* Version 0.04 (Documentation, LPC, Plots!) *examples:Random Bach Choral playing example (needs Music21 corpus)general:Sphinx documentation!Self-generated package and module summary at the docstringIntegration with NumPy (tested on 1.5.0, 1.6.1 and 1.6.2) and MatPlotLib
(tested on 1.0.1 and 1.2.0)More docstrings and doctests, besides lots of correctionsItemized package description, installation instructions and getting
started examples with plots in README.rstNow with 5400+ tests and 75% code coveragelazy_analysis:One-dimensional autocorrelation function withacorrand lag
“covariance” (due to lpc.covar) withlag_matrixDFT for any frequency, given a blockThree envelope filtering strategies (time domain)Three moving average filter strategiesSignal clipping functionSignal unwrap, defaults to the2 * piradians range but configurable
to other units and max signal difference allowedNew AMDF algorithm as a non-linear filterlazy_core:StrategyDict instances now are singletons of a new class, which have
lazy non-memoized docstrings based on their contentslazy_filters:ZFilter composition/substitution, e.g.,(1 + z **-1)(1/ z)results
to the ZFilter instance1 + zNew LinearFilter.plot() directly plots the frequency response of a LTI
filter to a MatPlotLib figure. Configurable:Linear (default) or logarithmic frequency scaleLinear, squared or dB (default) magnitude scalePlots together the DFT of a given block, if needed. Useful for LPCPhase unwrapping (defaults to True)Allows frequency in Hz and in rad/sample. When using radians units,
the tick locator is based onpi, as well as the formatterNew LinearFilter.zplot() for plotting the zero-pole plane of a LTI filter
directly into a MatPlotLib figureNew LinearFilterProperties read-only propertiesnumpolyzanddenpolyzreturning polynomials based onx = zinstead of the
polynomials based onx = z **-1returned fromnumpolyanddenpolyNew LinearFilter propertiespolesandzeros, based on NumPyNew classFilterListfor filter grouping with acallablesproperty, for casting from lists with constant gain values as filters.
It is an instance ofFilterListMeta(old CascadeFilterMeta), and
CascadeFilter now inherits from this FilterListMore LinearFilter behaviour into FilterList: Plotting (plotandzplot),poles,zeros,is_ltiandis_causalNewParallelFilterclass, inheriting from FilterListNow comb is a StrategyDict too, with 3 strategies:comb.fb(default): Feedback comb filter (IIR or time variant)comb.tau: Same to the feedback strategy, but with a time decaytauparameter (time in samples up to1/eamplitude, or
-8.686 dB) instead of a gainalphacomb.ff: Feed-forward comb filter (FIR or time variant)lazy_lpc (new!):Linear Predictive Coding (LPC) coefficients as a ZFilter from:lpc.autocor(default): Auto-selects autocorrelation implementation
(Faster)lpc.nautocor: Autocorrelation, with linear system solved by NumPy
(Safer)lpc.kautocor: Autocorrelation, using the Levinson-Durbin algorithmlpc.covarorlpc.ncovar: Covariance, with linear system solved
by NumPylpc.kcovar: Covariance, slower. Mainly for those without NumPylevinson_durbin: Same to thelpc.kautocor, but with the
autocorrelation vector as the input, not the signal dataToeplitz matrix as a list of listsPartial correlation coefficients (PARCOR) or reflection coefficientsLine Spectral Frequencies (LSF)Stability testers for filters with LSF and PARCORlazy_math:Newsigngets the sign of a given sequence.lazy_midi:Completed converters between frequency (in hertz), string and MIDI pitch
numbersNewoctavesfor finding all octaves in a frequency range given one
frequencylazy_misc:Newrational_formatter: casts floats to strings, perhaps with a symbol
string as multiplierNewpi_formatter: same torational_formatter, but with the symbol
fixed to pi, mainly for use in MatPlotLib labelslazy_poly:New Poly.roots property, based on NumPylazy_stream:Streamix class for mixing Streams based on delta starting times,
automatically managing the need for multiple “tracks”lazy_synth:Karplus-Strong algorithm now usestautime decay constant instead of
the comb filteralphagain.* Version 0.03 (Time variant filters, examples, etc.. Major changes!) *examples (new!):Gammatone frequency and impulse response plots exampleFM synthesis example for benchmarking with CPython and PyPySimple I/O wire example, connecting the input directly to the outputModulo Counter graphics w/ FM synthesis audio in a wxPython applicationWindow functions plot example (all window strategies)general:Namespace cleanup with __all__Lots of optimization and refactoring, also on tests and setup.pyBetter docstrings and README.rstDoctests (with pytest) and code coverage (needs pytest-cov)Now with 5200+ tests and 79% code coveragelazy_analysis (new!):NewwindowStrategyDict instance, with:Hamming (default)HannRectangularBartlett (triangular with zero endpoints)Triangular (without zeros)Blackmanlazy_auditory (new!):Two ERB (Equivalent Rectangular Bandwidth) models (both by Glasberg and
Moore)Function to find gammatone bandwidth from ERB for any gammatone orderThree gammatone filter implementations: sampled impulse response, Slaney,
Klapurilazy_core:MultiKeyDict: an “inversible” dict (i.e., a dict whose values must be
hashable) that may have several keys for each valueStrategyDict: callable dict to store multiple function implementations
in. Inherits from MultiKeyDict, so the same strategy may have multiple
names. It’s also an iterable on its values (functions)lazy_filters:LTI and LTIFreq no longer exists! They were renamed to LinearFilter and
ZFilter since filters now can have Streams as coefficients (they don’t
need to be “Time Invariant” anymore)Linear filters are now iterables, allowing:Comparison with almost_eq likeassert almost_eq(filt1, filt2)Expression likenumerator_data, denominator_data = filt, where
each data is a list of pairs that can be used as input for Poly,
LinearFilter or ZFilterLinearFilterProperties class, implementing numlist, denlist, numdict and
dendict, besides numerator and denominator, from numpoly and denpolyComparison “==” and “!=” are now strictCascadeFilter: list of filters that behave as a filterLinearFilter.__call__ now has the “zero” optional argument (allows
non-float)LinearFilter.__call__ memory input can be a function or a StreamLinearFilter.linearize: linear interpolated delay-line from fractional
delaysFeedback comb filter4 resonator filter models with 2-poles with exponential approximation
for finding the radius from the bandwidthSimple one pole lowpass and highpass filterslazy_io:AudioIO.record method, creating audio Stream instances from device datalazy_itertools:Now with a changed tee function that allows not-iterable inputs,
helpful to let the same code work with Stream instances and constantslazy_math (new!):dB10, dB20 functions for converting amplitude (squared or linear,
respectively) to logarithmic dB (power) values from complex-numbers
(like the ones returned by LinearFilter.freq_response)Most functions from math module, but working decorated with elementwise
(sin,cos,sqrt, etc.), and the constantseandpiOther functions:factorial,ln(thelogfrom math),log2,cexp(theexpfrom cmath) andphase(from cmath)lazy_midi:MIDI pitch numbers and Hz frequency converters from strings like “C#4”lazy_misc:Elementwise decorator now based on both argument keyword and positionlazy_poly:Horner-like scheme for Poly.__call__ evaluationPoly now can have Streams as coefficientsComparison “==” and “!=” are now strictlazy_stream:Methods and attributes from Stream elements can be used directly,
elementwise, likemy_stream.imagandmy_stream.conjugate()in a
stream with complex numbersNew thub() function and StreamTeeHub class: tee (or “T”) hub auto-copier
to help working with Stream instancesalmostthe same way as you do with
numberslazy_synth:Karplus-Strong synthesis algorithmADSR envelopeImpulse, ones, zeros/zeroes and white noise Stream generatorFaster sinusoid not based on the TableLookup class* Version 0.02 (Interactive Stream objects & Table lookup synthesis!) *general:10 new testslazy_midi (new!):MIDI to frequency (Hz) conversorlazy_misc:sHz function for explicit time (s) and frequency (Hz) units conversionlazy_stream:Interactive processing with ControlStream instancesStream class now allows inheritancelazy_synth (new!):TableLookup class, with sinusoid and sawtooth instancesEndless counter with modulo, allowing Stream inputs, mainly created for
TableLookup instancesLine, fade in, fade out, ADS attack with endless sustain* Version 0.01 (First “pre-alpha” version!) *general:4786 tests (including parametrized tests), based on pytestlazy_core:AbstractOperatorOverloaderMeta class to help massive operator
overloading as needed by Stream, Poly and LTIFreq (now ZFilter) classeslazy_filters:LTI filters, callable objects with operators and derivatives, returning
Stream instancesExplicit filter formulas with thezobject, e.g.filt = 1 / (.5 + z **-1)lazy_io:Multi-thread audio playing (based on PyAudio), with context manager
interfacelazy_itertools:Stream-based version of all itertoolslazy_misc:Block-based processing, given size and (optionally) hopSimple zero padding generatorElementwise decorator for functionsBit-based and diff-based “almost equal” comparison function for floats
and iterables with floats. Also works with (finite) generatorslazy_poly:Poly: polynomials based on dictionaries, with list interface and
operatorslazy_stream:Stream: each instance is basically a generator with elementwise
operatorsDecoratortostreamso generator functions can return Stream objects