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

# Detailerklärung zu Score und Note - VOICEVOX für Laravel

> Erläutert Design, Frame-Längen-Berechnung und JSON-Verwaltungsmuster von Score und Note, die in der Song-Synthese von VOICEVOX für Laravel verwendet werden.

## Ziel

Wir ordnen die Spezifikationen von `Score` und `Note`, die bei der Song-Synthese oft Fragen aufwerfen.

Grundlage der Umsetzung sind die Quellen von `Revolution\Voicevox\Song\Note` / `Score` / `SongAudioQuery`.

## `Note`-Klasse

`Note` stellt eine Note (oder Pause) dar.

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

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

### Konstruktor-Argumente

| Argument | Typ            | Beschreibung                                                                |
| -------- | -------------- | --------------------------------------------------------------------------- |
| `length` | `int`          | Frame-Länge. Der Ganzzahl-Wert von `Sekunden × 93,75`                       |
| `lyric`  | `string`       | Liedtext. Bei Pausen leerer String `''`                                     |
| `key`    | `int\|null`    | MIDI-Notennummer. Bei Pausen `null`                                         |
| `id`     | `string\|null` | Hilfs-ID, die beim Erzeugen von `FrameAudioQuery` in `note_id` kopiert wird |

### Berechnung der Frame-Länge

`length` ist in Frames angegeben. Aus den Sekunden berechnet er sich wie folgt.

```text theme={null}
length = Sekunden × 93,75
```

Da dieser Wert nicht intuitiv ist, ist die Verwendung von `Note::len()` praktisch, wenn Sie mit MIDI vertraut sind.

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

* Es wird davon ausgegangen, dass eine Viertelnote `480 ticks` beträgt.
* Standard-BPM ist `125`.
* Da intern mit `round()` in eine Ganzzahl umgewandelt wird, akkumulieren sich bei langen Stücken Rundungsfehler.

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

<Warning>
  `Note::len()` ist praktisch, achten Sie jedoch bei langen Stücken auf akkumulierte Fehler. Bei Bedarf justieren Sie die Längen abschnittsweise nach.
</Warning>

### Darstellung von Pausen

Eine Pause besteht aus folgender Kombination.

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

### Übersicht über MIDI-Notennummern

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

## `Score`-Klasse

`Score` ist ein Partitur-Objekt, das ein Array von `Note` enthält.

```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),
]);
```

### Wichtige Regel

Die erste Note muss unbedingt eine Pause sein.

### Wichtige APIs

* Erzeugen mit `Score::make(array $notes)`
* Hinzufügen mit `add(Note $note)`
* Als JSON-String ausgeben mit `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>
  Der `Score`-Konstruktor hat bei Array-Input eine Implementierung, die leere Strings bzw. `null` in `lyric` absorbiert – so lässt sich auch Form-Input, der über die `ConvertEmptyStringsToNull`-Middleware läuft, gut verarbeiten.
</Info>

## Praxismuster: JSON-Datei-Verwaltung (empfohlen)

In echten Produkten ist es einfacher, Partituren nicht direkt in PHP zu schreiben, sondern in JSON zu verwalten.

1. Eigenes JSON-Format speichern
2. Einlesen und in `Note` / `Score` umwandeln
3. An `Voicevox::song()` übergeben und generieren

### JSON-Beispiel

```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" }
  ]
}
```

### Einlesen und Synthetisieren

```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');
```

## Verwandte Seiten

* [Client: Song](/de/packages/laravel-voicevox/client-song)
* [Native: Song](/de/packages/laravel-voicevox/native-song)
* [Engine-API: Song](/de/packages/laravel-voicevox/engine-song)


## Related topics

- [Engine-API-Modus: Song (Gesangs-Sprachsynthese) - VOICEVOX für Laravel](/de/packages/laravel-voicevox/engine-song.md)
- [Entwicklungsleitfaden für Engine-API-Integrationsanwendungen - VOICEVOX für Laravel](/de/packages/laravel-voicevox/app-guide.md)
- [VOICEVOX für Laravel](/de/packages/laravel-voicevox/index.md)
- [Installation und Konfiguration - VOICEVOX für Laravel](/de/packages/laravel-voicevox/installation.md)
- [Client-Modus: Song (Gesangs-Sprachsynthese) - VOICEVOX für Laravel](/de/packages/laravel-voicevox/client-song.md)
