diff --git a/.DS_Store b/.DS_Store
index d3eb8d9..0e9fb13 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..3345269
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Chris Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/index.html b/index.html
index 315837f..e3ae86c 100644
--- a/index.html
+++ b/index.html
@@ -59,7 +59,7 @@
-
+
@@ -127,8 +127,8 @@
Flanger depth:
Flanger feedback:
-
An octave-doubling effect, using sample-accurate delay ramping.
-
+
A pitch-shifting effect, using sample-accurate delay ramping. Defaults to one octave down.
+ Pitch-shift:
A delay with a basic chorus effect.
Delay time:
diff --git a/js/effects.js b/js/effects.js
index 2fdf785..3328bd7 100644
--- a/js/effects.js
+++ b/js/effects.js
@@ -265,8 +265,8 @@ function changeEffect(effect) {
case 9: // Stereo Flange
currentEffectNode = createStereoFlange();
break;
- case 10: // Octave doubling
- currentEffectNode = createDoubler();
+ case 10: // Pitch shifting
+ currentEffectNode = createPitchShifter();
break;
case 11: // Mod Delay
currentEffectNode = createModDelay();
@@ -295,7 +295,7 @@ function changeEffect(effect) {
var tempWetGain = wetGain;
wetGain = pingPong.input;
wetGain = createAutowah();
- currentEffectNode = createDoubler();
+ currentEffectNode = createPitchShifter();
wetGain = tempWetGain;
break;
case 18: // Distorted Wah Chorus
@@ -341,7 +341,11 @@ function createTelephonizer() {
}
function createDelay() {
- var delayNode = audioContext.createDelay();
+ var delayNode = null;
+ if (window.location.search.substring(1) == "webkit")
+ delayNode = audioContext.createDelayNode();
+ else
+ delayNode = audioContext.createDelay();
delayNode.delayTime.value = parseFloat( document.getElementById("dtime").value );
dtime = delayNode;
@@ -680,7 +684,7 @@ function createStereoFlange() {
return inputNode;
}
-function createDoubler() {
+function createPitchShifter() {
effect = new Jungle( audioContext );
effect.output.connect( wetGain );
return effect.input;
diff --git a/js/jungle.js b/js/jungle.js
index 9daee4a..4119442 100644
--- a/js/jungle.js
+++ b/js/jungle.js
@@ -65,7 +65,7 @@ function createFadeBuffer(context, activeTime, fadeTime) {
return buffer;
}
-function createDelayTimeBuffer(context, activeTime, fadeTime) {
+function createDelayTimeBuffer(context, activeTime, fadeTime, shiftUp) {
var length1 = activeTime * context.sampleRate;
var length2 = (activeTime - 2*fadeTime) * context.sampleRate;
var length = length1 + length2;
@@ -76,10 +76,12 @@ function createDelayTimeBuffer(context, activeTime, fadeTime) {
// 1st part of cycle
for (var i = 0; i < length1; ++i) {
- // This line does octave-down transpose
- p[i] = i / length1;
- // This line does octave-up transpose
-// p[i] = (length1-i)/length;
+ if (shiftUp)
+ // This line does shift-up transpose
+ p[i] = (length1-i)/length;
+ else
+ // This line does shift-down transpose
+ p[i] = i / length1;
}
// 2nd part
@@ -105,20 +107,42 @@ function Jungle(context) {
// Delay modulation.
var mod1 = context.createBufferSource();
var mod2 = context.createBufferSource();
- var delayTimeBuffer = createDelayTimeBuffer(context, bufferTime, fadeTime);
- mod1.buffer = delayTimeBuffer;
- mod2.buffer = delayTimeBuffer;
+ var mod3 = context.createBufferSource();
+ var mod4 = context.createBufferSource();
+ this.shiftDownBuffer = createDelayTimeBuffer(context, bufferTime, fadeTime, false);
+ this.shiftUpBuffer = createDelayTimeBuffer(context, bufferTime, fadeTime, true);
+ mod1.buffer = this.shiftDownBuffer;
+ mod2.buffer = this.shiftDownBuffer;
+ mod3.buffer = this.shiftUpBuffer;
+ mod4.buffer = this.shiftUpBuffer;
mod1.loop = true;
mod2.loop = true;
-
+ mod3.loop = true;
+ mod4.loop = true;
+
+ // for switching between oct-up and oct-down
+ var mod1Gain = context.createGainNode();
+ var mod2Gain = context.createGainNode();
+ var mod3Gain = context.createGainNode();
+ mod3Gain.gain.value = 0;
+ var mod4Gain = context.createGainNode();
+ mod4Gain.gain.value = 0;
+
+ mod1.connect(mod1Gain);
+ mod2.connect(mod2Gain);
+ mod3.connect(mod3Gain);
+ mod4.connect(mod4Gain);
+
// Delay amount for changing pitch.
var modGain1 = context.createGainNode();
var modGain2 = context.createGainNode();
var delay1 = context.createDelayNode();
var delay2 = context.createDelayNode();
- mod1.connect(modGain1);
- mod2.connect(modGain2);
+ mod1Gain.connect(modGain1);
+ mod2Gain.connect(modGain2);
+ mod3Gain.connect(modGain1);
+ mod4Gain.connect(modGain2);
modGain1.connect(delay1.delayTime);
modGain2.connect(delay2.delayTime);
@@ -152,11 +176,17 @@ function Jungle(context) {
var t2 = t + bufferTime - fadeTime;
mod1.start(t);
mod2.start(t2);
+ mod3.start(t);
+ mod4.start(t2);
fade1.start(t);
fade2.start(t2);
this.mod1 = mod1;
this.mod2 = mod2;
+ this.mod1Gain = mod1Gain;
+ this.mod2Gain = mod2Gain;
+ this.mod3Gain = mod3Gain;
+ this.mod4Gain = mod4Gain;
this.modGain1 = modGain1;
this.modGain2 = modGain2;
this.fade1 = fade1;
@@ -173,3 +203,21 @@ Jungle.prototype.setDelay = function(delayTime) {
this.modGain1.gain.setTargetValueAtTime(0.5*delayTime, 0, 0.010);
this.modGain2.gain.setTargetValueAtTime(0.5*delayTime, 0, 0.010);
}
+
+var previousPitch = -1;
+
+Jungle.prototype.setPitchOffset = function(mult) {
+ if (mult>0) { // pitch up
+ this.mod1Gain.gain.value = 0;
+ this.mod2Gain.gain.value = 0;
+ this.mod3Gain.gain.value = 1;
+ this.mod4Gain.gain.value = 1;
+ } else { // pitch down
+ this.mod1Gain.gain.value = 1;
+ this.mod2Gain.gain.value = 1;
+ this.mod3Gain.gain.value = 0;
+ this.mod4Gain.gain.value = 0;
+ }
+ this.setDelay(delayTime*Math.abs(mult));
+ previousPitch = mult;
+}