Skip to content

Commit

Permalink
Merge pull request #96 from processing/newTone
Browse files Browse the repository at this point in the history
envelope improvements
  • Loading branch information
therewasaguy committed Feb 1, 2016
2 parents fbe35c5 + 5a6b23e commit 0f8d36f
Show file tree
Hide file tree
Showing 27 changed files with 3,364 additions and 757 deletions.
3 changes: 2 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ module.exports = function(grunt) {
include: ['src/app'],
onBuildWrite: function( name, path, contents ) {
if (path.indexOf('node_modules/tone/') > -1) {
return '/** Tone.js module by Yotam Mann, MIT License 2014 http://opensource.org/licenses/MIT **/\n' +
return '/** Tone.js module by Yotam Mann, MIT License 2016 http://opensource.org/licenses/MIT **/\n' +
require('amdclean').clean({
'code': contents.replace(/console.log(.*);/g, ''),
'escodegen': {
Expand Down Expand Up @@ -103,6 +103,7 @@ module.exports = function(grunt) {
out: 'lib/p5.sound.js',
paths: {
'Tone' : 'node_modules/tone/Tone',
'automation-timeline': 'node_modules/web-audio-automation-timeline/build/automation-timeline-amd',
'panner' : 'src/panner',
'sndcore': 'src/sndcore',
'master': 'src/master',
Expand Down
9 changes: 5 additions & 4 deletions examples/DelayNoiseEnvelope/sketch.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ function setup() {
delay = new p5.Delay();
delay.process(noise, .12, .7, 2300); // tell delay to process noise

// the Env accepts time / value pairs to
// create a series of timed fades
env = new p5.Env(.01, 1, .2, .1);
// the Env ADSR: attackTime, decayTime, sustainLevel, releaseTime
env = new p5.Env();
env.setADSR(0.01, 0.2, 0.2, 0.1)
env.setRange(1, 0);

// p5.Amplitude will analyze all sound in the sketch
analyzer = new p5.Amplitude();
Expand Down Expand Up @@ -52,5 +53,5 @@ function draw() {
}

function mousePressed() {
env.play(noise);
env.play(noise, 0, 0.1, 0);
}
Binary file not shown.
16 changes: 16 additions & 0 deletions examples/bells_envelope_test/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>bells_envelope_test</title>
<script language="javascript" type="text/javascript" src="../../lib/p5.js"></script>
<script language="javascript" type="text/javascript" src="../../lib/addons/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="../../lib/p5.sound.js"></script>

<script src="sketch.js" type="text/javascript"></script>

<style> body {padding: 0; margin: 0;} canvas {vertical-align: top;} </style>
</head>
<body>
</body>
</html>
142 changes: 142 additions & 0 deletions examples/bells_envelope_test/sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@

// This example shows a more complex use of the .ramp function for the envelope.
// You can use it to make a simple attack/decay envelope for struck or plucked style notes.
// Here, we're creating synthetic bells using additive synthesis, and triggering each of their attacks and decays differently to make different harmonics last for different times.
// Have fun! - Jeff Snyder
var osc = [];
var envelope = [];
var fft;
var myPhraseAttack, myPhraseRelease, myPart;
var atPattern = [1, 1,1,1,0,1,1,1,1,0,0,0,0]; // this rhythmic pattern puts some rests in there
var patternArray = [0,1,2,3,3,2,0,1]; // pattern of the notes (in terms of array indices from scaleArray)
var scaleArray = [64, 60, 62, 55]; // classic bell tune
var harmonicsArray = [.5, 1., 1.183, 1.506, 2., 2.514, 2.662, 3.011, 4.166, 5.433, 6.796, 8.215]; // bell partials taken from https://en.wikipedia.org/wiki/Strike_tone
var idealArray = [.5, 1., 1.2, 1.5, 2, 2.5, 2.6667, 3.0, 4.0, 5.3333, 6.6667, 8.0]; // ideal bell partials
var note = 0;
var startPoint = 0;
var endPoint = 0;
var numWaveforms = 100;
var numOsc = 12; // reduce this to reduce the number of overtones, 4 makes a nice, dark gamelan sound
var numNotes = 4;
var rawImpulse;
var cVerb;
var oscVols = [];
var firstNote = 1;
var pitchRatio = .8; //change this to transpose things around
var pitchDeviation = .001;
var idealOrReal = 0; // change this to 1 to change to an ideal bell instead of a measured bell
var maxAttack = .001; // in seconds ... setting to .001 makes things very percussive, setting to > 1 makes them sound far away
var maxDecay = 9.0; // in seconds ... short times make for deader bells
var percentWashed = 0.0;
var washedMax = 4;


function preload()
{
// create a p5.Convolver
cVerb = createConvolver('assets/LadyChapelStAlbansCathedral.wav');

}

function setup()
{
createCanvas(1000, 400);
rawImpulse = loadSound('assets/' + cVerb.impulses[0].name);

for (var i = 0; i < numNotes; i++)
{
// make the arrays into 2D arrays
osc[i] = [];
envelope[i] = [];
oscVols[i] = [];
var midiValue = scaleArray[i];
var freqValue = midiToFreq(midiValue);

for(var j = 0; j < numOsc; j++)
{
// make arrays of sine waves for each note, additive synthesis, and assign independent envelopes, amplitudes, and slight detunings for each harmonic
osc[i][j] = new p5.SinOsc();
envelope[i][j] = new p5.Env();
if (random(0, 1) > percentWashed)
{
myMaxAttack = maxAttack;
print("normal");
}
else
{
myMaxAttack = washedMax;
print("washed");
}
envelope[i][j].setADSR(random(.001, myMaxAttack), random(.01, maxDecay)); // turning sustain level to 0. makes an AD envelope
osc[i][j].amp(0.);
oscVols[i][j] = random(.01, .3);
if (idealOrReal == 0)
{
var myOvertone = harmonicsArray[j];
}
else
{
var myOvertone = idealArray[j];
}
osc[i][j].freq(freqValue * harmonicsArray[j] * random(1.0 - pitchDeviation, 1 + pitchDeviation) * pitchRatio);
osc[i][j].start();
osc[i][j].disconnect();
//put 'em through that reverb, ahhhhhh yeah it's like a New Age in here
cVerb.process(osc[i][j]);
}
}
myPhraseAttack = new p5.Phrase('testerAttack', makeSoundAttack, atPattern);
myPart = new p5.Part();
myPart.addPhrase(myPhraseAttack);
myPart.setBPM(15); // super slow because it's in 16th notes
myPart.loop();
myPart.start();
fft = new p5.FFT(); // for the drawing of the waveform (just using the buffer part)
endPoint = width / numWaveforms; // for the drawing
background(20);
}

function draw()
{
background(0, 0, 0, 9); //to make the trails fade like on a scope :)
var waveform = fft.waveform(); // analyze the waveform
fft.analyze();
beginShape();
noFill();
stroke(fft.getEnergy("bass") * 2.0, fft.getEnergy("mid")* 2.0, fft.getEnergy("treble") * 2.0); // the (* 2.0) is just to make the colors a little brighter
for (var i = 0; i < waveform.length; i++)
{
var x = map(i, 0, waveform.length, startPoint, endPoint);
var y = map(waveform[i], -.9, .9, height, 0);
vertex(x, y);
}
endShape();
startPoint = endPoint + 1;
endPoint += (width / numWaveforms);
if (endPoint > width)
{
redrawWaveform();
}
}

function makeSoundAttack(time, playbackRate)
{
var whichNote = patternArray[note];
for (var i = 0; i < numOsc; i++)
{
envelope[whichNote][i].ramp(osc[whichNote][i], time, (oscVols[whichNote][i] * random(.8, 1.0)), 0); // the added randomness just makes each strike a little different.
}
note = (note + 1) % patternArray.length;
if (firstNote == 1)
{
setTimeout(redrawWaveform, time * 1000.0); // just so the drawing display starts at the left on the first note
}
firstNote = 0;
}


function redrawWaveform()
{
startPoint = 0;
endPoint = (width / numWaveforms);
}
16 changes: 16 additions & 0 deletions examples/envAmpFreq/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<head>
<script language="javascript" type="text/javascript" src="../../lib/p5.js"></script>

<script language="javascript" type="text/javascript" src="../../lib/addons/p5.dom.js"></script>

<script language="javascript" type="text/javascript" src="../../lib/p5.sound.js"></script>

<script language="javascript" type="text/javascript" src="sketch.js"></script>

</head>

<body>
click to trigger amplitude and frequency envelopes

</body>
35 changes: 35 additions & 0 deletions examples/envAmpFreq/sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Control the level of an envelope
*/

var env; // this is the env
var osc; // this oscillator will modulate the amplitude of the carrier
var freqEnv; // env for frequency

function setup() {
env = new p5.Env();
env.setADSR(0.01, 0.2, 0.2, 0.3);
env.setRange(0, 1);

freqEnv = new p5.Env();
freqEnv.setADSR(0.01, 0.2, 0.2, 0.3);
freqEnv.setRange(300, 5000);


osc = new p5.Oscillator(); // connects to master output by default
osc.start(0);
osc.freq(220);
// osc.freq(env.scale(0,1,800,300));
osc.freq(freqEnv);
osc.amp(env);
}

function mousePressed() {
env.triggerAttack();
freqEnv.triggerAttack();
}

function mouseReleased() {
env.triggerRelease();
freqEnv.triggerRelease();
}
File renamed without changes.
118 changes: 118 additions & 0 deletions examples/envExp/sketch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* @name Note Envelope
* @description <p>An Envelope is a series of fades, defined
* as time / value pairs. In this example, the envelope
* will be used to "play" a note by controlling the output
* amplitude of an oscillator.<br/><br/>
* The p5.Oscillator sends its output through
* an internal Web Audio GainNode (p5.Oscillator.output).
* By default, that node has a constant value of 0.5. It can
* be reset with the osc.amp() method. Or, in this example, an
* Envelope takes control of that node, turning the amplitude
* up and down like a volume knob.</p>
* <p><em><span class="small"> To run this example locally, you will need the
* <a href="http://p5js.org/reference/#/libraries/p5.sound">p5.sound library</a> and a
* sound file.</span></em></p>
*/
var osc, envelope, fft;
var myPhraseAttack, myPhraseRelease, myPart;
var atPattern = [1, 0];
var relPattern = [0, 1];
var scaleArray = [60, 62, 64, 65, 67, 69, 71, 72];
var note = 0;
var expOrNot = 1;
var startPoint = 0;
var endPoint = 0;
var numWaveforms = 50;

var audioContext;

function setup() {
createCanvas(710, 200);
osc = new p5.SinOsc();

audioContext = getAudioContext();

// Instantiate the envelope with time / value pairs
envelope = new p5.Env(0.1, 0.5, 0.01, 0.0, 0.0, 0.0, 0.0, 0.0);
osc.amp(0.);
osc.start();
myPhraseAttack = new p5.Phrase('testerAttack', makeSoundAttack, atPattern);
myPhraseRelease = new p5.Phrase('testerRelease', makeSoundRelease, relPattern);
myPart = new p5.Part();
myPart.addPhrase(myPhraseAttack);
//myPart.addPhrase(myPhraseRelease);
myPart.setBPM(120);
myPart.loop();
myPart.start();
fft = new p5.FFT();
fft.setInput(osc);
masterVolume(0);
endPoint = width / numWaveforms;
noStroke();
background(20);
}

function draw() {

var waveform = fft.waveform(); // analyze the waveform
beginShape();
strokeWeight(5);
for (var i = 0; i < waveform.length; i++){
var x = map(i, 0, waveform.length, startPoint, endPoint);
var y = map(waveform[i], -1, 1, height, 0);
vertex(x, y);
}
endShape();
startPoint = endPoint + 1;
endPoint += (width / numWaveforms);
if (endPoint > width)
{
background(20);
startPoint = 0;
endPoint = (width / numWaveforms);
}


}


function makeSoundAttack(time, playbackRate)
{
var midiValue = scaleArray[note];
var freqValue = midiToFreq(midiValue);

if (note == 0)
{
// if (expOrNot == 0)
// {
// envelope.setExp(true);
// expOrNot = 1;
// }
// else
// {
// envelope.setExp(false);
// expOrNot = 0;
// }
}

osc.freq(freqValue * 2, 0, time);
// envelope.play(osc, time);
envelope.triggerAttack(osc, time);
//envelope.triggerRelease(osc);
note = (note + 1) % scaleArray.length;
setTimeout(redrawWaveform, time * 1000.0);

}

function makeSoundRelease(time, playbackRate)
{
envelope.triggerRelease(osc, time);
}

function redrawWaveform()
{
background(20);
startPoint = 0;
endPoint = (width / numWaveforms);
}
24 changes: 0 additions & 24 deletions examples/envSignalMath/sketch.js

This file was deleted.

Loading

0 comments on commit 0f8d36f

Please sign in to comment.