Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "decimate" capability to AnalyzePrint #395

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 42 additions & 24 deletions analyze_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,49 +35,67 @@
void AudioAnalyzePrint::update(void)
{
audio_block_t *block;
uint32_t offset = 0;
uint32_t remain, n;
//uint32_t offset = 0;
//uint32_t remain, n;

block = receiveReadOnly();
if (!block) return;
//if (!block) return;
//bknum++;

while (offset < AUDIO_BLOCK_SAMPLES) {
remain = AUDIO_BLOCK_SAMPLES - offset;
switch (state) {
do
{
//remain = AUDIO_BLOCK_SAMPLES - offset;
switch (state)
{
case STATE_WAIT_TRIGGER:
// TODO: implement this....
offset = AUDIO_BLOCK_SAMPLES;
break;

case STATE_DELAY:
//Serial.printf("STATE_DELAY, count = %u\n", count);
if (remain < count) {
count -= remain;
offset = AUDIO_BLOCK_SAMPLES;
} else {
offset += count;
count = print_length;
state = STATE_PRINTING;
if (count > offset) // still delaying?
{
count -= offset; // yes, decrement delay count...
offset = AUDIO_BLOCK_SAMPLES; // ... and exit
}
else
{
offset = count; // index first sample to print
count = print_length; // re-use for sample print count
state = STATE_PRINTING; // start printing on next iteration
//bknum = 0;
}
break;

case STATE_PRINTING:
n = count;
if (n > remain) n = remain;
count -= n;
while (n > 0) {
Serial.println(block->data[offset++]);
n--;
if (offset >= AUDIO_BLOCK_SAMPLES)
offset -= AUDIO_BLOCK_SAMPLES;
if (offset < AUDIO_BLOCK_SAMPLES) // may happen if decimate_length > AUDIO_BLOCK_SAMPLES
{
//Serial.print(bknum);
//Serial.print(' ');
//Serial.print(count);
//Serial.print(' ');
if (block) // real data, use it
Serial.println(block->data[offset]);
else // treat NULL as block of zeros - DON'T just ignore it!
Serial.println(0);
count--;
offset += decimate_length;
}
if (count == 0) state = STATE_IDLE;
if (count == 0)
state = STATE_IDLE;
break;

default: // STATE_IDLE
offset = AUDIO_BLOCK_SAMPLES;
break;
}
}
release(block);
} while (offset < AUDIO_BLOCK_SAMPLES);

if (block) // not safe to release(NULL), for some reason
release(block);
}

void AudioAnalyzePrint::trigger(void)
Expand All @@ -90,12 +108,12 @@ void AudioAnalyzePrint::trigger(void)
Serial.print(", delay=");
Serial.println(n);
count = n;
state = 2;
state = STATE_DELAY;
} else {
Serial.print("trigger ");
if (myname) Serial.println(myname);
count = print_length;
state = 3;
state = STATE_PRINTING;
}
}

12 changes: 8 additions & 4 deletions analyze_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,25 @@ class AudioAnalyzePrint : public AudioStream
{
public:
AudioAnalyzePrint(void) : AudioStream(1, inputQueueArray),
myname(NULL), state(0), trigger_edge(0), delay_length(0), print_length(500) {}
myname(NULL), state(0), trigger_edge(0), delay_length(0), print_length(500), decimate_length(1) {}
virtual void update(void);
void name(const char *str) { myname = str; }
void trigger(void);
void trigger(float level, int edge);
void delay(uint32_t num) { delay_length = num; }
void length(uint32_t num) { print_length = num; }
void decimate(uint32_t num) { if (num > 0) decimate_length = num; }
private:
const char *myname;
uint8_t state;
uint8_t trigger_edge; // trigger type, 0=none, 2=RISING, 3=FALLING
int16_t trigger_level;
uint32_t delay_length; // number of samples between trigger and printing
uint32_t print_length; // number of samples to print
uint32_t count;
uint32_t delay_length; // number of samples between trigger and printing
uint32_t print_length; // number of samples to print
uint32_t decimate_length; // number of samples to skip between those printed, -1
uint32_t offset; // offset into current block of sample to print: could be past end
uint32_t count; // count of samples to wait after trigger, or remaining to print
//uint32_t bknum;
audio_block_t *inputQueueArray[1];
};

Expand Down
134 changes: 134 additions & 0 deletions examples/Analysis/Print/Print.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Demonstrate use of AudioAnalyzePrint
//
// Generates a square wave shaped by an envelope, and alternately
// prints the resulting wave and just the envelope. Note that the
// actual audio output is silenced, we don't need it and the "raw"
// envelope might well be Bad for Stuff.
//
// Intended to be triggered by the user entering a decimation
// level, but as this isn't working in Arduino 1.8.13 Serial
// Plotter, it also sends output every couple of seconds: you can
// flip to Serial Monitor and enter a new value, then back to the
// Serial Plotter
//
// This example code is in the public domain.

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformDc dc1; //xy=97,441
AudioSynthWaveform waveform1; //xy=111,401
AudioMixer4 mixer1; //xy=259,428
AudioEffectEnvelope envelope1; //xy=394,426
AudioAmplifier amp1; //xy=538,425
AudioAnalyzePrint print1; //xy=540,366
AudioOutputI2S i2s1; //xy=699,422
AudioConnection patchCord1(dc1, 0, mixer1, 1);
AudioConnection patchCord2(waveform1, 0, mixer1, 0);
AudioConnection patchCord3(mixer1, envelope1);
AudioConnection patchCord4(envelope1, amp1);
AudioConnection patchCord5(envelope1, print1);
AudioConnection patchCord6(amp1, 0, i2s1, 1);
AudioConnection patchCord7(amp1, 0, i2s1, 0);
AudioControlSGTL5000 sgtl5000_1; //xy=553,532
// GUItool: end automatically generated code


void setup() {
Serial.begin(115200);
while (!Serial)
; // wait for Arduino Serial Monitor

AudioMemory(5);

pinMode(LED_BUILTIN,OUTPUT);

// not sure what these do...
sgtl5000_1.enable();
sgtl5000_1.volume(0.45);

// Set up print analyzer
print1.name("440Hz"); // not really needed
print1.decimate(44); // decimate by enough that we get to see the whole area of interest

waveform1.begin(1.0f,440.0f,WAVEFORM_SQUARE); // square makes it easier to see at high decimation values
dc1.amplitude(1.0f); // set to maximum
mixer1.gain(0,0.0f); // everything switched off
mixer1.gain(1,0.0f); // to start with
amp1.gain(0.0f); // don't really want the audio output
envelope1.release(40);// fast release so logs aren't too long
}

enum {Idle,doIt,doEnv1, doEnv2, doRelease,stopIt,} state = doIt,last=doIt;
uint32_t next = 100;
int8_t again = 10;

void loop() {
long num;

if (millis() > next)
{
next = millis() + 100;
switch (state)
{
default:
again--;
if (Serial.available() || 0 == again) // user entry or every so often
{
again = 20;
num = Serial.parseInt();
if (num > 0)
print1.decimate(num);
state = last == doIt
?doEnv2
:doIt;
last = state;
digitalWrite(LED_BUILTIN,HIGH);
}
break;

case doIt:
AudioNoInterrupts();
mixer1.gain(0,1.0f);
envelope1.noteOn();
print1.delay(4);
print1.length(250);
print1.trigger();
AudioInterrupts();
state = doRelease;
//next = millis() + 200;
break;

case doRelease:
envelope1.noteOff();
state = stopIt;
break;

case doEnv2:
Serial.println("raw env");
mixer1.gain(0,0.0f);
mixer1.gain(1,1000.0f);
print1.trigger();
envelope1.noteOn();
state = doRelease;
//next = millis() + 200;
break;

case stopIt:
mixer1.gain(0,0.0f);
mixer1.gain(1,0.0f);
state = Idle;
while (Serial.available())
Serial.read();
digitalWrite(LED_BUILTIN,LOW);
//AudioNoInterrupts();
break;

}
}

}
17 changes: 11 additions & 6 deletions gui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5044,7 +5044,7 @@ <h3>Notes</h3>
<h3>Summary</h3>
<div class=tooltipinfo>
<p>Print raw audio data to the Arduino Serial Monitor. This
object creates massive output quickly, and should not normally be used.</p>
object can create massive output quickly, and should not normally be used.</p>
</div>
<h3>Audio Connections</h3>
<table class=doc align=center cellpadding=3>
Expand All @@ -5053,19 +5053,24 @@ <h3>Audio Connections</h3>
</table>
<h3>Functions</h3>
<p class=func><span class=keyword>name</span>(string);</p>
<p class=desc>blah blah blah blah
<p class=desc>Set name so you know which instance of the object has caused the output
</p>
<p class=func><span class=keyword>trigger</span>();</p>
<p class=desc>blah blah blah blah
<p class=desc>Cause output to start, possibly after delay if that's been set
</p>
<p class=func><span class=keyword>trigger</span>(level, edge);</p>
<p class=desc>blah blah blah blah
<p class=desc>Not currently implemented
</p>
<p class=func><span class=keyword>delay</span>(samples);</p>
<p class=desc>blah blah blah blah
<p class=desc>Delay this many samples before output begins
</p>
<p class=func><span class=keyword>length</span>(samples);</p>
<p class=desc>blah blah blah blah
<p class=desc>Total number of samples to output before going idle again
</p>
<p class=func><span class=keyword>decimate</span>(sample_interval);</p>
<p class=desc>Skips &lt;sample_interval - 1&gt; samples between output samples, to
reduce amount of data output to manageable levels. 1 outputs every value, 10 every
tenth value, etc. 0 would be a poor choice, and is ignored.
</p>
<!--
<h3>Examples</h3>
Expand Down
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ windowFunction KEYWORD2
modify KEYWORD2
output KEYWORD2
trigger KEYWORD2
decimate KEYWORD2
length KEYWORD2
threshold KEYWORD2
setAddress KEYWORD2
Expand Down