1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
#include "AudioReaderOgg.h"
#if defined(WITH_VORBIS)
#if defined(DEATH_TARGET_WINDOWS) && !defined(CMAKE_BUILD) && !defined(WITH_VORBIS_DYNAMIC)
# if defined(_M_X64)
# pragma comment(lib, "../Libs/Windows/x64/libvorbisfile.lib")
# elif defined(_M_IX86)
# pragma comment(lib, "../Libs/Windows/x86/libvorbisfile.lib")
# else
# error Unsupported architecture
# endif
#endif
using namespace Death::IO;
namespace nCine
{
#if defined(WITH_VORBIS_DYNAMIC)
HMODULE AudioReaderOgg::_ovLib = nullptr;
bool AudioReaderOgg::_ovLibInitialized = false;
AudioReaderOgg::ov_clear_t* AudioReaderOgg::_ov_clear = nullptr;
AudioReaderOgg::ov_read_t* AudioReaderOgg::_ov_read = nullptr;
AudioReaderOgg::ov_raw_seek_t* AudioReaderOgg::_ov_raw_seek = nullptr;
AudioReaderOgg::ov_info_t* AudioReaderOgg::_ov_info = nullptr;
AudioReaderOgg::ov_open_callbacks_t* AudioReaderOgg::_ov_open_callbacks = nullptr;
AudioReaderOgg::ov_pcm_total_t* AudioReaderOgg::_ov_pcm_total = nullptr;
AudioReaderOgg::ov_time_total_t* AudioReaderOgg::_ov_time_total = nullptr;
#endif
AudioReaderOgg::AudioReaderOgg(std::unique_ptr<Stream> fileHandle, const OggVorbis_File& oggFile)
: fileHandle_(std::move(fileHandle)), oggFile_(oggFile)
{
DEATH_ASSERT(fileHandle_->IsValid());
}
AudioReaderOgg::~AudioReaderOgg()
{
#if defined(WITH_VORBIS_DYNAMIC)
_ov_clear(&oggFile_);
#else
ov_clear(&oggFile_);
#endif
}
std::int32_t AudioReaderOgg::read(void* buffer, std::int32_t bufferSize) const
{
std::int32_t bitStream = 0;
long bytes = 0;
std::int32_t bufferSeek = 0;
do {
// Read up to a buffer's worth of decoded sound data
// (0: little endian, 2: 16bit, 1: signed)
#if defined(WITH_VORBIS_DYNAMIC)
bytes = _ov_read(&oggFile_, static_cast<char*>(buffer) + bufferSeek, bufferSize - bufferSeek, 0, 2, 1, &bitStream);
#else
bytes = ov_read(&oggFile_, static_cast<char*>(buffer) + bufferSeek, bufferSize - bufferSeek, 0, 2, 1, &bitStream);
#endif
if (bytes < 0) {
#if defined(WITH_VORBIS_DYNAMIC)
_ov_clear(&oggFile_);
#else
ov_clear(&oggFile_);
#endif
LOGE("Error decoding at bitstream {}", bitStream);
}
// Reset the static variable at the end of a decoding process
if (bytes <= 0) {
bitStream = 0;
}
bufferSeek += bytes;
} while (bytes > 0 && bufferSize - bufferSeek > 0);
return bufferSeek;
}
void AudioReaderOgg::rewind() const
{
#if defined(WITH_VORBIS_DYNAMIC)
_ov_raw_seek(&oggFile_, 0);
#else
ov_raw_seek(&oggFile_, 0);
#endif
}
#if defined(WITH_VORBIS_DYNAMIC)
bool AudioReaderOgg::TryLoadLibrary()
{
if (_ovLibInitialized) {
return (_ovLib != nullptr);
}
_ovLibInitialized = true;
#if defined(WITH_OPENMPT)
const wchar_t* LibraryName = L"openmpt-vorbis.dll";
#else
const wchar_t* LibraryName = L"libvorbisfile.dll";
#endif
#if defined(DEATH_TARGET_WINDOWS_RT)
_ovLib = ::LoadPackagedLibrary(LibraryName, NULL);
#else
_ovLib = ::LoadLibrary(LibraryName);
#endif
if (_ovLib == nullptr) {
return false;
}
_ov_clear = (ov_clear_t*)::GetProcAddress(_ovLib, "ov_clear");
_ov_read = (ov_read_t*)::GetProcAddress(_ovLib, "ov_read");
_ov_raw_seek = (ov_raw_seek_t*)::GetProcAddress(_ovLib, "ov_raw_seek");
_ov_info = (ov_info_t*)::GetProcAddress(_ovLib, "ov_info");
_ov_open_callbacks = (ov_open_callbacks_t*)::GetProcAddress(_ovLib, "ov_open_callbacks");
_ov_pcm_total = (ov_pcm_total_t*)::GetProcAddress(_ovLib, "ov_pcm_total");
_ov_time_total = (ov_time_total_t*)::GetProcAddress(_ovLib, "ov_time_total");
if (_ov_clear == nullptr || _ov_read == nullptr || _ov_raw_seek == nullptr || _ov_info == nullptr ||
_ov_open_callbacks == nullptr || _ov_pcm_total == nullptr || _ov_time_total == nullptr) {
::FreeLibrary(_ovLib);
_ovLib = nullptr;
return false;
}
return true;
}
#endif
}
#endif
|