본문 바로가기

Developement/C/C++

DirectX/Dsound 용 mp3 to wave 디코더, MinGW용 소스 & 라이브러리

* 기존 v2 소스에 버그가 있어서 업데이트 되었습니다. 현재 v3, 큰 파일을 모두 디코딩 가능.



 이 소스는 MinGW (gcc) 에서 DirectX sound (Dsound) 를 사용할 때, MP3 를 음원으로 사용할 경우 유용하게 쓸 수 있는 라이브러리 입니다.

 원래 소스는 ffmpeg 에 있는 것을 사용한 상태 이며, 원본 소스가 C 용으로 만들어 져 있었기 때문에 변경 없이 쓰도록 만든 상태 입니다. ( libmp3wav 라이브러리 소스는 g++ 로 컴파일 불가 )


사용 가능한 컴파일러 제한: i686-posix-dwarf-rev3, Built by MinGW-W64 project) 4.9.2


mp3towave 만 사용할 경우, libmp3wave.a 와 mp3wave.h 파일 압축

libmp3wave_win32_mingw_w64_v3.zip


C++ 에서 간편히 쓰기 위한 mp3wav 소스

mp3wav_class_src.zip


libmp3wave 전체 소스 (테스트 코드 포함) , CodeBlocks project 로 만들어 져 있음.

libmp3wave_src_mingw_codeblocks_v3.zip



간편히 DSound 에서 mp3에서 wave 로 헤더와 함께 자동으로 편리하게 쓰려면 libmp3wave 와, mp3wav_class 만 받아서 쓰면 됩니다. mp3wav class 는 mp3wav 를 new 로 만든 다음, OpenStream 하면 됩니다만, 한글이나 아시아권 문자열은 깨질 수 있는 점 고려 해 주시기 바랍니다. (내부 소스 참조)


위 소스와 라이브러리 조합을 통해서 다음과 같이 사용이 가능 합니다.

먼저, DSound 에서 버퍼와 디스크립션 등을 묶어 주는 함수를 하나 만들고 ...

bool AllocDSoundEx( IDirectSoundBuffer* &dsbuff, mp3wav* mp3w, DSBUFFERDESC &dsdesc )
{
    if ( pDSnd == NULL )
        return false;

    if ( mp3w == NULL )
        return false;

    unsigned char* mp3decodedbuff = NULL;

    int dcdsize = mp3w->WaveSize();

    if ( dcdsize <= 0 )
        return false;

    mp3decodedbuff = new unsigned char[ dcdsize ];

    if ( mp3decodedbuff == NULL )
        return false;

    memcpy( mp3decodedbuff, mp3w->WaveData(), dcdsize );

    ZeroMemory( &dsdesc, sizeof( DSBUFFERDESC ) );
    dsdesc.dwSize = sizeof( DSBUFFERDESC );
    dsdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPOSITIONNOTIFY;
    dsdesc.dwBufferBytes = dcdsize;
    dsdesc.lpwfxFormat = mp3w->WaveFormat();

    HRESULT hr = pDSnd->CreateSoundBuffer( &dsdesc, &dsbuff, NULL );

    if ( hr == S_OK )
    {
        void* pwData1 = NULL;
        void* pwData2 = NULL;
        DWORD lenData1 = 0;
        DWORD lenData2 = 0;

        dsbuff->Lock( 0,
                      dsdesc.dwBufferBytes,
                      &pwData1,
                      &lenData1,
                      &pwData2,
                      &lenData2,
                      0 );

        memcpy( pwData1, mp3decodedbuff, dsdesc.dwBufferBytes );
        dsbuff->Unlock( pwData1, dsdesc.dwBufferBytes, NULL, 0 );

        delete[] mp3decodedbuff;

        return true;
    }
#ifdef DEBUG
    else
    {
        printf("Failed to create dsound buffer : %d\n", hr);
    }
#endif

    return false;
}

이걸 오디오 할당 하는 부분에서 다음과 같이 쓰면 됩니다.

            mp3Bg = new mp3wav();
            if ( mp3Bg != NULL )
            {
                if ( mp3Bg->OpenStream( TEXT(".⁄background.mp3") ) == true )
                {
                    AllocDSoundEx( pDSSndBuffBack, mp3Bg, dsBuffDescBack );

                    delete mp3Bg;
                    mp3Bg = NULL;
                }
            }

여기서 mp3Bg 는 mp3wav* mp3Bg; 로 선언 되어 있고, pDSSndBuffBack 이나, dsBuffDescBack 은 각각 다음과 같습니다.

IDirectSoundBuffer*             pDSSndBuffBack;
DSBUFFERDESC                    dsBuffDescBack;

해당 소스와 라이브러리는 LGPL 규약을 지키며, 가져다 쓰시고 응용하는 것은 자유이나, 해당 소스로 부터 발생하는 노가다나 버그 등에 대해서는 일절 제가 관여 하지 않습니다.

또한 VisualC++ 관련 소스는 일절 다루지 않습니다.


*주의*

mmsystem 을 함께 쓰기 위해서는 link 에 winmm 을 추가 해 주어야 하며, dxguid, dsound, windowcodecs 를 함께 추가 해야 합니다.