arduino-audio-tools
Loading...
Searching...
No Matches
VorbisDecoder.h
1#pragma once
2
3
4#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
5#include "AudioTools/CoreAudio/Buffers.h"
6
7#include <vorbis.h>
8
9namespace audio_tools {
10
30class VorbisDecoder : public AudioDecoder {
31 public:
39 VorbisDecoder(size_t buffer_size = 256, int header_packets = 3)
40 : pcm_buffer_size(buffer_size), num_header_packets(header_packets) {}
41
48
56 bool begin() override {
57 end();
59 vorbis_info_init(&vi);
60 vorbis_comment_init(&vc);
61 active = true;
62 return true;
63 }
64
68 void end() override {
69 vorbis_block_clear(&vb);
70 vorbis_dsp_clear(&vd);
71 vorbis_comment_clear(&vc);
72 vorbis_info_clear(&vi);
73 header_packets = 0;
74 decoder_initialized = false;
75 active = false;
76 }
77
88 size_t write(const uint8_t *data, size_t len) override {
89 ogg_packet packet;
90 packet.packet = (unsigned char *)data;
91 packet.bytes = len;
92 packet.b_o_s = (header_packets == 0) ? 1 : 0;
93 packet.e_o_s = 0;
94 packet.granulepos = 0;
95 packet.packetno = header_packets;
96
97 if (num_header_packets == 0 && !decoder_initialized) {
98 if (!initDecoder()) return 0;
99 decoder_initialized = true;
100 }
101 if (header_packets < num_header_packets) {
102 if (!parseHeaderPacket(packet, header_packets)) return 0;
103 header_packets++;
104 if (header_packets == num_header_packets) {
105 if (!initDecoder()) return 0;
106 decoder_initialized = true;
107 }
108 return 0;
109 }
110 if (header_packets == num_header_packets) {
111 notifyAudioChange(audioInfo());
112 }
113 if (!decoder_initialized) return 0;
114 return decodeAudioPacket(packet);
115 }
116
121 AudioInfo audioInfo() override {
122 AudioInfo info;
123 if (vi.channels > 0 && vi.rate > 0) {
124 info.sample_rate = vi.rate;
125 info.channels = vi.channels;
126 info.bits_per_sample = 16;
127 }
128 return info;
129 }
130
134 operator bool() override { return active; }
135
136 protected:
138 vorbis_info vi{};
140 vorbis_comment vc{};
142 vorbis_dsp_state vd{};
144 vorbis_block vb{};
146 Print *p_print = nullptr;
148 bool active = false;
150 size_t pcm_buffer_size = 256;
155 int header_packets = 0;
156 bool decoder_initialized = false;
163 bool parseHeaderPacket(ogg_packet &packet, int header_packets) {
164 if (vorbis_synthesis_headerin(&vi, &vc, &packet) != 0) {
165 LOGE("Header packet %d invalid", header_packets);
166 return false;
167 }
168 return true;
169 }
170
175 bool initDecoder() {
176 if (vorbis_synthesis_init(&vd, &vi) != 0) {
177 LOGE("vorbis_synthesis_init failed");
178 return false;
179 }
180 vorbis_block_init(&vd, &vb);
181 return true;
182 }
183
189 size_t decodeAudioPacket(ogg_packet &packet) {
190 size_t total_written = 0;
191 if (vorbis_synthesis(&vb, &packet) == 0) {
192 vorbis_synthesis_blockin(&vd, &vb);
193 float **pcm = nullptr;
194 int samples = vorbis_synthesis_pcmout(&vd, &pcm);
195 while (samples > 0 && pcm) {
196 int chunk = (samples > pcm_buffer_size) ? pcm_buffer_size : samples;
197 convertFloatToInt16PCM(pcm, chunk, vi.channels);
198 if (!pcmout_buffer.empty() && p_print) {
199 p_print->write((uint8_t *)pcmout_buffer.data(),
200 pcmout_buffer.size() * sizeof(int16_t));
201 total_written += pcmout_buffer.size() * sizeof(int16_t);
202 pcmout_buffer.clear();
203 }
204 vorbis_synthesis_read(&vd, chunk);
205 samples = vorbis_synthesis_pcmout(&vd, &pcm);
206 }
207 }
208 return total_written;
209 }
210
218 void convertFloatToInt16PCM(float **pcm, int samples, int channels) {
219 for (int i = 0; i < samples; ++i) {
220 for (int ch = 0; ch < channels; ++ch) {
221 float val = pcm[ch][i];
222 int16_t sample = (int16_t)(val * 32767.0f);
223 if (sample > 32767) sample = 32767;
224 if (sample < -32768) sample = -32768;
225 pcmout_buffer.push_back(sample);
226 }
227 }
228 }
229};
230
231} // namespace audio_tools
Definition NoArduino.h:62
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
~VorbisDecoder()
Destructor for VorbisDecoder.
Definition VorbisDecoder.h:47
int num_header_packets
Number of Vorbis header packets.
Definition VorbisDecoder.h:152
bool active
Decoder active state.
Definition CodecVorbis.h:175
bool parseHeaderPacket(ogg_packet &packet, int header_packets)
Parses a Vorbis header packet.
Definition VorbisDecoder.h:163
void convertFloatToInt16PCM(float **pcm, int samples, int channels)
Converts float PCM to interleaved int16 PCM and stores in pcmout_buffer.
Definition VorbisDecoder.h:218
vorbis_comment vc
Vorbis comment metadata.
Definition VorbisDecoder.h:140
size_t decodeAudioPacket(ogg_packet &packet)
Decodes an audio packet and writes PCM to output.
Definition VorbisDecoder.h:189
bool initDecoder()
Initializes the Vorbis decoder after header parsing.
Definition VorbisDecoder.h:175
size_t pcm_buffer_size
PCM output buffer size.
Definition VorbisDecoder.h:150
vorbis_block vb
Block structure for synthesis.
Definition VorbisDecoder.h:144
void end() override
Releases the reserved memory.
Definition CodecVorbis.h:66
size_t write(const uint8_t *data, size_t len) override
Feeds a Vorbis packet (header or audio) to the decoder.
Definition VorbisDecoder.h:88
Vector< int16_t > pcmout_buffer
Buffer for interleaved PCM output.
Definition VorbisDecoder.h:154
vorbis_info vi
Vorbis stream info (channels, sample rate, etc.)
Definition VorbisDecoder.h:138
VorbisDecoder(size_t buffer_size=256, int header_packets=3)
Constructor for VorbisDecoder.
Definition VorbisDecoder.h:39
bool begin() override
Resets decoder state and prepares for new Vorbis stream.
Definition VorbisDecoder.h:56
Print * p_print
Output stream for PCM audio.
Definition VorbisDecoder.h:146
vorbis_dsp_state vd
Decoder state for synthesis.
Definition VorbisDecoder.h:142
AudioInfo audioInfo() override
Provides the last available MP3FrameInfo.
Definition CodecVorbis.h:79
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59