Reverb Effects Box - Code - Page 1
Forum section: electronics / general

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 15, 2020, 09:29:15 am
content: It's nearing a close as I finish up a few optimizations; a good time to show off some of it, then!https://github.com/T3sl4co1l/ReverbStill have to take pictures; schematic is kind of superfluous with the netlist spelled out in several places, and the few analog bits being fairly obvious and straightforward. Build is on protoboard. Lots of wirewrap wires tacked down. Lots...Fits into a fairly neat case at least, and I also took the time to make a fairly proper one. Out of copper clad, of course. It's a base board, and two shell pieces, which slide onto it, held together with one lone screw. Tedious to make, but neat to pull off.There's a UI menu driven by four pushbuttons and a 2x16 LCD, and a serial console. Here's what that looks like:https://www.seventransistorlabs.com/Images/ReverbConsole1.pngWill have to take video as well, to show off the menu as well as the sound effects.How's performance? It's got a digital biquad filter (5 16x16+32 bit MAC (multiply-accumulate) operations), high pass filter (1 8x16+32 MAC), and up to 4 reverb tabs (GPIO driven SRAM + 1 8x16+32 MAC): a total of 10 MAC operations, plus assorted IO, all running at 25kS/s. That's over 250kMAC/s, with a peak rate around 800kMAC/s. Not bad for a puny 8-bitter.Tim

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: May 15, 2020, 10:27:36 am
content: Thanks for sharing!Is there any video showing it how it sounds in real?

