The DSP Livecode / Prototyping Thread

so I bought some I2C OLEDs, aaaaand the Axoloti I2C OLED devices all use I2C 0x3C or 0x7D and the displays are 0x7A or 0x7B. All the 0x3 OLEDs I seem to find are also 0.96" vs 1.3" so all the work I’ve done designing around the 1.3 is… either wasted, or I need to figure out how to get the Axoloti stuff to use different addresses… tbh it’s a pretty big let down and I’m kinda tired of spending money on things that won’t work for me. I guess that’s the cost of ignorance and impatience. I’ll be able to use them with other stuff, at least.

Maybe I can use a cheap lil QT Py or some other tiny microcontroller to translate the I2C crap, or modify the Axoloti modules to use different I2C addresses.

I haven’t dug too far into it and I don’t have an OLED around to test, but it looks like the axo files define the I2C address. I’m wondering if you change it to 0x7A or 0x7B if it’ll work. From a technical standpoint there’s no reason why it shouldn’t; it’s all in software and it’s just broadcasting that address on the I2C lines so the slave units accept/reject it. I guess there’s a question of whether the OLED controller codes it’s sending lines up with the OLED you have, but that’s a step past getting it to talk.

It looks like \ksoloti\1.0.12\axoloti-contrib\objects\tiar\HW\HW\OLED128x64.axo (or whichever one you’re using) has the definitions:

<attribs>
         <objref name="scope"/>
         <combo name="type">
            <MenuEntries>
               <string>SSD1306</string>
               <string>SH1106</string>
            </MenuEntries>
            <CEntries>
               <string>1306</string>
               <string>1106</string>
            </CEntries>
         </combo>
         <combo name="I2CADDR">
            <MenuEntries>
               <string>0x3C</string>  // Think these are just friendly names for the menu
               <string>0x3D</string>  // Think these are just friendly names for the menu
            </MenuEntries>
            <CEntries>
               <string>0x3C</string>   // Potentially change these?
               <string>0x3D</string>   // Potentially change these?
            </CEntries>
         </combo>
      </attribs>

You could probably just make a copy of the axo/axh files with new names for testing. No idea if it’ll work but seems like a quick fix if it does.

guy on the Ksoloti Discord told me that:

0x3C <<1 is 0x78
0x3D <<1 is 0x7A
Confusing I know.

so apparently they should work, but I now have OLEDs that use both lol. I can always return the ones I don’t need, the new ones are only 0x3A and cannot be changed.

Now to hook all this up to an Axoloti…

EDIT so while figuring that out I realized I had my I/O planned out all wrong so the labels on the other side of the plate are now wrong :smiley: Stems from switching to I2C display vs SPI… But what’s another few grams of PLA and an hour… I needed to make a revision to a cutout for the display anyway

1 Like

Axoloti is Easy Mode :trade_mark: :upside_down_face:

No idea how to add more than text, yet XD

The Big Ass Knob :trade_mark: is temporary, it’s a touch too large

EDIT Finally got it reading the encoder. I was about to give up on it. I think I had the wiring wrong because I’m, well, wiring it upside down :upside_down_face:

1 Like

That knob is hilarious, though. Seems rather fitting for it to be some kind of cryptic mode selector :magic_wand:

1 Like

It’s the second one I bought. The first is on my Proteus 2000 as the main data knob :smiley: The P2K is my go-to piano over plugins/sample libraries.


this right here tho…

@KvlT (or anyone else!), you ever mess with wavetable stuff outside the usual DAW/VST offerings? I’m familiar with Serum and the usual bunch, but less so the theory, creation and inner workings, especially in a live/livecoding environment.

Over the holidays I helped a friend out with a M4L device that implemented a couple of basic wavetable players in very specific ways (rigged up with some other stuff he wanted alongside some interesting controls), and it got me thinking about what all could be done with it as it’s not something I’ve explored beyond picking prebuilt tables and sticking some modulation on them.

I’d be interested to hear any experiences with them, specifically the creation of the wavetables themselves, fun ways to potentially scan through them, and any general wacko ideas about things to try. I’ve got a list of stuff to run through but extras brains are always good.

