MUFF WIGGLER Forum Index
 FAQ & Terms of UseFAQ & Terms Of Use   Wiggler RadioMW Radio   Muff Wiggler TwitterTwitter   Support the site @ PatreonPatreon 
 SearchSearch   RegisterSign up   Log inLog in 
WIGGLING 'LITE' IN GUEST MODE

Best options for Low-Latency DSP?
MUFF WIGGLER Forum Index -> Music Tech DIY  
Author Best options for Low-Latency DSP?
robin87
Hi!

I have set my mind on building a simple, voltage controlled delay line suitable for Karplus Strong, comb filtering and similar tasks. I’m not interested in a self contained KS or digital delay module, as I’d prefer to keep the feedback path analog and patchable. A digital BBD + clock driver, basically. Sounds simple, right?

So, in order to get the very short delay times I need (well past <1 millisecond preferably), I’d have to keep the roundtrip latency to a minimum. Which probably rules out the well established DSP approach, using block-based processing and audio codec ICs with some sort of ARM processor. I’ve dabbled around with both the axoloti board and a teensy + audioshield and the roundtrip latency was too high to do high pitched KS with external feedback on both. Even with per-sample processing, the codec still introduced about 1ms of latency. I don’t have a Rings or Clouds around to check, but I guess the popular WM8731 will give me similar results? I was not able to find anything about this in the datasheet.

The feedback routing, filtering and mixing will be done in the analog domain, so all that’s left to do for the processor is to feed the input to a ring buffer, lookup the position of the read pointer based on the CV input, interpolate between two adjacent samples and pass the result to the DAC.

The challenge will probably be to get the signal in and out as fast as possible. After doing some research, the best option for high speed conversion seems to be a SAR ADC and a String DAC. Expensive, I know.
Is there any downside to using high speed converters for audio, except for higher cost? There’s no filters included like with codec ICs, but with a sufficiently high sample rate, that shouldn’t be much of a problem.
Am I missing something? How about noise?


Has anybody looked into something similar? If so, I’d love to hear your suggestions!

Robin
guest
is the issue youre facing that most platforms do batch processing of the data: ie data comes in, goes to a buffer, then the next N samples are calculated and sent to another buffer where they played out from? so total delay is the delay line plus the processing buffer?

