BsOggVorbisDecoder.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsOggVorbisDecoder.h"
  4. #include "FileSystem/BsDataStream.h"
  5. #include <vorbis/codec.h>
  6. namespace bs
  7. {
  8. size_t oggRead(void* ptr, size_t size, size_t nmemb, void* data)
  9. {
  10. OggDecoderData* decoderData = static_cast<OggDecoderData*>(data);
  11. return static_cast<std::size_t>(decoderData->stream->read(ptr, size * nmemb));
  12. }
  13. int oggSeek(void* data, ogg_int64_t offset, int whence)
  14. {
  15. OggDecoderData* decoderData = static_cast<OggDecoderData*>(data);
  16. switch (whence)
  17. {
  18. case SEEK_SET:
  19. offset += decoderData->offset;
  20. break;
  21. case SEEK_CUR:
  22. offset += decoderData->stream->tell();
  23. break;
  24. case SEEK_END:
  25. offset = std::max(0, (INT32)decoderData->stream->size() - 1);
  26. break;
  27. }
  28. decoderData->stream->seek((UINT32)offset);
  29. return (int)(decoderData->stream->tell() - decoderData->offset);
  30. }
  31. long oggTell(void* data)
  32. {
  33. OggDecoderData* decoderData = static_cast<OggDecoderData*>(data);
  34. return (long)(decoderData->stream->tell() - decoderData->offset);
  35. }
  36. static ov_callbacks callbacks = { &oggRead, &oggSeek, nullptr, &oggTell };
  37. OggVorbisDecoder::OggVorbisDecoder()
  38. :mChannelCount(0)
  39. {
  40. mOggVorbisFile.datasource = nullptr;
  41. }
  42. OggVorbisDecoder::~OggVorbisDecoder()
  43. {
  44. if (mOggVorbisFile.datasource != nullptr)
  45. ov_clear(&mOggVorbisFile);
  46. }
  47. bool OggVorbisDecoder::isValid(const SPtr<DataStream>& stream, UINT32 offset)
  48. {
  49. stream->seek(offset);
  50. mDecoderData.stream = stream;
  51. mDecoderData.offset = offset;
  52. OggVorbis_File file;
  53. if (ov_test_callbacks(&mDecoderData, &file, nullptr, 0, callbacks) == 0)
  54. {
  55. ov_clear(&file);
  56. return true;
  57. }
  58. return false;
  59. }
  60. bool OggVorbisDecoder::open(const SPtr<DataStream>& stream, AudioDataInfo& info, UINT32 offset)
  61. {
  62. if (stream == nullptr)
  63. return false;
  64. stream->seek(offset);
  65. mDecoderData.stream = stream;
  66. mDecoderData.offset = offset;
  67. int status = ov_open_callbacks(&mDecoderData, &mOggVorbisFile, nullptr, 0, callbacks);
  68. if (status < 0)
  69. {
  70. LOGERR("Failed to open Ogg Vorbis file.");
  71. return false;
  72. }
  73. vorbis_info* vorbisInfo = ov_info(&mOggVorbisFile, -1);
  74. info.numChannels = vorbisInfo->channels;
  75. info.sampleRate = vorbisInfo->rate;
  76. info.numSamples = (UINT32)(ov_pcm_total(&mOggVorbisFile, -1) * vorbisInfo->channels);
  77. info.bitDepth = 16;
  78. mChannelCount = info.numChannels;
  79. return true;
  80. }
  81. void OggVorbisDecoder::seek(UINT32 offset)
  82. {
  83. ov_pcm_seek(&mOggVorbisFile, offset / mChannelCount);
  84. }
  85. UINT32 OggVorbisDecoder::read(UINT8* samples, UINT32 numSamples)
  86. {
  87. UINT32 numReadSamples = 0;
  88. while (numReadSamples < numSamples)
  89. {
  90. INT32 bytesToRead = (INT32)(numSamples - numReadSamples) * sizeof(INT16);
  91. UINT32 bytesRead = ov_read(&mOggVorbisFile, (char*)samples, bytesToRead, 0, 2, 1, nullptr);
  92. if (bytesRead > 0)
  93. {
  94. UINT32 samplesRead = bytesRead / sizeof(INT16);
  95. numReadSamples += samplesRead;
  96. samples += samplesRead * sizeof(INT16);
  97. }
  98. else
  99. break;
  100. }
  101. return numReadSamples;
  102. }
  103. }