Build a Tone.js Advanced Music Generator Web App in Browser Using HTML5 & Javascript Full Project For Beginners

 

 

 

index.html

 

 

<link href="https://fonts.googleapis.com/css?family=Rationale" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/13.8.10/Tone.min.js"></script>
<div class="wrapper">
  <div class="effects-board">
    <div class="sound-choice-container">
      <label class="sounds-label">Sounds</label>
      <section class="sound-type">
        <div class="sound-selections active" 
             id="Synth" 
             onclick="selectSynthType(id)"> 
          Synth
        </div>
        <div class="sound-selections" 
             id="MonoSynth" 
             onclick="selectSynthType(id)"> 
          MonoSynth
        </div>
        <div class="sound-selections" 
             id="AMSynth" 
             onclick="selectSynthType(id)"> 
          AMSynth
        </div>
        <div class="sound-selections" 
             id="FMSynth" 
             onclick="selectSynthType(id)"> 
          FMSynth
        </div>
        <div class="sound-selections" 
             id="MembraneSynth" 
             onclick="selectSynthType(id)"> 
          MembraneSynth
        </div>
      </section>
    </div>

    <div class="oscillator-choice-container">
      <label class="oscillator-label">Oscillator Type</label>
      <section class="oscillator-type">
        <div class="oscillator-selections active" 
             id="triangle" 
             onclick="changeOscillator(id)"> 
          Triangle
        </div>
        <div class="oscillator-selections" 
             id="sine" 
             onclick="changeOscillator(id)"> 
          Sine
        </div>
        <div class="oscillator-selections" 
             id="square" 
             onclick="changeOscillator(id)"> 
          Square
        </div>
        <div class="oscillator-selections" 
             id="sawtooth" 
             onclick="changeOscillator(id)"> 
          SawTooth
        </div>
      </section>
    </div>

    <div class="sound-wave" id="content">
      <canvas class="canvas" id="canvas"></canvas>
    </div>
    
    <div class="effects-choice-container">
      <label class="effects-label">Effects</label>
      <section class="effect-type">

        <div class="effect-selections" 
             id="Chorus">
          <i class="fas fa-power-off" 
             id="chorus-power" 
             onclick="chorusEffectToggle()"></i> 
          <h4>Chorus</h4>
          <div class="chorus-slider-container">
            <section>
              <input type="range" 
                     min="0" 
                     max="50" 
                     value="0" 
                     step="0.1" 
                     class="input" 
                     id="c-frequency">
              <label>Frequency</label>
            </section>
            <section>
              <input type="range" 
                     min="2" 
                     max="50" 
                     value="2" 
                     step="0.1" 
                     class="input" 
                     id="c-delay-time">
              <label>Delay</label>
            </section>
            <section>
              <input type="range" 
                     min="1" 
                     max="10" 
                     value="1" 
                     step="0.1" 
                     class="input" 
                     id="c-depth">
              <label>Depth</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="Tremelo" > 
          <i class="fas fa-power-off" 
             id="tremolo-power"
             onclick="tremoloEffectToggle()"></i> 
          <h4>Tremelo</h4>
          <div class="tremolo-slider-container">
            <section class="two-sliders">
              <input type="range" 
                     min="0" 
                     max="50" 
                     value="0" 
                     step=".1" 
                     class="input" 
                     id="tremolo-frequency">
              <label>Frequency</label>
            </section>
            <section class="two-sliders">
              <input type="range" 
                     min="1" 
                     max="50" 
                     value="1" 
                     step="0.1" 
                     class="input" 
                     id="tremolo-depth">
              <label>Depth</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="Vibrato"> 
          <i class="fas fa-power-off"
             id="vibrato-power"
             onclick="vibratoEffectToggle()"></i> 
          <h4>Vibrato</h4>
          <div class="vibrato-slider-container">
            <section class="two-sliders">
              <input type="range" 
                     min="0" 
                     max="10" 
                     value="0" 
                     step=".1" 
                     class="input" 
                     id="vibrato-frequency">
              <label>Frequency</label>
            </section>
            <section class="two-sliders">
              <input type="range" 
                     min="1" 
                     max="10" 
                     value="0" 
                     step="0.1" 
                     class="input" 
                     id="vibrato-depth">
              <label>Depth</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="Phaser"> 
          <i class="fas fa-power-off"
             id="phaser-power"
             onclick="phaserEffectToggle()"></i> 
          <h4>Phaser</h4>
          <div class="phaser-slider-container">
            <section>
              <input type="range" 
                     min="0" 
                     max="100" 
                     value="0" 
                     step=".1" 
                     class="input" 
                     id="phaser-frequency">
              <label>Frequency</label>
            </section>
            <section>
              <input type="range" 
                     min="0" 
                     max="4" 
                     value="0" 
                     step="1" 
                     class="input" 
                     id="phaser-octave">
              <label>Octaves</label>
            </section>
            <section>
              <input type="range" 
                     min="0" 
                     max="2000" 
                     value="0" 
                     step="1" 
                     class="input" 
                     id="phaser-baseFrequency">
              <label>Base</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="Reverb"> 
          <i class="fas fa-power-off"
             id="reverb-power"
             onclick="reverbEffectToggle()"></i> 
          <h4>Reverb</h4>
          <div class="reverb-slider-container">
            <section>
              <input type="range" 
                     min="0" 
                     max="0.9" 
                     value="0" 
                     step=".01" 
                     class="input" 
                     id="reverb-room-size">
              <label>Room Size</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="Distortion"> 
          <i class="fas fa-power-off"
             id="distortion-power"
             onclick="distortionEffectToggle()"></i> 
          <h4>Distortion</h4>
          <div class="distortion-slider-container">
            <section>
              <input type="range" 
                     min="0" 
                     max="100" 
                     value="0" 
                     step=".1" 
                     class="input" 
                     id="distortion">
              <label>Distortion</label>
            </section>
          </div>
        </div>

        <div class="effect-selections" 
             id="BitCrusher"> 
          <i class="fas fa-power-off"
             id="bitCrusher-power"
             onclick="bitCrusherEffectToggle()"></i> 
          <h4>BitCrusher</h4>
          <div class="bitCrusher-slider-container">
            <section>
              <input type="range" 
                     min="1" 
                     max="8" 
                     value="1" 
                     step="1"
                     class="input" 
                     id="bitCrusher">
              <label>Bit</label>
            </section>
          </div>
        </div>

      </section>
    </div>
  </div>

  <div class="keyboard-container">
    <svg >
      <g>
        <rect class="white-keys C" x="0" y="0" rx="4" onclick="whiteKeyPress('.C'); determineNote(97)"/>
        <text class="white-key-position" x="27" y="195">a</text>
      </g>
      <g>
        <rect class="white-keys D" x="63" y="0" rx="4" onclick="whiteKeyPress('.D'); determineNote(115)"/>
        <text class="white-key-position" x="92" y="195">s</text>
      </g>
      <g>
        <rect class="white-keys E" x="126" y="0" rx="4" onclick="whiteKeyPress('.E'); determineNote(100)"/>
        <text class="white-key-position" x="153" y="195">d</text>
      </g>
      <g>
        <rect class="white-keys F" x="189" y="0" rx="4" onclick="whiteKeyPress('.F'); determineNote(102)"/>
        <text class="white-key-position" x="218" y="195">f</text>
      </g>
      <g>
        <rect class="white-keys G" x="252" y="0" rx="4" onclick="whiteKeyPress('.G'); determineNote(103)"/>
        <text class="white-key-position" x="280" y="195">g</text>
      </g>
      <g>
        <rect class="white-keys A" x="315" y="0" rx="4" onclick="whiteKeyPress('.A'); determineNote(104)"/>
        <text class="white-key-position" x="342" y="195">h</text>
      </g>
      <g>
        <rect class="white-keys B" x="378" y="0" rx="4" onclick="whiteKeyPress('.B'); determineNote(106)"/>
        <text class="white-key-position" x="407" y="195">j</text>
      </g>
      <g>
        <rect class="white-keys octave-up-C" x="441" y="0" rx="4" onclick="whiteKeyPress('.octave-up-C'); determineNote(107)"/>
        <text class="white-key-position" x="470" y="195">k</text>
      </g>
      <g>
        <rect class="white-keys octave-up-D" x="504" y="0" rx="4" onclick="whiteKeyPress('.octave-up-D'); determineNote(108)"/>
        <text class="white-key-position" x="533" y="195">l</text>
      </g>
      <g>
        <rect class="white-keys octave-up-E" x="567" y="0" rx="4" onclick="whiteKeyPress('.octave-up-E'); determineNote(59)"/>
        <text class="white-key-position" x="595" y="195">;</text>
      </g>
      <g>
        <rect class="white-keys octave-up-F" x="630" y="0" rx="4" onclick="whiteKeyPress('.octave-up-F'); determineNote(39)"/>
        <text class="white-key-position" x="660" y="195">'</text>
      </g>


      <g>
        <rect class="black-keys C-sharp" x="42" y="0" rx="2" onclick="blackKeyPress('.C-sharp'); determineNote(119)"/>
        <text class="black-key-position" x="56" y="100">w</text>
      </g>
      <g>
        <rect class="black-keys D-sharp" x="105" y="0" rx="2" onclick="blackKeyPress('.D-sharp'); determineNote(101)"/>
        <text class="black-key-position" x="122" y="100">e</text>
      </g>
      <g>
        <rect class="black-keys F-sharp" x="231" y="0" rx="2" onclick="blackKeyPress('.F-sharp'); determineNote(116)"/>
        <text class="black-key-position" x="248" y="100">t</text>
      </g>
      <g>
        <rect class="black-keys G-sharp" x="294" y="0" rx="2" onclick="blackKeyPress('.G-sharp'); determineNote(121)"/>
        <text class="black-key-position" x="310" y="100">y</text>
      </g>
      <g>
        <rect class="black-keys A-sharp" x="357" y="0" rx="2" onclick="blackKeyPress('.A-sharp'); determineNote(117)"/>
        <text class="black-key-position" x="374" y="100">u</text>
      </g>
      <g>
        <rect class="black-keys octave-up-C-sharp" x="483" y="0" rx="2" onclick="blackKeyPress('.octave-up-C-sharp'); determineNote(111)"/>
        <text class="black-key-position" x="500" y="100">o</text>
      </g>
      <g>
        <rect class="black-keys octave-up-D-sharp" x="546" y="0" rx="2" onclick="blackKeyPress('.octave-up-D-sharp'); determineNote(112)"/>
        <text class="black-key-position" x="565" y="100">p</text>
      </g>
    </svg>

    <div class="octave-adjustment">
      <button class="change-octave-btn" type="button" onclick="determineNote(122)">- z</button>
      <button class="change-octave-btn" type="button" onclick="determineNote(120)">x +</button>
    </div>
  </div>

