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:
parent
869057b230
commit
ffb0a8bdf9
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue