본문 바로가기

Programming/DirectX

[DirectSound] 1. Wave 파일의 구조

반응형

DirectSound는 DirectX 중에서 음악의 재생 및 녹음과 같은 기능을 담당합니다.

DirectSound를 하기 전에 기본적으로 wav 파일의 구조를 알아보겠습니다.

간단하게 wav 파일은 헤더(Header) 정보 + PCM 데이터로 볼 수 있습니다.

즉, 실제 소리에 대한 정보인 PCM에 헤더를 앞에 추가한 것입니다.

역으로는 pcm 정보를 이용해서 wav를 만들 수도 있다는 의미입니다.

그러기 위해서는 몇 가지 알아야할 사항이 있는데, Sampling Rate, 샘플당 바이트수, 채널 등의 정보가 필요합니다.

이런 정보들이 wav 파일의 헤더에 들어가게 되는 겁니다.

이런 정보들은 재생하는데 필요한 정보들입니다.

CoolEdit나 Audition 등의 프로그램으로 wav를 열면 바로 열 수 있습니다.

하지만 pcm을 열려고 하면 부가적인 정보를 요구합니다.

이유는 pcm은 어떻게 읽어야 하는 지에 대한 정보가 파일 내부에 없기 때문입니다.

이런 정보들이 wav에는 헤더에 존재하지만, pcm에는 없기 때문에 다음과 같이 지정을 해줘야 합니다.

바로 이런 식으로 Format을 설정해주게 됩니다.

wav 헤더를 참조하면서 하나하나 상세하게 알아보도록 하겠습니다.

그럼 wav파일의 구조를 보겠습니다.

이것이 wav 파일의 구조입니다.

0~44Byte까지는 헤더이고 가장 밑에 실제 데이터가 있는 것을 볼 수 있습니다.

wav 파일의 경우, chunk라고 하는 몇 개의 덩어리가 있습니다.

맨 처음 부분이 RIFF Chunk로 이 부분은 이 파일이 RIFF 파일 형식이라는 걸 말해줍니다.

RIFF는 Resource InterChange File Format으로 avi나 wav같은 파일 형식을 나타내기 위해서 사용합니다.

헤더의 각 부분에 대한 정보는 다음과 같습니다.

Chunk ID : 여기에는 'RIFF' 가 들어가게 됩니다.(0x52494646 Big-Endian이라 순서대로 RIFF입니다.)

Chunk Size : 파일 크기에서 Chunk ID와 Chunk Size(8) 만큼 뺀 값으로 파일 크기 - 8입니다.
Little-Endian이기 때문에 0x24080000 으로 되어 있으면 거꾸로 0x00000824로 되어 파일 크기는 2084가 됩니다.

Format : 파일의 포맷입니다. wav파일의 경우는 대문자로 'WAVE'가 들어갑니다.
Big-Endian으로 기록되기 때문에 그냥 'WAVE'로 저장됩니다.

Subchunk1 ID : 첫번째 Sub chunk로 재생에 필요한 PCM의 형식을 저장하는 chunk의 시작부분입니다.
여기에는 'fmt '가 들어가는데 fmt 뒤에 공백이 존재합니다.
즉, 0x666d7420가 Big-Endian으로 기록됩니다.

Subchunk1 Size : Subchunk1 Size는 실제 기록되는 데이터 포맷의 크기입니다.
이 영역 밑에 기록된 Subchunk1의 크기를 나타내며 16 사이즈를 갖습니다.
Little-Endian으로 0x10000000 입니다.

AudioFormat : PCM의 경우 1이고 크기는 2바이트입니다.
Little-Endian으로 0x0100 입니다.

NumChannels : 채널 수를 나타내며 Mono는 1, Stereo는 2입니다.
이 부분도 2바이트로 구성되어 있으며, Stereo의 경우 0x0200입니다.(Little-Endian)

SampleRate : Sample Rate로 1초를 몇 개의 조각으로 세분화할 것인지입니다.
4바이트로 구성되며, 22050의 경우에는 0x00005622인데 Little-Endian으로 0x22560000이 됩니다.

ByteRate : 이것은 SampleRate * NumChannels * BitsPerSample / 8로 구해집니다.
BitsPerSample은 각 샘플을 몇개의 비트로 표현하는가 입니다.
ByteRate는 쉽게 말하면 1초의 소리가 차지하는 바이트 수입니다.
SampleRate가 22050, Stereo(2), 한 샘플을 16bit로 표현하면 22050 * 2 * 16 / 8 = 88280이 됩니다.
4바이트 Little-Endian으로 되어 있기 때문에 0x88580100이 됩니다.

BlockAlign : 전체 채널을 포함하는 한 샘플의 크기입니다.
2채널, 샘플당 비트수가 16bit이면 2 * 16 / 8(byte로 변환하기 위해서)입니다.
즉, 크기는 4가 되고 Little-Endian 방식으로 2바이트로 표현되므로 0x0400이 됩니다.

BitsPerSample : 위에 설명했듯이, 샘플당 비트수입니다.
1초를 샘플로 나누고 각각의 샘플을 몇 개의 비트로 표현할 지를 나타냅니다.
비트수가 커질 수록 음질은 나아지겠지만 용량을 그만큼 많이 차지하게 됩니다.
2바이트 Little-Endian 방식으로 표현되므로 16bit의 경우에는 0x1000이 됩니다.

Subchunk2 ID : 'data'가 들어가며, 모든 문자열과 같이, Big-Endian으로 들어갑니다.
즉, 0x64617461이 들어갑니다.

Subchunk2 Size : Subchunk2의 사이즈.
즉 실제 PCM 데이터의 사이즈가 들어갑니다.
(BitsPerSample / 8) * NumChannels * 실제 샘플수로 계산됩니다.

Data : 실제 PCM 데이터입니다.

약간 복잡한 내용이지만 재생을 하는데 중요한 정보입니다.

Wave의 실제 구조를 작성한 자료가 있어서 첨부합니다.

대략적인 구조를 파악할 수 있으면 됩니다.

Wave 파일의 구조를 통해서 알 수 있는 Wave 파일의 한계는 다음과 같습니다.

1. 4GB 이상의 Wave 파일을 생성할 수 없다.

SubChunk2 Size가 4바이트로 구성되어 있기 때문에 4GB 이상의 크기를 담을 수 없습니다.

다만 순환 버퍼를 통해서 재생을 할 때는 길이의 제약없이 재생은 가능합니다.

2. Information Field가 존재하지 않는다.

FLAC이나 MP3같은 경우는 곡 정보를 포함할 수 있지만 Wave는 그런 기능이 존재하지 않습니다.

반응형