arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
MozziStream.h
1
2
3#include "AudioTools.h"
4
5// prevent naming conflict with audiotools
6#define AudioOutput AudioOutputMozzi
7#include <Mozzi.h>
8#undef AudioOutput
9
10void updateControl();
11AudioOutputMozzi updateAudio();
12
13namespace audio_tools {
14
16 uint16_t control_rate = CONTROL_RATE;
17 int input_range_from = 0;
18 int input_range_to = 1023;
19 int16_t output_volume = 10;
20};
21
28class MozziStream : public AudioStream, public VolumeSupport {
29 public:
30 MozziStream() = default;
31
32 MozziStream(Stream& in) { setInput(in); }
33
34 MozziConfig defaultConfig() { return cfg; }
35
36 void setAudioInfo(AudioInfo info) { cfg.copyFrom(info); }
37
38 int audioRate() { return cfg.sample_rate; }
39
40 void setInput(Stream& in) { p_input = &in; }
41
42 AudioInfo audioInfo() { return cfg; }
43
44 bool begin(MozziConfig cfg) {
45 this->cfg = cfg;
46 return begin();
47 }
48
49 bool begin() {
50 if (cfg.bits_per_sample != 16) {
51 LOGE("bits_per_sample must be 16 and not %d", cfg.bits_per_sample);
52 return false;
53 }
54
55 // initialize range for input range determination
56 input_min = 32767;
57 input_max = -32768;
58
59 // setup control counter
60 control_counter_max = info.sample_rate / cfg.control_rate;
61 if (control_counter_max <= 0) {
62 control_counter_max = 1;
63 }
64 control_counter = control_counter_max;
65 active = true;
66 return true;
67 }
68
69 void end() { active = false; }
70
72 bool setVolume(int16_t vol) {
73 cfg.output_volume = vol;
74 return VolumeSupport::setVolume(vol);
75 }
76
78 size_t readBytes(uint8_t* data, size_t len) {
79 if (!active) return 0;
80 int samples = len / sizeof(int16_t);
81 int frames = samples / cfg.channels;
82 int16_t* data16 = (int16_t*)data;
83 int idx = 0;
84 for (int j = 0; j < frames; j++) {
85 int16_t sample = nextSample();
86 for (int ch = 0; ch < cfg.channels; ch++) {
87 data16[idx++] = sample;
88 }
89 }
90 return idx * sizeof(int16_t);
91 }
92
94 size_t write(const uint8_t* data, size_t len) {
95 if (!active) return 0;
96 if (buffer.size() == 0) {
97 buffer.resize(len * 2);
98 }
99 return buffer.writeArray(data, len);
100 }
101
106 int16_t result[cfg.channels] = {0};
107 if (p_input != nullptr) {
108 p_input->readBytes((uint8_t*)&result, sizeof(int16_t) * cfg.channels);
109 } else {
110 buffer.readArray((uint8_t*)&result, sizeof(int16_t) * cfg.channels);
111 }
112 // when we have multiple channels we provide the avg value
113 int sample = avg(result);
114 // calculate dynamic range
115 if (sample < input_min) input_min = sample;
116 if (sample > input_max) input_max = sample;
117 int sample1 = map(sample, input_min, input_max, cfg.input_range_from,
118 cfg.input_range_to);
119 return sample1;
120 }
121
122 protected:
123 MozziConfig cfg;
124 int control_counter_max;
125 int control_counter;
126 RingBuffer<uint8_t> buffer{0};
127 Stream* p_input = nullptr;
128 bool active = false;
129 int input_min = 32767;
130 int input_max = -32768;
131
132 int16_t avg(int16_t* values) {
133 int total = 0;
134 for (int ch = 0; ch < cfg.channels; ch++) {
135 total += values[ch];
136 }
137 return total / cfg.channels;
138 }
139
140 int16_t nextSample() {
141 // control update
142 if (--control_counter < 0) {
143 control_counter = control_counter_max;
144 LOGD("updateControl");
145 updateControl();
146 }
147
148 // updateAudio() STANDARD mode is between -244 and 243 inclusive
149 auto result = updateAudio() * cfg.output_volume;
150 // clip result
151 if (result > 32767) result = 32767;
152 if (result < -32768) result = -32768;
153 // Serial.println(result);
154 return result;
155 }
156};
157
158} // namespace audio_tools
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:119
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:37
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:59
Stream that provides audio information that was generated using the Mozzi API using the updateControl...
Definition MozziStream.h:28
bool setVolume(int16_t vol)
Defines the multiplication factor to scale the Mozzi value range to int16_t.
Definition MozziStream.h:72
int getAudioInput()
Definition MozziStream.h:105
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition MozziStream.h:36
AudioInfo audioInfo()
provides the actual input AudioInfo
Definition MozziStream.h:42
size_t readBytes(uint8_t *data, size_t len)
Provides the data filled by calling updateAudio()
Definition MozziStream.h:78
size_t write(const uint8_t *data, size_t len)
Write data to buffer so that we can access them by calling getAudioInput()
Definition MozziStream.h:94
Implements a typed Ringbuffer.
Definition Buffers.h:308
virtual size_t size() override
Returns the maximum capacity of the buffer.
Definition Buffers.h:394
Definition NoArduino.h:142
Supports the setting and getting of the volume.
Definition AudioTypes.h:189
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:194
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
long map(long x, long in_min, long in_max, long out_min, long out_max)
Maps input to output values.
Definition NoArduino.h:188
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:53
void copyFrom(AudioInfo info)
Same as set.
Definition AudioTypes.h:103
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59
Definition MozziStream.h:15