arduino-audio-tools
Loading...
Searching...
No Matches
AudioTypes.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioToolsConfig.h"
4#ifdef USE_TYPETRAITS
5#include <limits>
6#include <type_traits>
7#endif
8
12// Some top level functions: stop(), checkMemory()
14
15namespace audio_tools {
16
19using sample_rate_t = uint32_t;
20
26enum RxTxMode { UNDEFINED_MODE = 0, TX_MODE = 1, RX_MODE = 2, RXTX_MODE = 3 };
27
34
38static const char* RxTxModeNames[4] = {"UNDEFINED_MODE", "TX_MODE", "RX_MODE",
39 "RXTX_MODE"};
44// Some libc headers (e.g. sys/param.h, pulled in transitively by headers
45// included above) #define HZ - the #undef in AudioToolsConfig.h only guards
46// against pollution before that file's own includes run, not pollution
47// reintroduced by headers included since. Undef again right before use.
48#undef HZ
49enum TimeUnit { MS, US, HZ };
50static const char* TimeUnitStr[3]{"MS", "US", "HZ"};
51
56struct AudioInfo {
63
65 AudioInfo() = default;
66
68 AudioInfo(sample_rate_t sampleRate, uint16_t channelCount,
69 uint8_t bitsPerSample) {
70 sample_rate = sampleRate;
71 channels = channelCount;
72 bits_per_sample = bitsPerSample;
73 };
74
76 AudioInfo(const AudioInfo&) = default;
77
80 return sample_rate == alt.sample_rate && channels == alt.channels &&
82 }
83
85 bool operator!=(AudioInfo alt) { return !(*this == alt); }
86
88 bool equals(AudioInfo alt) { return *this == alt; }
89
92 return channels == alt.channels && bits_per_sample == alt.bits_per_sample;
93 }
94
96 void set(AudioInfo info) {
98 channels = info.channels;
100 }
101
103 void setAudioInfo(AudioInfo info) { set(info); }
104
106 void copyFrom(AudioInfo info) { setAudioInfo(info); }
107
108#ifndef SWIG
111 setAudioInfo(info);
112 return *this;
113 }
114#endif
116 operator bool() {
117 return sample_rate > 0 && sample_rate <= 192000 && channels > 0 &&
118 channels < 20 && bits_per_sample > 0 && bits_per_sample <= 64;
119 }
120
121 virtual void clear() {
122 sample_rate = 0;
123 channels = 0;
124 bits_per_sample = 0;
125 }
126
127 virtual void logInfo(const char* source = "") {
128 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d", source,
129 (int)sample_rate, (int)channels, (int)bits_per_sample);
130 }
131};
132
138 public:
140 virtual void setAudioInfo(AudioInfo info) = 0;
142 virtual AudioInfo audioInfo() = 0;
145 virtual AudioInfo audioInfoOut() { return audioInfo(); }
146};
147
153 public:
156 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
157 }
158
161 int pos = notify_vector.indexOf(&bi);
162 if (pos < 0) return false;
163 notify_vector.erase(pos);
164 return true;
165 }
166
168 virtual void clearNotifyAudioChange() { notify_vector.clear(); }
169
171 void setNotifyActive(bool flag) { is_notify_active = flag; }
172
175
176 protected:
178 bool is_notify_active = true;
179
181 if (isNotifyActive()) {
182 for (auto n : notify_vector) {
183 n->setAudioInfo(info);
184 }
185 }
186 }
187};
188
194 public:
196 virtual float volume() { return volume_value; }
198 virtual bool setVolume(float volume) {
200 return true;
201 }
202
203 protected:
204 float volume_value = 1.0f;
205};
206
212 public:
213 virtual size_t write(const uint8_t* data, size_t len) = 0;
214 virtual void setAudioInfo(AudioInfo from) = 0;
215 virtual void setOutput(Print& out_stream) = 0;
216 virtual operator bool() = 0;
217 virtual bool begin() = 0;
218 virtual bool begin(AudioInfo info) {
219 setAudioInfo(info);
220 return begin();
221 }
222 virtual void end() = 0;
223
224 protected:
225 void writeBlocking(Print* out, uint8_t* data, size_t len) {
226 TRACED();
227 int open = len;
228 int written = 0;
229 while (open > 0) {
230 int result = out->write(data + written, open);
231 open -= result;
232 written += result;
233 }
234 }
235};
236
242 public:
244 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit = 10) {
245 uint32_t result = 1000000l / samplingRate;
246 if (1000000l % samplingRate != 0) {
247 result++;
248 }
249 if (result <= limit) {
250 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
251 (unsigned int)samplingRate, (unsigned int)result,
252 (unsigned int)limit);
253 result = limit;
254 }
255 return result;
256 }
257
259 static uint32_t toBytes(uint32_t millis, AudioInfo info) {
260 size_t samples = info.sample_rate * millis / 1000;
261 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
262 return bytes;
263 }
264
265 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit = 1) {
266 uint32_t result = 1000l / samplingRate;
267 if (1000000l % samplingRate != 0) {
268 result++;
269 }
270 if (result <= limit) {
271 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
272 (unsigned int)samplingRate, (unsigned int)result,
273 (unsigned int)limit);
274 result = limit;
275 }
276 return result;
277 }
278
279 static float toRateUs(uint32_t time_us) { return 1000000.0 / time_us; }
280
281 static float toRateMs(uint32_t time_ms) { return 1000.0 / time_ms; }
282};
283
291template <typename T>
292inline T mapT(T x, T in_min, T in_max, T out_min, T out_max) {
293 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
294}
295
301 public:
303 static int64_t maxValue(int value_bits_per_sample) {
304 switch (value_bits_per_sample) {
305 case 8:
306 return 127;
307 case 16:
308 return 32767;
309 case 24:
310 return 8388607;
311 case 32:
312 return 2147483647;
313 }
314 return 32767;
315 }
316
318 template <typename T>
319 static float maxValueT() {
320#ifdef USE_TYPETRAITS
321 // int24_t uses 4 bytes instead of 3!
322 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
323 // maxValue(sizeof(T)*8);
324 return std::numeric_limits<T>::max();
325#else
326 return maxValue(sizeof(T) * 8);
327#endif
328 }
329
330 template <typename T>
331 static float minValueT() {
332#ifdef USE_TYPETRAITS
333 // int24_t uses 4 bytes instead of 3!
334 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
335 // maxValue(sizeof(T)*8);
336 return std::numeric_limits<T>::min();
337#else
338 return -maxValue(sizeof(T) * 8);
339#endif
340 }
341
343 template <typename T>
344 static T clipT(float value) {
345 float mv = maxValueT<T>();
346 if (value > mv) {
347 return mv;
348 } else if (value < -mv) {
349 return -mv;
350 }
351 return value;
352 }
353
355 inline static int32_t clip(float value, int bits) {
356 float mv = maxValue(bits);
357 if (value > mv) {
358 return mv;
359 } else if (value < -mv) {
360 return -mv;
361 }
362 return value;
363 }
364
366 template <typename T>
367 static float toFloatT(T value) {
368 return static_cast<float>(value) / maxValueT<T>();
369 }
370
372 template <typename T>
373 static T fromFloatT(float value) {
374 return value * maxValueT<T>();
375 }
376
378 inline static float toFloat(int32_t value, int bits) {
379 return static_cast<float>(value) / maxValue(bits);
380 }
381
383 inline static int32_t fromFloat(float value, int bits) {
384 return clip(value * maxValue(bits), bits);
385 }
386
388 template <typename FromT, typename ToT>
389 static ToT convert(FromT value) {
390 float value1 = value;
391 float minTo = minValueT<ToT>();
392 float maxTo = maxValueT<ToT>();
393 float maxFrom = maxValueT<FromT>();
394 float minFrom = minValueT<FromT>();
395
396 if (maxTo - minTo > 1.0f || maxFrom - minFrom > 1.0f) {
397 return mapT<float>(value1, minFrom, maxFrom, minTo, maxTo);
398 }
399
400 return value1 * maxValueT<ToT>() / maxValueT<FromT>();
401 }
402
404 template <typename FromT, typename ToT>
405 static void convertArray(FromT* from, ToT* to, int samples,
406 float vol = 1.0f) {
407 // convert() already maps FromT range to ToT range. Apply only the gain
408 // and clip to the valid ToT range to avoid double scaling.
409 for (int j = 0; j < samples; j++) {
410 ToT mapped = convert<FromT, ToT>(from[j]);
411 float scaled = static_cast<float>(mapped) * vol;
412 to[j] = clipT<ToT>(scaled);
413 }
414 }
415};
416
417#if defined(USE_I2S)
418
431
432static const char* i2s_formats[] = {"I2S_STD_FORMAT",
433 "I2S_LSB_FORMAT",
434 "I2S_MSB_FORMAT",
435 "I2S_PHILIPS_FORMAT",
436 "I2S_RIGHT_JUSTIFIED_FORMAT",
437 "I2S_LEFT_JUSTIFIED_FORMAT",
438 "I2S_PCM"};
439
449
450static const char* i2s_signal_types[] = {"Digital", "Analog", "PDM", "TDM"};
451
452#endif
453
455template <typename T>
456T readSample(Stream* p_stream) {
457 T result = 0;
458 uint8_t* p_result = (uint8_t*)&result;
459 int open = sizeof(T);
460 int total = 0;
461 // copy missing data
462 while (open > 0) {
463 int read = p_stream->readBytes(p_result + total, open);
464 open -= read;
465 total += read;
466 }
467 return result;
468}
469
471template <typename T>
472size_t readSamples(Stream* p_stream, T* data, int samples,
473 int retryCount = -1) {
474 uint8_t* p_result = (uint8_t*)data;
475 int open = samples * sizeof(T);
476 int total = 0;
477 int count0 = 0;
478 // copy missing data - we abort after 5 x read returned 0 bytes
479 while (open > 0) {
480 int read = p_stream->readBytes(p_result + total, open);
481 open -= read;
482 total += read;
483 if (read == 0) {
484 count0++;
485 delay(1);
486 } else {
487 count0 = 0;
488 }
489 // abort loop
490 if (retryCount >= 0 && count0 > retryCount) break;
491 }
492 // convert bytes to samples
493 return total / sizeof(T);
494}
495
497template <typename T, class P>
498size_t writeDataT(P* p_out, T* data, int samples, int maxSamples = 512) {
499 uint8_t* p_result = (uint8_t*)data;
500 int open = samples * sizeof(T);
501 int total = 0;
502 // copy missing data
503 while (open > 0) {
504 int to_write = min(open, static_cast<int>(maxSamples * sizeof(T)));
505 int written = p_out->write(p_result + total, to_write);
506 open -= written;
507 total += written;
508 }
509 // convert bytes to samples
510 return total / sizeof(T);
511}
512
513template <typename T>
514size_t writeData(Print* p_out, T* data, int samples, int maxSamples = 512) {
515 return writeDataT<T, Print>(p_out, data, samples, maxSamples);
516}
517
519static const char* mime_pcm = "audio/pcm";
520
521#ifndef IS_DESKTOP
523inline void waitFor(HardwareSerial& out) { while (!out); }
524#endif
525
527inline void waitFor(bool& flag) { while (!flag); }
528
532
553 public:
567 virtual const char* mime() = 0;
568};
569
586 public:
592 virtual uint32_t millis() { return ::millis(); }
593
603 virtual uint32_t playbackTime() { return millis(); }
604};
605
606} // namespace audio_tools
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define DEFAULT_BITS_PER_SAMPLE
Definition AudioToolsConfig.h:99
#define DEFAULT_CHANNELS
Definition AudioToolsConfig.h:95
#define DEFAULT_SAMPLE_RATE
Definition AudioToolsConfig.h:91
Definition Arduino.h:172
Definition Arduino.h:56
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
Supports the subscription to audio change notifications.
Definition AudioTypes.h:152
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:174
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:180
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:155
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:171
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:160
Vector< AudioInfoSupport * > notify_vector
Definition AudioTypes.h:177
bool is_notify_active
Definition AudioTypes.h:178
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:168
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:137
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:145
virtual AudioInfo audioInfo()=0
provides the actual input AudioInfo
virtual void setAudioInfo(AudioInfo info)=0
Defines the input AudioInfo.
Tools for calculating timer values.
Definition AudioTypes.h:241
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:259
static float toRateUs(uint32_t time_us)
Definition AudioTypes.h:279
static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit=1)
Definition AudioTypes.h:265
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:244
static float toRateMs(uint32_t time_ms)
Definition AudioTypes.h:281
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:211
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:225
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
virtual bool begin(AudioInfo info)
Definition AudioTypes.h:218
virtual size_t write(const uint8_t *data, size_t len)=0
virtual void setOutput(Print &out_stream)=0
virtual void end()=0
virtual bool begin()=0
Abstract interface for classes that can provide MIME type information.
Definition AudioTypes.h:552
virtual const char * mime()=0
Get the MIME type string.
Converts from a source to a target number with a different type.
Definition AudioTypes.h:300
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:367
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:373
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:405
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:378
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:344
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:383
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:303
static float minValueT()
Definition AudioTypes.h:331
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:389
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:355
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:319
Interface for classes that can provide time information - two distinct notions of "now",...
Definition AudioTypes.h:585
virtual uint32_t playbackTime()
Definition AudioTypes.h:603
virtual uint32_t millis()
Definition AudioTypes.h:592
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Supports the setting and getting of the volume.
Definition AudioTypes.h:193
float volume_value
Definition AudioTypes.h:204
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:196
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:198
MemoryType
Memory types.
Definition AudioTypes.h:33
uint32_t sample_rate_t
Type alias for sample rate values.
Definition AudioTypes.h:19
void waitFor(bool &flag)
wait for flag to be active
Definition AudioTypes.h:527
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
TimeUnit
Time Units.
Definition AudioTypes.h:49
@ RAM
Definition AudioTypes.h:33
@ PS_RAM
Definition AudioTypes.h:33
@ FLASH_RAM
Definition AudioTypes.h:33
@ RXTX_MODE
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ UNDEFINED_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
@ US
Definition AudioTypes.h:49
@ HZ
Definition AudioTypes.h:49
@ MS
Definition AudioTypes.h:49
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
static const char * i2s_signal_types[]
Definition AudioTypes.h:450
I2SSignalType
I2S Signal Types: Digital, Analog, PDM.
Definition AudioTypes.h:443
@ Digital
Definition AudioTypes.h:444
@ PDM
Definition AudioTypes.h:446
@ TDM
Definition AudioTypes.h:447
@ Analog
Definition AudioTypes.h:445
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:472
static const char * mime_pcm
Mime type for PCM.
Definition AudioTypes.h:519
static const char * TimeUnitStr[3]
Definition AudioTypes.h:50
static const char * RxTxModeNames[4]
Text string (description) for RxTxMode.
Definition AudioTypes.h:38
T mapT(T x, T in_min, T in_max, T out_min, T out_max)
Similar to Arduino map function but using floats.
Definition AudioTypes.h:292
I2SFormat
I2S Formats.
Definition AudioTypes.h:422
@ I2S_STD_FORMAT
Definition AudioTypes.h:423
@ I2S_PHILIPS_FORMAT
Definition AudioTypes.h:426
@ I2S_LSB_FORMAT
Definition AudioTypes.h:424
@ I2S_LEFT_JUSTIFIED_FORMAT
Definition AudioTypes.h:428
@ I2S_RIGHT_JUSTIFIED_FORMAT
Definition AudioTypes.h:427
@ I2S_MSB_FORMAT
Definition AudioTypes.h:425
@ I2S_PCM
Definition AudioTypes.h:429
void delay(uint32_t ms)
Definition Arduino.h:259
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:456
static const char * i2s_formats[]
Definition AudioTypes.h:432
size_t writeDataT(P *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition AudioTypes.h:498
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:260
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:514
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:106
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:58
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:88
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60
void set(AudioInfo info)
Copies the values from info.
Definition AudioTypes.h:96
AudioInfo(const AudioInfo &)=default
Copy constructor.
AudioInfo & operator=(const AudioInfo &info)
Same as set.
Definition AudioTypes.h:110
bool operator==(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:79
void setAudioInfo(AudioInfo info)
Same as set.
Definition AudioTypes.h:103
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:91
bool operator!=(AudioInfo alt)
Returns true if alt values are the different from the current values.
Definition AudioTypes.h:85
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:62
virtual void clear()
Definition AudioTypes.h:121
virtual void logInfo(const char *source="")
Definition AudioTypes.h:127
AudioInfo(sample_rate_t sampleRate, uint16_t channelCount, uint8_t bitsPerSample)
Constructor which supports all attribures as parameters.
Definition AudioTypes.h:68
AudioInfo()=default
Default constructor.