conserve powerpower draw
cumulative error
Here's a thought experiment.
Imagine there's a CD player next to the microphone. You insert a compact disc that offers 2 KHz test tones.
const int sampleRate = 8000;
This was mostly clear, if we assume S.I. units,
but an explicit ... = 8000; // Hz
would be a fine addition.
So positive x-axis crossings of the test tone will happen every 0.5 msec. And we should observe these samples: zero-crossing upward, +1 peak, zero-crossing downwardOh, -1 peak. And then it repeats. Or we see that with some fixed phase offset.
int now = micros();
if (now - timerLastSample >= (1 / sampleRate) * 1000)
{
Theseems the smallest interval one can now = microsLowPower.idle()
assignment is just fine, and perfectly clear.
But clarity of the comparison could be improved,
since instead of S.I. units we're dealing with μsec.
It's not like 1000SLEEP_15MS
is obscure or anything.
But phrasing it as a unity
conversion factor
like USEC_PER_MILLISEC
wouldMight be helpfulrelevant for noticing 60 Hz peak values.
And putting it in a SECONDS_TO_USEC()
macro wouldBut, sigh!, it's far too coarse to be even betterapplicable here.
what goes on the wire?
As I write this, I confess I do not understand
whatDocument the meaning ofspec for the (1 / sampleRate)
factor iswire protocol.
I initially thoughtIt wouldn't hurt to version it was sample period with units of seconds.
But now it seems like it would haveAnd to be period in milliseconds?
Yet I'm unwillingoccasionally send that version number to believe we're scheduling 8 million samples per secondthe peer host.
Sampling rates of much more than 44 KHz tend to be overkillThe sample rate might sometimes change,
at least for audio playback intended for humans.
That timerLastSample
identifier is a lovely identifier.
But consider abandoningso send it
in favor of a different concept: nextSampleDeadline
.
Then we can just ask if current time has hit as metadata or bundle such changes when you bump the deadline yet.
Suppose we have 1000 usec until next deadline.
Then we could safely sleep for a millisecond, saving on battery chargeversion number.
timerLastSample =int now;samples[sampleRate];
That seems like trouble.
Using the current code's approachYou told us we have a sign bit, prefer something like timerLastSample += samplePeriod
(assuming appropriate units)that it's not floating point, and that's about it.
The
Maybe it's ifint32
compares? Maybe a >= bint64
.?
Number of microseconds beyondMaybe the peer host has an bint
is a random variable.
So we're introducing a continually increasing phase shift
that has random jitter.
To verify, send a known test tone toof the mic andsame size? graphically plot the sampled waveform.
EDITAnd is of same endianess?
It seems the smallest interval one canBe explicit when you serialize.
I didn't even see any LowPower.idlehtonl()
is SLEEP_15MS
.
Might be relevant for noticing 60 Hz peak values calls.
But
Also, sigh!in addition to scheduling ADC readings, it's far too coarse it appears we want to be applicable heresend IP packets on a one-second isochronous schedule. Be explicit about that.
co-existing with other tasks
If down the roadReconsider whether that's really what you want.
My reading is that a maintenance engineer32-bit host would send 32000 bytes
definesof UDP payload in a serialEventRun
routinesingle call, which gets fragged out
then details of scheduling andto IDK about 22 IP fragments.
That seems super bursty, which encourages router drops.
And it grossly magnifies the app-level deadlineseffect of
will become more importanteven a tiny underlying drop rate.
As it standsMuch better to send ~350 samples at a time, each serial character processed
will introduce significant audio jitterso they fit within a single wifi frame.
You'reIn this prototype you're not sending redundant info in case of dropped packet -- we'll just ignore that in this prototype.