arduino-audio-tools
Loading...
Searching...
No Matches
AudioTypes.h
1#pragma once
2
3#include "AudioConfig.h"
4#ifdef USE_TYPETRAITS
5# include <type_traits>
6# include <limits>
7#endif
8
9#include "AudioTools/CoreAudio/AudioLogger.h"
10#include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.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
19
20namespace audio_tools {
21
22using sample_rate_t = uint32_t;
23
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","RXTX_MODE" };
45enum TimeUnit {MS, US, HZ};
46static const char* TimeUnitStr[3] {"MS","US","HZ"};
47
52struct AudioInfo {
53
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, uint8_t bitsPerSample) {
66 sample_rate = sampleRate;
68 bits_per_sample = bitsPerSample;
69 };
70
72 AudioInfo(const AudioInfo &) = default;
73
76 return sample_rate==alt.sample_rate && channels == alt.channels && bits_per_sample == alt.bits_per_sample;
77 }
78
81 return !(*this == alt);
82 }
83
86 return *this == alt;
87 }
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
103 set(info);
104 }
105
107 void copyFrom(AudioInfo info){
108 setAudioInfo(info);
109 }
110
111#ifndef SWIG
114 setAudioInfo(info);
115 return *this;
116 }
117#endif
119 operator bool() {
120 return sample_rate > 0 && channels > 0 && bits_per_sample > 0;
121 }
122
123 virtual void clear(){
124 sample_rate = 0;
125 channels = 0;
126 bits_per_sample = 0;
127 }
128
129 virtual void logInfo(const char* source="") {
130 LOGI("%s sample_rate: %d / channels: %d / bits_per_sample: %d",source, (int) sample_rate, (int)channels, (int)bits_per_sample);
131 }
132
133};
134
140 public:
142 virtual void setAudioInfo(AudioInfo info) = 0;
144 virtual AudioInfo audioInfo() = 0;
146 virtual AudioInfo audioInfoOut() { return audioInfo();}
147};
148// Support legacy name
149#if USE_OBSOLETE
150using AudioBaseInfo = AudioInfo;
151using AudioBaseInfoDependent = AudioInfoSupport;
152using AudioInfoDependent = AudioInfoSupport;
153#endif
154
160 public:
163 if (!notify_vector.contains(&bi)) notify_vector.push_back(&bi);
164 }
165
168 int pos = notify_vector.indexOf(&bi);
169 if (pos<0) return false;
170 notify_vector.erase(pos);
171 return true;
172 }
173
175 virtual void clearNotifyAudioChange() {
176 notify_vector.clear();
177 }
178
181 is_notify_active = flag;
182 }
183
186 return is_notify_active;
187 }
188
189 protected:
190 Vector<AudioInfoSupport*> notify_vector;
191 bool is_notify_active = true;
192
193 void notifyAudioChange(AudioInfo info){
194 if (isNotifyActive()){
195 for(auto n : notify_vector){
196 n->setAudioInfo(info);
197 }
198 }
199 }
200
201};
202
208 public:
210 virtual float volume() { return volume_value; }
212 virtual bool setVolume(float volume) {
213 volume_value = volume;
214 return true;
215 }
216 protected:
217 float volume_value = 1.0f;
218};
219
225 public:
226 virtual size_t write(const uint8_t *data, size_t len) = 0;
227 virtual void setAudioInfo(AudioInfo from) = 0;
228 virtual void setOutput(Print &out_stream) = 0;
229 virtual operator bool() = 0;
230 virtual bool begin() = 0;
231 virtual bool begin(AudioInfo info) {
232 setAudioInfo(info);
233 return begin();
234 }
235 virtual void end() = 0;
236 protected:
237 void writeBlocking(Print *out, uint8_t* data, size_t len){
238 TRACED();
239 int open = len;
240 int written = 0;
241 while(open>0){
242 int result = out->write(data+written, open);
243 open -= result;
244 written += result;
245 }
246 }
247};
248
254 public:
256 static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10){
257 uint32_t result = 1000000l / samplingRate;
258 if (1000000l % samplingRate!=0){
259 result++;
260 }
261 if (result <= limit){
262 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up", (unsigned int)samplingRate, (unsigned int)result, (unsigned int)limit);
263 result = limit;
264 }
265 return result;
266 }
267
270 size_t samples = info.sample_rate * millis / 1000;
271 size_t bytes = samples * info.channels * info.bits_per_sample / 8;
272 return bytes;
273 }
274
275 static uint32_t toTimeMs(uint32_t samplingRate, uint8_t limit=1){
276 uint32_t result = 1000l / samplingRate;
277 if (1000000l % samplingRate!=0){
278 result++;
279 }
280 if (result <= limit){
281 LOGW("Time for samplingRate %u -> %u is < %u μs - we rounded up", (unsigned int)samplingRate, (unsigned int)result, (unsigned int)limit);
282 result = limit;
283 }
284 return result;
285 }
286
287 static float toRateUs(uint32_t time_us){
288 return 1000000.0 / time_us;
289 }
290
291 static float toRateMs(uint32_t time_ms){
292 return 1000.0 / time_ms;
293 }
294};
295
303template <typename T>
305 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
306}
307
308
309
315 public:
318 switch(value_bits_per_sample){
319 case 8:
320 return 127;
321 case 16:
322 return 32767;
323 case 24:
324 return 8388607;
325 case 32:
326 return 2147483647;
327 }
328 return 32767;
329 }
330
332 template <typename T>
333 static float maxValueT(){
334#ifdef USE_TYPETRAITS
335 // int24_t uses 4 bytes instead of 3!
336 //return (std::is_same<T, int24_t>::value ) ? 8388607 : maxValue(sizeof(T)*8);
337 return std::numeric_limits<T>::max();
338#else
339 return maxValue(sizeof(T)*8);
340#endif
341 }
342
343 template <typename T>
344 static float minValueT(){
345#ifdef USE_TYPETRAITS
346 // int24_t uses 4 bytes instead of 3!
347 //return (std::is_same<T, int24_t>::value ) ? 8388607 : maxValue(sizeof(T)*8);
348 return std::numeric_limits<T>::min();
349#else
350 return -maxValue(sizeof(T)*8);
351#endif
352 }
353
354
355
357 template <typename T>
358 static T clipT(float value){
359 float mv = maxValueT<T>();
360 if (value > mv){
361 return mv;
362 } else if (value < -mv){
363 return -mv;
364 }
365 return value;
366 }
367
369 inline static int32_t clip(float value, int bits){
370 float mv = maxValue(bits);
371 if (value > mv){
372 return mv;
373 } else if (value < -mv){
374 return -mv;
375 }
376 return value;
377 }
378
380 template <typename T>
381 static float toFloatT(T value) {
382 return static_cast<float>(value) / maxValueT<T>();
383 }
384
386 template <typename T>
387 static T fromFloatT(float value){
388 return value * maxValueT<T>();
389 }
390
392 inline static float toFloat(int32_t value, int bits) {
393 return static_cast<float>(value) / maxValue(bits);
394 }
395
397 inline static int32_t fromFloat(float value, int bits){
398 return clip(value * maxValue(bits), bits);
399 }
400
402 template <typename FromT, typename ToT>
403 static ToT convert(FromT value){
404 float value1 = value;
405 float minTo = minValueT<ToT>();
406 float maxTo = maxValueT<ToT>();
407 float maxFrom = maxValueT<FromT>();
408 float minFrom = minValueT<FromT>();
409
410 if (maxTo - minTo > 1.0f
411 || maxFrom - minFrom > 1.0f) {
413 }
414
415
417 }
418
420 template <typename FromT, typename ToT>
421 static void convertArray(FromT* from, ToT*to, int samples, float vol=1.0f){
422 float factor = static_cast<float>(maxValueT<ToT>()) / maxValueT<FromT>();
423 float vol_factor = factor * vol;
424 for (int j=0;j<samples;j++){
425 to[j] = clipT<ToT>(vol * convert<FromT, ToT>(from[j]));
426 }
427 }
428
429};
430
431#if defined(USE_I2S)
432
437 I2S_STD_FORMAT,
438 I2S_LSB_FORMAT,
439 I2S_MSB_FORMAT,
440 I2S_PHILIPS_FORMAT,
441 I2S_RIGHT_JUSTIFIED_FORMAT,
442 I2S_LEFT_JUSTIFIED_FORMAT,
443 I2S_PCM,
444};
445
446static const char* i2s_formats[] = {"I2S_STD_FORMAT","I2S_LSB_FORMAT","I2S_MSB_FORMAT","I2S_PHILIPS_FORMAT","I2S_RIGHT_JUSTIFIED_FORMAT","I2S_LEFT_JUSTIFIED_FORMAT","I2S_PCM"};
447
452 Digital,
453 Analog,
454 PDM,
455 TDM,
456};
457
458static const char* i2s_signal_types[] = {"Digital","Analog","PDM","TDM"};
459
460#endif
461
463template<typename T>
464T readSample(Stream* p_stream){
465 T result=0;
466 uint8_t *p_result = (uint8_t*) &result;
467 int open = sizeof(T);
468 int total = 0;
469 // copy missing data
470 while (open>0){
471 int read = p_stream->readBytes(p_result+total, open);
472 open -= read;
473 total += read;
474 }
475 return result;
476}
477
479template<typename T>
480size_t readSamples(Stream* p_stream, T* data, int samples, int retryCount=-1){
481 uint8_t *p_result = (uint8_t*) data;
482 int open = samples*sizeof(T);
483 int total = 0;
484 int count0 = 0;
485 // copy missing data - we abort after 5 x read returned 0 bytes
486 while (open > 0){
487 int read = p_stream->readBytes(p_result+total, open);
488 open -= read;
489 total += read;
490 if (read == 0){
491 count0++;
492 delay(1);
493 } else {
494 count0 = 0;
495 }
496 // abort loop
497 if (retryCount >= 0 && count0 > retryCount)
498 break;
499 }
500 // convert bytes to samples
501 return total / sizeof(T);
502}
503
505template<typename T>
506size_t writeSamples(Print* p_out, T* data, int samples, int maxSamples=512){
507 uint8_t *p_result = (uint8_t*) data;
508 int open = samples*sizeof(T);
509 int total = 0;
510 // copy missing data
511 while (open>0){
512 int to_write = min(open, static_cast<int>(maxSamples*sizeof(T)));
513 int written = p_out->write(p_result+total, to_write );
514 open -= written;
515 total += written;
516 }
517 // convert bytes to samples
518 return total / sizeof(T);
519}
520
521
523static const char* mime_pcm = "audio/pcm";
524
525
526#ifndef IS_DESKTOP
528inline void waitFor(HardwareSerial &out){
529 while(!out);
530}
531#endif
532
534inline void waitFor(bool &flag){
535 while(!flag);
536}
537
540
541
542}
Supports the subscription to audio change notifications.
Definition AudioTypes.h:159
bool isNotifyActive()
Checks if the automatic AudioInfo update is active.
Definition AudioTypes.h:185
virtual void addNotifyAudioChange(AudioInfoSupport &bi)
Adds target to be notified about audio changes.
Definition AudioTypes.h:162
void setNotifyActive(bool flag)
Deactivate/Reactivate automatic AudioInfo updates: (default is active)
Definition AudioTypes.h:180
virtual bool removeNotifyAudioChange(AudioInfoSupport &bi)
Removes a target in order not to be notified about audio changes.
Definition AudioTypes.h:167
virtual void clearNotifyAudioChange()
Deletes all change notify subscriptions.
Definition AudioTypes.h:175
Supports changes to the sampling rate, bits and channels.
Definition AudioTypes.h:139
virtual AudioInfo audioInfoOut()
provides the actual output AudioInfo: this is usually the same as audioInfo() unless we use a transfo...
Definition AudioTypes.h:146
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:253
static uint32_t toBytes(uint32_t millis, AudioInfo info)
converts milliseconds to bytes
Definition AudioTypes.h:269
static uint32_t toTimeUs(uint32_t samplingRate, uint8_t limit=10)
converts sampling rate to delay in microseconds (μs)
Definition AudioTypes.h:256
E.g. used by Encoders and Decoders.
Definition AudioTypes.h:224
virtual void setAudioInfo(AudioInfo from)=0
Defines the input AudioInfo.
Definition NoArduino.h:149
Converts from a source to a target number with a different type.
Definition AudioTypes.h:314
static float toFloatT(T value)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:381
static T fromFloatT(float value)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:387
static void convertArray(FromT *from, ToT *to, int samples, float vol=1.0f)
Convert an array of int types.
Definition AudioTypes.h:421
static float toFloat(int32_t value, int bits)
Convert an integer integer autio type to a float (with max 1.0)
Definition AudioTypes.h:392
static T clipT(float value)
Clips the value to avoid any over or underflows.
Definition AudioTypes.h:358
static int32_t fromFloat(float value, int bits)
Convert a float (with max 1.0) to an integer autio type.
Definition AudioTypes.h:397
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:317
static ToT convert(FromT value)
Convert an int number from one type to another.
Definition AudioTypes.h:403
static int32_t clip(float value, int bits)
clips a value
Definition AudioTypes.h:369
static float maxValueT()
provides the biggest number for the indicated type
Definition AudioTypes.h:333
Definition NoArduino.h:58
Definition NoArduino.h:125
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:207
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:210
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:212
MemoryType
Memory types.
Definition AudioTypes.h:35
void waitFor(bool &flag)
wait for flag to be active
Definition AudioTypes.h:534
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:45
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioConfig.h:877
I2SSignalType
I2S Signal Types: Digital, Analog, PDM.
Definition AudioTypes.h:451
size_t readSamples(Stream *p_stream, T *data, int samples, int retryCount=-1)
guaranteed to return the requested data
Definition AudioTypes.h:480
static const char * mime_pcm
Mime type for PCM.
Definition AudioTypes.h:523
size_t writeSamples(Print *p_out, T *data, int samples, int maxSamples=512)
guaranteed to return the requested data
Definition AudioTypes.h:506
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:304
I2SFormat
I2S Formats.
Definition AudioTypes.h:436
T readSample(Stream *p_stream)
guaranteed to return the requested data
Definition AudioTypes.h:464
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:52
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:107
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:95
AudioInfo(const AudioInfo &)=default
Copy constructor.
AudioInfo & operator=(const AudioInfo &info)
Same as set.
Definition AudioTypes.h:113
bool operator==(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:75
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:80
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.