Updated IAudio Decoder (and all official decoders) to provide Total Time/Size/Decoded Size of an audio stream and the current position (in time, size, and decoded size). Audio Sources also expose this information.

This commit is contained in:
Joshua Jones 2010-02-17 03:49:22 +00:00
parent 869057b230
commit ffb0a8bdf9
12 changed files with 263 additions and 11 deletions

View File

@ -47,6 +47,14 @@ namespace cAudio
virtual void loop(const bool& toLoop);
virtual bool seek(const float& seconds, bool relative = false);
virtual float getTotalAudioTime();
virtual int getTotalAudioSize();
virtual int getCompressedAudioSize();
virtual float getCurrentAudioTime();
virtual int getCurrentAudioPosition();
virtual int getCurrentCompressedAudioPosition();
virtual bool update();
virtual void release();

View File

@ -32,6 +32,12 @@ namespace cAudio
virtual int readAudioData(void* output, int amount);
virtual bool setPosition(int position, bool relative);
virtual bool seek(float seconds,bool relative);
virtual float getTotalTime();
virtual int getTotalSize();
virtual int getCompressedSize();
virtual float getCurrentTime();
virtual int getCurrentPosition();
virtual int getCurrentCompressedPosition();
protected:
//! Callbacks used for read memory

View File

@ -23,6 +23,12 @@ namespace cAudio
virtual int readAudioData(void* output, int amount);
virtual bool setPosition(int position, bool relative);
virtual bool seek(float seconds,bool relative);
virtual float getTotalTime();
virtual int getTotalSize();
virtual int getCompressedSize();
virtual float getCurrentTime();
virtual int getCurrentPosition();
virtual int getCurrentCompressedPosition();
private:
unsigned int Frequency;

View File

@ -26,6 +26,12 @@ namespace cAudio
virtual int readAudioData(void* output, int amount);
virtual bool setPosition(int position, bool relative);
virtual bool seek(float seconds,bool relative);
virtual float getTotalTime();
virtual int getTotalSize();
virtual int getCompressedSize();
virtual float getCurrentTime();
virtual int getCurrentPosition();
virtual int getCurrentCompressedPosition();
private:
short Channels;

View File

@ -177,6 +177,36 @@ namespace cAudio
return state;
}
float cAudioSource::getTotalAudioTime()
{
return Decoder->getTotalTime();
}
int cAudioSource::getTotalAudioSize()
{
return Decoder->getTotalSize();
}
int cAudioSource::getCompressedAudioSize()
{
return Decoder->getCompressedSize();
}
float cAudioSource::getCurrentAudioTime()
{
return Decoder->getCurrentTime();
}
int cAudioSource::getCurrentAudioPosition()
{
return Decoder->getCurrentPosition();
}
int cAudioSource::getCurrentCompressedAudioPosition()
{
return Decoder->getCurrentCompressedPosition();
}
bool cAudioSource::update()
{
cAudioMutexBasicLock lock(Mutex);

View File

@ -146,6 +146,36 @@ namespace cAudio
}
return false;
}
float cOggDecoder::getTotalTime()
{
return ov_time_total(&oggStream, -1);
}
int cOggDecoder::getTotalSize()
{
return ov_pcm_total(&oggStream, -1) * vorbisInfo->channels;
}
int cOggDecoder::getCompressedSize()
{
return ov_raw_total(&oggStream, -1);
}
float cOggDecoder::getCurrentTime()
{
return ov_time_tell(&oggStream);
}
int cOggDecoder::getCurrentPosition()
{
return ov_pcm_tell(&oggStream) * vorbisInfo->channels;
}
int cOggDecoder::getCurrentCompressedPosition()
{
return ov_raw_tell(&oggStream);
}
};
#endif

View File

