Advertisement
Guest User

Untitled

a guest
May 21st, 2019
2,007
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*  ################################## TUNER ########################################  */
  2.  
  3. /* ES6 web audio class following the API standard
  4. * Author : Jordan Sintes
  5. * Comment: Based on the the pitch detecotr here: https://webaudiodemos.appspot.com/pitchdetect/index.html
  6. */
  7. window.TunerMachine = class TunerMachine extends WebAudioPluginCompositeNode {
  8.     constructor(ctx, URL, options) {
  9.         super(ctx, URL, options)
  10.         /*    ################     API PROPERTIES    ###############   */
  11.  
  12.         this.options = options;
  13.         this.state;
  14.         this.params = { "status": "disable" }
  15.         super.setup();
  16.  
  17.         this.analyser;
  18.         this.DEBUGCANVAS = null;
  19.         this.mediaStreamSource = null;
  20.         this.rafID = null,
  21.             this.tracks = null;
  22.         this.buflen = 2048;
  23.         this.buf = new Float32Array(this.buflen);
  24.         this.noteStrings = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
  25.         this.MIN_SAMPLES = 0;
  26.         this.GOOD_ENOUGH_CORRELATION = 0.9;
  27.  
  28.         //for function about mode choice
  29.         this.toneLevel = 0;
  30.         this.frequencyString = [0, 0, 0, 0, 0, 0]
  31.         this.valueSaved = 0;
  32.         this.wA = null;
  33.         this.hA = null;
  34.         this.hRect = null;
  35.         this.Angle = null
  36.     }
  37.  
  38.     /*    ################     API METHODS    ###############   */
  39.     getPatch(index) {
  40.         console.warn("this module does not implements patches use getState / setState to get an array of current params values ");
  41.     }
  42.     setPatch(data, index) {
  43.         console.warn("this module does not implements patches use getState / setState to get an array of current params values ");
  44.     }
  45.  
  46.     setParam(key, value) {
  47.         console.log(key, value);
  48.         try {
  49.             this[key] = (value);
  50.         } catch (error) {
  51.             console.warn(key, error);
  52.             console.warn("this plugin does not implement this param")
  53.         }
  54.     }
  55.  
  56.     createNodes() {
  57.         this.dryGainNode = this.context.createGain();
  58.         this.analyser = this.context.createAnalyser();
  59.  
  60.         this.dryGainNode.gain.value = 3;
  61.         this.analyser.fftSize = 2048;
  62.         this.bufferLength = this.analyser.frequencyBinCount;
  63.         this.dataArray = new Uint8Array(this.bufferLength);
  64.     }
  65.  
  66.     connectNodes() {
  67.         this._input.connect(this.dryGainNode);
  68.         this.dryGainNode.connect(this.analyser);
  69.         this.analyser.connect(this._output);
  70.     }
  71.  
  72.     /*  #########  Personnal code for Tuner  #########   */
  73.     set status(_sig) {
  74.         if (_sig === "enable") {
  75.             this.params.status = "enable";
  76.             this.updatePitch();
  77.             console.log("Tuner is on");
  78.         }
  79.  
  80.         else if (_sig === "disable") {
  81.             if (!window.cancelAnimationFrame)
  82.                 window.cancelAnimationFrame = window.webkitCancelAnimationFrame;
  83.             window.cancelAnimationFrame(this.rafID);
  84.  
  85.             this.params.status = "disable"
  86.             console.log("Tuner is off");
  87.         }
  88.     }
  89.  
  90.     noteFromPitch(frequency) {
  91.         var noteNum = 12 * (Math.log(frequency / 440) / Math.log(2));
  92.         return Math.round(noteNum) + 69;
  93.     }
  94.  
  95.     centsOffFromPitch(frequency, note) {
  96.         return Math.floor(1200 * Math.log(frequency / this.frequencyFromNoteNumber(note)) / Math.log(2));
  97.     }
  98.  
  99.     frequencyFromNoteNumber(note) {
  100.         return 440 * Math.pow(2, (note - 69) / 12);
  101.     }
  102.  
  103.     getAverageFrequency(arrayFrequencies)
  104.             {
  105.                 let values = 0;
  106.                 let average;
  107.  
  108.                 let length = arrayFrequencies.length;
  109.  
  110.                 for (let i = 0; i < length; i++) {
  111.                     values += arrayFrequencies[i];
  112.                 }
  113.  
  114.                 average = values / length;
  115.                 return average;
  116.             }
  117.  
  118.     updatePitch(time) {
  119.         this.analyser.getByteFrequencyData(this.dataArray);
  120.  
  121.             const averageFrequency = this.getAverageFrequency(this.dataArray);
  122.             var coordinateY = (averageFrequency);
  123.  
  124.             if(coordinateY < 0)
  125.                 coordinateY = 0;
  126.         this.hRect=coordinateY;
  127.         var canvasElem = this.gui._root.getElementById("output");
  128.         var detectorElem = this.gui._root.getElementById("detector");
  129.         var DEBUGCANVAS = this.gui._root.getElementById("waveform");
  130.         if (DEBUGCANVAS) {
  131.             var waveCanvas = DEBUGCANVAS.getContext("2d");
  132.             waveCanvas.strokeStyle = "black";
  133.             waveCanvas.lineWidth = 1;
  134.         }
  135.        
  136.         this.wA = this.gui._root.getElementById("output").offsetWidth;
  137.         this.hA = this.gui._root.getElementById("output").offsetHeight;
  138.  
  139.         //canvas aiguille
  140.         //le canvas de l'aiguille a été envelé pour le mettre dans le canvas principale
  141.  
  142.         let outputA = canvasElem.getContext('2d');
  143.        
  144.  
  145.         //canvas diode
  146.         let canvasdio = this.gui._root.getElementById("diode");
  147.         let outputD = canvasdio.getContext('2d');
  148.        
  149.  
  150.         //Tuner canvas
  151.         var pitchElem = this.gui._root.getElementById("pitch");
  152.         var noteElem = this.gui._root.getElementById("note");
  153.         var detuneElem = this.gui._root.getElementById("detune");
  154.         var detuneAmount = this.gui._root.getElementById("detune_amt");
  155.         this.analyser.getFloatTimeDomainData(this.buf);
  156.         var ac = this.autoCorrelate(this.buf, this.context.sampleRate);
  157.  
  158.         var newAngle = this.angle_frequence(ac); //angle modifié en fonction de la freq
  159.  
  160.         outputA.clearRect(0, 0, this.wA, this.hA); //pour effacer aiguille quand elle bouge(animation)
  161.  
  162.         this.background(outputA);
  163.         this.inittrait(outputA, newAngle);
  164.  
  165.         outputD = canvasdio.getContext('2d');
  166.         this.initdiiode(outputD, ac);
  167.  
  168.         this.drawGain(outputA);
  169.  
  170.  
  171.        /* if (this.gui._root.getElementById("waveform")) {  // This draws the current waveform, useful for debugging
  172.             this.gui._root.waveCanvas.clearRect(0, 0, 512, 256);
  173.             waveCanvas.strokeStyle = "red";
  174.             waveCanvas.beginPath();
  175.             waveCanvas.moveTo(0, 0);
  176.             waveCanvas.lineTo(0, 256);
  177.             waveCanvas.moveTo(128, 0);
  178.             waveCanvas.lineTo(128, 256);
  179.             waveCanvas.moveTo(256, 0);
  180.             waveCanvas.lineTo(256, 256);
  181.             waveCanvas.moveTo(384, 0);
  182.             waveCanvas.lineTo(384, 256);
  183.             waveCanvas.moveTo(512, 0);
  184.             waveCanvas.lineTo(512, 256);
  185.             waveCanvas.stroke();
  186.             waveCanvas.strokeStyle = "black";
  187.             waveCanvas.beginPath();
  188.             waveCanvas.moveTo(0, buf[0]);
  189.             for (var i = 1; i < 512; i++) {
  190.                 waveCanvas.lineTo(i, 128 + (buf[i] * 128));
  191.             }
  192.             waveCanvas.stroke();
  193.         }*/
  194.  
  195.         if (ac == -1) {
  196.             detectorElem.className = "vague";
  197.             pitchElem.innerText = "--";
  198.             noteElem.innerText = "-";
  199.             detuneElem.className = "";
  200.             detuneAmount.innerText = "--";
  201.         } else {
  202.             detectorElem.className = "confident";
  203.             var pitch = ac;
  204.             pitchElem.innerText = Math.round(pitch);
  205.             var note = this.noteFromPitch(pitch);
  206.             noteElem.innerHTML = this.noteStrings[note % 12];
  207.             var detune = this.centsOffFromPitch(pitch, note);
  208.             if (detune == 0) {
  209.                 detuneElem.className = "";
  210.                 detuneAmount.innerHTML = "--";
  211.             } else {
  212.                 if (detune < 0)
  213.                     detuneElem.className = "flat";
  214.                 else
  215.                     detuneElem.className = "sharp";
  216.                 detuneAmount.innerHTML = Math.abs(detune);
  217.             }
  218.             this.Modifdio(outputD, detune, detuneElem.className);
  219.         }
  220.        /* let freq = Math.round(ac);
  221.         if (this.valueSaved != freq) {
  222.             this.indicateTone(this.toneLevel);
  223.         }*/
  224.  
  225.  
  226.         if (!window.requestAnimationFrame)
  227.             window.requestAnimationFrame = window.webkitRequestAnimationFrame;
  228.         this.rafID = window.requestAnimationFrame(this.updatePitch.bind(this));
  229.     }
  230.  
  231.     background(ctx) {
  232.         ctx.save();
  233.         /*Modification afin de mettre une partie de l'arc de cercle à sa place*/
  234.         ctx.translate(this.wA / 2, this.hA - 10);
  235.  
  236.         ctx.strokeStyle = "rgb(255, 0, 0)";
  237.         ctx.lineWidth = 2;
  238.         ctx.beginPath();
  239.         ctx.moveTo(0, -this.hA / 3 - 15);
  240.         ctx.lineTo(0, -this.hA / 3 - 30);
  241.         ctx.stroke();
  242.  
  243.         var mesure = -50;
  244.         var cnorm;
  245.         this.Angle = 0;
  246.         while (mesure < 40) {
  247.  
  248.             //  ctx.rotate(Angle);
  249.             cnorm = this.map(mesure, -50, 0, 1, 0.1);
  250.             cnorm = this.mapLinearToLog(cnorm, -0.1, -1, 0.1, 1);
  251.             this.Angle = this.map(cnorm, -1, -0.1, -Math.PI / 4, 0); //angle
  252.  
  253.             ctx.rotate(this.Angle);
  254.  
  255.             // Graduation qui suit les cents de façon logarithmique
  256.             ctx.strokeStyle = "rgb(255, 0, 0)";
  257.             ctx.lineWidth = 2;
  258.             ctx.beginPath();
  259.             ctx.moveTo(0, -this.hA / 3 - 15);
  260.             ctx.lineTo(0, -this.hA / 3 - 30);
  261.             ctx.stroke();
  262.  
  263.             mesure += 10;
  264.         }
  265.         ctx.restore();
  266.  
  267.  
  268.         ctx.save();
  269.         /*Modification afin de mettre une l'autre de l'arc de cercle à sa place*/
  270.         ctx.translate(this.wA / 2, this.hA - 10);
  271.  
  272.         var mesure2 = -50;
  273.         var cnorm2;
  274.         var Angle2 = 0;
  275.         while (mesure2 < 40) {
  276.  
  277.             //  ctx.rotate(Angle);
  278.             cnorm2 = this.map(mesure2, -50, 0, 1, 0.1);
  279.             cnorm2 = this.mapLinearToLog(cnorm2, -0.1, -1, 0.1, 1);
  280.             Angle2 = this.map(cnorm2, -1, -0.1, Math.PI / 4, 0); //angle
  281.  
  282.             ctx.rotate(Angle2);
  283.  
  284.             // Graduation qui suit les cents de façon logarithmique
  285.             ctx.strokeStyle = "rgb(255, 0, 0)";
  286.             ctx.lineWidth = 2;
  287.             ctx.beginPath();
  288.             ctx.moveTo(0, -this.hA / 3 - 15);
  289.             ctx.lineTo(0, -this.hA / 3 - 30);
  290.             ctx.stroke();
  291.  
  292.             mesure2 += 10;
  293.         }
  294.         ctx.restore();
  295.     }
  296.  
  297.     // maps a value from [istart, istop] into [ostart, ostop]
  298.     map(value, istart, istop, ostart, ostop) {
  299.         return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
  300.     }
  301.  
  302.     // passage echelle linéaire -> echelle logarithmique
  303.     mapLinearToLog(x, istart, istop, ostart, ostop) {
  304.         // sliderValue is in [0, 10] range, adjust to [0, 1500] range  
  305.         var value = x;
  306.         var minp = istart;
  307.         var maxp = istop;
  308.  
  309.         // The result should be between 10 an 1500
  310.         var minv = Math.log(ostart);
  311.         var maxv = Math.log(ostop);
  312.  
  313.         // calculate adjustment factor
  314.         var scale = (maxv - minv) / (maxp - minp);
  315.  
  316.         value = Math.exp(minv + scale * (value - minp));
  317.         // end of logarithmic adjustment
  318.         return value;
  319.     }
  320.  
  321.     /**************** AIGUILLE Canvas ****************/
  322.     inittrait(ctx, A) // A l'angle défini par angle_fréquence(f)
  323.     {
  324.         ctx.save();
  325.         /*Modification afin de mettre l'aiguille a sa place*/
  326.         ctx.translate(this.wA / 2, this.hA - 10);
  327.         ctx.rotate(A);
  328.  
  329.         ctx.strokeStyle = "rgb(70, 70, 70)";
  330.         ctx.lineWidth = 2;
  331.         ctx.beginPath();
  332.         ctx.moveTo(0, 0);
  333.         /*Modification de la taille de l'aiguille*/
  334.         ctx.lineTo(0, -60);
  335.         ctx.stroke();
  336.         ctx.restore();
  337.     }
  338.  
  339.     initdiiode(ctx) // ctx context du canvas des diiode
  340.     {
  341.         ctx.fillStyle = "rgb(70, 70, 70)";
  342.         ctx.beginPath();
  343.  
  344.         ctx.arc(20, 20, 10, 0, 2 * Math.PI);
  345.         ctx.arc(90, 20, 10, 0, 2 * Math.PI);
  346.         ctx.arc(160, 20, 10, 0, 2 * Math.PI);
  347.         ctx.fill();
  348.         ctx.restore();
  349.     }
  350.  
  351.     /**************** GAIN Canvas ****************/
  352.     // Fonction qui initialisera le rectangle qui representera le volume du son
  353.     initGain(ctx) {
  354.         ctx.save();
  355.         ctx.fillStyle = "rgb(70, 70, 70)";
  356.         ctx.fillRect(this.wA - 15, 0, 10, this.hA);
  357.         this.hRect = this.hA;
  358.         ctx.restore();
  359.     }
  360.     // Fonction qui dessine le rectangle representant le volume du sons
  361.     drawGain(ctx) {
  362.         ctx.save();
  363.         ctx.clearRect(this.wA - 15, 0, 10, this.hA);
  364.         ctx.fillStyle = "rgb(70, 70, 70)";
  365.         ctx.fillRect(this.wA - 15, 0, 10, this.hA);
  366.         ctx.fillStyle = "rgb(0, 179, 0)";
  367.         ctx.fillRect(this.wA - 15, this.hA, 10, -this.hRect);
  368.         ctx.restore();
  369.     }
  370.  
  371.     angle_frequence(f) { // variation de l'angle en fonction de la fréquence émise
  372.         var note = this.noteFromPitch(f);
  373.         var cents = this.centsOffFromPitch(f, note);
  374.         var ref_freq = this.frequencyFromNoteNumber(note);
  375.         var cnorm;
  376.         if (f < ref_freq) {
  377.             cnorm = this.map(cents, -50, 0, 1, 0.1);
  378.             cnorm = this.mapLinearToLog(cnorm, 0.1, 1, 0.1, 1);
  379.             this.Angle = this.map(cnorm, 1, 0.1, -Math.PI / 2 + 0.2, 0); //angle
  380.             return this.Angle;
  381.         } else {
  382.             cnorm = this.map(cents, 0, 50, 0.1, 1);
  383.             cnorm = this.mapLinearToLog(cnorm, 0.1, 1, 0.1, 1);
  384.             this.Angle = this.map(cnorm, 0.1, 1, 0, Math.PI / 2 - 0.2); //angle
  385.             return this.Angle;
  386.         }
  387.     }
  388.  
  389.     Modifdio(ctx,ecart,side) //ecart = l'ecart entre la frequence du son et celle de la note reconnu
  390.                                   //et side contient une chaine de caractère qui va nous servir à savoir de quel côté allumé la diiode
  391.                                   //flat: à gauche  sharp:à gauhche  "": au centre  
  392. {
  393.     ctx.save();
  394.     ctx.clearRect(0,0,300,200);
  395.     if(side=="flat"&&ecart<=-5)
  396.     {
  397.         if(ecart>=-15)
  398.         {
  399.             ctx.fillStyle="rgb(0, 150, 0)";
  400.         }
  401.         else if(ecart>=-35)
  402.         {
  403.             ctx.fillStyle="rgb(255, 102, 0)";
  404.         }
  405.         else if(ecart<=-35)
  406.         {
  407.             ctx.fillStyle="rgb(200,0,0)";
  408.         }
  409.        
  410.     }
  411.     else
  412.     {
  413.         ctx.fillStyle="rgb(70, 70, 70)";
  414.     }
  415.     ctx.beginPath();
  416.    
  417.     ctx.arc(20, 20, 10, 0, 2 * Math.PI);
  418.     ctx.fill();
  419.    
  420.     if(side=="sharp"&&ecart>=5)
  421.     {
  422.         if(ecart<=15)
  423.         {
  424.             ctx.fillStyle="rgb(0, 150, 0)";
  425.         }
  426.         else if(ecart<=35)
  427.         {
  428.             ctx.fillStyle="rgb(255, 102, 0)";
  429.         }
  430.         else if(ecart>=35)
  431.         {
  432.             ctx.fillStyle="rgb(200,0,0)";
  433.         }
  434.     }
  435.     else
  436.     {
  437.         ctx.fillStyle="rgb(70, 70, 70)";
  438.     }
  439.     ctx.beginPath();
  440.     ctx.arc(160, 20, 10, 0, 2 * Math.PI);
  441.     ctx.fill();
  442.    
  443.     if(ecart <=5 && ecart >=-5)
  444.     {  
  445.         ctx.fillStyle="rgb(0, 230, 0)"
  446.     }
  447.     else
  448.     {
  449.         ctx.fillStyle="rgb(70, 70, 70)";
  450.     }
  451.     ctx.beginPath();
  452.     ctx.arc(90, 20, 10, 0, 2 * Math.PI);
  453.     ctx.fill();
  454.     ctx.restore();
  455. }
  456.  
  457.    
  458.  
  459.     /*autoCorrelate(buf, sampleRate) {
  460.          var MIN_SAMPLES = 0;  // will be initialized when AudioContext is created.
  461.          var GOOD_ENOUGH_CORRELATION = 0.9; // this is the "bar" for how close a correlation needs to be
  462.          var SIZE = buf.length;
  463.          var MAX_SAMPLES = Math.floor(SIZE / 2);
  464.          var best_offset = -1;
  465.          var best_correlation = 0;
  466.          var rms = 0;
  467.          var foundGoodCorrelation = false;
  468.          var correlations = new Array(MAX_SAMPLES);
  469.  
  470.          for (var i = 0; i < SIZE; i++) {
  471.              var val = buf[i];
  472.              rms += val * val;
  473.          }
  474.          rms = Math.sqrt(rms / SIZE);
  475.          if (rms < 0.01) // not enough signal
  476.              return -1;
  477.  
  478.          var lastCorrelation = 1;
  479.          for (var offset = MIN_SAMPLES; offset < MAX_SAMPLES; offset++) {
  480.              var correlation = 0;
  481.  
  482.              for (var i = 0; i < MAX_SAMPLES; i++) {
  483.                  correlation += Math.abs((buf[i]) - (buf[i + offset]));
  484.              }
  485.              correlation = 1 - (correlation / MAX_SAMPLES);
  486.              correlations[offset] = correlation; // store it, for the tweaking we need to do below.
  487.              if ((correlation > GOOD_ENOUGH_CORRELATION) && (correlation > lastCorrelation)) {
  488.                  foundGoodCorrelation = true;
  489.                  if (correlation > best_correlation) {
  490.                      best_correlation = correlation;
  491.                      best_offset = offset;
  492.                  }
  493.              } else if (foundGoodCorrelation) {
  494.                  // short-circuit - we found a good correlation, then a bad one, so we'd just be seeing copies from here.
  495.                  // Now we need to tweak the offset - by interpolating between the values to the left and right of the
  496.                  // best offset, and shifting it a bit.  This is complex, and HACKY in this code (happy to take PRs!) -
  497.                  // we need to do a curve fit on correlations[] around best_offset in order to better determine precise
  498.                  // (anti-aliased) offset.
  499.  
  500.                  // we know best_offset >=1,
  501.                  // since foundGoodCorrelation cannot go to true until the second pass (offset=1), and
  502.                  // we can't drop into this clause until the following pass (else if).
  503.                  var shift = (correlations[best_offset + 1] - correlations[best_offset - 1]) / correlations[best_offset];
  504.                  return sampleRate / (best_offset + (8 * shift));
  505.              }
  506.              lastCorrelation = correlation;
  507.          }
  508.          if (best_correlation > 0.01) {
  509.              // console.log("f = " + sampleRate/best_offset + "Hz (rms: " + rms + " confidence: " + best_correlation + ")")
  510.              return sampleRate / best_offset;
  511.          }
  512.          return -1;
  513.          // var best_frequency = sampleRate/best_offset;
  514.      }*/
  515.  
  516.     /*
  517.      * Autocorrelation purposed by dalatant, at this link:
  518.      * https://github.com/cwilso/PitchDetect/pull/23/commits/b0d5d28d2803d852dd85d2a1e53c22bcedba4cbf
  519.      */
  520.     autoCorrelate(buf, sampleRate) {
  521.         // Implements the ACF2+ algorithm
  522.         var SIZE = buf.length;
  523.         var rms = 0;
  524.         for (var i = 0; i < SIZE; i++) {
  525.             var val = buf[i];
  526.             rms += val * val;
  527.         }
  528.         rms = Math.sqrt(rms / SIZE);
  529.         if (rms < 0.01) // not enough signal
  530.             return -1;
  531.         var r1 = 0, r2 = SIZE - 1, thres = 0.2;
  532.         for (var i = 0; i < SIZE / 2; i++)
  533.             if (Math.abs(buf[i]) < thres) { r1 = i; break; }
  534.         for (var i = 1; i < SIZE / 2; i++)
  535.             if (Math.abs(buf[SIZE - i]) < thres) { r2 = SIZE - i; break; }
  536.         buf = buf.slice(r1, r2);
  537.         SIZE = buf.length;
  538.         var c = new Array(SIZE).fill(0);
  539.         for (var i = 0; i < SIZE; i++)
  540.             for (var j = 0; j < SIZE - i; j++)
  541.                 c[i] = c[i] + buf[j] * buf[j + i];
  542.         var d = 0; while (c[d] > c[d + 1]) d++;
  543.         var maxval = -1, maxpos = -1;
  544.         for (var i = d; i < SIZE; i++) {
  545.             if (c[i] > maxval) {
  546.                 maxval = c[i];
  547.                 maxpos = i;
  548.             }
  549.         }
  550.         var T0 = maxpos;
  551.         var x1 = c[T0 - 1], x2 = c[T0], x3 = c[T0 + 1];
  552.         var a = (x1 + x3 - 2 * x2) / 2;
  553.         var b = (x3 - x1) / 2;
  554.         if (a) T0 = T0 - b / (2 * a);
  555.         return sampleRate / T0;
  556.     }
  557.  
  558.    /* increaseSemiTone() {
  559.         if (this.toneLevel < 2) {
  560.             this.toneLevel++;
  561.             this.indicateTone(this.toneLevel);
  562.         }
  563.         console.log("increase semitone level : toneLevel =" + this.toneLevel)
  564.     }
  565.  
  566.     decreaseSemiTone() {
  567.         if (this.toneLevel > -2) {
  568.             this.toneLevel--;
  569.             this.indicateTone(this.toneLevel);
  570.         }
  571.         console.log("decrease semitone level : toneLevel =" + this.toneLevel);
  572.     }
  573.  
  574.     //Function about indicating the correct note depending of tuning mode
  575.     indicateTone(toneLevel) {
  576.         let freq = this.autoCorrelate(this.buf, this.context.sampleRate);
  577.         toneLevel = this.toneLevel;
  578.         let freqTest = Math.round(freq);
  579.         let intMin = 0;
  580.         let intMax = 0;
  581.         let freqMin = freqTest;
  582.         let freqMax = freqTest;
  583.         var detuneLessMode = this.gui._root.getElementById("lessArrow");
  584.         var detuneMoreMode = this.gui._root.getElementById("moreArrow");
  585.  
  586.  
  587.         switch (toneLevel) {
  588.             //Chord Mode, 0 is the standard tuning
  589.             case -2:
  590.                 this.frequencyString = [73, 98, 131, 175, 220, 294];
  591.                 break;
  592.             case -1:
  593.                 this.frequencyString = [78, 104, 139, 185, 233, 311];
  594.                 break;
  595.             case 0:
  596.                 this.frequencyString = [82, 110, 147, 196, 247, 330];
  597.                 break;
  598.             case 1:
  599.                 this.frequencyString = [87, 117, 156, 208, 262, 349];
  600.                 break;
  601.             case 2:
  602.                 this.frequencyString = [92, 123, 165, 220, 277, 370];
  603.                 break;
  604.         }
  605.  
  606.         /*
  607.          *  The goal here is while the frequency isn't close to one of frequency
  608.          *  present in the table, we must to catch on which interval the frequency is present
  609.          *  and after to indicate if the user must to tune more or less depending of the position
  610.          *  in the interval
  611.          *
  612.  
  613.         //If the frequency catched not corresponding to a frequency in the table and the value between the frequency of the first string and last string
  614.         if (this.frequencyString.indexOf(freqMin) == -1 && freqTest > this.frequencyString[0] && freqTest < this.frequencyString[5]) {
  615.             while (this.frequencyString.indexOf(freqMin) == -1 && freqMin > 0) {
  616.  
  617.                 //We decrease freqMin to find the first value of the interval
  618.                 freqMin--;
  619.                 //Until we find the first value of the interval
  620.                 if (this.frequencyString.indexOf(freqMin) != -1) {
  621.                     intMin = this.frequencyString[this.frequencyString.indexOf(freqMin)];
  622.                 }
  623.  
  624.             }
  625.             //Same test but to find the second value for the interval
  626.             while (this.frequencyString.indexOf(freqMax) == -1) {
  627.                 freqMax++;
  628.                 if (this.frequencyString.indexOf(freqMax) != -1) {
  629.                     intMax = this.frequencyString[this.frequencyString.indexOf(freqMax)];
  630.                 }
  631.             }
  632.  
  633.             //If the frequency catched is not closed of the exact frequency
  634.             if (freqTest > intMin + 2 || freqTest < intMax - 2) {
  635.                 let middle = (intMin + intMax) / 2;
  636.                 //if the frequency catched is above of the middle of the interval or under the frequency of the first string
  637.                 if (freqTest > middle || freqTest < this.frequencyString[0]) {
  638.                     //If it's closed to the max interval
  639.                     if (freqTest > intMax - 2 && freqTest < intMax + 2) {
  640.                         detuneLessMode.innerHTML = "";
  641.                         detuneMoreMode.innerHTML = "";
  642.                     } else {
  643.                         //Otherwise We told to increase the tuning
  644.                         detuneLessMode.innerHTML = "↑";
  645.                         detuneMoreMode.innerHTML = "";
  646.                     }
  647.                 }
  648.                 else if (freqTest < middle || freqTest > this.frequencyString[5]) {
  649.                     //Inversing test
  650.                     if (freqTest > intMin - 2 && freqTest < intMin + 2) {
  651.                         detuneLessMode.innerHTML = "";
  652.                         detuneMoreMode.innerHTML = "";
  653.                     } else {
  654.                         detuneMoreMode.innerHTML = "";
  655.                         detuneLessMode.innerHTML = "↓";
  656.                     }
  657.                 }
  658.             }
  659.         } else {
  660.             if (freqTest < this.frequencyString[0] - 2 && freqTest > 0) {
  661.                 detuneLessMode.innerHTML = "↑";
  662.                 detuneMoreMode.innerHTML = "";
  663.             }
  664.             else if (freqTest > this.frequencyString[5] + 2) {
  665.                 detuneMoreMode.innerHTML = "";
  666.                 detuneLessMode.innerHTML = "↓";
  667.             }
  668.             else {
  669.                 detuneMoreMode.innerHTML = "";
  670.                 detuneLessMode.innerHTML = "";
  671.             }
  672.         }
  673.         this.valueSaved = freqTest;
  674.     }
  675.     */
  676. }
  677.  
  678. //////////////////////////////////////////////////////////////////////////////////////////
  679.  
  680. window.WasabiTunerMachine = class WasabiTunerMachine extends WebAudioPluginFactory {
  681.     constructor(context, baseUrl) { super(context, baseUrl); }
  682. }
  683.  
  684. //////////////////////////////////////////////////////////////////////////////////////////
  685.  
  686. AudioContext.prototype.createWasabiDelayCompositeNode = OfflineAudioContext.prototype.createWasabiDelayCompositeNode = function (options) { return new TunerMachine(this, options); };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement