EigenLite 1.0 dev release

Status: In Development

(api subject to change)

EigenLite Repo Branch : dev

Features:

  • device filtering
  • device notifications
  • new connection/re-connection logic
  • embedded firmware
  • no runtime requirements

Platforms:

  • MacOS - arm64/ x86_64 (now available in dev)

Linux I will add when there is a use-case/demand.

Description

The focus of EigenLite 1.0 is to make it much easier to integrate with applications and for users to have NO additional setup steps, just install the app and go.

also, as part of this, I wanted to support those with multiple Eigenharps, by allowing different apps/processes connect to specific eigenharps.
this was not possible previously as EigenLite would connect to ALL eigneharp’s that it found. with 1.0, you can specify a filter to limit connections to specific harps.

Breaking changes

there are a few breaking changes.

  • Firmware readers are now passed as pointers, not references as they are optional
  • types in eigenapi.h have been moved to base c++ types, so no include are necessary.
  • callback::device has been replaced, connected() is a close substitute.
  • callback breath - change val signed (to do)
  • tau mode keys (course 1) , id change

Testing etc.

the connection logic has changes quite substantially, so I’ll be keeping an eye on this whilst this is in the dev phase.

Stability of API

Im using and have been testing this version , but it is in development :wink:
this version is still in active development, so changes are still quite like.

note: I will not develop 0.6 further, so the USE_DYNAMIC will only exist for full release… so consider a 1.0 feature … that just sneaked into 0.6 for Mac/arm.

3 Likes

ok, Ive added x86_64 builds to EigenLite 1.0/dev

@Kai , you can give this a go with ECMapper… let me know if you run into any issues.
should only take a few mins to update to api to give existing functionality.

this would be very useful to get some more extended testing from users - in particular, so we know there are no issues (particularly with new connection logic).

from there…

adding device filter is easy to add, though likely not a priority, as EigenCore is (presumably) fine getting messages from all eigenharps and then distributing to multiple ECMappers!?
i.e. you don’t need to run multiple EigenCore for different harps, just one EigenCore → to N ECMappers.

however…
it could be handy for some ECMapper users with multiple Eigenharps, and they want to use alongside EigenD/other EigenLite apps on the same computer.
e.g. if I want to use my Pico with EigenCore/Mapper, but my Alpha with my new project.

its a simple add, basically, you just need to have a UI in EigenCore which says, do you want to file r… if so what (Pico/BaseStation) and which device… that’ll then limit EigenLite to attaching to that single Eigenharp.

no another note… but related…

currently, Im supporting both dynamic/static libraries and embedded and multiple firmware readers.

but frankly, Im starting to wonder if we just stick to static and the embedded firmware?

theoretically, using file firmware reader and dynamic eigenlite/pico encoder means they can be updated without a new release of the client app.

however, we know:
a) there will never be a new Eigenharp firmware (ihx)
b) users will never update EigenLite without updating the client app

so its kind of functionality thats not going to be used, and for developers using the embedded firmware and static linking is just so much easier for distribution etc.

thoughts? have I missed something?

obviously we dont have to make this decision now… and of course, we should wait till we have a few releases under out belt, to know there are any oddities (e.g. different OS versions),
but Id like to consider it… KISS.

a couple more breaking changes.

(done/fixed ) tau : mode keys
had incorrect id, now start correctly from 0

(todo) breath
will become a signed integer value, to better reflect usage.
Im also going to calibrate a zero point, and adjust scaling.

bigger change possible…

Im considering changing all the callback values to give float values
so, 0…1 (unipolar) and -1.0f / 1.0f (bipolar) , rather than send the raw integer values.
this would allow EigenLite to potentially find better scaling/calibration, without clients apps having to worry about it.

basically, like breath, I think theres some possibilities for improvements here, and it makes no sense for me to calibrate raw values in floating point, and then convert them back to 0 - 4096 to ‘pretend’ they are raw…
also I think generally floats are easier to work with (scaling etc)

I’m positive. I can’t think of a reason why EigenLite users should need to know or care about the ihx files or picodecoder. So sounds like a simplification without any practical loss in flexibility to me. I struggled a lot with the dylibs/paths and how to properly bundle everything until I eventually learned about @executable_path, @loader_path and @rpath. That might just be me and my lack of Mac experience, but still, one less hurdle for the next newbie to tackle…

I like the idea of unipolar/bipolar floats. Easy to work with and to intuitively understand. Only thing I can think of, do you think there might be some value of EigenD/EigenLite “raw” data being exactly the same? E.g. EigenLite sending raw data into EigenD by whatever means and then have the rest of the EigenD setup behave just as if the device was internal? Or the other way around, where an app using EigenLite could receive that exact same data from EigenD instead? I don’t know how the data looks in EigenD, so wouldn’t know if this even makes theoretical sense.

