Resources usage

Wavetable will take some time, because I’m not happy about how current OwlProgram code. How about custom RGB tables, loadable from resources on the fly:

2 tables, each taking up 8kb on flash. This is using data from the “easter eggs” headers in firmware converterted to resources, didn’t bother generating different colors (but found the file that does that).

@antisvin sorry I didn’t see your FAUST documentation PR until now. I need to turn on GH notifications! Will review and merge asap.

Ok, since I have a plugin in IDE that shows my unmerged PRs, here’s the list of what else is pending:

OwlProgram - 2 PRs
OpenWare - 5
Libraries - 1

Some of that got reviewed and is waiting for updates from me, but most didn’t.

Also, I think Faust docs should be linked from OpenWareLab/README.md at master · pingdynasty/OpenWareLab · GitHub

Why not add a few more PRs, really.

Here’s an extract from the resource test patch that reads data from flash to memory, edits it and stores back to flash:

class TestData {
public:
    int value;
};

using TestMemoryResource = MemoryResource<TestData>;
using TestStorageResource = StorageResource<TestData>;

// ....

    ResourceStorage storage;
//...
            const TestStorageResource* res1 = storage.getResource<TestData>(TEST_RESOURCE_INDEX);
            // Copy storage resource to memory resource
            TestMemoryResource res2;
            res2 = *res1;
            // Edit and store updated resource
            res2.setName("test2");
            res2.payload.value = TOKEN2;
            if (storage.storeResource(TEST_RESOURCE_INDEX, res2)){
                debugMessage("Write OK");
            }
            else {
                debugMessage("Write FAIL");
            }

Added draft docs with resource usage info

Looking into ways to add support for using multi-dimensional wavetables with morphing in OwlProgram. General ideas:

  • should be usable for varying number of dimensions (i.e. defined using variadic template)
  • wavetable morphing can be for be enabled for each dimensions with a separate boolean parameter
  • should be usable with different array types, not just FloatArray. typically it would mean ShortArray
  • sample interpolation should be optional (I mean interpolation within a single table, not between multiple tables)

Naturally, resources would be used as WT data source (but there won’t be dependency on this).

So I was reminded that we have an extra SPI NOR chip thanks to Magus kickstarter stretch goal. I’ve found driver for this chip in repo and its datasheet. STM also has a nice header for larger version of this chip.

I’m not sure how much we can achieve without memory mapped mode support. I think this would require a separate storage and different access from user patches. We would have to add a service call for copying data from resource header pointer (using it as address only).

Defrag would also be a bit harder - currently we copy data to memory, but 8Mb is too much. It’s possible to erase data in 4k or 64k chunks, so we’d have to use buffer to erase data gradually. Also, refactoring done in Daisy branch allows us to use arbitrary alignment (as class template parameter). So we could align by sectors or blocks to make defrag code simpler.

Initial support for access to resources has been merged to development branches of OwlProgram/OpenWare. This enables read access to any flash resource by name and converting resources to array data.

There’s also Magus-specific code for overriding RGB tables with custom color schemes and resource browser UI page.

The outline of the process, to add resources to C++ patches, is:

  1. Declare a Resource pointer in your Patch class:
