arduino-audio-tools
Loading...
Searching...
No Matches
CodecOpusMultiStream.h
Go to the documentation of this file.
1#pragma once
2
4#include "Print.h"
5#include "opus.h"
6#include "opus/opus_multistream.h"
7
8#ifndef OPUS_ENC_MAX_BUFFER_SIZE
9#define OPUS_ENC_MAX_BUFFER_SIZE 2048
10#endif
11
12#ifndef OPUS_DEC_MAX_BUFFER_SIZE
13#define OPUS_DEC_MAX_BUFFER_SIZE 4 * 1024
14#endif
15
16namespace audio_tools {
17
30
38 sample_rate = 48000;
39 channels = 2;
40 bits_per_sample = 16;
41 }
44 int streams = 1;
47 unsigned char mapping[255] = {};
48
53 break;
56 break;
57 default:
58 break;
59 }
60 }
61
63 memset(mapping, 0, sizeof(mapping));
64 if (channels == 1) {
65 streams = 1;
67 mapping[0] = 0;
68 } else if (channels == 2) {
69 streams = 1;
71 mapping[0] = 0;
72 mapping[1] = 1;
73 } else {
76 for (int i = 0; i < channels; i++) {
77 mapping[i] = i;
78 }
79 }
80 }
81
83 memset(mapping, 0, sizeof(mapping));
86 for (int i = 0; i < channels; i++) {
87 mapping[i] = i;
88 }
89 }
90};
91
116
130 public:
133
138
140
141 AudioInfo audioInfo() override { return cfg; }
142
145
147 TRACED();
149 cfg = settings;
151 return begin();
152 }
153
154 bool begin() override {
155 TRACED();
157 LOGE("Sample rate not supported: %d", cfg.sample_rate);
158 return false;
159 }
162 assert(outbuf.data() != nullptr);
163
164 int err;
167 cfg.mapping, &err);
168 if (err != OPUS_OK || dec == nullptr) {
169 LOGE(
170 "opus_multistream_decoder_create: %s for sample_rate: %d, "
171 "channels:%d, streams:%d, coupled:%d",
174 return false;
175 }
176 active = true;
177 return true;
178 }
179
180 void end() override {
181 TRACED();
182 if (dec != nullptr) {
184 dec = nullptr;
185 }
186 if (release_on_end) {
187 outbuf.resize(0);
188 }
189 active = false;
190 }
191
192 void setAudioInfo(AudioInfo from) override {
193 bool channels_changed = info.channels != from.channels;
195 info = from;
197 cfg.channels = from.channels;
199 if (channels_changed) {
201 end();
202 begin();
203 }
204 }
205
206 size_t write(const uint8_t* data, size_t len) override {
207 if (!active || p_print == nullptr) return 0;
208 LOGD("OpusMultiStreamAudioDecoder::write: %d", (int)len);
210 int frame_count = cfg.max_buffer_size / cfg.channels / sizeof(opus_int16);
212 dec, (uint8_t*)data, len, (opus_int16*)outbuf.data(), frame_count,
214 if (out_samples < 0) {
215 LOGW("opus_multistream_decode: %s", opus_strerror(out_samples));
216 } else if (out_samples > 0) {
217 int out_bytes = out_samples * cfg.channels * sizeof(int16_t);
218 LOGD("opus_multistream_decode: %d", out_bytes);
219 int open = out_bytes;
220 int processed = 0;
221 while (open > 0) {
222 int to_write = std::min(open, cfg.max_buffer_write_size);
223 int written = p_print->write(outbuf.data() + processed, to_write);
224 open -= written;
225 processed += written;
226 }
227 }
228 return len;
229 }
230
231 operator bool() override { return active; }
232
234
235 protected:
236 Print* p_print = nullptr;
237 OpusMSDecoder* dec = nullptr;
239 bool active = false;
241 const uint32_t valid_rates[5] = {8000, 12000, 16000, 24000, 48000};
242 bool release_on_end = false;
243
244 bool isValidRate(int rate) {
245 for (auto& valid : valid_rates) {
246 if (valid == rate) return true;
247 }
248 return false;
249 }
250};
251
268 public:
270
272
274
275 const char* mime() override { return "audio/opus"; }
276
277 void setAudioInfo(AudioInfo from) override {
278 LOGD("OpusMultiStreamAudioEncoder::setAudioInfo: sample_rate: %d, channels: %d",
279 from.sample_rate, from.channels);
282 cfg.channels = from.channels;
284 // Restart the encoder
285 if (enc != nullptr) {
286 end();
287 begin();
288 }
289 }
290
291 bool begin() override {
292 LOGD("OpusMultiStreamAudioEncoder::begin: sample_rate: %d, channels: %d",
294 int err;
295 int size =
297 frame.resize(size);
298 assert(frame.data() != nullptr);
299
300 // make sure that the channel mapping is set up correctly
302
303 int packet_len =
306 assert(packet.data() != nullptr);
309 cfg.mapping, cfg.application, &err);
310 if (err != OPUS_OK || enc == nullptr) {
311 LOGE(
312 "opus_multistream_encoder_create: %s for sample_rate: %d, "
313 "channels:%d, streams:%d, coupled:%d",
316 return false;
317 }
318 is_open = settings();
319 return is_open;
320 }
321
323
325
327 cfg = settings;
328 return begin();
329 }
330
331 void end() override {
332 if (frame_pos > 0) {
334 encodeFrame();
335 frame_pos = 0;
336 }
337 if (enc != nullptr) {
339 enc = nullptr;
340 }
341 is_open = false;
342 }
343
344 size_t write(const uint8_t* data, size_t len) override {
345 if (!is_open || p_print == nullptr) return 0;
346 LOGD("OpusMultiStreamAudioEncoder::write: %d", (int)len);
347 for (int j = 0; j < len; j++) {
348 encodeByte(data[j]);
349 }
350 return len;
351 }
352
353 operator bool() override { return is_open; }
354
355 bool isOpen() { return is_open; }
356
358 if (enc == nullptr) return 0;
359 opus_int32 samples = 0;
361 OPUS_OK) {
362 return 0;
363 }
364 return samples > 0 ? samples : 0;
365 }
366
368
370 int bytesPerSample = cfg.channels * (int)sizeof(int16_t);
371 if (bytesPerSample <= 0) return 0;
372 return frame_pos / bytesPerSample;
373 }
374
376
377 protected:
378 Print* p_print = nullptr;
379 OpusMSEncoder* enc = nullptr;
381 bool is_open = false;
384 int frame_pos = 0;
385
386 void encodeByte(uint8_t data) {
387 frame[frame_pos++] = data;
388 if (frame_pos >= frame.size()) {
389 encodeFrame();
390 frame_pos = 0;
391 }
392 }
393
394 void encodeFrame() {
395 if (frame.size() > 0) {
396 int frames = frame.size() / cfg.channels / sizeof(int16_t);
397 LOGD("opus_multistream_encode - frame_size: %d", frames);
398 int len = opus_multistream_encode(enc, (opus_int16*)frame.data(), frames,
399 packet.data(), packet.size());
400 if (len < 0) {
401 LOGE("opus_multistream_encode: %s", opus_strerror(len));
402 } else if (len > 0) {
403 LOGD("opus_multistream_encode: %d", len);
404 int eff = p_print->write(packet.data(), len);
405 if (eff != len) {
406 LOGE("encodeFrame data lost: %d->%d", len, eff);
407 }
408 }
409 }
410 }
411
412 int getFrameSizeSamples(int sampling_rate) {
413 switch (cfg.frame_sizes_ms_x2) {
415 return sampling_rate / 400;
417 return sampling_rate / 200;
419 return sampling_rate / 100;
421 return sampling_rate / 50;
423 return sampling_rate / 25;
425 return 3 * sampling_rate / 50;
427 return 4 * sampling_rate / 50;
429 return 5 * sampling_rate / 50;
431 return 6 * sampling_rate / 50;
432 }
433 return sampling_rate / 100;
434 }
435
436 bool settings() {
437 bool ok = true;
438 if (cfg.bitrate >= 0 &&
440 OPUS_OK) {
441 LOGE("invalid bitrate: %d", cfg.bitrate);
442 ok = false;
443 }
444 if (cfg.force_channel >= 0 &&
447 LOGE("invalid force_channel: %d", cfg.force_channel);
448 ok = false;
449 }
450 if (cfg.vbr >= 0 &&
452 LOGE("invalid vbr: %d", cfg.vbr);
453 ok = false;
454 }
455 if (cfg.vbr_constraint >= 0 &&
458 LOGE("invalid vbr_constraint: %d", cfg.vbr_constraint);
459 ok = false;
460 }
461 if (cfg.complexity >= 0 &&
464 LOGE("invalid complexity: %d", cfg.complexity);
465 ok = false;
466 }
467 if (cfg.max_bandwidth >= 0 &&
470 LOGE("invalid max_bandwidth: %d", cfg.max_bandwidth);
471 ok = false;
472 }
475 LOGE("invalid signal: %d", cfg.signal);
476 ok = false;
477 }
478 if (cfg.inband_fec >= 0 &&
481 LOGE("invalid inband_fec: %d", cfg.inband_fec);
482 ok = false;
483 }
484 if (cfg.packet_loss_perc >= 0 &&
487 LOGE("invalid pkt_loss: %d", cfg.packet_loss_perc);
488 ok = false;
489 }
490 if (cfg.lsb_depth >= 0 &&
492 OPUS_OK) {
493 LOGE("invalid lsb_depth: %d", cfg.lsb_depth);
494 ok = false;
495 }
496 if (cfg.prediction_disabled >= 0 &&
499 OPUS_OK) {
500 LOGE("invalid pred_disabled: %d", cfg.prediction_disabled);
501 ok = false;
502 }
505 LOGE("invalid use_dtx: %d", cfg.use_dtx);
506 ok = false;
507 }
508 if (cfg.frame_sizes_ms_x2 > 0 &&
511 OPUS_OK) {
512 LOGE("invalid frame_sizes_ms_x2: %d", cfg.frame_sizes_ms_x2);
513 ok = false;
514 }
515 return ok;
516 }
517};
518
519} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define OPUS_DEC_MAX_BUFFER_SIZE
Definition CodecOpus.h:12
#define OPUS_ENC_MAX_BUFFER_SIZE
Definition CodecOpus.h:8
#define assert(T)
Definition avr.h:10
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
AudioInfo info
Definition AudioCodecsBase.h:76
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:28
Encoding of PCM data.
Definition AudioCodecsBase.h:97
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition AudioCodecsBase.h:106
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:174
Decoder for the Opus multistream audio format. Supports up to 255 channels by combining multiple Opus...
Definition CodecOpusMultiStream.h:129
bool active
Definition CodecOpusMultiStream.h:239
void setOutput(Print &out_stream) override
Defines where the decoded result is written to.
Definition CodecOpusMultiStream.h:139
Vector< uint8_t > outbuf
Definition CodecOpusMultiStream.h:240
OpusMultiStreamSettings & defaultConfig()
Definition CodecOpusMultiStream.h:144
OpusMultiStreamAudioDecoder(Print &out_stream)
Definition CodecOpusMultiStream.h:134
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition CodecOpusMultiStream.h:192
bool begin(OpusMultiStreamSettings settings)
Definition CodecOpusMultiStream.h:146
void end() override
Definition CodecOpusMultiStream.h:180
OpusMultiStreamAudioDecoder(bool releaseOnEnd=false)
Definition CodecOpusMultiStream.h:131
size_t write(const uint8_t *data, size_t len) override
Definition CodecOpusMultiStream.h:206
OpusMultiStreamSettings & config()
Definition CodecOpusMultiStream.h:143
OpusMultiStreamSettings cfg
Definition CodecOpusMultiStream.h:238
const uint32_t valid_rates[5]
Definition CodecOpusMultiStream.h:241
bool release_on_end
Definition CodecOpusMultiStream.h:242
bool isValidRate(int rate)
Definition CodecOpusMultiStream.h:244
void setReleaseOnEnd(bool flag)
Definition CodecOpusMultiStream.h:233
bool begin() override
Definition CodecOpusMultiStream.h:154
Print * p_print
Definition CodecOpusMultiStream.h:236
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition CodecOpusMultiStream.h:141
OpusMSDecoder * dec
Definition CodecOpusMultiStream.h:237
Encoder for Opus multistream audio. Supports up to 255 channels by combining multiple Opus streams in...
Definition CodecOpusMultiStream.h:267
bool is_open
Definition CodecOpusMultiStream.h:381
void setOutput(Print &out_stream) override
Default output assignment (encoders may override to store Print reference)
Definition CodecOpusMultiStream.h:273
bool begin(OpusMultiStreamEncoderSettings settings)
Definition CodecOpusMultiStream.h:326
OpusMSEncoder * enc
Definition CodecOpusMultiStream.h:379
OpusMultiStreamEncoderSettings & defaultConfig()
Definition CodecOpusMultiStream.h:324
bool isOpen()
Definition CodecOpusMultiStream.h:355
uint16_t samplesPerFrame()
Optional rtsp function: provide samples per the frame.
Definition CodecOpusMultiStream.h:375
OpusMultiStreamEncoderSettings cfg
Definition CodecOpusMultiStream.h:380
int frameSizeSamples()
Definition CodecOpusMultiStream.h:367
void setAudioInfo(AudioInfo from) override
Defines the sample rate, number of channels and bits per sample.
Definition CodecOpusMultiStream.h:277
void end() override
Definition CodecOpusMultiStream.h:331
void encodeFrame()
Definition CodecOpusMultiStream.h:394
int lookaheadSamples()
Definition CodecOpusMultiStream.h:357
size_t write(const uint8_t *data, size_t len) override
Definition CodecOpusMultiStream.h:344
OpusMultiStreamAudioEncoder(Print &out)
Definition CodecOpusMultiStream.h:271
OpusMultiStreamEncoderSettings & config()
Definition CodecOpusMultiStream.h:322
int pendingSamples()
Definition CodecOpusMultiStream.h:369
bool settings()
Definition CodecOpusMultiStream.h:436
const char * mime() override
Provides the mime type of the encoded result.
Definition CodecOpusMultiStream.h:275
Vector< uint8_t > packet
Definition CodecOpusMultiStream.h:383
int frame_pos
Definition CodecOpusMultiStream.h:384
bool begin() override
Definition CodecOpusMultiStream.h:291
Print * p_print
Definition CodecOpusMultiStream.h:378
Vector< uint8_t > frame
Definition CodecOpusMultiStream.h:382
void encodeByte(uint8_t data)
Definition CodecOpusMultiStream.h:386
int getFrameSizeSamples(int sampling_rate)
Definition CodecOpusMultiStream.h:412
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:316
int size()
Definition Vector.h:178
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
opus_channel_mapping_enum_t
Defines the channel mapping scenarios for Opus MultiStream: default is OPUS_CHANNEL_MAPPING_COMBINED ...
Definition CodecOpusMultiStream.h:25
@ OPUS_CHANNEL_MAPPING_CUSTOM
Definition CodecOpusMultiStream.h:28
@ OPUS_CHANNEL_MAPPING_COMBINED
Definition CodecOpusMultiStream.h:26
@ OPUS_CHANNEL_MAPPING_SEPARATE
Definition CodecOpusMultiStream.h:27
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
Settings for Opus MultiStream Encoder.
Definition CodecOpusMultiStream.h:97
int vbr
Definition CodecOpusMultiStream.h:104
int vbr_constraint
Definition CodecOpusMultiStream.h:105
int frame_sizes_ms_x2
Definition CodecOpusMultiStream.h:114
OpusMultiStreamEncoderSettings()
Definition CodecOpusMultiStream.h:98
int inband_fec
Definition CodecOpusMultiStream.h:109
int use_dtx
Definition CodecOpusMultiStream.h:113
int packet_loss_perc
Definition CodecOpusMultiStream.h:110
int complexity
Definition CodecOpusMultiStream.h:106
int force_channel
Definition CodecOpusMultiStream.h:103
int signal
Definition CodecOpusMultiStream.h:108
int bitrate
Definition CodecOpusMultiStream.h:102
int prediction_disabled
Definition CodecOpusMultiStream.h:112
int max_bandwidth
Definition CodecOpusMultiStream.h:107
int lsb_depth
Definition CodecOpusMultiStream.h:111
int application
Definition CodecOpusMultiStream.h:101
Settings for Opus MultiStream Decoder.
Definition CodecOpusMultiStream.h:36
void setupSeparateChannelsMapping()
Definition CodecOpusMultiStream.h:82
unsigned char mapping[255]
Definition CodecOpusMultiStream.h:47
void setupDefaultMapping()
Definition CodecOpusMultiStream.h:62
int coupled_streams
Definition CodecOpusMultiStream.h:45
int max_buffer_size
Definition CodecOpusMultiStream.h:42
int streams
Definition CodecOpusMultiStream.h:44
opus_channel_mapping_enum_t default_channel_mapping
Definition CodecOpusMultiStream.h:46
int max_buffer_write_size
Definition CodecOpusMultiStream.h:43
void setupChannelMapping()
Definition CodecOpusMultiStream.h:49
OpusMultiStreamSettings()
Definition CodecOpusMultiStream.h:37