More parameters for a lofi dsp Tuesday, Mar 23 2010 

Totally random, but when I finish this analog lofi matrix dsp, it will be called ‘lofnck.’

So some more mathematics, some more fun parameters, and some fun shiiit.

Another way that you can crunchy down a signal is by lowering its firing rate. That sort of thing acts like a wild form of a low-pass filter, or, as they say in the hood, a pretty gangsta’ LP filter.

Basically, we want to dirty down the signal by downsampling it. There’s a natural tendency for sound to move down to lower tones when they’re downsampled enough (that is, its Nyquist frequency goes down and square-like distortion is introduced).

Recall that I modeled discrete signals with a continuous map f:\mathbb{Z} \rightarrow [-1, 1]. Let’s simplify notation a bit and just look at pairs (x, f(x)) \in \mathbb{Z} \times [-1,1]. I believe that the set of these functions, or the function space, is a Banach space (but thankfully, this consideration is far off as I’m not making a synth here, but a stable audio processing unit). Also, I believe there should be a smooth lifting of these functions into \mathbb{R} \rightarrow [-1,1] (which I will use to model analog signals).

The function space is already a Lebesgue space under the measure \mu(X) = |X|. We can define a Lebesgue integral over it (or we can even go ahead and use the stronger example of sequence spaces, since the difference between N and Z in this application is not really important).

An example of a discrete linear approximation of the analog sound I want would be to simply take our DSP to be a map

(x, f(x)) \mapsto (x, (1/|A|)\sum_A f(x)) where A is a partition element of a nice partition of Z containing x.

but the issue with this map is that it’s naive and probably loses a lot of audio quality (God is in the details, as the old folks would say). There are a couple of details about its use as well:

1) In general, you can’t say if the digital signal is convergent, so you can’t guarantee that things would work out because input ‘niceness’ is something you can’t control. On the other hand, most audio signals people will use with this utility will be at the very least reasonable in that sense, being of finite time length and whatnot. So uh, it will work out, basically.

2) It will cost more to do it the nicer way. But CPUs are pretty powerful nowadays, and having quality shit is good even if it runs your CPU a bit hot.

3) Reasonably well mixed audio signals intended for music are going to be pretty super-nice anyways.

4) The parameter is discrete. Let’s make it more analogy.

So we may decide to anti-alias the downsampling and make it go all smoother and gooeyer all analog-like and shit. The signal we have corresponds with a simple function in the standard Lebesgue space on R. This simple function approximates some smooth functions, since simple functions are dense in the space of smooth functions. We want to find such a weak smooth function which can be approximated well using as little CPU as possible.

One thing we may do with such a lifting is to give nicely anti-aliased sound given a real number parameter for the width of the R-partition (or, in this case, it would be floats or doubles in application). So first we operate on the smooth lifting in this way:

(f:\mathbb{R} \rightarrow [-1, 1]) \mapsto (x \mapsto (1/\mu(A)) \int_A f d\mu) where x \in A a \phi-partition element of \mathbb{R}, and \phi is our partition length (which thus induces a downsampling of the analog signal model)

We also want modulated partition lengths to preserve audio stability. As I recall from an analysis class, subsets of \mathbb{R} of the form [a, b) are an important subcollection of Lebesgue-measurable sets in (\mathbb{R}, M, \mu). We may also partition \mathbb{R} with sets of this form and have a map from \mathbb{Z} into such a partition given by \chi: n \mapsto [a, b), \quad a \leq n < b.

So our audio processor is straight up like this: for (x, f(x)) \in [-1, 1]^\mathbb{Z}, \quad (x, f(x)) \mapsto (x, \frac{1}{\mu(A)} \int_A f d\mu) where A = \chi(x)

We get anti-aliasing and stability for free by how sets of the form [a, b) can build a disjoint partition of R.

The little bit missing from this picture is the smooth lifting. I’ll need some time to think on that one. There may be better ways of directly approximating this whole process that would take CPU use down several notches.

Postscript: I actually don’t know anything about audio engineering. 😉 I suppose I will have to let the plugin itself speak for the various ideas being thrown about here

Post-postscript: I got my VST developing environment set up! Experimentation is forthcoming. Watch this blog for free audio plugins, hehe.

edit: I think that what I really want to do is to find a series of polynomials which converge rapidly to the map mentioned above, as polynomials are both analytic and awesome.

edit2: Taylor series should totally work for this shit.

edit3: is the way to victory.

edit4: No, no, wait, it’s splines. Blergh.


DSP coding time. Monday, Mar 22 2010 

I’m doing this music project, and I wanted to add math to it, and I also got really into Panthu Du Prance’s “Black Noise” – it’s such a deep musical journey if you listen through it with an open mind; for me, the album felt like my first listens of Boards of Canada’s “Music Has the Right to Children”.

My fourier analysis is a bit rusty right now. Anybody more in tune with the psychoacoustic physics want to lend a hand and drop some tips on some psychoacoustic maps for the input and output signals? I’m coding a vintage-sounding lofi matrix for chiptune uses (so like signal discretification + coloration).

Thinking here for a model of what I’m trying to do – to be honest I’m really just making up terms as we go along based on things I remember: a digital signal would be discrete, so this matter would have to be handled discretely. The discrete signal may be represented mathematically as a continuous function f:\mathbb{Z} \rightarrow [-1, 1] where Z has the discrete topology and [-1, 1] the usual. The codomain, when I code this, will be represented by floats, but the math for floats is similar enough to math for real numbers on a bounded interval that the sound will pretty much be reproduced up to human perception.

Or to say that it’s with hi-fi signals I want to code. I want my shit to sound like vinyl signals being fed through NES hardware. Aw yeah.

Of course, I’ll also have to implement output for the discrete case, since the vst host may not do floats and do 24-bit or 16-bit integers instead (which is kinda weird now since we have 32-bit processors, but whatever, audio industry standards lol).

So let’s think about signal maps. A signal map is a map \phi:[-1, 1]^\mathbb{Z} \rightarrow [-1, 1]^\mathbb{Z}, where [-1, 1]^\mathbb{Z} is the function space for signals as modeled above. We may attempt to fit this function space with some properties, then.

Afterwards, I guess I should try to find a topology on the thing. Or maybe even a Hilbert space. Actually, it could very well be a Hilbert space given the right choices for the norm, addition and scalar multiplication. Though, that’s stuff that I would do just for the hell of doing it.

What I would need to do is to figure out specific signal maps that would make interesting effects for this project, really. Like for example the lofi matrix + analog coloration dsp I wanted to make would probably include discretification at some point. That would be some sort of discontinuous map f(x) = some chopped bits in the float representation of x.

Cool, I have a plan of attack now.

tl;dr: have a lollipop. I’m going to do some research on some shit hell yeah.


Thinking a bit more on the subject, I think I have an algo for making signals more discrete, given by f(x) = [\rho x]/\rho, where \rho is the granularity of the discretification.

moar edit:

Audio information preservation in the face of discretification is probably closely related to the fact that simple functions are dense in L_0 spaces and the algo I listed above is invariably a simple function (so in a sense density in L_0 suggests that all continuous functions can be approximated this way, which isn’t surprising, but nice and intuitive).