NEWBIE: Playing OggVorbis files without queued buffers

View: New views
4 Messages — Rating Filter:   Alert me  

NEWBIE: Playing OggVorbis files without queued buffers

by vexator :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello!
I'm new to OpenAL, I'm usually working with graphics :) I want to playback OggVorbis files, but not using queued buffers like in the sample. I got it working, but only if I manually adjust the buffer size. Seems that I'm missing something.. I've included my code (which is basically copy and pasted from the sample). The adjusted line is ulBufferSize *= 12. If I don't do this, only the first split second is being played.

Thank you!

Constructor:

FILE *pOggVorbisFile = fopen( m_strFilename.c_str(), "rb" );

fn_ov_open_callbacks( pOggVorbisFile, &sOggVorbisFile, NULL, 0, sCallbacks );

psVorbisInfo = fn_ov_info( &sOggVorbisFile, -1 );


ulFrequency = psVorbisInfo->rate;
ulChannels = psVorbisInfo->channels;

switch( ulChannels )
{
        case 1:

                ulBufferSize = ulFrequency >> 1;
                ulBufferSize -= (ulBufferSize % 2);
               
                ulFormat = AL_FORMAT_MONO16;

                break;

        case 2:

                ulBufferSize = ulFrequency;
                ulBufferSize -= (ulBufferSize % 4);
               
                ulFormat = AL_FORMAT_STEREO16;

                break;

        case 4:

                ulBufferSize = ulFrequency * 2;
                ulBufferSize -= (ulBufferSize % 8);
               
                ulFormat = alGetEnumValue( "AL_FORMAT_QUAD16" );

                break;

        case 6:

                ulBufferSize = ulFrequency * 3;
                ulBufferSize -= (ulBufferSize % 12);
               
                ulFormat = alGetEnumValue( "AL_FORMAT_51CHN16" );

                break;

        default:

                CLog::Get().Write( LOG_SERVER, "OpenAL: Unsupported format!" );

                return;
}


ulBufferSize *= 12; // <- why do I have to do this?!


pDecodeBuffer = (char*)malloc( ulBufferSize );
unsigned long ulBytesWritten = DecodeOggVorbis( &sOggVorbisFile, pDecodeBuffer, ulBufferSize, ulChannels );

alGenBuffers( 1, &m_uiBuffer );
alBufferData( m_uiBuffer, ulFormat, pDecodeBuffer, ulBytesWritten, ulFrequency );

alGenSources( 1, &m_uiSource );
alSourcei( m_uiSource, AL_BUFFER, m_uiBuffer );

Play() function:

int iState;
alGetSourcei( m_uiSource, AL_SOURCE_STATE, &iState );

if( iState == AL_PLAYING )
        return;

alSourcePlay( m_uiSource );

Re: NEWBIE: Playing OggVorbis files without queued buffers

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Saturday 07 March 2009 6:42:32 am vexator wrote:
> The adjusted line is ulBufferSize *= 12. If I
> don't do this, only the first split second is being played.
>
> ulBufferSize *= 12; // <- why do I have to do this?!

Likely because you're only specifying a buffer size that's originally 1/4th of
a second. ulFrequency is the number of sample frames per second (say, 44100).
For mono16, you divide this by 2 (giving a 22050 buffer size). Mono16 data
needs 2 bytes per sample frame (so one second would be 44100*2, or 88200,
bytes per second). Thus: 22050/88200 = 0.25, or 1/4th of a second.

The ulBufferSize *= 12 then increases that, to 12 * 0.25 (or 12 / 4) = 3
seconds.

Likely what you'll want to do is allocate a couple seconds to start with, then
every time the buffer fills up, realloc and double it's size (eg. start with 2
seconds, then expand to 4, 8, 16, 32..). When the Vorbis file ends, realloc
once more to the amount of data actually filled, so unused buffer space isn't
left over.

Hope that helps :)
- Chris
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: NEWBIE: Playing OggVorbis files without queued buffers

by vexator :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Bugzilla from chris.kcat@gmail.com wrote:
On Saturday 07 March 2009 6:42:32 am vexator wrote:
> The adjusted line is ulBufferSize *= 12. If I
> don't do this, only the first split second is being played.
>
> ulBufferSize *= 12; // <- why do I have to do this?!

Likely because you're only specifying a buffer size that's originally 1/4th of
a second. ulFrequency is the number of sample frames per second (say, 44100).
For mono16, you divide this by 2 (giving a 22050 buffer size). Mono16 data
needs 2 bytes per sample frame (so one second would be 44100*2, or 88200,
bytes per second). Thus: 22050/88200 = 0.25, or 1/4th of a second.

The ulBufferSize *= 12 then increases that, to 12 * 0.25 (or 12 / 4) = 3
seconds.

Likely what you'll want to do is allocate a couple seconds to start with, then
every time the buffer fills up, realloc and double it's size (eg. start with 2
seconds, then expand to 4, 8, 16, 32..). When the Vorbis file ends, realloc
once more to the amount of data actually filled, so unused buffer space isn't
left over.

Hope that helps :)
- Chris
Ah, so the size of the buffer was hard-coded in the sample. I didn't realize. But isn't there a simpler way to find out how big the buffer has to be? Can I, from the data provided by the OggVorbis lib, calculate the exact length of the file and from that the needed buffer size? I'm new to audio programming, so I'm not sure how to do it.

Anyway, thank you very much!

Re: NEWBIE: Playing OggVorbis files without queued buffers

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Saturday 07 March 2009 7:20:00 am vexator wrote:
> Ah, so the size of the buffer was hard-coded in the sample. I didn't
> realize. But isn't there a simpler way to find out how big the buffer has
> to be? Can I, from the data provided by the OggVorbis lib, calculate the
> exact length of the file and from that the needed buffer size? I'm new to
> audio programming, so I'm not sure how to do it.

It looks like ov_pcm_total can get the number of pcm sample frames (multiplied
by 2*channels for the number of bytes). Though, I assume this would only work
on seekable complete files, which isn't necessarily guaranteed to be true if
it's user-replaceable. Non-seekable files would likely return 0 or negative
for the size, so you would need to do the method I described earlier for them.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel