2#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
3#include "AudioToolsConfig.h"
4#include "vorbis-tremor.h"
12#ifndef VARBIS_MAX_READ_SIZE
13#define VARBIS_MAX_READ_SIZE 1024
16#define VORBIS_HEADER_OPEN_LIMIT 1024
43 LOGW(
"Decoder already active, calling end() first");
47 callbacks.read_func = read_func;
48 callbacks.seek_func = seek_func;
49 callbacks.close_func =
nullptr;
50 callbacks.tell_func = tell_func;
53 if (
p_input->available() < VORBIS_HEADER_OPEN_LIMIT) {
54 delay(delay_wait_for_data_ms);
56 LOGI(
"available: %d",
p_input->available());
58 is_ov_open = ovOpen();
59 LOGI(
"ovOpen result: %d", is_ov_open);
68 if (is_ov_open && active) {
70 LOGI(
"ov_clear completed");
82 virtual operator bool()
override {
return active; }
84 virtual bool copy()
override {
90 LOGE(
"Failed to open Vorbis stream");
96 if (pcm.data() ==
nullptr) {
97 LOGE(
"PCM buffer is null - memory allocation failed");
101 if (pcm.size() == 0) {
102 LOGE(
"PCM buffer size is 0");
108 LOGE(
"Decoder is not active");
112 LOGD(
"ov_read: buffer size %d", pcm.size());
116 long result = ov_read(&file, (
char *)pcm.data(), pcm.size(), &bitstream);
117 LOGI(
"copy result: %d", (
int)result);
121 if (current != cfg) {
124 notifyAudioChange(cfg);
128 p_print->write(pcm.data(), result);
130 LOGE(
"Output stream is null");
136 if (result == 0 || result == -3) {
138 LOGD(
"copy: %d - %s", (
int)result, readError(result));
140 LOGE(
"copy: %d - %s", (
int)result, readError(result));
142 delay(delay_on_no_data_ms);
148 const char *
mime()
override {
return "audio/vorbis+ogg"; }
158 max_read_size = size;
160 if (max_read_size > 8192) {
161 LOGW(
"Read size %zu is very large, consider smaller buffer",
170 ov_callbacks callbacks;
172 size_t delay_on_no_data_ms = 100;
173 size_t delay_wait_for_data_ms = 500;
174 size_t max_read_size = VARBIS_MAX_READ_SIZE;
176 bool is_first =
true;
177 bool is_ov_open =
false;
180 pcm.resize(max_read_size);
182 int rc = ov_open_callbacks(
this, &file,
nullptr, 0, callbacks);
184 LOGE(
"ov_open_callbacks failed with error %d: %s", rc, getOpenError(rc));
186 LOGI(
"ov_open_callbacks succeeded");
193 AudioInfo currentInfo() {
196 LOGE(
"Cannot get audio info - stream not open");
200 vorbis_info *info = ov_info(&file, -1);
201 if (info ==
nullptr) {
202 LOGE(
"ov_info returned null pointer");
206 result.sample_rate = info->rate;
207 result.channels = info->channels;
208 result.bits_per_sample = 16;
210 LOGD(
"Audio info - rate: %d, channels: %d", info->rate, info->channels);
214 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
215 size_t read_size = min(len, (
size_t)max_read_size);
216 size_t result =
p_input->readBytes((uint8_t *)data, read_size);
217 LOGD(
"readBytes: %zu", result);
221 static size_t read_func(
void *ptr,
size_t size,
size_t nmemb,
224 assert(datasource !=
nullptr);
225 size_t result = self->
readBytes((uint8_t *)ptr, size * nmemb);
226 LOGD(
"read_func: %d -> %d", size * nmemb, (
int)result);
230 static int seek_func(
void *datasource, ogg_int64_t offset,
int whence) {
231 VorbisDecoder *self = (VorbisDecoder *)datasource;
235 static long tell_func(
void *datasource) {
236 VorbisDecoder *self = (VorbisDecoder *)datasource;
246 const char *readError(
long error) {
252 return "Interruption in the data";
254 return "Invalid stream section";
258 return "Internal fault";
260 return "Unimplemented feature";
262 return "Invalid argument";
264 return "Not a Vorbis file";
266 return "Invalid Vorbis header";
268 return "Vorbis version mismatch";
270 return "Stream not seekable";
272 return "Unknown error";
276 const char *getOpenError(
int error) {
281 return "Read from media error";
283 return "Not Vorbis data";
285 return "Vorbis version mismatch";
287 return "Invalid Vorbis bitstream header";
289 return "Internal logic fault";
291 return "Unknown open error";
static void checkMemory(bool printMemory=false)
Executes heap_caps_check_integrity_all()
Definition AudioRuntime.h:29