54 #include <vorbis/vorbisfile.h> 71 static size_t read_stream_wrap(
void *ptr,
size_t size,
size_t nmemb,
void *dataSource) {
74 size_t result = stream->
read(ptr, size * nmemb);
97 stream->
seek((ptrdiff_t)offset, seekOrigin);
108 return stream->
pos();
149 _inStream(inStream, dispose),
150 _bufferEnd(_buffer +
ARRAYSIZE(_buffer)),
151 _length(kInvalidLength) {
155 warning(
"Could not create Vorbis stream (%d)", res);
160 ogg_int64_t total = ov_pcm_total(&
_ovFile, -1);
180 const size_t len = MIN<size_t>(numSamples - samples,
_bufferEnd -
_pos);
181 std::memcpy(buffer,
_pos, len * 2);
196 if (ov_pcm_seek(&
_ovFile, 0) != 0)
204 size_t len_left =
sizeof(
_buffer);
205 char *read_pos =
reinterpret_cast<char *
>(
_buffer);
207 while (len_left > 0) {
214 result = ov_read(&
_ovFile, read_pos, len_left,
217 #ifdef XOREOS_BIG_ENDIAN 218 result = ov_read(&
_ovFile, read_pos, len_left,
224 result = ov_read(&
_ovFile, read_pos, len_left,
231 if (result == OV_HOLE) {
233 warning(
"Corrupted data in Vorbis file");
234 }
else if (result == 0) {
239 }
else if (result < 0) {
240 warning(
"Error reading from Vorbis stream (%d)",
int(result));
287 std::queue<Common::SeekableReadStream *>
_queue;
303 vorbis_block_clear(&
_block);
318 if (stream.
size() < 3)
321 byte initialBytes[3];
322 stream.
read(initialBytes,
sizeof(initialBytes));
324 size_t headerSizes[3];
327 if (stream.
size() >= 6 && READ_BE_UINT16(initialBytes) == 30) {
330 for (
int i = 0; i < 3; i++) {
333 if (headerSizes[i] + stream.
pos() > stream.
size()) {
334 warning(
"Vorbis header size invalid");
338 headers[i].
reset(
new byte[headerSizes[i]]);
339 stream.
read(headers[i].
get(), headerSizes[i]);
341 }
else if (initialBytes[0] == 2 && stream.
size() < 0x7FFFFE00) {
345 for (
int i = 0; i < 2; i++) {
348 while (stream.
pos() < stream.
size()) {
350 headerSizes[i] += length;
358 warning(
"Vorbis header sizes damaged");
363 headerSizes[2] = stream.
size() - (headerSizes[0] + headerSizes[1] + offset);
366 for (
int i = 0; i < 3; i++) {
367 headers[i].
reset(
new byte[headerSizes[i]]);
368 stream.
read(headers[i].
get(), headerSizes[i]);
371 warning(
"Invalid vorbis initial header length: %d", initialBytes[0]);
375 for (
int i = 0; i < 3; i++) {
377 _packet.bytes = headerSizes[i];
381 warning(
"Vorbis header %d is damaged", i);
398 #define READ_WHOLE_STREAM(x) \ 400 Common::SeekableReadStream &packet = packet##x; \ 401 headerSizes[x - 1] = packet.size(); \ 402 headers[x - 1].reset(new byte[headerSizes[x - 1]]); \ 403 packet.read(headers[x - 1].get(), headerSizes[x - 1]); \ 410 #undef READ_WHOLE_STREAM 412 for (
int i = 0; i < 3; i++) {
414 _packet.bytes = headerSizes[i];
418 warning(
"Vorbis header %d is damaged", i);
435 while (samples < numSamples) {
441 int decSamples = vorbis_synthesis_pcmout(&
_dspState, &pcm);
442 if (decSamples <= 0) {
455 stream->read(data.get(), stream->size());
459 _packet.bytes = stream->size();
464 warning(
"Failed to synthesize from vorbis packet");
472 decSamples = MIN<int>((numSamples - samples) /
getChannels(), decSamples);
475 for (
int i = 0; i < decSamples; i++)
477 buffer[samples++] = (
int16)(pcm[j][i] / 32768);
479 for (
int i = 0; i < decSamples; i++)
481 buffer[samples++] = CLIP<int>(floor(pcm[j][i] * 32767.0f + 0.5), -32768, 32767);
484 vorbis_synthesis_read(&
_dspState, decSamples);
518 if (s && s->endOfData())
526 if (!stream->parseExtraData(extraData))
534 if (!stream->parseExtraData(packet1, packet2, packet3))
static ov_callbacks g_stream_wrap
static long tell_stream_wrap(void *dataSource)
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
void reset(PointerType o=0)
Resets the pointer with the new value.
static size_t read_stream_wrap(void *ptr, size_t size, size_t nmemb, void *dataSource)
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
uint64 getLength() const
Estimate the total number of samples per channel in this stream.
#define READ_WHOLE_STREAM(x)
vorbis_dsp_state _dspState
static int close_stream_wrap(void *dataSource)
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
PacketizedAudioStream * makePacketizedVorbisStream(Common::SeekableReadStream &extraData)
Create a new PacketizedAudioStream capable of decoding vorbis audio data.
bool isFinished() const
Is the stream marked as finished?
Seek from the end of the stream.
A simple scoped smart pointer template.
Origin
The position a seeking offset takes as a base.
int getRate() const
Sample rate of the stream.
int getChannels() const
Return the number channels in this stream.
A rewindable audio stream.
static int seek_stream_wrap(void *dataSource, ogg_int64_t offset, int whence)
Utility templates and functions.
std::queue< Common::SeekableReadStream * > _queue
uint16 readUint16BE()
Read an unsigned 16-bit word stored in big endian (MSB first) order from the stream and return it...
int getRate() const
Sample rate of the stream.
An AudioStream designed to work in terms of packets.
bool rewind()
Rewinds the stream to its start.
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
RewindableAudioStream * makeVorbisStream(Common::SeekableReadStream *stream, bool disposeAfterUse)
Create a new RewindableAudioStream from the Ogg Vorbis data in the given stream.
void queuePacket(Common::SeekableReadStream *packet)
Queue the next packet to be decoded.
void warning(const char *s,...)
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
Basic reading stream interfaces.
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
VorbisStream(Common::SeekableReadStream *inStream, bool dispose)
Convenience class that locks a mutex on creation and unlocks it on destruction.
Seek from the current position of the stream.
~PacketizedVorbisStream()
Common::DisposablePtr< Common::SeekableReadStream > _inStream
PointerType get() const
Returns the plain pointer value.
A smart pointer with a deletion flag.
bool parseExtraData(Common::SeekableReadStream &stream)
bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
size_t readBuffer(int16 *buffer, const size_t numSamples)
Fill the given buffer with up to numSamples samples.
void finish()
Mark this stream as finished.
int getChannels() const
Return the number channels in this stream.
bool endOfStream() const
End of stream reached? If this returns true, it means that all data in this stream is used up and no ...
bool endOfData() const
End of data reached? If this returns true, it means that at this time there is no data available in t...
Seek from the begin of the stream.
Interface for a seekable & readable data stream.
byte readByte()
Read an unsigned byte from the stream and return it.