Samples in faust

This device having space for sample storage is very tempting. Do we have access to use samples with faust running on a witch using the soundfile primitive?

Actually we do, I’ve added that a few years ago. But we run an old version of FAUST on server that can’t be upgraded easily, so it doesn’t support that primitive. If you want to build your patches offline, you can use the samples by following the README instructions.

Fantastic, I’ve compiled these locally a couple of times so that’s pretty straight forward. Thanks!

What is the reason ?

IIRC, the server runs an old Linux version with Libc that is incompatible with available recent FAUST binaries. And I think it might not have enough memory to build it locally. There’s been some WIP to move the server to a newer deployment system that would make it possible to run more recent OS or reconfigure server easily.

Another question here. I would like to be able to read and write my own wav files to non-volatile memory on the Witch, to use with a patch I have started making - is that possible using https://github.com/RebelTechnology/OwlProgram ? I haven’t found any instructions on this yet, so if anyone knows I’d love to hear how!

I assume I can’t use the https://witch.rebeltech.org/ site because the only web forms I’ve found for upload samples seem to be designed with names specific to the default patches which I am not interested in using, and I have found no way to view what samples are on the device using that site.

I did just discover that the witch site’s source is available, and that files appear to be sent to the device in a manner described here https://github.com/RebelTechnology/Witch/blob/505d302b6f6ec5cdbf29218022de68b6c18bb4c6/docs/js/owlcmd.js#L362. I’m certainly ok with pulling out js snippets and rolling my own whole local site that provides access to some of this stuff, but I assume that there’s an easier way because I can’t be the first to want to do this :slight_smile: .

You can already do this in Web patcher by clicking “Resource” > “Add”.

For offline builds (which you’ll need to get support for WAV files in FAUST at the moment) you can use “make resource SLOT=N RESOURCE=/path/to/file.wav”. Btw, I think current FAUST source might require a small fix to build without errors, let me know if you run into problems (it’s related to new features in memory allocator).

Ah there it is! Ok cool, I didn’t realise that I’d need to leave the witch specific site as it wasn’t linked to from there afaict, but that does make a lot of sense. I hadn’t noticed the tab previously

I hope to get some time to get everything running locally in the next couple of days, I’ll let you know if I hit any issues. Thanks!

Hey @antisvin ! So I got some time to try this today. It’s gone quite well but I am hitting issues with soundfile compilation.

  • Set up OwlProgram, latest develop. Couldn’t get this to work on MacOS, but I dug out my old ubuntu machine and the setup instructions were flawless
  • Already have FAUST Version 2.39.6 installed
  • Am able to run make clean && make FAUST=tune load and have the patch run on the Witch!
  • Attempting to run make clean && make FAUSTOPTS=soundfile FAUST=tune load does indeed yield errors

Terminal dump:

Building patch tune
In file included from ./Build/registerpatch.h:1,
                 from ./Source/PatchProgram.cpp:14:
./Build/Source/FaustPatch.hpp: In member function 'Soundfile* OwlResourceReader::createSoundfile(const char**, int, int)':
./Build/Source/FaustPatch.hpp:1181:37: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1181 |             soundfile->fBuffers[chan] = soundfile->fBuffers[chan % cur_chan];
      |                                     ^
./Build/Source/FaustPatch.hpp:1181:37: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp:1181:76: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1181 |             soundfile->fBuffers[chan] = soundfile->fBuffers[chan % cur_chan];
      |                                                                            ^
./Build/Source/FaustPatch.hpp:1181:76: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp: In member function 'Soundfile* OwlResourceReader::createSoundfile(int, int, int)':
./Build/Source/FaustPatch.hpp:1215:46: error: no matching function for call to 'Soundfile::Soundfile()'
 1215 |         Soundfile* soundfile = new Soundfile();
      |                                              ^
./Build/Source/FaustPatch.hpp:537:5: note: candidate: 'Soundfile::Soundfile(int, int, int, int, bool)'
  537 |     Soundfile(int cur_chan, int length, int max_chan, int total_parts, bool is_double)
      |     ^~~~~~~~~
