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"};
44enum TimeUnit { MS, US, HZ };
45static const char* TimeUnitStr[3]{"MS", "US", "HZ"};
46
51struct AudioInfo {
58
60 AudioInfo() = default;
61
63 AudioInfo(sample_rate_t sampleRate, uint16_t channelCount,
64 uint8_t bitsPerSample) {
65 sample_rate = sampleRate;
66 channels = channelCount;
67 bits_per_sample = bitsPerSample;
68 };
69
71 AudioInfo(const AudioInfo&) = default;
72
75 return sample_rate == alt.sample_rate && channels == alt.channels &&
77 }
78
80 bool operator!=(AudioInfo alt) { return !(*this == alt); }
81
83 bool equals(AudioInfo alt) { return *this == alt; }
84
87 return channels == alt.channels && bits_per_sample == alt.bits_per_sample;
88 }
89
91 void set(AudioInfo info) {
93 channels = info.channels;
95 }
96
98 void setAudioInfo(AudioInfo info) { set(info); }
99
101 void copyFrom(AudioInfo info) { setAudioInfo(info); }
102
103#ifndef SWIG
106 setAudioInfo(info);
107 return *this;
108 }
109#endif
111 operator bool() {
112 return sample_rate > 0 && sample_rate <= 100000 && channels > 0 && channels < 20 && bits_per_sample > 0 && bits_per_sample <= 64;
113 }
114
115 virtual void clear() {
116 sample_rate = 0;
117 channels = 0;
118 bits_per_sample = 0;
119 }
120
121 virtual void logInfo(const char* source = "") {
122 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d", source,
123 (int)sample_rate, (int)channels, (int)bits_per_sample);
124 }
125};
126
132 public:
134 virtual void setAudioInfo(AudioInfo info) = 0;
136 virtual AudioInfo audioInfo() = 0;
139 virtual AudioInfo audioInfoOut() { return audioInfo(); }
140};
141
147 public:
150 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
151 }
152
155 int pos = notify_vector.indexOf(&bi);
156 if (pos < 0) return false;
157 notify_vector.erase(pos);
158 return true;
159 }
160
162 virtual void clearNotifyAudioChange() { notify_vector.clear(); }
163
165 void setNotifyActive(bool flag) { is_notify_active = flag; }
166
169
170 protected:
172 bool is_notify_active = true;
173
175 if (isNotifyActive()) {
176 for (auto n : notify_vector) {
177 n->setAudioInfo(info);
178 }
179 }
180 }
181};
182
188 public:
190 virtual float volume() { return volume_value; }
192 virtual bool setVolume(float volume) {
194 return true;
195 }
196
197 protected:
198 float volume_value = 1.0f;
199};
200
206 public:
207 virtual size_t write(const uint8_t* data, size_t len) = 0;
208 virtual void setAudioInfo(AudioInfo from) = 0;
209 virtual void setOutput(Print& out_stream) = 0;
210 virtual operator bool() = 0;
211 virtual bool begin() = 0;
212 virtual bool begin(AudioInfo info) {
213 setAudioInfo(info);
214 return begin();
215 }
216 virtual void end() = 0;
217
218 protected:
219 void writeBlocking(Print* out, uint8_t* data, size_t len) {
220 TRACED();
221 int open = len;
222 int written = 0;
223 while (open > 0) {
224 int result = out->write(data + written, open);
225 open -= result;
226 written += result;
227 }
228 }
229};
230
236 public:
238 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit = 10) {
239 uint32_t result = 1000000l / samplingRate;
240 if (1000000l % samplingRate != 0) {
241 result++;
242 }
243 if (result <= limit) {
244 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
245 (unsigned int)samplingRate, (unsigned int)result,
246 (unsigned int)limit);
247 result = limit;
248 }
249 return result;
250 }
251
253 static uint32_t toBytes(uint32_t millis, AudioInfo info) {
254 size_t samples = info.sample_rate * millis / 1000;
255 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
256 return bytes;
257 }
258
259 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit = 1) {
260 uint32_t result = 1000l / samplingRate;
261 if (1000000l % samplingRate != 0) {
262 result++;
263 }
264 if (result <= limit) {
265 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
266 (unsigned int)samplingRate, (unsigned int)result,
267 (unsigned int)limit);
268 result = limit;
269 }
270 return result;
271 }
272
273 static float toRateUs(uint32_t time_us) { return 1000000.0 / time_us; }
274
275 static float toRateMs(uint32_t time_ms) { return 1000.0 / time_ms; }
276};
277
285template <typename T>
286inline T mapT(T x, T in_min, T in_max, T out_min, T out_max) {
287 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
288}
289
295 public:
297 static int64_t maxValue(int value_bits_per_sample) {
298 switch (value_bits_per_sample) {
299 case 8:
300 return 127;
301 case 16:
302 return 32767;
303 case 24:
304 return 8388607;
305 case 32:
306 return 2147483647;
307 }
308 return 32767;
309 }
310
312 template <typename T>
313 static float maxValueT() {
314#ifdef USE_TYPETRAITS
315 // int24_t uses 4 bytes instead of 3!
316 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
317 // maxValue(sizeof(T)*8);
318 return std::numeric_limits<T>::max();
319#else
320 return maxValue(sizeof(T) * 8);
321#endif
322 }
323
324 template <typename T>
325 static float minValueT() {
326#ifdef USE_TYPETRAITS
327 // int24_t uses 4 bytes instead of 3!
328 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
329 // maxValue(sizeof(T)*8);
330 return std::numeric_limits<T>::min();
331#else
332 return -maxValue(sizeof(T) * 8);
333#endif
334 }
335
337 template <typename T>
338 static T clipT(float value) {
339 float mv = maxValueT<T>();
340 if (value > mv) {
341 return mv;
342 } else if (value < -mv) {
343 return -mv;
344 }
345 return value;
346 }
347
349 inline static int32_t clip(float value, int bits) {
350 float mv = maxValue(bits);
351 if (value > mv) {
352 return mv;
353 } else if (value < -mv) {
354 return -mv;
355 }
356 return value;
357 }
358
360 template <typename T>
361 static float toFloatT(T value) {
362 return static_cast<float>(value) / maxValueT<T>();
363 }
364
366 template <typename T>
367 static T fromFloatT(float value) {
368 return value * maxValueT<T>();
369 }
370
372 inline static float toFloat(int32_t value, int bits) {
373 return static_cast<float>(value) / maxValue(bits);
374 }
375
377 inline static int32_t fromFloat(float value, int bits) {
378 return clip(value * maxValue(bits), bits);
379 }
380
382 template <typename FromT, typename ToT>
383 static ToT convert(FromT value) {
384 float value1 = value;
385 float minTo = minValueT<ToT>();
386 float maxTo = maxValueT<ToT>();
387 float maxFrom = maxValueT<FromT>();
388 float minFrom = minValueT<FromT>();
389
390 if (maxTo - minTo > 1.0f || maxFrom - minFrom > 1.0f) {
391 return mapT<float>(value1, minFrom, maxFrom, minTo, maxTo);
392 }
393
394 return value1 * maxValueT<ToT>() / maxValueT<FromT>();
395 }
396
398 template <typename FromT, typename ToT>
399 static void convertArray(FromT* from, ToT* to, int samples,
400 float vol = 1.0f) {
401 // convert() already maps FromT range to ToT range. Apply only the gain
402 // and clip to the valid ToT range to avoid double scaling.
403 for (int j = 0; j < samples; j++) {
404 ToT mapped = convert<FromT, ToT>(from[j]);
405 float scaled = static_cast<float>(mapped) * vol;
406 to[j] = clipT<ToT>(scaled);
407 }
408 }
409};
410
411#if defined(USE_I2S)
412
425
426static const char* i2s_formats[] = {"I2S_STD_FORMAT",
427 "I2S_LSB_FORMAT",
428 "I2S_MSB_FORMAT",
429 "I2S_PHILIPS_FORMAT",
430 "I2S_RIGHT_JUSTIFIED_FORMAT",
431 "I2S_LEFT_JUSTIFIED_FORMAT",
432 "I2S_PCM"};
433
443
444static const char* i2s_signal_types[] = {"Digital", "Analog", "PDM", "TDM"};
445
446#endif
447
449template <typename T>
450T readSample(Stream* p_stream) {
451 T result = 0;
452 uint8_t* p_result = (uint8_t*)&result;
453 int open = sizeof(T);
454 int total = 0;
455 // copy missing data
456 while (open > 0) {
457 int read = p_stream->readBytes(p_result + total, open);
458 open -= read;
459 total += read;
460 }
461 return result;
462}
463
465template <typename T>
466size_t readSamples(Stream* p_stream, T* data, int samples,
467 int retryCount = -1) {
468 uint8_t* p_result = (uint8_t*)data;
469 int open = samples * sizeof(T);
470 int total = 0;
471 int count0 = 0;
472 // copy missing data - we abort after 5 x read returned 0 bytes
473 while (open > 0) {
474 int read = p_stream->readBytes(p_result + total, open);
475 open -= read;
476 total += read;
477 if (read == 0) {
478 count0++;
479 delay(1);
480 } else {
481 count0 = 0;
482 }
483 // abort loop
484 if (retryCount >= 0 && count0 > retryCount) break;
485 }
486 // convert bytes to samples
487 return total / sizeof(T);
488}
489
491template <typename T, class P>
492size_t writeDataT(P* p_out, T* data, int samples, int maxSamples = 512) {
493 uint8_t* p_result = (uint8_t*)data;
494 int open = samples * sizeof(T);
495 int total = 0;
496 // copy missing data
497 while (open > 0) {
498 int to_write = min(open, static_cast<int>(maxSamples * sizeof(T)));
499 int written = p_out->write(p_result + total, to_write);
500 open -= written;
501 total += written;
502 }
503 // convert bytes to samples
504 return total / sizeof(T);
505}
506
507template <typename T>
508size_t writeData(Print* p_out, T* data, int samples, int maxSamples = 512) {
509 return writeDataT<T, Print>(p_out, data, samples, maxSamples);
510}
511
513static const char* mime_pcm = "audio/pcm";
514
515#ifndef IS_DESKTOP
517inline void waitFor(HardwareSerial& out) { while (!out); }
518#endif
519
521inline void waitFor(bool& flag) { while (!flag); }
522
526
527} // 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:104
#define DEFAULT_CHANNELS
Definition AudioToolsConfig.h:100
#define DEFAULT_SAMPLE_RATE
Definition AudioToolsConfig.h:96
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:146
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:168
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:174
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:149
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:165
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:154
Vector< AudioInfoSupport * > notify_vector
Definition AudioTypes.h:171
bool is_notify_active
Definition AudioTypes.h:172
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:162
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:131
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:139
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:235
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:253
static float toRateUs(uint32_t time_us)
Definition AudioTypes.h:273
static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit=1)
Definition AudioTypes.h:259
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:238
static float toRateMs(uint32_t time_ms)
Definition AudioTypes.h:275
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:205
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:219
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
virtual bool begin(AudioInfo info)
Definition AudioTypes.h:212
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
Converts from a source to a target number with a different type.
Definition AudioTypes.h:294
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:361
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:367
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:399
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:372
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:338
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:377
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:297
static float minValueT()
Definition AudioTypes.h:325
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:383
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:349
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:313
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:187
float volume_value
Definition AudioTypes.h:198
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:190
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:192
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:521
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:44
@ 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:44
@ HZ
Definition AudioTypes.h:44
@ MS
Definition AudioTypes.h:44
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:444
I2SSignalType
I2S Signal Types: Digital, Analog, PDM.
Definition AudioTypes.h:437
@ Digital
Definition AudioTypes.h:438
@ PDM
Definition AudioTypes.h:440
@ TDM
Definition AudioTypes.h:441
@ Analog
Definition AudioTypes.h:439
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:466
static const char * mime_pcm
Mime type for PCM.
Definition AudioTypes.h:513
static const char * TimeUnitStr[3]
Definition AudioTypes.h:45
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:286
I2SFormat
I2S Formats.
Definition AudioTypes.h:416
@ I2S_STD_FORMAT
Definition AudioTypes.h:417
@ I2S_PHILIPS_FORMAT
Definition AudioTypes.h:420
@ I2S_LSB_FORMAT
Definition AudioTypes.h:418
@ I2S_LEFT_JUSTIFIED_FORMAT
Definition AudioTypes.h:422
@ I2S_RIGHT_JUSTIFIED_FORMAT
Definition AudioTypes.h:421
@ I2S_MSB_FORMAT
Definition AudioTypes.h:419
@ I2S_PCM
Definition AudioTypes.h:423
void delay(uint32_t ms)
Definition Arduino.h:255
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:450
static const char * i2s_formats[]
Definition AudioTypes.h:426
size_t writeDataT(P *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition AudioTypes.h:492
uint32_t millis()
Returns the milliseconds since the start.
Definition Arduino.h:256
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
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:101
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:83
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
void set(AudioInfo info)
Copies the values from info.
Definition AudioTypes.h:91
AudioInfo(const AudioInfo &)=default
Copy constructor.
AudioInfo & operator=(const AudioInfo &info)
Same as set.
Definition AudioTypes.h:105
bool operator==(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:74
void setAudioInfo(AudioInfo info)
Same as set.
Definition AudioTypes.h:98
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:86
bool operator!=(AudioInfo alt)
Returns true if alt values are the different from the current values.
Definition AudioTypes.h:80
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57
virtual void clear()
Definition AudioTypes.h:115
virtual void logInfo(const char *source="")
Definition AudioTypes.h:121
AudioInfo(sample_rate_t sampleRate, uint16_t channelCount, uint8_t bitsPerSample)
Constructor which supports all attribures as parameters.
Definition AudioTypes.h:63
AudioInfo()=default
Default constructor.