39 virtual bool begin() {
42 activeWarningIssued =
false;
43 info.logInfo(
"SoundGenerator:");
52 virtual void end() { active =
false; }
62 virtual size_t readBytes(uint8_t* data,
size_t len) {
63 LOGD(
"readBytes: %d", (
int)len);
64 if (!active)
return 0;
66 int frame_size =
sizeof(T) * channels;
67 int frames = len / frame_size;
68 if (len >= frame_size) {
69 return readBytesFrames(data, len, frames, channels);
71 return readBytesFromBuffer(data, len, frame_size, channels);
83 LOGE(
"setFrequency not supported");
93 LOGE(
"invalid bits_per_sample: %d", info.
channels);
95 recalculatePlayTime();
98 void setPlayTime(uint32_t playMs, uint8_t upPercent = 20,
99 uint8_t downPercent = 30) {
100 LOGI(
"setPlayTime: playMs=%d, upPercent=%d, downPercent=%d", playMs,
101 upPercent, downPercent);
102 this->playMs = playMs;
103 this->upPercent = upPercent;
104 this->downPercent = downPercent;
106 recalculatePlayTime();
112 bool activeWarningIssued =
false;
115 RingBuffer<uint8_t> ring_buffer{0};
117 uint8_t upPercent = 5;
118 uint8_t downPercent = 40;
119 uint32_t playSamples = 0;
120 uint32_t upSamples = 0;
121 uint32_t rampDownSamples = 0;
122 float rampUpInc = 0.0;
123 float rampDownDec = 0.0;
125 uint32_t currentSample = 0;
127 void recalculatePlayTime() {
128 if (upPercent + downPercent > 100) {
129 downPercent = 100 - upPercent;
132 upSamples = (playSamples * upPercent) / 100;
133 rampDownSamples = (playSamples * downPercent) / 100;
136 rampUpInc = 1.0f / upSamples;
139 if (rampDownSamples > 0) {
140 rampDownDec = 1.0f / rampDownSamples;
144 size_t readBytesFrames(uint8_t* buffer,
size_t lengthBytes,
int frames,
146 T* result_buffer = (T*)buffer;
147 int frames_written = 0;
148 if (playMs > 0 && currentSample > playSamples) {
152 for (
int j = 0; j < frames; j++) {
158 sample = applyRamp(sample);
161 for (
int ch = 0; ch < channels; ch++) {
162 *result_buffer++ = sample;
167 if (playMs > 0 && currentSample > playSamples) {
171 return frames_written *
sizeof(T) * channels;
175 T applyRamp(T sample) {
177 if (rampUpInc > 0 && currentSample <= upSamples) {
184 else if (rampDownDec > 0 && currentSample >= playSamples - rampDownSamples) {
185 factor -= rampDownDec;
194 return (T)(factor * sample);
197 size_t readBytesFromBuffer(uint8_t* buffer,
size_t lengthBytes,
198 int frame_size,
int channels) {
200 if (ring_buffer.isEmpty()) {
201 uint8_t tmp[frame_size];
202 readBytesFrames(tmp, frame_size, 1, channels);
206 return ring_buffer.
readArray(buffer, lengthBytes);
734 this->amplitude = amplitude;
735 this->amplitude_to_be = amplitude;
739 void setAmplitude(
float amplitude) { this->amplitude_to_be = amplitude; }
748 if (angle >= 360.0f) {
749 while (angle >= 360.0f) {
755 updateAmplitudeInSteps();
758 return interpolate(angle);
769 bool begin(AudioInfo info,
float frequency) {
770 SoundGenerator<T>::begin(info);
777 bool begin(
int channels,
int sample_rate, uint16_t frequency = 0) {
778 SoundGenerator<T>::info.channels = channels;
779 SoundGenerator<T>::info.sample_rate = sample_rate;
780 return begin(SoundGenerator<T>::info, frequency);
784 step_new = freq / base_frequency;
789 LOGD(
"step: %f", step_new);
793 bool is_first =
true;
795 float amplitude_to_be;
796 float max_amplitude_step = 50.0f;
797 float base_frequency = 1.0f;
799 float step_new = 1.0f;
802 const float values[181] = {
803 0, 0.0174524, 0.0348995, 0.052336, 0.0697565, 0.0871557,
804 0.104528, 0.121869, 0.139173, 0.156434, 0.173648, 0.190809,
805 0.207912, 0.224951, 0.241922, 0.258819, 0.275637, 0.292372,
806 0.309017, 0.325568, 0.34202, 0.358368, 0.374607, 0.390731,
807 0.406737, 0.422618, 0.438371, 0.45399, 0.469472, 0.48481,
808 0.5, 0.515038, 0.529919, 0.544639, 0.559193, 0.573576,
809 0.587785, 0.601815, 0.615661, 0.62932, 0.642788, 0.656059,
810 0.669131, 0.681998, 0.694658, 0.707107, 0.71934, 0.731354,
811 0.743145, 0.75471, 0.766044, 0.777146, 0.788011, 0.798636,
812 0.809017, 0.819152, 0.829038, 0.838671, 0.848048, 0.857167,
813 0.866025, 0.87462, 0.882948, 0.891007, 0.898794, 0.906308,
814 0.913545, 0.920505, 0.927184, 0.93358, 0.939693, 0.945519,
815 0.951057, 0.956305, 0.961262, 0.965926, 0.970296, 0.97437,
816 0.978148, 0.981627, 0.984808, 0.987688, 0.990268, 0.992546,
817 0.994522, 0.996195, 0.997564, 0.99863, 0.999391, 0.999848,
818 1, 0.999848, 0.999391, 0.99863, 0.997564, 0.996195,
819 0.994522, 0.992546, 0.990268, 0.987688, 0.984808, 0.981627,
820 0.978148, 0.97437, 0.970296, 0.965926, 0.961262, 0.956305,
821 0.951057, 0.945519, 0.939693, 0.93358, 0.927184, 0.920505,
822 0.913545, 0.906308, 0.898794, 0.891007, 0.882948, 0.87462,
823 0.866025, 0.857167, 0.848048, 0.838671, 0.829038, 0.819152,
824 0.809017, 0.798636, 0.788011, 0.777146, 0.766044, 0.75471,
825 0.743145, 0.731354, 0.71934, 0.707107, 0.694658, 0.681998,
826 0.669131, 0.656059, 0.642788, 0.62932, 0.615661, 0.601815,
827 0.587785, 0.573576, 0.559193, 0.544639, 0.529919, 0.515038,
828 0.5, 0.48481, 0.469472, 0.45399, 0.438371, 0.422618,
829 0.406737, 0.390731, 0.374607, 0.358368, 0.34202, 0.325568,
830 0.309017, 0.292372, 0.275637, 0.258819, 0.241922, 0.224951,
831 0.207912, 0.190809, 0.173648, 0.156434, 0.139173, 0.121869,
832 0.104528, 0.0871557, 0.0697565, 0.052336, 0.0348995, 0.0174524,
835 T interpolate(
float angle) {
836 bool positive = (angle <= 180.0f);
837 float angle_positive = positive ? angle : angle - 180.0f;
838 int angle_int1 = angle_positive;
839 int angle_int2 = angle_int1 + 1;
840 T v1 = values[angle_int1] * amplitude;
841 T v2 = values[angle_int2] * amplitude;
842 T result = v1 < v2 ? map(angle_positive, angle_int1, angle_int2, v1, v2)
843 : map(angle_positive, angle_int1, angle_int2, v2, v1);
845 return positive ? result : -result;
848 T map(T x, T in_min, T in_max, T out_min, T out_max) {
849 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
852 void updateAmplitudeInSteps() {
853 float diff = amplitude_to_be - amplitude;
854 if (abs(diff) > max_amplitude_step) {
855 diff = (diff < 0) ? -max_amplitude_step : max_amplitude_step;
857 if (abs(diff) >= 1.0f) {