PART 05 · 강의 2/3

Quartz 음악 클럭

Quartz Subsystem을 활용한 정밀한 음악 타이밍, BPM 동기화, 양자화 재생

01

Quartz Subsystem 개요

음악 타이밍을 오디오 렌더 스레드에서 정밀하게 관리하는 시스템

Quartz는 UE5의 오디오 렌더링 스레드에서 동작하는 음악 타이밍 시스템입니다. BPM, 박자를 기반으로 메트로놈을 생성하고, 사운드 재생을 양자화 경계(Quantization Boundary)에 맞춰 스케줄링합니다.

Quartz 핵심 구성 요소

구성 요소클래스역할
Quartz Subsystem UQuartzSubsystem 클럭 생성 및 관리. World Subsystem으로 접근
Quartz Clock FQuartzClock (내부) BPM과 박자를 추적하는 메트로놈
Clock Handle UQuartzClockHandle Blueprint/C++에서 클럭을 제어하는 핸들
Quantization Boundary FQuartzQuantizationBoundary 재생을 맞출 음악적 단위 (비트, 마디 등)
Quartz Subsystem
Create Clock (BPM, Time Sig)
Clock Handle
Play Quantized
Audio Component
02

클럭 생성과 설정

BPM, 박자, 양자화 경계를 설정하여 클럭 생성

C++ - Quartz Clock 생성
// Quartz Subsystem 가져오기 UQuartzSubsystem* QuartzSubsystem = GetWorld()->GetSubsystem<UQuartzSubsystem>(); // 클럭 설정 FQuartzClockSettings ClockSettings; ClockSettings.TimeSignature.NumBeats = 4; // 4/4 박자 ClockSettings.TimeSignature.BeatType = EQuartzTimeSignatureQuantization::QuarterNote; // 클럭 생성 (이름으로 식별) UQuartzClockHandle* ClockHandle = QuartzSubsystem->CreateNewClock( GetWorld(), "MusicClock", // 클럭 이름 ClockSettings ); // BPM 설정 ClockHandle->SetBeatsPerMinute( GetWorld(), FQuartzQuantizationBoundary(), // 즉시 적용 FOnQuartzCommandEventBP(), ClockHandle, 120.0f // 120 BPM );

Quantization Boundary 옵션

단위Enum 값120 BPM 기준 간격
마디 (Bar)Bar2.0초 (4/4 기준)
비트 (Beat)Beat0.5초
Half BeatHalfNote1.0초
Quarter NoteQuarterNote0.5초
Eighth NoteEighthNote0.25초
Sixteenth NoteSixteenthNote0.125초
TickTick거의 즉시
03

양자화 재생 (Play Quantized)

다음 양자화 경계에 맞춰 사운드를 정밀하게 재생

Play Quantized는 Audio Component의 재생을 다음 양자화 경계(비트, 마디 등)에 맞춰 스케줄링합니다. 이를 통해 여러 스템이 정확히 같은 비트에서 시작하거나, 마디의 첫 박에 맞춰 전환됩니다.

C++ - 양자화 재생
// 다음 마디 시작에 맞춰 재생 FQuartzQuantizationBoundary Boundary; Boundary.Quantization = EQuartzCommandQuantization::Bar; // 마디 경계 Boundary.Multiplier = 1.0f; Boundary.CountingDirection = EQuartzCommandDelegateSubType::CommandOnQueued; // Audio Component를 양자화 재생 MusicAudioComp->PlayQuantized( GetWorld(), ClockHandle, // Quartz Clock Handle Boundary, // 양자화 경계 FOnQuartzCommandEventBP() // 콜백 (선택) ); // 여러 스템을 동시에 양자화 재생 (수직 리믹싱) for (UAudioComponent* Stem : MusicStems) { Stem->PlayQuantized( GetWorld(), ClockHandle, Boundary, FOnQuartzCommandEventBP()); }
콜백 이벤트 활용

PlayQuantized의 콜백으로 재생이 실제로 시작된 시점을 알 수 있습니다. 이를 활용하여 시각적 이펙트(비트 동기화 UI)나 다음 구간 준비 로직을 정확한 타이밍에 실행할 수 있습니다.

04

메트로놈 이벤트 구독

비트, 마디 경계에서 게임플레이 이벤트를 발생시키기

Quartz Clock의 메트로놈 이벤트를 구독하면, 매 비트, 마디에 맞춰 게임 로직을 실행할 수 있습니다. 리듬 게임, 비트 동기화 UI, 음악 기반 레벨 디자인에 활용됩니다.

C++ - 메트로놈 이벤트 구독
// 메트로놈 이벤트 델리게이트 구독 ClockHandle->SubscribeToQuantizationEvent( GetWorld(), EQuartzCommandQuantization::Beat, // 매 비트마다 OnBeatDelegate, // 콜백 델리게이트 ClockHandle ); ClockHandle->SubscribeToQuantizationEvent( GetWorld(), EQuartzCommandQuantization::Bar, // 매 마디마다 OnBarDelegate, ClockHandle ); // 비트 콜백 함수 void UMusicManager::OnBeat( FName ClockName, EQuartzCommandQuantization QuantizationType, int32 NumBars, int32 Beat, float BeatFraction) { // 비트에 맞춰 시각적 펄스 이펙트 OnMusicBeat.Broadcast(Beat); // 강박(1번 비트)에서 특별 처리 if (Beat == 1) { OnMusicDownbeat.Broadcast(NumBars); } }
BPM 변경

Quartz는 런타임 BPM 변경을 지원합니다. SetBeatsPerMinute을 호출하면 다음 양자화 경계에서 새 BPM이 적용됩니다. 점진적 BPM 변화(accelerando/ritardando)는 매 마디마다 소량씩 변경하여 구현합니다.

SUMMARY

핵심 요약

  • Quartz는 오디오 렌더 스레드에서 동작하는 정밀 음악 타이밍 시스템이다
  • Clock Handle로 BPM, 박자를 설정하고 메트로놈을 관리한다
  • Play Quantized로 다음 비트/마디에 맞춰 사운드를 정밀하게 스케줄링한다
  • 메트로놈 이벤트를 구독하여 비트/마디에 동기화된 게임 로직을 실행한다
  • 런타임 BPM 변경이 가능하며, 양자화 경계에서 자연스럽게 적용된다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: Quartz Clock 기본 설정

UQuartzSubsystem을 통해 Quartz Clock을 생성하고 BPM을 설정하세요. Clock에 Quantization Boundary(Bar, Beat, Eighth 등)를 설정하고, OnQuantizationBoundary 델리게이트로 비트에 맞춰 로그를 출력하세요.

실습 2: 비트 동기화 사운드 재생

Quartz Clock의 비트에 동기화하여 드럼 패턴을 재생하세요. PlayQuantized()를 사용하여 Kick, Snare, HiHat을 각각 비트에 맞춰 재생하는 간단한 드럼 머신을 구현하세요.

심화 과제: Quartz 기반 리듬 게임 프로토타입

Quartz Clock을 활용하여 리듬 게임의 핵심 시스템을 구현하세요. 음악 비트에 맞춰 노트가 생성되고, 플레이어 입력의 정확도를 Quantization Boundary 기준으로 판정(Perfect, Good, Miss)하는 시스템을 만드세요.