> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Explicación detallada de Score y Note - VOICEVOX for Laravel

> Explica el diseño de Score y Note en la síntesis de canciones de VOICEVOX for Laravel, el cálculo de longitud de frames y patrones de gestión en JSON.

## Objetivo

Organiza las especificaciones de `Score` y `Note` que suelen generar dudas al sintetizar canciones.

La base de la implementación son los archivos fuente de `Revolution\Voicevox\Song\Note` / `Score` / `SongAudioQuery`.

## Clase `Note`

`Note` representa una nota (o un silencio).

```php theme={null}
use Revolution\Voicevox\Song\Note;

$note = Note::make(
    length: 94,
    lyric: 'ド',
    key: 60,
    id: 'intro-1',
);
```

### Argumentos del constructor

| Argumento | Tipo           | Descripción                                                       |
| --------- | -------------- | ----------------------------------------------------------------- |
| `length`  | `int`          | Longitud en frames. Valor entero de `segundos × 93.75`            |
| `lyric`   | `string`       | Letra. Los silencios usan cadena vacía `''`                       |
| `key`     | `int\|null`    | Número de nota MIDI. Los silencios usan `null`                    |
| `id`      | `string\|null` | ID auxiliar que se copia a `note_id` al generar `FrameAudioQuery` |

### Cálculo de la longitud en frames

`length` está en frames. A partir de los segundos se calcula así:

```text theme={null}
length = segundos × 93.75
```

Este valor no es intuitivo, así que si estás acostumbrado a MIDI, en la práctica conviene usar `Note::len()`.

```php theme={null}
Note::len(int $ticks, int $bpm = 125): int
```

* Se asume que la negra son `480 ticks`
* Por defecto son `125 BPM`
* Internamente se redondea con `round()` y se convierte en entero, así que en canciones largas el error de redondeo se acumula poco a poco

```php theme={null}
Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60);  // Negra
Note::make(length: Note::len(960, 120), lyric: 'ミ', key: 64);  // Blanca
```

<Warning>
  `Note::len()` es cómodo, pero en canciones largas hay que tener cuidado con el error acumulado. Si es necesario, reajusta las longitudes por secciones.
</Warning>

### Representación de silencios

Los silencios son esta combinación:

```php theme={null}
Note::make(length: 15, lyric: '', key: null);
```

### Referencia de números de nota MIDI

| Nota | MIDI |
| ---- | ---- |
| C4   | 60   |
| D4   | 62   |
| E4   | 64   |
| F4   | 65   |
| G4   | 67   |
| A4   | 69   |
| B4   | 71   |
| C5   | 72   |

## Clase `Score`

`Score` es un objeto de partitura que contiene un array de `Note`.

```php theme={null}
use Revolution\Voicevox\Song\Score;

$score = Score::make([
    Note::make(length: 15, lyric: '', key: null),
    Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60),
]);
```

### Regla importante

La primera nota debe ser siempre un silencio.

### API principal

* Se crea con `Score::make(array $notes)`
* Se añade con `add(Note $note)`
* Se convierte a JSON con `toJson()`

```php theme={null}
$score = Score::make([
    Note::make(length: 15, lyric: '', key: null),
]);

$score->add(Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60));

$json = $score->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
```

<Info>
  El constructor de `Score` incluye una implementación que absorbe `lyric` vacío o `null` al recibir un array, así que también encaja bien con entradas de formulario que pasan por el middleware `ConvertEmptyStringsToNull`.
</Info>

## Patrón práctico: gestión con archivo JSON (recomendado)

En un producto real, es más manejable no escribir la partitura directamente en PHP y gestionarla en JSON.

1. Guarda un JSON con formato propio
2. Cárgalo y conviértelo en `Note` / `Score`
3. Pásalo a `Voicevox::song()` para generar

### Ejemplo de JSON

```json theme={null}
{
  "teacher": 6000,
  "speaker": 3001,
  "bpm": 120,
  "notes": [
    { "ticks": 120, "lyric": "", "key": null, "id": "r0" },
    { "ticks": 480, "lyric": "ド", "key": 60, "id": "n1" },
    { "ticks": 480, "lyric": "レ", "key": 62, "id": "n2" },
    { "ticks": 960, "lyric": "ミ", "key": 64, "id": "n3" },
    { "ticks": 120, "lyric": "", "key": null, "id": "r1" }
  ]
}
```

### Carga y síntesis

```php theme={null}
use Illuminate\Support\Facades\Storage;
use Revolution\Voicevox\Song\Note;
use Revolution\Voicevox\Song\Score;
use Revolution\Voicevox\Voicevox;

$chart = json_decode(
    Storage::disk('local')->get('songs/sample.json'),
    true,
    flags: JSON_THROW_ON_ERROR,
);

$score = Score::make(
    collect($chart['notes'])
        ->map(fn (array $note) => Note::make(
            length: Note::len(ticks: $note['ticks'], bpm: $chart['bpm']),
            lyric: $note['lyric'] ?? '',
            key: $note['key'],
            id: $note['id'] ?? null,
        ))
        ->all(),
);

$response = Voicevox::song($score, teacher: $chart['teacher'])
    ->generate(id: $chart['speaker']);

$response->storeAs('songs', 'sample.wav');
```

## Páginas relacionadas

* [Cliente: Song](/es/packages/laravel-voicevox/client-song)
* [Nativo: Song](/es/packages/laravel-voicevox/native-song)
* [Engine API: Song](/es/packages/laravel-voicevox/engine-song)


## Related topics

- [Guía de desarrollo de apps con integración de la Engine API - VOICEVOX for Laravel](/es/packages/laravel-voicevox/app-guide.md)
- [Modo Engine API: Song (síntesis de voz cantada) - VOICEVOX for Laravel](/es/packages/laravel-voicevox/engine-song.md)
- [Get frame-by-frame volume from a score / singing voice synthesis query](/es/packages/laravel-voicevox/engine-api/query-editing/get-frame-by-frame-volume-from-a-score-singing-voice-synthesis-query.md)
- [Get frame-by-frame fundamental frequency from a score / singing voice synthesis query](/es/packages/laravel-voicevox/engine-api/query-editing/get-frame-by-frame-fundamental-frequency-from-a-score-singing-voice-synthesis-query.md)
- [Modo cliente: Song (síntesis de voz cantada) - VOICEVOX for Laravel](/es/packages/laravel-voicevox/client-song.md)
