Emulating a Rotary Effect in Faust (and Teensy)

Started by niektb, September 09, 2021, 11:53:57 AM

Previous topic - Next topic

ferdinandstrat

Am I missing something? Where's the hardware part for it?

Please correct me cos I dont know alot about teensy

niektb

There's no hardware part designed yét! I first wanted to design a DSP program to see if I could get good sounding results... But unfortunately I haven't had a lot of feedback on the sound quality so it stalled a bit :)

But the hardware section would probably be a Teensy 4.0 board, combined with the audio board and a couple of peripherals (such as potmeters, analog pre and post buffering, bypass switching etc :))

niektb

Heey! New update from my side! I've picked up this project again and this time for the hardware platform! i've finished the (first version of the) schematic and started layouting!  ;D

5th image looks a bit weird with the 100ohms resistors but somehow the DNP crosses do not get printed to PDF, don't know why  :icon_rolleyes:







Digital Larry

I'm guessing that the AD part is just being used as a CODEC even though it apparently has some DSP capabilities?

I'll keep watching this thread.  When you said that the Teensy could be expanded with additional RAM, how is this done?  I'd sorta like to have 1 or two seconds of delay RAM available.

I'm also wondering about the ability to support a network stack, e.g. so I can send OSC messages from a tablet.  I suppose that one could map OSC to MIDI in the PC but that starts getting pretty complicated.

I'm not really interested in building or debugging things any more (bad vision mostly, followed by "been there, done that").

DL
Digital Larry
Want to quickly design your own effects patches for the Spin FV-1 DSP chip?
https://github.com/HolyCityAudio/SpinCAD-Designer

niektb

#24
Quote from: Digital Larry on June 21, 2022, 10:00:47 AM
I'm guessing that the AD part is just being used as a CODEC even though it apparently has some DSP capabilities?
[...]

It can be both really, from hardware perspective I kept both options open. the AD can do all the processing while being controlled and programmed from the Teensy (or not, it can also run standalone via the on-board EEPROM) using I2C but the audio can be routed to the Teensy as well to be processed there (or both are performing DSP operations, why not?)  The idea to use a AD stems from a Cab Sim project by Nathan but I wanted to experiment with Faust as well so I thought 'why not make a hybrid that can do both?'

Quote
[...]
I'll keep watching this thread.  When you said that the Teensy could be expanded with additional RAM, how is this done?  I'd sorta like to have 1 or two seconds of delay RAM available.
Via SPI. It can support both RAM and flash on the same (and it's something I realized today, I have to add a RAM chip as well and not just flash :) )
The Teensy Audio Adaptor shows the schematic: https://www.pjrc.com/store/teensy3_audio.html

Quote
I'm also wondering about the ability to support a network stack, e.g. so I can send OSC messages from a tablet.  I suppose that one could map OSC to MIDI in the PC but that starts getting pretty complicated.

The Teensy 4.1 also has a Ethernet PHY on-board. Have not really looked into it though as I'm using the 4.0 (which is smaller and I'm aiming for a 125B).

Quote
I'm not really interested in building or debugging things any more (bad vision mostly, followed by "been there, done that").

DL

Me too haha but in my case it's just a matter of being too lazy hahaaha  :icon_mrgreen:
I'd rather spend a little more time designing than to have to fix stuff afterwards :)  I also selected the components such that I can let do JLC the assembly :) (jayyy Chinese datasheets :P) (except for a couple through holes and the pedal connectors).

niektb

I've finished up the design and the PCBs are in production!!  :icon_mrgreen:

Here is a nice and fancy online viewer for the PCB (even in 3D!) and schematics:
https://365.altium.com/files/1DF0F890-AD99-4490-91D4-B7A7C4E66246

niektb

And the first proto's are in! smt assembly done by JLC. Now I need to put the through hole stuff in and build it in a box :)


ferdinandstrat

Damn that's nice! But how would one program the finished board?

niektb

Quote from: ferdinandstrat on July 10, 2022, 05:27:28 AM
Damn that's nice! But how would one program the finished board?

Hey thank you! The ADUA you can program over the (not yet soldered) 10 pin boxed header using SigmaStudio and a USBi programmer. The Teensy can be programmed via its own USB connector and the Arduino IDE :)

It should theoretically also be possible to program the ADAU from the Teensy but I have not looked into that yet

niektb

Hi y'all! It's the day you probably thought would never come but you're looking at the hardware part of this Teensy/Faust journey! I'm absolutely no craftsman so it ain't the prettiest thing in the world but hey, I didn't promise any of that, did I? ;)
As of this moment I still have to write software routines to test the hardware (such as the RAM and the flash) the power is OK and the teensy works and I was eager to share it with you guys!  :icon_mrgreen:



