commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
190
include/modules/audio_stream_ogg/audio_stream_ogg.cpp
Normal file
190
include/modules/audio_stream_ogg/audio_stream_ogg.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "audio_stream_ogg/audio_stream_ogg.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "platform.h"
|
||||
#include "log/log.h"
|
||||
#include "stb_vorbis.c"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::IO;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool AudioStreamOGG::Seek(int t_ms)
|
||||
{
|
||||
/// Rewind the stream and seek to the correct frame.
|
||||
int target = (vf->sample_rate * t_ms) / 1000;
|
||||
|
||||
// Logic is broken when seeking below the first packet.
|
||||
if (target < 1024)
|
||||
{
|
||||
h->Rewind();
|
||||
byte_left = 0;
|
||||
|
||||
stb_vorbis_flush_pushdata(vf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO compute seek point and sample to skip.
|
||||
int lo = 0, hi = h->GetSize();
|
||||
|
||||
forever
|
||||
{
|
||||
// Determine seek point.
|
||||
int mid = (lo + hi) / 2;
|
||||
|
||||
// Seek and reload push buffer.
|
||||
h->Seek(mid, Base::SeekStart);
|
||||
RefillBuffer();
|
||||
|
||||
stb_vorbis_flush_pushdata(vf);
|
||||
|
||||
int ns = 0, ch = 0, cs = 0;
|
||||
float **fo = NULL;
|
||||
|
||||
forever
|
||||
{
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
if (ns) // Samples are coming in.
|
||||
{
|
||||
cs = stb_vorbis_get_sample_offset(vf);
|
||||
if (cs != -1) // Sample located.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if target sample is within reach.
|
||||
if ((cs > (target - 24000)) && (cs <= target))
|
||||
forever
|
||||
{
|
||||
RefillBuffer();
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
int skip = target - cs;
|
||||
if ((cs != -1) && (skip < ns))
|
||||
{
|
||||
seek_correction = skip;
|
||||
return true;
|
||||
}
|
||||
cs = stb_vorbis_get_sample_offset(vf);
|
||||
}
|
||||
|
||||
// Refine approximation.
|
||||
if (cs > target)
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t AudioStreamOGG::GetPCMBufferSize() const
|
||||
{ return vorbis_info.max_frame_size * format.channels * 2 * 2; }
|
||||
size_t AudioStreamOGG::GetPCM(void *pcm)
|
||||
{
|
||||
int ns, ch;
|
||||
float **fo = NULL;
|
||||
|
||||
RefillBuffer();
|
||||
ConsumeBuffer(stb_vorbis_decode_frame_pushdata(vf, (uchar *)buffer.c_ptr(), byte_left, &ch, &fo, &ns));
|
||||
|
||||
if (vf->error != VORBIS__no_error)
|
||||
return 0;
|
||||
|
||||
if (seek_correction)
|
||||
{
|
||||
for (int n = 0; n < ch; ++n)
|
||||
fo[n] += seek_correction;
|
||||
ns -= seek_correction;
|
||||
seek_correction = 0;
|
||||
}
|
||||
if (ns < 0)
|
||||
ns = 0;
|
||||
|
||||
convert_channels_short_interleaved(ch, (short *)pcm, ch, fo, 0, ns); // size = ns * 2 * format.channels
|
||||
return ns * 2 * format.channels;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
size_t AudioStreamOGG::RefillBuffer()
|
||||
{
|
||||
size_t request_size = buffer.GetSize() - byte_left;
|
||||
size_t read = h->Read(&buffer[(int)byte_left], request_size);
|
||||
byte_left += read;
|
||||
return read;
|
||||
}
|
||||
void AudioStreamOGG::ConsumeBuffer(size_t size)
|
||||
{
|
||||
memmove(buffer, &buffer[(int)size], byte_left - size);
|
||||
byte_left -= size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool AudioStreamOGG::IsEOF() const
|
||||
{
|
||||
if (byte_left > 0)
|
||||
return false;
|
||||
if (h->IsEOF())
|
||||
return true;
|
||||
return vf ? asbool(vf->eof) : false;
|
||||
}
|
||||
bool AudioStreamOGG::Open(const char *uri)
|
||||
{
|
||||
h = Platform::Get().io->Open(uri);
|
||||
if (!h)
|
||||
return false;
|
||||
|
||||
if (!buffer.Allocate(16384))
|
||||
return false;
|
||||
|
||||
RefillBuffer();
|
||||
vf = stb_vorbis_open_pushdata((uchar *)buffer.c_ptr(), byte_left, &consumed, &err, NULL);
|
||||
if (!vf)
|
||||
{
|
||||
h = NULL;
|
||||
return false;
|
||||
}
|
||||
ConsumeBuffer(consumed);
|
||||
|
||||
vorbis_info = stb_vorbis_get_info(vf);
|
||||
seek_correction = 0;
|
||||
|
||||
format.channels = vorbis_info.channels;
|
||||
format.resolution = 16;
|
||||
format.frequency = vorbis_info.sample_rate;
|
||||
|
||||
__LOG_H__ << "Vorbis stream '" << uri << "' - " << vorbis_info.sample_rate << "hz 16bit " << vorbis_info.channels << " channel(s).\n";
|
||||
__LOG__ << " Max frame size = " << vorbis_info.max_frame_size << "\n";
|
||||
return true;
|
||||
}
|
||||
void AudioStreamOGG::Close()
|
||||
{
|
||||
if (vf)
|
||||
stb_vorbis_close(vf);
|
||||
vf = NULL;
|
||||
|
||||
__LOG_H__ << "Vorbis stream closed.\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
AudioStreamOGG::AudioStreamOGG()
|
||||
{
|
||||
vf = NULL;
|
||||
seek_correction = 0;
|
||||
byte_left = 0;
|
||||
}
|
||||
AudioStreamOGG::~AudioStreamOGG()
|
||||
{ Close(); }
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user