Leviathan  0.8.0.0
Leviathan game engine
Leviathan::VorbisCodec Class Reference

Vorbis audio codec. More...

#include <Codec.h>

+ Inheritance diagram for Leviathan::VorbisCodec:

Classes

struct  Implementation
 

Public Member Functions

DLLEXPORT VorbisCodec (const uint8_t *codecprivatedata, size_t datalength)
 
DLLEXPORT ~VorbisCodec ()
 
DLLEXPORT bool FeedRawFrame (const uint8_t *data, size_t length) override
 Sends the raw data frame to the codec. More...
 
DLLEXPORT void ReceiveDecodedFrames (FrameCallback callback) override
 Returns decoded frames one by one after they are ready. More...
 
- Public Member Functions inherited from Leviathan::Codec
 Codec ()=default
 
 Codec (const Codec &other)=delete
 
Codecoperator= (const Codec &other)=delete
 

Additional Inherited Members

- Public Types inherited from Leviathan::Codec
using FrameCallback = std::function< bool(const DecodedFrame &frame)>
 

Detailed Description

Vorbis audio codec.

Definition at line 98 of file Codec.h.

Constructor & Destructor Documentation

◆ VorbisCodec()

DLLEXPORT VorbisCodec::VorbisCodec ( const uint8_t *  codecprivatedata,
size_t  datalength 
)

Definition at line 246 of file Codec.cpp.

246  :
247  Pimpl(std::make_unique<Implementation>())
248 {
249  // First split the private data into the separate packets that are needed
250  const auto packets =
251  MatroskaParser::SplitVorbisPrivateSetupData(codecprivatedata, datalength);
252 
253  if(packets.empty())
254  throw InvalidArgument("Failed to split the vorbis codec private data to the distinct "
255  "initialization packets");
256 
257  bool first = true;
258 
259  // Then decode the private data
260  for(const auto [ptr, size] : packets) {
261  ogg_packet op;
262  std::memset(&op, 0, sizeof(op));
263 
264  op.packet = reinterpret_cast<unsigned char*>(const_cast<uint8_t*>(ptr));
265  op.bytes = size;
266 
267  // Needs to mark the first packet otherwise vorbis decoding just gives up
268  if(first)
269  op.b_o_s = 1;
270 
271  first = false;
272 
273  if(int error =
274  vorbis_synthesis_headerin(&Pimpl->VorbisInfo, &Pimpl->VorbisComment, &op);
275  error < 0) {
276  throw InvalidArgument(
277  "vorbis initialization packet processing failed, error code: " +
278  std::to_string(error));
279  }
280  }
281 
282  Pimpl->Channels = Pimpl->VorbisInfo.channels;
283  Pimpl->Frequency = Pimpl->VorbisInfo.rate;
284 
285  // Could store some of this info
286  // char** ptr = Pimpl->VorbisComment.user_comments;
287  // Pimpl->VorbisComment.vendor;
288 
289  if(vorbis_synthesis_init(&Pimpl->vd, &Pimpl->VorbisInfo) != 0)
290  throw InvalidState("vorbis synthesis init failed");
291 
292  vorbis_block_init(&Pimpl->vd, &Pimpl->vb);
293  Pimpl->Initialized = true;
294 }
static DLLEXPORT std::vector< std::tuple< const uint8_t *, size_t > > SplitVorbisPrivateSetupData(const uint8_t *codecprivatedata, size_t datalength)
Splits Vorbis private data into the 3 setup packets.

◆ ~VorbisCodec()

DLLEXPORT VorbisCodec::~VorbisCodec ( )

Definition at line 296 of file Codec.cpp.

296 {}

Member Function Documentation

◆ FeedRawFrame()

DLLEXPORT bool VorbisCodec::FeedRawFrame ( const uint8_t *  data,
size_t  length 
)
overridevirtual

Sends the raw data frame to the codec.

Returns
True on success. False if the codec couldn't handle the frame and is now possibly in broken state

Implements Leviathan::Codec.

Definition at line 298 of file Codec.cpp.

299 {
300  ogg_packet op;
301  std::memset(&op, 0, sizeof(op));
302 
303  op.packet = reinterpret_cast<unsigned char*>(const_cast<uint8_t*>(data));
304  op.bytes = length;
305 
306  // if(!data || length == 0) {
307  // op.e_o_s = 1;
308  // }
309 
310  if(vorbis_synthesis(&Pimpl->vb, &op) != 0) {
311  LOG_ERROR("VorbisCodec: vorbis synthesis failed");
312  return false;
313  }
314 
315  if(vorbis_synthesis_blockin(&Pimpl->vd, &Pimpl->vb) != 0) {
316  LOG_ERROR("VorbisCodec: vorbis_synthesis_blockin failed");
317  return false;
318  }
319 
320  return true;
321 }
#define LOG_ERROR(x)
Definition: Define.h:92

◆ ReceiveDecodedFrames()

DLLEXPORT void VorbisCodec::ReceiveDecodedFrames ( FrameCallback  callback)
overridevirtual

Returns decoded frames one by one after they are ready.

Call FeedRawFrame and then call this afterwards, there may be more than 1 or no decoded frames for each raw frame. If the callback returns false the loop for iterating the finished frames stops before all frames are passed to the callback

Implements Leviathan::Codec.

Definition at line 323 of file Codec.cpp.

324 {
325  float** pcm;
326  int samples;
327 
328  while((samples = vorbis_synthesis_pcmout(&Pimpl->vd, &pcm)) > 0) {
329 
330  bool continueLoop = callback(DecodedFrame(pcm, samples, Pimpl->Channels));
331 
332  // Mark all samples as read
333  vorbis_synthesis_read(&Pimpl->vd, samples);
334 
335  if(!continueLoop)
336  break;
337  }
338 }
Holds decoded data. This is only valid until the frame receive callback ends.
Definition: Codec.h:16

The documentation for this class was generated from the following files: