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

# Score 與 Note 詳細解說 - VOICEVOX for Laravel

> 解說 VOICEVOX for Laravel 的 Song 合成中所使用的 Score 與 Note 的設計、影格長度計算方式與 JSON 管理模式。

## 目的

整理在 Song 合成中容易讓人困惑的 `Score` 與 `Note` 規格。

實作依據為 `Revolution\Voicevox\Song\Note` / `Score` / `SongAudioQuery` 的原始碼。

## `Note` 類別

`Note` 代表一個音符（或休止符）。

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

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

### 建構子引數

| 引數       | 型別             | 說明                                          |
| -------- | -------------- | ------------------------------------------- |
| `length` | `int`          | 影格長度。將 `秒數 × 93.75` 取整後的值                   |
| `lyric`  | `string`       | 歌詞。休止符為空字串 `''`                             |
| `key`    | `int\|null`    | MIDI 音符編號。休止符為 `null`                       |
| `id`     | `string\|null` | 產生 `FrameAudioQuery` 時會複製到 `note_id` 的輔助 ID |

### 影格長度的計算

`length` 以影格為單位。從秒數換算方式如下：

```text theme={null}
length = 秒數 × 93.75
```

由於這個值不太直觀，如果你熟悉 MIDI，使用 `Note::len()` 會更實用。

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

* 以 4 分音符為 `480 ticks` 為前提
* 預設為 `125 BPM`
* 內部使用 `round()` 取整，因此長曲會逐漸累積捨入誤差

```php theme={null}
Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60);  // 4 分音符
Note::make(length: Note::len(960, 120), lyric: 'ミ', key: 64);  // 2 分音符
```

<Warning>
  `Note::len()` 雖然方便，但在長篇樂曲中請留意累積誤差。必要時可依區段重新調整長度。
</Warning>

### 休止符的表現

休止符是以下組合：

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

### MIDI 音符編號對照

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

## `Score` 類別

`Score` 是持有 `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),
]);
```

### 重要規則

第一個音符請務必設為休止符。

### 主要 API

* 使用 `Score::make(array $notes)` 建立
* 使用 `add(Note $note)` 追加
* 使用 `toJson()` 轉為 JSON 字串

```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>
  `Score` 建構子在陣列輸入時的實作會吸收 `lyric` 的空字串/`null`，因此透過 `ConvertEmptyStringsToNull` middleware 傳入的表單輸入也能輕鬆處理。
</Info>

## 實用模式：JSON 檔案管理（推薦）

在實際產品中，比起將樂譜直接寫在 PHP 內，以 JSON 管理更容易維運。

1. 儲存自訂格式的 JSON
2. 讀入後轉換為 `Note` / `Score`
3. 傳入 `Voicevox::song()` 進行生成

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

### 讀入與合成

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

## 相關頁面

* [用戶端：Song](/zh-TW/packages/laravel-voicevox/client-song)
* [原生：Song](/zh-TW/packages/laravel-voicevox/native-song)
* [引擎 API：Song](/zh-TW/packages/laravel-voicevox/engine-song)


## Related topics

- [Engine API 模式:Song(歌聲語音合成)- VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/engine-song.md)
- [引擎 API 整合應用開發指南 - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/app-guide.md)
- [.vvproj 檔案規格 - VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/vvproj.md)
- [Client 模式:Song(歌聲語音合成)- VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/client-song.md)
- [VOICEVOX for Laravel](/zh-TW/packages/laravel-voicevox/index.md)
