arduino-audio-tools
Loading...
Searching...
No Matches
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
23using sample_rate_t = uint32_t;
24
30enum RxTxMode { UNDEFINED_MODE = 0, TX_MODE = 1, RX_MODE = 2, RXTX_MODE = 3 };
31
37enum MemoryType { RAM, PS_RAM, FLASH_RAM };
38
42static const char* RxTxModeNames[4] = {"UNDEFINED_MODE", "TX_MODE", "RX_MODE",
43 "RXTX_MODE"};
48enum TimeUnit { MS, US, HZ };
49static const char* TimeUnitStr[3]{"MS", "US", "HZ"};
50
55struct AudioInfo {
57 sample_rate_t sample_rate = DEFAULT_SAMPLE_RATE;
59 uint16_t channels = DEFAULT_CHANNELS;
61 uint8_t bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
62
64 AudioInfo() = default;
65
67 AudioInfo(sample_rate_t sampleRate, uint16_t channelCount,
68 uint8_t bitsPerSample) {
69 sample_rate = sampleRate;
70 channels = channelCount;
71 bits_per_sample = bitsPerSample;
72 };
73
75 AudioInfo(const AudioInfo&) = default;
76
79 return sample_rate == alt.sample_rate && channels == alt.channels &&
81 }
82
84 bool operator!=(AudioInfo alt) { return !(*this == alt); }
85
87 bool equals(AudioInfo alt) { return *this == alt; }
88
91 return channels == alt.channels && bits_per_sample == alt.bits_per_sample;
92 }
93
95 void set(AudioInfo info) {
97 channels = info.channels;
99 }
100
102 void setAudioInfo(AudioInfo info) { set(info); }
103
105 void copyFrom(AudioInfo info) { setAudioInfo(info); }
106
107#ifndef SWIG
110 setAudioInfo(info);
111 return *this;
112 }
113#endif
115 operator bool() {
116 return sample_rate > 0 && sample_rate <= 100000 && channels > 0 && channels < 20 && bits_per_sample > 0 && bits_per_sample <= 64;
117 }
118
119 virtual void clear() {
120 sample_rate = 0;
121 channels = 0;
122 bits_per_sample = 0;
123 }
124
125 virtual void logInfo(const char* source = "") {
126 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d", source,
127 (int)sample_rate, (int)channels, (int)bits_per_sample);
128 }
129};
130
136 public:
138 virtual void setAudioInfo(AudioInfo info) = 0;
140 virtual AudioInfo audioInfo() = 0;
143 virtual AudioInfo audioInfoOut() { return audioInfo(); }
144};
145
151 public:
154 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
155 }
156
159 int pos = notify_vector.indexOf(&bi);
160 if (pos < 0) return false;
161 notify_vector.erase(pos);
162 return true;
163 }
164
166 virtual void clearNotifyAudioChange() { notify_vector.clear(); }
167
169 void setNotifyActive(bool flag) { is_notify_active = flag; }
170
172 bool isNotifyActive() { return is_notify_active; }
173
174 protected:
175 Vector<AudioInfoSupport*> notify_vector;
176 bool is_notify_active = true;
177
178 void notifyAudioChange(AudioInfo info) {
179 if (isNotifyActive()) {
180 for (auto n : notify_vector) {
181 n->setAudioInfo(info);
182 }
183 }
184 }
185};
186
192 public:
194 virtual float volume() { return volume_value; }
196 virtual bool setVolume(float volume) {
197 volume_value = volume;
198 return true;
199 }
200
201 protected:
202 float volume_value = 1.0f;
203};
204
210 public:
211 virtual size_t write(const uint8_t* data, size_t len) = 0;
212 virtual void setAudioInfo(AudioInfo from) = 0;
213 virtual void setOutput(Print& out_stream) = 0;
214 virtual operator bool() = 0;
215 virtual bool begin() = 0;
216 virtual bool begin(AudioInfo info) {
217 setAudioInfo(info);
218 return begin();
219 }
220 virtual void end() = 0;
221
222 protected:
223 void writeBlocking(Print* out, uint8_t* data, size_t len) {
224 TRACED();
225 int open = len;
226 int written = 0;
227 while (open > 0) {
228 int result = out->write(data + written, open);
229 open -= result;
230 written += result;
231 }
232 }
233};
234
240 public:
242 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit = 10) {
243 uint32_t result = 1000000l / samplingRate;
244 if (1000000l % samplingRate != 0) {
245 result++;
246 }
247 if (result <= limit) {
248 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
249 (unsigned int)samplingRate, (unsigned int)result,
250 (unsigned int)limit);
251 result = limit;
252 }
253 return result;
254 }
255
257 static uint32_t toBytes(uint32_t millis, AudioInfo info) {
258 size_t samples = info.sample_rate * millis / 1000;
259 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
260 return bytes;
261 }
262
263 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit = 1) {
264 uint32_t result = 1000l / samplingRate;
265 if (1000000l % samplingRate != 0) {
266 result++;
267 }
268 if (result <= limit) {
269 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
270 (unsigned int)samplingRate, (unsigned int)result,
271 (unsigned int)limit);
272 result = limit;
273 }
274 return result;
275 }
276
277 static float toRateUs(uint32_t time_us) { return 1000000.0 / time_us; }
278
279 static float toRateMs(uint32_t time_ms) { return 1000.0 / time_ms; }
280};
281
289template <typename T>
290inline T mapT(T x, T in_min, T in_max, T out_min, T out_max) {
291 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
292}
293
299 public:
301 static int64_t maxValue(int value_bits_per_sample) {
302 switch (value_bits_per_sample) {
303 case 8:
304 return 127;
305 case 16:
306 return 32767;
307 case 24:
308 return 8388607;
309 case 32:
310 return 2147483647;
311 }
312 return 32767;
313 }
314
316 template <typename T>
317 static float maxValueT() {
318#ifdef USE_TYPETRAITS
319 // int24_t uses 4 bytes instead of 3!
320 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
321 // maxValue(sizeof(T)*8);
322 return std::numeric_limits<T>::max();
323#else
324 return maxValue(sizeof(T) * 8);
325#endif
326 }
327
328 template <typename T>
329 static float minValueT() {
330#ifdef USE_TYPETRAITS
331 // int24_t uses 4 bytes instead of 3!
332 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
333 // maxValue(sizeof(T)*8);
334 return std::numeric_limits<T>::min();
335#else
336 return -maxValue(sizeof(T) * 8);
337#endif
338 }
339
341 template <typename T>
342 static T clipT(float value) {
343 float mv = maxValueT<T>();
344 if (value > mv) {
345 return mv;
346 } else if (value < -mv) {
347 return -mv;
348 }
349 return value;
350 }
351
353 inline static int32_t clip(float value, int bits) {
354 float mv = maxValue(bits);
355 if (value > mv) {
356 return mv;
357 } else if (value < -mv) {
358 return -mv;
359 }
360 return value;
361 }
362
364 template <typename T>
365 static float toFloatT(T value) {
366 return static_cast<float>(value) / maxValueT<T>();
367 }
368
370 template <typename T>
371 static T fromFloatT(float value) {
372 return value * maxValueT<T>();
373 }
374
376 inline static float toFloat(int32_t value, int bits) {
377 return static_cast<float>(value) / maxValue(bits);
378 }
379
381 inline static int32_t fromFloat(float value, int bits) {
382 return clip(value * maxValue(bits), bits);
383 }
384
386 template <typename FromT, typename ToT>
387 static ToT convert(FromT value) {
388 float value1 = value;
389 float minTo = minValueT<ToT>();
390 float maxTo = maxValueT<ToT>();
391 float maxFrom = maxValueT<FromT>();
392 float minFrom = minValueT<FromT>();
393
394 if (maxTo - minTo > 1.0f || maxFrom - minFrom > 1.0f) {
395 return mapT<float>(value1, minFrom, maxFrom, minTo, maxTo);
396 }
397
398 return value1 * maxValueT<ToT>() / maxValueT<FromT>();
399 }
400
402 template <typename FromT, typename ToT>
403 static void convertArray(FromT* from, ToT* to, int samples,
404 float vol = 1.0f) {
405 float factor = static_cast<float>(maxValueT<ToT>()) / maxValueT<FromT>();
406 float vol_factor = factor * vol;
407 for (int j = 0; j < samples; j++) {
408 to[j] = clipT<ToT>(vol_factor * convert<FromT, ToT>(from[j]));
409 }
410 }
411};
412
413#if defined(USE_I2S)
414
419 I2S_STD_FORMAT,
420 I2S_LSB_FORMAT,
421 I2S_MSB_FORMAT,
422 I2S_PHILIPS_FORMAT,
423 I2S_RIGHT_JUSTIFIED_FORMAT,
424 I2S_LEFT_JUSTIFIED_FORMAT,
425 I2S_PCM,
426};
427
428static const char* i2s_formats[] = {"I2S_STD_FORMAT",
429 "I2S_LSB_FORMAT",
430 "I2S_MSB_FORMAT",
431 "I2S_PHILIPS_FORMAT",
432 "I2S_RIGHT_JUSTIFIED_FORMAT",
433 "I2S_LEFT_JUSTIFIED_FORMAT",
434 "I2S_PCM"};
435
440 Digital,
441 Analog,
442 PDM,
443 TDM,
444};
445
446static const char* i2s_signal_types[] = {"Digital", "Analog", "PDM", "TDM"};
447
448#endif
449
451template <typename T>
452T readSample(Stream* p_stream) {
453 T result = 0;
454 uint8_t* p_result = (uint8_t*)&result;
455 int open = sizeof(T);
456 int total = 0;
457 // copy missing data
458 while (open > 0) {
459 int read = p_stream->readBytes(p_result + total, open);
460 open -= read;
461 total += read;
462 }
463 return result;
464}
465
467template <typename T>
468size_t readSamples(Stream* p_stream, T* data, int samples,
469 int retryCount = -1) {
470 uint8_t* p_result = (uint8_t*)data;
471 int open = samples * sizeof(T);
472 int total = 0;
473 int count0 = 0;
474 // copy missing data - we abort after 5 x read returned 0 bytes
475 while (open > 0) {
476 int read = p_stream->readBytes(p_result + total, open);
477 open -= read;
478 total += read;
479 if (read == 0) {
480 count0++;
481 delay(1);
482 } else {
483 count0 = 0;
484 }
485 // abort loop
486 if (retryCount >= 0 && count0 > retryCount) break;
487 }
488 // convert bytes to samples
489 return total / sizeof(T);
490}
491
493template <typename T, class P>
494size_t writeDataT(P* p_out, T* data, int samples, int maxSamples = 512) {
495 uint8_t* p_result = (uint8_t*)data;
496 int open = samples * sizeof(T);
497 int total = 0;
498 // copy missing data
499 while (open > 0) {
500 int to_write = min(open, static_cast<int>(maxSamples * sizeof(T)));
501 int written = p_out->write(p_result + total, to_write);
502 open -= written;
503 total += written;
504 }
505 // convert bytes to samples
506 return total / sizeof(T);
507}
508
509template <typename T>
510size_t writeData(Print* p_out, T* data, int samples, int maxSamples = 512) {
511 return writeDataT<T, Print>(p_out, data, samples, maxSamples);
512}
513
515static const char* mime_pcm = "audio/pcm";
516
517#ifndef IS_DESKTOP
519inline void waitFor(HardwareSerial& out) { while (!out); }
520#endif
521
523inline void waitFor(bool& flag) { while (!flag); }
524
528
529} // namespace audio_tools
Supports the subscription to audio change notifications.
Definition AudioTypes.h:150
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:172
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:153
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:169
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:158
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:166
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:135
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:143
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:239
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:257
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:242
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:209
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:298
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:365
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:371
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:403
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:376
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:342
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:381
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:301
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:387
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:353
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:317
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:191
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:194
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:196
MemoryType
Memory types.
Definition AudioTypes.h:37
uint32_t sample_rate_t
Type alias for sample rate values.
Definition AudioTypes.h:23
void waitFor(bool &flag)
wait for flag to be active
Definition AudioTypes.h:523
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
TimeUnit
Time Units.
Definition AudioTypes.h:48
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:439
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:468
static const char * mime_pcm
Mime type for PCM.
Definition AudioTypes.h:515
static const char * RxTxModeNames[4]
Text string (description) for RxTxMode.
Definition AudioTypes.h:42
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:290
I2SFormat
I2S Formats.
Definition AudioTypes.h:418
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:452
size_t writeDataT(P *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition AudioTypes.h:494
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:105
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:87
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
void set(AudioInfo info)
Copies the values from info.
Definition AudioTypes.h:95
AudioInfo(const AudioInfo &)=default
Copy constructor.
AudioInfo & operator=(const AudioInfo &info)
Same as set.
Definition AudioTypes.h:109
bool operator==(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:78
void setAudioInfo(AudioInfo info)
Same as set.
Definition AudioTypes.h:102
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:90
bool operator!=(AudioInfo alt)
Returns true if alt values are the different from the current values.
Definition AudioTypes.h:84
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
AudioInfo(sample_rate_t sampleRate, uint16_t channelCount, uint8_t bitsPerSample)
Constructor which supports all attribures as parameters.
Definition AudioTypes.h:67
AudioInfo()=default
Default constructor.