class MyPatch : public Patch {
  Resource* myresource;
  1. In your constructor, call Patch::getResource() and get the data from it that you need
  MyPatch() {
    myresource = getResource("909kick");
    FloatArray samples = myresource->asFloatArray();
  1. In your destructor, call Resource::destroy() to clean up memory allocations
  ~MyPatch(){
    Resource::destroy(myresource);

Of course this needs the latest develop firmware and OwlProgram to actually work, and you need to first store the resource on the device as well (roughly same method as storing patches, but with slot numbers starting at 43). We’ll be publishing more info on all of this shortly as we catch up with docs and releases.

Great work on this @antisvin, thank you again for your amazing PRs!

It may be a little bit earlier to advertise this API, I expect that it would require a few more updates to get everything right in OwlWare repo.

Also, I wonder if anyone except @mcc would dare running code from development branch :wink:

Would a test be helpful? I have use for the resources API (I’m making a small sequencer) and also I was considering doing a firmware update for the reasons I describe here. The thing is tho it is very important to me to retain MIDI HOST functionality so I don’t want to upgrade master if MIDI HOST is going to break like it did in my test with d6c58cf8ec6126

Yeah, it should work for storing sequencer data. There are 2 gotchas that I can think of here:

  1. There’s currently only 12 slots allowed for resource data, one of them is occupied by firmware settings. So using it to store each track in a separate slot would be limiting.

  2. I’ve made a simple script to generate resources from binary files, tables in C headers or WAV file bodies - OwlProgram/makeresource.py at develop · pingdynasty/OwlProgram · GitHub . It’s intended to work with simple arrays, you may have to add zero padding to get correct alignment for storing datastructures.

I might be ok with a small limit of resources, especially if there is some way (in principle) to back them up to a computer. Can resources currently be loaded/stored on the computer side?

One thing that might help with the 11-slot limit is if it were possible to load or save just a part of a resource (memory mapped mode would effectively give this too). If there’s a limit of 12 resources, then my thought is I should just create one resource per patch, and have the resource contain an array of presets within it. However at that point I would be worried about running out of RAM from loading the entire combined-resource into memory, or crashing while writing a single sub-resource and corrupting the entire combined-resource. If I could load or save a range of the named resource I could avert both these problems. I haven’t checked out the header yet to see if there is anything like this.

Supporting resource downloading sounds like a good idea. I can’t find anything like that in current sources, but recently added background tasks support could be used to implement such feature. For now you should just store a copy of your resources before uploading, but it likely would be possible to download them from device later. There were other planned enhancements for this, i.e. web based tool for browsing/managing resources, resource upload in web UI, etc.

Btw, don’t worry too much about number of resource slots - it’s just the beginning. There’s an extra chip with 8MB storage that would be supported in the near future. It would further complicate some things, as we’ll have to deal with 2 separate storages. But at least it would solve the storage space issue. It does have one limitation - you’ll have to load resource from that storage to RAM, while with current flash storage you can read data directly without using an extra memory buffer.

Is there in principle a way of loading resources on/off of the device with FirmwareSender? Shouldn’t that be able to download and upload whatever flash it needs?

Yes, FirmwareSender works with them the same way as patches (there’s no difference at its level). But I’m pretty sure that it doesn’t read from device slots, there’s just no support in current MIDI protocol for that.

Btw, there’s also integration in OwlProgram for uploading resources now, you can use something like make RESOURCE=/path/to/resource SLOT=SLOT_NUMBER resource . Resource slots follow patch slots, so 42 would be used by settings and you can write your own data in remaining 11 slots.

If it works correctly, new firmware will show upload progress bar and you will see new resource in resource browser page. You can also delete from that menu after clicking on it to enter delete mode. And resources that start with double underscore would be write protected in that menu (but can still be overwritten).

The current state of play (ie develop branches):

  • firmware supports new SysEx functions for storing a resource by name, and for retrieving stored resource names
  • Patch class has a new Resource* Patch::getResource(const char* name) function
  • FirmwareSender has been updated to pack, send and store a binary resource by name
  • resources such as samples can thus be stored by the user and accessed by a patch

To test it I’ve been doing the following:

  1. convert wav file to 48k mono float32 raw file with sox:
    sox sample.wav -r 48k -c 1 -t f32 sample.raw
  • send raw file to device and store as sample.wav:
    FirmwareSender -in sample.raw -out "OWL*" -name "sample.wav"
  • load test patch, e.g. ResSampler

I’ll create a simple web utility to upload resources, and a method for deleting (uploading with the same name automatically replaces an existing resource).

Would be great to have the ability to upload a wav in the browser and convert it to the correct raw format with JS, but that’s way beyond my front end coding skillz.

I think that we’ll eventually start supporting storing WAV files in resources. Then we could have a few service calls for getting WAV data or individual cue points. In such case, only non-audio data would require storing raw data as resources.

I would like to follow up on this…
Based on the notes on the 22.4 release it sounds like resources are now a working/shipping feature!
I see resource is documented in the API now.
I am going to update to 22.4 and try to write a patch on my Magus that uses resources.
I was wondering, is there a specific patch where source code is available that provides an example of using/selecting resources? This would save me time.
This thread mentions a “quad sampler” patch, but I didn’t find that patch in either the OwlProgram repo or in rebeltech.org/patch-library. Does “quad sampler” use resources? Is source available?

Hey Andi, welcome back!

Resources were usable for a while now, aside from a few changes to its API while we were still deciding how to make them convenient enough.

Here’s how data is loaded in Martin’s QuadSampler patch that you’ve mentioned.

We don’t have a way to select them dynamically yet, even though it makes sense for a device with display like Magus/Genius. So for the time being you have to hardcode resource name in your patch statically, but of course any resource contents can be used with that name later.

1 Like