./Build/Source/FaustPatch.hpp:537:5: note:   candidate expects 5 arguments, 0 provided
./Build/Source/FaustPatch.hpp:528:8: note: candidate: 'constexpr Soundfile::Soundfile(const Soundfile&)'
  528 | struct Soundfile {
      |        ^~~~~~~~~
./Build/Source/FaustPatch.hpp:528:8: note:   candidate expects 1 argument, 0 provided
./Build/Source/FaustPatch.hpp:1219:37: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1219 |             soundfile->fBuffers[chan] = new FAUSTFLOAT[length];
      |                                     ^
./Build/Source/FaustPatch.hpp:1219:37: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp:1220:44: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1220 |             memset(soundfile->fBuffers[chan], 0, sizeof(FAUSTFLOAT) * length);
      |                                            ^
./Build/Source/FaustPatch.hpp:1220:44: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp: In member function 'void OwlResourceReader::getBuffersOffset(Soundfile*, float**, int)':
./Build/Source/FaustPatch.hpp:1229:54: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1229 |             buffers[chan] = &soundfile->fBuffers[chan][offset];
      |                                                      ^
./Build/Source/FaustPatch.hpp:1229:54: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp: In member function 'void OwlResourceReader::readFile(Soundfile*, const char*, int, int&, int)':
./Build/Source/FaustPatch.hpp:1281:45: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1281 |                     soundfile->fBuffers[chan][offset + sample] = frame[chan] * factor;
      |                                             ^
./Build/Source/FaustPatch.hpp:1281:45: error: 'void*' is not a pointer-to-object type
./Build/Source/FaustPatch.hpp:1291:45: warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
 1291 |                     soundfile->fBuffers[chan][offset + sample] = frame[chan] * factor - 0.5f;
      |                                             ^
./Build/Source/FaustPatch.hpp:1291:45: error: 'void*' is not a pointer-to-object type
make[1]: *** [compile.mk:169: Build/PatchProgram.o] Error 1
make: *** [Makefile:110: patch] Error 2

Please let me know if this looks like the kind of error that you expected?

Actually I was thinking of different errors related to memory allocator changes, it looks like you’re running into something related to FAUST’s soundfile API. I’ll see what has changed in it. However, you’re running a rather old version too, current it’s 2.59.9. I suggest you to build the version from their master-dev branch on github or maybe there’s some PPA that contains fresh builds.

Ah yes that is a little old. I just upgraded to 2.59.9 and so far I’m seeing the same errors. I’ll try to get soundfile compilation going with faust in isolation first and then try again.

Oof, so far I can’t find a faust2xxx command that actually works with -soundfile. Previously I’d only ever used the soundfile option with faust2nodejs and faust2api, but faust2nodejs is completely broken with any args, and faust2api errors out if the -soundfile option is included. I see that sletz has made a ticket here regarding some of this https://github.com/grame-cncm/faust/issues/718. I’m on latest master-dev. I’ll have to dig into this deeper, perhaps next weekend.

Output for faust2api with -soundfile flag, 2.59.9 master-dev.

faust2api -alsa -soundfile ./mosfez-faust-passthrough.dsp
Your dsp-faust.zip API package for ALSA is being created
pPrinter.cpp:288:18: warning: type attributes ignored after type is already defined [-Wattributes]
  288 | struct FAUST_API Meta;
      |                  ^~~~
pPrinter.cpp:8439:17: warning: type attributes ignored after type is already defined [-Wattributes]
 8439 | class FAUST_API MapUI;
      |                 ^~~~~
/usr/bin/ld: /tmp/ccPAyAbv.o: in function `LibsndfileReader::checkFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
pPrinter.cpp:(.text._ZN16LibsndfileReader9checkFileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN16LibsndfileReader9checkFileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x9d): undefined reference to `std::experimental::filesystem::v1::__cxx11::path::_M_split_cmpts()'
/usr/bin/ld: pPrinter.cpp:(.text._ZN16LibsndfileReader9checkFileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN16LibsndfileReader9checkFileERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0xa5): undefined reference to `std::experimental::filesystem::v1::status(std::experimental::filesystem::v1::__cxx11::path const&)'
collect2: error: ld returned 1 exit status

@dxinteractive , I took a look at current state of FAUST soundfile support, looks like they’ve made some changes in order to support float or double data buffers and that led to some things not working on our end. I only had time to resolve things that broke compilation, but not tested the results on actual hardware yet.

You can give it a go using this branch: https://github.com/antisvin/OwlProgram/tree/feature/new-faust-fixes or wait for me to do some testing on OWL.

1 Like

Thanks so much for taking the time to do this! I checked out your repo / branch and compiled it, and found that yes it can now compile dsp with the FAUSTOPTS=soundfile flag. I then attempted to use soundfile, but it’s been a few years since I’ve done that and I’m not familiar with how I should address resources on the Witch. I tried something like sftest = 0,_~+(1) : soundfile("sample1.wav",1) : !,!,_; , as I can see I have sample1.wav already loaded on by default, but I can only assume it didn’t find the file as the sftest component of my DSP produced no audible output. Another part of the same DSP was audible as a check to see if the remainder of the compilation and execution worked as expected.

Perhaps now it’s just a matter of me using the correct syntax? This is still good progress

@dxinteractive, I’ve resurrected my old test patch and can confirm that it actually works with that fixed branch. Here’s how to install it:

  1. Go to MyPatches/Faust/Samples at master · antisvin/MyPatches · GitHub

  2. Flash KICK.wav / HAT.wav as resources.

  3. Build and flash patch in PercSample.dsp

  4. Set params C/D to 0. Trigger samples with buttons 1/2 or params C/D

If you have a specific patch that works on desktop and not on OWL, I can try to see why. But please leave complete patch source here or on github or in Rebeltech library (without publishing it).

Ok great

  • I’ve cloned your repo and have your patch and samples
    • What are KICK.bin and HAT.bin used for? Are these generated somehow from the wav files?
  • I’ve added KICK.wav and HAT.wav to the Witch via the resource upload on this website
    • Is there a way to do this without relying on this website?
  • Compiling and running your patch verbatim referencing KICK.wav and HAT.wav, or modifying it to reference the existing sound files sample1.wav and sample2.wav, I can successfully upload but I can see that I get the message Unsupported format on the website when either of those patches start. I can hear that the patch still runs if I make the following change, just without any sound files:
import("stdfaust.lib");

// Simple syntax for loading a single file
//wav1 = soundfile("test[url:test.wav]",2);
// Full syntax for multiple files
//wav1 = soundfile("test[url:{'test1.wav';'test2.wav'}]",2);
// We support both!

wav1         = soundfile("Percussion[url:{'KICK.wav';'HAT.wav'}]", 1);
// Percussion samples from KastleDrum are LoFi beyond ridiculous
kick_sound   = so.sound(wav1, 0);
hat_sound    = so.sound(wav1, 1);

process = kick , hat :> _ + os.osc(440.0) * 0.1 , _ + os.osc(441.0) * 0.1 
with {
    // Kick sample
    kick_gain = hslider("Kick Gain[OWL:A]", 0.5, 0.0, 1.0, 0.001);
    kick_trig_cv = hslider("Kick Trig by CV[OWL:C]", 0.0, 0.0, 1.0, 0.001) > 0.1;
    kick_trig_but = button("Kick Trig Gate[OWL:B1]");
    kick_trig = kick_trig_cv | kick_trig_but;

    // Hat sample
    hat_gain = hslider("Hat Gain[OWL:B]", 0.5, 0.0, 1.0, 0.001);
    hat_trig_cv = hslider("Hat Trig[OWL:D]", 0.0, 0.0, 1.0, 0.001) > 0.1;
    hat_trig_but = button("Hat Trig Gate[OWL:B2]");
    hat_trig = hat_trig_cv | hat_trig_but;

    // Percussion samples playback
    kick      = kick_sound.play(kick_gain, kick_trig) <: _, _;
    hat       = hat_sound.play(hat_gain, hat_trig) : sp.panner(0.8);    
};

KICK.wav and SNARE.wav both play locally fine. I’ll look into why it might think it is of unsupported format

I’ll also double check the firmware version on the Witch, I assumed it was up to date as I only received it a month or two ago, but I’d better make sure

FIRMWARE: Witch v22.0.0 , ok that’s quite old according to Releases · RebelTechnology/OpenWare · GitHub , I’ll upgrade it tonight just in case

It’s the same format, but converted to a format that is stored on device. Well really we just add a header with metadata that describe what’s getting stored on flash (resource name, size, checksum, etc).

First of all, besides Witch’s site you can also use device page in RT library that has resource uploader now.

To do it offline you can run a command like RESOURCE=/path/to/file.bin SLOT=X make resource . I think you’re supposed to use slot number >41 or maybe it doesn’t matter in newer firmware.

I’ve written a tool that converts data to resources (also has other features like parsing simple C LUTs, etc). Won’t remember all details now, but this seems to produce the same resources as are stored in repo:

python Tools/makeresource.py -i ../MyPatches/Faust/Samples/KICK.wav -o KICK.bin -d '<c' KICK.wav

Last parameter is resource name in metadata that would be used for loading resources.

It only supports 8 and 16 bit WAV data. So you’re likely using something else. I think adding 32 bit is trivial and I might add it soon, 24 bit need some extra decoding. Also, we have added WAV parsing in OWL library for C++ later than in FAUST, so I think I could replace wav parser used too.

This won’t make any improvements, because WAV file processing is handled by patch rather than firmware.