This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Ogg Vorbis Player Class Submitted by

This is a simple Ogg Vorbis player class for DirectX 8. Why Ogg Vorbis? Because MP3 is evil ;) You have to pay license royalties to Fraunhofer whenever you code an encoder / decoder. Ogg Vorbis on the other hand is really free. You'll need the Ogg Vorbis Sdk which you can obtained at http://www.vorbis.com/download_win.psp. Link the following files to your project: vorbisfile_static.lib, vorbis_static.lib, ogg_static, dsound.lib. Also be sure your include paths contain the SDK. To use the OggPlayer Class simply do the following:

    OggPlayer op;

    op.InitDirectSound(hwnd);
    op.OpenOgg("somemusic.ogg");
    op.Play();

    while(op.IsPlaying());

    op.Close();

You may use this code for whatever you want. :)

Currently browsing [oggplayer.zip] (2,958 bytes) - [OggPlayer.h] - (2,063 bytes)

    #include    <windows.h>                 // from your fave include dir ;)
    #include    <mmreg.h>

    #include    <dsound.h>                  // from the directx 8 sdk

    #include    <vorbis/codec.h>            // from the vorbis sdk
    #include    <vorbis/vorbisfile.h>       // also :)

    #define     BUFSIZE    65536*10         // buffer length

    class OggPlayer
    {
    protected:

        bool        bInitialized;           // initialized?
        bool        bFileOpened;            // have we opened an ogg yet?

        bool        bReleaseDS;             // release ds by ourselves?

        LPDIRECTSOUND8
                    pDS;                    // the directsound 8 object

        LPDIRECTSOUNDBUFFER
                    pDSB;                   // the buffer

        OggVorbis_File
                    vf;                     // for the vorbisfile interface

        int         nLastSection,           // which half of the buffer are/were
                    nCurSection;            // we playing?

        bool        bAlmostDone;            // only one half of the buffer to play
        bool        bDone;                  // done playing
        bool        bLoop;                  // loop?

    public:

        OggPlayer();
        ~OggPlayer();

        bool                                // initialize dsound ..
            InitDirectSound( HWND hWnd );

        inline void                         // .. or use already initialized
            UseDirectSound( LPDIRECTSOUND8 _pDS )
        {
            pDS = _pDS;
        }

        bool                                // this opens an oggvorbis for playing
            OpenOgg( char *filename );

        void                                // and this one closes it :)
            Close();

        void                                // play it again sam
            Play(bool loop = false);

        void                                // stop it
            Stop();

        void                                // be sure to call this from time to time
            Update();

        inline bool IsPlaying()
        {
            return !bDone;
        }
    };

Currently browsing [oggplayer.zip] (2,958 bytes) - [OggPlayer.cpp] - (4,564 bytes)

    #include "oggplayer.h"

    OggPlayer::OggPlayer()
    {
        bFileOpened     = false;
        bInitialized    = false;
        bReleaseDS      = false;
        pDS             = NULL;
        pDSB            = NULL;
        bLoop           = false;
        bDone           = false;
        bAlmostDone     = false;
    }

    OggPlayer::~OggPlayer()
    {
        if (bFileOpened)
            Close();

        if (bReleaseDS && pDS)
            pDS->Release();
    }

    bool OggPlayer::InitDirectSound( HWND hWnd )
    {
    	HRESULT hr;

    	if (FAILED(hr = DirectSoundCreate8(NULL, &pDS, NULL)))
            return bInitialized = false;

    	pDS->Initialize(NULL);
    	pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );

        bReleaseDS = true;

        return bInitialized = true;
    }

    bool OggPlayer::OpenOgg( char *filename )
    {
        if (!bInitialized)
            return false;

        if (bFileOpened)
            Close();

        FILE    *f;

        f = fopen(filename, "rb");
        if (!f) return false;

        ov_open(f, &vf, NULL, 0);

        // ok now the tricky part

        // the vorbis_info struct keeps the most of the interesting format info
        vorbis_info *vi = ov_info(&vf,-1);

        // set the wave format
    	WAVEFORMATEX	    wfm;

        memset(&wfm, 0, sizeof(wfm));

        wfm.cbSize          = sizeof(wfm);
        wfm.nChannels       = vi->channels;
        wfm.wBitsPerSample  = 16;                    // ogg vorbis is always 16 bit
        wfm.nSamplesPerSec  = vi->rate;
        wfm.nAvgBytesPerSec = wfm.nSamplesPerSec*wfm.nChannels*2;
        wfm.nBlockAlign     = 2*wfm.nChannels;
        wfm.wFormatTag      = 1;

        // set up the buffer
    	DSBUFFERDESC desc;

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

        desc.dwBufferBytes  = BUFSIZE*2;
        pDS->CreateSoundBuffer(&desc, &pDSB, NULL );

        // fill the buffer

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

        char    *buf;

        pDSB->Lock(0, size, (LPVOID*)&buf, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER);

        // now read in the bits
        while(ret && pos<size)
        {
            ret = ov_read(&vf, buf+pos, size-pos, 0, 2, 1, &sec);
            pos += ret;
        }

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

        nCurSection         =
        nLastSection        = 0;

        return bFileOpened = true;
    }

    void OggPlayer::Close()
    {
        bFileOpened = false;

        if (pDSB)
            pDSB->Release();
    }

    void OggPlayer::Play(bool loop)
    {
        if (!bInitialized)
            return;

        if (!bFileOpened)
            return;

        // play looping because we will fill the buffer
        pDSB->Play(0,0,DSBPLAY_LOOPING);

        bLoop = loop;
        bDone = false;
        bAlmostDone = false;
    }

    void OggPlayer::Stop()
    {
        if (!bInitialized)
            return;

        if (!bFileOpened)
            return;

        pDSB->Stop();
    }

    void OggPlayer::Update()
    {
        DWORD pos;

        pDSB->GetCurrentPosition(&pos, NULL);

        nCurSection = pos<BUFSIZE?0:1;

        // section changed?
        if (nCurSection != nLastSection)
        {
            if (bDone && !bLoop)
                Stop();

            // gotta use this trick 'cause otherwise there wont be played all bits
            if (bAlmostDone && !bLoop)
                bDone = true;

            DWORD   size = BUFSIZE;
            char    *buf;

            // fill the section we just left
            pDSB->Lock( nLastSection*BUFSIZE, size, (LPVOID*)&buf, &size, NULL, NULL, 0 );

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

            while(ret && pos<size)
            {
                ret = ov_read(&vf, buf+pos, size-pos, 0, 2, 1, &sec);
                pos += ret;
            }

            // reached the and?
            if (!ret && bLoop)
            {
                // we are looping so restart from the beginning
                // NOTE: sound with sizes smaller than BUFSIZE may be cut off

                ret = 1;
                ov_pcm_seek(&vf, 0);
                while(ret && pos<size)
                {
                    ret = ov_read(&vf, buf+pos, size-pos, 0, 2, 1, &sec);
                    pos += ret;
                }
            }
            else if (!ret && !(bLoop))
            {
                // not looping so fill the rest with 0
                while(pos<size)
                    *(buf+pos)=0; pos ++;

                // and say that after the current section no other sectin follows
                bAlmostDone = true;
            }

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

            nLastSection = nCurSection;
        }
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.