Skip to content

Commit 49f1d81

Browse files
jvntftherewasaguy
authored andcommitted
add p5.Compressor (#179)
* started writing compressor.js * rough structure of compressor * draft of compressor * updated gruntfile, added restrictions and error logging to compressor * removed range error checking * compressor test * started writing compressor.js * rough structure of compressor * draft of compressor * updated gruntfile, added restrictions and error logging to compressor * removed range error checking * compressor test * rough example added * reworking example * added time scheduling to compressor audioParams * setup objects for compressor example * finished UI for example * example working with UI * removed requirs(effect) from app.js * added description to example * formatted numbers to 2 dec places in ex * edited doc * fixed error in compressor test * added example to index.html * added doc, changed != to !==
1 parent a5d05fe commit 49f1d81

File tree

10 files changed

+672
-3
lines changed

10 files changed

+672
-3
lines changed

Gruntfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ module.exports = function(grunt) {
7878
'filter': 'src/filter',
7979
'reverb': 'src/reverb',
8080
'distortion': 'src/distortion',
81+
'compressor': 'src/compressor',
8182
'looper': 'src/looper',
8283
'soundRecorder': 'src/soundRecorder',
8384
'signal': 'src/signal',

examples/Compressor/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<head>
2+
<script language="javascript" type="text/javascript" src="../../lib/p5.js"></script>
3+
4+
<script language="javascript" type="text/javascript" src="../../lib/addons/p5.dom.js"></script>
5+
6+
<script language="javascript" type="text/javascript" src="../../lib/p5.sound.js"></script>
7+
8+
<script language="javascript" type="text/javascript" src="sketch.js"></script>
9+
10+
</head>

examples/Compressor/sketch.js

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
var fftHeight;
2+
var fftWidth;
3+
4+
var soundFile;
5+
var fft;
6+
7+
var compressor;
8+
9+
//UI Objects
10+
var cntrls = [];
11+
//var threshCntrl;
12+
13+
14+
//knob info
15+
16+
//colors
17+
var knobBckg;
18+
var knobLine;
19+
var threshLineCol;
20+
21+
//dimensions
22+
var knobRad;
23+
var knobLineLen;
24+
25+
var pressed;
26+
var cntrlIndex;
27+
28+
var description;
29+
30+
function preload() {
31+
soundFormats('mp3', 'ogg');
32+
soundFile = loadSound('../files/beat');
33+
}
34+
35+
function setup() {
36+
37+
38+
39+
pressed = false;
40+
angleMode(DEGREES);
41+
42+
createCanvas(710, 400);
43+
44+
45+
fftHeight = 0.75*height;
46+
fftWidth = 0.8*width;
47+
// loop the sound file
48+
// soundFile.loop();
49+
50+
51+
compressor = new p5.Compressor();
52+
53+
// Disconnect soundfile from master output.
54+
// Then, connect it to the filter, so that we only hear the filtered sound
55+
soundFile.disconnect();
56+
compressor.process(soundFile);
57+
58+
// compressor.process(soundFile);
59+
60+
fft = new p5.FFT();
61+
62+
63+
soundFile.loop();
64+
65+
66+
//Create cntrls
67+
var x = 0.0625*width;
68+
var y = .25*height;
69+
cntrls[0] = new Knob('attack');
70+
cntrls[1] = new Knob('knee');
71+
cntrls[2] = new Knob('ratio');
72+
cntrls[3] = new Knob('release');
73+
cntrls[4] = new Knob('drywet');
74+
75+
for (var i = 0; i < cntrls.length; i++) {
76+
cntrls[i].x = x;
77+
cntrls[i].y = y + y*i;
78+
}
79+
for (var i = 3; i < 5; i++) {
80+
cntrls[i].x = width - x;
81+
cntrls[i].y = y*(i-1);
82+
}
83+
// cntrls[3] = new Knob('release');
84+
// cntrls[3].x = width-x;
85+
// cntrls[3].y = 3*y;
86+
87+
knobRad = .15*height;
88+
knobLineLen = knobRad/2;
89+
90+
91+
//create Threshold control and
92+
//
93+
cntrls[5] = new ThreshLine('threshold');
94+
95+
knobBckg = color(150);
96+
knobLine = color(30);
97+
98+
99+
100+
threshLineCol = color(30);
101+
102+
description = createDiv("p5.Compressor: <br>" +
103+
"Adjust the knobs to control the compressor's " +
104+
"attack, knee, ratio, release, and wet / dry values " +
105+
"Move the slider to adjust threshold." +
106+
"For information on these audioParams, see <br>" +
107+
"<a href =https://www.w3.org/TR/webaudio/#the-dynamicscompressornode-interface>"+
108+
"Web Audio Dyanmics Compressor Node Interface</a>");
109+
description.size(.75*fftWidth, AUTO);
110+
description.position(width-fftWidth, 1.15*fftHeight);
111+
}
112+
//attack knee ratio threshold release
113+
114+
function draw() {
115+
116+
117+
118+
background(255);
119+
fill(180);
120+
//sound wave
121+
var spectrum = fft.analyze();
122+
noStroke();
123+
for (var i = 0; i< spectrum.length; i++){
124+
var x = map(i, 0, spectrum.length, 0.2*width, fftWidth);
125+
var h = -fftHeight + map(spectrum[i], 0, 255, fftHeight, 0.125*height);
126+
rect(x, fftHeight, fftWidth/spectrum.length, h) ;
127+
}
128+
129+
130+
131+
132+
if (pressed) {cntrls[cntrlIndex].change();}
133+
134+
for (var i = 0; i < cntrls.length; i++) {
135+
136+
cntrls[i].display();
137+
138+
}
139+
140+
//text(description, width - fftWidth, 1.1*fftHeight);
141+
142+
}
143+
144+
function ThreshLine(type) {
145+
this.type = type;
146+
this.x = width - fftWidth;
147+
this.range = getRange(type);
148+
this.current = getDefault(type);
149+
this.y = map(this.current, -100,0,fftHeight, height - fftHeight);
150+
151+
this.length = fftWidth;
152+
153+
this.display = function () {
154+
stroke(threshLineCol);
155+
line(this.x,this.y, this.length, this.y)
156+
noStroke();
157+
text(type, fftWidth - 50, this.y+knobLineLen, knobRad,knobRad);
158+
text(this.current, fftWidth - 50, this.y + knobLineLen + 10, knobRad, knobRad);
159+
160+
};
161+
162+
this.change = function () {
163+
// this.y = mouseY;
164+
if (mouseY < height - fftHeight) {this.y = height - fftHeight}
165+
else if (mouseY > fftHeight) {this.y = fftHeight;}
166+
else { this.y = mouseY;}
167+
this.current = map(this.y, fftHeight, height - fftHeight, -100,0);
168+
169+
170+
};
171+
172+
this.mouseOver = function () {
173+
if (mouseX > this.x && mouseX < width - this.x
174+
&& mouseY < this.y + 5 && mouseY > this.y - 5){
175+
return true;
176+
} else {
177+
return false;
178+
}
179+
}
180+
181+
}
182+
183+
function Knob(type){
184+
this.type = type;
185+
this.range = getRange(type);
186+
this.default = getDefault(type);
187+
this.current = this.default;
188+
this.curAngle = map(this.current, this.range[0], this.range[1],50,320);
189+
this.x;
190+
this.y;
191+
192+
this.display = function () {
193+
noStroke();
194+
fill(knobBckg);
195+
ellipse(this.x, this.y, knobRad,knobRad);
196+
197+
//draw the indicator line from knob center
198+
translate(this.x,this.y);
199+
rotate(this.curAngle);
200+
stroke(knobLine);
201+
line(0,0,0,knobLineLen);
202+
rotate(-this.curAngle);
203+
translate(-this.x,-this.y);
204+
noStroke();
205+
text(type, this.x - knobLineLen, this.y+knobLineLen, knobRad,knobRad);
206+
text(float(this.current).toFixed(2), this.x - knobLineLen, this.y + knobLineLen + 10, knobRad, knobRad);
207+
}
208+
209+
this.mouseOver = function () {
210+
if (mouseX > this.x - knobLineLen && mouseX < this.x + knobLineLen
211+
&& mouseY < this.y + knobLineLen && mouseY > this.y - knobLineLen){
212+
return true;
213+
} else {
214+
return false;
215+
}
216+
}
217+
218+
this.change = function () {
219+
translate(this.x, this.y);
220+
var a = atan2(mouseY - this.y, mouseX - this.x);
221+
//console.log(a);
222+
this.curAngle = a - 90;
223+
224+
if (this.curAngle < 0) {this.curAngle = this.curAngle + 360;}
225+
if (this.curAngle < 50 ) {this.curAngle = 50;}
226+
else if (this.curAngle > 320) {this.curAngle = 320;}
227+
this.current = updateVal(this.range, this.curAngle - 50, cntrlIndex);
228+
229+
translate(-this.x,-this.y);
230+
}
231+
}
232+
233+
234+
235+
236+
237+
238+
239+
// -50 -> 90 -> 320
240+
241+
242+
// 0 - 360
243+
244+
// 310 - 230
245+
246+
// map(value, 0, 360, 310, 230)
247+
248+
/**
249+
* @attack 0 - 1
250+
* @knee { 0 - 40}
251+
* ratio 1 -20
252+
* release 0 -1
253+
* threshold -100 - 0
254+
*/
255+
256+
257+
function getRange(type){
258+
switch (type) {
259+
case "attack":
260+
return [0,1];
261+
case "knee":
262+
return [0,40];
263+
case "ratio":
264+
return [1,20];
265+
case "release":
266+
return [0,1];
267+
case "threshold":
268+
return [-100,0];
269+
case "drywet":
270+
return [0,1];
271+
default:
272+
return 0;
273+
}
274+
}
275+
276+
function getDefault(type){
277+
switch (type) {
278+
case "attack":
279+
return .003;
280+
case "knee":
281+
return 30;
282+
case "ratio":
283+
return 12;
284+
case "release":
285+
return 0.25;
286+
case "threshold":
287+
return -24;
288+
case "drywet":
289+
return compressor.drywet(1);
290+
default:
291+
return 0;
292+
}
293+
}
294+
295+
296+
297+
298+
function updateVal(range, curAngle, cntrlIndex) {
299+
var newVal = map(curAngle, 0,270,range[0],range[1])
300+
switch (cntrlIndex) {
301+
case 0:
302+
compressor.attack(newVal);
303+
break;
304+
case 1:
305+
compressor.knee(newVal);
306+
break;
307+
case 2:
308+
compressor.ratio(newVal);
309+
break;
310+
case 3:
311+
compressor.release(newVal);
312+
break;
313+
case 4:
314+
compressor.drywet(newVal);
315+
break;
316+
case 5:
317+
compressor.threshold(newVal);
318+
break;
319+
default:
320+
break;
321+
}
322+
return newVal;
323+
}
324+
325+
function mousePressed(){
326+
for (var i = 0; i < cntrls.length; i++) {
327+
if (cntrls[i].mouseOver()){
328+
pressed = true;
329+
cntrlIndex = i;
330+
break;
331+
}
332+
333+
}
334+
335+
336+
}
337+
338+
function mouseReleased(){
339+
pressed = false;
340+
}

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ <h2>p5.sound
2121
<div><a href="examples/audioIn_Multiple_Sources">audioIn_Multiple_Sources</a></div>
2222
<div><a href="examples/autoCorrelation">autoCorrelation</a></div>
2323
<div><a href="examples/bells_envelope_test">bells_envelope_test</a></div>
24+
<div><a href="examples/Compressor">Compressor</a></div>
2425
<div><a href="examples/distortion">distortion</a></div>
2526
<div><a href="examples/envAmpFreq">envAmpFreq</a></div>
2627
<div><a href="examples/envExp">envExp</a></div>

0 commit comments

Comments
 (0)