2#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
3#include "AudioToolsConfig.h"
5#include "vorbis-tremor.h"
13#ifndef VARBIS_MAX_READ_SIZE
14#define VARBIS_MAX_READ_SIZE 1024
17#define VORBIS_HEADER_OPEN_LIMIT 1024
44 LOGW(
"Decoder already active, calling end() first");
48 callbacks.read_func = read_func;
49 callbacks.seek_func = seek_func;
50 callbacks.close_func =
nullptr;
51 callbacks.tell_func = tell_func;
54 if (
p_input->available() < VORBIS_HEADER_OPEN_LIMIT) {
55 delay(delay_wait_for_data_ms);
57 LOGI(
"available: %d",
p_input->available());
59 is_ov_open = ovOpen();
60 LOGI(
"ovOpen result: %d", is_ov_open);
69 if (is_ov_open &&
active) {
71 LOGI(
"ov_clear completed");
83 virtual operator bool()
override {
return active; }
85 virtual bool copy()
override {
91 LOGE(
"Failed to open Vorbis stream");
97 if (pcm.data() ==
nullptr) {
98 LOGE(
"PCM buffer is null - memory allocation failed");
102 if (pcm.size() == 0) {
103 LOGE(
"PCM buffer size is 0");
109 LOGE(
"Decoder is not active");
113 LOGD(
"ov_read: buffer size %d", pcm.size());
117 long result = ov_read(&file, (
char *)pcm.data(), pcm.size(), &bitstream);
118 LOGI(
"copy result: %d", (
int)result);
122 if (current != cfg) {
125 notifyAudioChange(cfg);
129 p_print->write(pcm.data(), result);
131 LOGE(
"Output stream is null");
137 if (result == 0 || result == -3) {
139 LOGD(
"copy: %d - %s", (
int)result, readError(result));
141 LOGE(
"copy: %d - %s", (
int)result, readError(result));
143 delay(delay_on_no_data_ms);
149 const char *
mime()
override {
return "audio/vorbis+ogg"; }
159 max_read_size = size;
161 if (max_read_size > 8192) {
162 LOGW(
"Read size %zu is very large, consider smaller buffer",
171 ov_callbacks callbacks;
173 size_t delay_on_no_data_ms = 100;
174 size_t delay_wait_for_data_ms = 500;
175 size_t max_read_size = VARBIS_MAX_READ_SIZE;
177 bool is_first =
true;
178 bool is_ov_open =
false;
181 pcm.resize(max_read_size);
183 int rc = ov_open_callbacks(
this, &file,
nullptr, 0, callbacks);
185 LOGE(
"ov_open_callbacks failed with error %d: %s", rc, getOpenError(rc));
187 LOGI(
"ov_open_callbacks succeeded");
197 LOGE(
"Cannot get audio info - stream not open");
201 vorbis_info *info = ov_info(&file, -1);
202 if (info ==
nullptr) {
203 LOGE(
"ov_info returned null pointer");
211 LOGD(
"Audio info - rate: %d, channels: %d", info->rate, info->channels);
215 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
216 size_t read_size = min(len, (
size_t)max_read_size);
217 size_t result =
p_input->readBytes((uint8_t *)data, read_size);
218 LOGD(
"readBytes: %zu", result);
222 static size_t read_func(
void *ptr,
size_t size,
size_t nmemb,
225 assert(datasource !=
nullptr);
226 size_t result = self->
readBytes((uint8_t *)ptr, size * nmemb);
227 LOGD(
"read_func: %d -> %d", size * nmemb, (
int)result);
231 static int seek_func(
void *datasource, ogg_int64_t offset,
int whence) {
232 VorbisDecoder *self = (VorbisDecoder *)datasource;
236 static long tell_func(
void *datasource) {
237 VorbisDecoder *self = (VorbisDecoder *)datasource;
247 const char *readError(
long error) {
253 return "Interruption in the data";
255 return "Invalid stream section";
259 return "Internal fault";
261 return "Unimplemented feature";
263 return "Invalid argument";
265 return "Not a Vorbis file";
267 return "Invalid Vorbis header";
269 return "Vorbis version mismatch";
271 return "Stream not seekable";
273 return "Unknown error";
277 const char *getOpenError(
int error) {
282 return "Read from media error";
284 return "Not Vorbis data";
286 return "Vorbis version mismatch";
288 return "Invalid Vorbis bitstream header";
290 return "Internal logic fault";
292 return "Unknown open error";
static void checkMemory(bool printMemory=false)
Executes heap_caps_check_integrity_all()
Definition AudioRuntime.h:23