The reverse channel from the SynthesizerService to the views has been
refactored a bit so it's just a standard MidiListener interface rather
than a whole bunch of listeners for individual messages.
This patch plumbs note on/off messages from the USB MIDI keyboard to
the piano view, so it's possible to see the notes being played.
Also contains some small UI improvements, like scaling some things to
the device density.
A bunch of improvements to core MIDI handling. New functionality to
decode directly from a byte array (so you don't have to go through
InputStream), as well as more efficient and more concise code for
MessageOutputProcessor, plus some bug fixes.
Note that the tests haven't been run, maybe that would be a good idea.
This patch moves the scan of the USB bus to the service, while plumbing
the display of the permission dialog to the activity that binds it. Also
a little cleanup of the USB device thread (less logging, using a hacky
timeout to make sure the thread gets shut down properly).
This patch moves the connection to the USB MIDI keyboard from a single
activity to the SynthesizerService so that it can run while the user
switches between more than one activity.
Note that in the current state, there are problems when the device is
detached when the service isn't running.
This patch moves the ownership of the NDK synthesizer from an activity
(PianoActivity2) to a service, so that the same synthesizer may be
shared by multiple activities.
Note: this change repurposes an existing class that was used by the old
Java synthesizer. Those code paths will no longer work, and should be
aggressively deleted.
This patch puts up a permissions dialog when needed for connecting a USB
MIDI device. It also avoids scanning the bus when the device is known
from the intent. This should make cases where there are multiple devices
on the USB bus more graceful.
Empirical testing reveals that a smaller buffer size improves two
separate issues. First, it gives much better results on devices that
misreport their buffer size (Moto X is one, and it avoids a crash given
that the reported buffer size was larger than the static allocation for
the synth internal buffer). Second, even on devices that correctly
report the buffer size, it reduces internal buffering in the OpenSL ES
implementation, so this change reduces latency without impacting
robustness.
This patch implements better USB MIDI handling, including listening for
detach, and handling the case where it's connected while the activity is
active.
This is a FIR filter with NEON speedup. The NEON version has been tested
for accuracy against the scalar one, and there is simple benchmarking
code in place as well.
Extremely highly optimized implementations of the ladder filter in Neon
assembler. The audio loops (both linear and non-linear) are hooked up
and running, while the matrix generation is still running in scalar
code, though the Neon version has been tested and benchmarked.
Performance numbers on Nexus 10: linear audio loop = 22.5 cycles.
Nonlinear audio loop = 62 cycles. Matrix generation = 580 cycles.
Note that the current code will crash on ARM v7 devices without Neon
(for example, Motorola Xoom).
This patch implements nonlinear distortion in the resonant ladder
filter. It's based on the differential equations in the Huovilainen '04
DAFx paper, but using matrix exponential to compute the evolution of the
state variables. The implementation is scalar (and calls into sqrtf),
but designed to be implemented in very efficient SIMD.
Fixes various crashes, by (a) disabling the stats gathering thread and
(b) only trying to open a USB device if it identifies itself as a MIDI
keyboard. Disabling stats gathering should improve responsiveness and
improve battery consumption as well.
The crash in the stats gathering thread was a race on destruction, where
the audio thread set the stats_ringbuffer to NULL, but the Java thread
continued to try to read from it. This could be made more robust.
This version was published to Play Store as 0.91.
Train patch didn't render right. Should investigate further, but in
the meantime swap out one that does. Also narrow filter range,
increase touch count to 10, and fix pitch env for L4 != 50 case
(take-off patch).
The "com.google" namespace is reserved for official releases, so
renaming to "com.levien".
Also small tweaking to piano2.xml to clean it up for release (arguably
should have been separate commit, but oh well).
This patch wires up the LFO to the synth unit, and makes it affect pitch
(control over amplitude is not there yet). It also adds LFO delay to the
base LFO implementation, and there are some other cleanups as well (for
example, not unpacking patch data every note).
LFO speeds, delays, and pitch modulation ranges have been calibrated
against the DX7, but testing hasn't been exhaustive.
Add a button to capture raw start and end callback time (just putting it
in a text buffer so it can be copied), which is useful for making plots.
Also a bunch of commented out code to provoke priority inversion or
sudden increases in load (which exercises the governor), again for the
purpose of probing performance and making plots.
A small amount of stats analysis, mostly max callback time, with simple
display in the UI.
Also improves pow calculation to use lut implementation instead of
math.h pow(), for a speedup somewhere around 20-30%.
The android_glue unit now collects timestamp stats and reports them up
through a ring buffer to the app. The app currently just displays a raw
line in a text view, but we'll expand that out to smarter aggregation.
On API 17+ (JellyBean MR1), get the buffer size and sample rate from the
platform, and use that, rather than hardcoding the defaults. We're still
using an internal buffer size (N) hardcoded to 64, so the amount of
computation per callback is not as consistent as it would be if that
were more flexible.
The FM kernel yields itself well to speedup using NEON assembler. This
patch contains the NEON assembly code, plus C integration code
(including making sure that buffers are aligned to 16 bytes).
This change adds a (single) resonant filter to the C++ synth unit, and
wires up both USB MIDI and on-screen controls for cutoff and resonance.
Also fixes a bug in KnobView which caused the knob value to jump around.
We were only using a very few STL functions (min, max, and iostream for
debug logging). This patch gets rid of those dependencies (implementing
the needed functions in synth.h), and turns on the "all" ABI target, so
that it works with all native architectures supported by the NDK.
This patch wires up pressure sensitivity from the touchscreen. It also
adds simple USB Host mode for MIDI keyboards (tested on M-Audio KeyRig 49
and Akai MPK mini). Finally, it cleans up a bit.
The USB listening thread should be moved out of the activity and into a
service (there can be problems on multiple plug and unplug). But this
should be good enough to play with.