@ -68,4 +68,53 @@ namespace cAudio{
int amountToSeek = seconds * (float)Frequency * (float)SampleSize;
return setPosition(amountToSeek, relative);
}
float cRawDecoder::getTotalTime()
{
int SampleSize = 0;
if(Format == EAF_8BIT_MONO)
SampleSize = 1;
else if(Format == EAF_8BIT_STEREO)
SampleSize = 2;
else if(Format == EAF_16BIT_MONO)
SampleSize = 2;
else
SampleSize = 4;
return (float)Stream->getSize() / ((float)Frequency * (float)SampleSize);
}
int cRawDecoder::getTotalSize()
{
return Stream->getSize();
}
int cRawDecoder::getCompressedSize()
{
return Stream->getSize();
}
float cRawDecoder::getCurrentTime()
{
int SampleSize = 0;
if(Format == EAF_8BIT_MONO)
SampleSize = 1;
else if(Format == EAF_8BIT_STEREO)
SampleSize = 2;
else if(Format == EAF_16BIT_MONO)
SampleSize = 2;
else
SampleSize = 4;
return (float)Stream->getCurrentPos() / ((float)Frequency * (float)SampleSize);
}
int cRawDecoder::getCurrentPosition()
{
return Stream->getCurrentPos();
}
int cRawDecoder::getCurrentCompressedPosition()
{
return Stream->getCurrentPos();
}
}

View File

@ -202,7 +202,35 @@ namespace cAudio
return setPosition(amountToSeek, relative);
}
float cWavDecoder::getTotalTime()
{
return (float)Stream->getSize() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
}
int cWavDecoder::getTotalSize()
{
return Stream->getSize();
}
int cWavDecoder::getCompressedSize()
{
return Stream->getSize();
}
float cWavDecoder::getCurrentTime()
{
return (float)Stream->getCurrentPos() / ((float)SampleRate * (float)Channels * (float)(BitsPerSample/8));
}
int cWavDecoder::getCurrentPosition()
{
return Stream->getCurrentPos();
}
int cWavDecoder::getCurrentCompressedPosition()
{
return Stream->getCurrentPos();
}
};
#endif

View File

@ -52,6 +52,24 @@ namespace cAudio
\param relative: Whether the number in position is relative to the current position.
\return True on success, False on failure. */
virtual bool seek(float seconds, bool relative) = 0;
//! If seeking is supported, will return the length of the audio steam in seconds. Returns a negative number if the total time cannot be determined.
virtual float getTotalTime() = 0;
//! If available, returns the total decoded size of the audio stream. Returns a negative number if this cannot be determined.
virtual int getTotalSize() = 0;
//! Returns the compressed (original) size of the audio stream, before decoding.
virtual int getCompressedSize() = 0;
//! If seeking is supported, will return the current position in the stream in seconds. Returns a negative number if the current time cannot be determined.
virtual float getCurrentTime() = 0;
//! If available, returns the current position in the decoded audio stream in bytes. Returns a negative number if this cannot be determined.
virtual int getCurrentPosition() = 0;
//! Returns the position in the compressed (original) audio stream before decoding.
virtual int getCurrentCompressedPosition() = 0;
protected:
//! Pointer to the data source to take audio data from.
IDataSource* Stream;

View File

@ -41,6 +41,14 @@ namespace cAudio
\return True on success, False if the codec does not support seeking. */
virtual bool seek(const float& seconds, bool relative = false) = 0;
virtual float getTotalAudioTime() = 0;
virtual int getTotalAudioSize() = 0;
virtual int getCompressedAudioSize() = 0;
virtual float getCurrentAudioTime() = 0;
virtual int getCurrentAudioPosition() = 0;
virtual int getCurrentCompressedAudioPosition() = 0;
//! Normally called every frame by the audio manager to update the internal buffers
//! Note: For internal use only.
virtual bool update() = 0;

View File

