String chunkID;
int chunkSize;
String format;
String FMT;
int FMTSize;
int audioFormat;
int channelSize;
int sampleRate;
int byteRate;
int blockAlign;
int bitsPerSample;
String data;
int dataSize;
byte[] pcmData;
그리고 이 멤버 변수들에 대해서 getter 을 구현한다.
public String getChunkID()
{
return chunkID;
}
public int getChunkSize()
{
return chunkSize;
}
public String getFormat()
{
return format;
}
public String getFMT()
{
return FMT;
}
public int getFMTSize()
{
return FMTSize;
}
public int getAudioFormat()
{
return audioFormat;
}
public int getChannelSize()
{
return channelSize;
}
public int getSampleRate()
{
return sampleRate;
}
public int getByteRate()
{
return byteRate;
}
public int getBlockAlign()
{
return blockAlign;
}
public int getBitsPerSample()
{
return bitsPerSample;
}
public String getData()
{
return data;
}
public int getDataSize()
{
return dataSize;
}
public byte[] getPCMData()
{
return pcmData;
}
다음으로 load() 부분을 구현해야하는데, wav 파일을 바이너리 읽기 모드로 열어, 각각 바이트 스트림을 읽어주고, 원하는 데이터형으로 변환하는 작업이 포함된다. 예를 들어 String 데이터를 읽는 경우 지정된 길이만큼 읽어오고, Encoding을 통하여 String 으로 변환한다. 기본적으로 UTF-8 이 아니라, ANSI 인코딩으로 읽어오거나, C#의 경우 시스템 기본 인코딩인 Encoding.Default.로 읽어와도 무방하다.
FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
먼저 우리가 작업할 wav 파일은 일반 텍스트 파일이 아니기 때문에 파일 스트림으로 바이너리 모드로 파일을 열어야 한다. 이렇게 열어진 파일은 read 메서드를 사용해서 파일 바이너리를 순차적으로 읽어올 수 있다.
2. 청크 영역 읽기
먼저 첫 번째 청크 영역은 chunkID, chunkSize 으로 구성된다. 청크 ID를 의미하는 스트링과 청크 영역 이후의 크기를 의미하는 chunkSIze로 구분된다. 각각 4바이트 String과 4바이트 int 방식이다.
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
FMT = Encoding.Default.GetString(buffer);
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
FMTSize = BitConverter.ToInt32(buffer, 0);
buffer = new byte[2];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
audioFormat = BitConverter.ToInt16(buffer, 0);
buffer = new byte[2];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
channelSize = BitConverter.ToInt16(buffer, 0);
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
sampleRate = BitConverter.ToInt32(buffer, 0);
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
byteRate = BitConverter.ToInt32(buffer, 0);
buffer = new byte[2];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
blockAlign = BitConverter.ToInt16(buffer, 0);
buffer = new byte[2];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
bitsPerSample = BitConverter.ToInt16(buffer, 0);
4. 데이터 영역 읽기
이제 실제 오디오 데이터가 존재하는 PCM 영역을 읽어 바이너리 모드로 가져와야 한다. 이 데이터는 추후 short 방식으로 변환하고, 수치 계산을 통해 double 형으로 변환한 뒤 오디오 작업에 사용할 수 있는 진폭 정보가 담긴 실제 파형 데이터를 의미하기도 한다. 먼저 4바이트는 data 스트링, 4바이트는 data 길이, 마지막 모든 데이터가 비로소 pcmData의 바이너리 데이터이다.
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
data = Encoding.Default.GetString(buffer);
buffer = new byte[4];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
dataSize = BitConverter.ToInt32(buffer, 0);
pcmData = new byte[dataSize];
bufferSize = fileStream.Read(buffer, 0, buffer.Length);
이렇게 만들어진 WavFile 클래스를 활용해서 메인 폼 창에서 파일을 로드하고 오디오 속성을 가져오는 소프트웨어를 개발할 수 있다. 이번 장에서는 오디오 속성 정보를 가져오고, 다음 장에서 실제 그래프에 파형 데이터를 출력해보려고 한다.
private void load(String fileName)
{
WavFile wv = new WavFile();
wv.load(fileName);
richTextBox1.Clear();
richTextBox1.AppendText("청크 ID : ");
richTextBox1.AppendText(wv.getChunkID() + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("청크 영역 크기 : ");
richTextBox1.AppendText(wv.getChunkSize() +"");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("FMT 바이너리 스트링 : ");
richTextBox1.AppendText(wv.getFMT()+ "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("FMT 영역 크기 : ");
richTextBox1.AppendText(wv.getFMTSize()+ "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("채널 개수 : ");
richTextBox1.AppendText(wv.getChannelSize()==2?"스테레오": wv.getChannelSize()==1?"모노":"다수" + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("SampleRate : ");
richTextBox1.AppendText(wv.getSampleRate()+ "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("BitsPerSample : ");
richTextBox1.AppendText(wv.getBitsPerSample() + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("ByteRate : ");
richTextBox1.AppendText(wv.getByteRate() + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("BlockAlign : ");
richTextBox1.AppendText(wv.getBlockAlign() + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("AUDIO FORMAT(PCM:1) : ");
richTextBox1.AppendText(wv.getAudioFormat() + "");
richTextBox1.AppendText("\n");
richTextBox1.AppendText("데이터 영역 크기 : ");
richTextBox1.AppendText(wv.getDataSize() + "");
richTextBox1.AppendText("\n");
}
결과 예시