</div>

 

See also  Build a PDF Document Generator in Javascript Using PDFMake & Mozilla PDF.js Library in Browser Full Tutorial For Beginners

 

style.css

 

 

body {
  background: #28263b;
  font-family: 'Rationale', sans-serif;
}

.wrapper {
  display: grid;
  grid-template-columns: 1fr;
}

.keyboard-container {
  display: grid;
  grid-template-comlumns: 1fr;
  height: fit-content;
  text-align: center;
  background: #3f2540;
  padding: 15px;
  box-shadow: 0px 7px 11px -3px #18121f;
  border-radius: 5px;
  margin: 0 auto;
}

.effects-board {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  width: 80%;
  border-radius: 5px;
  padding: 10px;
  margin: 0 auto;
}

.sound-choice-container, .oscillator-choice-container, .sound-wave {
  height: auto;
  width: 90%;
  background: #33304a;
  box-shadow: 0px 1px 5px 3px #1f1e1e80;
  border-radius: 5px;
  margin: 0 auto 20px;
  text-align: center;
  padding: 15px;
}

.effects-choice-container {
  height: auto;
  background: #33304a;
  box-shadow: 0px 1px 5px 3px #1f1e1e80;
  border-radius: 5px;
  margin: 0 auto;
  text-align: center;
  padding: 15px;
  grid-column: 1/4;
}

