mirror of
https://github.com/kennethreitz/pytheory.git
synced 2026-06-05 06:46:14 +00:00
866b110afa
index.rst: add figured bass, pitch class sets, scale recommendation, stereo, detune, pan/spread, master compressor, REPL quickstart.rst: same updates to "What's in the Box" README.md: add stereo, sidechain, compressor, repl, forte numbers drums.rst: document stereo drum panning playback.rst: document stereo output and master compressor cli.rst: add REPL section with cross-reference Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
180 lines
5.6 KiB
ReStructuredText
180 lines
5.6 KiB
ReStructuredText
Playback and Export
|
|
===================
|
|
|
|
This is the output layer. You've built your theory, composed your
|
|
arrangement, shaped your sounds -- now you need to hear it. PyTheory
|
|
gives you three ways to get your music out: speakers, WAV files, and
|
|
MIDI files.
|
|
|
|
Use **speakers** for immediate feedback while you're sketching and
|
|
experimenting. Use **WAV export** when you want to share actual audio
|
|
-- post it, send it, drop it into a video. Use **MIDI export** when you
|
|
want to bring your sketch into a real DAW and finish it with
|
|
professional instruments, mixing, and mastering. Each output serves a
|
|
different stage of the creative process.
|
|
|
|
PyTheory can play audio through your speakers, save to WAV, or export
|
|
to MIDI. Everything is synthesized from waveforms -- no samples or
|
|
external audio files needed.
|
|
|
|
.. note::
|
|
|
|
Audio playback requires `PortAudio <http://www.portaudio.com/>`_ to be
|
|
installed on your system. On macOS: ``brew install portaudio``.
|
|
On Ubuntu: ``apt install libportaudio2``.
|
|
|
|
play() -- Single Tones and Chords
|
|
---------------------------------
|
|
|
|
The simplest way to hear something:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Tone, Chord, play
|
|
|
|
play(Tone.from_string("A4"), t=1_000) # A440 for 1 second
|
|
play(Chord.from_symbol("Am7"), t=2_000) # chord for 2 seconds
|
|
|
|
Optional parameters for synth, envelope, and temperament:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Synth, Envelope
|
|
|
|
play(Tone.from_string("C4"), synth=Synth.SAW, envelope=Envelope.PLUCK, t=1_000)
|
|
play(Tone.from_string("C4"), temperament="pythagorean", t=1_000)
|
|
|
|
play_score() -- Full Arrangements
|
|
---------------------------------
|
|
|
|
Plays a ``Score`` with all its parts and drums mixed together.
|
|
Output is **stereo** — each part is panned according to its ``pan``
|
|
setting, drums are stereo-panned like a real kit, and reverb tails
|
|
have natural stereo width. A **master bus compressor/limiter** (4:1
|
|
ratio, brick-wall at 0.95) is applied to prevent clipping and make
|
|
the mix louder and punchier:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Score, Duration, Chord
|
|
from pytheory.play import play_score
|
|
|
|
score = Score("4/4", bpm=140)
|
|
score.drums("bossa nova", repeats=4)
|
|
chords = score.part("chords", synth="sine", envelope="pad")
|
|
for sym in ["Am", "Dm", "E7", "Am"]:
|
|
chords.add(Chord.from_symbol(sym), Duration.WHOLE)
|
|
play_score(score)
|
|
|
|
See :doc:`sequencing` for how to build scores and parts.
|
|
|
|
render_score() -- Headless Rendering
|
|
------------------------------------
|
|
|
|
Returns a raw audio buffer (numpy float32 array) without playing it.
|
|
Useful for saving to WAV or further processing:
|
|
|
|
.. code-block:: pycon
|
|
|
|
>>> from pytheory.play import render_score
|
|
>>> buf = render_score(score) # numpy float32 array
|
|
>>> len(buf)
|
|
604800
|
|
|
|
save() -- WAV Export
|
|
--------------------
|
|
|
|
Render tones or chords to a WAV file. Works without speakers or
|
|
PortAudio:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import save, Chord, Tone, Synth
|
|
|
|
save(Tone.from_string("A4"), "a440.wav", t=1_000)
|
|
save(Chord.from_name("Am7"), "am7.wav", t=2_000)
|
|
save(
|
|
Chord.from_name("C"),
|
|
"c_triangle.wav",
|
|
synth=Synth.TRIANGLE,
|
|
temperament="meantone",
|
|
t=3_000,
|
|
)
|
|
|
|
save_midi() -- MIDI Export
|
|
--------------------------
|
|
|
|
MIDI export is probably the most useful feature here for working
|
|
musicians. The idea is simple: sketch your ideas in Python -- where
|
|
iteration is fast, where you can use loops and randomness and music
|
|
theory functions -- and then export to MIDI. Open that MIDI file in
|
|
Logic, Ableton, Reaper, FL Studio, or whatever you use, and now you've
|
|
got your chord progressions, melodies, and bass lines on real tracks.
|
|
Swap in your favorite soft synths, add real mixing, finish the track
|
|
properly. Python is the sketchpad; the DAW is the canvas.
|
|
|
|
Export tones, chords, progressions, or full scores as Standard MIDI
|
|
Files. MIDI files can be opened in any DAW, edited, transposed, and
|
|
assigned to any instrument.
|
|
|
|
Simple export (single tone, chord, or progression):
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import save_midi, Key, Tone, Chord
|
|
|
|
save_midi(Tone.from_string("C4"), "middle_c.mid", t=1000)
|
|
save_midi(Chord.from_symbol("Am7"), "am7.mid")
|
|
|
|
chords = Key("C", "major").progression("I", "V", "vi", "IV")
|
|
save_midi(chords, "pop.mid", t=500, bpm=120)
|
|
|
|
Score-based export (with time signature, tempo, and parts):
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Score, Duration, Key
|
|
|
|
score = Score("4/4", bpm=140)
|
|
for chord in Key("G", "major").progression("I", "IV", "V", "I"):
|
|
score.add(chord, Duration.WHOLE)
|
|
score.save_midi("progression.mid")
|
|
|
|
play_pattern() -- Drum Patterns
|
|
-------------------------------
|
|
|
|
Play a drum pattern through the speakers:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Pattern
|
|
from pytheory.play import play_pattern
|
|
|
|
play_pattern(Pattern.preset("rock"), repeats=4, bpm=120)
|
|
play_pattern(Pattern.preset("bossa nova"), repeats=4, bpm=140)
|
|
|
|
See :doc:`drums` for the full list of 58 presets and 21 fills.
|
|
|
|
play_progression() -- Quick Chord Playback
|
|
------------------------------------------
|
|
|
|
Play a chord progression in sequence with a single call:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Key, play_progression
|
|
|
|
chords = Key("C", "major").progression("I", "V", "vi", "IV")
|
|
play_progression(chords, t=800)
|
|
|
|
Optional synth, envelope, and gap parameters:
|
|
|
|
.. code-block:: python
|
|
|
|
from pytheory import Synth, Envelope
|
|
|
|
play_progression(chords, t=1000, synth=Synth.TRIANGLE, gap=200)
|
|
play_progression(chords, t=2000, envelope=Envelope.PAD)
|
|
|
|
That's the workflow: hear it, tweak it, hear it again. When it sounds right, export to WAV or MIDI and take it somewhere bigger.
|