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