on the microdec (http://wiki.openmusiclabs.com/wiki/MICrODEC), i processed each sample as they came in, and then sent them right out. i used the WM8731 at 44ksps, but it could be run at 88ksps, so it was essentially down to a 1 or 2 sample delay, depending upon how you did your accounting. so 22us or so. with an ARM processor you could run a codec at 192ksps and really push this down.

but, i think if you want really small delay times, doing it with a fixed sample rate is going to be an issue, as changing the sample time will be choppy. you could do interpolation, so maybe it wouldnt be that bad.

how many samples did you want to have? going the analog BBD route would limit this, as they can only be clocked so fast (200kHz?), and they have bad SNR. you could do a digital BBD with a sigma delta converter running in the 10MHz to 20MHz range. then, if you had a HF VCO you could smoothly change the delay time.

one other thing to look at is Bela for the beaglebone. its a low latency audio library, but i think the latency they are talking about there is from CV inputs to actuation, but i could be mistaken. i suppose you need low latency in the audio pathway for the CV to have low latency.
Synthiq

At 48ksps, the WM8731 can realistically only only use mode 0 or 1 to achieve 20kHz bandwidth so the delay in the ADC+DAC alone will be 0.48ms or 0.79ms. Increasing the sample rate to 96ksps and using mode 2 or 3 would reduce the delay to 0.08ms or 0.11ms and would be better for this application.

Using longer FIR filters in DAC decimation filters and ADC interpolation filters results in larger group delay but can also result in sharper transition between passband and stopband and/or better stopband attenuation so it is as usual a compromise between different requirements.
robin87
Thank you very much for your replies! Let me start by saying that I don't have any experience with DSP, especially when it comes to the hardware setup. I did lots of Arduino work, dabbled around a bit with the mutable firmwares and wrote a few custom objects for axoloti, but that’s about it. So feel free to correct me if I get things wrong.

Synthiq wrote:
At 48ksps, the WM8731 can realistically only only use mode 0 or 1 to achieve 20kHz bandwidth so the delay in the ADC+DAC alone will be 0.48ms or 0.79ms. Increasing the sample rate to 96ksps and using mode 2 or 3 would reduce the delay to 0.08ms or 0.11ms and would be better for this application.


Thanks for pointing this out, I must have missed it! 0.1ms sounds like a workable compromise, so I'll keep the WM8731 in mind.

guest wrote:
is the issue youre facing that most platforms do batch processing of the data: ie data comes in, goes to a buffer, then the next N samples are calculated and sent to another buffer where they played out from? so total delay is the delay line plus the processing buffer?


Exactly, plus the inherent latency added by the commonly used codec chip. And yes, I think per-sample processing at a high sample rate is the way to go here. There’s not a lot else to do for the processor after all. Your microdec looks very nice, did you ever measure the roundtrip latency? As Synthiq points out, the digital filters in the WM8731 add some latency on their own.

Quote:
how many samples did you want to have?


Are you referring to the size of the ring buffer? I’m not sure about that, as it depends on the samplerate. But when it comes to absolute delay times, I like to think about it in terms of pitch when doing Karplus Strong, so a five octave range at the very least. From ~61ms at C0 to ~0.24ms at C8 would be ideal for KS, I think.

Quote:
going the analog BBD route would limit this, as they can only be clocked so fast (200kHz?), and they have bad SNR. you could do a digital BBD with a sigma delta converter running in the 10MHz to 20MHz range. then, if you had a HF VCO you could smoothly change the delay time.


Something like this has crossed my mind as well, but I was not sure if it would actually work. So, you’d have the processor poll the ADC constantly at a very high samplerate and use an external hardware interrupt from a HFVCO to get it to "pass the buckets along"?

Quote:
one other thing to look at is Bela for the beaglebone. its a low latency audio library, but i think the latency they are talking about there is from CV inputs to actuation, but i could be mistaken. i suppose you need low latency in the audio pathway for the CV to have low latency.


Interesting, I’ve stumbled across this one too! The analog inputs and outputs have very low latency and use a combination of SAR ADC and String DAC: https://blog.bela.io/2016/11/07/bela-analogue-vs-audio/ Seems a bit excessive to use such a powerful and expensive device just for a short delay line. Although it might be possible to do multiple independent delay lines at once, which would be nice. And considering the cost and availability of functional alternatives in modular synths, I’m not afraid of throwing some money at the problem eventually.

I think I’ll start with some suitable converters and a teensy 3.6 for convenience, just to see how fast I can get audio in and out. I’m looking at LTC1865 and DAC8552 right now.
With a sufficiently high samplerate, I should not be too concerned about filtering, right?
guest
if you can get your hands on a codecshield, and have an arduino handy, you can test out the wm8731 approach. running it at 88ksps would give 22 samples in the buffer at the high end. im not sure exactly where the ideal buffer size is, but i have to imagine if you have a buffer of 1, it will be horrible and probably not work.

the digital BBD wouldnt be too bad to build, but with any of these things you will need to make that tradeoff between aliasing artifacts and delay in the filters (as synhtiq points out). your analog filters will have the same issue, especially considering the karplus algorithm has a lot of high frequency components (it starts out with noise at your sample rate).
robin87
guest wrote:
if you can get your hands on a codecshield, and have an arduino handy, you can test out the wm8731 approach. running it at 88ksps would give 22 samples in the buffer at the high end. im not sure exactly where the ideal buffer size is, but i have to imagine if you have a buffer of 1, it will be horrible and probably not work.


Well, but since there is no real processing going on, I’m still not sure about the benefits of block-based approach in my case. If I manage to send the data in and out fast enough, why not just write to and read from the ring buffer at sample rate?

Quote:
the digital BBD wouldnt be too bad to build, but with any of these things you will need to make that tradeoff between aliasing artifacts and delay in the filters (as synhtiq points out). your analog filters will have the same issue, especially considering the karplus algorithm has a lot of high frequency components (it starts out with noise at your sample rate).


That’s true, but then your typical KS patch involves some sort of lowpass filter anyway. Might even be a good idea to include input and output filters directly in the module, like the Wilson Analog Delay did. So I don’t know if having dedicated anti-aliasing filters in the codec is really necessary..
Synthiq
robin87 wrote:
I think I’ll start with some suitable converters and a teensy 3.6 for convenience, just to see how fast I can get audio in and out. I’m looking at LTC1865 and DAC8552 right now.
With a sufficiently high samplerate, I should not be too concerned about filtering, right?

It depends on how strict you want to be. The WM8731 typically has 60dB attenuation in the stopband and if you want the same attenuation for high frequency signals that might alias back into the audio band, you will need a 5th order filter for 96kHz sample rate and at least a 3rd order filter at 192kHz. These filters will also have delays but not as long as the filters in sigma-delta converters as the filter order is much lower.
robin87
Synthiq wrote:

It depends on how strict you want to be. The WM8731 typically has 60dB attenuation in the stopband and if you want the same attenuation for high frequency signals that might alias back into the audio band, you will need a 5th order filter for 96kHz sample rate and at least a 3rd order filter at 192kHz. These filters will also have delays but not as long as the filters in sigma-delta converters as the filter order is much lower.


That's good to know, thanks. Seems like a reasonable thing to do, since both filter types wouldn't be very hard to implement.
guest
just checked the microdec, its around 1ms round trip. im using filter 1 at 44ksps, so thats 0.86ms, and then there are 5 poles of filter on the input, and 3 poles on the output which make up the rest.

doesnt the karplus algorithm fill the buffer with noise to begin with, and then filter it? i wonder what that is like if the buffer only has 20 samples. i feel like that would be equivalent to a wavetable synth with only 20 samples in the table. in the digital domain, the really high frequencies can be controlled in the filtration process, but with analog filters in the loop, they might just throw it all away too quickly. the 1b version would have 10k samples for 1ms of delay (if run at 10MHz), and would preserve high frequencies. you still might have the issue of the analog filters needing higher frequency response.
loki
robin87,

You really don't want to use a SAR ADC and String DAC. To use them you have to have a high performance analog filter and sample and hold on the input and a high performance sample and hold and analog filter on the output. I was around in the early days of digital audio, I heard 14 bit digital recordings in 1973 at the University of Utah. They were doing speech synthesis research for ARPA.

The early efforts used high speed instrumentation modules for the ADC and the DAC. It wasn't pretty and a lot of effort went into learning how to improve the conversion system. Use an audio codec with performance in the 105 to 110 dB range running at a 192 kHz sample rate to minimize the latency.

Back about 20 years ago Sony was promoting the idea of doing audio processing in serial using FPGAs. You might look into that. I'll look and see if I can find the Sony brochures describing what they were doing.
Synthiq
loki wrote:
You really don't want to use a SAR ADC and String DAC. To use them you have to have a high performance analog filter and sample and hold on the input and a high performance sample and hold and analog filter on the output.

Luckily electronics have advanced in the last 45 years. The LTC1865 ADC mentioned above is a switched capacitor converter so the sample/hold is an inherent part of the converter itself so no external one is needed in this case. And if I read the datasheet for the DAC8552 DAC, also mentioned above, correctly the glitch energy is only 0.15nV-s so even if we update the DAC 100ksps the energy would still not be more than 15uV-s and would still be around 100dB below full output signal so we might not need a s/h here either.

If we would set the delay in the loop for 1ms for a 1kHz signal and want the signal to decay 60dB in 1 second when the excitation signal is removed, the loop gain has to be -0.06dB. For the decay to be the same at all frequencies, the flatness of the passband has to be better than this. The WM8731 has deviations in both the ADC and DAC in the order of 0.01dB to 0.03dB each and the TLV320AIC3104 doesn't spec better than +/-0.1dB in the ADC and +/-0.06dB in the DAC so it is even worse. I have not tested it, but I suspect an external anti-aliasing filter with unmatched discrete resistors and capacitors could be even worse. In any case, this is a spec that shouldn't be overlooked if long decays and gain close to 1 is needed.
robin87
Here's a short update:

I found a WM8731 breakout board in my box of Arduino/Teensy stuff and hooked it up as a I2S slave to a teensy 3.2 and used the audio library for testing purposes. I started poking around in audiostream.h and the sample rate register of the WM8731 and it appears to be passing audio at 96kHz with a block size of 16 samples just fine. I tried setting up a simple KS patch and got a pitch of ~2kHz out of it, so roughly 0.5ms roundtrip latency. Getting useable sounds at this rate is already tricky, so it is probably good enough for what I have in mind.

I also found a delay library that interpolates between the samples to allow for smooth time changes, which seems to work pretty well. The next step will be to write my own interpolating delay code and figure out a way to scale the delay time for exponential CV response. Also, keeping the CV ADCs clean and free of noise/jitter will be crucial and my initial breadboard experiments with a potentiometer hooked up to the teensy ADC were not very promising.

I've attached a quick and dirty clip that features the breadboard delay as a flanger with a modulated VCFQ in it's feedback path. EDIT: It's not a real flanger since there's no dry signal mixed in, which would make the effect more pronounced. Just a modulated delayline with an analog feedback path.


When it comes to Karplus Strong, I can definitely see your concerns about doing it in hybrid digital/analog situation like this and I agree that it’s not ideal. I don’t expect it to perform the same as a fully digital implementation, which is the way to go if you want to explore the algorithm as it was intended. I still think it would be worthwhile to have a very short delay with reasonable audio quality around in a modular environment. Perhaps it’s better to think about this as a modern take on the Serge WAD instead of a proper KS engine. A building block for time-based effects and approaching physical modelling techniques in a modular context.

Until now I've used a 256-stage Doepfer BBD to do the same, but it would be nice to have a more "hifi" option available.
Synthiq
A few years back I was experimenting with a MIDI-controlled 6 string Karplus-Strong synth implemented on a 40MHz dsPIC33. To increase frequency resolution I also used a fractional delay filter to interpolate between samples. I ended up with a 16 tap FIR filter with 256 sets of coefficients for a time resolution of 1/256 of a sample and I couldn't hear any steps in the frequency when I used the pitch wheel on the keyboard to modulate the frequency. The interpolation filter is normally done as a sinc function multiplied by a window. Both the Hann and Hamming windows had too much ripple in the passband and I instead used a Kaiser window with the alpha parameter set to 8.6 to minimize the ripple. At higher sampling rates it may be possible to use fewer taps and then a Lagrange filter might be interesting since it has no ripple.

To convert a CV voltage (or in my case a MIDI note) to a delay, I used a table lookup. The table only needs to include the lowest octave as the value is simply divided by two for every octave above. If I remember right, a table with only 64 values with linear interpolation between them will have an error of less than 1 cent. Any noise on the CV can be reduced by lowpass filter the ADC value although it will also reduce the bandwidth so some compromise is needed here.

The result of the experiments was never a convincing guitar string sound and I think it is just to simplistic to use white noise as the input signal. It would still be interesting to add the ability to excite the string with an external signal that could be more complex to see if it would be possible to generate more realistic sounds.

Below are plots of the frequency response for a few different implementations of the fractional delay when the delay is set to right between two samples. The more taps in the filter, the higher the corner frequency will be.



TheSlowGrowth
Synthiq wrote:
I ended up with a 16 tap FIR filter


That is interesting. When I looked at various implementations of Schroeder allpasses for reverbs, I only ever saw 3 or 4 point interpolation in the fractional delay lines. It just dawned on me that those could also be understood as FIR filters, only that you probably wouldn't lookup the coefficients from a table but compute them at runtime. Have you looked at the frequency responses of those? I never did, but it would by quite interesting to see how they compare.
loki
loki wrote:
Back about 20 years ago Sony was promoting the idea of doing audio processing in serial using FPGAs. You might look into that. I'll look and see if I can find the Sony brochures describing what they were doing.
Synthiq
TheSlowGrowth wrote:
Synthiq wrote:
I ended up with a 16 tap FIR filter


That is interesting. When I looked at various implementations of Schroeder allpasses for reverbs, I only ever saw 3 or 4 point interpolation in the fractional delay lines. It just dawned on me that those could also be understood as FIR filters, only that you probably wouldn't lookup the coefficients from a table but compute them at runtime. Have you looked at the frequency responses of those? I never did, but it would by quite interesting to see how they compare.


I have never looked at Schroeder allpass filters so I can't say. But if they are true allpass filters they should have the same gain at all frequencies.
TheSlowGrowth
Synthiq wrote:
I have never looked at Schroeder allpass filters

I should have clarified: A schroeder allpass is basically to sums and a delayline. The delayline needs to be fractional to be able to modulate it without audible artifacts. What I meant is a fractional delay made from a 4 point interpolation like this one from the Reaktor library:

This can be understood as a FIR filter.
I don't have matlab available to me right now but I managed to calculate the frequency response and coefficients for this within 1h with python (the more I use it the more I love it). So, this is the response for the Reaktor version of the fractional delay at the fractional f=0.5:

and as a double-log plot:

The coefficients would be (for the fractional f = [0..1]):
-0.5*f^3 + 1.0*f^2 - 0.5*f
1.5*f^3 - 2.5*f^2 + 1
-1.5*f^3 + 2.0*f^2 + 0.5*f
0.5*f^3 - 0.5*f^2

I find it interesting that the implementation from Reaktor lends itself to a fixed point implementation, because the *0.5 can be replaced with a bitshift operation.
MUFF WIGGLER Forum Index -> Music Tech DIY  
Page 1 of 1
Powered by phpBB © phpBB Group