arduino-audio-tools
Loading...
Searching...
No Matches
CodecMP3Shine.h
Go to the documentation of this file.
1
2#pragma once
3
4#include <stdint.h>
5#include <string.h>
6
8#include "codec-shine.h" // https://github.com/pschatzmann/codec-shine
9
10namespace audio_tools {
11
23 public:
24 MP3EncoderShine() = default;
25
26 ~MP3EncoderShine() override { end(); }
27
28 // -------------------------
29 // AudioInfoSupport
30 // -------------------------
31 void setAudioInfo(AudioInfo from) override {
33
34 if (_shine != nullptr) {
35 // we need to restart the encoder
36 end();
37 begin();
38 }
39 }
40
41 AudioInfo audioInfo() override { return info; }
42
44 return info; // MP3 does not change SR in Shine
45 }
46
47 // -------------------------
48 // AudioWriter
49 // -------------------------
50 void setOutput(Print& out_stream) override { _out = &out_stream; }
51
52 operator bool() override { return _shine != nullptr && _out != nullptr; }
53
54 bool begin() override {
55 if (!_out) return false;
56
57 if (info.bits_per_sample != 16) {
58 LOGE("Unsupported bits per sample: %d. Only 16 is supported.",
60 return false;
61 }
62
63 if (info.channels != 1 && info.channels != 2) {
64 LOGE("Unsupported number of channels: %d. Only 1 or 2 are supported.",
66 return false;
67 }
68
70 _config.wave.channels = (channels)info.channels;
71 _config.wave.samplerate = info.sample_rate;
72 _config.mpeg.mode = (info.channels == 1) ? MONO : STEREO;
73 _config.mpeg.bitr = bitrate;
74
75 if (info.channels == 1 && _config.mpeg.mode != MONO) {
76 LOGW(
77 "Input is mono but Shine encoder is configured for stereo. "
78 "Forcing mono mode.");
79 _config.mpeg.mode = MONO;
80 }
81
83 if (!_shine) {
84 LOGE(
85 "Failed to initialize Shine encoder with sample rate %d, channels "
86 "%d, bitrate %d",
87 info.sample_rate, info.channels, bitrate);
88 return false;
89 }
90 LOGI(
91 "Shine encoder initialized with sample rate %d, channels %d, bitrate "
92 "%d",
93 info.sample_rate, info.channels, bitrate);
94
96 int buffer_size_bytes = samples_per_pass * info.channels * sizeof(int16_t);
97 if (!_pcm_buffer.resize(buffer_size_bytes)) {
98 LOGE("Failed to resize PCM buffer to %d bytes", buffer_size_bytes);
99 return false;
100 }
101
102 return true;
103 }
104
105 void end() override {
106 if (_shine) {
107 flush();
108
110 _shine = nullptr;
111 }
112 }
113
114 // -------------------------
115 // Main encode path
116 // -------------------------
117 size_t write(const uint8_t* data, size_t len) override {
118 if (!_shine || !_out) return 0;
119
120 for (int j = 0; j < len; j++) {
121 _pcm_buffer.write(data[j]);
122 if (_pcm_buffer.isFull()) {
123 writeMP3();
125 }
126 }
127 return len;
128 }
129
131 void setBitrate(int br) { _bitrate = br; }
136 void setCopyright(bool copyright) { _config.mpeg.copyright = copyright; }
138 void setOriginal(bool original) { _config.mpeg.original = original; }
141 void setMode(modes mode) { _config.mpeg.mode = mode; }
142
143 const char* mime() override { return "audio/mpeg"; }
144
146 // 1152 samples per frame at sample rate
147 return (1152000000ULL / info.sample_rate);
148 }
149
150 uint16_t samplesPerFrame() override { return 1152; }
151
152 void flush() {
153 if (_shine == nullptr || _out == nullptr) return;
154 // complete buffer with zeros and write the last frame
155 while (!_pcm_buffer.isFull())
156 _pcm_buffer.write(0); // pad with zeros until full
157 writeMP3();
158
159 int written = 0;
160 uint8_t* data = shine_flush(_shine, &written);
161 if (written > 0 && data) {
162 writeBlocking(_out, data, written);
163 }
164 }
165
166 protected:
167 Print* _out = nullptr;
168 shine_t _shine = nullptr;
169 int _bitrate = 128;
172
173 int writeMP3() {
174 int written = 0;
176 _shine, (int16_t*)_pcm_buffer.data(), &written);
177 if (written > 0) {
178 writeBlocking(_out, mp3, written);
179 }
180 return written;
181 }
182
183 // ---------------------------------------------------
184 // Fast bitrate selector (zero allocation version)
185 // ---------------------------------------------------
186 static int selectBitrateFast(int sr, int req) {
187 // minimal safe mapping (embedded-friendly)
188 if (req <= 0) {
189 if (sr <= 12000) return 32;
190 if (sr <= 22050) return 64;
191 if (sr <= 32000) return 128;
192 return 128;
193 }
194
195 if (sr <= 12000 && req > 64) return 64;
196 if (sr <= 22050 && req > 128) return 128;
197 if (sr <= 32000 && req > 256) return 256;
198
199 if (req > 320) return 320;
200
201 // snap to valid MP3 ladder
202 const int table[] = {32, 40, 48, 56, 64, 80, 96,
203 112, 128, 160, 192, 224, 256, 320};
204
205 int best = 128;
206 for (int i = 0; i < 14; i++) {
207 if (req <= table[i]) {
208 best = table[i];
209 break;
210 }
211 }
212
213 return best;
214 }
215};
216
217} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Encoding of PCM data.
Definition AudioCodecsBase.h:97
AudioInfo info
Definition AudioCodecsBase.h:116
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:106
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:223
void clear()
same as reset
Definition Buffers.h:95
Lean MP3 Encoder using the shine library.
Definition CodecMP3Shine.h:22
void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition CodecMP3Shine.h:50
void setCopyright(bool copyright)
Sets the copyright flag for encoding.
Definition CodecMP3Shine.h:136
Print * _out
Definition CodecMP3Shine.h:167
shine_config_t _config
Definition CodecMP3Shine.h:170
void setOriginal(bool original)
Sets the original flag for encoding.
Definition CodecMP3Shine.h:138
shine_t _shine
Definition CodecMP3Shine.h:168
int _bitrate
Definition CodecMP3Shine.h:169
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition CodecMP3Shine.h:31
void setMode(modes mode)
Definition CodecMP3Shine.h:141
int writeMP3()
Definition CodecMP3Shine.h:173
void end() override
Definition CodecMP3Shine.h:105
void setBitrate(int br)
Request the bitrate for encoding (in kbps).
Definition CodecMP3Shine.h:131
uint16_t samplesPerFrame() override
Optional rtsp function: provide samples per the frame.
Definition CodecMP3Shine.h:150
size_t write(const uint8_t *data, size_t len) override
Definition CodecMP3Shine.h:117
const char * mime() override
Provides the mime type of the encoded result.
Definition CodecMP3Shine.h:143
AudioInfo audioInfoOut() override
Definition CodecMP3Shine.h:43
~MP3EncoderShine() override
Definition CodecMP3Shine.h:26
uint32_t frameDurationUs() override
Optional rtsp function: provide the frame duration in microseconds.
Definition CodecMP3Shine.h:145
SingleBuffer< uint8_t > _pcm_buffer
Definition CodecMP3Shine.h:171
bool begin() override
Definition CodecMP3Shine.h:54
void setDeemphasis(emph deemphasis)
Definition CodecMP3Shine.h:134
static int selectBitrateFast(int sr, int req)
Definition CodecMP3Shine.h:186
void flush()
Definition CodecMP3Shine.h:152
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition CodecMP3Shine.h:41
Definition NoArduino.h:62
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:206
bool isFull() override
checks if the buffer is full
Definition Buffers.h:240
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:305
T * data()
Provides address of actual data.
Definition Buffers.h:284
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61