author: Yansi
author_rank: Super Contributor
timestamp: May 15, 2020, 10:55:47 am
content: Could you please post some sound demos?How does the DSP processing structure look like? Could you please draw a simple diagram what it does?Seems it runs on xmega64?Very interesting project, thanks for sharing.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 15, 2020, 06:16:13 pm
content: Code:Important part is at the bottom of dsp.c, in the interrupt vector:{int16_t samp;samp = dspGetLiveSample();samp = dspHighpass(samp);if (dspParams.taps > numelem(dspParams.dlyList)) {dspParams.taps = numelem(dspParams.dlyList);}samp = dspReverbTaps(samp, headAddr);//Filter the reverb buffer to give a more natural rolloffif (dspParams.filtEn) {dspParams.filtEn = true;samp = dspBiquadFilter(samp);}writeDac(samp);writeRamWord(headAddr, samp); headAddr += 2;}The two important functions in turn (dspReverbTaps and dspBiquadFilter) are chains of fetching and MAC. Everything is summed into the same (int32) accumulator as much as possible, then rounded off (return (int16) samp).Everything's controlled by the state vector dspParams, which is written to by menu and console functions. The filter and number of taps can be controlled, as well as their parameters. (The writes aren't generally atomic, as the worst that can happen is one or a few samples gets corrupted. If this were a system with real life consequences, like a motion control, it would be well worth implementing.)Interestingly I only put in 16 bits of delay range (which is a few seconds worth, more than enough), but the RAM chip is 512k, hence the read/writeRam functions taking a uint24 (an AVR builtin) and performing all the requisite port writes.Hmm, I should also dly << 1, so odd settings don't cause misaligned reads.(Which sounds like white noise more or less, as you'd expect.)Tim

author: Yansi
author_rank: Super Contributor
timestamp: May 17, 2020, 10:12:00 am
content: Aww thanks, now I see what you did there. Still, would you like to share some sound demos and tap/filter settings to produce them?I like to toy with audio/DSP a lot (on an amateur-level), never tried any reverb as I have never understood how one works.I might try now.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 17, 2020, 04:08:33 pm
content: Out of curiosity, what do you call "reverb taps"?Basic reverb algorithms (like the Schroeder reverberator) rely on combinations of comb and all-pass filters. More evolved algorithms usually elaborate on this (not talking of course about much more sophisticated algorithms which require a lot of processing power.)Is what you implemented not more like a "delay box" of some kind?

author: Yansi
author_rank: Super Contributor
timestamp: May 17, 2020, 04:21:37 pm
content: His reverb is a sum of a multiple fed back delayed signals. (couple different echos together).

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 17, 2020, 04:25:12 pm
content: Quote from: Yansi on May 17, 2020, 04:21:37 pmOK, that's what I thought. This is not a reverb effect actually.Not that the project itself is not impressive already, given the target. But just thought the title was a bit inaccurate.

author: Yansi
author_rank: Super Contributor
timestamp: May 17, 2020, 06:01:34 pm
content: Why does not that count as a reverb?As far as I see, it is exactly what for example Hal Chamberlin describes in his book "Musical applications of microprocessors" as a "Tapped delay line reverberator".Although I have never tried implementing any of the reverb structures from this book, I would highly recommend getting a copy and reading.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 17, 2020, 07:00:44 pm
content: It's the comb section (using a tapped delay), with feedback, but without the allpass sections; I don't have enough accesses (each read or write cycle takes 0.77us) or MACs to do that, though I definitely have enough RAM. The difference I think is fewer impulses/sec (more "flutter") and more widely varying gain (because it's all comb).This site is fantastic by the way:https://ccrma.stanford.edu/~jos/pasp/Artificial_Reverberation.htmlIf you have an STM32 platform for example, you can definitely make a full reverb stack, and you'll probably have enough RAM onboard (or trivially added with bus interface hardware) that the read/writeRAM functions can be replaced with macros. Can afford 16 bit analog converters too, some may have these integrated (or the ADCs anyway), or perhaps interrupts can run fast enough that DAC oversampling can be done as well. (Note that I'm doing 8x oversampling at 12 bits, which helps a little, but there's no way I can oversample the DAC, unfortunately.)I'm using the onboard (XMEGA) 12 bit ADC, and an external 12 bit DAC. It's definitely low enough to have noticeable quantization noise. Internal representation is ca. 15 bits, thanks to oversampling -- and this also helps numerically, but the actual accumulators are 24 or 32 bits which implies I could keep a lot more accuracy if I maintained that format between cycles. But there's not enough time to do that, either, so there will be some rounding.That said, even somewhat narrow biquad filters seem to work, without incurring noticeable rounding error; I did a, what was it, I don't have the inputs written down anywhere, I did happen to save the coefficients to the device though:a0 = 1148, a1 = 0, a2 = -1148, b1 = 30386, b2 = -14089. (Note these are scaled by 16384, and b1 and b2 are negated, to suit my internal format.) Doesn't seem to be particularly noisy, and very much sounds like a shitty telephone call, or a narrow tunnel. Think it was a modest Q bandpass centered around 400Hz or so.I notice biquads don't seem to have great high frequency cutoff, which is a shame; it would also be neat to have multiple peaks (say emulating a vocal tract, since my primary application is using this with my Theremin), but again that would take way too many rounds of filtering, and I can barely afford the one on this platform.I should look at CIC filters, too; probably a few stages could be executed in the same time as the biquad.Tim

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 17, 2020, 07:08:36 pm
content: Alright - didn't look closely at what you did exactly. Then yes, it's at least close to a reverb effectI also suggest reading "DAFX: Digital Audio Effects". Pretty neat.I have implemented a few reverb effects, and IMHE, the Schroeder approach (comb + allpass) + some additional filtering was the bare minimum to get something acceptable in terms of "reverberation". Of course, what you did here was likely not meant to be "hi-fi" either, and it's impressive given the platform. I'd be curious to hear some samples.

author: Yansi
author_rank: Super Contributor
timestamp: May 17, 2020, 07:37:53 pm
content: I would like to try this on an STM32, unfortunately no time for toying now. Too busy with work and other stuff.

author: radioactive
author_rank: Regular Contributor
timestamp: May 17, 2020, 09:55:58 pm
content: Quote from: Yansi on May 17, 2020, 04:21:37 pmI don't really know what it is classified as, but for the previous rev of the dsp_ice board, I just filled up a block ram and then start adding it back into the generated audio. Had to keep dropping some lsb's or you start getting too much re-generation. I think it sounds like delay + reverb combo. Fun stuff.https://github.com/tvelliott/dsp_ice/blob/master/firmware/audio_synth_test/dsp_ice_audio_synth_test.mp3

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 17, 2020, 10:05:58 pm
content: Video uploading... enjoy some photos for now:Top view (assembled). Plug has +V, GND, signal in and out (two GNDs, interleaved for best signal quality).Better view of the front panel inside. Made connectors for everything, so the main board and cover can be completely disconnected, and also the serial/PB board can be unmounted (which is also slotted in place, secured with only one screw).Setting up the geometry for the pushbuttons (and the holes for their caps, and their pins), and the board, was an... interesting exercise. Managed to turn out alright...Note the end cap is slotted and tabbed. The base board slides into the top piece, and the end cap slides onto that. One screw in the end cap secures the whole thing!Labeled:https://www.seventransistorlabs.com/Images/Reverb2_Labels.jpgBetter view of the base board:https://www.seventransistorlabs.com/Images/Reverb3.jpgLabeled:https://www.seventransistorlabs.com/Images/Reverb3_Labels.jpgAnalog stuff on the left, and some power. There's a 3.3V regulator in the middle, between the cord and programming header.I actually needed a -5V (or so) supply, for the DAC reference -- the DAC1209 is a multiplying R2R type, with internal feedback resistor. This makes it easy to use with just an external op-amp (convenient for its day), but forces inverting operation which is dumb. So, easiest solution I figured was to use a negative reference, and easiest way to do that from arbitrary supply (5-10V input) is... a NE555P.This is shunt regulated with a TL431 to -5V. (The DAC seems to be perfectly happy with 5-15V supply, so it's straight off the input, no worry about regulation. Still TTL compatible inputs. Pretty handy.)In Notes.txt, I listed off some DACs I have on hand. I probably would've been better off with the MCP4922 -- assuming I have a free SPI port anyway, that can be used while, say, writing RAM. I wonder if a serial SRAM would be reasonable as well? Still have to do the address calculations, but could maybe interleave some calculations (previous tap MAC operation?) while it's clocking out. Though if it's addressed by 24 serial bits, that's going to take quite a while...Would also be neat to use the XMEGA with external bus interface -- the top A series model has this. But economically speaking, you're way, way better off just getting a STM32, even the simplest one...Back side view. Serial port (asynchronous 115.2kbps, RS-232) and programming port (AVRISPMKII compatible). Didn't put a wall on this side, because, with the ports there, there's not really any way to have one slide into place, or to keep access open for soldering. Could add some tabs to hold a 4th piece on top of everything, I suppose.Tim

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 17, 2020, 11:53:36 pm
content: And the sound and UI:Tim

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: May 18, 2020, 05:51:33 am
content: Thanks for sharing, I recommend using STM32H750VB, it's under 5$ in LCSC and can do it @ 480MHz, also I recommend using CS4344 as the Audio DAC it's around 0.5$ ,you can use CS5343 as the Audio ADC, then you have enough RAM, CPU power and DAC quality, not to mention it's cheaper and easier than XMEGA.

author: Yansi
author_rank: Super Contributor
timestamp: May 18, 2020, 09:11:14 am
content: H750 is I'd say crazy overkill, just for a reverb. You could likely make a basic 16 channel audio mixer desk with it. Way to much hassle to even get the MCU running in a state where you can even begin laying some reverb code.Even the well known cheap and abundant STM32F103 is likely more then adequate for a decent reverberator.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 18, 2020, 06:51:48 pm
content: Yeah something like that, you might as well run Quake on it, with its multichannel sound mixing system; and a software MIDI synth driver.(Not that Quake came with a MIDI sound track, unfortunately.)Wonder if it's enough to run Q3 actually.. maybe not looking so great without graphics acceleration. Got to imagine the engine itself isn't actually a big deal though.Tim

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 18, 2020, 06:59:05 pm
content: Helper to design biquads:https://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/

author: themadhippy
author_rank: Super Contributor
timestamp: May 18, 2020, 07:20:45 pm
content: But does it make a boooiiiinnnnngg sound if you hit /kick it?

author: Yansi
author_rank: Super Contributor
timestamp: May 18, 2020, 09:28:57 pm
content: Yup, a microphone and a few handclaps would make for better demo than the squealing of theremin.plsssss!

author: ali_asadzadeh
author_rank: Super Contributor
timestamp: May 19, 2020, 07:04:51 am
content: H750 is great, if it's ovekill, then something new maybe come to your mind to add to the mix, the price is good enough to include it

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 20, 2020, 01:48:41 pm
content: Huzzah, hand optimizing has yielded significant gains. I have enough free cycles now that it appears 6 delay taps and 2 filter stages are possible!Also addressed the LCD/UI hangup issue; maybe it will slow down or crawl at nearly total CPU usage, but it's fine for now.Flash usage has also dropped by ~200 bytes, not that that's very important but every saved instruction is a saved cycle (or two) and extra so for inner loops.Tim

author: T3sl4co1l
author_rank: Super Contributor
timestamp: May 21, 2020, 06:13:37 am
content: A quick shortcut for that biquad calculator:https://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/Code:javascript:(function() { var conv_count = 0; var ret = ""; document.getElementById('biquad_coefsList').innerHTML.split(" ").forEach(function(x) { if (Number.parseFloat(x)) { ret += ", " + (Math.round(Number.parseFloat(x) * 16384 * (conv_count >= 3 ? -1 : 1))); conv_count++; } } ); alert(ret.substr(2)); })();Save this in a bookmark and hit it once you've entered values. Returns properly scaled and signed parameters in order. Quick one-off scripts for formatting and calculating stuff, so nice to have.I may later add a filter calculator menu; would be pretty cool, and not cost too much code space (one-offs of advanced functions, pffbt, execution time doesn't even figure). Looks like it uses exponents (for decibels and other math), tangent, square root, and basic arithmetic. Nothing a floating point library can't handle, or it would also be fun to implement them myself, just because. Say 16.16 fixed point, within some reasonable degree of accuracy.Tim

author: T3sl4co1l
author_rank: Super Contributor
timestamp: June 08, 2020, 10:50:11 am
content: Update committed, if anyone's curious what the artisinal bespoke assembler optimization looks like, among other things.https://github.com/T3sl4co1l/ReverbTim