The Paulimba
I built a Paulimba. Here's the end-part music from my C64 demo Lunatico played live on it.
Download
- Linus Akesson - Lunatico End Part on the Paulimba.mp3 (MP3, 1.1 MB)
Background
Making a Paulimba seemed like an easy task.
Paula, the Amiga soundchip, is designed for sample playback. It has four independent channels where you can play a sound stored in the memory of the computer, and you can get different pitches by adjusting the playback rate.
So after setting up an Amiga with the necessary development tools and a way of transferring files to and from the machine, I sat down and wrote a first implementation. It worked something like this: Wait for a keypress, convert the key code to a pitch using a lookup table, start playing a Kalimba sample with that pitch, and go back to the beginning.
If a sample is started on a channel that's already in use, the previous note gets cut off. Thus, in order to support overlapping and simultaneous notes, the program steps through the four channels in a fixed cycle. It also alternates between left and right stereo panning.
So far so good, but this naïve implementation was a disappointment in terms of sound quality, and there are two major reasons for that.
Sample resolution
The first is resolution or bit depth. Paula works with 8-bit samples, so every point on the soundwave is rounded to the nearest digital level, and there are 2^8 or 256 different levels to choose from.
But the sound of a Kalimba starts with a loud attack and decays to a much lower volume level. When sampling, we have to adjust the gain to make the attack fit within the range of 256 levels. But then the bulk of the sound only covers a small part of the signal range, where there's only a handful of levels to choose from. This leads to distortion.
A technique called dithering involves adding just the right amount of noise to cover up the distortion. The ear is tricked and we hear the original soundwave—but we also hear the added noise.
Many instruments—including bells, plucked strings, and piano notes—share this general shape of the loudness curve (or envelope), so the problem is rather common. And there's a good solution if we are willing to put in some work: Paula lets us set the volume independently for each channel, from 0 to 64, and we can even change it while the sample is playing.
So we start by measuring the envelope of the original Kalimba sound. Then we compensate for it by turning up the gain as the sound progresses. Only then do we sample with 8-bit precision, and because this sound is equally loud throughout, we can approximate every part of it with 256 levels. And then we re-apply the original loudness curve during playback, by updating the volume register as we go. It's enough to update the volume every 10–20 ms or so, because the loudness curve changes relatively slowly.
Playback rate
The second problem with my initial implementation has to do with sample playback rate. Paula has a maximum playback rate of 28 kHz and the Paulimba has a range of about three octaves. So if we only have a single sound sample, and we play it at 28 kHz to produce the highest note, then we have to play it at 3.5 kHz to obtain the lowest note. Granted, that lowest note has a fundamental frequency of as little as 130 Hz, and we can reproduce an acceptable sinewave at that rate. But the Kalimba is quite rich in overtones, so we wouldn't be able to capture its bell-like timbre. Instead we would hear a bunch of inharmonic overtones caused by the jagged edges of the low-resolution approximation. Those overtones are present when we play the sample at a high rate too, but they end up outside the range of human hearing (and are therefore filtered out by hardware before they even reach the speakers).
Here's a common solution: We keep the top octave as it is. To play notes below that, we switch to a different sample of a Kalimba note that sounds one octave lower, and so we can play that at the maximum rate of 28 kHz. And one octave below that, we switch to yet another sample and play that at the maximum rate.
I recorded three different notes from the Kalimba itself, but they had very different characters, and in the end I felt that the Paulimba ought to have a consistent sound across its range. So I decided to use only one of my original high-resolution samples and generate pitch-shifted versions of that, before filtering and downsampling to 28 kHz.
Having done all that, I was still a bit underwhelmed by the sound quality, so I decided to go all the way and use the maximum playback rate for everything. I wrote a program to generate 37 individual samples, one for each note on the keyboard, from the same high-resolution recording. But how would I fit them all in the limited amount of RAM available on the Amiga?
Making loops
You may have noticed that the loudness-adjusted sound has a very static quality after the initial attack. We can actually cut away most of the data and loop the final part of what's left. My sample-generating program cuts each sample after 4 KB of data, and adds a crossfade just before the cut, blending the audio data back to the looping point. But what's the ideal location of the looping point?
If the length of the loop corresponds to exactly one period of the soundwave—the fundamental pitch of the sampled note—then we'll end up with a very clean loop with pure overtones and no low-frequency noise. But the length of the loop needs to be an integer—an even integer on Paula, actually, because data is fetched 16 bits at a time. So in general, our best hope is to find a loop that corresponds to a whole number of soundwave periods. For each pitch, my program computes the ideal loop length (a non-integer). Then it multiplies this number by every integer in the range 1–400 to determine what product is closest to an even integer. After rounding, this product is then used as the loop length.
Aliasing
Confident that I had maxed out on every parameter (at the cost of a humongous RAM footprint), I now had high expectations for the sound quality. But to my dismay, I found that aliasing had somehow snuck into the high end of the range. It took me quite a while to figure this one out; the phenomenon isn't documented in the Amiga Hardware Reference Manual, and I don't think it's widely known. I eventually stumbled over an explanation in Henryk Richter's Dear Paula.
In a PAL system, Paula is clocked at 3.546895 MHz (that's the colour carrier frequency times 4/5). The playback rate is specified in clock cycles, i.e. you're telling Paula to wait a given number of clock cycles before advancing to the next datum in the sample. The playback rate is limited by how fast sample data can be streamed from memory, which comes out to once every 123 clock cycles. The period register is 16 bits wide, so valid period values range from 123 to 65535 cycles. Every such period, new sample data is fetched and converted to a voltage using a digital-to-analog converter (DAC).
Meanwhile, the volume control is implemented as a kind of pulse-width modulation. The maximum volume, 64, is a special case: The DAC output is connected directly to the output without resampling. The fact that volume level 64 gets special treatment makes the up-to-eleven thing a bit less mysterious (but no less cool). For the remaining volume levels, Paula increments a 6-bit counter on every clock cycle. The following is an oversimplification, but, in essence, as long as the counter is less than the specified volume level, sound is emitted. Since the 6-bit counter wraps around every 64 cycles, the sound is effectively resampled at 1/64 of the Paula clock frequency, about 55.42 kHz.
To prevent aliasing, we have to ensure that the sound (as emitted by the DAC) is in sync with this resampling. As I suggest in the video, it's safe to resample at an integer multiple of the playback frequency. Thus, for instance, if we play the sample at 27.71 kHz, every individual number passing through the DAC will be resampled exactly twice. Another way to think about it is that the playback period, the amount of time between changes to the DAC output, should be an exact multiple of the resampling period, 64 cycles. The shortest valid playback period that is a multiple of 64 is 128.
So the aliasing disappears if we choose a playback period of 128 (or any other multiple of 64). ProTracker users take note: This corresponds to an A-3 with finetune -1 (or, equivalently, G#3 with finetune +7).
In the video I demonstrate the difference between the maximum playback rate, with plenty of aliasing, and the slightly reduced playback rate. For this scene I made a special version of the software with two complete sets of samples, generated separately for the two playback rates. If I had played the same set of samples with period values 123 and 128, the aliasing would disappear in the same way, but there would also have been a quarter-tone difference in pitch, and I didn't want to distract the viewers with that.
Playability
Different Amiga models appear to suffer more or less from keyboard ghosting: My A1200 struggles with certain key combinations when the keys are pressed simultaneously, so one has to arpeggiate some intervals, playing one of the notes a tiny instant earlier than the other. But my A600 doesn't seem to have this problem at all, at least for the note combinations in the Lunatico piece.
Overall, I think this project turned out rather well, so you can expect to hear more of the Paulimba in the future. Probably in combination with other instruments, as the sound is a good fit for my growing little retro-computer orchestra.
Posted Friday 27-Jan-2023 10:48
Discuss this page
Disclaimer: I am not responsible for what people (other than myself) write in the forums. Please report any abuse, such as insults, slander, spam and illegal material, and I will take appropriate actions. Don't feed the trolls.
Jag tar inget ansvar för det som skrivs i forumet, förutom mina egna inlägg. Vänligen rapportera alla inlägg som bryter mot reglerna, så ska jag se vad jag kan göra. Som regelbrott räknas till exempel förolämpningar, förtal, spam och olagligt material. Mata inte trålarna.
Massimo C.
Fri 27-Jan-2023 11:44
After reading the description with more technical details, a couple of ideas surfaced.
1) It would be also fun to be able to play several different timbres together. As maybe you are already using too much memory for loops, an option worth considering is the use of e.g. a Pistorm card with several hundred MB of fast RAM that can be moved on demand to Chip RAM. This may probably not be acceptable for a live instrument, which is your goal there, but it could be an effective way for tracker-style music playing. Of course, managing the Chip Ram buffer as cache knowing in advance what samples will ben needed requires smart prefetch caching algorithms. Besides, using a modern day accelerator is a form of cheating the HW, and old ones are rarities.
2) What about setting the video in DBLSCAN modes? It would allow for a double maximum sample frequency. E.g., minimum period would be 64, and sample frequency would be 55.42KHz, same as the volume resampling. In conjunction with your "envelope shaping" this would allow for nearly Hi-Fi sound on stock Amiga Hardware...
Fri 27-Jan-2023 16:56
Massimo C.
Fri 27-Jan-2023 18:10
Sun 29-Jan-2023 15:51
Mon 6-Feb-2023 10:58
Yeah, the A1200 is known to be afflicted with keyboard ghosting. Mine certainly is. I love the thing to bits, but if I could change anything about it, the keyboard would probably top the list.
Markus Becker
Sun 6-Aug-2023 21:40