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.
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.
length = Sekunden × 93,75
Da dieser Wert nicht intuitiv ist, ist die Verwendung von Note::len() praktisch, wenn Sie mit MIDI vertraut sind.
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.
Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60); // Viertelnote
Note::make(length: Note::len(960, 120), lyric: 'ミ', key: 64); // Halbe Note
Note::len() ist praktisch, achten Sie jedoch bei langen Stücken auf akkumulierte Fehler. Bei Bedarf justieren Sie die Längen abschnittsweise nach.
Darstellung von Pausen
Eine Pause besteht aus folgender Kombination.
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.
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()
$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);
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.
Praxismuster: JSON-Datei-Verwaltung (empfohlen)
In echten Produkten ist es einfacher, Partituren nicht direkt in PHP zu schreiben, sondern in JSON zu verwalten.
- Eigenes JSON-Format speichern
- Einlesen und in
Note / Score umwandeln
- An
Voicevox::song() übergeben und generieren
JSON-Beispiel
{
"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
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
Zuletzt geändert am 13. Juli 2026