have look looked at the source code for Braids? I’m also positive I’ve seen a video on the PPG wave and how they do the lookup tables, etc. Or maybe that was about NCOs… (Numerically Controlled Oscillators).

Semi-related this is free for now, a wavetable creator thing:

But I digress. Speaking of M4L I’ve considered getting a Daisy Seed device of some sorts as they can be programmed with Max or PD (or C++ stuff, too, that’s an option), some other ways. Working with the Axoloti patcher is part of that. $24 for 65MB of RAM and a 480MHz M7, or for $68 there is the Seed Pod which is an audio platform with a handful of controls and audio/MIDI I/O. I dunno, exploring a few things but trying to temper my impatience with a willingness to learn more and less shortcuts lol. They are out of stock on their Eurorack and desktop module platforms but those are expensive as hell

Also, the Seed breaks my rule of no more Micro USB :upside_down_face:

1 Like

Funny you should mention Braids - the original brief was “kinda like Braids WTx4 but with some other stuff”. After digging into what he actually was trying to accomplish it drifted away from that a bit, but it did give me cause to pick through the code. I think that would probably have been more helpful if I was trying to do this for resource-constrained hardware. All the MI stuff is a masterclass in stuffing as much functionality as humanly possible into that space, but it makes the code both hard to read and harder to extrapolate to a wide-open system like a PC. I learned some things but it hurt my brain to do it lol

The basic implementation wasn’t that tough. It’s just a buffer of waveforms and you pick out the parts you want to use. I’ve yet to find a more reasonable setup than just stacking one after the other, reading the whole file in, then addressing the chunks (64/256/512 samples, etc). Then depending on what you’re doing interpolate between and maybe throw some band limiting/filtering in for good measure. Looks good, sounds good, plays good.

What I’m just starting to work on is tunable cross-modulation between multiple wavetables as well as chaining or routing several wavetables into a matrix mixer sort of setup where the actual playable wavetable is a partial sum of all the inputs. Smart money on that failing horribly lol

I’m also looking at potentially using non-generative sources (ie raw audio, not something set up specifically as a wavetable). If that works, I have a hair-brained idea about using real-time audio input so you could make on-the-fly wavetables out of someone talking into a mic or the output of a mixing desk and then playing it while it happens, sort of like Serum meets dub sound system. No idea if it’ll work but it’ll be fun to try.

1 Like

This does seem kind of tricky; the real question is whether standard wavetable synths are just two values at both ends and the rest is simply interpolated values between the two, but most synths (and wavetable buffers) seem to be more complex than that, with multiple, varied ‘steps’ with their own interpolated stages in between for more complex curves and detail.

I’ve never tried implementing anything raw aside from basic / non-buffered fundamentals but this definitely sounds like an interesting challenge. I’d love to simply attempt to crossfade between basic sine / squares to try and see what snags show up, along with even a few standard skewing algorithms. Getting that far would feel like a crazy accomplishment, so I think you’ve got a better handle on this stuff than you think!

I’ve been eyeballing these for a long time, too. It’s probably not too far from what can be done with an ESP32 with some amplification or something, but I love how it’s just ready to go out of the box. Being programmable in so many different environments makes it even cooler than anything else, imo.

I’m not sure exactly what hardware guides like these use, but I bet anyone with a pocket full of goods could use something like this to get up and running, too. If I wasn’t scared of frying the few components I have, I’d definitely start here :sweat_smile:

2 Likes

100%. There’s a ton of work already done on this and as usual I’m recreating the wheel a bit. What I ended up doing, as I usually do when I get lost in the woods, is remind myself that the goal is to output a single value between -1 and 1 to the DAC (really 48000 values a second), and work back from there. All the cool visualization stuff you get in a VST goes out the window and it turns into a math problem with variable order of operations that results in a string of single numbers.

Basic workings, feel free to skip