@ -3,7 +3,7 @@
#include <string.h>
cMP3Decoder::cMP3Decoder(IDataSource* stream) : IAudioDecoder(stream), Context(0x0),
Valid(false), DataOffset(0), NumChannels(0), Frequency(0)
Valid(false), DataOffset(0), NumChannels(0), Frequency(0), TotalSize(0), CurrentPosition(0)
{
if(Stream && Stream->isValid() && Stream->getSize() > 0)
{
@ -64,6 +64,29 @@ cMP3Decoder::cMP3Decoder(IDataSource* stream) : IAudioDecoder(stream), Context(0
Context->parse_only = 0;
Stream->seek(DataOffset, false);
//Now, calculate our max size
Context->parse_only = 1;
int curPos = DataOffset;
while(curPos < Stream->getSize())
{
outputSize = 0;
inputSize = Stream->read(inputBuffer, 4096);
int rv = mpaudec_decode_frame( Context, tempBuffer, &outputSize, inputBuffer, inputSize);
if(rv < 0)
return;
curPos += rv;
TotalSize += Context->frame_size;
Stream->seek(curPos, false);
}
Context->parse_only = 0;
Stream->seek(DataOffset, false);
//This is a hack, for some reason on every mp3 I tested, Total Size was roughly 4 times less than the real value.
TotalSize *= 4;
Valid = true;
}
}
@ -135,8 +158,6 @@ int cMP3Decoder::readAudioData(void* output, int amount)
return 0;
int rv = mpaudec_decode_frame( Context, CurrentPacket.data, &CurrentPacket.size, inputBuffer, inputSize);
Stream->seek(oldPos + rv, false);
//Oops, error...
if(rv < 0)
@ -149,12 +170,7 @@ int cMP3Decoder::readAudioData(void* output, int amount)
if(Frequency != Context->sample_rate)
return -1;
//Error from reading, but we need to try to move ahead to avoid stopping the feed since it may be recoverable
if(CurrentPacket.size < 0)
{
CurrentPacket.size = Context->frame_size;
memset(CurrentPacket.data, 0, CurrentPacket.size);
}
Stream->seek(oldPos + rv, false);
}
//If we have data left since last time, put it in if we have space
@ -166,6 +182,7 @@ int cMP3Decoder::readAudioData(void* output, int amount)
//Dump in all our data
memcpy(output, CurrentPacket.data + CurrentPacket.read, amountLeft);
CurrentPacket.read += amountLeft;
CurrentPosition += amountLeft;
return amountLeft;
}
else
@ -173,6 +190,7 @@ int cMP3Decoder::readAudioData(void* output, int amount)
//Not enough space for all our data, put in a little bit
memcpy(output, CurrentPacket.data + CurrentPacket.read, amount);
CurrentPacket.read += amount;
CurrentPosition += amount;
return amount;
}
}
@ -204,6 +222,8 @@ bool cMP3Decoder::setPosition(int position, bool relative)
Context->frame_size = oldContext.frame_size;
Context->sample_rate = oldContext.sample_rate;
CurrentPosition = 0;
Context->parse_only = 1;
int lastFrameSize = 0;
while(Stream->getCurrentPos() < position)
@ -223,8 +243,6 @@ bool cMP3Decoder::setPosition(int position, bool relative)
int outputSize = 0;
int rv = mpaudec_decode_frame( Context, tempBuffer, &outputSize, inputBuffer, inputSize);
Stream->seek(oldPos + rv, false);
//Oops, error...
if(rv < 0)
@ -233,6 +251,9 @@ bool cMP3Decoder::setPosition(int position, bool relative)
return false;
}
Stream->seek(oldPos + rv, false);
CurrentPosition += Context->frame_size;
lastFrameSize = rv;
}
Context->parse_only = 0;
@ -253,3 +274,34 @@ bool cMP3Decoder::seek(float seconds, bool relative)
}
return false;
}
float cMP3Decoder::getTotalTime()
{
return (float)TotalSize / ((float)Frequency * (float)NumChannels * 2.0f);
}
int cMP3Decoder::getTotalSize()
{
return TotalSize;
}
int cMP3Decoder::getCompressedSize()
{
return Stream->getSize();
}
float cMP3Decoder::getCurrentTime()
{
return (float)CurrentPosition / ((float)Frequency * (float)NumChannels * 2.0f);
}
int cMP3Decoder::getCurrentPosition()
{
return CurrentPosition;
}
int cMP3Decoder::getCurrentCompressedPosition()
{
return Stream->getCurrentPos();
}

View File

@ -52,6 +52,14 @@ class cMP3Decoder : public IAudioDecoder
//!If seeking is supported, will seek the stream to seconds
virtual bool seek(float seconds, bool relative);
virtual float getTotalTime();
virtual int getTotalSize();
virtual int getCompressedSize();
virtual float getCurrentTime();
virtual int getCurrentPosition();
virtual int getCurrentCompressedPosition();
protected:
MPAuDecContext* Context;
bool Valid;
@ -59,6 +67,9 @@ class cMP3Decoder : public IAudioDecoder
int NumChannels;
int Frequency;
int TotalSize;
int CurrentPosition;
cMP3Packet CurrentPacket;
};