Skip to content

Commit 737268d

Browse files
committed
Logging
1 parent 2c2c5fe commit 737268d

File tree

22 files changed

+117812
-50
lines changed

22 files changed

+117812
-50
lines changed

.vscode/settings.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@
1313
"vec3f": "cpp",
1414
"vec4d": "cpp",
1515
"vec4f": "cpp",
16-
"tuple": "cpp"
16+
"tuple": "cpp",
17+
"deque": "cpp",
18+
"list": "cpp",
19+
"string": "cpp",
20+
"vector": "cpp",
21+
"hash_map": "cpp",
22+
"array": "cpp",
23+
"hashtable": "cpp",
24+
"unordered_map": "cpp",
25+
"unordered_set": "cpp",
26+
"initializer_list": "cpp",
27+
"ranges": "cpp",
28+
"mixinvector": "cpp",
29+
"type_traits": "cpp",
30+
"utility": "cpp",
31+
"optional": "cpp",
32+
"istream": "cpp",
33+
"ratio": "cpp",
34+
"system_error": "cpp",
35+
"valueobject": "cpp"
1736
}
1837
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ We also provide plenty of examples that demonstrate how to implement the differe
1919
As “Audio Sources” we will have e.g.:
2020

2121
- Analog Microphones – [AnalogAudioStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_analog_audio_stream.html)
22-
- Digital Microphonse[I2SStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_i2_s_stream.html)
22+
- Digital Microphones[I2SStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_i2_s_stream.html)
2323
- Files on the Internet – [UrlStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_url_stream.html)
2424
- Generated Sound – [GeneratedSoundStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_generated_sound_stream.html)
2525
- Mobile Phone A2DP Bluetooth – [A2DPStream](https://pschatzmann.github.io/arduino-audio-tools/html/classaudio__tools_1_1_a2_d_p_stream.html)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Decoding a WAV file
2+
3+
In this example we decode a WAV file into RAW output and send it to a PWM pin on a Raspberry Pico
4+
5+
MemoryStream -> AudioOutputStream -> WAVDecoder -> AudioPWM
6+
7+
For the time beeing we just have an impelemntation of AudioPWM for the Rasperry Pico. But it should be possible to extend in to others as well in the future....

examples/streams-memory_wav-pwm/knghtsng.h

Lines changed: 117031 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* @file stream-memory_wav-pwm.ino
3+
* @author Phil Schatzmann
4+
* @brief decode WAV stream and output to PWM pins
5+
* @version 0.1
6+
* @date 2021-01-24
7+
*
8+
* @copyright Copyright (c) 2021
9+
*/
10+
11+
#include "AudioTools.h"
12+
#include "CodecWAV.h"
13+
#include "knghtsng.h"
14+
15+
using namespace audio_tools;
16+
17+
// MemoryStream -> AudioOutputStream -> WAVDecoder -> CsvStream
18+
MemoryStream wav(knghtsng_wav, knghtsng_wav_len);
19+
AudioPWM<int16_t> pwm; // PWM output
20+
WAVDecoder decoder(pwm); // decode wav to pcm and send it to printer
21+
AudioOutputStream out(decoder); // output to decoder
22+
StreamCopy copier(out, wav); // copy in to out
23+
24+
void setup(){
25+
Serial.begin(115200);
26+
AudioLogger::instance().begin(Serial, AudioLogger::Debug);
27+
28+
// setup pwm output
29+
PWMConfig config = pwm.defaultConfig();
30+
config.channels = 1;
31+
config.sample_rate = 1000;
32+
pwm.begin(config);
33+
}
34+
35+
void loop(){
36+
if (wav) {
37+
copier.copy();
38+
} else {
39+
// after we are done we just print some info form the wav file
40+
auto info = decoder.audioInfo();
41+
LOGI("The audio rate from the wav file is %d", info.sample_rate);
42+
LOGI("The channels from the wav file is %d", info.channels);
43+
stop();
44+
}
45+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* @file streams-generator-a2dp.ino
3+
* @author Phil Schatzmann
4+
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-generator-a2dp/README.md
5+
*
6+
* @author Phil Schatzmann
7+
* @copyright GPLv3
8+
*
9+
*/
10+
#include "AudioTools.h"
11+
#include "AudioWebServer.h"
12+
#include "AudioMozzi.h"
13+
#include <Oscil.h>
14+
#include <tables/cos2048_int8.h> // table for Oscils to play
15+
#include <mozzi_fixmath.h>
16+
#include <EventDelay.h>
17+
#include <mozzi_rand.h>
18+
#include <mozzi_midi.h>
19+
#include "WiFi.h"
20+
21+
using namespace audio_tools;
22+
23+
typedef int16_t sound_t; // sound will be represented as int16_t (with 2 bytes)
24+
uint8_t channels = 2; // The stream will have 2 channels
25+
MozziGenerator mozzi(CONTROL_RATE); // subclass of SoundGenerator
26+
GeneratedSoundStream<sound_t> in(mozzi, channels); // Stream generated with mozzi
27+
AudioWebServer server;
28+
29+
/// Copied from AMsynth.ino
30+
#define CONTROL_RATE 64 // Hz, powers of 2 are most reliable
31+
32+
// audio oscils
33+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier(COS2048_DATA);
34+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModulator(COS2048_DATA);
35+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModDepth(COS2048_DATA);
36+
37+
// for scheduling note changes in updateControl()
38+
EventDelay kNoteChangeDelay;
39+
40+
// synthesis parameters in fixed point formats
41+
Q8n8 ratio; // unsigned int with 8 integer bits and 8 fractional bits
42+
Q24n8 carrier_freq; // unsigned long with 24 integer bits and 8 fractional bits
43+
Q24n8 mod_freq; // unsigned long with 24 integer bits and 8 fractional bits
44+
45+
// for random notes
46+
Q8n0 octave_start_note = 42;
47+
48+
49+
void setup(){
50+
Serial.begin(115200);
51+
AudioLogger::instance().begin(Serial, AudioLogger::Info);
52+
53+
// connect to WIFI
54+
WiFi.begin("Phil Schatzmann", "sabrina01");
55+
while (WiFi.status() != WL_CONNECTED){
56+
Serial.print(".");
57+
delay(500);
58+
}
59+
Serial.println();
60+
Serial.print("Connect to http://");
61+
Serial.print(WiFi.localIP());
62+
63+
// We send the test signal via A2DP - so we conect to the MyMusic Bluetooth Speaker
64+
server.begin(in, AUDIO_RATE, mozzi.config().sample_rate);
65+
66+
// Start Mozzi
67+
ratio = float_to_Q8n8(3.0f); // define modulation ratio in float and convert to fixed-point
68+
kNoteChangeDelay.set(200); // note duration ms, within resolution of CONTROL_RATE
69+
aModDepth.setFreq(13.f); // vary mod depth to highlight am effects
70+
randSeed(); // reseed the random generator for different results each time the sketch runs
71+
in.begin();
72+
}
73+
74+
void updateControl(){
75+
static Q16n16 last_note = octave_start_note;
76+
77+
if(kNoteChangeDelay.ready()){
78+
79+
// change octave now and then
80+
if(rand((byte)5)==0){
81+
last_note = 36+(rand((byte)6)*12);
82+
}
83+
84+
// change step up or down a semitone occasionally
85+
if(rand((byte)13)==0){
86+
last_note += 1-rand((byte)3);
87+
}
88+
89+
// change modulation ratio now and then
90+
if(rand((byte)5)==0){
91+
ratio = ((Q8n8) 1+ rand((byte)5)) <<8;
92+
}
93+
94+
// sometimes add a fractionto the ratio
95+
if(rand((byte)5)==0){
96+
ratio += rand((byte)255);
97+
}
98+
99+
// step up or down 3 semitones (or 0)
100+
last_note += 3 * (1-rand((byte)3));
101+
102+
// convert midi to frequency
103+
Q16n16 midi_note = Q8n0_to_Q16n16(last_note);
104+
carrier_freq = Q16n16_to_Q24n8(Q16n16_mtof(midi_note));
105+
106+
// calculate modulation frequency to stay in ratio with carrier
107+
mod_freq = (carrier_freq * ratio)>>8; // (Q24n8 Q8n8) >> 8 = Q24n8
108+
109+
// set frequencies of the oscillators
110+
aCarrier.setFreq_Q24n8(carrier_freq);
111+
aModulator.setFreq_Q24n8(mod_freq);
112+
113+
// reset the note scheduler
114+
kNoteChangeDelay.start();
115+
}
116+
}
117+
118+
AudioOutput_t updateAudio(){
119+
int32_t mod = (128u+ aModulator.next()) * ((byte)128+ aModDepth.next());
120+
return MonoOutput::fromNBit(24, mod * aCarrier.next());
121+
}
122+
123+
// Arduino loop
124+
void loop() {
125+
server.copy();
126+
}

sandbox/streams-memory_aac-a2dp/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ We can use the GeneratedSoundStream class together with a SoundGenerator class.
55

66
To test the output I'm using this generated signal and write it to A2DP (e.g. a Bluetooth Speaker).
77

8+
9+
## Compile Settings
10+
11+
Please set the Patition Scheme to __Hugh APP__

sandbox/streams-memory_aac-a2dp/streams-memory_aac-a2dp.ino

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
using namespace audio_tools;
1616

17-
MemoryStream in(audio_aac, audio_aac_len);
17+
//recorded with 2 channels at 44100 hz
18+
MemoryStream in(gs_16b_2c_44100hz_aac, gs_16b_2c_44100hz_aac_len);
1819

1920
A2DPStream a2dp = A2DPStream::instance() ; // A2DP input - A2DPStream is a singleton!
2021
AACDecoder decoder(a2dp); // decode AAC to pcm and send it to a2dp
@@ -26,7 +27,7 @@ void setup(void) {
2627
Serial.begin(115200);
2728

2829
// We send the sound signal via A2DP - so we conect to the MyMusic Bluetooth Speaker
29-
out.begin(TX_MODE, "MyMusic");
30+
a2dp.begin(TX_MODE, "MyMusic");
3031

3132
Serial.println("A2DP is connected now...");
3233
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Using Mozzi on Bluetooth
2+
3+
I am providing a simple integration for [Mozzi](https://sensorium.github.io/Mozzi/).
4+
In this demo we provide the result as a result WAV stream which is available in the Web Browser
5+
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* @file streams-generator-a2dp.ino
3+
* @author Phil Schatzmann
4+
* @brief see https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/streams-generator-a2dp/README.md
5+
*
6+
* @author Phil Schatzmann
7+
* @copyright GPLv3
8+
*
9+
*/
10+
#include "AudioTools.h"
11+
#include "AudioWAVServer.h"
12+
#include "AudioMozzi.h"
13+
#include <Oscil.h>
14+
#include <tables/cos2048_int8.h> // table for Oscils to play
15+
#include <mozzi_fixmath.h>
16+
#include <EventDelay.h>
17+
#include <mozzi_rand.h>
18+
#include <mozzi_midi.h>
19+
20+
using namespace audio_tools;
21+
22+
typedef int16_t sound_t; // sound will be represented as int16_t (with 2 bytes)
23+
uint8_t channels = 1; // The stream will have 2 channels
24+
MozziGenerator mozzi(CONTROL_RATE); // subclass of SoundGenerator
25+
GeneratedSoundStream<sound_t> in(mozzi, channels); // Stream generated with mozzi
26+
WebServer server;
27+
28+
/// Copied from AMsynth.ino
29+
#define CONTROL_RATE 64 // Hz, powers of 2 are most reliable
30+
31+
// audio oscils
32+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier(COS2048_DATA);
33+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModulator(COS2048_DATA);
34+
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModDepth(COS2048_DATA);
35+
36+
// for scheduling note changes in updateControl()
37+
EventDelay kNoteChangeDelay;
38+
39+
// synthesis parameters in fixed point formats
40+
Q8n8 ratio; // unsigned int with 8 integer bits and 8 fractional bits
41+
Q24n8 carrier_freq; // unsigned long with 24 integer bits and 8 fractional bits
42+
Q24n8 mod_freq; // unsigned long with 24 integer bits and 8 fractional bits
43+
44+
// for random notes
45+
Q8n0 octave_start_note = 42;
46+
47+
48+
void setup(){
49+
Serial.begin(115200);
50+
51+
// connect to WIFI
52+
WiFi.begin("network", "password");
53+
while (WiFi.status() != WL_CONNECTED){
54+
Serial.print(".");
55+
delay(500);
56+
}
57+
Serial.println();
58+
Serial.print("Connect to http://");
59+
Serial.print(WiFi.localIP());
60+
61+
//start stream
62+
in.begin();
63+
64+
// We send the audio via the server
65+
server.begin(in, mozzi.config().sample_rate, channels);
66+
67+
// Start Mozzi
68+
ratio = float_to_Q8n8(3.0f); // define modulation ratio in float and convert to fixed-point
69+
kNoteChangeDelay.set(200); // note duration ms, within resolution of CONTROL_RATE
70+
aModDepth.setFreq(13.f); // vary mod depth to highlight am effects
71+
randSeed(); // reseed the random generator for different results each time the sketch runs
72+
in.begin();
73+
}
74+
75+
void updateControl(){
76+
static Q16n16 last_note = octave_start_note;
77+
78+
if(kNoteChangeDelay.ready()){
79+
80+
// change octave now and then
81+
if(rand((byte)5)==0){
82+
last_note = 36+(rand((byte)6)*12);
83+
}
84+
85+
// change step up or down a semitone occasionally
86+
if(rand((byte)13)==0){
87+
last_note += 1-rand((byte)3);
88+
}
89+
90+
// change modulation ratio now and then
91+
if(rand((byte)5)==0){
92+
ratio = ((Q8n8) 1+ rand((byte)5)) <<8;
93+
}
94+
95+
// sometimes add a fractionto the ratio
96+
if(rand((byte)5)==0){
97+
ratio += rand((byte)255);
98+
}
99+
100+
// step up or down 3 semitones (or 0)
101+
last_note += 3 * (1-rand((byte)3));
102+
103+
// convert midi to frequency
104+
Q16n16 midi_note = Q8n0_to_Q16n16(last_note);
105+
carrier_freq = Q16n16_to_Q24n8(Q16n16_mtof(midi_note));
106+
107+
// calculate modulation frequency to stay in ratio with carrier
108+
mod_freq = (carrier_freq * ratio)>>8; // (Q24n8 Q8n8) >> 8 = Q24n8
109+
110+
// set frequencies of the oscillators
111+
aCarrier.setFreq_Q24n8(carrier_freq);
112+
aModulator.setFreq_Q24n8(mod_freq);
113+
114+
// reset the note scheduler
115+
kNoteChangeDelay.start();
116+
}
117+
}
118+
119+
AudioOutput_t updateAudio(){
120+
int32_t mod = (128u+ aModulator.next()) * ((byte)128+ aModDepth.next());
121+
return MonoOutput::fromNBit(24, mod * aCarrier.next());
122+
}
123+
124+
// Arduino loop
125+
void loop() {
126+
server.copy();
127+
}

0 commit comments

Comments
 (0)