arduino-audio-tools
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 
10 void updateControl();
11 AudioOutputMozzi updateAudio();
12 
13 namespace 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 
28 class 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:109
virtual int readArray(T data[], int len)
reads multiple values
Definition: Buffers.h:41
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition: Buffers.h:65
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
virtual size_t size()
Returns the maximum capacity of the buffer.
Definition: Buffers.h:383
Definition: NoArduino.h:125
Supports the setting and getting of the volume.
Definition: AudioTypes.h:207
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition: AudioTypes.h:212
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:859
long map(long x, long in_min, long in_max, long out_min, long out_max)
Maps input to output values.
Definition: NoArduino.h:162
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:52
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:107
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:55
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