0

Here is the code:

I want to create an audio program that can play audio from very low frequency to high frequency.

However, this code results in different output (even with the same device):

  1. The sound comes out suddenly - the expected result is it comes out gradually. I am sure my hearing is okay because I've asked my friends to hear;
  2. The audio sounds different on the same frequency.

WARNING: Please adjust your volume to very low in case of any hurting before running this script.

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();

// create Oscillator node
var oscillator = audioCtx.createOscillator();

var osc_arr = [];

function purgeSound(){
  osc_arr.forEach(function(v){
    try {
      v.stop();
      v.disconnect(audioCtx.destination);
    } catch (e) {}
  })
}

function playSoundAtFreq(fq){
  purgeSound();
  var osc = audioCtx.createOscillator();
  osc_arr.push(osc);
  osc.type = 'square';
  osc.frequency.setValueAtTime(fq, audioCtx.currentTime); // value in hertz
  $('#fff').val(fq);
  osc.connect(audioCtx.destination);
  osc.start();
}

$('#stop').click(function(){
  purgeSound();
  _break = true;
})

var _break = false;
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
var pointer = 0;
var go = appendAttemptAsync(10000);
async function appendAttemptAsync(range) {
  if(_break) return;
  var target = pointer+range;
  for (pointer; pointer<range; pointer++) {
    playSoundAtFreq(pointer);
    console.log(pointer)
    //if(pointer % 1 == 0) {
      await sleep(100)
    //}
  }
  return 5221;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id='stop'>stop</button>
<input id="fff" type="text" />

WARNING: Please adjust your volume to very low in case of any hurting before running this script.

Thanks for any kind of suggestions to improve my code.

AGamePlayer
  • 7,404
  • 19
  • 62
  • 119
  • What does "comes out gradually" mean? What do you mean audio sounds differently at the same frequency? Your test doesn't produce the same frequency. – Raymond Toy Oct 11 '19 at 14:41
  • By the word "gradually" I mean, I want to create a sound that is created from a low frequency to a high frequency. – AGamePlayer Oct 12 '19 at 05:25
  • Not sure what you're looking for. At least on chrome, you won't hear anything until you press stop because chrome's autoplay policy blocks the output until there's a user gesture. If you add a start button to start the oscillators, then I suspect it will work for you. – Raymond Toy Oct 14 '19 at 16:41
  • But for my Chrome, it starts automatically. It doesn't need a start button. And what I'm looking for is just something like this:https://www.youtube.com/watch?v=H-iCZElJ8m0 I want to use JavaScript to simulate the stuff in this video. – AGamePlayer Oct 15 '19 at 04:23

1 Answers1

1

If you want an Oscillator to sweep like in the YouTube video that you mentioned, you can do something like:

let osc = new OscillatorNode(audioCtx);
osc.connect(audioCtx.destination);
osc.frequency.setValueAtTime(20, audioCtx.currentTime);
osc.frequency.linearRampToValueAtTime(audioCtx.sampleRate / 2, audioCtx.currentTime + 300);
osc.start();

Change the 300 to some appropriate time over which the tone sweeps. I arbitrarily chose 5 minutes.

I do not know why your example doesn't work, but this snippet is the typical way to sweep a tone using WebAudio.

Raymond Toy
  • 5,490
  • 10
  • 13
  • Hi Raymond, thanks very much. It works, but I have one more question, I used my iPhone-X to play this it's not working, does the Web Audio only support Desktop? – AGamePlayer Oct 16 '19 at 03:46
  • WebAudio certainly works on mobile. Sorry, but I don't know why it wouldn't work on an iPhone. I think your best bet is to file an issue with Apple and/or WebKit about this. – Raymond Toy Oct 16 '19 at 14:47
  • do you have another mobile brand that can play the sound? Just wondering... I am interested to file an issue but if there’s a device which can run it would be easier to push them :) – AGamePlayer Oct 16 '19 at 15:56
  • I only have Android devices and your codepen works fine for me. – Raymond Toy Oct 16 '19 at 16:32
  • Sure. I tried on an ancient Nexus 4, and a Pixel 2 with pretty recent versions of Chrome. These are the devices I happen to have handy right now. – Raymond Toy Oct 16 '19 at 17:22
  • 1
    I think the reason why the codepen doesn't work in Safari is this line `let osc = new OscillatorNode(audioCtx);`. Safari doesn't support the constructor syntax. You can rewrite it like this: `let osc = audioCtx.createOscillator();`. Or if you want to stick with the new syntax you can use standardized-audio-context which lets you use the constructor in Safari, too. – chrisguttandin Oct 18 '19 at 10:21