프로그래밍 관련/사운드

사운드 다이렉트 OGG 재생

AlrepondTech 2011. 1. 5. 10:39
반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

ogg.zip
다운로드

출처:

http://cafe.naver.com/daegudim/10

막상 프로그램 코드를 하나 올릴려니 새로 하기 좀 귀찮아서

 

저번주에 타싸이트(다음게임카페)에 올렸던 설명글과 컴파일한 라이브러리파일 예제소스를 올립니다.

 

아래 설명글은 공게용 글이라 대충 썼습니다. 대충들 보시면 되요 ^^;;; 허허허

 

그래도 ( __);; 타싸이트에 올리지 않았던 예제소스가 동봉입니다. 귀엽게 봐주세요

 

아참전 장훈입니다. 이거 닉네임 어케 바꾸는지 원 적응안됨 에혀

 

======================== 설명글 시작 ===========================================================

그러고 보니 서버게시판 담당이었는데 서버풀그램을 안한지 좀 되어서 ^^;;;

 

나중에 보드게임에 사용한 서버소스만 올리고 오늘은 ogg에 대해서 ^^;;

 

얼마전 프로그램을 짜면서 음악을 삽입할려고 DSound를 이용하였습니다.

 

DSound를 보시면 아시겠지만 쓸만한 오디오 포맷이 Wave 밖에 없는터라(다른건 없었나 (__))

 

머 다들 음악품질이나 재생속도가 빠르다고 하니 어쩔수 없지만 자료를 옴길때 문제가 되는것이

 

요량문제더군요. 1분짜리 배경음악을 하나 틀려고 파일을 보면 대략 20메가가 넘더라구요

 

요량을 줄이는 다른 방법이 있을지 모르겠지만 지식이 짧은 터라 다들 ogg파일을 많이 쓴다고

 

하여 한번 해보았지요 첨에는 이곳저곳을 찾아 당기며 자료를 찾아봤지만 대략 난감하다가

 

알게된것이 ogg 포맷이 공개용이라 라이브러리를 가져다 쓰면된다는군요 또 이것이 문제가되는것이

 

자료를 또 찾아보니 건진것이 대략 http://www.ogg.org의 공식홈페이지를 이용하여 다운받아

 

사용 이란 문구하나 털썩~~ 좌절을 하면서 시작을 해보았습니다.

 

음~~ 왠지 한탄의 글이 되어가는듯한 그럼 여기서 사적인 얘기는 접고

 

Ogg Vorbis 라이브러리를 이용하여 ogg 파일을 wave파일로 디코딩하여 Dsound에서 재생하는법을

 

적어 보겠습니다.

 

우선 Ogg의 공식 홈페이지인 http://www.ogg.org에 가시면 ogg를 이용한 다양한 써비스관련

 

프로젝트를 볼수있다고 합니다.(영어가 짧아 봐도 잘 모르겠더라구요 대략 난감 ㅡㅡ;)

 

그리고 ogg 포맷을 사용하기 위해선 SDK를 받으셔야 하는데 SDK는 http://www.vorbis.com 에서

 

다운 받으실수 있습니다.(또 이게 난감한게 가서 다운로드 페이지를 봐도 이게 SDK인지 한시간

 

동안 고민을 했습니다. 같은 홈페이지인데도 왜이리 낫선지 한국의 인터넷문화가 진짜 편하게

 

느껴지더라구요 ㅡㅡ;; 사실 머리가 나쁜게 죄죠)

 

http://www.vorbis.com 홈페이지에 가시면 화면 중앙에

 

To obtain the source code, please see the xiph download page.
(소스코드를 받기위해 xiph 페이지로 가세요)

 

라는 문장을 클릭하셔서 SDK 다운로드 페이지로 가시면 Developer Downloads라고해서 SDK

 

라이브러리를 다운 받을수 있는 표가 보이실거에요 보자 현제 05.11.10자에 다시 가보니

 

현제 라이브러리 버전이 vorbis가 1.1.1 이군요 이 vorbis란게 보니 ogg라이브러리를 이용하여

 

