[directmusic] Re: Compression: ADPCM?

  • From: "justin" <jlove@xxxxxxx>
  • To: <directmusic@xxxxxxxxxxxxx>
  • Date: Sat, 15 Mar 2003 17:08:26 -0800

Encapsulation in this context means hiding complexity--like the
cMusicManager class that MS provides in dmutil.  Here is the code for a
DirectX-based Ogg Vorbis player, it should be easy to convert to play
Ogg Vorbis files in whatever application you planned.  The code isn't
mine and I can't remember where I got it from but we were able to use it
to stream Ogg Vorbis files into our game...

Justin Love
University of Victoria

/*
This is a simple Ogg Vorbis player class for DirectX 8. Why Ogg Vorbis?
Because MP3 is evil ;) You have to pay 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. :)

*/

/**************************************************************
* OggPlayer.h
***************************************************************/

#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;
    }
};

/****************************************************
* OggPlayer.cpp
****************************************************/

#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;
    }
}




-----Original Message-----
From: directmusic-bounce@xxxxxxxxxxxxx
[mailto:directmusic-bounce@xxxxxxxxxxxxx] On Behalf Of Paul Stroud
Sent: March 13, 2003 3:53 AM
To: directmusic@xxxxxxxxxxxxx
Subject: [directmusic] Re: Compression: ADPCM?


Hi Justin,

I have no idea what encapsulation means, but it sounds good.  I've heard
of
Ogg before - does the encapsulation install the codec, because it's for
a
showreel

Cheers

Paul

> -----Original Message-----
> From: directmusic-bounce@xxxxxxxxxxxxx
> [mailto:directmusic-bounce@xxxxxxxxxxxxx]On Behalf Of justin
> Sent: 12 March 2003 17:49
> To: directmusic@xxxxxxxxxxxxx
> Subject: [directmusic] Re: Compression: ADPCM?
>
>
>
> I used Ogg Vorbis (similar compression and quality to MP3, except it
is
> open source and license-free) for a game last year. If you are
> interested I can post a nice encapsulation we used.
>
> Justin Love
> University of Victoria
>
> -----Original Message-----
> From: directmusic-bounce@xxxxxxxxxxxxx
> [mailto:directmusic-bounce@xxxxxxxxxxxxx] On Behalf Of Bjorn Lynne
> Sent: March 12, 2003 5:39 AM
> To: directmusic@xxxxxxxxxxxxx
> Subject: [directmusic] Re: Compression: ADPCM?
>
>
> Hi Paul,
>
> > Anyone know if there is anything else that will compress my wavs
into
> ADPCM
> > format other than DMP?
> >
> > I've heard that this compression can sound a bit grainy or slightly
> harsh,
> > but an external editor, like wavelab, might be able to render my
files
> a
> > touch more elegantly.
>
> You can save out ADPCM from SoundForge, but don't expect any miracles.
> ADPCM
> compression sounds great with *most* sounds, but a few sounds will
sound
> very gritty and harsh, no matter which program performed the
> compression.
>
> > I was tempted to go the mp3 route, but this 2.1 second thing sound
> like a
> > real pain - is it DMP that adds the glitch on play back? If you
encode
> in
> an
> > external editor and replace the runtime files, it must be in the
play
> back
> > that the glitch occurs.
>
> I'm not sure if you are talking about the little bit of silence added
to
> the
> beginning and end of the mp3 file, making it unsuitable for sounds
that
> need
> to start immediately, or looping sounds... but this is a weakness of
the
> mp3
> file format. I investigated this a lot a couple of years ago
(including
> communicating directly with one of the guys at Frauhofer who made the
> format), and there is apparently no way to create mp3 files that don't
> have
> this little bit of silence at the beginning and end... making mp3
> unsuitable
> for looping or low-latency playback.
>
> Actually, there is ONE program that does seem to make it possible:
> Flash. If
> you import a WAV file into Flash and set the compression to "mp3
> compression" inside Flash, then you can save out your Flash movie,
which
> will include an embedded mp3, which *will* loop smoothly in Flash
> Player.
> I'm guessing that this is because Flash has compressed to mp3 itself,
it
> knows exactly how much silence has been added to the beginning and
end,
> and
> is able to skip these parts when it plays back.
>
> > Is any of these compression formats more CPU friendly on decode?
>
> I believe mp3 is a great deal more CPU intensive than ADPCM. Somebody
> correct me if I'm wrong.
>
> Cheers,
> --
> Bjorn Lynne - Composer, Producer, Sound Designer
> Main music site: www.lynnemusic.com
>
>
>
>
>
>
>
>
>





Other related posts: