14

I need a sample code that could:

  1. generate sine wave (an array of samples) and then

  2. play it.

All done in browser using some HTML5 API in JavaScript.

(I am tagging this web-audio, although I am not 100% sure it is applicable)

exebook
  • 32,014
  • 33
  • 141
  • 226
  • What have you tried? And it isn't completely clear what you mean by generate a sine wave – Binvention Jan 10 '16 at 18:24
  • 1
    @Binventionm by "generate a sine wave" I mean to create an array of samples in the range of -1 to 1 using the Math.sin() function, of arbitrary length and frequency. – exebook Jan 10 '16 at 18:57
  • So you're trying to mathematically create a sine wave and have it read as an audio file? – Binvention Jan 10 '16 at 18:59
  • @Binvention, right, except for the "file" part, it could be called a "buffer" instead more correctly. – exebook Jan 10 '16 at 19:18
  • 1
    Just to clarify: there is no HTML 5 API. Any API provided by the platform and JavaScript machine are offered regardless of the document type, it's just that not all documents allow for script execution, but SVG and HTML do, among others. Furthermore, some APIs are standardized and some aren't. – Armen Michaeli Nov 05 '18 at 11:41
  • 1
    @exebook: maybe a good way to re-formulate this *excellent* question would be to say that you want to 'listen to a function'; the function (for example, Math.sin) is passed as a parameter, the buffer-array is generated, and then played. A pity that self-important know-it-all-s have closed this question. I don't think that the 'why not use oscillator' is a good argument against the question. Probably, for those who lack imagination, it might seem like it. Anyway, to make the purpose 'clearer than necessary', there is my suggestion. – mathheadinclouds Mar 28 '20 at 15:34

1 Answers1

27

This is how to play 441 Hertz sine wave tone in the browser using the cross-browser AudioContext.

window.AudioContext = window.AudioContext || window.webkitAudioContext;

var context = new AudioContext();

function playSound(arr) {
  var buf = new Float32Array(arr.length)
  for (var i = 0; i < arr.length; i++) buf[i] = arr[i]
  var buffer = context.createBuffer(1, buf.length, context.sampleRate)
  buffer.copyToChannel(buf, 0)
  var source = context.createBufferSource();
  source.buffer = buffer;
  source.connect(context.destination);
  source.start(0);
}

function sineWaveAt(sampleNumber, tone) {
  var sampleFreq = context.sampleRate / tone
  return Math.sin(sampleNumber / (sampleFreq / (Math.PI * 2)))
}

var arr = [],
  volume = 0.2,
  seconds = 0.5,
  tone = 441

for (var i = 0; i < context.sampleRate * seconds; i++) {
  arr[i] = sineWaveAt(i, tone) * volume
}

playSound(arr)
Olian04
  • 6,480
  • 2
  • 27
  • 54
exebook
  • 32,014
  • 33
  • 141
  • 226
  • 2
    Although this answers the OP question, why bother creating your own sampled sine wave when you can just use WebAudio's oscillator node to create a sine wave for the desired frequency and duration? – Raymond Toy Jan 10 '16 at 23:30
  • 4
    @RaymondToy because you can edit the created wave in all the creative ways, fading in/out, distorting, cutting, mixing with other waves and doing any other soft of DSP over the array of samples. – exebook Feb 18 '18 at 05:06
  • Maybe so, but that wasn't the question. You wanted a sine wave, not some modified kind-a-like-a sine wave. And with a gain node you can do the fade in/out, cutting, and mixing. With a WaveShaperNode, you can do some kinds of distortion. – Raymond Toy Feb 19 '18 at 16:48
  • Safari does not support `buffer.copyToChannel`. Use `buffer.getChannelData` instead and modify the channel directly as shown in [the examples of MDN's BaseAudioContext.createBuffer](https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createBuffer#Examples) – Akseli Palén Mar 18 '19 at 21:38
  • That snippet doesn't work for me (I'm using Chrome on a Macbook pro). – Rusca8 Jul 26 '21 at 07:40
  • [Visualizations with Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API) check this mozilla demo – hulkyuan Mar 11 '22 at 02:57