When there's no sustain, the release step needs to be calculated from
the attack level, not the sustain level. Otherwise, contrary to intent,
this leads to the actual release taking a loooonnngg time.
A note can be placed in the center (panning=0) or moved to just the left
(panning=1) or right (panning=-1) channels. Fractional panning values
place it partially in both channels.
Now the vibrato 'units' are 1.0 = one octave, 1/12 = one semitone,
1/1200 = one cent. Before, the units were somewhat arbitrary and were not
perceptually "symmetrical" around the base frequency.
For vibrato_depth = 1/12 and base frequency of 440,
before: pitch from 403.33 to 476.67Hz, not corresponding to any notes
after: pitch from 415.30 to 466.16Hz, corresponding to G# and A#
this has the side effect of making some notes more accurate, the new
frequency= value in the test is closer to the true midi frequency of
830.609...Hz.
esp_ping_new_session can fail, particularly if ping is called quickly
many times in succession.
This is because `esp_ping_new_session` has to do a bunch of stuff
including creating a task and a socket. Calling `esp_ping_delete_session`
doesn't clean up these resources immediately. Instead, it signals the
task to clean up resources and exit 'soon', but 'soon' is defined as 1
second.
When the calls are frequent, the in-use sockets and tasks fill up
available slots—I didn't actually check which resource gets used
up first.
With this change, the ping call will raise an exception instead of
continuing with a call to esp_ping_start that crashes.
Closes#5980 based on my testing on an ESP32S3-N8R2.
The internal flash cache wasn't being properly used, because
`write_blocks` unconditionally performed the flash write.
Fixing this so that the write's not done until `internal_flash_flush`
fixes the problem in my test program with i2sout & synthio.
as a future optimization, `flash_read_blocks` could learn to read out
of the cache, but that's probably not super important.
and re-vamp overall envelope calculation again.
Now, if you set a low overall attack level like 0.2 this avoids the
"diminishing volume" effect when many notes sound at once. You need
simply choose a maximum attack level that is appropriate for the max
number of voices that will actually be played.
.. and account releasing notes at their sustain level until they're
done.
this ameliorates the effect where multiple releasing notes
don't seem to actually be releasing, but stay at a constant volume.