Eirlaw
Sewing patterns on the seam between beat chopping and texture.
eirlaw · Welsh for sleet · said AYR-lau
Eirlaw is a loop-and-break sampler with a deep step sequencer at its heart, and granular and layered depth underneath, where the beat player can reach it. The chop, the grain and the groove all run on one clock. Every hit lands on its own sample.
A sampler at the seam.
Samplers have drifted into three camps: one chops breaks, one hosts big multisampled instruments, one granulates and smears. Each has its own idea of what a sample is.
Eirlaw stands on the seam between the chopping and the texture. The player who chops a break is the same person who, a bar later, wants that break to dissolve into grains and come back on the downbeat. That usually takes two instruments, two clocks and a bounce. In Eirlaw the dissolve is a step in the same pattern as the chop, on the same clock, with the same groove. The texture stops being a separate instrument and becomes something the beat does.
Building multisampled instruments is in there too, but as the floor beneath, not the front door.
Timing is the material.
A sampler's whole art is where things land. A chop is a decision about a point in time. A groove is a set of small decisions about points in time. A grain cloud is thousands of them a second.
So every trig, every slice start and every grain start in Eirlaw is placed on its exact sample inside the host's buffer, never rounded to the edge of a buffer or to a coarse internal grid. Swing, micro-timing, locks and grains add no timing error of their own, and nothing adds latency to pretend it can see ahead.
Feel lives in the last few hundred microseconds. Move every hit of a break by a buffer's worth and the feel is gone, and nobody can say why the bounce sounds stiff. So I won't call Eirlaw tight. It's exact: every hit on its own sample, tested to that rule rather than trusted.
The sequencer is the instrument.
Eirlaw doesn't have a sequencer bolted on. It is the family sequencer with sample engines attached: the same locks, conditions, micro-timing and scenes, the same rows on the panel. All Eirlaw adds is what a sample can be told on a step: which slice, which layers at what level, where the grain sits.
A lock on every step, a condition on every hit, a fill that is a rule rather than a recording: here they reach the sample itself. A step that plays the third slice through just its hits. A step that pushes the grain early. A step that fires every fourth bar unless the scene just changed. The pattern stops being a list of hits and becomes an arrangement of behaviours, which is how a drummer thinks about a break.
The feel of a break is often worth more than its sound, and it's what usually gets lost in the chop. Eirlaw lifts the feel off a break and keeps it as a groove: just the small pushes and pulls, early or late, harder or softer. The pattern still decides which steps play; the groove decides how. So the feel survives the chop and can be lent to the other tracks, until everything leans the same way.
Grains on the clock.
Granular has always had a rate in hertz. Eirlaw's grain rate is a note value: a grain every sixteenth, every triplet eighth, every beat, placed by the same clock that places the hits. Position, size and density are things a step can lock, so the cloud is written into the pattern rather than hovering over it. A rate in hertz is still there for anyone who wants a wash, labelled as what it is.
A cloud at a rate in hertz drifts against the beat. The same cloud on a note value is a rhythm, and it swings when the track swings. A grain every sixteenth over a vocal is a stutter that follows the groove. A step lock that walks the grain position backwards is a reverse that lands on the bar. Granular stops being an effect and becomes another way the sequencer plays the sample.
A sample is three sounds.
Every sample Eirlaw imports is split once into three layers: the hits, the tone, and the air that is neither. It's ordinary signal processing, harmonic against percussive with the remainder kept. No machine learning, no model to download. The three layers then play as three ordinary samples that share a start, and each step says which of them sound and how loudly.
Most of what a producer does to a break with EQ and transient shapers is an attempt to reach one of these layers through the other two. Here they're already apart. A step with just the hits is a ghost note. A step with just the tone is the break's pitch without its hits. A bar that fades the air out is a sweep nobody had to automate.
A buffer is not a clock.
A host doesn't hand an instrument a stream of samples. It hands over a buffer of N samples at a time, and says where the song has got to once, at the top of each. The obvious design lets that buffer be the clock: whatever is due somewhere in the next N samples starts at the top. I refuse that, and the reason is arithmetic.
Let n be the sample a hit belongs on, counted from the start of the song, and n_0 the count at the top of the buffer that contains it. The hit sounds at offset d:
d = n − n_0, 0 ≤ d ≤ N − 1
In words: count how far into the buffer the hit belongs, and start it there. Nothing is written before that point. The buffer's length N sets how far in a hit can be, and has no say in which sample the hit belongs on, so one song cut into buffers of any length gives one output. A digital instrument can know the number of every sample it will ever write; exactness is that knowledge, used. That is the design, and it is also the test: render a pattern at four different buffer sizes, from very small to large, and the four files must match bit for bit. One differing sample fails. So does a test that passes on one run and not on the next.
Start the hit at the top of the buffer instead and it is early, by however far in it belonged. The worst case is a whole buffer: about a millisecond and a half for a small buffer of 64 samples, nearly twelve milliseconds for 512, over twenty for 1,024.
The worst case is bad; the pattern is worse. A sixteenth note at 120 BPM is an eighth of a second, which is not a whole number of buffers, so each hit in a row of straight sixteenths falls at a different depth in its own buffer. Moved to the top of a 512-sample buffer, the first five come out early by anything from nothing to nearly nine milliseconds: a straight row made uneven by amounts that have nothing to do with the music and that change completely at another buffer size. A bounce needn't run at the buffer size you were listening at, and when it doesn't, what it prints is not what you approved.
Set that beside what a groove is made of. The smallest move a step can make is a 240th of a step, which for a sixteenth at 120 BPM is about half a millisecond. A 64-sample buffer is nearly three of those and a 512-sample buffer is twenty-two. Round to the buffer and the groove's own units are gone before anyone hears them.
The family's engines also keep a grid of 16 samples for settings that are allowed to step. Sixteen samples is about a third of a millisecond, and hits don't go on that grid either. There the reason is tone more than time. Two copies of one sound that were meant to start together and land a few samples apart don't sound late. They sound filtered: added together, the copies cancel at some frequencies and reinforce at others, which is a comb filter. At fifteen samples apart, the most a 16-sample grid can cost, the first cancelled frequency sits near 1.5 kHz, in the middle of the band. Even at one sample apart the sum is already more than two decibels down at 10 kHz. An error far too small to hear as late can still be heard, as a duller top.
Whole numbers, then one rounding.
The sample a hit belongs on has to come from somewhere, and where it comes from decides whether exact means anything. A step's place can't be a decimal number of beats. A third of a beat has no exact binary form, so two tracks at different speeds that ought to meet on a beat can arrive a hair apart, and a hair is enough to tip a rounding. Ties aren't rare enough to wave away either: at 120 BPM and 44.1 kHz every second sixteenth falls exactly half-way between two samples.
So a place is a whole number of one small unit, 1/80,640 of a beat. It looks like an odd number until you take it apart:
80640 = 2^8 · 3^2 · 5 · 7
It is built from twos, threes, a five and a seven so that everything the sequencer can ask for is whole in it: a step at every track speed, a 240th of the shortest step, which is the smallest move a nudge or a groove can make and comes to 21 units with nothing left over, and a ratchet's place when a step is cut into anything from one to eight equal parts. Two other schemes were on the table. A coarser unit with ratchets kept as fractions beside it gave smaller numbers and two kinds of arithmetic. Every place as a fraction was the most general, the slowest and the most to prove. One kind of whole number everywhere won.
Tempo is a whole number too, in ten-thousandths of a BPM. Then a place becomes a sample in one division of whole numbers, rounded once to the nearest sample, and an exact half goes to the later one. Nothing in that division is a decimal, so it has one answer on every machine. The second sixteenth at 120 BPM and 44.1 kHz is one of those exact halves, and it goes to the later sample everywhere, every time. At 48 kHz the same step is sample 6,000 with nothing to round.
The sum starts from the song's start every time and nothing is carried from one hit to the next, so a hit an hour in is placed as exactly as the one on bar 1. At 120 BPM one unit is about a quarter of a sample at 44.1 kHz: the ruler is finer than the thing it measures.
Swing is the one thing not forced onto the unit. Its delay is kept as the exact fraction it works out to and goes through the same single rounding. Rounding it to a 240th of a step could have moved a hit by about 11 samples at 120 BPM; rounding it to the unit, by one. Keeping the fraction moves it by none.
Hits can be early. A nudge and a groove offset together are held to three-quarters of a step either way, and to find the early ones the sequencer gathers hits from up to a beat and a half ahead in the pattern. A beat and a half is three-quarters of the slowest track's step, which is two beats, so nothing the rules allow falls outside it. That is knowledge of the pattern and not a delay: no audio is held back and no latency is reported to the host. Two alternatives were turned down. Never early would have thrown away every pushed feel. Earlier still, by reporting latency, would have made the whole instrument late under the hands in order to be early on paper.
A groove is a list of whole numbers.
A groove file holds no audio and no pattern. For each of up to 64 steps it holds two whole numbers: how far the hit sits from the grid, in 240ths of a step, and how much harder or softer it is than a base velocity the file also keeps. Which steps play stays with the pattern.
Lifting a groove from a break is a measurement. The hits are found once per file and the list is fingerprinted, so a later run is a check and never a second opinion. Each hit is then laid against a ruler, here a ruler marked in sixteenths at the break's own tempo. Two things are read off: which mark the hit is nearest, and how far from that mark it sits, in 240ths of a step. No hit is more than half a step from its nearest mark, so the reading runs from 120 one way to 120 the other, which is exactly the range the file allows. A hit that lands about a fifteenth of a step behind the third sixteenth is stored as step 2, counting from zero, and +16. How a hit's loudness becomes its velocity number isn't written yet, and nor are the rules for the awkward cases: two hits on one step, a step with none.
That 16 is a fraction of a step and not a time, so it follows the tempo and it travels. Put the groove on a track at another tempo, in a session at another sample rate, and the same sixteen 240ths go through the same single rounding as any other hit and land on one particular sample.
In use the groove's offset is scaled by an amount in whole per cent, rounded once to a whole 240th, added to the step's own nudge, and the total held to three-quarters of a step either way. Velocity goes the same way with an amount of its own: the groove's harder-or-softer number is scaled, added to the step's velocity and held between 1 and 127. Halves round to the later 240th and to the higher velocity. A groove shorter than the pattern goes round again.
Why 240? On a sixteenth grid a 240th of a step is one tick of a MIDI file at 960 ticks to the beat, so a groove goes out as MIDI and comes back identical. A unit four times finer would have kept more of what the measurement finds, but it needs four times the ticks to the beat and fewer things read such files. The cost is stated: a 240th is about half a millisecond at 120 BPM, so a stored offset is within a quarter of a millisecond of what was measured. A groove is coarser than the sample clock on purpose. What is exact is where each written number lands.
Two earlier designs were dropped. Accents were once ratios against the groove's average; offsets from a stored base replaced them, because base plus offset survives the trip through MIDI unchanged. And a track once played swing or a groove, never both. Now loading a groove switches the track's swing off, and switching it back on adds the two.
A grain is a hit the pattern didn't write.
A grain rate in hertz and a tempo are two clocks, and two clocks drift. At 121 BPM sixteenths arrive a shade more than 8 times a second, so a cloud at 8 Hz slips a whole step against them every 15 seconds. Here the rate is a note value, and the gap between grains is worked out from the tempo, the way a sixteenth or a triplet eighth is for any hit. A sixteenth at 120 BPM is 8 grains a second: a rhythm, not a pitch.
That gap is never added up. Each grain has a place in the bar, and its sample comes from the same sum as any hit's: counted from the start, rounded once. At 120 BPM and 44.1 kHz a sixteenth is a whole number of samples and a half, so the gaps between grains come out alternately one sample longer and one shorter, and the grain on each beat is on the beat exactly. Add up a rounded gap instead and the cloud is 8 samples out after a bar and about 5 milliseconds out after a minute.
Swing reaches the grains as it reaches the hits: the off-beat grain is made late, by up to half a step. At two-thirds swing the off-beat grain of a sixteenth cloud lands on the triplet. A step can pull its grain early by up to three-quarters of a step, the same limit as any hit.
A grain is a window laid over a piece of the source. The window is a short fade up and down. Under it is a stretch of the sample, read from a chosen point at a chosen speed, and the speed sets the grain's pitch. The cloud is whatever grains are sounding at that moment, added together. How many overlap is, on average, the grain's length divided by the gap between grains.
The window is not innocent. Laying a short window over a sound smears every partial in it, and the shorter the window, the wider the smear. Under a smooth window (a Hann) a grain an eighth of a second long blurs each partial across 32 Hz. A grain a hundredth of a second long blurs it across 400 Hz and stops being a note. A hard-edged window smears half as widely and spills far more to either side (Harris, 1978). Underneath all of it is one inequality, Gabor's (1946):
Δt · Δf ≥ 1 / (4π)
Δt is how spread out a sound is in time and Δf how spread out it is in frequency. Multiply the two and the answer can't go below a fixed floor: nothing can be both short and narrow. A window's edge is as audible as its length, and the shapes aren't settled.
Then the dice:
r = h( seed, step, m ), 0 ≤ r < 1
Every random quantity a grain has is one such draw r, a number from 0 up to 1, scaled by its control. h is a fixed function of three whole numbers: the track's seed, the step's number and the grain's number m. It isn't a generator asked for its next value. A next value depends on how many were drawn before, which depends on where playback started and how the audio was cut into buffers. A function has no history. Start at bar 9 and the third grain of step 5 draws what it draws from bar 1. Digital random is a sequence with an address, and the design keeps the address. Which function h will be isn't chosen. The start sample is never one of the things drawn.
Three masks that sum to one.
The split has to be something I can write down, run twice and get the same three files from. That rules out a trained model, which answers a different question (which instrument is this?) and whose answer can't be derived on paper. What is left is old signal processing, and the interesting decision is when to do it. A transform has to hear a whole window before it can say anything about it, so done live it owes the listener that window as delay. A window of 2,048 samples is 46 ms at 44.1 kHz, and nothing in this instrument adds latency. Done once, at import, the split owes nothing.
The transform turns the sample into a picture: time runs across, frequency runs up, and the brightness of each point is how much of that frequency is present at that moment. In that picture a held note is a horizontal line, a hit is a vertical one and everything else is neither. Two median filters tell them apart (Fitzgerald, 2010). One runs along time: each point is replaced by the middle value of its neighbours before and after. A hit occupies a few moments of a long run, and a median ignores a minority however loud it is, so what comes out is the lines that last. The other runs up and down the frequencies and keeps the lines that are tall, for the mirror-image reason. A median is also a sort and not a sum. It does no arithmetic, so it has no rounding to disagree about.
Then the masks. A mask is a share: for every point in the picture, how much of it goes to the tone and how much to the hits. This is the family I mean, not the final formula. Each point is shared out by how strongly each median claims it, with a margin: to be claimed, a point must be clearly one thing or the other. With no margin, tone and hits take everything between them and there is no third layer. Widen the margin and what neither claims is the remainder, the air: the three-way cut of Driedger, Müller and Disch (2014). The air's share is never less than nothing.
Whatever the masks end up being, the three shares of every point sum to one, and that is the property the rest leans on:
tone[n] + hits[n] + air[n] = x[n]
x is the sample you imported and n counts along it. Turning the three masked pictures back into sound is a linear step, so the three layers add back to the sample, to the last bit or two of the arithmetic. All three levels at full is the untouched sound, not a reconstruction of it. It is also why the layers must share a start to the sample. Masking a transform smears a little of each hit across its window, and the smear in one layer is cancelled by its opposite in the others. Slide one layer by a single sample and it isn't.
The window length is the open question, and it is a real trade. A window long enough to draw a low bass note's partials as separate lines spreads every hit across the better part of a tenth of a second. A short one keeps the hit sharp and turns the bass into a blur that neither median reads as a line, so it falls into the air. No window does both. Which window, which median lengths and how wide a margin are the detail still on the bench.
Three ways to change a loop's length.
A loop recorded at one tempo has to last a different time at another. The stretch factor is a ratio of two tempos:
α = T_loop / T_song
T_loop is the loop's own tempo, found at import and open to correction, and T_song is the song's. A 140 BPM loop in a 120 BPM song has to last a sixth longer: each beat must take half a second where it took rather less. The oldest answer is to read the file slower and let the pitch fall, here by more than two and a half semitones. Every other answer is a way of not paying that, and each pays somewhere else. So there are three, each named for what it does. What is settled is the kind of each; their controls aren't.
Clean is a phase vocoder (Flanagan and Golden, 1966). It cuts the loop into overlapping frames, takes each frame apart into narrow bands of frequency, and lays the frames back down further apart. How loud each band is, it keeps. What it has to work out is where each band should be in its cycle when the next frame starts. So it measures how far each band's cycle really turned between one frame and the next, which gives the frequency actually present, and then turns the cycle on by what that frequency would cover in the longer gap. Every partial comes out continuous and at its own pitch. What is lost is agreement between bands at one instant, and that agreement is what a hit is: every component lined up at one moment. Left alone, a vocoder softens every hit. The textbook cure is to drop the worked-out position at a hit and take the measured one again. Clean has to keep its hits; how it does so is on the bench.
Grain is overlap-add at the original speed. Short pieces of the loop are played at their own speed and laid down at even intervals, each overlapping the last, while the point they are read from moves through the loop at the pace the song needs. Nothing inside a grain is altered, so pitch stays put and a hit inside a grain is that hit, sample for sample. The joins pay. Where two grains overlap, each holds the same held note read from a slightly different place, and at some pitches the two copies meet opposite and cancel. Held notes flutter at the grain rate and drums mostly don't notice. This is the rhythmic one, and the levers in this page's closing section can colour its grains.
Extreme keeps how loud each band is in each frame and throws away where it was in its cycle, putting a fresh random angle in its place for every band of every frame. The frames are long, and with no cycle to honour they can be taken from the loop as close together as any stretch asks: a factor of ten, or a hundred. A hit becomes a wash as long as the window, and what survives is the slow outline of the spectrum. It isn't a poorer Clean. It is a different instrument on the same switch. The angles come from the seed, like every other random number here, so the wash on the bounce is the wash you heard.
All three read a file and not a live input, so they can read as far ahead in the sample as a window needs without holding anything back. Reading ahead in a file isn't looking ahead in time.
Reading between the samples.
Play a sample at any pitch or rate but its own and the engine is asked for values the file doesn't hold. That is two questions: where to read, and what to compute there. The former has an exact answer and gets it.
p(k) = s + k · ρ
p is where in the file to read, k counts the output samples of a play from the hit's own sample, s is the start, a whole sample number of the file that never moves, and ρ is how fast the file is read. Start, plus how many samples have gone out, times the speed: the position is worked out from the count each time. The other way, adding the speed to a running total every sample, rounds on every sample where this rounds once, and its answer depends on its history.
For a change of sample rate the speed is a ratio of whole numbers, and the sum needs no rounding at all. A 44.1 kHz file in a 48 kHz session is read at 147 file samples for every 160 that go out. After a minute the reader has moved through sixty seconds of file, to the sample. The reading point can only ever sit a whole number of 160ths between two samples, so a converter needs 160 sets of weights and no more. A pitch change is less obliging. The ratio for a number of cents is irrational except at whole octaves, so it can't be held as a fraction, and how to hold it so that every run agrees is an open question.
What to compute there is a filter design. The cheap answers are three. Hold: use the last sample the reader passed. Line: draw a straight line between the two neighbours and read off it. Curve: run a smooth curve through the four nearest samples, the Catmull-Rom spline (Catmull and Rom, 1974), the one Tonnau's oscillators read with. Each is a filter in disguise: join the samples with a box, a triangle or a curve, then sample the result. What matters is how much each leaves around multiples of the file's rate, where copies of the audio sit, because whatever is left folds back into the band at the session's rate. For a 10 kHz partial in a 44.1 kHz file, a hold leaves the nearest copy only about 11 dB down and a line about 23. For a 1 kHz partial the figures are about 33 and 65. Cheap reading is clean in the bass and dirty at the top, and the dirt isn't harmonic.
The clean answer is a windowed sinc (Smith and Gossett, 1984). Every value read is a weighted sum of many file samples either side of the reading point. The weights follow the curve of an ideal low-pass filter, faded out by a window so that it ends somewhere. And the filter is narrowed whenever the file is read faster than one file sample per output sample, because the file then holds frequencies the output can't. Read up an octave without that and a 15 kHz partial in a 44.1 kHz file becomes 30 kHz and comes back at about 14 kHz. Which filter, how long, and how its own arithmetic gives the same bits on every machine are open. Two things are fixed. The conversion is my own code with fixed weights, specified so that one file becomes the same samples wherever it is opened. And the cheap readers stay, on purpose, which is the next section.
Error, put back on purpose.
Most of this page is about removing error. This section puts some back. The rule for doing it is short: every lever is a named, exact, repeatable departure from exactness, and every one rests at zero. Nothing is modelled on a machine, because "sounds like that box" can't be checked and "eight bits, held for four samples" can.
Bit depth is the plainest lever. Round to B bits and the error is at most half a step either way. Take that error as noise spread evenly across the step (Bennett, 1948), measure it against a full-scale sine, and the signal-to-noise ratio is:
SNR = 6.02 · B + 1.76 dB
Every bit is worth six decibels. So 16 bits is about 98 dB, 12 is 74, 8 is 50 and 6 is 38. Tonnau's version of this lever runs from 16 bits down to 6; where Eirlaw's stops isn't settled.
The even spread fails on quiet or simple material. There the error follows the signal and becomes distortion that comes and goes with the note. Dither, which is noise added before the rounding, breaks that link and leaves a steady hiss. The textbook triangular kind costs a little under 5 dB of that figure. The lever offers both, dither or none, and the dither is seeded: the hiss on the bounce is the hiss you heard.
Sample rate is a hold. The lever takes a value and holds it for a whole number of samples: the session's rate divided by the rate asked for, rounded, and never less than one. Ask for 12 kHz and the hold is four samples at both common rates, which makes 12,000 Hz in a 48 kHz session and 11,025 Hz at 44.1 kHz. Same setting, two rates a semitone and a half apart, and I would sooner print that than hide it. No filter comes before the hold. That is aliasing, asked for by name: a partial above half the new rate is folded back below it. At 12 kHz a 7 kHz partial returns at 5 kHz, 10 kHz at 2 kHz and 13 kHz at 1 kHz, none of them related to the note. Counting the hold from the hit's own sample is the part that matters. Count from anything else and a slice catches a different one in four of its samples each time it plays, so one snare aliases four ways. Counted from the hit, it has one.
Interpolation is the third lever: a blend from the clean reader towards the line and the hold of the section before. A fourth snaps the reading position to a coarse grid.
Jitter looks like a contradiction and isn't. The clock adds none; that was the point of the opening sections. A jitter lever is a list of small offsets drawn from the seed, the same list every time. What it will be allowed to move in Eirlaw isn't settled, and nor is which of these levers reach the panel or what they will be called.
What Eirlaw does.
Decided features only. The rest is below.
- Eight stereo tracks, each a loop, slices, a multisample or a grain track.
- Up to sixteen one-shot pads inside any track, each with its own row of steps: a kit inside a track.
- Slicing by transient or by grid, with a slice chosen per step.
- Grain rate as a note value, or in hertz. Grain position, size and density lockable per step.
- Grain randomness you can get back: the same pattern gives the same grains.
- Every sample split on import into hits, tone and air, with a level for each layer on every step.
- Three tempo-synced stretch modes: Clean, Grain and Extreme.
- Lift the groove from a break, keep it in a library, and take it in and out as MIDI.
- The family sequencer: locks, conditions, micro-timing, scenes and a song mode.
- One track's loudness can move another: every track's envelope follower is a modulation source.
- Record from an input, or resample a track's own output, both to the exact sample.
- Digital character from honest levers, bit depth, sample rate, interpolation, jitter and aliasing, and nothing modelled on a named machine.
On the bench.
The shape is settled; some of the detail isn't. The controls on the three stretch modes, the grain window shapes and the fine detail of the three-way split are still on the bench.
If you chop breaks, build textures or do both, tell me what you'd want from it: [email protected]. When the plan changes, the Workbench says so.