<!DOCTYPE html>
<html>
  <head>
    <title>Amplitude Detector</title>
    <script>
        // Initialize variables
        let playButton, amplitudeDisplay, audioCtx, oscillator, microphone, scriptProcessor, meter;
        max = 0;
        var samples = [];
        sampleindex = -1;
        samplesize = 0;
        updatereading = 0;

        // Function to handle button click
        function handlePlayButtonClick() {
        	
// starting detection of pressure, add the action of your choice
            document.body.style.backgroundColor = "green";
//
            // Initialize the audio context
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();

            // Create an oscillator node for the tone
            oscillator = audioCtx.createOscillator();
            oscillator.frequency.value = 2000;   // do not change this value 2000 
            oscillator.start();

            // Connect the oscillator to the audio context's destination
            oscillator.connect(audioCtx.destination);

            // Create a media stream for the microphone
            navigator.mediaDevices.getUserMedia({ audio: true, video: false })
                .then(stream => {
                    microphone = audioCtx.createMediaStreamSource(stream);

                    // Create a script processor node
                    scriptProcessor = audioCtx.createScriptProcessor(256, 1, 1);  // do not change this value

                    // Connect the microphone to the script processor
                    microphone.connect(scriptProcessor);

                    // Continuously update the amplitude display
                    scriptProcessor.onaudioprocess = function(event) {
                        const data = event.inputBuffer.getChannelData(0);   // only detecct the amplitude of the right audio channel
                        let amplitude = 0;

                        for (let i = 0; i < data.length; i++) {
                            amplitude += Math.abs(data[i]);
                        }

                        amplitude = amplitude / data.length;
                      
// take average of 10 pressure samples for more stable output                        
                        if (samplesize < 10) {           //initial fill up samples array
                          samplesize++;
                          sampleindex = samplesize - 1;
                          samples.push(amplitude);
                        } else {                        //after samples array is filled, FIFO
                          sampleindex++;
                          if (sampleindex > (samplesize - 1)) {
                            sampleindex = 0;
                          } 
                          samples[sampleindex] = amplitude;
                        }
                        //console.log(sampleindex," ",samplesize," ",amplitude);
                        temp = 0;
                        for (let i = 0; i < samplesize; i++){
                          temp = temp + samples[i];
                        }
                        temp = temp / samplesize;
                      
// pressure detected, add the action of your choice  
                        updatereading++;
                        if (updatereading == 10) {
                          updatereading = 0;
                          amplitudeDisplay100.innerHTML = temp.toFixed(4);
                        }

                        if (temp > max){
                          max = temp;
                          meter.max = max;
                        }
                        meter.value = temp;
                        amplitudeDisplay.innerHTML = amplitude.toFixed(4);

                    }

                    // Connect the script processor to the audio context's destination
                    scriptProcessor.connect(audioCtx.destination);
                });
        }

        // Function to handle button click
        function handleStopButtonClick() {
// stopping the detection of presssure, add the action of your choice       	
            document.body.style.backgroundColor = "white";
//
            oscillator.stop();
            microphone.disconnect();
            scriptProcessor.disconnect();
        }
        
        function handlePenButtonClick() {
        	console.log("click");
        	console.log(event.key);
        		if (event.key === "MediaPlayPause") {
					        if (document.body.style.backgroundColor === "green") {
					          document.body.style.backgroundColor = "yellow";
					        } else {
					          document.body.style.backgroundColor = "green";
					        }
					  }
        }

        // On page load
        window.onload = function() {
            playButton = document.getElementById("play-button");
            stopButton = document.getElementById("stop-button");
            meter = document.getElementById("volume-meter");
            amplitudeDisplay = document.getElementById("amplitude-display");
            amplitudeDisplay100 = document.getElementById("amplitude-display100");

            // Add event listeners to the buttons
            playButton.addEventListener("click", handlePlayButtonClick);
            stopButton.addEventListener("click", handleStopButtonClick);
            document.addEventListener("keydown", handlePenButtonClick);
        }
    </script>
  </head>
  <body>
  	<p>If you are running this Javascipt program on a Windows PC, please make sure SonarPen windows driver is not running at the background, or else NO pressure will be detected.</p>
    <p>Click the button to change background color. (Button not working in Chromebook and Mac yet)</p>
    <button id="play-button">Start SonarPen</button>
    <button id="stop-button">Stop</button>
    <meter id="volume-meter" min="0" max="0.4" value="0"></meter>
    <span id="amplitude-display100">average</span>
    <span id="amplitude-display">reading</span>
  	<p>Tested on: Windows PC (Chrome, Firefox), Chromebook (Chrome), MacBook (Chrome, Firefox, Safari), Android (FireFox)</p>    
  </body

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.