How to measure decibel value (dBHL) from a website?

44 Views Asked by At

I developed a website for conducting pure tone audiometry, which features frequencies at 500, 1000, 2000, and 4000Hz played separately in each ear. It includes a volume slider ranging from 0dB to 120dB. Users are prompted to click "next" when they can barely detect the tone, with the corresponding decibel value being saved upon clicking.

My challenge lies in verifying the accuracy of the decibel values. How can I ensure that 5dB is indeed 5dB and 10dB is accurately represented? Also, the laptop's volume control interferes with the website's volume slider, affecting the accuracy of the decibel readings. I am using Web Audio API.

sample website

I've heard about using an oscilloscope or spectrum analyzer for this purpose, but I wonder if there's software or a library available to assist with programming this feature.

I purchased an inexpensive sound level meter and experimented with apps like Decibel X. However, accurate testing demands a soundproof environment, and the meter only detects a minimum of 30dB.

Should we consider using an existing audiometer device to compare its "decibel" readings with those of our website? If so, what would be the approach?

let audioContext;
let oscillator;
let gainNode;
let isPlaying = false;
let currentFrequencyIndex = 0;
let frequencies = [500, 1000, 2000, 4000];
let currentEar = 'Left';
let frequencyDecibelData = [];

function playTone() {
  if (!isPlaying) {
    stopTone();
    audioContext = new (window.AudioContext || window.webkitAudioContext)();
    oscillator = audioContext.createOscillator();
    gainNode = audioContext.createGain();

    const panNode = audioContext.createStereoPanner();
    panNode.pan.value = currentEar === 'Left' ? -1 : 1;

    oscillator.type = 'sine';
    oscillator.frequency.setValueAtTime(frequencies[currentFrequencyIndex], audioContext.currentTime);
    oscillator.connect(panNode);
    panNode.connect(gainNode);
    gainNode.connect(audioContext.destination);

    const volumeSlider = document.getElementById('volumeSlider');
    const currentVolumeElement = document.getElementById('currentVolume');
    
    volumeSlider.addEventListener('input', function() {
      const volumeValue = parseFloat(volumeSlider.value);
      gainNode.gain.setValueAtTime(convertToGain(volumeValue), audioContext.currentTime);
      currentVolumeElement.textContent = volumeValue + ' dB';
    });

    const volumeValue = parseFloat(volumeSlider.value);
    gainNode.gain.setValueAtTime(convertToGain(volumeValue), audioContext.currentTime);

    const currentFrequencyElement = document.getElementById('currentFrequency');
    currentFrequencyElement.textContent = frequencies[currentFrequencyIndex] + ' Hz';

    const currentEarElement = document.getElementById('currentEar');
    currentEarElement.textContent = currentEar;

    oscillator.start();
    isPlaying = true;
  }
}

function pauseTone() {
  if (isPlaying) {
    oscillator.stop();
    isPlaying = false;
  }
}

function stopTone() {
  if (isPlaying) {
    oscillator.stop();
    isPlaying = false;
  }
}

function nextFrequency() {
  stopTone();

  // save the frequency, decibel, and ear values in the console (database simulation)
  const volumeValue = parseFloat(document.getElementById('volumeSlider').value);
  frequencyDecibelData.push({
    frequency: frequencies[currentFrequencyIndex],
    decibel: volumeValue,
    ear: currentEar
  });

  if (currentEar === 'Left') {
    // move to the next frequency for the left ear
    if (currentFrequencyIndex < frequencies.length - 1) {
      currentFrequencyIndex++;
    } else {
      // switch to the right ear if all frequencies are tested for the left ear
      currentEar = 'Right';
      currentFrequencyIndex = 0;
    }
  } else if (currentEar === 'Right') {
    // move to the next frequency for the right ear
    if (currentFrequencyIndex < frequencies.length - 1) {
      currentFrequencyIndex++;
    } else {
      // end of the test for both ears
      alert('Hearing test completed!');
      displayFrequencyDecibelData();

      // log for checking
      console.log('Test completed, sending data to the database...');

      sendDataToDatabase();

      return;
    }
  }

  // update the display with the current frequency and ear
  const currentFrequencyElement = document.getElementById('currentFrequency');
  currentFrequencyElement.textContent = frequencies[currentFrequencyIndex] + ' Hz';

  const currentEarElement = document.getElementById('currentEar');
  currentEarElement.textContent = currentEar;

  playTone();
}




function convertToGain(volume) {
  return volume / 100;
}

function sendDataToDatabase() {
  if (frequencyDecibelData.length > 0) {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'test.php', true);
    xhr.setRequestHeader('Content-Type', 'application/json');

    const data = {
      decibels: frequencyDecibelData.map(entry => entry.decibel)
    };

    console.log('Decibel Values Array:', frequencyDecibelData.map(entry => entry.decibel));

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          console.log('Data sent to database successfully.');
          // clear array after successful submission
          frequencyDecibelData = [];
        } else {
          console.log('Error sending data to the database. Status:', xhr.status);
        }
      }
    };

    xhr.send(JSON.stringify(data));
  }
}


function displayFrequencyDecibelData() {
  console.log("Frequency and Decibel Data:");
  frequencyDecibelData.forEach(data => {
    console.log(`Frequency: ${data.frequency} Hz, Decibel: ${data.decibel} dB, Ear: ${data.ear}`);
  });
}

// initial setup
window.onload = function() {
  playTone();
};

0

There are 0 best solutions below