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 <= 192000 && channels > 0 &&
113 channels < 20 && bits_per_sample > 0 && bits_per_sample <= 64;
114 }
115
116 virtual void clear() {
117 sample_rate = 0;
118 channels = 0;
119 bits_per_sample = 0;
120 }
121
122 virtual void logInfo(const char* source = "") {
123 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d", source,
124 (int)sample_rate, (int)channels, (int)bits_per_sample);
125 }
126};
127
133 public:
135 virtual void setAudioInfo(AudioInfo info) = 0;
137 virtual AudioInfo audioInfo() = 0;
140 virtual AudioInfo audioInfoOut() { return audioInfo(); }
141};
142
148 public:
151 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
152 }
153
156 int pos = notify_vector.indexOf(&bi);
157 if (pos < 0) return false;
158 notify_vector.erase(pos);
159 return true;
160 }
161
163 virtual void clearNotifyAudioChange() { notify_vector.clear(); }
164
166 void setNotifyActive(bool flag) { is_notify_active = flag; }
167
170
171 protected:
173 bool is_notify_active = true;
174
176 if (isNotifyActive()) {
177 for (auto n : notify_vector) {
178 n->setAudioInfo(info);
179 }
180 }
181 }
182};
183
189 public:
191 virtual float volume() { return volume_value; }
193 virtual bool setVolume(float volume) {
195 return true;
196 }
197
198 protected:
199 float volume_value = 1.0f;
200};
201
207 public:
208 virtual size_t write(const uint8_t* data, size_t len) = 0;
209 virtual void setAudioInfo(AudioInfo from) = 0;
210 virtual void setOutput(Print& out_stream) = 0;
211 virtual operator bool() = 0;
212 virtual bool begin() = 0;
213 virtual bool begin(AudioInfo info) {
214 setAudioInfo(info);
215 return begin();
216 }
217 virtual void end() = 0;
218
219 protected:
220 void writeBlocking(Print* out, uint8_t* data, size_t len) {
221 TRACED();
222 int open = len;
223 int written = 0;
224 while (open > 0) {
225 int result = out->write(data + written, open);
226 open -= result;
227 written += result;
228 }
229 }
230};
231
237 public:
239 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit = 10) {
240 uint32_t result = 1000000l / samplingRate;
241 if (1000000l % samplingRate != 0) {
242 result++;
243 }
244 if (result <= limit) {
245 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
246 (unsigned int)samplingRate, (unsigned int)result,
247 (unsigned int)limit);
248 result = limit;
249 }
250 return result;
251 }
252
254 static uint32_t toBytes(uint32_t millis, AudioInfo info) {
255 size_t samples = info.sample_rate * millis / 1000;
256 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
257 return bytes;
258 }
259
260 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit = 1) {
261 uint32_t result = 1000l / samplingRate;
262 if (1000000l % samplingRate != 0) {
263 result++;
264 }
265 if (result <= limit) {
266 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up",
267 (unsigned int)samplingRate, (unsigned int)result,
268 (unsigned int)limit);
269 result = limit;
270 }
271 return result;
272 }
273
274 static float toRateUs(uint32_t time_us) { return 1000000.0 / time_us; }
275
276 static float toRateMs(uint32_t time_ms) { return 1000.0 / time_ms; }
277};
278
286template <typename T>
287inline T mapT(T x, T in_min, T in_max, T out_min, T out_max) {
288 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
289}
290
296 public:
298 static int64_t maxValue(int value_bits_per_sample) {
299 switch (value_bits_per_sample) {
300 case 8:
301 return 127;
302 case 16:
303 return 32767;
304 case 24:
305 return 8388607;
306 case 32:
307 return 2147483647;
308 }
309 return 32767;
310 }
311
313 template <typename T>
314 static float maxValueT() {
315#ifdef USE_TYPETRAITS
316 // int24_t uses 4 bytes instead of 3!
317 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
318 // maxValue(sizeof(T)*8);
319 return std::numeric_limits<T>::max();
320#else
321 return maxValue(sizeof(T) * 8);
322#endif
323 }
324
325 template <typename T>
326 static float minValueT() {
327#ifdef USE_TYPETRAITS
328 // int24_t uses 4 bytes instead of 3!
329 // return (std::is_same<T, int24_t>::value ) ? 8388607 :
330 // maxValue(sizeof(T)*8);
331 return std::numeric_limits<T>::min();
332#else
333 return -maxValue(sizeof(T) * 8);
334#endif
335 }
336
338 template <typename T>
339 static T clipT(float value) {
340 float mv = maxValueT<T>();
341 if (value > mv) {
342 return mv;
343 } else if (value < -mv) {
344 return -mv;
345 }
346 return value;
347 }
348
350 inline static int32_t clip(float value, int bits) {
351 float mv = maxValue(bits);
352 if (value > mv) {
353 return mv;
354 } else if (value < -mv) {
355 return -mv;
356 }
357 return value;
358 }
359
361 template <typename T>
362 static float toFloatT(T value) {
363 return static_cast<float>(value) / maxValueT<T>();
364 }
365
367 template <typename T>
368 static T fromFloatT(float value) {
369 return value * maxValueT<T>();
370 }
371
373 inline static float toFloat(int32_t value, int bits) {
374 return static_cast<float>(value) / maxValue(bits);
375 }
376
378 inline static int32_t fromFloat(float value, int bits) {
379 return clip(value * maxValue(bits), bits);
380 }
381
383 template <typename FromT, typename ToT>
384 static ToT convert(FromT value) {
385 float value1 = value;
386 float minTo = minValueT<ToT>();
387 float maxTo = maxValueT<ToT>();
388 float maxFrom = maxValueT<FromT>();
389 float minFrom = minValueT<FromT>();
390
391 if (maxTo - minTo > 1.0f || maxFrom - minFrom > 1.0f) {
392 return mapT<float>(value1, minFrom, maxFrom, minTo, maxTo);
393 }
394
395 return value1 * maxValueT<ToT>() / maxValueT<FromT>();
396 }
397
399 template <typename FromT, typename ToT>
400 static void convertArray(FromT* from, ToT* to, int samples,
401 float vol = 1.0f) {
402 // convert() already maps FromT range to ToT range. Apply only the gain
403 // and clip to the valid ToT range to avoid double scaling.
404 for (int j = 0; j < samples; j++) {
405 ToT mapped = convert<FromT, ToT>(from[j]);
406 float scaled = static_cast<float>(mapped) * vol;
407 to[j] = clipT<ToT>(scaled);
408 }
409 }
410};
411
412#if defined(USE_I2S)
413
426
427static const char* i2s_formats[] = {"I2S_STD_FORMAT",
428 "I2S_LSB_FORMAT",
429 "I2S_MSB_FORMAT",
430 "I2S_PHILIPS_FORMAT",
431 "I2S_RIGHT_JUSTIFIED_FORMAT",
432 "I2S_LEFT_JUSTIFIED_FORMAT",
433 "I2S_PCM"};
434
444
445static const char* i2s_signal_types[] = {"Digital", "Analog", "PDM", "TDM"};
446
447#endif
448
450template <typename T>
451T readSample(Stream* p_stream) {
452 T result = 0;
453 uint8_t* p_result = (uint8_t*)&result;
454 int open = sizeof(T);
455 int total = 0;
456 // copy missing data
457 while (open > 0) {
458 int read = p_stream->readBytes(p_result + total, open);
459 open -= read;
460 total += read;
461 }
462 return result;
463}
464
466template <typename T>
467size_t readSamples(Stream* p_stream, T* data, int samples,
468 int retryCount = -1) {
469 uint8_t* p_result = (uint8_t*)data;
470 int open = samples * sizeof(T);
471 int total = 0;
472 int count0 = 0;
473 // copy missing data - we abort after 5 x read returned 0 bytes
474 while (open > 0) {
475 int read = p_stream->readBytes(p_result + total, open);
476 open -= read;
477 total += read;
478 if (read == 0) {
479 count0++;
480 delay(1);
481 } else {
482 count0 = 0;
483 }
484 // abort loop
485 if (retryCount >= 0 && count0 > retryCount) break;
486 }
487 // convert bytes to samples
488 return total / sizeof(T);
489}
490
492template <typename T, class P>
493size_t writeDataT(P* p_out, T* data, int samples, int maxSamples = 512) {
494 uint8_t* p_result = (uint8_t*)data;
495 int open = samples * sizeof(T);
496 int total = 0;
497 // copy missing data
498 while (open > 0) {
499 int to_write = min(open, static_cast<int>(maxSamples * sizeof(T)));
500 int written = p_out->write(p_result + total, to_write);
501 open -= written;
502 total += written;
503 }
504 // convert bytes to samples
505 return total / sizeof(T);
506}
507
508template <typename T>
509size_t writeData(Print* p_out, T* data, int samples, int maxSamples = 512) {
510 return writeDataT<T, Print>(p_out, data, samples, maxSamples);
511}
512
514static const char* mime_pcm = "audio/pcm";
515
516#ifndef IS_DESKTOP
518inline void waitFor(HardwareSerial& out) { while (!out); }
519#endif
520
522inline void waitFor(bool& flag) { while (!flag); }
523
527
548 public:
562 virtual const char* mime() = 0;
563};
564
581 public:
587 virtual uint32_t millis() { return ::millis(); }
588
598 virtual uint32_t playbackTime() { return millis(); }
599};
600
601} // 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:147
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:169
void notifyAudioChange(AudioInfo info)
Definition AudioTypes.h:175
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:150
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:166
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:155
Vector< AudioInfoSupport * > notify_vector
Definition AudioTypes.h:172
bool is_notify_active
Definition AudioTypes.h:173
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:163
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:132
virtual AudioInfo audioInfoOut()
Definition AudioTypes.h:140
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:236
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:254
static float toRateUs(uint32_t time_us)
Definition AudioTypes.h:274
static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit=1)
Definition AudioTypes.h:260
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:239
static float toRateMs(uint32_t time_ms)
Definition AudioTypes.h:276
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:206
void writeBlocking(Print *out, uint8_t *data, size_t len)
Definition AudioTypes.h:220
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
virtual bool begin(AudioInfo info)
Definition AudioTypes.h:213
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:547
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:295
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:362
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:368
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:400
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:373
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:339
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:378
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:298
static float minValueT()
Definition AudioTypes.h:326
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:384
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:350
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:314
Interface for classes that can provide time information - two distinct notions of "now",...
Definition AudioTypes.h:580
virtual uint32_t playbackTime()
Definition AudioTypes.h:598
virtual uint32_t millis()
Definition AudioTypes.h:587
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:188
float volume_value
Definition AudioTypes.h:199
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:191
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:193
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:522
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:445
I2SSignalType
I2S Signal Types: Digital, Analog, PDM.
Definition AudioTypes.h:438
@ Digital
Definition AudioTypes.h:439
@ PDM
Definition AudioTypes.h:441
@ TDM
Definition AudioTypes.h:442
@ Analog
Definition AudioTypes.h:440
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:467
static const char * mime_pcm
Mime type for PCM.
Definition AudioTypes.h:514
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:287
I2SFormat
I2S Formats.
Definition AudioTypes.h:417
@ I2S_STD_FORMAT
Definition AudioTypes.h:418
@ I2S_PHILIPS_FORMAT
Definition AudioTypes.h:421
@ I2S_LSB_FORMAT
Definition AudioTypes.h:419
@ I2S_LEFT_JUSTIFIED_FORMAT
Definition AudioTypes.h:423
@ I2S_RIGHT_JUSTIFIED_FORMAT
Definition AudioTypes.h:422
@ I2S_MSB_FORMAT
Definition AudioTypes.h:420
@ I2S_PCM
Definition AudioTypes.h:424
void delay(uint32_t ms)
Definition Arduino.h:259
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:451
static const char * i2s_formats[]
Definition AudioTypes.h:427
size_t writeDataT(P *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition AudioTypes.h:493
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:509
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:116
virtual void logInfo(const char *source="")
Definition AudioTypes.h:122
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.