You start with a .wav file (or whatever format) - it has X number of samples based on what you want your length/resolution to be, lets keep is small and simple at 64. So the wav has a a 64-sample sine followed by a 64-sample square, and that’s it. We read that into a buffer and tell the software that wave #1 is samples 0-63 and wave #2 is 64-128. If you want to play a square wave, just loop 64-127 over and over. So far so good.

To move between the two, for each 64 steps of your loop you read the value at both wave 1 and wave 2 and interpolate between them, scaled by where you are in-between (ie the midway point is just 0.5), basic linear interpolation. The math ain’t hard but gen makes it dumb simple with the mix operator which does linear interp for you. Map a knob to the position/contribution and you can dial in where you are between them.

So now you can easily move through the “in-between” stages of two waveforms. To get more complex, throw a triangle wave in between the sine and square in your .wav - now you have 0-63: sine, 64-127: triangle, 128-191: square. Nothing really changes except you have to tell your software that the wave file is bigger and where the indexes are. If you turn your knob to halfway, you get a triangle, anywhere else and it interps between either a sine and triangle or triangle and square.

Where it gets interesting and more complex is expanding the idea to multiple dimensions: your software indexes all the waves into a 2D (or ND) matrix by row and column. You pick row 3 column 4 and hey, that’s a sqaure wave or whatever is in that spot in the .wav file. The actual file is still just a linear set of waveforms one after another, you’re using the software to ‘chunk’ them into discrete waves by indexing into the big wave in a specific way, in this case an NxN matrix. It’s purely organizational but it does give you another way to approach using it. But at the end it’s doing the exact same thing as the trivial case: interp between two numbers based on position index.

It’s pretty easy to extend this to a 3D setup, after all the “higher dimensions” are really just an organizational/software cheat - it’s still just a bunch of waveforms one after another in a wav file. You pick X=2,Y=4,Z=5 and it figures out where you’re talking about and indexes a little 64 sample chunk. But there’s also the idea of an actual 3D audio “landscape”, think of heightmap/terrain map but for audio, where z = f(x,y). So you’re feeding it positional data and it’s returning a single z value (the “height” at that location), and you can navigate that landscape by changing your x/y coods. I’m not sure this is something you can compute on the fly of if it’d need to be pre-computed. It’s something I’ve only read about but I get how it works in theory and am exited to try it.

Playback is sort of it’s own thing. Pitch is just how fast you loop through the samples. You mess with it the same way you’d mess with any other wave playback: fucking with the speed and position. Easy enough to base it on curve of some kind or an LFO, though you could also do reverse or granular or whatever. You’re really just changing the way the software indexes into each wave buffer.

So where does that leave the matrix mixer thing? It’s basically two steps - compute each input as above then scale the interp of those numbers based on the relative values of the mixer - input #1 is half way between a sine and sqaure at 30%, input #2 is 90% supersaw 10% sine at 70%, etc. You’re just doing all the individual computations first and then doing the math to mix them. Still not sure if it’ll work like I’m expecting or product anything interesting.

1 Like

Rebel Tech’s OWL platform uses the Daisy Seed, too. Befaco’s Lich also runs OWL so it can be programmed the same way. There’s also Faust which I’ve been looking at but don’t know enough about it to try anything, yet. SynthUX Academy’s projects also run a Daisy Seed. Iirc the Seed was literally created for audio stuff. I wish I knew before I got a Teensy for Christmas lol. People do make USB C for it but it uses up some pins iirc.

I know Teensy has their own sort of “patcher” but what it’s for mainly is to just spit out code to set up your audio I/O and other relevant devices. You connect it all up and then it gives you C code to paste into your program. Including working with their audio shield.

I added this to my wishlist for someday, saw it and thought of your bare metal vs library post

basic I2C mics exist to go nuts with :eyes: or was it I2S… I think those are mostly DACs…


EDIT - Praise the Omnissiah, I found a Leonardo clone with USB C :smiley:

EDIT AGAIN here’s another open source wavetable synth for VCVRack called Terrorform that describes itself as “An extensive wavetable oscillator that lets you explore and rip apart wavetables in many different ways.”

1 Like