.sounds-label, .effects-label, .oscillator-label {
  color: #c73e61;
  font-size: 22px;
  font-weight: 300;
  margin: 0 auto;
}

.sound-type, .oscillator-type {
  color: white;
  text-align: left;
  display: flex;
  margin-top: 15px;
}

.effect-type {
  color: white;
  font-size: 14px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
}

.sound-selections, .oscillator-selections {
  margin: auto;
  cursor: pointer;
  padding: 8px;
}

.sound-selections:hover, .oscillator-selections:hover {
  color: #ff2975;
}

.canvas {
  width: 100%;
  height:75px;
  fill: none;
}

.effect-selections {
  box-shadow: 0 0 4px 0px #c833ff87;
  border-radius: 5px;
  height: fit-content;
  width: auto;
  text-align: center;
  margin: 5px;
  justify-items: center;
  align-items: center;
  padding: 8px;
  animation: colorShift 5s ease infinite;
  transition: animation 2s;
  display: grid;
  grid-template-rows: 2em 3em 6em;
}

.effect-type div:nth-child(1){
  animation-delay: 0s;
}
.effect-type div:nth-child(2){
  animation-delay: .2s;
}
.effect-type div:nth-child(3){
  animation-delay: .4s;
}
.effect-type div:nth-child(4){
  animation-delay: .6s;
}
.effect-type div:nth-child(5){
  animation-delay: .8s;
}
.effect-type div:nth-child(6){
  animation-delay: 1s;
}
.effect-type div:nth-child(7){
  animation-delay: 1.2s;
}

