Welcome to JS Bin
Load cached copy from
24
 
1
<!DOCTYPE html>
2
<html>
3
<head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width">
6
  <title>Sine wave</title>
7
</head>
8
<body>
9
  
10
  <div class="flex">
11
    <span id="range-value"></span>
12
    <input type="range" id="freq" min=440 max=12000 value=440>
13
  </div>
14
15
  <div class="flex">
16
    <span id="volume-value"></span>
17
    <input type="range" id="volume" min=0 max=100 value=0>
18
  </div>
19
  
20
  <button>Toggle sound</button>
21
  
22
  <main><canvas></canvas></main>
23
</body>
24
</html>
55
 
1
* {
2
  box-sizing: border-box;
3
  background: white;
4
  font-family: sans-serif;
5
  font-size: 14px;
6
}
7
8
input[type=range] {
9
  width: 100%;
10
}
11
12
.flex {
13
  display: flex;
14
}
15
16
div {
17
  position: relative;
18
}
19
20
#range-value,
21
#volume-value {
22
  width: 80px;
23
  text-align: right;
24
}
25
26
#range-value:after {
27
  content: 'hz'
28
}
29
30
#volume-value:after {
31
  content: '%'
32
}
33
34
#volume-value:before {
35
  content: 'vol '
36
}
37
38
39
button {
40
  margin: 10px 0;
41
  cursor: pointer;
42
  border: 0;
43
  background: rgb(3, 169, 244);
44
  color: white;
45
  padding: 10px 20px;
46
  border-radius: 5px;
47
}
48
49
button:hover {
50
  background: #1976d2;
51
}
52
53
canvas {
54
  border: 1px solid rgb(3, 169, 244);
55
}
121
 
1
//noprotect
2
3
// apologies for the horrible code, I was being lazy
4
5
// globalsFTW ¯\_(ツ)_/¯
6
let gainNode;
7
let context;
8
let audio;
9
let analyser;
10
let bufferLength;
11
let dataArray;
12
13
const updatePosition = (input, output) => () => {
14
  output.innerHTML = input.value;
15
  output.style.left = `calc(${(input.value - input.min) / (input.max - input.min) * 95}%)`;
16
}
17
18
function getAudio() {
19
  // create web audio api context
20
  context = new (window.AudioContext || window.webkitAudioContext)();
21
  
22
  // create Oscillator node
23
  const oscillator = context.createOscillator();
24
25
  oscillator.type = 'sine';
26
  oscillator.frequency.value = range.value; // value in hertz
27
  // oscillator.connect(audioCtx.destination);
28
  
29
  gainNode = context.createGain();
30
  // Connect the source to the gain node.
31
  oscillator.connect(gainNode);
32
  // Connect the gain node to the destination.
33
  gainNode.connect(context.destination);
34
35
  const fraction = parseInt(volume.value) / parseInt(volume.max);
36
  gainNode.gain.value = fraction * fraction;
37
  
38
  analyser = context.createAnalyser();
39
  gainNode.connect(analyser);
40
  
41
  bufferLength = analyser.frequencyBinCount;
42
  dataArray = new Uint8Array(bufferLength);
43
44
  analyser.fftSize = 1024;
45
  
46
  oscillator.start();
47
48
  return oscillator;
49
}
50
51
function draw() {
52
  requestAnimationFrame(draw);
53
  
54
  if (!analyser) {
55
    return;
56
  }
57
  
58
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
59
  // analyser.getByteTimeDomainData(dataArray);
60
  analyser.getByteFrequencyData(dataArray);
61
62
  var barWidth = ((WIDTH) / bufferLength) * 1.5;
63
  var barHeight;
64
  var x = 0;
65
  
66
  for (var i = 0; i < bufferLength; i++) {
67
    barHeight = dataArray[i];
68
69
    ctx.fillStyle = 'rgb(3,169,244)';
70
    ctx.fillRect(x+.5,HEIGHT-barHeight/2+.5,barWidth,barHeight);
71
72
    x += barWidth + 1;
73
  }
74
  
75
}
76
77
78
const $$ = q => Array.from(document.querySelectorAll(q));
79
const $ = document.querySelector.bind(document);
80
81
//-----
82
83
const position = $('#range-value');
84
const range = $('#freq');
85
const updateFreq = updatePosition(freq, position);
86
range.oninput = () => {
87
  updateFreq();
88
  if (audio) audio.frequency.value = range.value; // value in hertz
89
}
90
updateFreq();
91
92
const vposition = $('#volume-value');
93
const volume = $('#volume');
94
const updateVolume = updatePosition(volume, vposition);
95
volume.oninput = () => {
96
  updateVolume();
97
  const fraction = parseInt(volume.value) / parseInt(volume.max);
98
99
  gainNode.gain.value = fraction * fraction;
100
}
101
updateVolume();
102
103
// button
104
const button = $('button');
105
let running = false;
106
button.onclick = function () {
107
  if (running) {
108
    audio.stop();
109
  } else {
110
    audio = getAudio();
111
  }
112
  running = !running;
113
}
114
115
// canvas
116
const canvas = $('canvas');
117
const ctx = canvas.getContext('2d');
118
const WIDTH = canvas.width = canvas.parentNode.offsetWidth;
119
const HEIGHT = canvas.height = canvas.parentNode.offsetHeight;
120
121
draw();
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x