@mcptoolshop/pianoai 1.3.0 → 1.3.1
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.
Potentially problematic release.
This version of @mcptoolshop/pianoai might be problematic. Click here for more details.
- package/README.es.md +148 -184
- package/README.fr.md +149 -185
- package/README.hi.md +152 -188
- package/README.it.md +157 -193
- package/README.ja.md +149 -185
- package/README.md +147 -210
- package/README.pt-BR.md +168 -204
- package/README.zh.md +148 -184
- package/dist/cli.js +78 -59
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.js +97 -30
- package/dist/mcp-server.js.map +1 -1
- 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/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/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/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/package.json +2 -1
package/README.es.md
CHANGED
|
@@ -9,39 +9,35 @@
|
|
|
9
9
|
<h1 align="center">PianoAI</h1>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
|
|
12
|
+
Reproductor de piano con motor de audio integrado — suena por los altavoces, sin software externo necesario. Servidor MCP + CLI.
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
[-blue)](https://github.com/mcp-tool-shop-org/ai-music-sheets)
|
|
15
|
+
[](https://github.com/mcp-tool-shop-org/pianoai)
|
|
16
|
+
[](https://github.com/mcp-tool-shop-org/pianoai)
|
|
17
|
+
[](https://github.com/mcp-tool-shop-org/ai-music-sheets)
|
|
19
18
|
|
|
20
19
|
## ¿Qué es esto?
|
|
21
20
|
|
|
22
|
-
Un
|
|
21
|
+
Un reproductor de piano en TypeScript que reproduce archivos MIDI estándar y canciones integradas a través de tus altavoces. No requiere software externo — el motor de audio integrado se encarga de todo. Incluye un servidor MCP para integración con LLMs y un CLI para uso directo.
|
|
22
|
+
|
|
23
|
+
Soporta narración de canto en tiempo real y retroalimentación de enseñanza en vivo durante la reproducción.
|
|
23
24
|
|
|
24
25
|
## Características
|
|
25
26
|
|
|
27
|
+
- **Motor de piano integrado** — reproduce por los altavoces vía `node-web-audio-api`, sin hardware MIDI necesario
|
|
28
|
+
- **Soporte de archivos MIDI estándar** — reproduce cualquier archivo `.mid`: `pianoai play song.mid`
|
|
29
|
+
- **Canto en tiempo real** — narra nombres de notas, solfeo, contorno o sílabas durante la reproducción MIDI
|
|
30
|
+
- **Filtros de voz** — canta solo la melodía (nota más aguda), armonía (más grave) o todas las notas por acorde
|
|
31
|
+
- **Retroalimentación de enseñanza en vivo** — consejos de dinámica según la posición, avisos de rango, límites de sección, anuncios de hitos
|
|
32
|
+
- **Seguimiento de posición** — mapeo de pulso/compás/tempo desde MIDI en crudo con soporte de búsqueda
|
|
26
33
|
- **4 modos de reproducción** — completa, compás por compás, manos separadas, bucle
|
|
27
|
-
- **Control de velocidad** — práctica lenta a 0.5x hasta
|
|
28
|
-
- **
|
|
29
|
-
- **
|
|
30
|
-
- **
|
|
31
|
-
- **
|
|
32
|
-
- **Retroalimentación por voz** — salida `VoiceDirective` para integración con mcp-voice-soundboard
|
|
33
|
-
- **Retroalimentación en vivo** — estímulo en tiempo real, consejos de dinámica y avisos de dificultad durante la reproducción
|
|
34
|
-
- **Interjecciones aparte** — salida `AsideDirective` para la bandeja de mcp-aside
|
|
34
|
+
- **Control de velocidad** — práctica lenta a 0.5x hasta 4x rápida, acumulable con modificación de tempo
|
|
35
|
+
- **Controles en tiempo real** — pausa, reanudación, cambio de velocidad, búsqueda durante la reproducción con listeners de eventos
|
|
36
|
+
- **12 herramientas MCP** — reproducir, pausar, velocidad, detener, explorar, cantar, enseñar — todo mediante el protocolo MCP
|
|
37
|
+
- **12 hooks de enseñanza** — console, silent, recording, callback, voice, aside, sing-along, live feedback, MIDI singing, MIDI live feedback, compose
|
|
38
|
+
- **Salida MIDI opcional** — enrutar a software externo con la bandera `--midi` (requiere loopMIDI + VMPK)
|
|
35
39
|
- **Análisis seguro** — las notas incorrectas se omiten con `ParseWarning`s recopilados
|
|
36
|
-
- **
|
|
37
|
-
- **Analizador de notas** — notación científica de altura a MIDI y viceversa
|
|
38
|
-
- **Conector simulado** — cobertura completa de tests sin hardware MIDI
|
|
39
|
-
|
|
40
|
-
## Requisitos previos
|
|
41
|
-
|
|
42
|
-
1. **[loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)** — crea un puerto MIDI virtual (ej. "loopMIDI Port")
|
|
43
|
-
2. **[VMPK](https://vmpk.sourceforge.io/)** — configura la entrada MIDI a tu puerto loopMIDI
|
|
44
|
-
3. **Node.js 18+**
|
|
40
|
+
- **Conector simulado** — cobertura completa de tests sin hardware
|
|
45
41
|
|
|
46
42
|
## Instalación
|
|
47
43
|
|
|
@@ -49,46 +45,62 @@ Un CLI en TypeScript y servidor MCP que carga canciones de piano desde [ai-music
|
|
|
49
45
|
npm install -g @mcptoolshop/pianoai
|
|
50
46
|
```
|
|
51
47
|
|
|
48
|
+
Requiere **Node.js 18+**. Eso es todo — sin controladores MIDI, sin puertos virtuales, sin software externo.
|
|
49
|
+
|
|
52
50
|
## Inicio rápido
|
|
53
51
|
|
|
54
52
|
```bash
|
|
55
|
-
#
|
|
56
|
-
pianoai
|
|
53
|
+
# Reproducir un archivo MIDI
|
|
54
|
+
pianoai play path/to/song.mid
|
|
57
55
|
|
|
58
|
-
#
|
|
59
|
-
pianoai
|
|
56
|
+
# Reproducir con canto (narrar nombres de notas mientras suenan)
|
|
57
|
+
pianoai play song.mid --with-singing
|
|
60
58
|
|
|
61
|
-
#
|
|
62
|
-
pianoai play
|
|
59
|
+
# Cantar solo la melodía (omitir notas de acorde, solo la voz superior)
|
|
60
|
+
pianoai play song.mid --with-singing --voice-filter melody-only
|
|
63
61
|
|
|
64
|
-
# Reproducir con
|
|
65
|
-
pianoai play
|
|
62
|
+
# Reproducir con retroalimentación de enseñanza (dinámica, estímulo)
|
|
63
|
+
pianoai play song.mid --with-teaching
|
|
66
64
|
|
|
67
|
-
#
|
|
68
|
-
pianoai play
|
|
65
|
+
# Reproducir con canto y enseñanza juntos
|
|
66
|
+
pianoai play song.mid --with-singing --with-teaching --sing-mode solfege
|
|
69
67
|
|
|
70
|
-
# Práctica a mitad de velocidad
|
|
71
|
-
pianoai play
|
|
68
|
+
# Práctica a mitad de velocidad con canto
|
|
69
|
+
pianoai play song.mid --speed 0.5 --with-singing
|
|
72
70
|
|
|
73
|
-
#
|
|
74
|
-
pianoai play
|
|
71
|
+
# Saltar al segundo 45 y reproducir desde ahí
|
|
72
|
+
pianoai play song.mid --seek 45
|
|
75
73
|
|
|
76
|
-
#
|
|
77
|
-
pianoai
|
|
74
|
+
# Reproducir una canción de la biblioteca integrada
|
|
75
|
+
pianoai play let-it-be
|
|
78
76
|
|
|
79
|
-
#
|
|
80
|
-
pianoai
|
|
77
|
+
# Listar todas las canciones integradas
|
|
78
|
+
pianoai list
|
|
81
79
|
|
|
82
|
-
#
|
|
83
|
-
pianoai
|
|
80
|
+
# Mostrar detalles de canción + notas de enseñanza
|
|
81
|
+
pianoai info moonlight-sonata-mvt1
|
|
84
82
|
|
|
85
|
-
#
|
|
86
|
-
pianoai sing
|
|
83
|
+
# Cantar junto con una canción de la biblioteca (narración por voz)
|
|
84
|
+
pianoai sing let-it-be --mode solfege --with-piano
|
|
87
85
|
```
|
|
88
86
|
|
|
87
|
+
### Opciones de reproducción
|
|
88
|
+
|
|
89
|
+
| Bandera | Descripción |
|
|
90
|
+
|---------|-------------|
|
|
91
|
+
| `--speed <mult>` | Multiplicador de velocidad: 0.5 = mitad, 1.0 = normal, 2.0 = doble |
|
|
92
|
+
| `--tempo <bpm>` | Modificar el tempo predeterminado de la canción (10-400 BPM) |
|
|
93
|
+
| `--mode <mode>` | Modo de reproducción: `full`, `measure`, `hands`, `loop` |
|
|
94
|
+
| `--with-singing` | Activar narración de canto en tiempo real |
|
|
95
|
+
| `--with-teaching` | Activar retroalimentación de enseñanza en vivo |
|
|
96
|
+
| `--sing-mode <mode>` | Modo de canto: `note-names`, `solfege`, `contour`, `syllables` |
|
|
97
|
+
| `--voice-filter <f>` | Filtro de voz: `all`, `melody-only`, `harmony` |
|
|
98
|
+
| `--seek <seconds>` | Saltar a un momento específico antes de reproducir |
|
|
99
|
+
| `--midi` | Enrutar a software MIDI externo en lugar del motor integrado |
|
|
100
|
+
|
|
89
101
|
## Servidor MCP
|
|
90
102
|
|
|
91
|
-
El servidor MCP expone
|
|
103
|
+
El servidor MCP expone 12 herramientas para integración con LLMs:
|
|
92
104
|
|
|
93
105
|
| Herramienta | Descripción |
|
|
94
106
|
|-------------|-------------|
|
|
@@ -96,15 +108,14 @@ El servidor MCP expone 8 herramientas para integración con LLMs:
|
|
|
96
108
|
| `song_info` | Obtener lenguaje musical completo, objetivos de enseñanza, sugerencias de práctica |
|
|
97
109
|
| `registry_stats` | Conteo de canciones por género y dificultad |
|
|
98
110
|
| `teaching_note` | Nota de enseñanza por compás, digitación, dinámicas |
|
|
99
|
-
| `sing_along` | Obtener texto cantable por compás (nombres de notas, solfeo, contorno, sílabas); soporta `withPiano` para acompañamiento sincronizado |
|
|
100
111
|
| `suggest_song` | Obtener una recomendación basada en criterios |
|
|
101
112
|
| `list_measures` | Vista general de compases con notas de enseñanza + advertencias de análisis |
|
|
113
|
+
| `sing_along` | Obtener texto cantable (nombres de notas, solfeo, contorno, sílabas) por compás |
|
|
102
114
|
| `practice_setup` | Sugerir velocidad, modo y configuración de voz para una canción |
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```
|
|
115
|
+
| `play_song` | Reproducir una canción o archivo MIDI con canto y enseñanza opcionales |
|
|
116
|
+
| `pause_playback` | Pausar o reanudar la canción en reproducción |
|
|
117
|
+
| `set_speed` | Cambiar la velocidad de reproducción durante la reproducción |
|
|
118
|
+
| `stop_playback` | Detener la canción en reproducción |
|
|
108
119
|
|
|
109
120
|
### Configuración de Claude Desktop
|
|
110
121
|
|
|
@@ -112,195 +123,148 @@ pnpm mcp
|
|
|
112
123
|
{
|
|
113
124
|
"mcpServers": {
|
|
114
125
|
"pianoai": {
|
|
115
|
-
"command": "
|
|
126
|
+
"command": "npx",
|
|
127
|
+
"args": ["-y", "-p", "@mcptoolshop/pianoai", "pianoai-mcp"]
|
|
116
128
|
}
|
|
117
129
|
}
|
|
118
130
|
}
|
|
119
131
|
```
|
|
120
132
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
| Comando | Descripción |
|
|
124
|
-
|---------|-------------|
|
|
125
|
-
| `list [--genre <genre>]` | Listar canciones disponibles, opcionalmente filtradas por género |
|
|
126
|
-
| `info <song-id>` | Mostrar detalles de canción: lenguaje musical, notas de enseñanza, estructura |
|
|
127
|
-
| `play <song-id> [opts]` | Reproducir una canción a través de VMPK vía MIDI |
|
|
128
|
-
| `sing <song-id> [opts]` | Cantar junto — narrar notas durante la reproducción |
|
|
129
|
-
| `stats` | Estadísticas del registro (canciones, géneros, compases) |
|
|
130
|
-
| `ports` | Listar puertos de salida MIDI disponibles |
|
|
131
|
-
| `help` | Mostrar información de uso |
|
|
133
|
+
### play_song con canto y enseñanza
|
|
132
134
|
|
|
133
|
-
|
|
135
|
+
La herramienta MCP `play_song` acepta las banderas `withSinging` y `withTeaching`:
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
| `--tempo <bpm>` | Modificar el tempo predeterminado de la canción (10-400 BPM) |
|
|
139
|
-
| `--speed <mult>` | Multiplicador de velocidad: 0.5 = mitad, 1.0 = normal, 2.0 = doble |
|
|
140
|
-
| `--mode <mode>` | Modo de reproducción: `full`, `measure`, `hands`, `loop` |
|
|
137
|
+
```
|
|
138
|
+
play_song({ id: "path/to/song.mid", withSinging: true, withTeaching: true, singMode: "solfege" })
|
|
139
|
+
```
|
|
141
140
|
|
|
142
|
-
|
|
141
|
+
## API programática
|
|
143
142
|
|
|
144
|
-
|
|
145
|
-
|---------|-------------|
|
|
146
|
-
| `--mode <mode>` | Modo de canto: `note-names`, `solfege`, `contour`, `syllables` |
|
|
147
|
-
| `--hand <hand>` | Qué mano: `right`, `left`, `both` |
|
|
148
|
-
| `--with-piano` | Reproducir acompañamiento de piano mientras se canta |
|
|
149
|
-
| `--sync <mode>` | Sincronización voz+piano: `concurrent` (por defecto, dúo), `before` (voz primero) |
|
|
143
|
+
### Reproducir un archivo MIDI con controles en tiempo real
|
|
150
144
|
|
|
151
|
-
|
|
145
|
+
```typescript
|
|
146
|
+
import { createAudioEngine, parseMidiFile, PlaybackController } from "@mcptoolshop/pianoai";
|
|
152
147
|
|
|
153
|
-
|
|
148
|
+
const connector = createAudioEngine();
|
|
149
|
+
await connector.connect();
|
|
154
150
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
| `createConsoleTeachingHook()` | CLI — registra compases, momentos y finalización en consola |
|
|
158
|
-
| `createSilentTeachingHook()` | Testing — sin operación |
|
|
159
|
-
| `createRecordingTeachingHook()` | Testing — graba eventos para aserciones |
|
|
160
|
-
| `createCallbackTeachingHook(cb)` | Personalizado — redirige a cualquier callback asíncrono |
|
|
161
|
-
| `createVoiceTeachingHook(sink)` | Voz — produce `VoiceDirective` para mcp-voice-soundboard |
|
|
162
|
-
| `createAsideTeachingHook(sink)` | Aparte — produce `AsideDirective` para la bandeja de mcp-aside |
|
|
163
|
-
| `createSingAlongHook(sink, song)` | Canto — narra notas/solfeo/contorno antes de cada compás |
|
|
164
|
-
| `createLiveFeedbackHook(voiceSink, asideSink, song)` | Retroalimentación — estímulo, consejos de dinámica, avisos de dificultad |
|
|
165
|
-
| `composeTeachingHooks(...hooks)` | Múltiple — despacha a múltiples hooks en serie |
|
|
151
|
+
const midi = await parseMidiFile("song.mid");
|
|
152
|
+
const controller = new PlaybackController(connector, midi);
|
|
166
153
|
|
|
167
|
-
|
|
154
|
+
// Escuchar eventos
|
|
155
|
+
controller.on("noteOn", (e) => console.log(`Nota: ${e.noteName}`));
|
|
156
|
+
controller.on("stateChange", (e) => console.log(`Estado: ${e.state}`));
|
|
168
157
|
|
|
169
|
-
|
|
170
|
-
import { createSession, createVoiceTeachingHook } from "@mcptoolshop/pianoai";
|
|
171
|
-
import { getSong } from "ai-music-sheets";
|
|
172
|
-
|
|
173
|
-
const voiceHook = createVoiceTeachingHook(
|
|
174
|
-
async (directive) => {
|
|
175
|
-
// Redirigir a voice_speak de mcp-voice-soundboard
|
|
176
|
-
console.log(`[Voice] ${directive.text}`);
|
|
177
|
-
},
|
|
178
|
-
{ voice: "narrator", speechSpeed: 0.9 }
|
|
179
|
-
);
|
|
158
|
+
await controller.play({ speed: 0.75 });
|
|
180
159
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
});
|
|
160
|
+
controller.pause(); // pausar
|
|
161
|
+
controller.setSpeed(1.5); // cambiar velocidad
|
|
162
|
+
await controller.resume();// reanudar a nueva velocidad
|
|
185
163
|
|
|
186
|
-
await
|
|
187
|
-
// voiceHook.directives → todas las instrucciones de voz que se dispararon
|
|
164
|
+
await connector.disconnect();
|
|
188
165
|
```
|
|
189
166
|
|
|
190
|
-
###
|
|
167
|
+
### Reproducir con canto y enseñanza en vivo
|
|
191
168
|
|
|
192
169
|
```typescript
|
|
193
170
|
import {
|
|
194
|
-
|
|
195
|
-
|
|
171
|
+
createAudioEngine,
|
|
172
|
+
parseMidiFile,
|
|
173
|
+
PlaybackController,
|
|
174
|
+
createSingOnMidiHook,
|
|
175
|
+
createLiveMidiFeedbackHook,
|
|
196
176
|
composeTeachingHooks,
|
|
197
|
-
createSession,
|
|
198
177
|
} from "@mcptoolshop/pianoai";
|
|
199
|
-
import { getSong } from "@mcptoolshop/ai-music-sheets";
|
|
200
178
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const singHook = createSingAlongHook(voiceSink, song, {
|
|
205
|
-
mode: "solfege",
|
|
206
|
-
hand: "right",
|
|
207
|
-
});
|
|
208
|
-
const teachHook = createVoiceTeachingHook(voiceSink);
|
|
209
|
-
const combined = composeTeachingHooks(singHook, teachHook);
|
|
179
|
+
const connector = createAudioEngine();
|
|
180
|
+
await connector.connect();
|
|
181
|
+
const midi = await parseMidiFile("song.mid");
|
|
210
182
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
183
|
+
const singHook = createSingOnMidiHook(
|
|
184
|
+
async (d) => console.log(`♪ ${d.text}`),
|
|
185
|
+
midi,
|
|
186
|
+
{ mode: "solfege", voiceFilter: "melody-only" }
|
|
187
|
+
);
|
|
215
188
|
|
|
216
|
-
|
|
189
|
+
const feedbackHook = createLiveMidiFeedbackHook(
|
|
190
|
+
async (d) => console.log(`🎓 ${d.text}`),
|
|
191
|
+
async (d) => console.log(`💡 ${d.text}`),
|
|
192
|
+
midi,
|
|
193
|
+
{ voiceInterval: 8 }
|
|
194
|
+
);
|
|
217
195
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
createAsideTeachingHook,
|
|
222
|
-
createRecordingTeachingHook,
|
|
223
|
-
composeTeachingHooks,
|
|
224
|
-
} from "@mcptoolshop/pianoai";
|
|
196
|
+
const composed = composeTeachingHooks(singHook, feedbackHook);
|
|
197
|
+
const controller = new PlaybackController(connector, midi);
|
|
198
|
+
await controller.play({ teachingHook: composed });
|
|
225
199
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
createVoiceTeachingHook(voiceSink),
|
|
229
|
-
createAsideTeachingHook(asideSink),
|
|
230
|
-
createRecordingTeachingHook()
|
|
231
|
-
);
|
|
200
|
+
// feedbackHook.tracker tiene información de posición
|
|
201
|
+
console.log(`Total de compases: ${feedbackHook.tracker.totalMeasures}`);
|
|
232
202
|
```
|
|
233
203
|
|
|
234
|
-
|
|
204
|
+
### Reproducir una canción de la biblioteca integrada
|
|
235
205
|
|
|
236
206
|
```typescript
|
|
237
|
-
import { getSong } from "ai-music-sheets";
|
|
238
|
-
import { createSession,
|
|
207
|
+
import { getSong } from "@mcptoolshop/ai-music-sheets";
|
|
208
|
+
import { createSession, createAudioEngine } from "@mcptoolshop/pianoai";
|
|
239
209
|
|
|
240
|
-
const connector =
|
|
210
|
+
const connector = createAudioEngine();
|
|
241
211
|
await connector.connect();
|
|
242
212
|
|
|
243
213
|
const song = getSong("autumn-leaves")!;
|
|
244
214
|
const session = createSession(song, connector, {
|
|
245
|
-
mode: "
|
|
246
|
-
|
|
247
|
-
speed: 0.75, // 75% de velocidad para práctica
|
|
248
|
-
onProgress: (p) => console.log(p.percent), // "25%", "50%", etc.
|
|
215
|
+
mode: "full",
|
|
216
|
+
speed: 0.75,
|
|
249
217
|
});
|
|
250
218
|
|
|
251
|
-
await session.play();
|
|
252
|
-
session.next(); // avanza al siguiente compás
|
|
253
|
-
await session.play(); // reproduce el siguiente compás
|
|
254
|
-
session.setSpeed(1.0); // vuelve a velocidad normal
|
|
255
|
-
await session.play(); // reproduce el siguiente compás a velocidad completa
|
|
256
|
-
session.stop(); // detiene y reinicia
|
|
257
|
-
|
|
258
|
-
// Verificar advertencias de análisis (notas incorrectas en los datos de la canción)
|
|
259
|
-
if (session.parseWarnings.length > 0) {
|
|
260
|
-
console.warn("Algunas notas no pudieron ser analizadas:", session.parseWarnings);
|
|
261
|
-
}
|
|
262
|
-
|
|
219
|
+
await session.play();
|
|
263
220
|
await connector.disconnect();
|
|
264
221
|
```
|
|
265
222
|
|
|
266
223
|
## Arquitectura
|
|
267
224
|
|
|
268
225
|
```
|
|
269
|
-
ai-music-sheets
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
│
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
226
|
+
Archivos MIDI estándar (.mid) Canciones integradas (ai-music-sheets)
|
|
227
|
+
│ │
|
|
228
|
+
▼ ▼
|
|
229
|
+
MIDI Parser ──────────────── Note Parser
|
|
230
|
+
│ │
|
|
231
|
+
▼ ▼
|
|
232
|
+
MidiPlaybackEngine SessionController
|
|
233
|
+
│ │
|
|
234
|
+
└──────── PlaybackController ──┘
|
|
235
|
+
(eventos en tiempo real, hooks)
|
|
236
|
+
│
|
|
237
|
+
┌─────────────┼─────────────┐
|
|
238
|
+
▼ ▼ ▼
|
|
239
|
+
AudioEngine Teaching Hooks Progress
|
|
240
|
+
(altavoces) (canto, retro.) (callbacks)
|
|
241
|
+
│
|
|
242
|
+
▼
|
|
243
|
+
node-web-audio-api (Rust DSP)
|
|
244
|
+
|
|
245
|
+
Seguimiento de posición:
|
|
246
|
+
MIDI Parser → PositionTracker → mapeo de pulso/compás/tempo
|
|
247
|
+
→ búsqueda por tiempo / búsqueda por compás
|
|
248
|
+
→ resúmenes de compás para retroalimentación en vivo
|
|
283
249
|
|
|
284
250
|
Enrutamiento de hooks de enseñanza:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
251
|
+
PlaybackController → TeachingHook → VoiceDirective → mcp-voice-soundboard
|
|
252
|
+
→ AsideDirective → bandeja de mcp-aside
|
|
253
|
+
→ Console log → terminal del CLI
|
|
254
|
+
→ Recording → aserciones de test
|
|
289
255
|
```
|
|
290
256
|
|
|
291
257
|
## Testing
|
|
292
258
|
|
|
293
259
|
```bash
|
|
294
|
-
pnpm test #
|
|
295
|
-
pnpm smoke # 29 smoke tests (integración, sin MIDI necesario)
|
|
260
|
+
pnpm test # 243 tests con Vitest
|
|
296
261
|
pnpm typecheck # tsc --noEmit
|
|
262
|
+
pnpm smoke # tests de integración
|
|
297
263
|
```
|
|
298
264
|
|
|
299
|
-
El conector VMPK simulado (`createMockVmpkConnector`) registra todos los eventos MIDI sin hardware, permitiendo cobertura completa de tests. Las funciones de análisis seguro (`safeParseMeasure`) recopilan objetos `ParseWarning` en lugar de lanzar excepciones, de modo que la reproducción continúa correctamente si una canción tiene notas malformadas.
|
|
300
|
-
|
|
301
265
|
## Relacionados
|
|
302
266
|
|
|
303
|
-
- **[ai-music-sheets](https://github.com/mcp-tool-shop-org/ai-music-sheets)** — La biblioteca de canciones
|
|
267
|
+
- **[ai-music-sheets](https://github.com/mcp-tool-shop-org/ai-music-sheets)** — La biblioteca de canciones integrada
|
|
304
268
|
|
|
305
269
|
## Licencia
|
|
306
270
|
|