flexinfer-chiptune
A Python library for generating 8-bit/16-bit style music and sound effects with a semantic API that agents can use to programmatically compose music. Supports both MIDI export and direct audio synthesis with authentic retro chip waveforms.
Features
- Music Theory Foundation: Scales, chords, arpeggios with emotion-to-music mapping
- Game Theme Templates: Pre-built patterns for battle, boss, victory, overworld, etc.
- Multiple Chip Systems: NES 2A03, Game Boy DMG, C64 SID, and Sega Genesis FM
- Audio Effects: Vibrato, tremolo, echo, chorus, tape delay, and effect chains
- Procedural Generation: Markov-based melodies, auto bass lines, countermelodies
- Adaptive Intensity: Dynamic music that responds to game state (0.0-1.0)
- Preset Library: One-liner genre presets, effect chains, and quick composers
- CLI Tool: Generate music from the command line
- Agent-Friendly API: Natural language context to music generation
- Dual Export: MIDI files or direct WAV synthesis
Installation
pip install flexinfer-chiptune
Or with uv:
uv add flexinfer-chiptune
For audio playback support:
pip install flexinfer-chiptune[audio]
Quick Start
Command Line Interface
# Generate a battle theme
chiptune generate --preset battle --output battle.wav
# Generate with custom settings
chiptune generate --preset overworld --root G --bpm 130 --bars 16 --effects space
# Generate a sound effect
chiptune sfx coin --output coin.mid
# List all available presets
chiptune list all
Using Genre Presets
from chiptune.presets import GenrePresets, QuickCompose
# One-liner battle track with drums
composer = QuickCompose.battle_track(length_bars=16)
track = composer.build()
# Pre-configured genre composers
battle = GenrePresets.battle_theme() # A minor, 165 BPM
overworld = GenrePresets.overworld() # C major, 120 BPM
dungeon = GenrePresets.dungeon() # E dorian, 85 BPM
title = GenrePresets.title_screen() # F major, 130 BPM
chase = GenrePresets.chase_scene() # E phrygian, 185 BPM
Using the Composer API
from chiptune import ChiptuneComposer, AudioExporter
from chiptune.presets import EffectPresets
# Create a heroic battle theme
composer = ChiptuneComposer.create(bpm=150, root="A", mode="minor")
composer.set_progression(["i", "VII", "VI", "V"])
composer.add_melody(length_bars=8, contour="ascending")
composer.add_countermelody(motion="contrary")
composer.add_bass(style="octave")
composer.add_drums(pattern="driving")
# Build and export with effects
track = composer.build()
effects = EffectPresets.retro_gaming()
exporter = AudioExporter()
exporter.export_wav(track, "battle_theme.wav", effects=effects)
Audio Effects
from chiptune.output.audio.effects import (
Tremolo, Vibrato, Echo, TapeDelay, Chorus, EffectChain
)
# Individual effects
tremolo = Tremolo(rate=5.0, depth=0.3)
echo = Echo(delay_time=0.25, feedback=0.5)
chorus = Chorus.lush()
# Chain effects together
chain = EffectChain(effects=[
Tremolo.subtle(),
Chorus.classic(),
Echo.medium(),
])
# Or use the | operator
chain = Tremolo() | Chorus.subtle() | Echo.short()
# Apply to audio
output = chain.process(samples, sample_rate=44100)
Effect Presets
from chiptune.presets import EffectPresets
# Pre-built effect chains
clean = EffectPresets.clean() # No effects
retro = EffectPresets.retro_gaming() # Subtle chorus + echo
space = EffectPresets.space_adventure() # Lush chorus + space delay
lofi = EffectPresets.lo_fi_nostalgia() # Tape delay + tremolo
arcade = EffectPresets.arcade_cabinet() # Chorus + slapback
dreamy = EffectPresets.dreamy() # Heavy modulation effects
dungeon = EffectPresets.dungeon_reverb() # Cavernous echo
boss = EffectPresets.boss_battle() # Punchy minimal effects
Procedural Melody Generation
from chiptune.generation import (
MarkovMelodyGenerator, MelodyStyle,
BassGenerator, CountermelodyGenerator,
IntensityProfile, IntensityController
)
# Generate melody from Markov chain
gen = MarkovMelodyGenerator(order=2)
gen.train_from_midi_pitches([60, 62, 64, 65, 67, 65, 64, 62, 60])
notes = gen.generate(16, start_pitch=60)
# Use style presets
heroic = MelodyStyle.heroic()
mysterious = MelodyStyle.mysterious()
chiptune = MelodyStyle.chiptune()
# Auto-generate bass lines
bass_gen = BassGenerator.jazz()
bass_notes = bass_gen.generate(chords, beats_per_chord=4)
# Generate countermelody
counter_gen = CountermelodyGenerator.contrary()
counter = counter_gen.generate(melody, scale=scale)
Adaptive Intensity
from chiptune.generation import IntensityProfile, IntensityController
# Intensity profiles for different game states
calm = IntensityProfile.calm() # Low, steady
building = IntensityProfile.building() # Gradually increasing
battle = IntensityProfile.battle() # High, volatile
boss = IntensityProfile.boss_fight() # Maximum intensity
# Controller maps intensity to musical parameters
controller = IntensityController.action()
tempo = controller.get_tempo(progress=0.5) # 80-160 BPM
velocity = controller.get_velocity(progress=0.5) # 60-120
layers = controller.get_active_layers(0.5, total_layers=4)
Chip Systems
from chiptune.chip.systems import NES2A03, GameBoyChip, SIDChip, GenesisChip
# NES 2A03 (2 pulse + triangle + noise)
nes = NES2A03.create()
nes_fami = NES2A03.famitracker_style()
# Game Boy DMG
gameboy = GameBoyChip.create()
# Commodore 64 SID
sid = SIDChip.create()
# Sega Genesis YM2612 (FM synthesis)
genesis = GenesisChip.create()
Sound Effects
from chiptune import SFXGenerator
sfx = SFXGenerator()
# Generate common game sounds (returns MIDI bytes)
coin = sfx.coin_collect()
jump = sfx.jump()
explosion = sfx.explosion()
powerup = sfx.powerup()
laser = sfx.laser()
teleport = sfx.teleport()
door_open = sfx.door_open()
menu_select = sfx.menu_select()
# Save to file
sfx.save(coin, "coin.mid")
Jingles
from chiptune import Jingle
# Quick musical phrases
victory = Jingle.victory_fanfare(root="C", tempo=140)
item = Jingle.item_get(root="G")
level_up = Jingle.level_up()
game_over = Jingle.game_over()
Agent API
from chiptune import MusicAgent
agent = MusicAgent()
# Generate music from natural language context
music = agent.compose_for_context(
context="player enters the boss arena",
duration_seconds=30.0,
intensity=0.9,
)
# Generate a sound effect
sfx = agent.generate_sfx("coin_collect")
CLI Reference
chiptune generate [options]
--preset, -p Genre preset: battle, overworld, dungeon, victory,
title, shop, sad, chase (default: overworld)
--output, -o Output file path (default: output.wav)
--bars, -b Length in bars (default: 8)
--root, -r Root note (C, D, E, F, G, A, B with optional #/b)
--bpm Tempo in BPM (overrides preset default)
--effects, -e Effect preset: clean, retro, space, lofi, arcade,
dreamy, dungeon, boss (default: retro)
--format, -f Output format: wav, midi (default: wav)
--no-drums Exclude drums
--no-bass Exclude bass
--no-counter Exclude countermelody
--seed, -s Random seed for reproducibility
chiptune sfx <type> [options]
type Effect type: jump, land, coin, powerup, damage,
explosion, laser, shield, teleport, menu_select,
menu_confirm, menu_back, success, error,
door_open, door_close, heartbeat, countdown
--output, -o Output file path (default: sfx.mid)
chiptune list [category]
category What to list: presets, effects, sfx, all (default: all)
Semantic Mappings
Emotions to Musical Elements
| Emotion | Scale/Mode | Tempo | Character |
|---|---|---|---|
| Heroic | Major/Lydian | Fast | Driving, 4ths/5ths |
| Mysterious | Dorian | Medium | Syncopated |
| Danger | Phrygian/Locrian | Fast | Urgent, chromatic |
| Peaceful | Pentatonic | Slow | Flowing, 3rds/6ths |
| Sad | Minor/Aeolian | Slow | Simple, minor 3rds |
Game Contexts to Themes
| Context | Characteristics |
|---|---|
| Battle | Fast, minor, syncopated, driving drums |
| Boss | Epic, chromatic, heavy bass, intense |
| Victory | Major fanfare, I-IV-V-I, triumphant |
| Overworld | Adventurous, major, walking bass |
| Dungeon | Modal, sparse, atmospheric |
| Shop | Relaxed, major, simple rhythm |
| Chase | Very fast, phrygian, urgent |
Development
# Clone the repository
git clone https://gitlab.flexinfer.ai/libs/py-chiptune.git
cd py-chiptune
# Install dependencies
uv sync
# Run tests
uv run pytest
# Type checking
uv run mypy src/chiptune
# Linting
uv run ruff check src/chiptune
License
MIT License
Metadata
Release files for flexinfer-chiptune 0.5.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flexinfer_chiptune-0.5.2-py3-none-any.whl | Python 3 | none | any | Details |
Release files / flexinfer_chiptune-0.5.2-py3-none-any.whl
| Download URL | flexinfer_chiptune-0.5.2-py3-none-any.whl |
|---|---|
| Size | 113.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a136383e009d5e35d4be9abf00b846d644edd9ffc96e497aaf5b87acc35466e7
|
|
BLAKE2b-256 checksum How to use checksums |
5c1ee28438c89a74aba4d136556ea259fd54f4e19feb5a26fc3653478f087b52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Security for flexinfer-chiptune 0.5.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.