Distorsion using PixelBender
After reading Tinic Uro and Kevin Goldsmith’s posts, I decided to try PixelBender for audio processing.
Mixing several sounds is nice, but it would be cool to process real time effects. Here is a first try. A very very simple distorion, still not a wave shaper (wich should sound better).
This PixelBender filter uses two parameters : drive and volume. Volume is usefull to readjust the signal after it has been limited by the distorion.
I have recorded a raw sound from an electric guitar, without any effect.
The effect needs to be improved. It doesn’t sound that bad near the “crunch” position, but gets bad after. But, on my computer, Dual Core 3G, it only takes 3 to 5% of the CPU usage with FireFox. I’m pretty sure it would be more CPU expensive without the shader.
The code :
as3:
package {
/**
*
* Auteur: Yann Rayon
* d'apres : kevin goldsmith http://blogs.adobe.com/kevin.goldsmith/adobe-image-foundation/pixel-bender/
* et : Tinic Uro http://www.kaourantin.net/2008/10/audio-mixing-with-pixel-bender.html
* Website: http://www.akaneko.com
* Description: test d'effet distorsion avec PixelBender.
*
**/
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
import flash.display.Shader;
import flash.filters.ShaderFilter;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.SampleDataEvent;
import flash.utils.ByteArray;
import flash.display.ShaderJob;
public class Distorsion extends Sprite {
private var _loader:URLLoader;
private var shader:Shader;
private var filter:ShaderFilter;
private var guitar:Sound;
private var sc:SoundChannel;
private var audioTrack:Sound = new Sound();
private var sourcePos:Number = 0;
private static var BUFFER_SIZE:uint = 0x800;
public function Distorsion():void {
_loader = new URLLoader();
_loader.dataFormat = URLLoaderDataFormat.BINARY;
_loader.addEventListener(Event.COMPLETE, onLoadComplete);
_loader.load(new URLRequest( "distorsion.pbj"));
addEventListener(MouseEvent.CLICK, doMouse);
}
private function doMouse(e:MouseEvent):void
{
var cible = e.target;
switch(cible) {
case btStart:
sc = audioTrack.play();
break;
case btStop:
if(sc!=null){
sc.stop();
}
break;
default:
break;
}
}
private function onLoadComplete(event:Event):void {
shader = new Shader(event.target.data);
guitar = new Signal(); // audio file
audioTrack.addEventListener(SampleDataEvent.SAMPLE_DATA, audioProcess)
}
function audioProcess(event:SampleDataEvent):void {
var shaderBuffer:ByteArray = new ByteArray();
shaderBuffer.length = BUFFER_SIZE * 2 * 4;
sourcePos += guitar.extract(shaderBuffer, BUFFER_SIZE, sourcePos);
shaderBuffer.position = 0;
shader.data["source"].width = BUFFER_SIZE / 1024;
shader.data["source"].height = 512;
shader.data["source"].input = shaderBuffer;
shader.data["drive"].value = [ slider.value];
shader.data["volume"].value = [ 1 + (slider.value / 2)];
var effectJob:ShaderJob = new ShaderJob( shader, event.data, BUFFER_SIZE / 1024, 512 );
effectJob.start(true);
if ( sourcePos >= (462848) ) // detecting mp3 end. the bytesTotal property returns a wrong value for an embeded mp3, so I used an int instead, wich is the reel length to use.
{
sourcePos = 0;
}
}
}
}
pixelbender:
<languageVersion : 1.0;>
kernel NewFilter
< namespace : "com.akaneko";
vendor : "Yann Rayon";
version : 1;
description : "soundWork";
>
{
input image4 source;
output float4 dest;
parameter float drive <
minValue: float(1.0);
maxValue: float(500.0);
defaultValue: float(1.0);
>;
parameter float volume <
minValue: float(1.0);
maxValue: float(500.0);
defaultValue: float(1.0);
>;
void evaluatePixel()
{
dest = sampleNearest(source, outCoord());
dest[0] = max(-(1.0/drive),min((1.0/drive),dest[0]))*volume;
dest[2] = max(-(1.0/drive),min((1.0/drive),dest[2]))*volume;
dest[1] = max(-(1.0/drive),min((1.0/drive),dest[1]))*volume;
dest[3] = max(-(1.0/drive),min((1.0/drive),dest[3]))*volume;
}
}
Now, I’ll try to improve this with a wave shaper, and I’m pretty sure that efficient and low CPU Eqs, fast pitch shifting …. are possible.
October 15th, 2009 at 11:22 pm
[...] This post was mentioned on Twitter by Tex, tekool. tekool said: RT @yannrayon: first try with pixelbender and audio http://bit.ly/38KgNi [...]
October 16th, 2009 at 6:15 am
Some things are so sweet they make your teeth hurt. OUCH!
October 17th, 2009 at 5:19 pm
Hello from Russia!
Can I quote a post in your blog with the link to you?
January 2nd, 2010 at 1:54 am
With this one I play it then I scroll down the page and the file pays back all timestretched down a few notches, radness in the browser glitch!