Zum Hauptinhalt springen

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

ArgumentTypBeschreibung
lengthintFrame-Länge. Der Ganzzahl-Wert von Sekunden × 93,75
lyricstringLiedtext. Bei Pausen leerer String ''
keyint|nullMIDI-Notennummer. Bei Pausen null
idstring|nullHilfs-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

NoteMIDI
C460
D462
E464
F465
G467
A469
B471
C572

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.
  1. Eigenes JSON-Format speichern
  2. Einlesen und in Note / Score umwandeln
  3. 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