wav 파일 포맷에 대해 알아보자

 wave file format은 멀티미디어 파일 재생을 위해 마이크로소프트에서 만든 데이터 포맷RIFF(Resource Interchange File Format)의 하나이다. 본 포스트에서는 wave file format에 대해 알아보고 간단한 python code를 만들어 wave file을 분석해 보았다.

file format은 아래 문서를 참조 했다.

Multimedia Programming Interface and Data Specifications 1.0

Issued as a joint design by IBM Corporation and Microsoft Corporation
August 1991


RIFF chunk

wave file format은 RIFF 컨테이너를 사용하고 있다. 각 chunk는 ID, 길이 정보, 데이터를 가지고 있다. Chunk의 ID 및 Format는 big-endian이고, 그 외는 little-endian으로 저장되어 있다.

그림 1. wave file format RIFF chunk

wave 파일의 sub chunk에는 기본으로 fmt, data chunk가 들어가며, 필요에 따라 fact, cue points, playlist, associated data list 들이 들어간다.  

fmt Chunk

그림 2. fmt chunk

fmt chunk는 그림 2와 같은 형태로 이루어져 있으며, data chunk에 들어있는 오디오 데이터의 형식에 관한 정보를 가지고 있다.

 fmt chunk는 공통을 사용되는 'common filed'와 오디오 포맷에 따라 달라지는 'format specific field'로 나눠져 있다. format specific field는 오디오 format에 따라 존재하거나 존재하지 않을 수 있다.

common field의 의미는 아래와 같다.

wFormatTag : 데이터 포맷 

mmreg.h 참조 (https://docs.microsoft.com/en-us/windows/win32/api/mmreg/)

#define WAVE_FORMAT_PCM         1
#define  WAVE_FORMAT_UNKNOWN                    0x0000 /* Microsoft Corporation */
#define  WAVE_FORMAT_ALAW                       0x0006 /* Microsoft Corporation */
#define  WAVE_FORMAT_MULAW                      0x0007 /* Microsoft Corporation */  
...
#define  WAVE_FORMAT_EXTENSIBLE                 0xFFFE /* Microsoft */

wChannels : 채널 수
dwSamplesPerSec : 샘플링 레이트
dwAvgBytesPerSec : 데이터 레이트로 nSamplesPerSec  * nBlockAlign 이다.
wBlockAlign : Data 블록 사이즈이며, 바이트 단위이다.  (wBitsPerSample / 8) * nChannels 
wBitsPerSample : 샘플 당 비트 수를 의미한다. 


fact Chunk

그림 3. fact chunk

pcm이 아닌 데이터는 fact chunk를 가지고 있다. fact chunk는 dwSampleLegth 필드 하나만을 가지고 있다.

dwSampleLength 는 채널당 샘플의 개수를 나타낸다.


playlist chunk

playlist chunk('plst')는 cue-point에 대한 재생 순서를 지정하는데 사용된다.

그림 4. playlist chunk

dwSegments : play-segment 개수를 의미한다.
play-segment.dwName : cue-point의 이름으로 cue-points chunk의 cue-point의 이름과 일치해야 한다. 
play-segment.dwLength : 샘플의 섹션 길이를 지정한다.
play-segment.dwLoops : 섹션의 재생 횟수를 지정한다.


cue-points chunk

cue-points chunk ('cue ')에는 cue-point 들이 들어있으며, playlist chunk에서 이 cue-point를 사용한다. cue-point는 데이터 스트림에서 일련의 위치를 식별하는 데 사용된다.

그림 5. cue-points chunk

dwCuePoints : cue-point의 개수를 나타낸다.
cue-point.dwName : cue-point의 이름을 나타내며, 파일내에서 중복되지 않아야 한다.
cue-point.dwposition : cue-point의 샘플 위치를 나타낸다. 재생 순서 내의 순차적인 샘플의 번호.
cue-point.fccChunk : cue-point를 포함하는 chunk의 이름 또는 ChunkID를 나타낸다.
cue-point.dwChunkStart : cue-point를 포함하는 chunk의 파일내에서의 시작 위치를 나타낸다.
cue-point.dwBlockStart : cue-point 위치을 포함한 block의 시작 위치를 나태난다.
cue-point.dwSampleOffset : cue-point의 샘플 위치 나타낸다. block위치에서 offset으로 표현된다.


associated data chunk

associated data chunk('adtl')는 LIST chunk 내에 존재하며, wave 파일 내에 label, note, text, 별도의 데이터를 첨부하는 기능을 가지고 있다. 

그림 6. associated data chunk


adtl 내부의 labl, note, ltxt, file chunk의 dwName은 cue-points chunk안에 존재해야 한다.


PEAK chunk

peak chunk는 data chunk내의 오디오 샘플에서 amplitude가 가장 큰 위치와 값을 알려주는 역할을 한다.

그림 7. peak chunk

value는 float 값이며, position은 peak의 위치를 나타낸다. 


data Chunk

그림 4. data chunk


data chunk에는 샘플링된 오디오 데이터가 들어있다.

PCM 데이터가 들어있는 순서는 다음과 같다. 

8 bits mono pcm의 경우

| sample 1 | sample 2 | sample 3 | ...

8 bits stereo pcm의 경우

| left channel sample 1 | right channel sample 1 | left channel sample 2 | right channel sample 2 | ...

16 bits mono pcm의 경우

| low-order byte of sample 1 | high-order byte of sample 1 | low-order byte of sample 2 | high-order byte of sample 2 | ...



wave 파일 분석 예

https://en.wikipedia.org/wiki/WAV 페이지에서 몇 개의 wave파일을 다운 받은 후 간단히 python 코드를 만들어 분석해 보았다. 



wave file : 11k16bitpcm.wav

wave file format :  RIFF 304570 WAVE
---------
sub chunk id : fmt    cksize: 16
  wFormatTag : 1
  wChannels : 1
  dwSamplePerSec : 11025
  dwAvgBytesPerSec : 22050
  wBlockAlign : 2
  wBitsPerSample : 16
---------
sub chunk id : data   cksize: 304534



wave file : 8kulaw.wav

wave file format :  RIFF 110538 WAVE
---------
sub chunk id : fmt    cksize: 18
  wFormatTag : 7
  wChannels : 1
  dwSamplePerSec : 8000
  dwAvgBytesPerSec : 8000
  wBlockAlign : 1
  wBitsPerSample : 8
  cbsize : 0
---------
sub chunk id : fact   cksize: 4
  dwSampleLength : 110488
---------
sub chunk id : data   cksize: 110488



wave file : 8kmp38.wav

wave file format :  RIFF 13576 WAVE
---------
sub chunk id : fmt    cksize: 30
  wFormatTag : 85
  wChannels : 1
  dwSamplePerSec : 8000
  dwAvgBytesPerSec : 1000
  wBlockAlign : 1
  wBitsPerSample : 0
  cbsize : 12
    format specific data : 0x 010002000000480001007105
---------
sub chunk id : fact   cksize: 4
  dwSampleLength : 110488
---------
sub chunk id : data   cksize: 13514


관련 글

python의로 만든 wav 파일 parser 예제 코드

댓글

이 블로그의 인기 게시물

base64 인코딩 디코딩 예제 c 소스

아두이노(arduino) 심박센서 (heart rate sensor) 심박수 측정 example code

간단한 cfar 알고리즘에 대해

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

바로 프로젝트 적용 가능한 FIR Filter (low/high/band pass filter )를 c나 python으로 만들기