.fa-power-off {
  font-size: 12px;
  color: #9ca0b1;
}

.fa-power-off:hover {
  /*   color: #ff7297; */
  cursor: pointer;
}

.active{
  color: #ff2975;
}

.chorus-slider-container, .phaser-slider-container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  font-size: 13px;
  color: #ff2975;
  grid-gap: 20px;
}

.tremolo-slider-container, .vibrato-slider-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  font-size: 13px;
  color: #ff2975;
  grid-gap: 25px;
}

.two-sliders {
  display: grid;
  grid-template-columns: 1fr;
  margin: 0 auto;
}

.reverb-slider-container, .distortion-slider-container, .bitCrusher-slider-container {
  display: grid;
  grid-template-columns: min-content;
  font-size: 13px;
  color: #ff2975;
  margin: 0 auto;
}

.input[type="range"] {
  -webkit-appearance: none;
  height: 5px;
  width: 35px;
  border-radius: 5px;
  background: #4d4879;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
  transform: rotate(270deg);
  position: relative;
  bottom: 15px;
}

.input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 25px;
  border-radius: 5px;
  background-image: linear-gradient(to right, #DA22FF 0%, #9733EE 51%, #DA22FF 100%);
  cursor: pointer;
}

.input::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #4CAF50;
  cursor: pointer;
}

.slide-container {
  display: grid;
  grid-template-columns: 1fr;
  text-align: left;
  font-size: 12px;
}

/* PIANO SIDE */

.right {
  color: white;
}

svg {
  height: 200px;
  width: 690px;
  margin-top: 10px;
}

.white-keys {
  fill: #e0d6e4;
  stroke: #e0d6e4;
  width: 60px;
  height: 200px;
}

.white-key-position {
  fill: #c73e61;
  font-size: 18px;
}

.black-key-position {
  fill: #c73e61;
  font-size: 18px;
}

.black-keys {
  fill: #453858;
  stroke: #453858;
  height: 110px;
  width: 40px;
}

.octave-adjustment {
  color: white;
  text-align: left;
  display: flex;
  margin-top: 8px;
}

.change-octave-btn{
  width: 42px;
  background: #c73e61;
  border-radius: 5px;
  border: none;
  color: white;
  font-size: 14px;
  margin-left: 4px;
  padding: 5px;
  text-align: center;
  box-shadow: 0px 2px 6px 1px #2b0c10;
  font-family: 'Rationale', sans-serif;
}


@keyframes colorShift {
  0% {
    box-shadow: 0 0 4px 0px #ff333387;
  }
  20% {
    box-shadow: 0 0 4px 0px #c833ff87;
  }
  40% {
    box-shadow: 0 0 4px 0px #3b33ff87;
  }
  60% {
    box-shadow: 0 0 4px 0px #33f1ff87;
  }
  80% {
    box-shadow: 0 0 4px 0px #ffce3387;
  }
  100% {
    box-shadow: 0 0 4px 0px #ff703387;
  }
}

 

See also  Javascript Exact Age Calculator From Date of Birth Calendar Widget in Browser Full Project For Beginners

 

