Jump to content
  • Advertisement
Sign in to follow this  
TheKrust

Ogg Vorbis Files (Please help!)

This topic is 4076 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement
Using libogg and libvorbis. There's pleanty of links in Google, and I have some code you can have if you want; although it obviously won't compile straight up, it's just for reference.

Header:

class PMusic : public EMusic, public PSoundBuffer
{
public:
PMusic();
virtual ~PMusic();

typedef ESP<PMusic> SP;

//========================================================================
// EMusic:
virtual void Play(bool bLoop);
virtual void Pause();
virtual void Stop();
virtual bool IsPlaying() const;
virtual void SetVolume(u8 nVolume);

//========================================================================
// PMusic:
bool OpenOgg(EResource::SP pResource);

protected:
//========================================================================
// PSoundBuffer:
virtual void FillBuffer(BYTE* pBuffer, size_t nLen);

private:
// Ogg vorbis callbacks
static size_t Ogg_Read(void* ptr, size_t size, size_t nmemb, void *datasource);
static int Ogg_Seek(void* datasource, ogg_int64_t offset, int whence);
static int Ogg_Close(void* datasource);
static long Ogg_Tell(void* datasource);


PMutex m_mutex;
EResource::SP m_pResource;
size_t m_nReadOffset;
OggVorbis_File m_theFile;
bool m_bLooping;

// Pre-decompressed vorbis buffer
static const size_t ms_nMaxBufferLen = 4096;
BYTE m_byBuffer[ms_nMaxBufferLen];
size_t m_nBufferLen;
};



Relevant source:

bool PMusic::OpenOgg(EResource::SP pResource)
{
// Setup callbacks
ov_callbacks theCallbacks;
theCallbacks.read_func = Ogg_Read;
theCallbacks.seek_func = Ogg_Seek;
theCallbacks.close_func = Ogg_Close;
theCallbacks.tell_func = Ogg_Tell;

// Open OGG file
m_pResource = pResource;
m_nReadOffset = 0;
if(ov_open_callbacks(this, &m_theFile, NULL, 0, theCallbacks) < 0)
{
m_pResource = 0;
m_nReadOffset = 0;
return false;
}

// Get file info and create buffer
vorbis_info* pInfo = ov_info(&m_theFile, -1);
if(!InitStreaming((int)pInfo->rate, 16, pInfo->channels))
{
memset(&m_theFile, 0, sizeof(m_theFile));
ov_clear(&m_theFile);
m_pResource = 0;
m_nReadOffset = 0;
return false;
}

return true;
}

//============================================================================

void PMusic::FillBuffer(BYTE* pBuffer, size_t nLen)
{
size_t nRemain = nLen;

// Any data in the buffer already?
if(m_nBufferLen != 0)
{
size_t nCopyLen = min(nRemain, m_nBufferLen);
memcpy(pBuffer, m_byBuffer + (ms_nMaxBufferLen-m_nBufferLen), nCopyLen);
nRemain -= nCopyLen;
pBuffer += nCopyLen;
m_nBufferLen -= nCopyLen;
}

// Read from the file into out buffer
m_mutex.Enter();
bool bEOF = false;
while(!bEOF)
{
// Read a chunk
Assert(m_nBufferLen == 0, "");
long lRet = ov_read(&m_theFile, (char*)m_byBuffer, ms_nMaxBufferLen, 0, 2, 1, NULL);
if(lRet == 0)
{
// If we're looping, go back to the start and carry on
if(m_bLooping)
ov_raw_seek(&m_theFile, 0);
else
bEOF = true;
}

// We read data ok
else if(lRet > 0)
{
if((size_t)lRet > nRemain)
{
m_nBufferLen = (size_t)lRet - nRemain;
memcpy(pBuffer, m_byBuffer, nRemain);
nRemain = 0;
break;
}
else
{
memcpy(pBuffer, m_byBuffer, lRet);
nRemain -= (size_t)lRet;
pBuffer = pBuffer + lRet;
}
}

else if(lRet == OV_HOLE)
{
// OV_HOLE can happen after we rewind the stream.
// Just re-loop to ov_read again
continue;
}

// Error
else
{
Assert(false, "ov_read returns error code %d", lRet);
break;
}
}
m_mutex.Exit();

// Fill the remainder of the buffer with silence
if(nRemain) memset(pBuffer, 0, nRemain);
return;
}

//============================================================================
// Callbacks shouldn't take the mutex, since they'll be called from a mutex-locked
// Ogg vorbis call anyway

size_t PMusic::Ogg_Read(void* ptr, size_t size, size_t nmemb, void* datasource)
{
PMusic* pThis = (PMusic*)datasource;
size_t nSize = size*nmemb;
if(pThis->m_nReadOffset + nSize > pThis->m_pResource->GetLength())
nSize = pThis->m_pResource->GetLength() - pThis->m_nReadOffset;
memcpy(ptr, pThis->m_pResource->GetData()+pThis->m_nReadOffset, nSize);
pThis->m_nReadOffset += nSize;
return nSize;
}

int PMusic::Ogg_Seek(void* datasource, ogg_int64_t offset, int whence)
{
PMusic* pThis = (PMusic*)datasource;

switch(whence)
{
case SEEK_SET: pThis->m_nReadOffset = (size_t)offset; break;
case SEEK_CUR: pThis->m_nReadOffset += (size_t)offset; break;
case SEEK_END: pThis->m_nReadOffset = (size_t)(pThis->m_pResource->GetLength() - offset); break;
}

if(pThis->m_nReadOffset > pThis->m_pResource->GetLength())
{
pThis->m_nReadOffset = 0;
return -1;
}
return 0;
}

int PMusic::Ogg_Close(void* datasource)
{
PMusic* pThis = (PMusic*)datasource;
pThis->m_nReadOffset = 0;
return 0;
}

long PMusic::Ogg_Tell(void* datasource)
{
PMusic* pThis = (PMusic*)datasource;
return (long)pThis->m_nReadOffset;
}


Examples off all the relevant Ogg vorbis functions should be in there.

Hope this helps,
Steve

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!