lol I was just going to use an SM57 into my interface since it’s all sitting right here :smiley:

That looks pretty awesome. I’m gonna give it a spin. Thanks for the heads up!

1 Like

lol SM57 was the first mic I used with my Polyend Tracker+ I bought a $6 XLR to TRS cable XD

My 57 is beat to hell looking and I love it. I think I paid $30 for it


I found my first Axoloti patch ever, a drum machine and I remember at the time laughing about how “weak” the CPU in these things was as I hit 35% or something on just the kick and snare, but now it’s at 36% with that kick, snare, two cymbals, and a clap with some associated filters and LFO(s). I’ll probably add some toms to it now that I’ve added cymbals and a clap.

A simple 808-style kick, ie a sine wave and EGs for pitch and decay

808-ish snare with triangle, noise, and EGs for pitch and decay

I tried an 808 cymbal and it just didn’t sound right despite the 6 specifically-detuned square oscillators. But there’s a really fun cymbal module that sounds electronic and not like white noise. Added some filters I found, not the usual lp, bp, etc. Doubled it up, might try to figure out how to do a choke group with a VCA or something

Clap is using a Braids Clocked Noise model and other stuff with a weird 555 LFO on the output volume. It’s no 909 clap, but I think it sounds unique.

@Artificer Befaco’s Oneiroi has a wavetable oscillator that reads from the looper so the code for that might be useful to you “Wavetable oscillator that uses the Looper buffer”


There are two Ksoloti Gills on Reverb priced at $850 lol. The kit from Thonk is $270 shipped and tariffed. This feels like a side hustle opportunity :eyes: and I could really use the spare cash :upside_down_face:


Apparently this thing lets you Live Code :trade_mark: in Eurorack

I know nothing beyond that. They just showed it to me XD


Well, this Leonardo clone with USB C is f’ing DOA (it’s just a USB C port but requires USB A connection. Premium Chinesium be like…)

But it works. So now I have a USB C connected Trellis, but I am salty it will not work with an actual USB C port :upside_down_face: I think I could add a resistor in the right place to trick USB C to work properly. That’s how it signals what is what. or more likely it’s just a limitation of the ATmega32u4. But if I connect a USB C to A adapter between the USB C port on my Mini and the USBC Leonardo it all works ¯_(ツ)_/¯

I’ve been eyeballing this (and the one from No Starch Press) too!

The only thing holding me back is that they both require a very specific STM32 Nucleo board (respectively), and the one I have is apparently underpowered / on the ‘not recommended’ list for both. So these are probably excellent starter books, but I guess you also have to factor in the cost of the board, otherwise the example code and specific techniques won’t work.

I really want to go all in on this once I feel confident with x64 ASM, but getting really close to the hardware really feels rewarding for some strange reason!

The cool thing about this one is that it starts you out in the Linux terminal, so if that’s familiar to you at all, you can at least cut through the proprietary / corporate IDE stuff. I’m not sure about the other one, but I’m hoping it’s not too far off.

Man, if I ever made it that far, my biggest fear would be optimization; if something runs too slow after I’ve figured all of that out, I think I would need to lay down for a while. I really can’t wait for updates on this thing, and I’m excited to see how it turns out!

1 Like

well I think I just managed to plug a LiPo battery in backwards and burn out the charging circuit of this Adafruit Metro board… there was a chip beneath my thumb and now that thumb smells terrible lol, and so does the tiny smd chip next to the connector. And the charging circuit LED no longer lights/flashes. The connectors are keyed, though, and I plugged it in again very briefly and caught a wiff of that smell again.

welp. thanks cheap shitty battery

plugged a lipo battery into an Adafruit Metro board with a charging circuit and only thing I got was a bad smell and now the charging LED no longer functions >_> welp. One of my thumbs smelled, too, I think I shorted something when plugging it in :woman_shrugging:t2:

2 Likes

Damn, that sucks. That’s a really solid board, too. I’m not sure what their intended peripherals are, but I think that’s the one I used for my weird MIDI controller a few hundred or so posts ago