arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
CodecMP3Mini.h
1#pragma once
2
3#define MINIMP3_NO_STDIO
4//#define MINIMP3_NO_SIMD
5//#define MINIMP3_IMPLEMENTATION
6//#define MINIMP3_ONLY_MP3
7//#define MINIMP3_FLOAT_OUTPUT
8
9#ifndef MINIMP3_MAX_SAMPLE_RATE
10#define MINIMP3_MAX_SAMPLE_RATE 44100
11#endif
12
13#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
14#include "minimp3.h"
15
16
17namespace audio_tools {
18
29 public:
30 MP3DecoderMini() = default;
31
34 if (active) {
35 end();
36 }
37 }
38
39 void setBufferLength(int len) { buffer_size = len; }
40
42 bool begin() {
43 TRACED();
44 //esp_task_wdt_delete(nullptr);
45 ::mp3dec_init(&mp3d);
46 buffer.resize(buffer_size);
47 pcm.resize(MINIMP3_MAX_SAMPLES_PER_FRAME);
48 buffer_pos = 0;
49 active = true;
50 return true;
51 }
52
54 void end() {
55 TRACED();
56 flush();
57 active = false;
58 }
59
61 void setOutput(Print &outStream) { this->out = &outStream; }
62
64 size_t write(const uint8_t *data, size_t len) {
65 LOGD("write: %zu", len);
66 if (active) {
67 if (buffer_pos+len>=buffer.size()){
68 decode(len);
69 }
70 assert(buffer_pos+len<buffer.size());
71 memcpy(buffer.data()+buffer_pos, data, len);
72 buffer_pos += len;
73 }
74 return len;
75 }
76
78 void flush() {
79 // decode the full buffer
80 decode(0);
81 buffer_pos = 0;
82 }
83
85 virtual operator bool() { return active; }
86
87 void setSampleRateLimit(int limit){
88 sample_rate_limit = limit;
89 }
90
91 protected:
92 Print *out = nullptr;
93 mp3dec_t mp3d;
94 mp3dec_frame_info_t mp3dec_info;
95 size_t buffer_size = 5 * 1024;
96 size_t buffer_pos = 0;
97 Vector<uint8_t> buffer;
98 Vector<mp3d_sample_t> pcm;
99 #ifdef MINIMP3_FLOAT_OUTPUT
100 Vector<int16_t> pcm16;
101 #endif
102 bool active;
103 int sample_rate_limit = MINIMP3_MAX_SAMPLE_RATE; //32000;
104
106 void decode(int write_len) {
107 LOGD("decode: %zd ", buffer_pos);
108 int open = buffer_pos;
109 int processed = 0;
110 int samples;
111 do {
112 // decode data
113 samples = ::mp3dec_decode_frame(&mp3d, buffer.data()+processed, open,
114 pcm.data(), &mp3dec_info);
115 LOGD("frame_offset: %d - frame_bytes: %d -> samples %d", mp3dec_info.frame_offset, mp3dec_info.frame_bytes, samples);
116 open -= mp3dec_info.frame_bytes;
117 processed += mp3dec_info.frame_bytes;
118 // output decoding result
119 if (samples > 0) {
120 provideResult(samples);
121 }
122 // process until we have space for the next write
123 } while(processed < write_len);
124
125 // save unprocessed data
126 buffer_pos = open;
127 memmove(buffer.data(),buffer.data()+processed, open);
128 }
129
131 void provideResult(int samples) {
132 LOGD("provideResult: %d samples", samples);
133 AudioInfo tmp;
134 tmp.sample_rate = mp3dec_info.hz>sample_rate_limit ? sample_rate_limit : mp3dec_info.hz;
135 tmp.channels = mp3dec_info.channels;
136 tmp.bits_per_sample = 16;
137
138 // notify about audio changes
139 if (tmp != info) {
140 tmp.logInfo();
141 notifyAudioChange(tmp);
142 }
143 // store last info so that we can detect any changes
144 info = info;
145
146 // provide result pwm data
147 if (out != nullptr) {
148 #ifdef MINIMP3_FLOAT_OUTPUT
149 pcm16.resize(samples);
150 f32_to_s16(pcm.data(), pcm16.data(), samples);
151 out->write((uint8_t *)pcm16.data(), samples * sizeof(int16_t));
152 #else
153 out->write((uint8_t *)pcm.data(), samples * sizeof(mp3d_sample_t));
154 #endif
155 }
156 }
157
158 void f32_to_s16(float *in, int16_t *out, int num_samples) {
159 int i = 0;
160 for(; i < num_samples; i++){
161 float sample = in[i] * 32768.0f;
162 if (sample >= 32766.5f)
163 out[i] = (int16_t) 32767;
164 else if (sample <= -32767.5f)
165 out[i] = (int16_t)-32768;
166 else {
167 int16_t s = (int16_t)(sample + .5f);
168 s -= (s < 0); /* away from zero, to be compliant */
169 out[i] = s;
170 }
171 }
172 }
173
174
175};
176
177} // namespace audio_tools
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
MP3 Decoder using https://github.com/pschatzmann/minimp3. This decoder does not provide any good resu...
Definition CodecMP3Mini.h:28
void setOutput(Print &outStream)
Defines the output Stream.
Definition CodecMP3Mini.h:61
bool begin()
Starts the processing.
Definition CodecMP3Mini.h:42
~MP3DecoderMini()
Destroy the MP3DecoderMini object.
Definition CodecMP3Mini.h:33
void provideResult(int samples)
Provides Metadata and PCM data.
Definition CodecMP3Mini.h:131
void end()
Releases the reserved memory.
Definition CodecMP3Mini.h:54
void flush()
Decodes the last outstanding data.
Definition CodecMP3Mini.h:78
void decode(int write_len)
Process single bytes so that we can decode a full frame when it is available.
Definition CodecMP3Mini.h:106
size_t write(const uint8_t *data, size_t len)
Write mp3 data to decoder.
Definition CodecMP3Mini.h:64
Definition NoArduino.h:62
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