Skip to main content

Music

PyPI Python versions CI Docs License: MIT

Extreme-fidelity synthesis of musical elements.

Music generates and manipulates sound in LPCM audio, sample by sample. It implements MASS (Music and Audio in Sample Sequences), a collection of psychophysical descriptions of musical elements expressed as equations and corresponding Python routines.

import music

# a chromatic scale, written to a WAV file
scale = [music.note(440 * 2 ** (i / 12), duration=0.25) for i in range(13)]
music.write_wav_mono(music.horizontal_stack(*scale), "scale.wav")

📖 API reference — every routine documented with the equation it implements and the article it comes from.

Core features

  • Sample-based synthesis. State is updated at every sample. A note with a vibrato has a different instantaneous frequency at each of its samples, and the vibrato pattern is folded into the wavetable lookup rather than applied afterwards, so the rendered sound is as close as it can be to the mathematical model that describes it.
  • Musical structures with an emphasis on symmetry and discourse: permutation groups, change-ringing peals and plain changes.
  • play_audio to listen to a result without saving a file.

Music can be used alone or with other packages, and it is well suited to the audiovisualization of data. It works with Percolation and Participation for harnessing open linked social data, and with the audiovisual analytics vocabulary and ontology (AAVO).

To understand the routines further, read Musical elements in the discrete-time representation of sound. If you use this package, please cite that article.

How to install

pip install music

Requires Python 3.10 or newer. Every dependency comes with it; they are declared in pyproject.toml.

To hack on it, install from a checkout so your edits take effect immediately:

git clone https://github.com/ttm/music.git
pip install -e music

A closer look

Every routine returns a numpy array of PCM samples, so results compose with each other and with anything else you can express in numpy.

Notes and envelopes

note = music.note_with_vibrato(freq=220, duration=2,
                               vibrato_freq=6, max_pitch_dev=0.5)
shaped = music.adsr(sonic_vector=note, attack_duration=80,
                    sustain_level=-6, release_duration=200)

Durations are in seconds, envelope stages in milliseconds, levels in decibels and pitch deviations in semitones — each parameter in the unit it is usually thought about in.

Change ringing

Permutation groups and the peals of campanology, acted on any domain you like — here on frequencies, so the peal is the melody:

peal = music.PlainChanges(4)                      # every permutation, once
rows = peal.act([220, 275, 330, 440])
notes = [music.note(freq, duration=0.2) for row in rows for freq in row]
music.write_wav_mono(music.horizontal_stack(*notes), "campanology.wav")

Spatialisation

A source moving from one side to the other, its interaural time and intensity differences computed at every sample from its position:

passing = music.localize_linear(music.note(330, duration=3),
                                theta1=150, theta2=30, dist=0.6)
music.write_wav_stereo(passing, "passing.wav")

Sequencing

seq = music.Sequencer()
for i, freq in enumerate([440, 550, 660]):
    seq.add_note(freq, start=i * 0.25, duration=1.0,
                 adsr_params={"attack_duration": 20, "release_duration": 400})
seq.write("chord.wav")

Noise

Six colours, each defined by its gain per octave — brown at −6 dB, pink at −3, white at 0, blue at +3, violet at +6, black at −12 — or any number you pass instead:

colours = [music.noise(kind, duration=0.5)
           for kind in ("brown", "pink", "white", "blue", "violet")]
music.write_wav_mono(music.horizontal_stack(*colours), "colours.wav")

Examples