script.js

 

 

console.clear();
let keyboardPosition = 4,
    synthType = "new Tone.Synth().toMaster()",
    soundSelected = "Synth",
    oscillatorType = "triangle",
    effectsAddedList = [],
    synth = new Tone.Synth().toMaster(),
    chorus = new Tone.Chorus(0,2,1).connect(Tone.Master),
    tremolo = new Tone.Tremolo(0, 1).toMaster().start(),
    vibrato = new Tone.Vibrato(4, 0.5).connect(Tone.Master),
    phaser = new Tone.Phaser(0.5, 3, 350).connect(Tone.Master),
    reverb = new Tone.JCReverb(.2).connect(Tone.Master),
    distortion = new Tone.Distortion(1.5).connect(Tone.Master),
    bitCrusher = new Tone.BitCrusher(4).connect(Tone.Master),
    frequency = synth.frequency.value;

document.onkeypress = (e) => {
  e = e || window.event;
  let charCode = e.keyCode;

  if (charCode) {
    determineNote(charCode);
  }
}

function selectSynthType(sound) {
  if(soundSelected !== sound) {
    document.getElementById(soundSelected).classList.remove("active");
    document.getElementById(sound).classList.add("active");
    soundSelected = sound;
  }
}

function changeOscillator(type) {
  if(oscillatorType !== type) {
    document.getElementById(oscillatorType).classList.remove("active");
    document.getElementById(type).classList.add("active");
    oscillatorType = type;
  }
}

const determineNote = (note) => {
  selectSynthSound();

  switch(note) {
    case 122:
      keyboardPosition--;
      break;
    case 120:
      keyboardPosition++;
      break;
    case 97:
      synth.triggerAttackRelease("C" + keyboardPosition, "8n");
      whiteKeyPress(".C");
      break;
    case 115:
      synth.triggerAttackRelease("D" + keyboardPosition, "8n");
      whiteKeyPress(".D");
      break;
    case 100:
      synth.triggerAttackRelease("E" + keyboardPosition, "8n");
      whiteKeyPress(".E");
      break;
    case 102:
      synth.triggerAttackRelease("F" + keyboardPosition, "8n");
      whiteKeyPress(".F");
      break;
    case 103:
      synth.triggerAttackRelease("G" + keyboardPosition, "8n");
      whiteKeyPress(".G");
      break;
    case 104:
      synth.triggerAttackRelease("A" + keyboardPosition, "8n");
      whiteKeyPress(".A");
      break;
    case 106:
      synth.triggerAttackRelease("B" + keyboardPosition, "8n");
      whiteKeyPress(".B");
      break;
    case 107:
      synth.triggerAttackRelease("C" + (keyboardPosition + 1), "8n");
      whiteKeyPress(".octave-up-C");
      break;
    case 108:
      synth.triggerAttackRelease("D" + (keyboardPosition + 1), "8n");
      whiteKeyPress(".octave-up-D");
      break;
    case 59:
      synth.triggerAttackRelease("E" + (keyboardPosition + 1), "8n");
      whiteKeyPress(".octave-up-E");
      break;
    case 39:
      synth.triggerAttackRelease("F" + (keyboardPosition + 1), "8n");
      whiteKeyPress(".octave-up-F");
      break;
    case 119:
      synth.triggerAttackRelease("C#" + keyboardPosition, "8n");
      blackKeyPress(".C-sharp");
      break;
    case 101:
      synth.triggerAttackRelease("D#" + keyboardPosition, "8n");
      blackKeyPress(".D-sharp");
      break;
    case 116:
      synth.triggerAttackRelease("F#" + keyboardPosition, "8n");
      blackKeyPress(".F-sharp");
      break;
    case 121:
      synth.triggerAttackRelease("G#" + keyboardPosition, "8n");
      blackKeyPress(".G-sharp");
      break;
    case 117:
      synth.triggerAttackRelease("A#" + keyboardPosition, "8n");
      blackKeyPress(".A-sharp");
      break;
    case 111:
      synth.triggerAttackRelease("C#" + (keyboardPosition + 1), "8n");
      blackKeyPress(".octave-up-C-sharp");
      break;
    case 112:
      synth.triggerAttackRelease("D#" + (keyboardPosition + 1), "8n");
      blackKeyPress(".octave-up-D-sharp");
      break;
    default:
      console.log("Not a note on the keyboard!!");
  };

  frequency = synth.frequency.value;
  // playSound(frequency, oscillatorType);
}

