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
584// out of class definition is needed before C++17 (e.g. -std=gnu++14)
585template <class T>
586constexpr int16_t FastIntSineGenerator<T>::sine_table[];
587
590#if PREFER_FIXEDPOINT
591template <class T = int16_t>
592using SineGenerator = FastIntSineGenerator<T>;
593#else
594template <class T = int16_t>
596#endif
597
599template <class T = int16_t>
601
616template <class T = int16_t>
618 public:
619 SquareWaveGenerator(float amplitude = NumberConverter::maxValueT<T>(),
620 float phase = 0.0f) {
621 LOGD("SquareWaveGenerator");
622 setAmplitude(amplitude);
623 setPhase(phase);
624 }
625
626 bool begin() override {
627 TRACEI();
630 return true;
631 }
632
633 bool begin(AudioInfo info) override {
634 LOGI("%s::begin(channels=%d, sample_rate=%d)", "SquareWaveGenerator",
635 (int)info.channels, (int)info.sample_rate);
638 return true;
639 }
640
641 bool begin(AudioInfo info, float frequency) {
643 if (frequency > 0.0f) {
644 setFrequency(frequency);
645 }
646 return true;
647 }
648
649 bool begin(int channels, int sample_rate, float frequency) {
650 SoundGenerator<T>::info.channels = channels;
651 SoundGenerator<T>::info.sample_rate = sample_rate;
652 return begin(SoundGenerator<T>::info, frequency);
653 }
654
659
661 void setFrequency(float frequency) override {
662 LOGI("setFrequency: %.2f", frequency);
663 m_frequency = frequency;
665 }
666
668 void setPhase(float phase) {
669 double turns = phase / (2.0 * PI);
670 m_phase_offset = (uint32_t)(turns * 4294967296.0);
671 }
672
673 void setAmplitude(float amp) {
674 m_amplitude = amp;
675 m_amplitude_i = (int32_t)amp;
676 }
677
679 virtual T readSample() override {
680 uint32_t phase = m_phase_acc + m_phase_offset;
682 // top bit of the phase marks the half of the cycle we're in
683 return (int32_t)phase >= 0 ? (T)m_amplitude_i : (T)(-m_amplitude_i);
684 }
685
686 protected:
687 volatile float m_frequency = 0.0f;
688 float m_amplitude = 1.0f;
689 int32_t m_amplitude_i = 32767;
690 // fixed point (32 bit) phase: wrapping is implicit via unsigned overflow
691 uint32_t m_phase_acc = 0;
692 uint32_t m_phase_offset = 0;
693 uint32_t m_phase_increment = 0;
694
695 // only called from begin()/setFrequency()/setAudioInfo(), never per sample
697 uint32_t sample_rate = SoundGenerator<T>::info.sample_rate;
698 if (sample_rate > 0) {
700 (uint32_t)((double)m_frequency / sample_rate * 4294967296.0);
701 }
702 }
703};
704
720template <class T = int16_t>
722 public:
723 SawToothGenerator(float amplitude = NumberConverter::maxValueT<T>(),
724 float phase = 0.0f) {
725 LOGD("SawToothGenerator");
726 setAmplitude(amplitude);
727 setPhase(phase);
728 }
729
730 bool begin() override {
731 TRACEI();
734 return true;
735 }
736
737 bool begin(AudioInfo info) override {
738 LOGI("%s::begin(channels=%d, sample_rate=%d)", "SawToothGenerator",
739 (int)info.channels, (int)info.sample_rate);
742 return true;
743 }
744
745 bool begin(AudioInfo info, float frequency) {
747 if (frequency > 0.0f) {
748 setFrequency(frequency);
749 }
750 return true;
751 }
752
753 bool begin(int channels, int sample_rate, float frequency) {
754 SoundGenerator<T>::info.channels = channels;
755 SoundGenerator<T>::info.sample_rate = sample_rate;
756 return begin(SoundGenerator<T>::info, frequency);
757 }
758
763
765 void setFrequency(float frequency) override {
766 LOGI("setFrequency: %.2f", frequency);
767 m_frequency = frequency;
769 }
770
772 void setPhase(float phase) {
773 double turns = phase / (2.0 * PI);
774 m_phase_offset = (uint32_t)(turns * 4294967296.0);
775 }
776
777 void setAmplitude(float amp) {
778 m_amplitude = amp;
779 m_amplitude_i = (int32_t)amp;
780 }
781
783 virtual T readSample() override {
784 uint32_t phase = m_phase_acc + m_phase_offset;
786 // reinterpreting the wrapping unsigned phase as signed already gives
787 // a linear ramp from -2^31 to 2^31-1: exactly a saw tooth
788 int32_t ramp = (int32_t)phase;
789 return (T)(((int64_t)ramp * m_amplitude_i) >> 31);
790 }
791
792 protected:
793 volatile float m_frequency = 0.0f;
794 float m_amplitude = 1.0f;
795 int32_t m_amplitude_i = 32767;
796 // fixed point (32 bit) phase: wrapping is implicit via unsigned overflow
797 uint32_t m_phase_acc = 0;
798 uint32_t m_phase_offset = 0;
799 uint32_t m_phase_increment = 0;
800
801 // only called from begin()/setFrequency()/setAudioInfo(), never per sample
803 uint32_t sample_rate = SoundGenerator<T>::info.sample_rate;
804 if (sample_rate > 0) {
806 (uint32_t)((double)m_frequency / sample_rate * 4294967296.0);
807 }
808 }
809};
810
818template <class T = int16_t>
820 public:
823
826
827 protected:
829 // //range : [min, max]
830 int random(int min, int max) { return min + rand() % ((max + 1) - min); }
831};
832
840template <class T = int16_t>
842 public:
845 this->amplitude = amplitude;
846 max_key = 0x1f; // Five bits set
847 key = 0;
848 for (int i = 0; i < 5; i++) white_values[i] = rand() % (amplitude / 5);
849 }
850
853 T last_key = key;
854 unsigned int sum;
855
856 key++;
857 if (key > max_key) key = 0;
858 // Exclusive-Or previous value with current value. This gives
859 // a list of bits that have changed.
860 int diff = last_key ^ key;
861 sum = 0;
862 for (int i = 0; i < 5; i++) {
863 // If bit changed get new random number for corresponding
864 // white_value
865 if (diff & (1 << i)) white_values[i] = rand() % (amplitude / 5);
866 sum += white_values[i];
867 }
868 return sum;
869 }
870
871 protected:
874 unsigned int white_values[5];
875 unsigned int amplitude;
876};
877
887template <class T = int16_t>
889 public:
890 // the scale defines the max value which is generated
891 SilenceGenerator(T value = 0) { this->value = value; }
892
895 return value; // return 0
896 }
897
898 protected:
900};
901
909template <class T = int16_t>
911 public:
915
925 GeneratorFromStream(Stream& input, int channels = 1, float volume = 1.0) {
926 maxValue = NumberConverter::maxValue(sizeof(T) * 8);
927 setStream(input);
930 }
931
933 void setStream(Stream& input) { this->p_stream = &input; }
934
935 void setChannels(int channels) { this->channels = channels; }
936
939 T data = 0;
940 float total = 0;
941 if (p_stream != nullptr) {
942 for (int j = 0; j < channels; j++) {
943 p_stream->readBytes((uint8_t*)&data, sizeof(T));
944 total += data;
945 }
946 float avg = (total / channels) * volume();
947 if (avg > maxValue) {
948 data = maxValue;
949 } else if (avg < -maxValue) {
950 data = -maxValue;
951 } else {
952 data = avg;
953 }
954 }
955 return data;
956 }
957
958 protected:
959 Stream* p_stream = nullptr;
960 int channels = 1;
961 float maxValue;
962};
963
973template <class T = int16_t>
975 public:
989 template <size_t arrayLen>
990 GeneratorFromArray(T (&array)[arrayLen], int repeat = 0,
991 bool setInactiveAtEnd = false, size_t startIndex = 0) {
992 TRACED();
993 this->max_repeat = repeat;
994 this->inactive_at_end = setInactiveAtEnd;
995 this->sound_index = startIndex;
996 setArray(array, arrayLen);
997 }
998
999 template <int arrayLen>
1000 void setArray(T (&array)[arrayLen]) {
1001 TRACED();
1002 setArray(array, arrayLen);
1003 }
1004
1005 void setArray(T* array, size_t size) {
1006 table.resize(size);
1007 for (int j = 0; j < size; j++) {
1008 table[j] = array[j];
1009 }
1010 LOGI("table_length: %d", (int)size);
1011 }
1012
1014 bool begin(AudioInfo info) override {
1016 }
1017
1020 bool rc = begin(info);
1022 return rc;
1023 }
1024
1026 bool begin() override {
1027 TRACEI();
1029 sound_index = 0.0f;
1030 repeat_counter = 0;
1031 is_running = true;
1032 return true;
1033 }
1034
1035 void end() override { table.resize(0); }
1036
1038 T readSample() override {
1039 if (table.size() == 0) {
1040 return 0;
1041 }
1042
1043 if (!this->is_running) {
1044 return 0;
1045 }
1046
1047 const float table_size = static_cast<float>(table.size());
1048
1049 // at end deactivate output
1050 while (sound_index >= table_size) {
1051 // LOGD("reset index - sound_index: %d, table_length:
1052 // %d",sound_index,table_length);
1053 sound_index -= table_size;
1054 // deactivate when count has been used up
1055 if (max_repeat >= 1 && ++repeat_counter >= max_repeat) {
1056 LOGD("atEnd");
1057 this->is_running = false;
1058 if (inactive_at_end) {
1059 this->active = false;
1060 }
1061 return 0;
1062 }
1063 }
1064
1065 // LOGD("index: %d - active: %d", sound_index, this->active);
1066 T result = 0;
1067 if (this->is_running) {
1068 int idx0 = static_cast<int>(sound_index);
1069 int idx1 = idx0 + 1;
1070 if (idx1 >= static_cast<int>(table.size())) {
1071 idx1 = 0;
1072 }
1073 float frac = sound_index - static_cast<float>(idx0);
1074 float sample = static_cast<float>(table[idx0]) * (1.0f - frac) +
1075 static_cast<float>(table[idx1]) * frac;
1076 result = static_cast<T>(sample);
1078 }
1079
1080 return result;
1081 }
1082
1083 // step size the sound index is incremented (default = 1)
1084 void setIncrement(int inc) {
1085 index_increment = inc;
1086 frequency = 0.0f;
1087 }
1088
1090 void setFrequency(float frequency) override {
1091 if (SoundGenerator<T>::audioInfo().sample_rate <= 0 || table.size() == 0) {
1092 LOGE("setFrequency failed: sample_rate=%d table_size=%d",
1093 (int)SoundGenerator<T>::audioInfo().sample_rate, (int)table.size());
1094 return;
1095 }
1096 if (frequency < 0.0f) {
1097 frequency = 0.0f;
1098 }
1099 this->frequency = frequency;
1101 frequency * static_cast<float>(table.size()) /
1102 static_cast<float>(SoundGenerator<T>::audioInfo().sample_rate);
1103 }
1104
1105 // Sets up a sine table - returns the effective frequency
1106 int setupSine(int sampleRate, float reqFrequency, float amplitude = 1.0) {
1107 int sample_count =
1108 static_cast<float>(sampleRate) /
1109 reqFrequency; // e.g. 44100 / 300hz = 147 samples per wave
1110 float angle = 2.0 * PI / sample_count;
1111 table.resize(sample_count);
1112 for (int j = 0; j < sample_count; j++) {
1113 table[j] = sinf(j * angle) * amplitude;
1114 }
1115 // calculate effective frequency
1116 return sampleRate / sample_count;
1117 }
1118
1119 // Similar like is active to check if the array is still playing.
1120 bool isRunning() { return is_running; }
1121
1122 protected:
1123 float sound_index = 0.0f;
1124 int max_repeat = 0;
1126 bool inactive_at_end = false;
1127 bool is_running = false;
1128 bool owns_data = false;
1130 float index_increment = 1.0f;
1131 float frequency = 0.0f;
1132};
1133
1141template <class T = int16_t>
1143 public:
1145
1147
1148 void setValue(T value) { value_set = value; }
1149
1151 bool begin() override {
1152 TRACEI();
1154 is_running = true;
1156 return true;
1157 }
1158
1160 T readSample() override { return value_return; }
1161
1162 // Similar like is active to check if the array is still playing.
1163 bool isRunning() { return is_running; }
1164
1165 protected:
1168 bool is_running = false;
1169};
1170
1178template <class T = int16_t>
1180 public:
1181 SineFromTable(float amplitude = NumberConverter::maxValueT<T>()) {
1182 this->amplitude = amplitude;
1183 this->amplitude_to_be = amplitude;
1184 }
1185
1188
1192
1194 // update angle
1195 angle += step;
1196 if (angle >= 360.0f) {
1197 while (angle >= 360.0f) {
1198 angle -= 360.0f;
1199 }
1200 // update frequency at start of circle (near 0 degrees)
1201 step = step_new;
1202
1204 // amplitude = amplitude_to_be;
1205 }
1206 return interpolate(angle);
1207 }
1208
1209 bool begin() {
1210 is_first = true;
1213 360.0f; // 122.5 hz (at 44100); 61 hz (at 22050)
1214 return true;
1215 }
1216
1217 bool begin(AudioInfo info, float frequency) {
1220 360.0f; // 122.5 hz (at 44100); 61 hz (at 22050)
1221 setFrequency(frequency);
1222 return true;
1223 }
1224
1225 bool begin(int channels, int sample_rate, uint16_t frequency = 0) {
1226 SoundGenerator<T>::info.channels = channels;
1227 SoundGenerator<T>::info.sample_rate = sample_rate;
1228 return begin(SoundGenerator<T>::info, frequency);
1229 }
1230
1231 void setFrequency(float freq) {
1232 step_new = freq / base_frequency;
1233 if (is_first) {
1234 step = step_new;
1235 is_first = false;
1236 }
1237 LOGD("step: %f", step_new);
1238 }
1239
1240 protected:
1241 bool is_first = true;
1244 float max_amplitude_step = 50.0f;
1245 float base_frequency = 1.0f;
1246 float step = 1.0f;
1247 float step_new = 1.0f;
1248 float angle = 0.0f;
1249 // 122.5 hz (at 44100); 61 hz (at 22050)
1250 const float values[181] = {
1251 0, 0.0174524, 0.0348995, 0.052336, 0.0697565, 0.0871557,
1252 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
1253 0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
1254 0.309017, 0.325568, 0.34202, 0.358368, 0.374607, 0.390731,
1255 0.406737, 0.422618, 0.438371, 0.45399, 0.469472, 0.48481,
1256 0.5, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
1257 0.587785, 0.601815, 0.615661, 0.62932, 0.642788, 0.656059,
1258 0.669131, 0.681998, 0.694658, 0.707107, 0.71934, 0.731354,
1259 0.743145, 0.75471, 0.766044, 0.777146, 0.788011, 0.798636,
1260 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
1261 0.866025, 0.87462, 0.882948, 0.891007, 0.898794, 0.906308,
1262 0.913545, 0.920505, 0.927184, 0.93358, 0.939693, 0.945519,
1263 0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.97437,
1264 0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
1265 0.994522, 0.996195, 0.997564, 0.99863, 0.999391, 0.999848,
1266 1, 0.999848, 0.999391, 0.99863, 0.997564, 0.996195,
1267 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
1268 0.978148, 0.97437, 0.970296, 0.965926, 0.961262, 0.956305,
1269 0.951057, 0.945519, 0.939693, 0.93358, 0.927184, 0.920505,
1270 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.87462,
1271 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
1272 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.75471,
1273 0.743145, 0.731354, 0.71934, 0.707107, 0.694658, 0.681998,
1274 0.669131, 0.656059, 0.642788, 0.62932, 0.615661, 0.601815,
1275 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
1276 0.5, 0.48481, 0.469472, 0.45399, 0.438371, 0.422618,
1277 0.406737, 0.390731, 0.374607, 0.358368, 0.34202, 0.325568,
1278 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
1279 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
1280 0.104528, 0.0871557, 0.0697565, 0.052336, 0.0348995, 0.0174524,
1281 0};
1282
1284 bool positive = (angle <= 180.0f);
1285 float angle_positive = positive ? angle : angle - 180.0f;
1286 int angle_int1 = angle_positive;
1287 int angle_int2 = angle_int1 + 1;
1288 T v1 = values[angle_int1] * amplitude;
1289 T v2 = values[angle_int2] * amplitude;
1290 T result = v1 < v2 ? map(angle_positive, angle_int1, angle_int2, v1, v2)
1291 : map(angle_positive, angle_int1, angle_int2, v2, v1);
1292 // float result = v1;
1293 return positive ? result : -result;
1294 }
1295
1296 T map(T x, T in_min, T in_max, T out_min, T out_max) {
1297 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
1298 }
1299
1301 float diff = amplitude_to_be - amplitude;
1302 if (abs(diff) > max_amplitude_step) {
1303 diff = (diff < 0) ? -max_amplitude_step : max_amplitude_step;
1304 }
1305 if (abs(diff) >= 1.0f) {
1306 amplitude += diff;
1307 }
1308 }
1309};
1310
1319template <class T = int16_t>
1321 public:
1322 GeneratorMixer() = default;
1323
1324 void add(SoundGenerator<T>& generator) { vector.push_back(&generator); }
1325 void add(SoundGenerator<T>* generator) { vector.push_back(generator); }
1326
1327 void clear() { vector.clear(); }
1328
1330 float total = 0.0f;
1331 float count = 0.0f;
1332 for (auto& generator : vector) {
1333 if (generator->isActive()) {
1334 T sample = generator->readSample();
1335 total += sample;
1336 count += 1.0f;
1337 }
1338 }
1339 return count > 0.0f ? total / count : 0;
1340 }
1341
1342 protected:
1345};
1346
1355template <class T = int16_t>
1357 public:
1358 TestGenerator(T max = 1000, T inc = 1) { this->max = max; }
1359
1360 T readSample() override {
1361 value += inc;
1362 if (abs(value) >= max) {
1363 inc = -inc;
1364 value += (inc * 2);
1365 }
1366 return value;
1367 }
1368
1369 protected:
1371 T value = 0;
1372 T inc = 1;
1373};
1374
1383template <class T = int16_t>
1385public:
1386 virtual bool begin(uint16_t queue_size=256) {
1387 return queue.resize(queue_size) && SoundGenerator<T>::begin();
1388 }
1389
1390 virtual void end() override { SoundGenerator<T>::end(); clear(); }
1391
1392 // Returns the requested number of bytes from the current generator.
1393 // If the current generator runs out of bytes before the buffer is filled,
1394 // it will move to the next queued generator. If there are no more generators,
1395 // it will stop filling the buffer and return the number of bytes it was able to fill.
1396 virtual size_t readBytes(uint8_t *buffer, size_t buf_len) override {
1397 LOGD("readBytes: %d", (int)buf_len);
1398 if (!SoundGenerator<T>::active) return 0;
1399 if (queue.available() == 0) return 0; // Nothing in the queue.
1400
1401 size_t bytes_read = 0;
1402 size_t ret = 0;
1403 SoundGenerator<T> *current_generator = nullptr;
1404
1405 while (bytes_read < buf_len) {
1406 if ((current_generator = getCurrentGenerator()) == nullptr) break; // No generator.
1407
1408 ret = current_generator->readBytes(buffer+bytes_read, buf_len-bytes_read);
1409 bytes_read += ret;
1410
1411 if (ret == 0) {
1412 // Done with this generator, move to the next one.
1414 if (queue.available() == 0) break; // No more generators
1415 }
1416 }
1417 return bytes_read;
1418 }
1419
1420 // If no bytes are available, will return 0.
1421 virtual T readSample() override {
1422 T buf;
1423 if (readBytes((uint8_t *)&buf, sizeof(T)) != sizeof(T)) return (T)0;
1424 return buf;
1425 }
1426
1427 virtual inline size_t readSamples(T* data, size_t len) override {
1428 return (readBytes((uint8_t *)data, len*sizeof(T)) / sizeof(T));
1429 }
1430
1431 // Add a generator to the queue. The generator MUST be time limited BEFORE adding
1432 // to the queue (eg: calling setPlayTime()). Otherwise, the generator will never
1433 // run out of bytes and nothing after it will ever play.
1434 // Callbacks are called in the context of read*() methods, so you probably want them
1435 // to be quick and not block on anything.
1437 void (*start_cb)(SoundGenerator<T> *, const void *) = nullptr,
1438 void (*end_cb)(SoundGenerator<T> *, const void *) = nullptr,
1439 const void *cb_data = nullptr
1440 ) {
1441 LOGD("pushGenerator()");
1442 if (queue.availableForWrite() == 0) return false; // Queue is full.
1443
1444 QNode *node = new QNode(gen, start_cb, end_cb, cb_data); // Deleted in removeCurrentGenerator;
1445 if (node == nullptr) return false; // new failed
1446
1447 if (!queue.write(node)) {
1448 delete node;
1449 return false;
1450 }
1451 return true;
1452 }
1453
1454 // GeneratorQueue doesn't do everything other generators do. We rely on the
1455 // queued SoundGenerators to do any shaping.
1456 virtual inline void setPlayTime(uint32_t p, uint8_t u = 20, uint8_t d = 30) override {
1457 LOGW("GeneratorQueue::setPlayTime() does nothing.");
1458 }
1459 virtual inline void setFrequency(float f) override {
1460 LOGW("GeneratorQueue::setFrequency() does nothing.");
1461 }
1462
1464 QNode *node;
1465 if (!queue.peek(node)) return nullptr;
1466 return node->generator;
1467 }
1468
1469 virtual bool clear() {
1470 while (removeCurrentGenerator()) {}; // Deletes all the QNodes.
1471 return queue.available() == 0;
1472 }
1473
1474 virtual inline size_t size() { return queue.available(); }
1475 virtual inline size_t available() { return queue.available(); }
1476 virtual inline size_t availableForWrite() { return queue.availableForWrite(); }
1477 virtual inline bool empty() { return queue.available() == 0; }
1478
1479protected:
1480 struct QNode {
1482 void (*start_cb)(SoundGenerator<T> *, const void *);
1483 void (*end_cb)(SoundGenerator<T> *, const void *);
1484 const void *cb_data;
1486 QNode(SoundGenerator<T> *g, void (*s)(SoundGenerator<T> *, const void *), void (*e)(SoundGenerator<T> *, const void *), const void *d) :
1487 generator(g), start_cb(s), end_cb(e), cb_data(d) { restarted=false; }
1488 };
1489
1491
1492 // Returns the SoundGenerator at the head of the queue,
1493 // restarting it if it hasn't been restarted yet.
1495 if (queue.available() == 0) return nullptr;
1496
1497 QNode *node = nullptr;
1498 if (!queue.peek(node) || node == nullptr) return nullptr;
1499
1500 if (!node->restarted) {
1501 if (node->start_cb) {
1502 node->start_cb(node->generator, node->cb_data);
1503 }
1504 node->generator->restart();
1505 node->restarted = true; // persistent dynamic objects, this will persist.
1506 }
1507 return node->generator;
1508 }
1509
1510 // Removes the current SoundGenerator from the queue, and cleans up memory use.
1512 if (queue.available() == 0) return false;
1513
1514 QNode *node = nullptr;
1515 bool ret = queue.read(node);
1516 if (node != nullptr) {
1517 if (node->end_cb) {
1518 node->end_cb(node->generator, node->cb_data);
1519 }
1520 delete node;
1521 }
1522 return ret;
1523 }
1524
1525 // readBytes(), readSample(), and readSamples() have all been reimplemented above
1526 // and do not use readBytesFrames(), so this will never be called. But it's not
1527 // virtual in SoundGenerator so I can't overwrite it.
1528 //size_t readBytesFrames(uint8_t *b, size_t l, int f, int c) {
1529 // LOGE("GeneratorQueue::readBytesFrames() should never get called.");
1530 // return 0;
1531 //}
1532
1533};
1534
1535
1536
1537} // 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
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
static constexpr int16_t sine_table[kTableSize]
Definition SoundGenerator.h:555
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:1142
T value_set
Definition SoundGenerator.h:1166
bool isRunning()
Definition SoundGenerator.h:1163
virtual bool begin(AudioInfo info)
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:1146
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1160
bool is_running
Definition SoundGenerator.h:1168
bool begin() override
Starts the generation of samples.
Definition SoundGenerator.h:1151
T value_return
Definition SoundGenerator.h:1167
void setValue(T value)
Definition SoundGenerator.h:1148
We generate the samples from an array which is provided in the constructor.
Definition SoundGenerator.h:974
void setFrequency(float frequency) override
Defines the output frequency based on sample rate and table size.
Definition SoundGenerator.h:1090
void setIncrement(int inc)
Definition SoundGenerator.h:1084
int setupSine(int sampleRate, float reqFrequency, float amplitude=1.0)
Definition SoundGenerator.h:1106
bool isRunning()
Definition SoundGenerator.h:1120
bool inactive_at_end
Definition SoundGenerator.h:1126
Vector< T > table
Definition SoundGenerator.h:1129
void end() override
Definition SoundGenerator.h:1035
float sound_index
Definition SoundGenerator.h:1123
void setArray(T *array, size_t size)
Definition SoundGenerator.h:1005
float index_increment
Definition SoundGenerator.h:1130
GeneratorFromArray(T(&array)[arrayLen], int repeat=0, bool setInactiveAtEnd=false, size_t startIndex=0)
Construct a new Generator from an array.
Definition SoundGenerator.h:990
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1038
bool is_running
Definition SoundGenerator.h:1127
int max_repeat
Definition SoundGenerator.h:1124
bool owns_data
Definition SoundGenerator.h:1128
int repeat_counter
Definition SoundGenerator.h:1125
bool begin(AudioInfo info) override
Starts the generation of samples with the provided AudioInfo.
Definition SoundGenerator.h:1014
bool begin() override
Starts the generation of samples.
Definition SoundGenerator.h:1026
float frequency
Definition SoundGenerator.h:1131
bool begin(AudioInfo info, float frequency)
Starts the generation of samples with the provided AudioInfo and frequency.
Definition SoundGenerator.h:1019
void setArray(T(&array)[arrayLen])
Definition SoundGenerator.h:1000
An Adapter Class which lets you use any Stream as a Generator.
Definition SoundGenerator.h:910
int channels
Definition SoundGenerator.h:960
GeneratorFromStream()
Definition SoundGenerator.h:912
Stream * p_stream
Definition SoundGenerator.h:959
void setStream(Stream &input)
(Re-)Assigns a stream to the Adapter class
Definition SoundGenerator.h:933
void setChannels(int channels)
Definition SoundGenerator.h:935
float maxValue
Definition SoundGenerator.h:961
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:925
T readSample()
Provides a single sample from the stream.
Definition SoundGenerator.h:938
Generator which combines (mixes) multiple sound generators into one output.
Definition SoundGenerator.h:1320
void add(SoundGenerator< T > *generator)
Definition SoundGenerator.h:1325
Vector< SoundGenerator< T > * > vector
Definition SoundGenerator.h:1343
int actualChannel
Definition SoundGenerator.h:1344
void clear()
Definition SoundGenerator.h:1327
T readSample()
Provides a single sample.
Definition SoundGenerator.h:1329
void add(SoundGenerator< T > &generator)
Definition SoundGenerator.h:1324
Queues SoundGenerators and plays them sequentially. Queued SoundGenerators must be limited (eg: setPl...
Definition SoundGenerator.h:1384
virtual size_t availableForWrite()
Definition SoundGenerator.h:1476
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:1456
virtual SoundGenerator< T > * peek()
Definition SoundGenerator.h:1463
virtual bool begin(uint16_t queue_size=256)
Definition SoundGenerator.h:1386
virtual bool clear()
Definition SoundGenerator.h:1469
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:1396
SoundGenerator< T > * getCurrentGenerator()
Definition SoundGenerator.h:1494
virtual bool empty()
Definition SoundGenerator.h:1477
virtual T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1421
virtual size_t available()
Definition SoundGenerator.h:1475
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:1436
bool removeCurrentGenerator()
Definition SoundGenerator.h:1511
virtual size_t size()
Definition SoundGenerator.h:1474
virtual size_t readSamples(T *data, size_t len) override
Definition SoundGenerator.h:1427
virtual void end() override
Definition SoundGenerator.h:1390
virtual void setFrequency(float f) override
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:1459
RingBufferSPSC< QNode * > queue
Definition SoundGenerator.h:1490
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:841
PinkNoiseGenerator(T amplitude=32767)
the amplitude defines the max value which is generated
Definition SoundGenerator.h:844
T key
Definition SoundGenerator.h:873
unsigned int amplitude
Definition SoundGenerator.h:875
T max_key
Definition SoundGenerator.h:872
unsigned int white_values[5]
Definition SoundGenerator.h:874
T readSample()
Provides a single sample.
Definition SoundGenerator.h:852
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:721
void updatePhaseIncrement()
Definition SoundGenerator.h:802
void setFrequency(float frequency) override
Defines the frequency - the only place where float math is used.
Definition SoundGenerator.h:765
void setAmplitude(float amp)
Definition SoundGenerator.h:777
uint32_t m_phase_increment
Definition SoundGenerator.h:799
virtual T readSample() override
Provides a single sample - integer only, no float ops!
Definition SoundGenerator.h:783
volatile float m_frequency
Definition SoundGenerator.h:793
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:753
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:759
SawToothGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:723
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:737
bool begin() override
Starts the processing.
Definition SoundGenerator.h:730
uint32_t m_phase_acc
Definition SoundGenerator.h:797
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:745
void setPhase(float phase)
Defines the starting phase in radians.
Definition SoundGenerator.h:772
uint32_t m_phase_offset
Definition SoundGenerator.h:798
int32_t m_amplitude_i
Definition SoundGenerator.h:795
float m_amplitude
Definition SoundGenerator.h:794
Provides a fixed value (e.g. 0) as sound data. This can be used e.g. to test the output functionality...
Definition SoundGenerator.h:888
SilenceGenerator(T value=0)
Definition SoundGenerator.h:891
T value
Definition SoundGenerator.h:899
T readSample()
Provides a single sample.
Definition SoundGenerator.h:894
A sine generator based on a table. The table is created using degrees where one full wave is 360 degr...
Definition SoundGenerator.h:1179
float amplitude
Definition SoundGenerator.h:1242
T interpolate(float angle)
Definition SoundGenerator.h:1283
float base_frequency
Definition SoundGenerator.h:1245
const float values[181]
Definition SoundGenerator.h:1250
T map(T x, T in_min, T in_max, T out_min, T out_max)
Definition SoundGenerator.h:1296
void updateAmplitudeInSteps()
Definition SoundGenerator.h:1300
bool is_first
Definition SoundGenerator.h:1241
float step_new
Definition SoundGenerator.h:1247
bool begin()
Starts the processing.
Definition SoundGenerator.h:1209
bool begin(int channels, int sample_rate, uint16_t frequency=0)
Definition SoundGenerator.h:1225
void setFrequency(float freq)
Abstract method: not implemented! Just provides an error message...
Definition SoundGenerator.h:1231
float step
Definition SoundGenerator.h:1246
float amplitude_to_be
Definition SoundGenerator.h:1243
float angle
Definition SoundGenerator.h:1248
float max_amplitude_step
Definition SoundGenerator.h:1244
void setAmplitude(float amplitude)
Defines the new amplitude (volume)
Definition SoundGenerator.h:1187
void setMaxAmplitudeStep(float step)
Definition SoundGenerator.h:1191
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:1217
T readSample()
Provides a single sample.
Definition SoundGenerator.h:1193
SineFromTable(float amplitude=NumberConverter::maxValueT< T >())
Definition SoundGenerator.h:1181
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:617
SquareWaveGenerator(float amplitude=NumberConverter::maxValueT< T >(), float phase=0.0f)
Definition SoundGenerator.h:619
void updatePhaseIncrement()
Definition SoundGenerator.h:696
void setFrequency(float frequency) override
Defines the frequency - the only place where float math is used.
Definition SoundGenerator.h:661
void setAmplitude(float amp)
Definition SoundGenerator.h:673
uint32_t m_phase_increment
Definition SoundGenerator.h:693
virtual T readSample() override
Provides a single sample - integer only, no float ops!
Definition SoundGenerator.h:679
volatile float m_frequency
Definition SoundGenerator.h:687
bool begin(int channels, int sample_rate, float frequency)
Definition SoundGenerator.h:649
virtual void setAudioInfo(AudioInfo info) override
Defines/updates the AudioInfo.
Definition SoundGenerator.h:655
bool begin(AudioInfo info) override
Starts the processing with the provided AudioInfo.
Definition SoundGenerator.h:633
bool begin() override
Starts the processing.
Definition SoundGenerator.h:626
uint32_t m_phase_acc
Definition SoundGenerator.h:691
bool begin(AudioInfo info, float frequency)
Definition SoundGenerator.h:641
void setPhase(float phase)
Defines the starting phase in radians.
Definition SoundGenerator.h:668
uint32_t m_phase_offset
Definition SoundGenerator.h:692
int32_t m_amplitude_i
Definition SoundGenerator.h:689
float m_amplitude
Definition SoundGenerator.h:688
Generates a test signal which is easy to check because the values are incremented or decremented by 1...
Definition SoundGenerator.h:1356
T inc
Definition SoundGenerator.h:1372
T value
Definition SoundGenerator.h:1371
T max
Definition SoundGenerator.h:1370
T readSample() override
Provides a single sample.
Definition SoundGenerator.h:1360
TestGenerator(T max=1000, T inc=1)
Definition SoundGenerator.h:1358
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:819
T amplitude
Definition SoundGenerator.h:828
WhiteNoiseGenerator(T amplitude=32767)
the scale defines the max value which is generated
Definition SoundGenerator.h:822
int random(int min, int max)
Definition SoundGenerator.h:830
T readSample()
Provides a single sample.
Definition SoundGenerator.h:825
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6
FloatSineGenerator< T > SineGenerator
Definition SoundGenerator.h:595
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:1480
const void * cb_data
Definition SoundGenerator.h:1484
bool restarted
Definition SoundGenerator.h:1485
SoundGenerator< T > * generator
Definition SoundGenerator.h:1481
QNode(SoundGenerator< T > *g, void(*s)(SoundGenerator< T > *, const void *), void(*e)(SoundGenerator< T > *, const void *), const void *d)
Definition SoundGenerator.h:1486
void(* end_cb)(SoundGenerator< T > *, const void *)
Definition SoundGenerator.h:1483
void(* start_cb)(SoundGenerator< T > *, const void *)
Definition SoundGenerator.h:1482