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 부호 있는 정수
이 기사가 도움이 되었나요?
아니요
이 기사에 관한 의견 및 요청사항을 보내 주시기 바랍니다.