코딩시 쉽게 사용할수있게 짜논 SDK같은데요 이 SDK를 받아 사용할수 있게 준비를 해보겠습니다.

 

Developer Downloads 표를 보시면 첫번째 항목인 libogg 라이브러리를 먼저 다운받고
(보시면 gz/zip 포맷이 있는데 친숙한 zip를 받기로 하죠 ^^;;)
바로 밑의 libvorbis 라이브러리를 받습니다.

 

다운 받으신 파일을 2개를 압축을 푸시고 이제 컴파일을 하여 라이브러리 파일과 dll 파일을 만들어야

합니다.

 

우선 라이브러리의 기본이 되는 ogglib 폴더에 들어가셔서 보시면 win32 폴더가 보이실 겁니다.

 

win32 폴더를 보시면 컴파일 해주는 bat 파일이 있을거에요(각파일의 용도는 제작을 마치고 설명을 하겠습니다.)
 - build_ogg_dynamic.bat
 - build_ogg_dynamic_debug.bat
 - build_ogg_static.bat
 - build_ogg_static_debug.bat
이 4개의 파일을 각각 실행을 하시면 해당파일이름의 폴더가 생기면서 폴더안에 lib/dll 파일이 컴파일 되어

생길겁니다.

이렀게 컴파일된 lib/dll 파일과 libogg폴더의 include 폴더안의 파일을 libvorbis폴더의

include => include
lib/dll => win32 폴더로 복사를 해주세요 그래야 기본 ogg 라이브러리를 가지고 vorbis라이브러리를 컴파일할수

 

있거든요 자 그럼 이렀게 마치고 libvorbis 폴더안에도 win32폴더로 들어가 12개의 bat파일을 실행파일

lib/dll 파일을 제작을 합니다.

이렀게 하시면 이제 코딩에 사용될 라이브러리 제작을 마친겁니다.

이제 사용할 include폴더와 방금까지 제작한 lib/dll파일등을 lib 폴더안에 모아서 사운드를 입힐 프로젝트에

 

복사를 하여 사용하시면 됩니다. 복사를 하셔서 툴의 폴더 지정을 하셔도 되고

 

#pragma comment(lib, "lib/ogg_static_d") 이런 식으로 직접 링크를 해주셔도 되는데 전 자주 쓰지 않는것을

 

폴더로 지정을 해놀려니 찝찝해서 pragma로 했습니다. 모 사용하신는 분들의 마음이시겠죠 ^^;;

 

그럼 코드 사용설명을 들어가기전에 컴파일 하여 생성한 lib 파일들의 이름에 따른 용도를 말씀 드릴게요

 

위에서 얘기를 할때 lib/dll 파일 두가지 종류가 있다고 했는데 말씀안하셔도 아시겠지만 ^^;;

괜한마음에 설명을 드리면 lib는 정적링크가 되겠구요 dll은 동적 링크로 사용하실때 쓰는겁니다.

허허 왠지 머슥해지는 ( __);;

 

제가 다음에 설명을 드릴 소스는 lib의 정적 링크로 하겠습니다. 동적링크로하면 줄수가 엄청 늘어나는고로 정적링크를 하여 설명을 드리겠습니다.

lib 파일중에서도 잘보시면 파일으름중 끝부분에 _d 붙은건 디버깅모드로 컴파일 할실때 삽입해야할

 

lib이구요 없는것은 릴리즈 모드에 사용될 파일입니다. 우선 ogg파일을 디코딩하여 wave파일로 재생할

때는 3개의 파일만을 사용하므로

 

간편하게 디버깅/릴리즈를 사용하실려면

 

#ifdef _DEBUG
// 디버깅 모드
#pragma comment(lib, "lib/ogg_static_d")
#pragma comment(lib, "lib/vorbis_static_d")
#pragma comment(lib, "lib/vorbisfile_static_d")
#else
// 릴리즈 모드
#pragma comment(lib, "lib/ogg_static")
#pragma comment(lib, "lib/vorbis_static")
#pragma comment(lib, "lib/vorbisfile_static")
#endif

 

이런 식으로 사용하시면 편하실 겁니다. ㅡㅡ; 어디까지나 저의 입장에서 말이죠 허허 ( __)

