Bad, vile and meaningless: Near release with GNUitar from Alan's clob

Sync

Plenty of minor activity in my life lately.

Toothache

I've now understood at very fundamental level that going to dentist belongs as part of the interface to being human. That is to say, it's mandatory, not optional, and a damn good device you'll be fool to do without.

I have had some sorts of minor toothache for years now, but I always pushed going to dentist off on the theory that eventually the hole will kill the kernel of the tooth and that's the end of the problem. Well! I didn't know about root canals, which have a tendency to get infected. And I didn't know how painful such an infection can be in the jaw, when it nears the nerve that goes along the line of teeth in the jaw. (And it's particularly gruesome if that nerve would be destroyed by an infection.) I was taking a wait-see attitude, but gradually the pain was getting worse...

Last week, I was howling in pain half the time and drunk bucketfuls of ice cold water, as cold water gave temporary ease to the pain. I had several liters of water in freezer at all times, and would fetch a new bottle as soon as I had warmed the last one by holding mouthfuls of said water in mouth and then spitting it out. I hardly slept for three nights. (It's hard to sleep with ice water in your mouth. I tried. The problem is that as soon as you fall asleep you drool it all over your pillow.)

Why did it take three nights? Am I exceptionally stupid or stubborn? You might say so, and even be relatively right, but in this case the timing was an issue: the toothache got serious only late Saturday and dentists weren't available on Sunday, so I had to survive until Monday before it could be operated. Now, that's only two nights. The pain just didn't go away; the infection was still going strong. I was on antibiotics but it took a few days to reverse this train of pain, somewhere from brink of personal extinction back to "whee, I can sleep without overdose of painkillers".

In fact, the only painkiller that had any effect for me was prescribed by the dentist, and would work for about 1-2 hours at a time. Except in many nights I was not smart enough to go to bed immediately after swallowing a pill, but rather enjoyed the relatively painless time awake. Stupid, stupid, stupid.

In the end penicilin won the day, and I had second operation on friday at another tooth that was as bad as the first one. I hardly noticed any residual pain, and in fact I've been feeling excessively healthy with the absence of almost any tooth pain. (The remaining problem cases will be dealt with in a few later visits to dentist. I can hardly wait to exit this episode in my life.)

Gnuitar update

So I've spent good chunk of last month working over gnuitar, and also playing my guitar. I've written bunch of effects and start to feel like I understood C programming by and by.

All in all, remarkably good month programming-activity-wise. We'll make a new release shortly. Max has cancelled 0.3.3, probably 0.4.0, too, and the release will be called 0.5.0, I think. As far as I can see, only one item in the TODO list is left and that's for Win32 which I have washed my hands clean of.

There is whole folklore of "good C practices", which I suspect are really big set of accumulated crud that I frankly think should be rethought. My girl friend works on a company that is big on C standards, and recently commented me typing something like

int     i, j, k, foo, bar;

which would be illegal in her company because the variables are not commented. My dismissive reply was "if the name is so bad as to need comment, the name must be changed".

I think .h files should only be used to declare the things required to interface with their corresponding .c file. No functions, defines or variables not intended to be shared should be written into it. I wish C compilers supported "private" symbols, that is, symbols never "extern"'d anywhere. I hate having every heap variable and function in a global namespace in the end, it tends to make variable names so long.

And while we are here: why exactly can't the C compiler determine that variable foo or function bar was never used anywhere else but in one .c file and reduce visibility of that symbol to that one file. Linker complains if I redefine a symbol, which sucks.

Featured DSP effects

A word or two about the latest DSP effects in gnuitar.

Feature: Chorus

Chorus is an effect that simulates several players playing the same tune, although it sounds quite a bit different than what you would expect from such a description.

Chorus is implemented with mixing of time-delayed signal with the original. This is a simplified mixing function for a simple 1-voice chorus:

O(t) = I(t) + I(t - b - c * (1 + sin(nt)) / 2)

That is, the output of the effect is the current signal mixed with signal delayed by factors b and c times some modulation function. In the original version, the b parameter (called base delay or simply delay) is zero, and the c and n parameters are user tunable.

I changed this function as follows:

O(t) = I(t) + I(t - b - c * (1 + sin(nt     )) / 2) +
          I(t - b - c * (1 + sin(nt +  p)) / 2) + 
          I(t - b - c * (1 + sin(nt + 2p)) / 2) +
      ...

p is phase angle between the voices and is chosen so that each voice gets equal share of the "phase pie". For 3 voices, the angle would be 120. The algorithm in CSound where I stole this idea from featured more than one sin function and new parameters c2 and n2 which may be used to provide extra variation to the chorus sound.

In addition, I made this effect multichannel aware. In this case, the channel-specific output is coming from a function of this type, where c denotes the channel number:

O(t, c) = I(t) + I(t - b - c * (1 + sin(nt + cp)) / 2)

That is, the original signal combined with phase angle that depends on channel number. If there are more channels than voices, the effect currently duplicates the data on some channels. It might be a good idea to choose p from the number of output channels rather than let user pick a value in this case, or require that there are at most as many voices as there are channels.

Feature: echo

Echo in gnuitar is an infinite response device that remembers the last audio data in N parallel reverb buffers and mixes them all together into output using various decay factors derived from the age of the data in the reverb buffer.

The lengths of the reverb buffers are chosen from a set of prime numbers, starting from 10 and discarding every other prime. So buffer lengths are values like 11, 17, 23 times some unit of time. In addition, the decay factors are adjusted to buffer lengths assuming exponential decay. For instance, if there is 50 % of signal left after 11 time units, there must be less than 25 % signal left after about double of the time, 23. This means that data in the 3rd buffer decays over twice more per repeat of buffer, but the decay itself happens only less than half often.

What does it sound like? It produces a weird ripply click-clickrkrkrkkkrkk kind of echo that appears to come out of cave or something like that. Overall, our echo is even more "reverby" than the reverb effect, and much more versatile. By setting the number of voices to 1, you get the GNUitar stock reverb effect. I'm thinking about removing the reverb effect alltogether in favour of echo.

What I still need to investigate is adding some filtering to the repeatings of the data in buffer. A real echo discards some of the bass and probably some of the treble as well, acting like a bandpass filter. Also, some type of lo-fi decimator for the echoed sound might add additional sense of realism.

Above all, I must convert echo into multichannel. I'll probably do it the usual way and simply split the echo buffers up between available channels, producing a very complicated echo pattern that should mimick large hall echo fairly well.