Posted By

stefangoodchild on 02/10/10


Tagged


Versions (?)

Audio DNA Processing Sketch


 / Published in: Java
 

After some prompting I though I would publish some of my Processing source code to see what people made of it. Probably not the tidiest code out there, but these are essentially sketches so figured it didn’t matter too much.

To make this work you’ll need a few bits from around the internets. First up is the FFTOctaveAnalyser class from Dave Bollinger which you need to put in the root of your sketch directory, then you’ll need to download the Ess library.

Finally you’ll need something like Audacity to split an audio file into it’s left and right channels. Save them as two mono wav files (for some reason AIFF seems to upset it) called .L and .R and pop them in the sketch data directory.

Assuming all this has gone to plan all you need to do is edit the source code on line 4 so the audioFilename variable is the same as the referenced above and click the play button. Give it a second or two (depending on the length of the audio file) and you should see the Audio DNA displayed and find a TIFF version sitting in a folder called ‘out’ in your sketch folder.

Onto the source. The key to this is it’s not real time. It scans the audio file chunk by chunk so in this instance it’s faster than real-time. With some tweaks a similar technique can be used to render out audio reactive Processing sketches that run slower than real-time if that’s your bag.

  1. import krister.Ess.*;
  2.  
  3. String audioFilename = "md";
  4. String audioFilenameL = audioFilename+".L";
  5. String audioFilenameR = audioFilename+".R";
  6.  
  7. int imgSize = 500;
  8.  
  9. // SinCos Lookup tables from Toxi (i think via flight404...) He's a clever chap, look him up.
  10. public static final float sinLUT[];
  11. public static final float cosLUT[];
  12. public static final float SINCOS_PRECISION=1f;
  13. public static final int SINCOS_LENGTH= (int) (360f/SINCOS_PRECISION);
  14. static {
  15. sinLUT=new float[SINCOS_LENGTH];
  16. cosLUT=new float[SINCOS_LENGTH];
  17. for (int i=0; i<SINCOS_LENGTH; i++) {
  18. sinLUT[i]= (float)Math.sin(i*DEG_TO_RAD*SINCOS_PRECISION);
  19. cosLUT[i]= (float)Math.cos(i*DEG_TO_RAD*SINCOS_PRECISION);
  20. }
  21. }
  22.  
  23. AudioChannel chnL;
  24. AudioChannel chnR;
  25. FFT fftL;
  26. FFT fftR;
  27. FFTOctaveAnalyzer octL;
  28. FFTOctaveAnalyzer octR;
  29. int bufferSize = 1024;
  30. int samplingRate = 44100;
  31.  
  32. int frameL = 0;
  33. int frameR = 360;
  34.  
  35. int samplesPerDegree;
  36. int section;
  37.  
  38. float[] limits = new float[9];
  39. float[] radii = new float[9];
  40. float[] linethick = new float[9];
  41.  
  42. float radStep;
  43.  
  44. void setup() {
  45. size(imgSize, imgSize, P3D);
  46. noStroke();
  47. Ess.start(this);
  48. chnL = new AudioChannel(dataPath(audioFilenameL));
  49. chnR = new AudioChannel(dataPath(audioFilenameR));
  50. samplesPerDegree = chnL.size/181;
  51. fftL = new FFT(bufferSize*2);
  52. fftR = new FFT(bufferSize*2);
  53. fftL.limits();
  54. fftR.limits();
  55. fftL.damp(.5);
  56. fftR.damp(.5);
  57. octL = new FFTOctaveAnalyzer(fftL, samplingRate, 1);
  58. octR = new FFTOctaveAnalyzer(fftR, samplingRate, 1);
  59. octL.peakHoldTime = 10; // hold longer
  60. octL.peakDecayRate = 3; // decay slower
  61. octL.linearEQIntercept = 0.7; // reduced gain at lowest frequency
  62. octL.linearEQSlope = 0.02; // increasing gain at higher frequencies
  63. octR.peakHoldTime = 10; // hold longer
  64. octR.peakDecayRate = 3; // decay slower
  65. octR.linearEQIntercept = 0.7; // reduced gain at lowest frequency
  66. octR.linearEQSlope = 0.02; // increasing gain at higher frequencies
  67. background(255);
  68. fill(0);
  69. noLoop();
  70. }
  71.  
  72. void draw() {
  73. limits[0] = 0.3;
  74. limits[1] = 0.6;
  75. limits[2] = 0.5;
  76. limits[3] = 0.4;
  77. limits[4] = 0.4;
  78. limits[5] = 0.4;
  79. limits[6] = 0.3;
  80. limits[7] = 0.3;
  81. limits[8] = 0.3;
  82.  
  83. float radStart = imgSize/10;
  84. float radEnd = imgSize*0.9;
  85. radStep = (radEnd-radStart)/9;
  86. float radCurrent = radStart;
  87.  
  88. for (int r = 0; r < 9; r++) {
  89. radii[r] = radCurrent/2;
  90. radCurrent = radCurrent+radStep;
  91. }
  92.  
  93. for (int frm = 0; frm < 181; frm++) {
  94. analyze();
  95. render();
  96. advance();
  97. }
  98. saveFrame("out/"+audioFilename+".tif");
  99. }
  100.  
  101. void analyze() {
  102. section = (int)(frameL * samplesPerDegree);
  103. fftL.getSpectrum(chnL.samples, section);
  104. fftR.getSpectrum(chnR.samples, section);
  105. octL.calculate();
  106. octR.calculate();
  107. }
  108.  
  109. void render() {
  110. for (int i = 0; i < 9; i++) {
  111. if (octL.averages[i]>limits[i]) myArc(width/2,height/2,frameL,frameL+2,radii[i],radStep/2.5,.5);
  112. if (octR.averages[i]>limits[i]) myArc(width/2,height/2,frameR,frameR+2,radii[i],radStep/2.5,.5);
  113. }
  114. }
  115.  
  116. void advance() {
  117. frameL ++;
  118. frameR --;
  119. }
  120.  
  121. public void stop() {
  122. Ess.stop();
  123. super.stop();
  124. }
  125.  
  126. void arc(float x,float y,float degS,float degE,float rad,float w) {
  127. int start=(int)min (degS/SINCOS_PRECISION,SINCOS_LENGTH-1);
  128. int end=(int)min (degE/SINCOS_PRECISION,SINCOS_LENGTH-1);
  129. beginShape(QUAD_STRIP);
  130. for(int i=start; i<end; i++) {
  131. vertex(cosLUT[i]*(rad)+x,sinLUT[i]*(rad)+y);
  132. vertex(cosLUT[i]*(rad+w)+x,sinLUT[i]*(rad+w)+y);
  133. }
  134. endShape();
  135. }
  136.  
  137. void myArc(float x,float y,float degS,float degE,float rad,float w, float step) {
  138. beginShape(QUAD_STRIP);
  139. noStroke();
  140. for (float i = degS; i < degE; i=i+step) {
  141. vertex(rad*cos(radians(i))+x,rad*sin(radians(i))+y);
  142. vertex((rad+w)*cos(radians(i))+x,(rad+w)*sin(radians(i))+y);
  143. }
  144. endShape();
  145. }

Report this snippet  

You need to login to post a comment.