arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
AudioTypes.h
1#pragma once
2
3#include "AudioToolsConfig.h"
4#ifdef USE_TYPETRAITS
5#include <limits>
6#include <type_traits>
7#endif
8
9#include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.h"
10#include "AudioTools/CoreAudio/AudioLogger.h"
11
12// fix compile error for ESP32 C3
13#undef HZ
14
15// MIN
16#undef MIN
17#define MIN(A, B) ((A) < (B) ? (A) : (B))
18
19namespace audio_tools {
20
21using sample_rate_t = uint32_t;
22
28enum RxTxMode { UNDEFINED_MODE = 0, TX_MODE = 1, RX_MODE = 2, RXTX_MODE = 3 };
29
35enum MemoryType { RAM, PS_RAM, FLASH_RAM };
36
40static const char* RxTxModeNames[4] = {"UNDEFINED_MODE", "TX_MODE", "RX_MODE",
41 "RXTX_MODE"};
46enum TimeUnit { MS, US, HZ };
47static const char* TimeUnitStr[3]{"MS", "US", "HZ"};
48
53struct AudioInfo {
55 sample_rate_t sample_rate = DEFAULT_SAMPLE_RATE;
57 uint16_t channels = DEFAULT_CHANNELS;
59 uint8_t bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
60
62 AudioInfo() = default;
63
65 AudioInfo(sample_rate_t sampleRate, uint16_t channelCount,
66 uint8_t bitsPerSample) {
67 sample_rate = sampleRate;
68 channels = channelCount;
69 bits_per_sample = bitsPerSample;
70 };
71
73 AudioInfo(const AudioInfo&) = default;
74
77 return sample_rate == alt.sample_rate && channels == alt.channels &&
79 }
80
82 bool operator!=(AudioInfo alt) { return !(*this == alt); }
83
85 bool equals(AudioInfo alt) { return *this == alt; }
86
89 return channels == alt.channels && bits_per_sample == alt.bits_per_sample;
90 }
91
93 void set(AudioInfo info) {
95 channels = info.channels;
97 }
98
100 void setAudioInfo(AudioInfo info) { set(info); }
101
103 void copyFrom(AudioInfo info) { setAudioInfo(info); }
104
105#ifndef SWIG
108 setAudioInfo(info);
109 return *this;
110 }
111#endif
113 operator bool() {
114 return sample_rate > 0 && channels > 0 && bits_per_sample > 0;
115 }
116
117 virtual void clear() {
118 sample_rate = 0;
119 channels = 0;
120 bits_per_sample = 0;
121 }
122
123 virtual void logInfo(const char* source = "") {
124 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d", source,
125 (int)sample_rate, (int)channels, (int)bits_per_sample);
126 }
127};
128
134 public:
136 virtual void setAudioInfo(AudioInfo info) = 0;
138 virtual AudioInfo audioInfo() = 0;
141 virtual AudioInfo audioInfoOut() { return audioInfo(); }
142};
143
149 public:
152 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
153 }
154
157 int pos = notify_vector.indexOf(&bi);
158 if (pos < 0) return false;
159 notify_vector.erase(pos);
160 return true;
161 }
162
164 virtual void clearNotifyAudioChange() { notify_vector.clear(); }
165
167 void setNotifyActive(bool flag) { is_notify_active = flag; }
168
170 bool isNotifyActive() { return is_notify_active; }
171
172 protected:
173 Vector<AudioInfoSupport*> notify_vector;
174 bool is_notify_active = true;
175
176 void notifyAudioChange(AudioInfo info) {
177 if (isNotifyActive()) {
178 for (auto n : notify_vector) {
179 n->setAudioInfo(info);
180 }
181 }
182 }
183};
184
190 public:
192 virtual float volume() { return volume_value; }
194 virtual bool setVolume(float volume) {
195 volume_value = volume;
196 return true;
197 }
198
199 protected:
200 float volume_value = 1.0f;
201};
202
208 public:
209 virtual size_t write(const uint8_t* data, size_t len) = 0;
210 virtual void setAudioInfo(AudioInfo from) = 0;
211 virtual void setOutput(Print& out_stream) = 0;
212 virtual operator bool() = 0;
213 virtual bool begin() = 0;
214 virtual bool begin(AudioInfo info) {
215 setAudioInfo(info);
216 return begin();
217 }
218 virtual void end() = 0;
219
220 protected:
221 void writeBlocking(Print* out, uint8_t* data, size_t len) {
222 TRACED();
223 int open = len;
224 int written = 0;
225 while (open > 0) {
226 int result = out->write(data + written, open);
227 open -= result;
228 written += result;
229 }
230 }
231};
232
238 public:
240 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit = 10) {
241 uint32_t result = 1000000l / samplingRate;
242 if (1000000l % samplingRate != 0) {
243 result++;
244 }
245 if (result <= limit) {
246 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
247 (unsigned int)samplingRate, (unsigned int)result,
248 (unsigned int)limit);
249 result = limit;
250 }
251 return result;
252 }
253
255 static uint32_t toBytes(uint32_t millis, AudioInfo info) {
256 size_t samples = info.sample_rate * millis / 1000;
257 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
258 return bytes;
259 }
260
261 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit = 1) {
262 uint32_t result = 1000l / samplingRate;
263 if (1000000l % samplingRate != 0) {
264 result++;
265 }
266 if (result <= limit) {
267 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
268 (unsigned int)samplingRate, (unsigned int)result,
269 (unsigned int)limit);
270 result = limit;
271 }
272 return result;
273 }
274
275 static float toRateUs(uint32_t time_us) { return 1000000.0 / time_us; }
276
277 static float toRateMs(uint32_t time_ms) { return 1000.0 / time_ms; }
278};
279
287template <typename T>
288inline T mapT(T x, T in_min, T in_max, T out_min, T out_max) {
289 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
290}
291
297 public:
299 static int64_t maxValue(int value_bits_per_sample) {
300 switch (value_bits_per_sample) {
301 case 8:
302 return 127;
303 case 16:
304 return 32767;
305 case 24:
306 return 8388607;
307 case 32:
308 return 2147483647;
309 }
310 return 32767;
311 }
312
314 template <typename T>
315 static float maxValueT() {
316#ifdef USE_TYPETRAITS
317 // int24_t uses 4 bytes instead of 3!
318 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
319 // maxValue(sizeof(T)*8);
320 return std::numeric_limits<T>::max();
321#else
322 return maxValue(sizeof(T) * 8);
323#endif
324 }
325
326 template <typename T>
327 static float minValueT() {
328#ifdef USE_TYPETRAITS
329 // int24_t uses 4 bytes instead of 3!
330 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
331 // maxValue(sizeof(T)*8);
332 return std::numeric_limits<T>::min();
333#else
334 return -maxValue(sizeof(T) * 8);
335#endif
336 }
337
339 template <typename T>
340 static T clipT(float value) {
341 float mv = maxValueT<T>();
342 if (value > mv) {
343 return mv;
344 } else if (value < -mv) {
345 return -mv;
346 }
347 return value;
348 }
349
351 inline static int32_t clip(float value, int bits) {
352 float mv = maxValue(bits);
353 if (value > mv) {
354 return mv;
355 } else if (value < -mv) {
356 return -mv;
357 }
358 return value;
359 }
360
362 template <typename T>
363 static float toFloatT(T value) {
364 return static_cast<float>(value) / maxValueT<T>();
365 }
366
368 template <typename T>
369 static T fromFloatT(float value) {
370 return value * maxValueT<T>();
371 }
372
374 inline static float toFloat(int32_t value, int bits) {
375 return static_cast<float>(value) / maxValue(bits);
376 }
377
379 inline static int32_t fromFloat(float value, int bits) {
380 return clip(value * maxValue(bits), bits);
381 }
382
384 template <typename FromT, typename ToT>
385 static ToT convert(FromT value) {
386 float value1 = value;
387 float minTo = minValueT<ToT>();
388 float maxTo = maxValueT<ToT>();
389 float maxFrom = maxValueT<FromT>();
390 float minFrom = minValueT<FromT>();
391
392 if (maxTo - minTo > 1.0f || maxFrom - minFrom > 1.0f) {
393 return mapT<float>(value1, minFrom, maxFrom, minTo, maxTo);
394 }
395
396 return value1 * maxValueT<ToT>() / maxValueT<FromT>();
397 }
398
400 template <typename FromT, typename ToT>
401 static void convertArray(FromT* from, ToT* to, int samples,
402 float vol = 1.0f) {
403 float factor = static_cast<float>(maxValueT<ToT>()) / maxValueT<FromT>();
404 float vol_factor = factor * vol;
405 for (int j = 0; j < samples; j++) {
406 to[j] = clipT<ToT>(vol * convert<FromT, ToT>(from[j]));
407 }
408 }
409};
410
411#if defined(USE_I2S)
412
417 I2S_STD_FORMAT,
418 I2S_LSB_FORMAT,
419 I2S_MSB_FORMAT,
420 I2S_PHILIPS_FORMAT,
421 I2S_RIGHT_JUSTIFIED_FORMAT,
422 I2S_LEFT_JUSTIFIED_FORMAT,
423 I2S_PCM,
424};
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
438 Digital,
439 Analog,
440 PDM,
441 TDM,
442};
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
525
526} // namespace audio_tools
Supports the subscription to audio change notifications.
Definition AudioTypes.h:148
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:170
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:151
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:167
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:156
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:164
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:133
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:141
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:237
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:255
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:240
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:207
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
Definition NoArduino.h:179
Converts from a source to a target number with a different type.
Definition AudioTypes.h:296
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:363
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:369
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:401
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:374
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:340
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:379
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:299
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:385
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:351
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:315
Definition NoArduino.h:62
Definition NoArduino.h:142
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:189
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:192
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:194
MemoryType
Memory types.
Definition AudioTypes.h:35
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:28
TimeUnit
Time Units.
Definition AudioTypes.h:46
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
I2SSignalType
I2S Signal Types: Digital, Analog, PDM.
Definition AudioTypes.h:437
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 * RxTxModeNames[4]
Text string (description) for RxTxMode.
Definition AudioTypes.h:40
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:288
I2SFormat
I2S Formats.
Definition AudioTypes.h:416
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:450
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 Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:103
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:85
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
void set(AudioInfo info)
Copies the values from info.
Definition AudioTypes.h:93
AudioInfo(const AudioInfo &)=default
Copy constructor.
AudioInfo & operator=(const AudioInfo &info)
Same as set.
Definition AudioTypes.h:107
bool operator==(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:76
void setAudioInfo(AudioInfo info)
Same as set.
Definition AudioTypes.h:100
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:88
bool operator!=(AudioInfo alt)
Returns true if alt values are the different from the current values.
Definition AudioTypes.h:82
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59
AudioInfo(sample_rate_t sampleRate, uint16_t channelCount, uint8_t bitsPerSample)
Constructor which supports all attribures as parameters.
Definition AudioTypes.h:65
AudioInfo()=default
Default constructor.