const whiteKeyPress = (selector) => {
  document.querySelector(selector).style.fill = "#906e9e";
  setTimeout(function(){
    document.querySelector(selector).style.fill = "#e0d6e4";
  }, 200)
}

const blackKeyPress = (selector) => {
  document.querySelector(selector).style.fill = "#745f92";
  setTimeout(function(){
    document.querySelector(selector).style.fill = "#453858";
  }, 200)
}

const selectSynthSound = () => {
  let effects = effectsAddedList.toString();

  switch(soundSelected) {
    case "Synth":
      synthType =  "new Tone.Synth().chain(" + effects + ").toMaster()";
      synth = eval(synthType);
      break;
    case "MonoSynth":
      synthType =  "new Tone.MonoSynth().chain(" + effects + ").toMaster()";
      synth = eval(synthType);
      break;
    case "AMSynth":
      synthType =  "new Tone.AMSynth().chain(" + effects + ").toMaster()";
      synth = eval(synthType);
      break;
    case "FMSynth":
      synthType =  "new Tone.FMSynth().chain(" + effects + ").toMaster()";
      synth = eval(synthType);
      break;
    case "MembraneSynth":
      synthType =  "new Tone.MembraneSynth().chain(" + effects + ").toMaster()";
      synth = eval(synthType);
      break;
    default:
      synth = new Tone.Synth().toMaster();
  }
  synth.oscillator.type = oscillatorType;
}

// ------------CHORUS EFFECTS

let chorusPower = document.getElementById("chorus-power"),
    chorusFreqSlider = document.getElementById("c-frequency"),
    chorusDelaySlider = document.getElementById("c-delay-time"),
    chorusDepthSlider = document.getElementById("c-depth");

function chorusEffectToggle() { 
  addRemoveEffects("chorus");
  chorusPower.style.color = effectsAddedList.includes("chorus") ? "#bd3578" : "#9ca0b1";
}

chorusFreqSlider.oninput = () => {
  chorus.frequency.value = chorusFreqSlider.value;
}

chorusDelaySlider.oninput = () => {
  chorus.delayTime = chorusDelaySlider.value;
}

chorusDepthSlider.oninput = () => {
  chorus.depth = chorusDepthSlider.value;
}

// ------------TREMOLO EFFECTS

let tremoloPower = document.getElementById("tremolo-power"),
    tremoloFreqSlider = document.getElementById("tremolo-frequency"),
    tremoloDepthSlider = document.getElementById("tremolo-depth");

function tremoloEffectToggle() { 
  addRemoveEffects("tremolo");
  tremoloPower.style.color = effectsAddedList.includes("tremolo") ? "#bd3578" : "#9ca0b1";
}

tremoloFreqSlider.oninput = () => {
  tremolo.frequency.value = tremoloFreqSlider.value;
}

tremoloDepthSlider.oninput = () => {
  tremolo.depth.input.value = tremoloDepthSlider.value;
}

// ------------VIBRATO EFFECTS

let vibratoPower = document.getElementById("vibrato-power"),
    vibratoFreqSlider = document.getElementById("vibrato-frequency"),
    vibratoDepthSlider = document.getElementById("vibrato-depth");

function vibratoEffectToggle() {
  addRemoveEffects("vibrato");
  vibratoPower.style.color = effectsAddedList.includes("vibrato") ? "#bd3578" : "#9ca0b1";
}

vibratoFreqSlider.oninput = () => {
  vibrato.frequency.value = vibratoFreqSlider.value;
}

vibratoDepthSlider.oninput = () => {
  vibrato.depth.input.value = vibratoDepthSlider.value;
}

// ------------PHASER EFFECTS
let phaserPower = document.getElementById("phaser-power"),
    phaserFreqSlider = document.getElementById("phaser-frequency"),
    phaserOctaveSlider = document.getElementById("phaser-octave"),
    phaserBaseFreqSlider = document.getElementById("phaser-baseFrequency");

