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

# 클라이언트 모드: 송 (노래 음성 합성) - VOICEVOX for Laravel

> VOICEVOX for Laravel의 클라이언트 모드에서 Score와 Note로 노래 음성 합성하는 방법을 설명합니다.

## 클라이언트 모드에서 노래 부르게 하기

클라이언트 모드의 노래 합성에서는 공식 VOICEVOX 엔진의 `sing_frame_audio_query`와 `frame_synthesis` API를 사용합니다.

토크와 달리, 먼저 `Score`와 `Note`를 조립할 필요가 있습니다.

## 사전 준비

```shell theme={null}
docker pull voicevox/voicevox_engine:cpu-latest
docker run --rm -p '127.0.0.1:50021:50021' voicevox/voicevox_engine:cpu-latest
```

## `Score`와 `Note` 만들기

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

$score = Score::make([
    Note::make(length: 15),
    Note::make(length: Note::len(ticks: 480, bpm: 120), lyric: 'ド', key: 60),
    Note::make(length: Note::len(480, 120), lyric: 'レ', key: 62),
    Note::make(length: Note::len(960, 120), lyric: 'ミ', key: 64),
    Note::make(length: 2),
]);
```

| 파라미터     | 타입          | 설명                   |
| -------- | ----------- | -------------------- |
| `length` | `int`       | 프레임 길이               |
| `lyric`  | `string`    | 가사. 빈 문자열 또는 생략 시 쉼표 |
| `key`    | `int\|null` | MIDI 노트 번호           |

<Tip>
  `Note::len($ticks, $bpm)`을 사용하면 MIDI의 ticks와 BPM에서 프레임 길이를 계산할 수 있습니다. 4분음표를 480 ticks로 취급하면 이해하기 쉽습니다.
</Tip>

## 기본적인 사용법

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

$score = Score::make([
    Note::make(length: 15),
    Note::make(length: Note::len(480, 120), lyric: 'ド', key: 60),
    Note::make(length: Note::len(480, 120), lyric: 'レ', key: 62),
    Note::make(length: Note::len(960, 120), lyric: 'ミ', key: 64),
    Note::make(length: 2),
]);

$response = Voicevox::song($score, teacher: 6000)
    ->generate(id: 3001);

$response->storeAs('client', 'song.wav');
```

### `teacher`와 `id`

* `teacher`: `sing_frame_audio_query`에 전달할 스타일 ID. 현재는 6000 하나만 존재하므로 기본값이 6000.
* `generate(id:)`: `frame_synthesis`에 전달할 스타일 ID

사용 가능한 노래 스피커 목록은 `singers()`에서 획득할 수 있습니다.

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

$singers = Voicevox::singers();
```

## `tap()`으로 F0와 볼륨 조정

Song에서는 `tap()`의 활용처가 특히 명확하며, `SongAudioQuery`를 조정한 뒤 `generate()`로 흘려보낼 수 있습니다.

```php theme={null}
use Revolution\Voicevox\Client\SongAudioQuery;
use Revolution\Voicevox\Voicevox;

$response = Voicevox::song($score, teacher: 6000)
    ->tap(function (SongAudioQuery $song) {
        $song->sync();
    })
    ->generate(id: 3001);
```

F0와 볼륨을 개별적으로 업데이트할 경우는 **F0 → 볼륨** 순서로 실행합니다.

```php theme={null}
->tap(function (SongAudioQuery $song) {
    $song->updateF0();
    $song->updateVolume();
})
```

Score를 변경한 뒤 재동기화할 때도 `tap()`이 편리합니다.

```php theme={null}
->tap(function (SongAudioQuery $song) {
    $song->score->notes[2] = Note::make(length: Note::len(480, 120), lyric: 'ファ', key: 65);
    $song->sync();
})
```

<Info>
  `tap()`의 발상은 [tap() 헬퍼와 Tappable 트레이트](/ko/advanced/tap)에 정리되어 있습니다. VOICEVOX for Laravel은 "반환값을 바꾸지 않고 중간 오브젝트만 조정하고 싶다"의 전형적인 예입니다.
</Info>

## 다음에 읽어볼 페이지

<Columns cols={3}>
  <Card title="Score와 Note 상세" href="/ko/packages/laravel-voicevox/song-score-note" icon="list-music">
    프레임 길이 계산과 JSON 관리 패턴을 확인합니다.
  </Card>

  <Card title="네이티브 Song" href="/ko/packages/laravel-voicevox/native-song" icon="music">
    같은 `Score`를 FFI 경유의 네이티브 모드에서 사용합니다.
  </Card>

  <Card title="VOICEVOX Core for PHP 사용법" href="/ko/packages/voicevox-core-php/usage" icon="library">
    코어 라이브러리 단독 음성 합성 흐름을 확인합니다.
  </Card>
</Columns>


## Related topics

- [네이티브 모드: 송 (노래 음성 합성) - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/native-song.md)
- [엔진 API 모드: 송 (노래 음성 합성) - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/engine-song.md)
- [클라이언트 모드: 토크 (텍스트 음성 합성) - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/client-talk.md)
- [클라이언트 모드 - 프리셋 - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/client-presets.md)
- [클라이언트 모드 - 사용자 사전 - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/client-user-dict.md)