Yeah, that was my current plan, at least. …but, I guess I could still use device filtering. Perhaps an advanced config (a.k.a. @keymanpal mode) with an editable list like this?
Enabled   Model   #   IP        Port
       Pico    0  127.0.0.1  1234
       Pico    1  127.0.0.1  1235
       Alpha   0  127.0.0.1  1234

3 Likes

yeah, rpaths are a bit tricky…
I do like using shared libraries generally, but as I said not sure adds much here.

bipolar/unipolar.
debate really is how much EigenLite is just a thin wrapper around eigend code vs how much it adds value and is easy to use.
but even then, its questionable… EigenD converts this data into bipolar floats anyway, so one could argue, it’s just where do you stop the abstraction.

overall, I think the benefits of a ease of use outweigh the theory of just give me raw data.
why?
basically because, Ive got a pretty good understanding of how EigenD massages this raw data, and I know the EigenD code well enough to check we get a similar view…
whereas other developers likely don’t want to go fishing around EigenD to find this information.
also… do we all want to reinvent the wheel in our client code?

I think the pitchbend/breath handling provides a good example where just taking these raw values and converting will not give you the same ‘feeling’ as EigenD unless you know a bit more about how EigenD handles these values.

so, overall I think its a move in the right direction :slight_smile:

device filtering … yeah, as I said, I think the main benefit of using the Device Filter with ECMapper EigenCore is if the users wants to use another application e.g. EigenD or my new App alongside ECMapper.
Currently this is not possible as EigenCore/EigenLite 0.5 will open ALL eigenharps and so make it impossible for another app to open and eigenharp. (as usb open is exclusive to one app)

so I do think is useful… and as I say, its very simplistic, all you need to do in EigenCore is two selectors:
Filter:
Device Type : All, Pico, Basestation
Device Number: 1…N

this maps onto api as

Device Type = ALL → setDeviceFilter (false, 0)
Device Type = Base, DevNum → setDeviceFilter (false, DevNum)
Device Type = Pico DevNum → setDeviceFilter (true, DevNum)

I could have made the filter more complex,
but honestly I see the main use case as linking an app to ONE specific device (advanced use)
OR just connecting to everything. (normal/default)

implementation note:
currently I only evaluate filter on device connection…
as I didn’t really want to start disconnecting devices when they fall outside the filter :wink:
but may review this later.

lets also remember, there are only a few of us with multiple eigenharps, and only a subset of those actively use multiple on the same computer at the same time :wink:
(which is why the current, no filtering, has not really been an issue for most)

Sounds reasonable to me. Making things as easy as possible, but without crossing the line into making assumptions about what the user wants to do with the data. As an example, providing the Y axis data as a linear, bipolar float sounds good to me. But assuming that the Y axis will be used for pitch and apply a curve that suits that use is a decision better left to the user application.

So, I guess my preference would be for EigenLite to provide “linear” data that feels like a neutral starting point for further processing. Which probably means quite some massaging - at least for breath.

I also think sensitivity and behaviour close to the same, regardless of model would be useful. Iirc, at least breath sensitivity is different across models. EigenLite taking this into account and adjusting for it could potentially be of value. Someone with a only a Pico to test on could implement breath and have confidence in that the behaviour would be almost the same on an Alpha.

Hmm. Come to think of it, it doesn’t have to be either/or… Perhaps one consideration regarding simplicity and not having to reinvent the wheel, but still keeping EigenLite “raw” could be to add an example application with a set of utility functions for commonly needed stuff like scaling, velocity calculation, pitch bend curves, breath scaling and threshold, etc. Even conversion to floats, I guess… If you decide to keep EigenLite as light as possible, some of the calculations we are already doing in ECMapper and MEC could be copied to such an example project as suggested use. Sounds like something I’d be happy to assist with a first version of if that is the direction you want to take things in.

2 Likes

EigenLite is going to remain simple… its designed to be just an abstraction of the hardware…
its not going to be ‘opinionated’, rather just deal with the quirks of the hardware.

its focus is low level communication and prepping the data for delivery.
(preparation is limited to ‘calibration’ steps. really… the changes to the api are just to make this easier)

this was, and remains the goal of EigenLite…I do not want to extend the api beyond this goal.

so, as for how the data is used/interpreted that remains up to the client application…

could there be another layer/library that adds higher level abstractions , possibly…

however, Im busy working on a new project at the moment, this project has a (very) broad scope for Eigenharps.
it’s already doing a good job of highlighting what’s needed to get to EigenD levels of functionality.
this is why Im ‘poking’ at EigenLite a little bit as needed, however, my main focus is on this project.

once the project is ‘complete’ (in some form), I may take a look at which parts could be re-used in a more generic form, perhaps as a layer above EigenLite (and that layer WILL be opinionated ;))
… but its too early to commit yet, as its a big project… though progress is very fast so far!

2 Likes

bug fix: enable ‘tau mode’ on processing loop
main difference is led on mode buttons are now addressed correctly.