function phaserEffectToggle() {
  addRemoveEffects("phaser");
  phaserPower.style.color = effectsAddedList.includes("phaser") ? "#bd3578" : "#9ca0b1";
}

phaserFreqSlider.oninput = () => {
  phaser.frequency.value = phaserFreqSlider.value;
}

phaserOctaveSlider.oninput = () => {
  phaser.octave = phaserOctaveSlider.value;
}

phaserBaseFreqSlider.oninput = () => {
  phaser.baseFrequency = phaserBaseFreqSlider.value;
}

// ------------REVERB EFFECTS

let reverbPower = document.getElementById("reverb-power"),
    reverbRoomSizeSlider = document.getElementById("reverb-room-size");

function reverbEffectToggle() {
  addRemoveEffects("reverb");
  reverbPower.style.color = effectsAddedList.includes("reverb") ? "#bd3578" : "#9ca0b1";
}

reverbRoomSizeSlider.oninput = () => {
  reverb.roomSize.input.value = reverbRoomSizeSlider.value;
}

// ------------DISTORTION EFFECTS

let distortionPower = document.getElementById("distortion-power"),
    distortionEffectSlider = document.getElementById("distortion");

function distortionEffectToggle() {
  addRemoveEffects("distortion");
  distortionPower.style.color = effectsAddedList.includes("distortion") ? "#bd3578" : "#9ca0b1";
}

distortionEffectSlider.oninput = () => {
  distortion.distortion = distortionEffectSlider.value;
}

// ------------BITCRUSHER EFFECTS

let bitCrusherPower = document.getElementById("bitCrusher-power"),
    bitCrusherBitSlider = document.getElementById("bitCrusher");

function bitCrusherEffectToggle() {
  addRemoveEffects("bitCrusher");
  bitCrusherPower.style.color = effectsAddedList.includes("bitCrusher") ? "#bd3578" : "#9ca0b1";
}

bitCrusherBitSlider.oninput = () => {
  bitCrusher.bits = bitCrusherBitSlider.value;
}

// ---------------------------------------------------

const addRemoveEffects = (effect) => {
  if(effectsAddedList.includes(effect)) {
    let index = effectsAddedList.indexOf(effect)
    effectsAddedList.splice(index, 1);
  } else {
    effectsAddedList.push(effect);
  }
}

// Stole this from https://codepen.io/PavelRodionoff/pen/XwKvVd?&page=1
function showSoundWave() {
  navigator.mediaDevices
    .getUserMedia({ audio: true, video: false })
    .then(function(stream) {

    let audioContext = new (window.AudioContext || window.webkitAudioContext)();
    let gainNode = audioContext.createGain();
    let src = audioContext.createMediaStreamSource(stream);

    src.connect(gainNode);
    gainNode.connect(audioContext.destination);
    gainNode.gain.setTargetAtTime(0, audioContext.currentTime, 0);

    let analyser = audioContext.createAnalyser();

    let canvas = document.getElementById("canvas");
    let ctx = canvas.getContext("2d");

    src.connect(analyser);
    gainNode.connect(analyser);

    let bufferLength = analyser.frequencyBinCount;
    let dataArray = new Float32Array(bufferLength);
    let WIDTH = canvas.width;
    let HEIGHT = canvas.height;

    function draw() {
      drawVisual = requestAnimationFrame(draw);
      analyser.getFloatTimeDomainData(dataArray);

      ctx.fillStyle = '#33304a';
      ctx.fillRect(0, 0, WIDTH, HEIGHT);
      ctx.lineWidth = 2;
      ctx.strokeStyle = "rgb(255, 255, 255)";
      ctx.beginPath();

      let sliceWidth = WIDTH * 1.0 / bufferLength;
      let x = 0;

      for (var i = 0; i < bufferLength; i++) {
        let v = dataArray[i] * 50;
        let y = HEIGHT / 2 + v;

        if (i === 0) {
          ctx.moveTo(x, y);
        } else {
          ctx.lineTo(x, y);
        }
        x += sliceWidth;
      }
      ctx.lineTo(canvas.width, canvas.height / 2);
      ctx.stroke();
    }
    draw();
  })
    .catch(function(err) {
    console.log("error:");
    console.log(err);
  });
}

showSoundWave();

Leave a Reply