Recently, in Boing Boing, there was a post about a company marketing a subliminal message to gamers. They would hear the message 10000 – 20000 times a second. That’s 10 kHz – 20 kHz. Those repetitions are almost too high to be in the audio range! I can’t hear 20 kHz all that well. Also, what about scaling? To keep from peaking, the maximum amplitude of
each message would have to be between 0.00005 – 0.0001 of the total amplitude range. That’s pretty subliminal, all right.
I went to work trying to play a short aiff file over and over at that rate. My processor crapped out really fast. That’s a lot of addition. As I was falling asleep that night, I calculated that on a CD, each new message would start every 4 – 10 bytes! Why at that rate, it’s practically convolution.
Indeed, it is more than “practically” convolution, it is convolution and as such it doesn’t need to be done via real-time additions, but can be done via free software like SoundHack. The first step is getting a series of impulses. To try to create a “subliminal” message, you need a series of positive impulses that vary randomly between 10000 – 20000 times per second. I wrote a short SuperCollider program to produce such impulses.
SynthDef("subliminal-impulse", {arg out = 0;
var white, ir;
white = WhiteNoise.kr;
white = white.abs;
white = white * 10000;
white = white + 10000;
ir = Dust.ar(white);
Out.ar(out, ir);
}).play
The WhiteNoise.kr produces random values between -1 and 1. We take the absolute value of that to just get numbers between 0 – 1. Then we multiply, to make them numbers between 0 – 10000 and add to put them in the range 10k – 20k.
Dust makes impulses at random intervals. The impulses are between 0 – 1. The argument is the average number of impulses per second. So Dust makes 10k – 20k impulses per second. Record the output of that to disk and you’ve got some noise, but it’s noise with some important characteristics – all the impulses are positive and they have zeros between them. This is what we need if we’re going to be subliminal at gamers.
Ok, so I’m going to take that file and open it SoundHack and save a copy of it as a 16bit file, rather and a 32 bit file. Then I’ll split the copy into separate mono files. (This is all under the file menu.) then, to save disk space, I’ll throw away the 32 bit file and the silent right channel. So now I have a 16bit mono file full of impulses open in SoundHack
Under the Hack menu, there’s an option called “Convolution.” Pick that. Check the box that says “Normalize” (that will handle the amplitude for you so the result is neither too quiet or too loud) and then hit the button that says “Pick Impulse.” This will be our recording of spoken text that we want made subliminal. (Fortunately, I had such a message at hand.) In actuality, it doesn’t matter which file is the one with the clicks and which is the one with the text. Convolution treats both files as equal partners. Then it asks us to name the output file. Then it goes, then we’re done. Here’s my result.
If you suddenly feel like forming a militia or running in fear, then it worked. If not, well, the sonic result is still kind of interesting. The timbres are all totally present but the actual sound events are unintelligible (at least to the conscious mind). For every one of our little impulses created by Dust.ar, we’ve got a new copy of Jessica plotting revolution. (The text is actually from Lesbian Philosophy: Explorations by Jeffner Allen (Palo Alto: Institute of Lesbian Studies, 1987) and the piece I originally made with it is here.)
This is actually a lot like granular synthesis, if you think about it. Imagine that instead of convolving the whole audio file, we just did 50ms bits of it. Every impulse would start a new copy of the 50 ms grain, but instead of with additions, with FFTs, which are faster – we can have many, many more grains. And they could be smaller and still be meaningful. Heck, they could be the size of the FFT window.
The FFT version of a convolution involves taking a window of the impulse and another of the IR (our subliminal message – normally known as an impulse response). You add the phases together and multiply the amplitudes. The amplitudes multiplications give us the right pitch and the phase addition gives us the right timing – almost. Some additions will be too big for the window and wrap around to the beginning. You can avoid that by adding zero padding. You double the size of the window, but only put input in the first half. Then none of your phases will wrap around.
We can get some very granular like processes, but with nicer sound and better efficiency. For example, time stretching. We could only update the IR half as often as the impulse stream and do window-by window convolutions. There are other applications here. I need to spend time thinking of what to do with this. Aside from sublimating revolution.
Podcast: Play in new window | Download