トップへ(mam-mam.net/)

Playing PCM Data in JavaScript How to Use AudioContext.createBuffer

Japanese

Generate and Play PCM Sine Wave Data: Left Channel (261 Hz C + 330 Hz E), Right Channel (392 Hz G + 522 Hz C)

If you want to play PCM data in JavaScript but aren’t sure how to use AudioContext,
this article explains in detail how to generate and play sounds using createBuffer.

Please be careful with the volume when playing the sound.
It’s recommended to start with a low volume and gradually increase it.
Depending on your speakers, high‑frequency tones may not be audible.

Volume:
5


Play Sound Stop Sound

Source Code

<div style="display:flex;"><div>Volume:</div><div id="vol_label">5</div></div>
<input type="range" value="5" max="100" min="1" step="1" id="vol" style="max-width:100%;width:600px;"><br>
<a onclick="" style="cursor:pointer;" class="bt112 bt112r" id="play">Play Sound</a>
<a onclick="" style="cursor:pointer;" class="bt112 bt112b" id="stop">Stop Sound</a>
<br>

<script>
  var audioCtx = null, source = null;
  var vol = 5;              // Volume
  var samplingRate = 44100; // 44,100 PCM samples per second

  window.addEventListener('DOMContentLoaded', function(){
    // Change volume
    document.getElementById('vol').addEventListener('input', function(){
      document.getElementById('vol_label').innerHTML = document.getElementById('vol').value;
      vol = document.getElementById('vol').value;
    });

    // Play sound
    document.getElementById('play').addEventListener('click', function(){
      if(audioCtx == null){
        audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        //audioCtx.sampleRate = samplingRate;
      }

      // Create an empty 1‑second stereo buffer
      var myArrayBuffer = audioCtx.createBuffer(
        2,                // Number of channels
        samplingRate * 1, // 1 second
        samplingRate      // Sampling rate
      );

      // Set PCM data for channel 0 (left): combined 261 Hz and 330 Hz
      let leftBuffer = myArrayBuffer.getChannelData(0);
      for(let i = 0; i < leftBuffer.length; i++){
        leftBuffer[i] =
          Math.sin(Math.PI * 2 * i / samplingRate * 261) * vol / 100 +
          Math.sin(Math.PI * 2 * i / samplingRate * 330) * vol / 100;
      }

      // Set PCM data for channel 1 (right): combined 392 Hz and 522 Hz
      let rightBuffer = myArrayBuffer.getChannelData(1);
      for(let i = 0; i < rightBuffer.length; i++){
        rightBuffer[i] =
          Math.sin(Math.PI * 2 * i / samplingRate * 392) * vol / 100 +
          Math.sin(Math.PI * 2 * i / samplingRate * 522) * vol / 100;
      }

      // Get an AudioBufferSourceNode
      source = audioCtx.createBufferSource();
      // Assign the buffer to the AudioBufferSourceNode
      source.buffer = myArrayBuffer;
      // Connect the AudioBufferSourceNode to the output
      source.connect(audioCtx.destination);
      // Start playing the PCM data
      source.start();
    });

    // Stop sound
    document.getElementById('stop').addEventListener('click', function(){
      source.stop();
    });
  });
</script>