@mcptoolshop/ai_jam_session 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.es.md +212 -0
- package/README.fr.md +212 -0
- package/README.hi.md +212 -0
- package/README.it.md +212 -0
- package/README.ja.md +214 -0
- package/README.md +214 -0
- package/README.pt-BR.md +212 -0
- package/dist/audio-engine.d.ts +9 -0
- package/dist/audio-engine.d.ts.map +1 -0
- package/dist/audio-engine.js +422 -0
- package/dist/audio-engine.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +551 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +903 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/midi/parser.d.ts +16 -0
- package/dist/midi/parser.d.ts.map +1 -0
- package/dist/midi/parser.js +192 -0
- package/dist/midi/parser.js.map +1 -0
- package/dist/midi/types.d.ts +44 -0
- package/dist/midi/types.d.ts.map +1 -0
- package/dist/midi/types.js +8 -0
- package/dist/midi/types.js.map +1 -0
- package/dist/note-parser.d.ts +105 -0
- package/dist/note-parser.d.ts.map +1 -0
- package/dist/note-parser.js +278 -0
- package/dist/note-parser.js.map +1 -0
- package/dist/playback/controls.d.ts +124 -0
- package/dist/playback/controls.d.ts.map +1 -0
- package/dist/playback/controls.js +252 -0
- package/dist/playback/controls.js.map +1 -0
- package/dist/playback/midi-engine.d.ts +68 -0
- package/dist/playback/midi-engine.d.ts.map +1 -0
- package/dist/playback/midi-engine.js +227 -0
- package/dist/playback/midi-engine.js.map +1 -0
- package/dist/playback/position.d.ts +95 -0
- package/dist/playback/position.d.ts.map +1 -0
- package/dist/playback/position.js +223 -0
- package/dist/playback/position.js.map +1 -0
- package/dist/playback/timing.d.ts +31 -0
- package/dist/playback/timing.d.ts.map +1 -0
- package/dist/playback/timing.js +57 -0
- package/dist/playback/timing.js.map +1 -0
- package/dist/sample-engine.d.ts +17 -0
- package/dist/sample-engine.d.ts.map +1 -0
- package/dist/sample-engine.js +428 -0
- package/dist/sample-engine.js.map +1 -0
- package/dist/schemas.d.ts +40 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +42 -0
- package/dist/schemas.js.map +1 -0
- package/dist/session.d.ts +106 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +361 -0
- package/dist/session.js.map +1 -0
- package/dist/sfz-parser.d.ts +36 -0
- package/dist/sfz-parser.d.ts.map +1 -0
- package/dist/sfz-parser.js +95 -0
- package/dist/sfz-parser.js.map +1 -0
- package/dist/smoke.d.ts +2 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +512 -0
- package/dist/smoke.js.map +1 -0
- package/dist/songs/config/loader.d.ts +14 -0
- package/dist/songs/config/loader.d.ts.map +1 -0
- package/dist/songs/config/loader.js +53 -0
- package/dist/songs/config/loader.js.map +1 -0
- package/dist/songs/config/schema.d.ts +70 -0
- package/dist/songs/config/schema.d.ts.map +1 -0
- package/dist/songs/config/schema.js +53 -0
- package/dist/songs/config/schema.js.map +1 -0
- package/dist/songs/index.d.ts +16 -0
- package/dist/songs/index.d.ts.map +1 -0
- package/dist/songs/index.js +20 -0
- package/dist/songs/index.js.map +1 -0
- package/dist/songs/jam.d.ts +48 -0
- package/dist/songs/jam.d.ts.map +1 -0
- package/dist/songs/jam.js +324 -0
- package/dist/songs/jam.js.map +1 -0
- package/dist/songs/loader.d.ts +27 -0
- package/dist/songs/loader.d.ts.map +1 -0
- package/dist/songs/loader.js +90 -0
- package/dist/songs/loader.js.map +1 -0
- package/dist/songs/midi/hands.d.ts +46 -0
- package/dist/songs/midi/hands.d.ts.map +1 -0
- package/dist/songs/midi/hands.js +134 -0
- package/dist/songs/midi/hands.js.map +1 -0
- package/dist/songs/midi/ingest.d.ts +8 -0
- package/dist/songs/midi/ingest.d.ts.map +1 -0
- package/dist/songs/midi/ingest.js +191 -0
- package/dist/songs/midi/ingest.js.map +1 -0
- package/dist/songs/midi/measures.d.ts +41 -0
- package/dist/songs/midi/measures.d.ts.map +1 -0
- package/dist/songs/midi/measures.js +64 -0
- package/dist/songs/midi/measures.js.map +1 -0
- package/dist/songs/midi/types.d.ts +25 -0
- package/dist/songs/midi/types.d.ts.map +1 -0
- package/dist/songs/midi/types.js +8 -0
- package/dist/songs/midi/types.js.map +1 -0
- package/dist/songs/registry.d.ts +37 -0
- package/dist/songs/registry.d.ts.map +1 -0
- package/dist/songs/registry.js +197 -0
- package/dist/songs/registry.js.map +1 -0
- package/dist/songs/types.d.ts +99 -0
- package/dist/songs/types.d.ts.map +1 -0
- package/dist/songs/types.js +27 -0
- package/dist/songs/types.js.map +1 -0
- package/dist/teaching/live-midi-feedback.d.ts +36 -0
- package/dist/teaching/live-midi-feedback.d.ts.map +1 -0
- package/dist/teaching/live-midi-feedback.js +259 -0
- package/dist/teaching/live-midi-feedback.js.map +1 -0
- package/dist/teaching/midi-feedback.d.ts +33 -0
- package/dist/teaching/midi-feedback.d.ts.map +1 -0
- package/dist/teaching/midi-feedback.js +208 -0
- package/dist/teaching/midi-feedback.js.map +1 -0
- package/dist/teaching/sing-on-midi.d.ts +77 -0
- package/dist/teaching/sing-on-midi.d.ts.map +1 -0
- package/dist/teaching/sing-on-midi.js +186 -0
- package/dist/teaching/sing-on-midi.js.map +1 -0
- package/dist/teaching.d.ts +148 -0
- package/dist/teaching.d.ts.map +1 -0
- package/dist/teaching.js +453 -0
- package/dist/teaching.js.map +1 -0
- package/dist/test-sound.d.ts +3 -0
- package/dist/test-sound.d.ts.map +1 -0
- package/dist/test-sound.js +41 -0
- package/dist/test-sound.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/vmpk.d.ts +23 -0
- package/dist/vmpk.d.ts.map +1 -0
- package/dist/vmpk.js +236 -0
- package/dist/vmpk.js.map +1 -0
- package/logo.png +0 -0
- package/package.json +70 -0
- package/songs/builtin/a-change-is-gonna-come.json +95 -0
- package/songs/builtin/a-thousand-years.json +93 -0
- package/songs/builtin/aint-no-sunshine.json +98 -0
- package/songs/builtin/all-blues.json +92 -0
- package/songs/builtin/autumn-leaves.json +100 -0
- package/songs/builtin/baba-oriley.json +91 -0
- package/songs/builtin/bach-invention-no1.json +70 -0
- package/songs/builtin/bach-prelude-c-major-bwv846.json +1282 -0
- package/songs/builtin/basic-12-bar-blues.json +119 -0
- package/songs/builtin/beethoven-waldstein-mvt1.json +7766 -0
- package/songs/builtin/bennie-and-the-jets.json +92 -0
- package/songs/builtin/besame-mucho.json +93 -0
- package/songs/builtin/black-orpheus.json +92 -0
- package/songs/builtin/blue-bossa.json +94 -0
- package/songs/builtin/blues-in-g.json +92 -0
- package/songs/builtin/bohemian-rhapsody-intro.json +94 -0
- package/songs/builtin/boogie-woogie-basics.json +93 -0
- package/songs/builtin/bossa-nova-basic.json +95 -0
- package/songs/builtin/chopin-nocturne-op9-no2.json +70 -0
- package/songs/builtin/cinema-paradiso.json +94 -0
- package/songs/builtin/clair-de-lune.json +11511 -0
- package/songs/builtin/clocks.json +91 -0
- package/songs/builtin/crystal-stream.json +70 -0
- package/songs/builtin/desafinado.json +93 -0
- package/songs/builtin/dont-stop-believin.json +91 -0
- package/songs/builtin/dream-on.json +100 -0
- package/songs/builtin/easy-winners.json +70 -0
- package/songs/builtin/el-condor-pasa.json +93 -0
- package/songs/builtin/elite-syncopations.json +70 -0
- package/songs/builtin/evening-calm.json +70 -0
- package/songs/builtin/everyday-blues.json +93 -0
- package/songs/builtin/fly-me-to-the-moon.json +91 -0
- package/songs/builtin/forrest-gump-suite.json +93 -0
- package/songs/builtin/fur-elise.json +20094 -0
- package/songs/builtin/georgia-on-my-mind.json +93 -0
- package/songs/builtin/girl-from-ipanema.json +92 -0
- package/songs/builtin/gladiolus-rag.json +70 -0
- package/songs/builtin/great-balls-of-fire.json +92 -0
- package/songs/builtin/guantanamera.json +92 -0
- package/songs/builtin/hallelujah.json +92 -0
- package/songs/builtin/hedwigs-theme.json +93 -0
- package/songs/builtin/hotel-california.json +92 -0
- package/songs/builtin/imagine.json +92 -0
- package/songs/builtin/just-the-two-of-us.json +92 -0
- package/songs/builtin/la-bamba.json +92 -0
- package/songs/builtin/layla-piano-coda.json +93 -0
- package/songs/builtin/lean-on-me.json +91 -0
- package/songs/builtin/let-it-be.json +101 -0
- package/songs/builtin/lets-stay-together.json +93 -0
- package/songs/builtin/magnetic-rag.json +70 -0
- package/songs/builtin/maple-leaf-rag.json +99 -0
- package/songs/builtin/mia-and-sebastians-theme.json +93 -0
- package/songs/builtin/minor-blues-in-a.json +94 -0
- package/songs/builtin/misty.json +94 -0
- package/songs/builtin/moon-river.json +93 -0
- package/songs/builtin/moonlight-sonata-mvt1.json +101 -0
- package/songs/builtin/morning-light.json +70 -0
- package/songs/builtin/mountain-dawn.json +70 -0
- package/songs/builtin/mozart-k545-mvt1.json +2956 -0
- package/songs/builtin/my-girl.json +92 -0
- package/songs/builtin/night-train.json +92 -0
- package/songs/builtin/november-rain.json +93 -0
- package/songs/builtin/ocean-waves.json +70 -0
- package/songs/builtin/over-the-rainbow.json +93 -0
- package/songs/builtin/oye-como-va.json +93 -0
- package/songs/builtin/peacherine-rag.json +70 -0
- package/songs/builtin/piano-man.json +92 -0
- package/songs/builtin/pineapple-rag.json +70 -0
- package/songs/builtin/pink-panther.json +94 -0
- package/songs/builtin/ragtime-dance.json +70 -0
- package/songs/builtin/river-flows-in-you.json +102 -0
- package/songs/builtin/rocket-man.json +92 -0
- package/songs/builtin/satie-gymnopedie-no1.json +70 -0
- package/songs/builtin/satin-doll.json +93 -0
- package/songs/builtin/schindlers-list.json +96 -0
- package/songs/builtin/schumann-traumerei.json +70 -0
- package/songs/builtin/sitting-on-the-dock.json +91 -0
- package/songs/builtin/slow-blues-in-bb.json +98 -0
- package/songs/builtin/snowfall.json +70 -0
- package/songs/builtin/so-what.json +92 -0
- package/songs/builtin/solace.json +70 -0
- package/songs/builtin/someone-like-you.json +92 -0
- package/songs/builtin/spirited-away.json +94 -0
- package/songs/builtin/st-louis-blues.json +93 -0
- package/songs/builtin/stairway-intro.json +93 -0
- package/songs/builtin/starlight-waltz.json +70 -0
- package/songs/builtin/stay-with-me.json +93 -0
- package/songs/builtin/stormy-monday.json +94 -0
- package/songs/builtin/superstition.json +93 -0
- package/songs/builtin/sweet-home-chicago.json +93 -0
- package/songs/builtin/take-five.json +92 -0
- package/songs/builtin/take-the-a-train.json +93 -0
- package/songs/builtin/the-entertainer.json +98 -0
- package/songs/builtin/the-godfather-waltz.json +93 -0
- package/songs/builtin/thrill-is-gone.json +94 -0
- package/songs/builtin/twilight-garden.json +70 -0
- package/songs/builtin/watermark.json +70 -0
- package/songs/builtin/wave.json +93 -0
- package/songs/builtin/whats-going-on.json +93 -0
- package/songs/builtin/yesterday.json +92 -0
package/README.pt-BR.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
<p align="center"><a href="README.md">English</a> | <a href="README.ja.md">日本語</a> | <a href="README.es.md">Español</a> | <a href="README.fr.md">Français</a> | <a href="README.hi.md">हिन्दी</a> | <a href="README.it.md">Italiano</a> | <strong>Português</strong></p>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="logo.png" alt="Logo do PianoAI" width="180" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<h1 align="center">PianoAI</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
Piano com IA com motor de audio integrado e biblioteca de 100 musicas. Servidor MCP para o Claude, CLI para humanos.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
[](https://github.com/mcp-tool-shop-org/ai_jam_session)
|
|
14
|
+
[](https://github.com/mcp-tool-shop-org/ai_jam_session)
|
|
15
|
+
[](https://github.com/mcp-tool-shop-org/ai_jam_session)
|
|
16
|
+
|
|
17
|
+
## O que e isto?
|
|
18
|
+
|
|
19
|
+
Um piano que o Claude consegue tocar. PianoAI e um servidor MCP com motor de audio integrado — toca diretamente pelas suas caixas de som, sem necessidade de software externo. O Claude navega por uma biblioteca de 100 musicas em 10 generos, escolhe musicas, ensina e improvisa sobre elas. Tambem funciona como CLI independente.
|
|
20
|
+
|
|
21
|
+
## Funcionalidades
|
|
22
|
+
|
|
23
|
+
- **Motor de piano integrado** — audio baseado em amostras via `node-web-audio-api`, toca pelas caixas de som
|
|
24
|
+
- **Biblioteca de 100 musicas** — classico, jazz, pop, blues, rock, R&B, latin, cinema, ragtime, new-age
|
|
25
|
+
- **AI Jam Session** — o Claude analisa os acordes e a melodia de uma musica e cria a sua propria interpretacao
|
|
26
|
+
- **Suporte a arquivos MIDI** — toque qualquer arquivo `.mid`: `pianoai play song.mid`
|
|
27
|
+
- **Sistema de ensino** — notas de ensino por compasso, descricoes em linguagem musical, recomendacoes de pratica
|
|
28
|
+
- **4 modos de reproducao** — completo, compasso a compasso, maos separadas, loop
|
|
29
|
+
- **Controle de velocidade** — 0.5x para pratica lenta ate 4x rapido
|
|
30
|
+
- **Controles em tempo real** — pausar, retomar, alterar velocidade durante a reproducao
|
|
31
|
+
- **15 ferramentas MCP** — tocar, navegar, ensinar, improvisar, importar — tudo pelo protocolo MCP
|
|
32
|
+
- **Adicione suas proprias musicas** — a ferramenta `add_song` aceita JSON SongEntry, `import_midi` converte arquivos MIDI
|
|
33
|
+
- **Saida MIDI opcional** — encaminhe para software externo via flag `--midi` (requer loopMIDI + VMPK)
|
|
34
|
+
|
|
35
|
+
## Instalacao
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install -g @mcptoolshop/ai_jam_session
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requer **Node.js 18+**. So isso — sem drivers MIDI, sem portas virtuais, sem software externo.
|
|
42
|
+
|
|
43
|
+
## Inicio Rapido
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Tocar uma musica da biblioteca
|
|
47
|
+
ai-jam-session play let-it-be
|
|
48
|
+
|
|
49
|
+
# Tocar um arquivo MIDI
|
|
50
|
+
ai-jam-session play path/to/song.mid
|
|
51
|
+
|
|
52
|
+
# Pratica em meia velocidade
|
|
53
|
+
ai-jam-session play moonlight-sonata-mvt1 --speed 0.5
|
|
54
|
+
|
|
55
|
+
# Listar todas as musicas da biblioteca
|
|
56
|
+
ai-jam-session list
|
|
57
|
+
|
|
58
|
+
# Mostrar detalhes da musica + notas de ensino
|
|
59
|
+
ai-jam-session info autumn-leaves
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Opcoes de Reproducao
|
|
63
|
+
|
|
64
|
+
| Flag | Descricao |
|
|
65
|
+
|------|-----------|
|
|
66
|
+
| `--speed <mult>` | Multiplicador de velocidade: 0.5 = metade, 1.0 = normal, 2.0 = dobro |
|
|
67
|
+
| `--tempo <bpm>` | Substituir o andamento padrao da musica (10-400 BPM) |
|
|
68
|
+
| `--mode <mode>` | Modo de reproducao: `full`, `measure`, `hands`, `loop` |
|
|
69
|
+
| `--midi` | Encaminhar para software MIDI externo em vez do motor integrado |
|
|
70
|
+
|
|
71
|
+
## Servidor MCP
|
|
72
|
+
|
|
73
|
+
O servidor MCP disponibiliza 15 ferramentas para integracao com LLMs:
|
|
74
|
+
|
|
75
|
+
| Ferramenta | Descricao |
|
|
76
|
+
|------------|-----------|
|
|
77
|
+
| `list_songs` | Navegar/buscar musicas por genero, dificuldade ou consulta |
|
|
78
|
+
| `song_info` | Linguagem musical completa, objetivos de ensino, sugestoes de pratica |
|
|
79
|
+
| `registry_stats` | Contagem de musicas por genero e dificuldade |
|
|
80
|
+
| `teaching_note` | Nota de ensino por compasso, dedilhado, dinamica |
|
|
81
|
+
| `suggest_song` | Recomendacao baseada em criterios |
|
|
82
|
+
| `list_measures` | Visao geral dos compassos com notas de ensino |
|
|
83
|
+
| `practice_setup` | Sugerir velocidade, modo e configuracoes para uma musica |
|
|
84
|
+
| `sing_along` | Texto cantavel (nomes de notas, solfejo, contorno) por compasso |
|
|
85
|
+
| `play_song` | Tocar uma musica ou arquivo MIDI pelas caixas de som |
|
|
86
|
+
| `pause_playback` | Pausar ou retomar a musica em reproducao |
|
|
87
|
+
| `set_speed` | Alterar a velocidade durante a reproducao |
|
|
88
|
+
| `stop_playback` | Parar a musica em reproducao |
|
|
89
|
+
| `ai_jam_session` | Obter um resumo para jam — acordes, melodia, orientacao de estilo — para improvisacao |
|
|
90
|
+
| `add_song` | Adicionar uma nova musica (JSON SongEntry) a biblioteca |
|
|
91
|
+
| `import_midi` | Converter um arquivo MIDI em SongEntry e registra-lo |
|
|
92
|
+
|
|
93
|
+
### AI Jam Session
|
|
94
|
+
|
|
95
|
+
A ferramenta `ai_jam_session` extrai um "resumo de jam" estruturado de qualquer musica: progressao de acordes, contorno melodico e orientacao de estilo especifica do genero. O Claude usa o resumo para criar a sua propria interpretacao.
|
|
96
|
+
|
|
97
|
+
Dois modos:
|
|
98
|
+
- **Musica especifica:** `ai_jam_session({ songId: "autumn-leaves", style: "blues" })` — improvisar sobre Autumn Leaves, estilo blues
|
|
99
|
+
- **Escolha aleatoria por genero:** `ai_jam_session({ genre: "jazz" })` — escolher uma musica de jazz aleatoria e improvisar
|
|
100
|
+
|
|
101
|
+
Parametros opcionais: `mood` (animado, melancolico, sonhador, etc.), `difficulty`, `measures` (intervalo como "1-8").
|
|
102
|
+
|
|
103
|
+
### Configuracao Claude Desktop / Claude Code
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"mcpServers": {
|
|
108
|
+
"pianoai": {
|
|
109
|
+
"command": "npx",
|
|
110
|
+
"args": ["-y", "-p", "@mcptoolshop/ai_jam_session", "ai-jam-session-mcp"]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Plugin para Claude Code
|
|
117
|
+
|
|
118
|
+
O PianoAI inclui um plugin para Claude Code que adiciona comandos de barra e personalidades de agente:
|
|
119
|
+
|
|
120
|
+
| Comando | Descricao |
|
|
121
|
+
|---------|-----------|
|
|
122
|
+
| `/pianoai:teach <song>` | Iniciar uma sessao de ensino estruturada |
|
|
123
|
+
| `/pianoai:practice <song>` | Obter um plano de pratica com recomendacoes de velocidade/modo |
|
|
124
|
+
| `/pianoai:explore [query]` | Navegar pela biblioteca de musicas por genero, dificuldade ou palavra-chave |
|
|
125
|
+
| `/pianoai:jam <song or genre>` | Iniciar uma sessao de jam — o Claude cria a sua propria interpretacao |
|
|
126
|
+
|
|
127
|
+
Duas personalidades de agente:
|
|
128
|
+
- **Professor de Piano** — paciente, pedagogico, encontra o aluno no nivel em que ele esta
|
|
129
|
+
- **Musico de Jam** — clima descontraido de jam band, groove em primeiro lugar, incentiva a experimentacao
|
|
130
|
+
|
|
131
|
+
## Biblioteca de Musicas
|
|
132
|
+
|
|
133
|
+
100 musicas integradas em 10 generos, 3 niveis de dificuldade:
|
|
134
|
+
|
|
135
|
+
| Genero | Musicas | Exemplos |
|
|
136
|
+
|--------|---------|----------|
|
|
137
|
+
| Classico | 10 | Fur Elise, Clair de Lune, Moonlight Sonata, Bach Prelude in C |
|
|
138
|
+
| Jazz | 10 | Autumn Leaves, Take Five, So What, Misty |
|
|
139
|
+
| Pop | 10 | Imagine, Hallelujah, Piano Man, Bohemian Rhapsody |
|
|
140
|
+
| Blues | 10 | Basic 12-Bar, St. Louis Blues, Stormy Monday, Thrill Is Gone |
|
|
141
|
+
| Rock | 10 | Stairway Intro, Hotel California, Rocket Man, Layla Coda |
|
|
142
|
+
| R&B | 10 | Superstition, Georgia On My Mind, Lean On Me, My Girl |
|
|
143
|
+
| Latin | 10 | Girl from Ipanema, Besame Mucho, Oye Como Va, Wave |
|
|
144
|
+
| Cinema | 11 | Cinema Paradiso, Moon River, Hedwig's Theme, Spirited Away |
|
|
145
|
+
| Ragtime | 9 | The Entertainer, Maple Leaf Rag, Elite Syncopations |
|
|
146
|
+
| New-Age | 10 | River Flows in You, Snowfall, Crystal Stream, Evening Calm |
|
|
147
|
+
|
|
148
|
+
## API Programatica
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { createAudioEngine, parseMidiFile, PlaybackController } from "@mcptoolshop/ai_jam_session";
|
|
152
|
+
|
|
153
|
+
const connector = createAudioEngine();
|
|
154
|
+
await connector.connect();
|
|
155
|
+
|
|
156
|
+
const midi = await parseMidiFile("song.mid");
|
|
157
|
+
const controller = new PlaybackController(connector, midi);
|
|
158
|
+
|
|
159
|
+
controller.on("noteOn", (e) => console.log(`Note: ${e.noteName}`));
|
|
160
|
+
await controller.play({ speed: 0.75 });
|
|
161
|
+
|
|
162
|
+
controller.pause();
|
|
163
|
+
controller.setSpeed(1.5);
|
|
164
|
+
await controller.resume();
|
|
165
|
+
|
|
166
|
+
await connector.disconnect();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Tocar uma musica da biblioteca
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { getSong, createSession, createAudioEngine } from "@mcptoolshop/ai_jam_session";
|
|
173
|
+
|
|
174
|
+
const connector = createAudioEngine();
|
|
175
|
+
await connector.connect();
|
|
176
|
+
|
|
177
|
+
const song = getSong("autumn-leaves")!;
|
|
178
|
+
const session = createSession(song, connector, {
|
|
179
|
+
mode: "full",
|
|
180
|
+
speed: 0.75,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
await session.play();
|
|
184
|
+
await connector.disconnect();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Arquitetura
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
MIDI files (.mid) Built-in song library (JSON)
|
|
191
|
+
| |
|
|
192
|
+
v v
|
|
193
|
+
MIDI Parser ──────────────── Note Parser
|
|
194
|
+
| |
|
|
195
|
+
v v
|
|
196
|
+
MidiPlaybackEngine SessionController
|
|
197
|
+
| |
|
|
198
|
+
└──────── PlaybackController ──┘
|
|
199
|
+
(real-time events, hooks)
|
|
200
|
+
|
|
|
201
|
+
┌─────────────┼─────────────┐
|
|
202
|
+
v v v
|
|
203
|
+
AudioEngine Teaching Hooks Progress
|
|
204
|
+
(speakers) (per-measure) (callbacks)
|
|
205
|
+
|
|
|
206
|
+
v
|
|
207
|
+
node-web-audio-api (Rust DSP)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Licenca
|
|
211
|
+
|
|
212
|
+
MIT
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { VmpkConnector } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create the built-in piano engine.
|
|
4
|
+
*
|
|
5
|
+
* Implements VmpkConnector so it's a drop-in replacement anywhere
|
|
6
|
+
* the codebase uses a connector (sessions, CLI, MCP server).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createAudioEngine(): VmpkConnector;
|
|
9
|
+
//# sourceMappingURL=audio-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-engine.d.ts","sourceRoot":"","sources":["../src/audio-engine.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AAqItE;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAgUjD"}
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
// ─── pianoai: Built-in Piano Engine ──────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Quality multi-harmonic piano synthesis using node-web-audio-api.
|
|
4
|
+
// No external software required — npm install gives you everything.
|
|
5
|
+
//
|
|
6
|
+
// Piano model features:
|
|
7
|
+
// - 12 sine partials per voice with inharmonic frequency stretching
|
|
8
|
+
// - Per-partial amplitude envelopes (higher harmonics decay faster)
|
|
9
|
+
// - Velocity-dependent timbre (harder = brighter, more harmonics)
|
|
10
|
+
// - Hammer noise transient (bandpass-filtered noise burst on attack)
|
|
11
|
+
// - Duplex stringing simulation (subtle random detuning per partial)
|
|
12
|
+
// - Stereo imaging (low notes left, high notes right)
|
|
13
|
+
// - DynamicsCompressor for polyphony safety
|
|
14
|
+
// - 48-voice polyphony with LRU voice stealing
|
|
15
|
+
//
|
|
16
|
+
// Usage:
|
|
17
|
+
// const piano = createAudioEngine();
|
|
18
|
+
// await piano.connect();
|
|
19
|
+
// piano.noteOn(60, 100); // middle C, forte
|
|
20
|
+
// piano.noteOff(60);
|
|
21
|
+
// await piano.disconnect();
|
|
22
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
// ─── Lazy Import ────────────────────────────────────────────────────────────
|
|
24
|
+
// Don't load the native binary until the engine is actually used.
|
|
25
|
+
let _AudioContext = null;
|
|
26
|
+
async function loadAudioContext() {
|
|
27
|
+
if (!_AudioContext) {
|
|
28
|
+
const mod = await import("node-web-audio-api");
|
|
29
|
+
_AudioContext = mod.AudioContext;
|
|
30
|
+
}
|
|
31
|
+
return _AudioContext;
|
|
32
|
+
}
|
|
33
|
+
// ─── Piano Physics ──────────────────────────────────────────────────────────
|
|
34
|
+
/** Max partials per voice (bass notes get all, treble gets fewer). */
|
|
35
|
+
const MAX_PARTIALS = 12;
|
|
36
|
+
/** Maximum simultaneous voices before stealing. */
|
|
37
|
+
const MAX_POLYPHONY = 48;
|
|
38
|
+
/** MIDI note → frequency (A4 = 440 Hz). */
|
|
39
|
+
function midiToFreq(note) {
|
|
40
|
+
return 440 * Math.pow(2, (note - 69) / 12);
|
|
41
|
+
}
|
|
42
|
+
/** MIDI note → octave (0–8). */
|
|
43
|
+
function midiToOctave(note) {
|
|
44
|
+
return Math.max(0, Math.min(8, Math.floor(note / 12) - 1));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Stereo pan: low notes left, high notes right.
|
|
48
|
+
* Mimics sitting at a piano — bass on the left, treble on the right.
|
|
49
|
+
*/
|
|
50
|
+
function noteToPan(note) {
|
|
51
|
+
return Math.max(-0.7, Math.min(0.7, ((note - 21) / 87) * 1.4 - 0.7));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Inharmonicity coefficient by octave.
|
|
55
|
+
*
|
|
56
|
+
* Piano strings are stiff, not ideal — partials are stretched above
|
|
57
|
+
* pure harmonics. This gives pianos their characteristic shimmer.
|
|
58
|
+
*
|
|
59
|
+
* f_n = n × f₀ × √(1 + B × n²)
|
|
60
|
+
*/
|
|
61
|
+
const B_COEFF = [
|
|
62
|
+
0.00012, // octave 0 (A0 area) — highest inharmonicity
|
|
63
|
+
0.00008, // octave 1
|
|
64
|
+
0.00004, // octave 2
|
|
65
|
+
0.00002, // octave 3
|
|
66
|
+
0.00001, // octave 4 (middle C)
|
|
67
|
+
0.000006, // octave 5
|
|
68
|
+
0.000004, // octave 6
|
|
69
|
+
0.000003, // octave 7
|
|
70
|
+
0.000002, // octave 8
|
|
71
|
+
];
|
|
72
|
+
/** Compute stretched partial frequency with inharmonicity. */
|
|
73
|
+
function partialFreq(fundamental, n, B) {
|
|
74
|
+
return n * fundamental * Math.sqrt(1 + B * n * n);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* How many partials to use for this note.
|
|
78
|
+
* Bass notes have richer harmonic content; treble is simpler.
|
|
79
|
+
*/
|
|
80
|
+
function partialsForNote(midiNote) {
|
|
81
|
+
if (midiNote > 90)
|
|
82
|
+
return 5; // High treble
|
|
83
|
+
if (midiNote > 72)
|
|
84
|
+
return 8; // Upper register
|
|
85
|
+
if (midiNote > 54)
|
|
86
|
+
return 10; // Middle register
|
|
87
|
+
return MAX_PARTIALS; // Bass — full harmonic series
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Amplitude for the nth partial (1-based).
|
|
91
|
+
*
|
|
92
|
+
* Base amplitude follows ~1/n^0.7 with exponential rolloff.
|
|
93
|
+
* Velocity controls brightness: soft = warm, hard = bright.
|
|
94
|
+
*/
|
|
95
|
+
function partialAmplitude(n, velocity01) {
|
|
96
|
+
const base = Math.pow(n, -0.7) * Math.exp(-0.08 * n);
|
|
97
|
+
// Velocity-dependent brightness: high partials only appear at higher velocity
|
|
98
|
+
if (n <= 3)
|
|
99
|
+
return base;
|
|
100
|
+
const brightnessGate = Math.pow(velocity01, 0.3 + (n - 3) * 0.12);
|
|
101
|
+
return base * brightnessGate;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Decay time constant (seconds) for the nth partial at a given MIDI note.
|
|
105
|
+
*
|
|
106
|
+
* Higher partials decay much faster than the fundamental.
|
|
107
|
+
* Lower notes ring longer than higher notes.
|
|
108
|
+
*/
|
|
109
|
+
function partialDecayTime(n, midiNote) {
|
|
110
|
+
// Base decay for fundamental: 3s (treble) to 15s (bass)
|
|
111
|
+
const registerFactor = 1.0 - (midiNote - 21) / 87;
|
|
112
|
+
const baseFundamental = 3 + registerFactor * 12;
|
|
113
|
+
// Higher partials: decay ∝ 1/n^0.8
|
|
114
|
+
return baseFundamental * Math.pow(n, -0.8);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Attack time based on velocity.
|
|
118
|
+
* Harder strikes = shorter hammer pulse = sharper attack.
|
|
119
|
+
*/
|
|
120
|
+
function attackTime(velocity01) {
|
|
121
|
+
return 0.002 + (1 - velocity01) * 0.008; // 2ms (ff) to 10ms (pp)
|
|
122
|
+
}
|
|
123
|
+
// ─── Engine ─────────────────────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Create the built-in piano engine.
|
|
126
|
+
*
|
|
127
|
+
* Implements VmpkConnector so it's a drop-in replacement anywhere
|
|
128
|
+
* the codebase uses a connector (sessions, CLI, MCP server).
|
|
129
|
+
*/
|
|
130
|
+
export function createAudioEngine() {
|
|
131
|
+
let ctx = null;
|
|
132
|
+
let currentStatus = "disconnected";
|
|
133
|
+
let compressor = null;
|
|
134
|
+
let master = null;
|
|
135
|
+
const activeVoices = new Map();
|
|
136
|
+
const voiceOrder = []; // LRU tracking for voice stealing
|
|
137
|
+
// ── Noise buffer (shared across all voices) ──
|
|
138
|
+
let hammerNoiseBuffer = null;
|
|
139
|
+
function ensureConnected() {
|
|
140
|
+
if (!ctx || currentStatus !== "connected") {
|
|
141
|
+
throw new Error("Piano engine not connected");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/** Create a reusable noise buffer for hammer transients. */
|
|
145
|
+
function createHammerNoiseBuffer() {
|
|
146
|
+
const durationMs = 40;
|
|
147
|
+
const length = Math.ceil((durationMs / 1000) * ctx.sampleRate);
|
|
148
|
+
hammerNoiseBuffer = ctx.createBuffer(1, length, ctx.sampleRate);
|
|
149
|
+
const data = new Float32Array(length);
|
|
150
|
+
for (let i = 0; i < length; i++) {
|
|
151
|
+
data[i] = Math.random() * 2 - 1;
|
|
152
|
+
}
|
|
153
|
+
hammerNoiseBuffer.copyToChannel(data, 0);
|
|
154
|
+
}
|
|
155
|
+
/** Synthesize a single piano voice. */
|
|
156
|
+
function createVoice(note, velocity) {
|
|
157
|
+
const velocity01 = Math.max(0.01, Math.min(1.0, velocity / 127));
|
|
158
|
+
const freq = midiToFreq(note);
|
|
159
|
+
const octave = midiToOctave(note);
|
|
160
|
+
const B = B_COEFF[octave] ?? 0.000003;
|
|
161
|
+
const now = ctx.currentTime;
|
|
162
|
+
const attack = attackTime(velocity01);
|
|
163
|
+
const numPartials = partialsForNote(note);
|
|
164
|
+
// ── Master gain: constant volume (per-partial gains shape the envelope) ──
|
|
165
|
+
const voiceMaster = ctx.createGain();
|
|
166
|
+
voiceMaster.gain.value = velocity01 * 0.25;
|
|
167
|
+
// ── Stereo panner ──
|
|
168
|
+
const panner = ctx.createStereoPanner();
|
|
169
|
+
panner.pan.value = noteToPan(note);
|
|
170
|
+
voiceMaster.connect(panner);
|
|
171
|
+
panner.connect(compressor);
|
|
172
|
+
// ── Sine partials with per-partial envelopes ──
|
|
173
|
+
const oscillators = [];
|
|
174
|
+
const partialGains = [];
|
|
175
|
+
for (let n = 1; n <= numPartials; n++) {
|
|
176
|
+
const pFreq = partialFreq(freq, n, B);
|
|
177
|
+
if (pFreq > 18000)
|
|
178
|
+
break; // Near hearing limit
|
|
179
|
+
const osc = ctx.createOscillator();
|
|
180
|
+
osc.type = "sine";
|
|
181
|
+
osc.frequency.value = pFreq;
|
|
182
|
+
// Duplex stringing: subtle random detuning for warmth
|
|
183
|
+
osc.detune.value = (Math.random() - 0.5) * 3; // ±1.5 cents
|
|
184
|
+
const gain = ctx.createGain();
|
|
185
|
+
const amp = partialAmplitude(n, velocity01);
|
|
186
|
+
const decay = partialDecayTime(n, note);
|
|
187
|
+
// Envelope: silence → attack → exponential decay
|
|
188
|
+
gain.gain.setValueAtTime(0, now);
|
|
189
|
+
gain.gain.linearRampToValueAtTime(amp, now + attack);
|
|
190
|
+
// Exponential decay toward near-zero
|
|
191
|
+
gain.gain.setTargetAtTime(0.0001, now + attack, decay);
|
|
192
|
+
osc.connect(gain);
|
|
193
|
+
gain.connect(voiceMaster);
|
|
194
|
+
osc.start(now);
|
|
195
|
+
oscillators.push(osc);
|
|
196
|
+
partialGains.push(gain);
|
|
197
|
+
}
|
|
198
|
+
// ── Hammer noise transient ──
|
|
199
|
+
let noiseSource = null;
|
|
200
|
+
if (hammerNoiseBuffer) {
|
|
201
|
+
noiseSource = ctx.createBufferSource();
|
|
202
|
+
noiseSource.buffer = hammerNoiseBuffer;
|
|
203
|
+
// Bandpass near note frequency — gives the attack a tonal character
|
|
204
|
+
const noiseFilter = ctx.createBiquadFilter();
|
|
205
|
+
noiseFilter.type = "bandpass";
|
|
206
|
+
noiseFilter.frequency.value = Math.min(freq * 2.5, 10000);
|
|
207
|
+
noiseFilter.Q.value = 0.5 + velocity01 * 2.5;
|
|
208
|
+
// Quick envelope: burst then silence
|
|
209
|
+
const noiseGain = ctx.createGain();
|
|
210
|
+
const noiseAmp = velocity01 * 0.2;
|
|
211
|
+
noiseGain.gain.setValueAtTime(noiseAmp, now);
|
|
212
|
+
noiseGain.gain.exponentialRampToValueAtTime(0.001, now + 0.025);
|
|
213
|
+
noiseSource.connect(noiseFilter);
|
|
214
|
+
noiseFilter.connect(noiseGain);
|
|
215
|
+
noiseGain.connect(voiceMaster);
|
|
216
|
+
noiseSource.start(now);
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
note,
|
|
220
|
+
oscillators,
|
|
221
|
+
partialGains,
|
|
222
|
+
masterGain: voiceMaster,
|
|
223
|
+
panner,
|
|
224
|
+
noiseSource,
|
|
225
|
+
startTime: now,
|
|
226
|
+
released: false,
|
|
227
|
+
cleanupTimer: null,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/** Release a voice (damper engages — fast fade out). */
|
|
231
|
+
function releaseVoice(voice) {
|
|
232
|
+
if (voice.released)
|
|
233
|
+
return;
|
|
234
|
+
voice.released = true;
|
|
235
|
+
const now = ctx.currentTime;
|
|
236
|
+
const releaseTime = 0.12; // 120ms damper release
|
|
237
|
+
// Cancel ongoing scheduled values and fade to silence
|
|
238
|
+
for (const g of voice.partialGains) {
|
|
239
|
+
g.gain.cancelScheduledValues(now);
|
|
240
|
+
g.gain.setValueAtTime(g.gain.value, now);
|
|
241
|
+
g.gain.linearRampToValueAtTime(0, now + releaseTime);
|
|
242
|
+
}
|
|
243
|
+
// Schedule full cleanup after release completes
|
|
244
|
+
voice.cleanupTimer = setTimeout(() => killVoice(voice), (releaseTime + 0.05) * 1000);
|
|
245
|
+
}
|
|
246
|
+
/** Immediately destroy a voice and free resources. */
|
|
247
|
+
function killVoice(voice) {
|
|
248
|
+
if (voice.cleanupTimer) {
|
|
249
|
+
clearTimeout(voice.cleanupTimer);
|
|
250
|
+
voice.cleanupTimer = null;
|
|
251
|
+
}
|
|
252
|
+
for (const osc of voice.oscillators) {
|
|
253
|
+
try {
|
|
254
|
+
osc.stop();
|
|
255
|
+
osc.disconnect();
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
/* already stopped */
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
for (const g of voice.partialGains) {
|
|
262
|
+
try {
|
|
263
|
+
g.disconnect();
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
/* ok */
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (voice.noiseSource) {
|
|
270
|
+
try {
|
|
271
|
+
voice.noiseSource.stop();
|
|
272
|
+
voice.noiseSource.disconnect();
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
/* ok */
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
voice.masterGain.disconnect();
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
/* ok */
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
voice.panner.disconnect();
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
/* ok */
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/** Steal the oldest voice when at max polyphony. */
|
|
292
|
+
function stealOldest() {
|
|
293
|
+
if (voiceOrder.length === 0)
|
|
294
|
+
return;
|
|
295
|
+
const oldestNote = voiceOrder.shift();
|
|
296
|
+
const voice = activeVoices.get(oldestNote);
|
|
297
|
+
if (voice) {
|
|
298
|
+
killVoice(voice);
|
|
299
|
+
activeVoices.delete(oldestNote);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/** Remove a note from the LRU order. */
|
|
303
|
+
function removeFromOrder(note) {
|
|
304
|
+
const idx = voiceOrder.indexOf(note);
|
|
305
|
+
if (idx >= 0)
|
|
306
|
+
voiceOrder.splice(idx, 1);
|
|
307
|
+
}
|
|
308
|
+
// ── VmpkConnector Implementation ──
|
|
309
|
+
return {
|
|
310
|
+
async connect() {
|
|
311
|
+
if (currentStatus === "connected")
|
|
312
|
+
return;
|
|
313
|
+
currentStatus = "connecting";
|
|
314
|
+
try {
|
|
315
|
+
const AC = await loadAudioContext();
|
|
316
|
+
ctx = new AC({ latencyHint: "playback" });
|
|
317
|
+
// Master chain: compressor → gain → speakers
|
|
318
|
+
compressor = ctx.createDynamicsCompressor();
|
|
319
|
+
compressor.threshold.value = -15;
|
|
320
|
+
compressor.knee.value = 12;
|
|
321
|
+
compressor.ratio.value = 6;
|
|
322
|
+
compressor.attack.value = 0.003;
|
|
323
|
+
compressor.release.value = 0.2;
|
|
324
|
+
master = ctx.createGain();
|
|
325
|
+
master.gain.value = 0.85;
|
|
326
|
+
compressor.connect(master);
|
|
327
|
+
master.connect(ctx.destination);
|
|
328
|
+
// Pre-generate shared noise buffer
|
|
329
|
+
createHammerNoiseBuffer();
|
|
330
|
+
currentStatus = "connected";
|
|
331
|
+
console.error("Piano engine connected (built-in audio)");
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
currentStatus = "error";
|
|
335
|
+
throw new Error(`Failed to start piano engine: ${err instanceof Error ? err.message : String(err)}`);
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
async disconnect() {
|
|
339
|
+
// Kill all active voices
|
|
340
|
+
for (const [, voice] of activeVoices) {
|
|
341
|
+
try {
|
|
342
|
+
killVoice(voice);
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
/* ok */
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
activeVoices.clear();
|
|
349
|
+
voiceOrder.length = 0;
|
|
350
|
+
if (ctx) {
|
|
351
|
+
try {
|
|
352
|
+
await ctx.close();
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
/* ok */
|
|
356
|
+
}
|
|
357
|
+
ctx = null;
|
|
358
|
+
compressor = null;
|
|
359
|
+
master = null;
|
|
360
|
+
hammerNoiseBuffer = null;
|
|
361
|
+
}
|
|
362
|
+
currentStatus = "disconnected";
|
|
363
|
+
},
|
|
364
|
+
status() {
|
|
365
|
+
return currentStatus;
|
|
366
|
+
},
|
|
367
|
+
listPorts() {
|
|
368
|
+
return ["Built-in Piano"];
|
|
369
|
+
},
|
|
370
|
+
noteOn(note, velocity, channel) {
|
|
371
|
+
ensureConnected();
|
|
372
|
+
// Kill existing voice on same note (retrigger)
|
|
373
|
+
const existing = activeVoices.get(note);
|
|
374
|
+
if (existing) {
|
|
375
|
+
killVoice(existing);
|
|
376
|
+
activeVoices.delete(note);
|
|
377
|
+
removeFromOrder(note);
|
|
378
|
+
}
|
|
379
|
+
// Voice stealing if at capacity
|
|
380
|
+
while (activeVoices.size >= MAX_POLYPHONY) {
|
|
381
|
+
stealOldest();
|
|
382
|
+
}
|
|
383
|
+
const voice = createVoice(note, velocity);
|
|
384
|
+
activeVoices.set(note, voice);
|
|
385
|
+
voiceOrder.push(note);
|
|
386
|
+
},
|
|
387
|
+
noteOff(note, channel) {
|
|
388
|
+
if (!ctx || currentStatus !== "connected")
|
|
389
|
+
return;
|
|
390
|
+
const voice = activeVoices.get(note);
|
|
391
|
+
if (voice) {
|
|
392
|
+
releaseVoice(voice);
|
|
393
|
+
activeVoices.delete(note);
|
|
394
|
+
removeFromOrder(note);
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
allNotesOff(channel) {
|
|
398
|
+
if (!ctx)
|
|
399
|
+
return;
|
|
400
|
+
for (const [, voice] of activeVoices) {
|
|
401
|
+
killVoice(voice);
|
|
402
|
+
}
|
|
403
|
+
activeVoices.clear();
|
|
404
|
+
voiceOrder.length = 0;
|
|
405
|
+
},
|
|
406
|
+
async playNote(midiNote) {
|
|
407
|
+
if (midiNote.note < 0) {
|
|
408
|
+
// Rest — just wait
|
|
409
|
+
await sleep(midiNote.durationMs);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
this.noteOn(midiNote.note, midiNote.velocity, midiNote.channel);
|
|
413
|
+
await sleep(midiNote.durationMs);
|
|
414
|
+
this.noteOff(midiNote.note, midiNote.channel);
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
419
|
+
function sleep(ms) {
|
|
420
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
421
|
+
}
|
|
422
|
+
//# sourceMappingURL=audio-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-engine.js","sourceRoot":"","sources":["../src/audio-engine.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|