그리고 사운드 코드에 들어갈 include 파일은

 

#include    "vorbis/codec.h"
#include    "vorbis/vorbisfile.h"

 

이렀게 2가지가 되겠습니다. 라이브러리(oggvorbis 폴더) 안에 보시면 doc폴더가 있는데 그안을 보시면 여러가지

 

예제파일이 많습니다.

보시고 참고하세요( 머저야 봐도 모르겠더군요 ㅡㅡ;;)

 

자 그럼 셋팅이 끝나셨다면 간단희 ogg파일을 오픈/디코딩하여 DSound로 넘겨 재생을 해보도록 하죠..


쉬운 설명을 드리기위해 제작 소스를 펼쳐놓고 주석형식으로 설명을 드릴게요(어디까지나 저의 편의땜시 허허허 ( __))

 

 - 우선 DX 사운드랑 ogg파일을 불러다 셋팅할 vorbis 구조체를 선언합니다.
LPDIRECTSOUND8  m_pDSound;  // DX Sound
OggVorbis_File  m_sVF;   // OggVorbis 파일 구조체

 

 - Direct Sound 초기화 해주시고
if(FAILED(hr = DirectSoundCreate8(NULL, &m_pDSound, NULL)))
 return m_bInitDS = FALSE; 
m_pDSound->Initialize(NULL);
m_pDSound->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );

 - vorbis 고수준 입출력을 이용하여 ogg 파일을 불러다 wave 디코딩 DX 버퍼에 셋팅해줌니다.

 

// DX 에 셋팅하기 위해 임시 버퍼를 선언 했습죠
LPDIRECTSOUNDBUFFER  pTemp; // 임시버퍼


// 파일 입출력을 사용하여 ogg파일을 불러옵니다.
FILE *f;
f = fopen(filename, "rb");

 

// 파일 입출력으로 불러온 버퍼를
// vorbis의 ov_open함수를 사용하여 Ogg 파일오픈 오디오파일로 변환을 시작합니다.
ov_open(f, &m_sVF, NULL, 0);

 

// vorbis의 ov_info()함수를 이용 Ogg 정보 얻어오기
vorbis_info *vi = ov_info(&m_sVF,-1);

 

// DX SDK에서 지원하는 wave헤더 구조체
// Wave형식으로 디코딩하기 위하여 Wave 헤더파일을 셋팅해줘야 합니다.
// 첨엔 이 헤더를 어케체우고 어떤걸로 구조체를 만들어야 하니 심히 걱정을
// 했는데 MS에서 만들어논 구조체가 있다는걸 알고 모니터를 창문밖으로 던질뻔 했다는 ㅠ.ㅠ
WAVEFORMATEX        wfm;

// wave header 셋팅 후 Ogg파일에서 가져온 정보를 이용하여 채워준다
memset(&wfm, 0, sizeof(wfm));
wfm.cbSize          = sizeof(wfm);
wfm.nChannels       = vi->channels;
wfm.wBitsPerSample  = 16;     // ogg vorbis는 항상 16bit
wfm.nSamplesPerSec  = vi->rate;
wfm.nAvgBytesPerSec = wfm.nSamplesPerSec*wfm.nChannels*2; // 테이터사이즈 셋팅
wfm.nBlockAlign     = 2*wfm.nChannels;
wfm.wFormatTag      = 1;


// 이 wave header 파일을 셋팅해줄때 여러가지를 찾아보니 각의미가 대충
// 아래와 같이 직접 제작을 해서 쓰더군요 음악포맷의 문외한 이라 아~ 이렀구나 하고
// 대충 넘어갔습죠 부디 양해를 ㅡㅡ;;
// 대충 의미를 파악하여 위와 같이 셋팅을 해주면 다 잘돌아 갑니다 하하하 ㅠ.ㅠ
/*
struct WAVE_HEADER
{
 char riff_id[4];  //
 long riff_size;  //
 char wave_id[4];  //
 char format_id[4];  //
 long format_size;  // 데이터 블록의 길이
 short format_type;  // 파일의 포맷 종류
 // 0001H=MS PCM, 0101H=IBM u-law, 0102H=IBM a-law, 0103H=IBM AVC ADPCM
 short ChannelNo;  // 1=mono, 2=stereo
 long SamplesPerSec; // 초당 샘플수
 long AvgBytesPerSec; // 총당 bytes수 - 데이터 전송율
 short BytesPerSample;  // 모든 채널의 sample당 bytes수
 short BitsPerSample;  // 각 채널의 sample당 bit수
 char data_id[4];  //
 long data_size;  // wave데이터의 크기
}waveheader;
*/

 