Inside the examples folder you can find some scripts that use the main features of Music.

  • chromatic_scale: writes twelve notes into a WAV file from a sequence of frequencies.
  • penta_effects: writes a pentatonic scale repeated once clean, once with pitch, one with vibrato, one with Doppler, and one with FM, into a WAV stereo file.
  • noisy: writes into a WAV file a sequence of different noises.
  • thirty_notes and thirty_numpy_notes generate a sequence of sounds by using a synth class (in this case the class Being).
  • campanology and geometric_music both use Being as their synth, but this time with permutations.
  • isynth also uses a synth class, but of a different kind, IteratorSynth, that iterates through arbitrary lists of variables.
  • singing_demo: demonstrates music.singing.setup_engine() and music.singing.make_test_song() to render a short sung phrase.
  • binaural_beats: generates binaural beats using two pure tones with tremolo for relaxation or focus.
  • The music.singing module provides basic text-to-speech utilities. Run music.singing.setup_engine() once to clone the eCantorix engine before using these features. It is cloned into your user cache directory; set MUSIC_ECANTORIX_DIR to put it elsewhere. Because eCantorix is a Perl program driving espeak through a Makefile, it also needs git, make, perl and espeak installed on the system — setup_engine() will tell you which are missing.

Package structure

The modules are:

  • core:
    • synths for synthesization of notes (including vibratos, glissandos, etc.), noises and envelopes.
    • filters for the application of filters such as ADSR envelopes, fades, IIR and FIR, reverb, loudness, and localization.
    • io for reading, writing and playing audio, both mono and stereo.
    • functions for normalization.
  • structures for higher level musical structures such as permutations (and related to algebraic groups and change ringing peals), scales, chords, counterpoint, tunings, etc.
  • legacy for musical pieces that are rendered with the Music package and might be used as material to make more music.
  • tables for the generation of lookup tables for some basic waveform.
  • utils for various functions regarding conversions, mix, etc.
  • sequencer for scheduling notes into a timeline and exporting audio.

Plans

Concrete things the code itself is waiting for, rather than a wish list:

  • A head-related transfer function. Both localize and localize2 say so in their own notes: the height of a source, and whether it is in front of or behind the listener, are cues an HRTF carries and neither of them models.
  • The remaining peals. Peals.twenty_all_over and Peals.an_eight_and_forty raise NotImplementedError, and Being.walk's perm-walk method was never restored from its predecessor.
  • Reconciling core/functions.py with the MASS reference implementation, routine by routine.
  • An article describing the package, as a companion to the MASS one.

Contributing

The test, type-check, lint and documentation tooling comes with the dev and docs extras:

pip install -e '.[dev,docs]'
pytest                                       # 476 tests, 100% coverage
mypy music                                   # type check
ruff check music tests examples conftest.py  # lint, at PEP 8's 79 columns
sphinx-build -b html -W docs docs/_build/html

All four run in CI on Python 3.10 through 3.13 for every push and pull request, and both pytest and sphinx-build are configured to fail on anything less than full coverage or a docstring numpydoc cannot parse.

Docstrings are numpydoc style throughout, and the code follows PEP 8. For the maths behind a routine, examples of its use, and the article it comes from, read its docstring — or the rendered API reference.

Further information

Music is primarily intended for artistic use, psychophysics experiments and data sonification.

You can find an example in Versinus, an animated visualization method for evolving networks that uses Music to render the musical track that represents networks structures.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

music-1.1.0.tar.gz (104.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

music-1.1.0-py3-none-any.whl (78.7 kB view details)

Uploaded Python 3

File details

Details for the file music-1.1.0.tar.gz.

File metadata

  • Download URL: music-1.1.0.tar.gz
  • Upload date:
  • Size: 104.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.10

File hashes

Hashes for music-1.1.0.tar.gz
Algorithm Hash digest
SHA256 50d19371336645880df3548c9cda419d8f206629e396509e5292ed175b5feedf
MD5 f5fdc27fe6f1c076607f545865035a20
BLAKE2b-256 aec26b0d4272f10dbde7ac88be8117dd5ec4bad245d44605f9df2434aac889ad

See more details on using hashes here.

File details

Details for the file music-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: music-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 78.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.10

File hashes

Hashes for music-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 499bb9d2cd3364fd6023ead73b41c12a4523d50097e1981324a5fcf2d031d77b
MD5 cb476438c10b23dc67436113ae0f01bd
BLAKE2b-256 7612a992279e5e1617b87a2effc7ca6b9de7cf4e469727df3d59146975211f15

See more details on using hashes here.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page