niektb

#30
Hee look at that! I had to hunt down some bugs in the hardware (I flipped the plus and minus of the output opamp xD) but lo and behold, I have managed to get a reverb running on it:

This audio example is from a looper into a custom boost pedal into Boss Katana with this teensy pedal in the FX loop.  I start dry briefly and then flick on the reverb :)

PRR

#31
Quote from: niektb on April 12, 2023, 03:56:12 PM...(apparently the video is too short for the embedded player)...

https://www.debugbar.com/how-long-are-youtube-shorts/
-says 15 to 60 seconds. There's a lot of bumph all over about the 60sec, not much about 15sec.

And FWIW that debugbar site may be wrong on other points, needing the YT app and needing YT-licensed music. My mate shot a 50 second self-sung "Happy Birthday" video, I uploaded the same-old way, and YT returned a SHORTS format URL.
  • SUPPORTER

niektb

#32
Yeah I know it has to do with the shorts format, but apparently the embedded player doesn't support shorts :/

Edit: aaah, I found that you can just edit the link so it returns a normal video link :)

niektb

#33
Hi all! A development update from my side! Seems I got it all to work in a fairly decent manner!

In summary I managed to integrate 3 different DSP toolchains to get the result I have now:
1. Faust 2 Teensy (https://faustdoc.grame.fr/tutorials/teensy/)
2. Teensy Audio Library (https://www.pjrc.com/teensy/gui/index.html)
3. SigmaDSP. A combination of SigmaStudio and the library https://github.com/MCUdude/SigmaDSP so I can actually boot the SigmaDSP from the Teensy (the ROM code is in the Teensy flash) so no USBi programmer is needed :)

Demo
But let's start with a demo ;)
(Forgot to mention it in the video: the loop is recorded using a cheap strat with P90 pickups through a Behringer TM300)


SigmaDSP
In the SigmaDSP I made a simple mixer project:

This allows me to have a very low-latency (3 samples instead of teensy's 128) dry signal while still keeping it digital. The parameters of this mixer block are controlled by the Teensy over I2C.

Faust
The heart of the effect is written in Faust. There is an online IDE (https://faustide.grame.fr/) where you can efficiently write a DSP algorithm. This is very nice because the develop-test cycle is very fast, with real-time compilation and graphical output of what the program looks like. When satisfied you can then export the code to get a teensy compatible .CPP and .H files which you can plug into the Arduino environment. Compared to the earlier posts I've reduced the program a bit down to be mono (because the hardware is mono) and to use less knobs. Mono is definitely less nice (not as whoosy if that makes sense :P) but stereo wouldn't fit in the 125B box :)

I realize the code could've been simplified even further because the bypass is done using a relay and dry-wet mix is done in the SigmaDSP but aah well :)
To summarize what the code below does: First the full signal runs through a simple drive simulation (using the atan function). Then it splits the signal up into 3 bands: <200Hz, 200Hz - 800Hz and >800Hz. The lowest band passes through unaffected, the middle band is amplitude modulated and the high band has a combination of FM, AM and a modulated low-pass filter. Then the combined signal is fed through a peak EQ (which can boost up to 10dB at 2KHz). Et viola!

import("stdfaust.lib");
/* ROTARY EFFECT */
ms_sample = ma.SR / 1000;

//UI Elements
rot_bpc = checkbox("Bypass");
t = checkbox("Chorale/Tremolo");

slow_rate_knob = vslider("[04]Speed[style:knob]", 0.5, 0.1, 1, 0.01) : si.smoo;
ramp_speed = slow_rate_knob * 4;
fast_rate_knob = slow_rate_knob * 8;

low_lfo_freq = slow_rate_knob + (fast_rate_knob - slow_rate_knob) * en.asr(ramp_speed*3,1,ramp_speed*3,t) : /(1.1);
high_lfo_freq = slow_rate_knob + (fast_rate_knob - slow_rate_knob) * en.asr(ramp_speed,1,ramp_speed,t);

// LFOs
high_lfo = 0.5*os.oscsin(high_lfo_freq)+0.5;
low_lfo = 0.5*os.oscsin(low_lfo_freq/1.1)+0.5;

// Dynamics Parameters
rot_waveshaper(_) = (1/atan(rot_k))*atan(rot_k*_*rot_gain)
with {
    rot_gain = vslider("[02]Gain[style:knob]", 1.0, 0.1, 10, 0.1);
    rot_k = 2;
};

rot_volume = _*rot_vol
with {
    rot_vol = vslider("[03]Volume[style:knob]", 1.0, 0.001, 2, 0.01);
};

max_delay_ms = 30;
rot_trem_depth = 0.6;
rotary(_) = de.fdelay(delay_buf_size, high_lfo * max_delay_ms) * am : fi.resonlp(fm,0.7,1)
with {
    delay_buf_size = max_delay_ms * ms_sample;
    am = 1-rot_trem_depth*high_lfo;
    fm = 2000 + 2000 * (1-high_lfo);
};

rot_dry_wet(x1,y1) = (wet*y1 + dry*x1)
with {
    wet = dw;
    dry = 1.0-wet;
    dw = vslider("[05]Mix[style:knob]", 1.0, 0.0, 1, 0.01);
};

rotary_effect = ba.bypass_fade(100,rot_bpc, (_ <:
        _,(rot_waveshaper(_) <:
        low, hi :
        +) :
        rot_dry_wet :
        rot_volume
    )
)
with {
    low = fi.lowpass(1, 800) <: fi.lowpass(1,200), fi.highpass(1,200) : _+_*-low_lfo;
    hi = fi.highpass(1, 800): rotary(_) : rot_horn_eq;
    rot_horn_eq = fi.peak_eq_cq(gain,2000,.4);
    gain = vslider("[07]Horn[style:knob]", 5, 0.0, 10.0, 0.1);
};

process = hgroup("Rotary", rotary_effect);


Teensy Audio Library
In the Teensy Audio Library I drew this diagram, adding amp1 as placeholder for where I would put the Rotary Effect (importing custom modules is not possible in the graphical design tool so that's a manual step for later)

to make the sound less dry I've added Teensy's freeverb implementation. It sounds quite decent but is rather noisy so I added a low-pass filter post-reverb to filter some of that away. Of course it would be possible to develop a reverb in Faust and put it there  ;)

Arduino IDE
And finally I plugged it all together in an Arduino Sketch and wrapped it inside the code for the potmeters and display etc. that I've written myself.

I do have all these content in a repository but it's a tad messy and not ready to share with the big world :D but if you want to have a peek you can drop a PM :)

Observations and known (hardware) issues
(in case you want to build something similar ;))
- Generating the Master Clock for the SigmaDSP on the Teensy. Turned out to be quite annoying. The Teensy Audio Library I2S is required to be the master in which it generates the master clock. This is annoying cause it effectively disables the option to run the ADAU1701 in standalone. The DSP will also simply shut down when you upload new code to the teensy. It also takes some fiddling to get MCLK frequency that the SigmaDSP requires. In the end I got this function which gives me the proper frequency:
// Set the master clock frequency to 11.2896 MHz
void setMasterClock() {
  uint32_t register_value = ((F_CPU / 11289600) / 2) - 1;
  *(volatile uint32_t *)0x400E4490 = 0x00080000 | (register_value << 6);
}


- Analog circuitry problems: + en - on the output op-amp were reversed. Input Pad doesn't work (probably because the 100k pull-up (R22) is too big. 10k is a better value I think.

Mistake in placed/not placed: (R38 shouldve been placed instead of R12) Means that we only have green instead of bi-color ;)


- Memory Management. Current I had no luck in getting the external RAM to work. (The external flash doés btw but I have no use for it in the current effect). Trying to share the chip select between the chips with an inverter trick was a bad idea :)
Also I'm only using RAM1 from the Teensy.

It should be possible to get the Faust code to make use of RAM2. At least the 30ms delay line I use for the pitch modulation. This would free up a lot of RAM1 (I was now balancing on the edge of what fitted and what not) but that's not trivial :/
https://faustdoc.grame.fr/manual/architectures/#custom-memory-manager
https://faustdoc.grame.fr/manual/optimizing/#managing-dsp-memory-layout

- The teensy was overheating. Too busy handling buttons I think :P it's also somewhat expected with a closed box where no air can flow ::) I've underclocked the Teensy to 450MHz and now the temperature sits around ~85degC, that's fine I think. With the underclock the CPU spends around ~20% of it's time on audio processing, I think there's room for more effects  :icon_mrgreen:

Well I hope you had a nice read and that I made you enthusiastic for the combination of Teensy and Faust!
Cheers,

Niek

niektb

I decided to call it a day :) I've added the option to store the current set of parameters to an EEPROM. I've also published the source code to Github: https://github.com/niektb/teensy_rotary_redux_mono
I have grown quite fond of the sound, overdrive doesn't sound as bad as I initally thought ;)  Here is another demo :D This time with a normal amp instead of a Behringer Sansamp clone :D