// 아래는 SDK의 SSound 예제에서 카피를 한것이라 자세한 설명은
// 직접 SDK의 Sound 예제를 보심이 좋을것 같습니다.
// set up the buffer
DSBUFFERDESC desc;

desc.dwSize         = sizeof(desc);
desc.dwFlags        = 0;
desc.lpwfxFormat    = &wfm;
desc.dwReserved     = 0;
desc.dwBufferBytes  = BUFSIZE;


// CREATE TEMPORARY BUFFER
m_pDSound->CreateSoundBuffer(&desc, &pTemp, NULL );

DWORD   size = BUFSIZE;
DWORD   pos = 0;
int     sec = 0;
int     ret = 1;

char    *buf;
char    *buf2;

pTemp->Lock(0, size, (LPVOID*)&buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);
   
// 위에서 채워논 Ogg->wav 컨버전 헤더파일과
// vorbis의 ov_read함수를 이용 Ogg->wav파일로 컨버팅 한다
while(ret && pos<size)
{
    ret = ov_read(&m_sVF, buf+pos, size-pos, 0, 2, 1, &sec);
    pos += ret;
}

pTemp->Unlock( buf, size, NULL, NULL );

 

//아래쪽도 SDK의 SSound Wave파일 셋팅부 ^^;;;
//CREATE BUFFER TO MATCH ACTUAL SIZE OF FILE
desc.dwBufferBytes  = pos;
 
m_pDSound->CreateSoundBuffer(&desc, &m_sOggSound[m_iOggFlag].pDSBuffer, NULL );
LPDIRECTSOUNDBUFFER pDSBuffer->Lock(0, pos, (LPVOID*)&buf2, &pos, NULL, NULL, DSBLOCK_ENTIREBUFFER);
CopyMemory(buf2,buf,pos);
pDSBuffer->Unlock( buf2, size, NULL, NULL );
 
//DUMP THE TEMP BUFFER
pTemp->Release();

 

// 자 이제 마지막 까지 오셨는데 위에서 보시면 vorbis open함수를 이용하여
// ogg 파일을 열었으니 DXSound에 셋팅이 끝난고로 닫어주어야 합니다.
// 머 프로그램이란게 그렇듯이 열었으니 닫아주는게 예의 아니겠습니까..? ^0^/
// vorbis를 이용 Ogg정보를 다 사용한후 삭제해줍니다.
ov_clear(&m_sVF);
fclose(f); // 당연희 파일도 닫아주어야겠죠 허허허

 

자 그럼 이제 DXSound 초디화 해서 ogg파일 불러다 wave로 컨버전해서 셋팅해 주었습니다.
그리고 나서

pDSBuffer->GetStatus(&dwStatus);
pDSBuffer->SetCurrentPosition(0);
pDSBuffer->SetVolume( m_iVolume);
pDSBuffer->Play( 0, 0, NULL);

 

이런식으로 플레이를 시켜 주시면 되겠죠.

자 그럼 제가 아는 한에서 모든 설명을 드린것 같네요 ^^;; 나머지는 DXSound설정들을 해주어

음향을 조절하거나 하시면 될것 같구요 ogg파일쪽은 열었다가 닫아준다는 설명 밖에 없는것 같은데

다른 기능들을 알고 싶으시면 lib 폴더안의 doc 폴더안의 예제들을 보시면 되겠습니다.

허허허 왠지 글을 올리고 욕만 안먹으면 될것같네요 ^^;;;

 

 

 

=================================

=================================

=================================

 

 

 

 

반응형