wav 파일의 음량을 기반으로 립싱크(Web)
업데이트: 2021/05/13
개요
Cubism SDK for Web 샘플에서는 립싱크 기능을 사용하여 wav 파일의 오디오 데이터 음량을 기반으로 실시간으로 립싱크를 움직이는 기능을 제공합니다.
이 샘플은 Cubism 4 SDK for Web R3 beta1 이상에서 제공됩니다.
사용 방법
준비
모션에 연결된 wav 파일을 .json 파일에 기술합니다. 각 모션의 “Sound” 키에 해당하는 wav 파일 패스를 지정하십시오.
{ ・ ・ ・ "Motions": { "Idle": [ {"File":"motions/haru_g_idle.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_05.wav"}, {"File":"motions/haru_g_m15.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_06.wav"} ], "TapBody": [ {"File":"motions/haru_g_m06.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_01.wav"}, {"File":"motions/haru_g_m09.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_02.wav"}, {"File":"motions/haru_g_m20.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_03.wav"}, {"File":"motions/haru_g_m26.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_04.wav"} ] }, ・ ・ ・ }
위에서 지정한 위치에 wav 파일을 배치합니다. wav 파일의 패스가 올바르지 않으면 립싱크가 이루어지지 않습니다.
음량 취득 시작
샘플에서는 LAppWavFileHandler 클래스를 통해 wav 파일로부터의 정보 취득을 실시하고 있습니다.
LAppWavFileHandler::Start()를 실행하면 wav 파일에서 오디오 데이터를 읽고 립싱크를 수행하는 데 필요한 내부 상태를 초기화합니다.
public startMotion( group: string, no: number, priority: number, onFinishedMotionHandler?: FinishedMotionCallback ): CubismMotionQueueEntryHandle { ・ ・ ・ //voice const voice = this._modelSetting.getMotionSoundFileName(group, no); if (voice.localeCompare('') ! = 0) { let path = voice; path = this._modelHomeDir + path; this._wavFileHandler.start(path); } ・ ・ ・ }
상태 업데이트 및 음량 취득
LAppWavFileHandler::Update()를 실행하면 경과 시간에 해당하는 부분의 음량을 측정합니다. 측정 결과의 음량은 LAppWavFileHandler::GetRms()에서 취득할 수 있습니다. 취득한 음량을 립싱크 값으로서, 모델에 CubismModel::AddParameterValue 함수로 설정합니다.
샘플에서는 취득해 온 음량을 0.8배하여 립싱크 값으로 하고 있습니다. 여기서 사운드 라이브러리 등에서 취득한 음량을 립싱크 값으로 설정할 수도 있습니다.
public update(): void { ・ ・ ・ // 립싱크 설정 if (this._lipsync) { let value = 0.0; // 실시간으로 립싱크를 수행하는 경우 시스템에서 음량을 취득하여 0~1 범위의 값을 입력합니다. this._wavFileHandler.update(deltaTimeSeconds); value = this._wavFileHandler.getRms(); for (let i = 0; i < this._lipSyncIds.getSize(); ++i) { this._model.addParameterValueById(this._lipSyncIds.at(i), value, 0.8); } } ・ ・ ・ }
보충
- 샘플에는 오디오를 장치에서 재생하는 기능이 없습니다.
- LAppWavFileHandler::GetRms()는 현재 음량값을 0~1 범위에서 반환합니다.
- 음량의 단위는 RMS(제곱평균제곱근)입니다.
- 모든 채널 음성의 평균값을 계산합니다.
- 예를 들어 스테레오 오디오의 경우 좌우 채널을 포함한 오디오의 평균값을 계산합니다.
제한사항
샘플에서는 이하의 wav 파일의 로드에 대응하고 있습니다. 하기 포맷에 대응하지 않는 파일을 읽어들일 경우 립싱크가 실행되지 않습니다.
- Microsoft WAV(리틀 엔디안 형식)
- 리니어 PCM
- μ-raw, ADPCM 등으로 인코딩된 wav는 미대응입니다.
- 채널 수: 모노/스테레오
- 대응 비트 깊이: 8, 16, 24bit 부호 있는 정수