work-in-progress. already posted on DIY stomp, but maybe I'll do the same here. a whole lot of discussion going on in original thread
too, but I guess I can update here as I go along.
I thought I'd try something. For years I've wanted to build my dream looper. When I first started DIY stompboxes and noise-generators 6-ish years ago, I never in my right mind would I have guessed I'd be doing projects at the complexity I am now! And original ones at that! But still, these last few years, I've been gearing up (mentally) to tackle something huge (to my eyes). Looping is not only an important part of my music, but the ability to manipulate loops on the fly as well. I've tried many loopers. While many were excellent, they all lacked something another had that I thought was fantastic! So here I am now, thinking about how to combine those very best features and add a few of my own.
And I thought I'd start a thread about it, and log it as I make progress.
I've only just started, and there will be many firsts for me in this project as well, so I'll try and keep it informative. How I made certain decisions and not others.There isn't a whole lot of information out there when it comes to non-ISD based loopers. Maybe this thread will contribute in some tiny bit. A reference of things that come up for such a project, to others. A mixture of technical and laypersons theory, and I will try and keep the theory to a maximum! But mostly, it will be a curiosity! It will also be a learning experience. I don't claim to be an expert, and I will make mistakes and errors in judgment. I'm learning as I go along with this ambitious project.So really, what do I want? - Hi-fi. 16bit 44khz is my goal.
- Variable fidelity/sampling rate for stepless time/pitch effects.
- Overdub with variable feedback. No question.
- Resonant LP / HP filter, and an automatic antialiasing filter
- Complete mixer to be able to mix from selectable inputs
- Same-pitch time stretching
- Automatic & manual "scrubbing"
- Ping-pong scrubbing, or "freeze" effects
- Loop cropping / trimming. Defining start-end loop points in realtime.
- Clickless seamsWill not do / not smart enough to do:- Undo
- SD card storage
- Multitrack or stereo
- BPM or time-sensitive quantizationWhat have I done so far:
A simple breadboarded setup that can pass 12bit audio at around 100khz! ;D It doesn't do anything but pass audio, no recording or feature whatsoever. Just raw analog-to-digital conversion and back again. I'm concentrating on getting simple audio right before I do any sort of recording, playback, logic or feature. What I'm using so far:
I've started using MikroC, which is a C compiler for various microcontrollers. This is a very big step for me. Up 'till now, I had been using 8-bit AVRs and Bascom. While great for LFOs, presets and automation, they simply don't have the horsepower to do anything but telephone-quality audio. I've experimented quite a bit with audio on them, but I don't know assembly, so wasn't hitting good samplerates. What I made were fun little glitchy noise boxes that sample and loop, but in no way were they going to satisfy my looping needs. Bascom (basic) only supports AVRs, so I need to learn a new environment, and while I'm at it, language. A common language like C opens up future possibilities for other platforms as well, unlike Basic. So now, I learn. I'm still very much at the beginning of the language fundamentals of C.
Another new thing for me will be heavy use of surfacemount packages. I've done a few before, but with AVRs and most pedal builds, it wasn't really needed. With high-speed audio and data, it will be needed, and often in tiny pitch (0.5mm). I'm considering buying a cheap stereo microscope to aid me in this and other projects.CPU:
A PIC32 board from Mikroelectronica. A little expensive but it's in an easy to use footprint on a DIP40 stamp and packs a punch! The chip on it is 32bit and clocks at 80MHz. Digital-to-analog:
A PT8211 16bit DAC. Same company who make our beloved 2399 delay ic! Easily found for cheap (2 bucks a chip on ebay) and in an easy to use package (DIP8 or SOIC8), and specced to deliver better than CD-quality sound. I've tested it, it sounds good, it's cheap, it's fast, it works, I'm set!Analog-to-digital:
Currently an MCP3201. It's easy to find and cheap, but is "only" 12bit and is quite slow. I can get decent samplerates with it, but data/SPI transfer isn't fast at all, so it doesn't leave the CPU much free time to do logic. I'm using it at the moment because I know it and I had some at hand. Must find something else. I've orded a couple LTC1864 which is, according to the datasheet, an extremely fast 16bit ADC in a nice SOIC8 package! Pretty expensive though, at $14 each. According to how hard my PIC32 is currently chugging, and if my math is right, I will be able to get 200khz sampling speeds at 16bit, just raw audio pass-through! That should leave my PIC32 with tons of time to perform logic and whatnot if I'm aiming for 44khz!RAM:
This was the hard one. I've made some calculations. How much looping time do I want? Well, 10 seconds is a nice round number! Lessee..- 1 sample at 16bit uses up two bytes.
- At 44khz, 44000-ish samples per second, one second uses up 88000 bytes, or 88KB.
- 10 seconds needs 880KB, or 1MB if we're rounding up for easy findability.
I've used Microchips 23k256 RAM ics a few times. They are in nice DIP8 packages, use fast and easy SPI communication, but they are only 32KB. Forget it. So I hop onto Mouser and Digikey to see what my RAM options are. This takes several days of reading datasheets and measuring options, actually. I have to filter out anythign that comes in BGA. So, a few kinds of RAM:
- FRAM. SPI communication, fast, easy package, but still small storage quantity
at 128KB and costs a leg at $28 for that little amount. Scratch that.
- Parallel RAM. Cheap-ish, common, easy to understand, VERY fast as its parallel
instead of serial com, but uses a ton of pins. 8 data pins + 20 address pins + 2-3
extra. I need over 30 free pins on my CPU! If I was using a large PIC32, I could do that,
but I'm not. I'm using a 64-pin micro on a 40-pin stamp, and not all of those 40 pins are
the right "kind". Also, I don't want the headache of routing the PCB for all those traces.
Still... parallel RAM is the de facto standard when it comes to consumer audio looping
and sampling at high-speed. Better order a couple, in case.
- Flash memory. Cheap, easy to use, nice packages, but a little slow, and limited write
cycles. 100,000 or so. If I'd be using this as a traditional looper, that might be enough,
but I have to plan for the time where I set the loop-trimming to 5 milliseconds and hit
record. There, I just burnt through 10% of the chips available rewrites in a second! ;D
- MRAM. Specifically MR25H40. Hmm... doesn't seem to be a common type of memory.
But oooOOOHH! Look at these specs! Lightning-fast SPI com, zero read/write time, infinite
rewrites, and available as a 512KB! $14 is a bit pricey, but I'm willing to spend that much
if I only have to use one or two of them in the project! But... wait.... ohhhh
DFN package. That's nearly as bad as BGA.It's like... THERE ARE NO PINS! The pins are tiny little exposed metal UNDER the 8-pin square. Anyways, I order a couple, ball a bit of solder directly on the "pads", tin a SOIC-to-DIP adapter's pads (same footprint), and melt the balled-DFN onto the tinned adapter. It seems to have worked. Okay, I can do this. The specs make it worth it! Oooohh, data retention under no power even!Speed test:
I have the digital oscilloscope (a cheap 25mhz Owon) hooked up to the circuit. The red lines represent the SPI clock hooked up to the slow 12bit ADC. The yellow lines are the clock on the fast DAC and MRAM. The green line I added represents a single sample. It represents an elapsed time of almost 30us. That's 30 millionths of a second! That's a short amount of time to us humans, but to a 32bit 80MHz microcontroller, a lot can be done in that amount of time. Here is how many millionths of a second my PIC32 hs to work with for each sample:- 44khz = 23us per sample
- 33khz = 30us per sample
- 22khz = 45us per sample
Considering that, at the time I took this picture, I guess it was sampling at about 35khz, which in all honesty to my ears, sounds mostly fine.
The two large red blocks represent 8 clock pulses (for a total of 16, which is what the ADC needs to sample a single 12bits). They're just tight together which is why they look like one single huge pulse. The yellow represent the SPI clock hooked up to the much much faster 16bit DAC and MRAM ic! All 8 of the yellow lines have 8 little clock pulses of their own. Just so much more tightly together they appear as a single line! The first two of those blocks (16 pulses) are for the fast 16bit DAC, and the other 6 (48 pulses) for the MRAM.Once I get my new fast ADC, those two large red blocks will shrink to the size of the tiny yellow ones, and the PIC32 will have much more free time for logic/features, and/or will be able to achieve even higher samplerates!
I can measure how long it takes to read or write to the MRAM, about 4us, how long it takes to output to the DAC, 2us, and how long it currently takes to sample from the ADC, 8us.
It's half past midnight so I'll stop now. In a day or three, I'll write about why I chose to use a seperate ADC and DAC rather than use an audio codec chip, which is what's comonly used. Also, what I've learned about antialias filtering! Also, I'll fill in some links to stuff.
****************Testing new parts:
As I've said, this project has a lot of new things for me! New kinds of fast parts, a new language and environment, a brand new type of microcontroller. I didn't just plug new parts together and hoped I could get it working! ;)
I know AVRs (8bit micros) fairly well, so when I purchased the new MRAM and 16bit DAC, I hooked those up to the AVR instead to see if I knew how to use them, figure out the routines, data order, control bits, etc. It made debugging and discovering a new part FAR easier. There were issues, but I could remove the AVR from the equation because I knew how to use these. Once I had a set of rules on how to use my new ics, I could move on to the new language and PIC32 and "translate" those rules. The AVR is far far too slow for decent audio.Inspiration:
Looping is my main part of my solo sets. I use loopers as instruments if at all possible, and not just as stomp-and-forget boxes. I've used so many, and sold them after a while. I did keep four of them, though! And they're kind of my main inspiration for this project, feature-wise.- Timefactor. Awesome looper! Has loop cropping/trimming and is pretty flexible! Wish they would of gone the extra mile with the crazy features, though!
- Stereo Memory Man / Hazarai. My simple workhorse looper when I don't need something complex. I like the filter on it and how fast one can lay down a loop.
- 2880. Not too many crazy features, but the UI design is something I admire! I think I prefer the tabletop format. I wish I could make mine multitrack, but for the moment, best focus on a single track.
- PDS-8000. Just love it!Separate ADC / DAC vs codec IC:
I think a standard for these types of applications is a dedacated codec IC which incorporates ADC/DAC as well as audio-optimized filtering and stuff. I know my 2880 uses one of the Texas Instrument ones, maybe the PCM3001 (from memory), and I've seen them in a lot of other products where audio quality was important. They're an "all-in-one" audio solution to be connected to a microcontroller or CPU, which only handles the thinking. They're generally not too expensive, and have a lot of built-in audio features that normally I'd need a lot of external components for, but I chose not to go this route for one reason. They also all require a secondary clock that's hundreds of times higher frequency than the SPI/data transfer clock.
An SPI clock is a clock signal that drives the "engine" of a part to deliver or recieve data in that specific timing. This can be a variable speed, but is usually multiples of two. Some parts can send/recieve data to and from the PIC32 very quickly, while others require a slower clock running parallel to the data stream. Codecs are a bit more difficult, as they require a secondary clock that's exactly 256 or 512 times the samplerate (well into the MHz), and it has to be in sync with the SPI clock at all times! The SPI clock has to scale along with the samplerate, and that I simply can't do. I've read about it, and it's way way over my head. There are strict rules in place when it comes to codec timing and control. Maybe someday I will get familiar enough with this language and environment that I'll be able to use a codec, but at the moment, I'd rather find another way. Separate ADC and DAC it is. They are much "looser" in terms of these kinds of things, and are operated simply by SPI which I know pretty well. No additional clock required. No strict scaling of the SPI clock relative to the samplerate.
Using an ADC/DAC combo over a codec however brigns on another challenge. Antialias filtering. A codec IC wwhen properly controlled will filter the sample "stepping" in digital audio and will adjust the filter according to your samplerate. This is very helpful to have in a single chip! But since I'm going to be using an ADC/DAC combo, I'll have to devise external fitlering to get rid of the jaggies, and I'll need to sweep the filter when I tune the loop down to a slower speed. I'll probably end up using a MAX7404 ic which is a filter-on-a-chip controllable by either capacitor or clock input. If I use a clock, it won't have to be scaled perfectly with the SPI clock or samplerate. I can just wing it, use my ear. Much easier! More on that AA filter some other time.
Using an ADC/DAC combo vs a codec is moves much of the work involved from programming in the new environment (not my strength), over to external components and "winging it". Fine with me!Display:
I'm gonna need some sort of visual feedback, though I haven't figured out what I want yet. An LCD would be nice, but I don't yet know how to cut squares in metal.Controls (so far)
Here are the controls and features I will be trying to implement. The how's are mostly already clear.
Knob –Speed (PIC32)
Knob –Forward/freeze/reverse (555)
Knob –Freeze granularity (555)
Knob –Start point (PIC32)
Knob –End point (PIC32)
Knob –Drift (PIC32)
Knob –Filter cutoff (analog)
Knob –Filter resonance (analog)
Toggle –Filter post/pre feedback (analog)
Knob –Modulation speed (AVR)
Knob –Modulation depth (AVR)
Knob –Input gain
The stuff in brackets is how its gonna be done. PIC32 means the pot will be directly connected to the micro and will be handled in code. Analog means just that, and AVR means I have a little 8pin modulation AVR I like to use for these kinds of thing. It’ll PWM a push and pull into the Speed pot’s ADC.
The Forward/freeze/reverse and freeze granularity is what I think I’m most excited about. Here’s how:Forward / freeze / reverse
Nearly all (or all) loopers I know of manage reverse in one way. A button, or a toggle switch. Off it goes forward, on it goes in reverse. I want something a bit more special than that. I want a knob that has totally variable states between:- full speed forward
- slower speed forward (no pitch change)
- very slow forward (still no pitch change)
- very slow reverse (still no pitch change)
- slow speed reverse (etc..)
- full speed reverse
Here’s how I’m gonna do it. The PIC32 will have a digital input pin. Low pin is forward, high pin is backwards. Then I attach a 555 with controllable speed and PWM! This image is a representation of the PWM signal to be generated by the 555 and fed into the PIC32 forward/reverse toggle pin.
Each segment is a short period of time. For the sake of the argument, lets say 5 milliseconds. On full forward, there are no pulses, just a low signal. The PIC32 interprets that as forward playback.
Turn the pot a bit and the 555 generates a little duty cycle. In this example, 25%. The PIC32 interprets that as mostly forward playback, with 25% rewind. Since this is done very quickly, every couple of milliseconds, our ears and brains will interpret that as “slower speed”, and it will preserve the pitch.
If the pot is in the center, then the forward and reverse duty cycle are the same, and a “freeze” is achieved. Turn it even more, and the reverse state is longer than the forward state and so you start to go back in time. An additional potentiometer can be
This is not a “perfect” method of pitch-preserving time stretching. That would probably involve blending microsamples and advanced DSP stuff that I’m no where near ready to try. This is a hack, but it works! I’ve tried it on an AVR sampler a year and a half ago. This time, it’ll be fine-tuned and hi-fi.Crossfade
Another thing I want to implement is some kind of realtime crossfade at the loop point. Not an audible one, though. Just enough to get rid of the nastiest of the pop/click at loop point. Say 100 samples worth. How I incision doing this:
As soon as a new loop recording is done, all
samples are saved but the actual played loop will be 100 samples shorter. Only a couple milliseconds worth, it won't make a difference to the ear. As the loop playback hits (total loop length - 100), it adds (first of extra samples / 100), to the current one and divides the result again by 1.5 or 2 (I'll have to experiment with that whether I want a linear crossfade or log). The next sample adds a little bit more of the second of extra samples. And so on. Not the most efficient of algorithms so I'll figure something better out. But that's the gist of it.
It'll be realtime and not "cooked" into the saved samples, because I want to be able to move the loop point around dynamically.