arduino-audio-tools
Loading...
Searching...
No Matches
SoundGenerator.h
Go to the documentation of this file.
1#pragma once
2
3#include <math.h>
4
10
11
18namespace audio_tools {
19
29template <class T = int16_t>
31 public:
32 SoundGenerator() { info.bits_per_sample = sizeof(T) * 8; }
33
34 virtual ~SoundGenerator() { end(); }
35
37 virtual bool begin(AudioInfo info) {
38 this->info = info;
39 return begin();
40 }
41
43 virtual bool begin() {
44 TRACED();
45 active = true;
46 activeWarningIssued = false;
47 info.logInfo("SoundGenerator:");
48
49 // support bytes < framesize
50 ring_buffer.resize(info.channels * sizeof(T));
51
52 return true;
53 }
54
55 virtual void end() { end(false); }
56
59 virtual void end(bool allow_rampdown) {
60 if (!active || !allow_rampdown || downSamples == 0) {
61 // No rampdown to do
62 LOGD("end() immediate");
63 active = false;
64 }
65 // Are we already in a rampdown? If so, don't restart it.
67 LOGD("end() continuing rampdown: %u more samples", playSamples+downSamples-currentSample);
68 }
69 // Otherwise, trigger the start of ramp down.
70 else {
71 LOGD("end() starting rampdown: %u samples", downSamples);
73 }
74 }
75
77 virtual bool isActive() { return active; }
78
80 virtual T readSample() = 0;
81
83 virtual size_t readBytes(uint8_t* data, size_t len) {
84 LOGD("readBytes: %d", (int)len);
85 if (!active) return 0;
86 int channels = audioInfo().channels;
87 int frame_size = sizeof(T) * channels;
88 int frames = len / frame_size;
89 if (len >= frame_size) {
90 return readBytesFrames(data, len, frames, channels);
91 }
92 return readBytesFromBuffer(data, len, frame_size, channels);
93 }
94
97 virtual size_t readSamples(T* data, size_t len) {
98 if (!active) return 0;
99 int channels = audioInfo().channels;
100 int frames = len / channels;
101 if (frames == 0) return 0;
102 return readBytesFrames((uint8_t*)data, frames * sizeof(T) * channels,
103 frames, channels) /
104 sizeof(T);
105 }
106
109 AudioInfo def;
110 def.bits_per_sample = sizeof(T) * 8;
111 return def;
112 }
113
115 virtual void setFrequency(float frequency) {
116 LOGE("setFrequency not supported");
117 }
118
120 virtual AudioInfo audioInfo() { return info; }
121
124 this->info = info;
125 if (info.bits_per_sample != sizeof(T) * 8) {
126 LOGE("invalid bits_per_sample: %d", info.channels);
127 }
129 }
130
132 virtual void setPlayTime(uint32_t playMs, uint8_t upPercent = 20,
133 uint8_t downPercent = 30) {
134 LOGI("setPlayTime: playMs=%d, upPercent=%d, downPercent=%d", playMs,
136 this->playMs = playMs;
137 this->upPercent = upPercent;
138 this->downPercent = downPercent;
139 this->upMs = 0;
140 this->downMs = 0;
141 currentSample = 0;
143 factor = 0.0f;
144 }
145
150 virtual void setRampTimes(uint32_t playMs, uint32_t upMs = 5, uint32_t downMs = 5) {
151 LOGI("setRampTimes: playMs=%u upMs=%u, downMs=%u", playMs, upMs, downMs);
152
153 this->playMs = playMs;
154 this->upMs = upMs;
155 this->downMs = downMs;
156 this->upPercent = 0;
157 this->downPercent = 0;
158
159 currentSample = 0;
161 factor = 0.0f;
162 LOGD("setRampTimes() playSamples: %u playMs: %u upSamples: %u downSamples: %u", playSamples, playMs, upSamples, downSamples);
163 }
164
165
167 virtual void restart() {
168 currentSample = 0;
169 active = true;
170 }
171
172 protected:
173 bool active = false;
175 // int output_channels = 1;
178 uint32_t playMs = 0;
179 uint8_t upPercent = 5;
180 uint8_t downPercent = 40;
181 uint32_t upMs = 0;
182 uint32_t downMs = 0;
183 uint32_t playSamples = 0;
184 uint32_t upSamples = 0;
185 uint32_t downSamples = 0;
186 float rampUpInc = 0.0;
187 float rampDownDec = 0.0;
188 float factor = 1.0f;
189 uint32_t currentSample = 0;
190
192 // Enforce exclusion between setPlayTime() and setRampTimes()
193 if ((upPercent || downPercent) && (upMs || downMs)) {
194 LOGE("Only use either: setPlayTime() or setRampTimes(), not both. up%% %u down%% %u upMs: %u downMs: %u",
196 LOGE("Reset the other to zero if switching back and forth.")
197 return;
198 }
199
200 // Set playSamples. playMs == 0 results in playSamples == 0 will play
201 // indefinitely, until end() is called. end(true) will ramp-down,
202 // end(false) stops immediately. Default is false/immediate.
204
205 // Set up/down samples based on either Percentages or times.
206 if (upMs || downMs) {
207 // Using ramp time in ms
208 upSamples = info.sample_rate / 1000 * upMs;
210 }
211 else if (upPercent || downPercent) {
212 // Using ramp percentages of play time
213 if (upPercent + downPercent > 100) {
214 downPercent = 100 - upPercent;
215 }
216 upSamples = (playSamples * upPercent) / 100;
218 }
219 else {
220 // No ramp specified.
221 upSamples = 0;
222 downSamples = 0;
223 }
224
225 // Turn all that into parameters to use in applyRamp()
226 rampUpInc = 0;
227 if (upSamples > 0) {
228 rampUpInc = 1.0f / upSamples;
229 }
230 rampDownDec = 0;
231 if (downSamples > 0) {
232 rampDownDec = 1.0f / downSamples;
233 }
234 }
235
236 size_t readBytesFrames(uint8_t* buffer, size_t lengthBytes, int frames,
237 int channels) {
238 T* result_buffer = (T*)buffer;
239 int frames_written = 0;
241 active = false;
242 return 0;
243 }
244
245 for (int j = 0; j < frames; j++) {
246 T sample = readSample();
247
248 // if we requested a play time or ramp times
249 if (playSamples > 0 || upSamples > 0 || downSamples > 0) {
251 sample = applyRamp(sample);
252 }
253
254 for (int ch = 0; ch < channels; ch++) {
255 *result_buffer++ = sample;
256 }
257
258 frames_written++;
259 // exit loop if we have reached the requested play time
261 active = false;
262 break;
263 }
264 }
265 return frames_written * sizeof(T) * channels;
266 }
267
268 // Applies ramp up and ramp down logic to the sample
269 T applyRamp(T sample) {
270 // Ramp up
271 if (rampUpInc > 0 && currentSample <= upSamples) {
272 factor += rampUpInc;
273 if (factor > 1.0f) {
274 factor = 1.0f;
275 }
276 }
277 // Ramp down
278 else if (rampDownDec > 0 && currentSample >= playSamples - downSamples) {
280 if (factor < 0.0f) {
281 factor = 0.0f;
282 }
283 }
284 // Sustain
285 else {
286 factor = 1.0f;
287 }
288 return (T)(factor * sample);
289 }
290
291 size_t readBytesFromBuffer(uint8_t* buffer, size_t lengthBytes,
292 int frame_size, int channels) {
293 // fill ringbuffer with one frame
294 if (ring_buffer.isEmpty()) {
295 uint8_t tmp[frame_size];
296 readBytesFrames(tmp, frame_size, 1, channels);
297 ring_buffer.writeArray(tmp, frame_size);
298 }
299 // provide result
300 return ring_buffer.readArray(buffer, lengthBytes);
301 }
302};
303
316template <class T = int16_t>
318 public:
319 // the scale defines the max value which is generated
320 FloatSineGenerator(float amplitude = NumberConverter::maxValueT<T>(),
321 float phase = 0.0f) {
322 LOGD("FloatSineGenerator");
323 m_amplitude = amplitude;
324 m_phase = phase;
325 }
326
327 bool begin() override {
328 TRACEI();
330 this->m_deltaTime = 1.0f / SoundGenerator<T>::info.sample_rate;
331 return true;
332 }
333
334 bool begin(AudioInfo info) override {
335 LOGI("%s::begin(channels=%d, sample_rate=%d)", "FloatSineGenerator",
336 (int)info.channels, (int)info.sample_rate);
338 this->m_deltaTime = 1.0f / SoundGenerator<T>::info.sample_rate;
339 return true;
340 }
341
342 bool begin(AudioInfo info, float frequency) {
343 LOGI("%s::begin(channels=%d, sample_rate=%d, frequency=%.2f)",
344 "FloatSineGenerator", (int)info.channels, (int)info.sample_rate,
345 frequency);
347 this->m_deltaTime = 1.0f / SoundGenerator<T>::info.sample_rate;
348 if (frequency > 0.0f) {
349 setFrequency(frequency);
350 }
351 return true;
352 }
353
354 bool begin(int channels, int sample_rate, float frequency) {
355 SoundGenerator<T>::info.channels = channels;
356 SoundGenerator<T>::info.sample_rate = sample_rate;
357 return begin(SoundGenerator<T>::info, frequency);
358 }
359
360 // update m_deltaTime
361 virtual void setAudioInfo(AudioInfo info) override {
363 this->m_deltaTime = 1.0f / SoundGenerator<T>::info.sample_rate;
364 }
365
366 virtual AudioInfo defaultConfig() override {
368 }
369
371 void setFrequency(float frequency) override {
372 LOGI("setFrequency: %.2f", frequency);
373 LOGI("active: %s", SoundGenerator<T>::active ? "true" : "false");
374 if (m_frequency != frequency) {
375 m_cycles = 0.0f; // reset cycles to avoid phase jumps
376 m_phase = 0.0f; // reset phase to avoid jumps
377 }
378 m_frequency = frequency;
379 }
380
382 virtual T readSample() override {
383 float angle = double_Pi * m_cycles + m_phase;
384 T result = m_amplitude * sinf(angle);
386 if (m_cycles > 1.0f) {
387 m_cycles -= 1.0f;
388 }
389 return result;
390 }
391
392 void setAmplitude(float amp) { m_amplitude = amp; }
393
394 protected:
395 volatile float m_frequency = 0.0f;
396 float m_cycles = 0.0f; // Varies between 0.0 and 1.0
397 float m_amplitude = 1.0f;
398 float m_deltaTime = 0.0f;
399 float m_phase = 0.0f;
400 const float double_Pi = 2.0f * PI;
401
402 void logStatus() {
403 SoundGenerator<T>::info.logStatus();
404 LOGI("amplitude: %f", this->m_amplitude);
405 LOGI("active: %s", SoundGenerator<T>::active ? "true" : "false");
406 }
407};
408
416template <class T = int16_t>
418 public:
419 FastSineGenerator(float amplitude = NumberConverter::maxValueT<T>(), float phase = 0.0)
420 : FloatSineGenerator<T>(amplitude, phase) {
421 LOGD("FastSineGenerator");
422 }
423
435
436 protected:
438 inline float sine(float t) {
439 float p = (t - (int)t) - 0.5f; // 0 <= p <= 1
440 float pp = p * p;
441 return (p - 6.283211f * pp * p + 9.132843f * pp * pp * p) * -6.221086f;
442 }
443};
444
461template <class T = int16_t>
463 public:
464 FastIntSineGenerator(float amplitude = NumberConverter::maxValueT<T>(),
465 float phase = 0.0f) {
466 LOGD("FastIntSineGenerator");
467 setAmplitude(amplitude);
468 setPhase(phase);
469 }
470
471 bool begin() override {
472 TRACEI();
475 return true;
476 }
477
478 bool begin(AudioInfo info) override {
479 LOGI("%s::begin(channels=%d, sample_rate=%d)", "FastIntSineGenerator",
480 (int)info.channels, (int)info.sample_rate);
483 return true;
484 }
485
486 bool begin(AudioInfo info, float frequency) {
488 if (frequency > 0.0f) {
489 setFrequency(frequency);
490 }
491 return true;
492 }
493
494 bool begin(int channels, int sample_rate, float frequency) {
495 SoundGenerator<T>::info.channels = channels;
496 SoundGenerator<T>::info.sample_rate = sample_rate;
497 return begin(SoundGenerator<T>::info, frequency);
498 }
499
504
506 void setFrequency(float frequency) override {
507 LOGI("setFrequency: %.2f", frequency);
508 m_frequency = frequency;
510 }
511
513 void setPhase(float phase) {
514 double turns = phase / (2.0 * PI);
515 m_phase_offset = (uint32_t)(turns * 4294967296.0);
516 }
517
518 void setAmplitude(float amp) {
519 m_amplitude = amp;
520 m_amplitude_i = (int32_t)amp;
521 }
522
524 virtual T readSample() override {
525 // top kTableBits of the 32 bit accumulator select the table entry
526 uint32_t index = (m_phase_acc + m_phase_offset) >> kIndexShift;
528 int32_t sine_q15 = sine_table[index];
529 return (T)(((int64_t)sine_q15 * m_amplitude_i) >> 15);
530 }
531
532 protected:
533 static const int kTableBits = 8;
534 static const int kTableSize = 1 << kTableBits; // 256 entries
535 static const int kIndexShift = 32 - kTableBits;
536
537 volatile float m_frequency = 0.0f;
538 float m_amplitude = 1.0f;
539 int32_t m_amplitude_i = 32767;
540 // fixed point (32 bit) phase: wrapping is implicit via unsigned overflow
541 uint32_t m_phase_acc = 0;
542 uint32_t m_phase_offset = 0;
543 uint32_t m_phase_increment = 0;
544
545 // only called from begin()/setFrequency()/setAudioInfo(), never per sample
547 uint32_t sample_rate = SoundGenerator<T>::info.sample_rate;
548 if (sample_rate > 0) {
550 (uint32_t)((double)m_frequency / sample_rate * 4294967296.0);
551 }
552 }
553
554 // one sine period in Q15 fixed point (-32767..32767)
555 static constexpr int16_t sine_table[kTableSize] = {
556 0, 804, 1608, 2410, 3212, 4011, 4808, 5602, 6393, 7179,
557 7962, 8739, 9512, 10278, 11039, 11793, 12539, 13279, 14010, 14732,
558 15446, 16151, 16846, 17530, 18204, 18868, 19519, 20159, 20787, 21403,
559 22005, 22594, 23170, 23731, 24279, 24811, 25329, 25832, 26319, 26790,
560 27245, 27683, 28105, 28510, 28898, 29268, 29621, 29956, 30273, 30571,
561 30852, 31113, 31356, 31580, 31785, 31971, 32137, 32285, 32412, 32521,
562 32609, 32678, 32728, 32757, 32767, 32757, 32728, 32678, 32609, 32521,
563 32412, 32285, 32137, 31971, 31785, 31580, 31356, 31113, 30852, 30571,
564 30273, 29956, 29621, 29268, 28898, 28510, 28105, 27683, 27245, 26790,
565 26319, 25832, 25329, 24811, 24279, 23731, 23170, 22594, 22005, 21403,
566 20787, 20159, 19519, 18868, 18204, 17530, 16846, 16151, 15446, 14732,
567 14010, 13279, 12539, 11793, 11039, 10278, 9512, 8739, 7962, 7179,
568 6393, 5602, 4808, 4011, 3212, 2410, 1608, 804, 0, -804,
569 -1608, -2410, -3212, -4011, -4808, -5602, -6393, -7179, -7962, -8739,
570 -9512, -10278,-11039,-11793,-12539,-13279,-14010,-14732,-15446,-16151,
571 -16846,-17530,-18204,-18868,-19519,-20159,-20787,-21403,-22005,-22594,
572 -23170,-23731,-24279,-24811,-25329,-25832,-26319,-26790,-27245,-27683,
573 -28105,-28510,-28898,-29268,-29621,-29956,-30273,-30571,-30852,-31113,
574 -31356,-31580,-31785,-31971,-32137,-32285,-32412,-32521,-32609,-32678,
575 -32728,-32757,-32767,-32757,-32728,-32678,-32609,-32521,-32412,-32285,
576 -32137,-31971,-31785,-31580,-31356,-31113,-30852,-30571,-30273,-29956,
577 -29621,-29268,-28898,-28510,-28105,-27683,-27245,-26790,-26319,-25832,
578 -25329,-24811,-24279,-23731,-23170,-22594,-22005,-21403,-20787,-20159,
579 -19519,-18868,-18204,-17530,-16846,-16151,-15446,-14732,-14010,-13279,
580 -12539,-11793,-11039,-10278,-9512, -8739, -7962, -7179, -6393, -5602,
581 -4808, -4011, -3212, -2410, -1608, -804};
582};
583
586#if PREFER_FIXEDPOINT
587template <class T = int16_t>
588using SineGenerator = FastIntSineGenerator<T>;
589#else
590template <class T = int16_t>
592#endif
593
595template <class T = int16_t>
597
612template <class T = int16_t>
614 public:
615 SquareWaveGenerator(float amplitude = NumberConverter::maxValueT<T>(),
616 float phase = 0.0f) {
617 LOGD("SquareWaveGenerator");
618 setAmplitude(amplitude);
619 setPhase(phase);
620 }
621
622 bool begin() override {
623 TRACEI();
626 return true;
627 }
628
629 bool begin(AudioInfo info) override {
630 LOGI("%s::begin(channels=%d, sample_rate=%d)", "SquareWaveGenerator",
631 (int)info.channels, (int)info.sample_rate);
634 return true;
635 }
636
637 bool begin(AudioInfo info, float frequency) {
639 if (frequency > 0.0f) {
640 setFrequency(frequency);
641 }
642 return true;
643 }
644
645 bool begin(int channels, int sample_rate, float frequency) {
646 SoundGenerator<T>::info.channels = channels;
647 SoundGenerator<T>::info.sample_rate = sample_rate;
648 return begin(SoundGenerator<T>::info, frequency);
649 }
650
655
657 void setFrequency(float frequency) override {
658 LOGI("setFrequency: %.2f", frequency);
659 m_frequency = frequency;
661 }
662
664 void setPhase(float phase) {
665 double turns = phase / (2.0 * PI);
666 m_phase_offset = (uint32_t)(turns * 4294967296.0);
667 }
668
669 void setAmplitude(float amp) {
670 m_amplitude = amp;
671 m_amplitude_i = (int32_t)amp;
672 }
673
675 virtual T readSample() override {
676 uint32_t phase = m_phase_acc + m_phase_offset;
678 // top bit of the phase marks the half of the cycle we're in
679 return (int32_t)phase >= 0 ? (T)m_amplitude_i : (T)(-m_amplitude_i);
680 }
681
682 protected:
683 volatile float m_frequency = 0.0f;
684 float m_amplitude = 1.0f;
685 int32_t m_amplitude_i = 32767;
686 // fixed point (32 bit) phase: wrapping is implicit via unsigned overflow
687 uint32_t m_phase_acc = 0;
688 uint32_t m_phase_offset = 0;
689 uint32_t m_phase_increment = 0;
690
691 // only called from begin()/setFrequency()/setAudioInfo(), never per sample
693 uint32_t sample_rate = SoundGenerator<T>::info.sample_rate;
694 if (sample_rate > 0) {
696 (uint32_t)((double)m_frequency / sample_rate * 4294967296.0);
697 }
698 }
699};
700
716template <class T = int16_t>
718 public:
719 SawToothGenerator(float amplitude = NumberConverter::maxValueT<T>(),
720 float phase = 0.0f) {
721 LOGD("SawToothGenerator");
722 setAmplitude(amplitude);
723 setPhase(phase);
724 }
725
726 bool begin() override {
727 TRACEI();
730 return true;
731 }
732
733 bool begin(AudioInfo info) override {
734 LOGI("%s::begin(channels=%d, sample_rate=%d)", "SawToothGenerator",
735 (int)info.channels, (int)info.sample_rate);
738 return true;
739 }
740
741 bool begin(AudioInfo info, float frequency) {
743 if (frequency > 0.0f) {
744 setFrequency(frequency);
745 }
746 return true;
747 }
748
749 bool begin(int channels, int sample_rate, float frequency) {
750 SoundGenerator<T>::info.channels = channels;
751 SoundGenerator<T>::info.sample_rate = sample_rate;
752 return begin(SoundGenerator<T>::info, frequency);
753 }
754
759
761 void setFrequency(float frequency) override {
762 LOGI("setFrequency: %.2f", frequency);
763 m_frequency = frequency;
765 }
766
768 void setPhase(float phase) {
769 double turns = phase / (2.0 * PI);
770 m_phase_offset = (uint32_t)(turns * 4294967296.0);
771 }
772
773 void setAmplitude(float amp) {
774 m_amplitude = amp;
775 m_amplitude_i = (int32_t)amp;
776 }
777
779 virtual T readSample() override {
780 uint32_t phase = m_phase_acc + m_phase_offset;
782 // reinterpreting the wrapping unsigned phase as signed already gives
783 // a linear ramp from -2^31 to 2^31-1: exactly a saw tooth
784 int32_t ramp = (int32_t)phase;
785 return (T)(((int64_t)ramp * m_amplitude_i) >> 31);
786 }
787
788 protected:
789 volatile float m_frequency = 0.0f;
790 float m_amplitude = 1.0f;
791 int32_t m_amplitude_i = 32767;
792 // fixed point (32 bit) phase: wrapping is implicit via unsigned overflow
793 uint32_t m_phase_acc = 0;
794 uint32_t m_phase_offset = 0;
795 uint32_t m_phase_increment = 0;
796
797 // only called from begin()/setFrequency()/setAudioInfo(), never per sample
799 uint32_t sample_rate = SoundGenerator<T>::info.sample_rate;
800 if (sample_rate > 0) {
802 (uint32_t)((double)m_frequency / sample_rate * 4294967296.0);
803 }
804 }
805};
806
814template <class T = int16_t>
816 public:
819
822
823 protected:
825 // //range : [min, max]
826 int random(int min, int max) { return min + rand() % ((max + 1) - min); }
827};
828
836template <class T = int16_t>
838 public:
841 this->amplitude = amplitude;
842 max_key = 0x1f; // Five bits set
843 key = 0;
844 for (int i = 0; i < 5; i++) white_values[i] = rand() % (amplitude / 5);
845 }
846
849 T last_key = key;
850 unsigned int sum;
851
852 key++;
853 if (key > max_key) key = 0;
854 // Exclusive-Or previous value with current value. This gives
855 // a list of bits that have changed.
856 int diff = last_key ^ key;
857 sum = 0;
858 for (int i = 0; i < 5; i++) {
859 // If bit changed get new random number for corresponding
860 // white_value
861 if (diff & (1 << i)) white_values[i] = rand() % (amplitude / 5);
862 sum += white_values[i];
863 }
864 return sum;
865 }
866
867 protected:
870 unsigned int white_values[5];
871 unsigned int amplitude;
872};
873
883template <class T = int16_t>
885 public:
886 // the scale defines the max value which is generated
887 SilenceGenerator(T value = 0) { this->value = value; }
888
891 return value; // return 0
892 }
893
894 protected:
896};
897
905template <class T = int16_t>
907 public:
911
921 GeneratorFromStream(Stream& input, int channels = 1, float volume = 1.0) {
922 maxValue = NumberConverter::maxValue(sizeof(T) * 8);
923 setStream(input);
926 }
927
929 void setStream(Stream& input) { this->p_stream = &input; }
930
931 void setChannels(int channels) { this->channels = channels; }
932
935 T data = 0;
936 float total = 0;
937 if (p_stream != nullptr) {
938 for (int j = 0; j < channels; j++) {
939 p_stream->readBytes((uint8_t*)&data, sizeof(T));
940 total += data;
941 }
942 float avg = (total / channels) * volume();
943 if (avg > maxValue) {
944 data = maxValue;
945 } else if (avg < -maxValue) {
946 data = -maxValue;
947 } else {
948 data = avg;
949 }
950 }
951 return data;
952 }
953
954 protected:
955 Stream* p_stream = nullptr;
956 int channels = 1;
957 float maxValue;
958};
959
969template <class T = int16_t>
971 public:
985 template <size_t arrayLen>
986 GeneratorFromArray(T (&array)[arrayLen], int repeat = 0,
987 bool setInactiveAtEnd = false, size_t startIndex = 0) {
988 TRACED();
989 this->max_repeat = repeat;
990 this->inactive_at_end = setInactiveAtEnd;
991 this->sound_index = startIndex;
992 setArray(array, arrayLen);
993 }
994
995 template <int arrayLen>
996 void setArray(T (&array)[arrayLen]) {
997 TRACED();
998 setArray(array, arrayLen);
999 }
1000
1001 void setArray(T* array, size_t size) {
1002 table.resize(size);
1003 for (int j = 0; j < size; j++) {
1004 table[j] = array[j];
1005 }
1006 LOGI("table_length: %d", (int)size);
1007 }
1008
1010 bool begin(AudioInfo info) override {
1012 }
1013
1016 bool rc = begin(info);
1018 return rc;
1019 }
1020
1022 bool begin() override {
1023 TRACEI();
1025 sound_index = 0.0f;
1026 repeat_counter = 0;
1027 is_running = true;
1028 return true;
1029 }
1030
1031 void end() override { table.resize(0); }
1032
1034 T readSample() override {
1035 if (table.size() == 0) {
1036 return 0;
1037 }
1038
1039 if (!this->is_running) {
1040 return 0;
1041 }
1042
1043 const float table_size = static_cast<float>(table.size());
1044
1045 // at end deactivate output
1046 while (sound_index >= table_size) {
1047 // LOGD("reset index - sound_index: %d, table_length:
1048 // %d",sound_index,table_length);
1049 sound_index -= table_size;
1050 // deactivate when count has been used up
1051 if (max_repeat >= 1 && ++repeat_counter >= max_repeat) {
1052 LOGD("atEnd");
1053 this->is_running = false;
1054 if (inactive_at_end) {
1055 this->active = false;
1056 }
1057 return 0;
1058 }
1059 }
1060
1061 // LOGD("index: %d - active: %d", sound_index, this->active);
1062 T result = 0;
1063 if (this->is_running) {
1064 int idx0 = static_cast<int>(sound_index);
1065 int idx1 = idx0 + 1;
1066 if (idx1 >= static_cast<int>(table.size())) {
1067 idx1 = 0;
1068 }
1069 float frac = sound_index - static_cast<float>(idx0);
1070 float sample = static_cast<float>(table[idx0]) * (1.0f - frac) +
1071 static_cast<float>(table[idx1]) * frac;
1072 result = static_cast<T>(sample);
1074 }
1075
1076 return result;
1077 }
1078
1079 // step size the sound index is incremented (default = 1)
1080 void setIncrement(int inc) {
1081 index_increment = inc;
1082 frequency = 0.0f;
1083 }
1084
1086 void setFrequency(float frequency) override {
1087 if (SoundGenerator<T>::audioInfo().sample_rate <= 0 || table.size() == 0) {
1088 LOGE("setFrequency failed: sample_rate=%d table_size=%d",
1089 (int)SoundGenerator<T>::audioInfo().sample_rate, (int)table.size());
1090 return;
1091 }
1092 if (frequency < 0.0f) {
1093 frequency = 0.0f;
1094 }
1095 this->frequency = frequency;
1097 frequency * static_cast<float>(table.size()) /
1098 static_cast<float>(SoundGenerator<T>::audioInfo().sample_rate);
1099 }
1100
1101 // Sets up a sine table - returns the effective frequency
1102 int setupSine(int sampleRate, float reqFrequency, float amplitude = 1.0) {
1103 int sample_count =
1104 static_cast<float>(sampleRate) /
1105 reqFrequency; // e.g. 44100 / 300hz = 147 samples per wave
1106 float angle = 2.0 * PI / sample_count;
1107 table.resize(sample_count);
1108 for (int j = 0; j < sample_count; j++) {
1109 table[j] = sinf(j * angle) * amplitude;
1110 }
1111 // calculate effective frequency
1112 return sampleRate / sample_count;
1113 }
1114
1115 // Similar like is active to check if the array is still playing.
1116 bool isRunning() { return is_running; }
1117
1118 protected:
1119 float sound_index = 0.0f;
1120 int max_repeat = 0;
1122 bool inactive_at_end = false;
1123 bool is_running = false;
1124 bool owns_data = false;
1126 float index_increment = 1.0f;
1127 float frequency = 0.0f;
1128};
1129
1137template <class T = int16_t>
1139 public:
1141
1143
1144 void setValue(T value) { value_set = value; }
1145
1147 bool begin() override {
1148 TRACEI();
1150 is_running = true;
1152 return true;
1153 }
1154
1156 T readSample() override { return value_return; }
1157
1158 // Similar like is active to check if the array is still playing.
1159 bool isRunning() { return is_running; }
1160
1161 protected:
1164 bool is_running = false;
1165};
1166
1174template <class T = int16_t>
1176 public:
1177 SineFromTable(float amplitude = NumberConverter::maxValueT<T>()) {
1178 this->amplitude = amplitude;
1179 this->amplitude_to_be = amplitude;
1180 }
1181
1184
1188
1190 // update angle
1191 angle += step;
1192 if (angle >= 360.0f) {
1193 while (angle >= 360.0f) {
1194 angle -= 360.0f;
1195 }
1196 // update frequency at start of circle (near 0 degrees)
1197 step = step_new;
1198
1200 // amplitude = amplitude_to_be;
1201 }
1202 return interpolate(angle);
1203 }
1204
1205 bool begin() {
1206 is_first = true;
1209 360.0f; // 122.5 hz (at 44100); 61 hz (at 22050)
1210 return true;
1211 }
1212
1213 bool begin(AudioInfo info, float frequency) {
1216 360.0f; // 122.5 hz (at 44100); 61 hz (at 22050)
1217 setFrequency(frequency);
1218 return true;
1219 }
1220
1221 bool begin(int channels, int sample_rate, uint16_t frequency = 0) {
1222 SoundGenerator<T>::info.channels = channels;
1223 SoundGenerator<T>::info.sample_rate = sample_rate;
1224 return begin(SoundGenerator<T>::info, frequency);
1225 }
1226
1227 void setFrequency(float freq) {
1228 step_new = freq / base_frequency;
1229 if (is_first) {
1230 step = step_new;
1231 is_first = false;
1232 }
1233 LOGD("step: %f", step_new);
1234 }
1235
1236 protected:
1237 bool is_first = true;
1240 float max_amplitude_step = 50.0f;
1241 float base_frequency = 1.0f;
1242 float step = 1.0f;
1243 float step_new = 1.0f;
1244 float angle = 0.0f;
1245 // 122.5 hz (at 44100); 61 hz (at 22050)
1246 const float values[181] = {
1247 0, 0.0174524, 0.0348995, 0.052336, 0.0697565, 0.0871557,
1248 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
1249 0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
1250 0.309017, 0.325568, 0.34202, 0.358368, 0.374607, 0.390731,
1251 0.406737, 0.422618, 0.438371, 0.45399, 0.469472, 0.48481,
1252 0.5, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
1253 0.587785, 0.601815, 0.615661, 0.62932, 0.642788, 0.656059,
1254 0.669131, 0.681998, 0.694658, 0.707107, 0.71934, 0.731354,
1255 0.743145, 0.75471, 0.766044, 0.777146, 0.788011, 0.798636,
1256 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
1257 0.866025, 0.87462, 0.882948, 0.891007, 0.898794, 0.906308,
1258 0.913545, 0.920505, 0.927184, 0.93358, 0.939693, 0.945519,
1259 0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.97437,
1260 0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
1261 0.994522, 0.996195, 0.997564, 0.99863, 0.999391, 0.999848,
1262 1, 0.999848, 0.999391, 0.99863, 0.997564, 0.996195,
1263 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
1264 0.978148, 0.97437, 0.970296, 0.965926, 0.961262, 0.956305,
1265 0.951057, 0.945519, 0.939693, 0.93358, 0.927184, 0.920505,
1266 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.87462,
1267 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
1268 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.75471,
1269 0.743145, 0.731354, 0.71934, 0.707107, 0.694658, 0.681998,
1270 0.669131, 0.656059, 0.642788, 0.62932, 0.615661, 0.601815,
1271 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
1272 0.5, 0.48481, 0.469472, 0.45399, 0.438371, 0.422618,
1273 0.406737, 0.390731, 0.374607, 0.358368, 0.34202, 0.325568,
1274 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
1275 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
1276 0.104528, 0.0871557, 0.0697565, 0.052336, 0.0348995, 0.0174524,
1277 0};
1278
1280 bool positive = (angle <= 180.0f);
1281 float angle_positive = positive ? angle : angle - 180.0f;
1282 int angle_int1 = angle_positive;
1283 int angle_int2 = angle_int1 + 1;
1284 T v1 = values[angle_int1] * amplitude;
1285 T v2 = values[angle_int2] * amplitude;
1286 T result = v1 < v2 ? map(angle_positive, angle_int1, angle_int2, v1, v2)
1287 : map(angle_positive, angle_int1, angle_int2, v2, v1);
1288 // float result = v1;
1289 return positive ? result : -result;
1290 }
1291
1292 T map(T x, T in_min, T in_max, T out_min, T out_max) {
1293 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
1294 }
1295
1297 float diff = amplitude_to_be - amplitude;
1298 if (abs(diff) > max_amplitude_step) {
1299 diff = (diff < 0) ? -max_amplitude_step : max_amplitude_step;
1300 }
1301 if (abs(diff) >= 1.0f) {
1302 amplitude += diff;
1303 }
1304 }
1305};
1306
1315template <class T = int16_t>
1317 public:
1318 GeneratorMixer() = default;
1319
1320 void add(SoundGenerator<T>& generator) { vector.push_back(&generator); }
1321 void add(SoundGenerator<T>* generator) { vector.push_back(generator); }
1322
1323 void clear() { vector.clear(); }
1324
1326 float total = 0.0f;
1327 float count = 0.0f;
1328 for (auto& generator : vector) {
1329 if (generator->isActive()) {
1330 T sample = generator->readSample();
1331 total += sample;
1332 count += 1.0f;
1333 }
1334 }
1335 return count > 0.0f ? total / count : 0;
1336 }
1337
1338 protected:
1341};
1342
1351template <class T = int16_t>
1353 public:
1354 TestGenerator(T max = 1000, T inc = 1) { this->max = max; }
1355
1356 T readSample() override {
1357 value += inc;
1358 if (abs(value) >= max) {
1359 inc = -inc;
1360 value += (inc * 2);
1361 }
1362 return value;
1363 }
1364
1365 protected:
1367 T value = 0;
1368 T inc = 1;
1369};
1370
1379template <class T = int16_t>
1381public:
1382 virtual bool begin(uint16_t queue_size=256) {
1383 return queue.resize(queue_size) && SoundGenerator<T>::begin();
1384 }
1385
1386 virtual void end() override { SoundGenerator<T>::end(); clear(); }
1387
1388 // Returns the requested number of bytes from the current generator.
1389 // If the current generator runs out of bytes before the buffer is filled,
1390 // it will move to the next queued generator. If there are no more generators,
1391 // it will stop filling the buffer and return the number of bytes it was able to fill.
1392 virtual size_t readBytes(uint8_t *buffer, size_t buf_len) override {
1393 LOGD("readBytes: %d", (int)buf_len);
1394 if (!SoundGenerator<T>::active) return 0;
1395 if (queue.available() == 0) return 0; // Nothing in the queue.
1396
1397 size_t bytes_read = 0;
1398 size_t ret = 0;
1399 SoundGenerator<T> *current_generator = nullptr;
1400
1401 while (bytes_read < buf_len) {
1402 if ((current_generator = getCurrentGenerator()) == nullptr) break; // No generator.
1403
1404 ret = current_generator->readBytes(buffer+bytes_read, buf_len-bytes_read);
1405 bytes_read += ret;
1406
1407 if (ret == 0) {
1408 // Done with this generator, move to the next one.
1410 if (queue.available() == 0) break; // No more generators
1411 }
1412 }
1413 return bytes_read;
1414 }
1415
1416 // If no bytes are available, will return 0.
1417 virtual T readSample() override {
1418 T buf;
1419 if (readBytes((uint8_t *)&buf, sizeof(T)) != sizeof(T)) return (T)0;
1420 return buf;
1421 }
1422
1423 virtual inline size_t readSamples(T* data, size_t len) override {
1424 return (readBytes((uint8_t *)data, len*sizeof(T)) / sizeof(T));
1425 }
1426
1427 // Add a generator to the queue. The generator MUST be time limited BEFORE adding
1428 // to the queue (eg: calling setPlayTime()). Otherwise, the generator will never
1429 // run out of bytes and nothing after it will ever play.
1430 // Callbacks are called in the context of read*() methods, so you probably want them
1431 // to be quick and not block on anything.
1433 void (*start_cb)(SoundGenerator<T> *, const void *) = nullptr,
1434 void (*end_cb)(SoundGenerator<T> *, const void *) = nullptr,
1435 const void *cb_data = nullptr
1436 ) {
1437 LOGD("pushGenerator()");
1438 if (queue.availableForWrite() == 0) return false; // Queue is full.
1439
1440 QNode *node = new QNode(gen, start_cb, end_cb, cb_data); // Deleted in removeCurrentGenerator;
1441 if (node == nullptr) return false; // new failed
1442
1443 if (!queue.write(node)) {
1444 delete node;
1445 return false;
1446 }
1447 return true;
1448 }
1449
1450 // GeneratorQueue doesn't do everything other generators do. We rely on the
1451 // queued SoundGenerators to do any shaping.
1452 virtual inline void setPlayTime(uint32_t p, uint8_t u = 20, uint8_t d = 30) override {
1453 LOGW("GeneratorQueue::setPlayTime() does nothing.");
1454 }
1455 virtual inline void setFrequency(float f) override {
1456 LOGW("GeneratorQueue::setFrequency() does nothing.");
1457 }
1458
1460 QNode *node;
1461 if (!queue.peek(node)) return nullptr;
1462 return node->generator;
1463 }
1464
1465 virtual bool clear() {
1466 while (removeCurrentGenerator()) {}; // Deletes all the QNodes.
1467 return queue.available() == 0;
1468 }
1469
1470 virtual inline size_t size() { return queue.available(); }
1471 virtual inline size_t available() { return queue.available(); }
1472 virtual inline size_t availableForWrite() { return queue.availableForWrite(); }
1473 virtual inline bool empty() { return queue.available() == 0; }
1474
1475protected:
1476 struct QNode {
1478 void (*start_cb)(SoundGenerator<T> *, const void *);
1479 void (*end_cb)(SoundGenerator<T> *, const void *);
1480 const void *cb_data;
1482 QNode(SoundGenerator<T> *g, void (*s)(SoundGenerator<T> *, const void *), void (*e)(SoundGenerator<T> *, const void *), const void *d) :
1483 generator(g), start_cb(s), end_cb(e), cb_data(d) { restarted=false; }
1484 };
1485
1487
1488 // Returns the SoundGenerator at the head of the queue,
1489 // restarting it if it hasn't been restarted yet.
1491 if (queue.available() == 0) return nullptr;
1492
1493 QNode *node = nullptr;
1494 if (!queue.peek(node) || node == nullptr) return nullptr;
1495
1496 if (!node->restarted) {
1497 if (node->start_cb) {
1498 node->start_cb(node->generator, node->cb_data);
1499 }
1500 node->generator->restart();
1501 node->restarted = true; // persistent dynamic objects, this will persist.
1502 }
1503 return node->generator;
1504 }
1505
1506 // Removes the current SoundGenerator from the queue, and cleans up memory use.
1508 if (queue.available() == 0) return false;
1509
1510 QNode *node = nullptr;
1511 bool ret = queue.read(node);
1512 if (node != nullptr) {
1513 if (node->end_cb) {
1514 node->end_cb(node->generator, node->cb_data);
1515 }
1516 delete node;
1517 }
1518 return ret;
1519 }
1520
1521 // readBytes(), readSample(), and readSamples() have all been reimplemented above
1522 // and do not use readBytesFrames(), so this will never be called. But it's not
1523 // virtual in SoundGenerator so I can't overwrite it.
1524 //size_t readBytesFrames(uint8_t *b, size_t l, int f, int c) {
1525 // LOGE("GeneratorQueue::readBytesFrames() should never get called.");
1526 // return 0;
1527 //}
1528
1529};
1530
1531
1532
1533} // namespace audio_tools
#define PI
Definition AudioEffectsSuite.h:28
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Definition Arduino.h:136
virtual size_t readBytes(uint8_t *data, size_t len)
Definition Arduino.h:140
Sine wave generator that does not use any floating point operations in the readSample() hot path: it ...
Definition SoundGenerator.h:462
void updatePhaseIncrement()
Definition SoundGenerator.h:546
static const int kTableSize
Definition SoundGenerator.h:534
void setFrequency(float frequency) override
Defines the frequency - the only place where float math is used.
Definition SoundGenerator.h:506
void setAmplitude(float amp)
Definition SoundGenerator.h:518
uint32_t m_phase_increment
Definition SoundGenerator.h:543
static constexpr int16_t sine_table[kTableSize]
Definition SoundGenerator.h:555
virtual T readSample() override
Provides a single sample - integer only, no float ops or sin() calls!
Definition SoundGenerator.h:524
volatile float m_frequency
Definition SoundGenerator.h:537
static const int kIndexShift
Definition SoundGenerator.h:535
FastIntSineGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:464
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:494
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:500
static const int kTableBits
Definition SoundGenerator.h:533
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:478
bool begin() override
Starts the processing.
Definition SoundGenerator.h:471
uint32_t m_phase_acc
Definition SoundGenerator.h:541
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:486
void setPhase(float phase)
Defines the starting phase in radians.
Definition SoundGenerator.h:513
uint32_t m_phase_offset
Definition SoundGenerator.h:542
int32_t m_amplitude_i
Definition SoundGenerator.h:539
float m_amplitude
Definition SoundGenerator.h:538
Sine wave which is based on a fast approximation function using floating point math.
Definition SoundGenerator.h:417
float sine(float t)
sine approximation.
Definition SoundGenerator.h:438
virtual T readSample() override
Provides a single sample.
Definition SoundGenerator.h:424
FastSineGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0)
Definition SoundGenerator.h:419
Generates a Sound with the help of sin() function. If performance is of concern, I suggest to use the...
Definition SoundGenerator.h:317
void setFrequency(float frequency) override
Defines the frequency - after the processing has been started.
Definition SoundGenerator.h:371
float m_phase
Definition SoundGenerator.h:399
void setAmplitude(float amp)
Definition SoundGenerator.h:392
virtual T readSample() override
Provides a single sample.
Definition SoundGenerator.h:382
volatile float m_frequency
Definition SoundGenerator.h:395
float m_deltaTime
Definition SoundGenerator.h:398
const float double_Pi
Definition SoundGenerator.h:400
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:354
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:361
virtual AudioInfo defaultConfig() override
Provides the default configuration.
Definition SoundGenerator.h:366
FloatSineGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:320
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:334
bool begin() override
Starts the processing.
Definition SoundGenerator.h:327
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:342
void logStatus()
Definition SoundGenerator.h:402
float m_cycles
Definition SoundGenerator.h:396
float m_amplitude
Definition SoundGenerator.h:397
Just returns a constant value.
Definition SoundGenerator.h:1138
T value_set
Definition SoundGenerator.h:1162
bool isRunning()
Definition SoundGenerator.h:1159
virtual bool begin(AudioInfo info)
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:1142
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1156
bool is_running
Definition SoundGenerator.h:1164
bool begin() override
Starts the generation of samples.
Definition SoundGenerator.h:1147
T value_return
Definition SoundGenerator.h:1163
void setValue(T value)
Definition SoundGenerator.h:1144
We generate the samples from an array which is provided in the constructor.
Definition SoundGenerator.h:970
void setFrequency(float frequency) override
Defines the output frequency based on sample rate and table size.
Definition SoundGenerator.h:1086
void setIncrement(int inc)
Definition SoundGenerator.h:1080
int setupSine(int sampleRate, float reqFrequency, float amplitude=1.0)
Definition SoundGenerator.h:1102
bool isRunning()
Definition SoundGenerator.h:1116
bool inactive_at_end
Definition SoundGenerator.h:1122
Vector< T > table
Definition SoundGenerator.h:1125
void end() override
Definition SoundGenerator.h:1031
float sound_index
Definition SoundGenerator.h:1119
void setArray(T *array, size_t size)
Definition SoundGenerator.h:1001
float index_increment
Definition SoundGenerator.h:1126
GeneratorFromArray(T(&array)[arrayLen], int repeat=0, bool setInactiveAtEnd=false, size_t startIndex=0)
Construct a new Generator from an array.
Definition SoundGenerator.h:986
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1034
bool is_running
Definition SoundGenerator.h:1123
int max_repeat
Definition SoundGenerator.h:1120
bool owns_data
Definition SoundGenerator.h:1124
int repeat_counter
Definition SoundGenerator.h:1121
bool begin(AudioInfo info) override
Starts the generation of samples with the provided AudioInfo.
Definition SoundGenerator.h:1010
bool begin() override
Starts the generation of samples.
Definition SoundGenerator.h:1022
float frequency
Definition SoundGenerator.h:1127
bool begin(AudioInfo info, float frequency)
Starts the generation of samples with the provided AudioInfo and frequency.
Definition SoundGenerator.h:1015
void setArray(T(&array)[arrayLen])
Definition SoundGenerator.h:996
An Adapter Class which lets you use any Stream as a Generator.
Definition SoundGenerator.h:906
int channels
Definition SoundGenerator.h:956
GeneratorFromStream()
Definition SoundGenerator.h:908
Stream * p_stream
Definition SoundGenerator.h:955
void setStream(Stream &input)
(Re-)Assigns a stream to the Adapter class
Definition SoundGenerator.h:929
void setChannels(int channels)
Definition SoundGenerator.h:931
float maxValue
Definition SoundGenerator.h:957
GeneratorFromStream(Stream &input, int channels=1, float volume=1.0)
Constructs a new Generator from a Stream object that can be used e.g. as input for AudioEffectss.
Definition SoundGenerator.h:921
T readSample()
Provides a single sample from the stream.
Definition SoundGenerator.h:934
Generator which combines (mixes) multiple sound generators into one output.
Definition SoundGenerator.h:1316
void add(SoundGenerator< T > *generator)
Definition SoundGenerator.h:1321
Vector< SoundGenerator< T > * > vector
Definition SoundGenerator.h:1339
int actualChannel
Definition SoundGenerator.h:1340
void clear()
Definition SoundGenerator.h:1323
T readSample()
Provides a single sample.
Definition SoundGenerator.h:1325
void add(SoundGenerator< T > &generator)
Definition SoundGenerator.h:1320
Queues SoundGenerators and plays them sequentially. Queued SoundGenerators must be limited (eg: setPl...
Definition SoundGenerator.h:1380
virtual size_t availableForWrite()
Definition SoundGenerator.h:1472
virtual void setPlayTime(uint32_t p, uint8_t u=20, uint8_t d=30) override
Defines the play time in ms and the ramp up and ramp down time in percent.
Definition SoundGenerator.h:1452
virtual SoundGenerator< T > * peek()
Definition SoundGenerator.h:1459
virtual bool begin(uint16_t queue_size=256)
Definition SoundGenerator.h:1382
virtual bool clear()
Definition SoundGenerator.h:1465
virtual size_t readBytes(uint8_t *buffer, size_t buf_len) override
Provides the data as byte array with the requested number of channels.
Definition SoundGenerator.h:1392
SoundGenerator< T > * getCurrentGenerator()
Definition SoundGenerator.h:1490
virtual bool empty()
Definition SoundGenerator.h:1473
virtual T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1417
virtual size_t available()
Definition SoundGenerator.h:1471
virtual bool pushGenerator(SoundGenerator< T > *gen, void(*start_cb)(SoundGenerator< T > *, const void *)=nullptr, void(*end_cb)(SoundGenerator< T > *, const void *)=nullptr, const void *cb_data=nullptr)
Definition SoundGenerator.h:1432
bool removeCurrentGenerator()
Definition SoundGenerator.h:1507
virtual size_t size()
Definition SoundGenerator.h:1470
virtual size_t readSamples(T *data, size_t len) override
Definition SoundGenerator.h:1423
virtual void end() override
Definition SoundGenerator.h:1386
virtual void setFrequency(float f) override
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:1455
RingBufferSPSC< QNode * > queue
Definition SoundGenerator.h:1486
static int64_t maxValue(int value_bits_per_sample)
provides the biggest number for the indicated number of bits
Definition AudioTypes.h:303
Generates pink noise.
Definition SoundGenerator.h:837
PinkNoiseGenerator(T amplitude=32767)
the amplitude defines the max value which is generated
Definition SoundGenerator.h:840
T key
Definition SoundGenerator.h:869
unsigned int amplitude
Definition SoundGenerator.h:871
T max_key
Definition SoundGenerator.h:868
unsigned int white_values[5]
Definition SoundGenerator.h:870
T readSample()
Provides a single sample.
Definition SoundGenerator.h:848
Implements a typed Ringbuffer.
Definition Buffers.h:363
virtual int readArray(T data[], int len) override
reads multiple values
Definition Buffers.h:412
virtual int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:432
virtual bool resize(size_t len)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:483
bool isEmpty()
Definition Buffers.h:453
Lock-free Single-Producer Single-Consumer ring buffer.
Definition RingBufferSPSC.h:52
Generates a saw tooth wave sound. Uses a 32 bit phase accumulator with an integer increment,...
Definition SoundGenerator.h:717
void updatePhaseIncrement()
Definition SoundGenerator.h:798
void setFrequency(float frequency) override
Defines the frequency - the only place where float math is used.
Definition SoundGenerator.h:761
void setAmplitude(float amp)
Definition SoundGenerator.h:773
uint32_t m_phase_increment
Definition SoundGenerator.h:795
virtual T readSample() override
Provides a single sample - integer only, no float ops!
Definition SoundGenerator.h:779
volatile float m_frequency
Definition SoundGenerator.h:789
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:749
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:755
SawToothGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:719
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:733
bool begin() override
Starts the processing.
Definition SoundGenerator.h:726
uint32_t m_phase_acc
Definition SoundGenerator.h:793
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:741
void setPhase(float phase)
Defines the starting phase in radians.
Definition SoundGenerator.h:768
uint32_t m_phase_offset
Definition SoundGenerator.h:794
int32_t m_amplitude_i
Definition SoundGenerator.h:791
float m_amplitude
Definition SoundGenerator.h:790
Provides a fixed value (e.g. 0) as sound data. This can be used e.g. to test the output functionality...
Definition SoundGenerator.h:884
SilenceGenerator(T value=0)
Definition SoundGenerator.h:887
T value
Definition SoundGenerator.h:895
T readSample()
Provides a single sample.
Definition SoundGenerator.h:890
A sine generator based on a table. The table is created using degrees where one full wave is 360 degr...
Definition SoundGenerator.h:1175
float amplitude
Definition SoundGenerator.h:1238
T interpolate(float angle)
Definition SoundGenerator.h:1279
float base_frequency
Definition SoundGenerator.h:1241
const float values[181]
Definition SoundGenerator.h:1246
T map(T x, T in_min, T in_max, T out_min, T out_max)
Definition SoundGenerator.h:1292
void updateAmplitudeInSteps()
Definition SoundGenerator.h:1296
bool is_first
Definition SoundGenerator.h:1237
float step_new
Definition SoundGenerator.h:1243
bool begin()
Starts the processing.
Definition SoundGenerator.h:1205
bool begin(int channels, int sample_rate, uint16_t frequency=0)
Definition SoundGenerator.h:1221
void setFrequency(float freq)
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:1227
float step
Definition SoundGenerator.h:1242
float amplitude_to_be
Definition SoundGenerator.h:1239
float angle
Definition SoundGenerator.h:1244
float max_amplitude_step
Definition SoundGenerator.h:1240
void setAmplitude(float amplitude)
Defines the new amplitude (volume)
Definition SoundGenerator.h:1183
void setMaxAmplitudeStep(float step)
Definition SoundGenerator.h:1187
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:1213
T readSample()
Provides a single sample.
Definition SoundGenerator.h:1189
SineFromTable(float amplitude=NumberConverter::maxValueT< T >())
Definition SoundGenerator.h:1177
Base class to define the abstract interface for the sound generating classes.
Definition SoundGenerator.h:30
bool active
Definition SoundGenerator.h:173
virtual void restart()
Restarts the generator, e.g. after a play time has been defined and reached.
Definition SoundGenerator.h:167
uint32_t downSamples
Definition SoundGenerator.h:185
virtual size_t readBytes(uint8_t *data, size_t len)
Provides the data as byte array with the requested number of channels.
Definition SoundGenerator.h:83
virtual T readSample()=0
Provides a single sample.
bool activeWarningIssued
Definition SoundGenerator.h:174
float factor
Definition SoundGenerator.h:188
uint32_t playMs
Definition SoundGenerator.h:178
virtual bool begin(AudioInfo info)
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:37
AudioInfo info
Definition SoundGenerator.h:176
float rampDownDec
Definition SoundGenerator.h:187
SoundGenerator()
Definition SoundGenerator.h:32
virtual void setFrequency(float frequency)
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:115
virtual bool begin()
Starts the processing.
Definition SoundGenerator.h:43
virtual size_t readSamples(T *data, size_t len)
Definition SoundGenerator.h:97
virtual void setRampTimes(uint32_t playMs, uint32_t upMs=5, uint32_t downMs=5)
Definition SoundGenerator.h:150
virtual bool isActive()
Checks if the begin method has been called - after end() isActive is false.
Definition SoundGenerator.h:77
void recalculatePlayTime()
Definition SoundGenerator.h:191
virtual void setAudioInfo(AudioInfo info)
Defines/updates the AudioInfo.
Definition SoundGenerator.h:123
T applyRamp(T sample)
Definition SoundGenerator.h:269
uint32_t downMs
Definition SoundGenerator.h:182
float rampUpInc
Definition SoundGenerator.h:186
uint32_t upMs
Definition SoundGenerator.h:181
size_t readBytesFrames(uint8_t *buffer, size_t lengthBytes, int frames, int channels)
Definition SoundGenerator.h:236
uint32_t upSamples
Definition SoundGenerator.h:184
uint32_t playSamples
Definition SoundGenerator.h:183
virtual AudioInfo audioInfo()
Provides the AudioInfo.
Definition SoundGenerator.h:120
virtual void end()
Definition SoundGenerator.h:55
virtual ~SoundGenerator()
Definition SoundGenerator.h:34
uint8_t downPercent
Definition SoundGenerator.h:180
uint8_t upPercent
Definition SoundGenerator.h:179
virtual void end(bool allow_rampdown)
Definition SoundGenerator.h:59
virtual void setPlayTime(uint32_t playMs, uint8_t upPercent=20, uint8_t downPercent=30)
Defines the play time in ms and the ramp up and ramp down time in percent.
Definition SoundGenerator.h:132
size_t readBytesFromBuffer(uint8_t *buffer, size_t lengthBytes, int frame_size, int channels)
Definition SoundGenerator.h:291
virtual AudioInfo defaultConfig()
Provides the default configuration.
Definition SoundGenerator.h:108
RingBuffer< uint8_t > ring_buffer
Definition SoundGenerator.h:177
uint32_t currentSample
Definition SoundGenerator.h:189
Generates a square wave sound. Uses the same 32 bit phase accumulator as SawToothGenerator/FastIntSin...
Definition SoundGenerator.h:613
SquareWaveGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:615
void updatePhaseIncrement()
Definition SoundGenerator.h:692
void setFrequency(float frequency) override
Defines the frequency - the only place where float math is used.
Definition SoundGenerator.h:657
void setAmplitude(float amp)
Definition SoundGenerator.h:669
uint32_t m_phase_increment
Definition SoundGenerator.h:689
virtual T readSample() override
Provides a single sample - integer only, no float ops!
Definition SoundGenerator.h:675
volatile float m_frequency
Definition SoundGenerator.h:683
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:645
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:651
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:629
bool begin() override
Starts the processing.
Definition SoundGenerator.h:622
uint32_t m_phase_acc
Definition SoundGenerator.h:687
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:637
void setPhase(float phase)
Defines the starting phase in radians.
Definition SoundGenerator.h:664
uint32_t m_phase_offset
Definition SoundGenerator.h:688
int32_t m_amplitude_i
Definition SoundGenerator.h:685
float m_amplitude
Definition SoundGenerator.h:684
Generates a test signal which is easy to check because the values are incremented or decremented by 1...
Definition SoundGenerator.h:1352
T inc
Definition SoundGenerator.h:1368
T value
Definition SoundGenerator.h:1367
T max
Definition SoundGenerator.h:1366
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1356
TestGenerator(T max=1000, T inc=1)
Definition SoundGenerator.h:1354
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:193
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:196
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:198
Generates a random noise sound with the help of rand() function.
Definition SoundGenerator.h:815
T amplitude
Definition SoundGenerator.h:824
WhiteNoiseGenerator(T amplitude=32767)
the scale defines the max value which is generated
Definition SoundGenerator.h:818
int random(int min, int max)
Definition SoundGenerator.h:826
T readSample()
Provides a single sample.
Definition SoundGenerator.h:821
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
FloatSineGenerator< T > SineGenerator
Definition SoundGenerator.h:591
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:58
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:62
virtual void logInfo(const char *source="")
Definition AudioTypes.h:127
Definition SoundGenerator.h:1476
const void * cb_data
Definition SoundGenerator.h:1480
bool restarted
Definition SoundGenerator.h:1481
SoundGenerator< T > * generator
Definition SoundGenerator.h:1477
QNode(SoundGenerator< T > *g, void(*s)(SoundGenerator< T > *, const void *), void(*e)(SoundGenerator< T > *, const void *), const void *d)
Definition SoundGenerator.h:1482
void(* end_cb)(SoundGenerator< T > *, const void *)
Definition SoundGenerator.h:1479
void(* start_cb)(SoundGenerator< T > *, const void *)
Definition SoundGenerator.h:1478