Back to Projects

Carnatic AI Music Generator

Full-stack AI-powered Carnatic music composition tool. FastAPI backend with raga definitions (Shankarabharanam, Kalyani, Mohanam, Hamsadhwani), swara-to-MIDI mapping, melody generator, 10 preset tunes, and MIDI file construction (mido).

Python 3.11FastAPImidoReact 18Vite 5Tone.jspytestGitHub ActionsDocker ComposeMakefile

Role

Full-stack Developer

Team

Solo

Company/Organization

Personal Project

The Problem

Carnatic classical music has rich melodic frameworks (ragas) but no accessible browser-based tooling for generating raga-compliant melodies...

Musicians and learners had no way to quickly generate, hear, and download raga-based melodies with different instruments and tempos without...

Tone.js browser synthesis required distinct synth architectures per instrument to capture the characteristic timbre of classical Indian instruments...

Preset tunes like Jana Gana Mana and Vande Mataram needed to be encoded as note sequences with correct swaras, durations, and timingno existing...

MIDI generation from raga note sequences required mapping Carnatic swara names to MIDI note numbers and constructing valid MIDI tracks with tempo,...

The Solution

Built a clean full-stack architecture separating raga/instrument definitions, melody generation, MIDI construction, presets, and API routing into...

Backend (Python 3.11 + FastAPI)

ragas.py — Defines 4 Carnatic ragas as swara (note name) sequences with octave and scale degree mappings. Shankarabharanam (equivalent to major...

instruments.py — Maps 5 instruments to MIDI program numbers: Veena (24 — Acoustic Guitar pluck approximation), Violin (40 — Violin), Flute (73 —...

generator.py — Melody generation service: takes raga name, instrument, tempo (BPM), and note length as inputs. Randomly samples notes from the...

midi_utils.py — MIDI file construction via mido: creates MidiFile with MetaMessage (tempo, time signature), adds NoteOn/NoteOff events for each...

presets.py — 10 hardcoded preset tunes encoded as note sequences: Happy Birthday, Twinkle Twinkle, Ode to Joy, Jana Gana Mana, Vande Mataram,...

main.py — FastAPI app with 7 endpoints: GET / (health), GET /ragas, GET /instruments, GET /presets, GET /presets/{id}, GET /download/{file}, POST...

Frontend (React 18 + Vite 5 + Tone.js)

App.jsx — Tab-based UI with two modes: Raga Generator (select raga, instrument, tempo, length → generate → play/download) and Preset Tunes...

Player.jsx — Tone.js playback component. Instrument-specific synth initialisation:

Veena: Tone.PluckSynth (karplus-strong string model, natural decay)

Violin: Tone.FMSynth (frequency modulation for bowed string harmonics)

Flute: Tone.FMSynth with high modulation index for breathy overtones

Piano: Tone.FMSynth with low modulation for percussive attack

Mridangam: Tone.MembraneSynth (membrane percussion model)

Schedules notes via Tone.Transport, tracks active note index for highlighting, renders progress bar with elapsed/total time.

api.js — Axios-based API client, reads VITE_API_URL from environment variables (localhost:8000 in dev, production URL in build). Typed...

Testing (36 pytest tests)

ragas.py: Valid swara sequences for each raga, aroha/avaroha completeness, swara-to-MIDI mapping correctness

instruments.py: MIDI program numbers, channel assignments, drum channel validation

presets.py: All 10 presets load, note sequences non-empty, required fields present

midi_utils.py: MIDI file construction produces valid .mid files, note events present, tempo set correctly

generator.py: Output length matches requested note count, all notes belong to specified raga's swara set

main.py (API routes): All 7 endpoints return correct status codes and response shapes

CI/CD (GitHub Actions)

Backend job: Python 3.11, install requirements.txt, run pytest (36 tests)

Frontend job: Node 20, npm install, npm run build (Vite production build check)

Runs on every push and PR to main

Design Decisions

Separated raga definitions (ragas.py), instrument mappings (instruments.py), melody generation (generator.py), MIDI construction (midi_utils.py), and...

Tone.js with instrument-specific synth architectures (PluckSynth for Veena, MembraneSynth for Mridangam, FMSynth variants for Violin/Flute/Piano)...

mido for MIDI construction over pretty-midi or music21mido is lightweight, pure Python, with no native dependencies. pretty-midi requires numpy...

Hardcoded preset note sequences over MIDI file parsingencoding presets as Python note lists keeps them version-controlled, readable, and editable...

FastAPI over Flask/Django for the backendFastAPI's automatic OpenAPI docs (/docs) are valuable for exploring the 7 endpoints during development,...

Generated MIDI files stored in generated/ (gitignored) and auto-cleaned after downloadavoids unbounded disk growth in production without requiring...

Docker Compose with separate backend and frontend containers behind a shared networkallows independent service restarts, local development...

GitHub Actions with separate backend (Python 3.11 + pytest) and frontend (Node 20 + Vite build) jobsparallel execution, clear failure attribution...

Tradeoffs & Constraints

Melody generation is rule-based (random weighted sampling from raga swara sets) rather than ML-basedproduces valid raga-compliant melodies but...

Tone.js synths approximate instrument timbres in the browser but are not sample-basedPluckSynth for Veena uses karplus-strong synthesis which...

MIDI download is the primary output formatMIDI requires a player or DAW to hear. WAV/MP3 export would make compositions immediately listenable...

Presets are hardcoded in presets.pyadding new tunes requires a code change and redeploy. A database-backed preset system would allow adding tunes...

No tala (rhythm cycle) supportmelodies are generated without rhythmic structure beyond note duration. Full Carnatic composition requires...

Would improve: Add Markov chain or LSTM-based melody generation for musically coherent phrases, implement tala (rhythm cycle) support, add sampled...

Outcome & Impact

Full-stack Carnatic music generation platform with raga generator (4 ragas, 5 instruments, configurable tempo and length), 10 preset tunes, Tone.js...

Backend defines 4 Carnatic ragas (Shankarabharanam, Kalyani, Mohanam, Hamsadhwani) as swara sequences with instrument-to-MIDI program mappings...

Tone.js playback uses instrument-specific synth architectures: PluckSynth (Veena), FMSynth (Violin, Flute, Piano), MembraneSynth (Mridangam)...

10 preset tunes encoded as structured note sequences: Happy Birthday, Twinkle Twinkle, Ode to Joy, Jana Gana Mana, Vande Mataram, Saare Jahan Se...

7 FastAPI REST endpoints: health check, raga list, instrument list, preset list, preset detail, MIDI file download, and POST /generate for raga-based...

36 pytest tests cover all backend modules: raga/swara validation, MIDI program mappings, preset completeness, MIDI file construction correctness,...

GitHub Actions CI/CD runs backend pytest (Python 3.11) and frontend Vite production build (Node 20) on every push and PR to main. Docker Compose...

Tech Stack

Backend: Python 3.11, FastAPI, Uvicorn

Music: mido (MIDI file construction), custom raga/swara definitions

Frontend: React 18, Vite 5, Tone.js (PluckSynth, FMSynth, MembraneSynth)

API Client: Axios (env-aware VITE_API_URL)

Testing: pytest (36 testsragas, instruments, presets, MIDI utils, generator, API routes)

CI/CD: GitHub Actions (Python 3.11 backend + Node 20 frontend jobs)

Infrastructure: Docker, Docker Compose

Automation: Makefile (install, run, stop, test, clean)

Back to Projects