DIR : /home/kozerus/public_html/ko/sound4.html
/home/kozerus/public_html/ko
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width">
<!--
<title>Creating Sounds with AudioContext < JavaScript | The Art of Web</title>
<meta name="description" content="An introduction to creating sounds with the built-in AudioContext interface which is now supported in all modern browsers.">
<meta name="author" content="Chirp Internet">
<meta name="theme-color" content="#333914">
-->
<!--
<link rel="stylesheet" href="/A.style.css,,q2+chirp_lightbox.css,Mcc.IRTz1vAmfc.css.pagespeed.cf.9UddlHi30d.css"/>
-->
<!--
<link rel="alternate" type="application/rss+xml" title="RSS: New and updated articles" href="/rss.xml">
-->
<style type="text/css">#analyser{display:flex;align-items:flex-end;margin:1em 0;height:100px;border:1px solid #ccc}#analyser>div{flex:1;border-top:2px solid green;transition:.1s}#piano{display:flex;margin:0 auto;max-width:80%}#piano>div{flex:1;position:relative;height:240px;margin:0 1px;border:1px solid #999;border-radius:1px 1px 5px 5px;box-shadow:2px 2px 5px rgba(0,0,0,.4);cursor:pointer}#piano>div::after{position:absolute;bottom:1em;width:100%;text-align:center;content:attr(data-note);font-size:1.5em}#piano>div>div{position:absolute;top:-1px;left:70%;height:160px;width: calc(60% + 2px);background:#000;border-radius:1px 1px 5px 5px;box-shadow:2px 2px 5px rgba(0,0,0,.4);cursor:pointer;z-index:10}</style>
<script id=script_soundplayer src=soundplayer.js></script>
</head>
<body>
<!--htdig_noindex-->
<a class="chirplink" accesskey="S" href="#content">skip to content</a>
<!--/htdig_noindex-->
<header id="header">
<a href="/"><img src="/images/banner-taow.png" width="737" height="87" alt="The Art of Web"></a>
<!--htdig_noindex-->
<nav id="menu" itemscope itemtype="http://schema.org/WebSite">
<meta itemprop="url" content="https://www.the-art-of-web.com/">
<form id="searchbox" itemprop="potentialAction" itemscope itemtype="http://schema.org/SearchAction" method="POST" action="/searchresult.html" accept-charset="UTF-8" onsubmit="return (words.value != '');">
<meta itemprop="target" content="https://www.the-art-of-web.com/searchresult.html?words={words}">
<input aria-label="site search" id="sitesearch" itemprop="query-input" type="search" results="10" autosave="searches" name="words" placeholder="Search">
<ul id="suggest"><li></li></ul>
</form>
<ul>
<li id="menu_trigger"><a href="#" accesskey="M">≡</a></li>
<li><a accesskey="1" href="/">Home</a></li>
<li><a accesskey="2" href="/html/">HTML</a></li>
<li><a accesskey="3" href="/css/">CSS</a></li>
<li><a accesskey="4" href="/javascript/">JavaScript</a></li>
<li><a accesskey="5" href="/php/">PHP</a></li>
<li><a accesskey="6" href="/sql/">SQL</a></li>
<li><a accesskey="7" href="/system/">System</a></li>
<li><a accesskey="8" href="/links/">Links</a></li>
</ul>
</nav>
<!--/htdig_noindex-->
</header>
<aside id="rhs">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- The Art of Web - RWD Top -->
<ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9789897350102210" data-ad-slot="8956648230" data-ad-format="auto"></ins>
<script>(adsbygoogle=window.adsbygoogle||[]).push({});</script>
</aside>
<main id="content">
<!--htdig_noindex-->
<aside id="ad_content" class="noprint">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- The Art of Web - RWD Content -->
<ins class="adsbygoogle" style="display: block;" data-ad-client="ca-pub-9789897350102210" data-ad-slot="1433381437" data-ad-format="auto"></ins>
<script>(adsbygoogle=window.adsbygoogle||[]).push({});</script>
</aside>
<!--/htdig_noindex-->
<div id="titlebox">
<div>
<h1><span class="nomobile">JavaScript: </span>Creating Sounds with AudioContext</h1>
<p class="social_counters"><a class="tweets" title="Share on Twitter" target="_blank" href="https://twitter.com/intent/tweet?text=Creating+Sounds+with+AudioContext:&url=https%3A%2F%2Fwww.the-art-of-web.com%2Fjavascript%2Fcreating-sounds%2F&via=theartofweb"><span> <span>Tweet</span></span></a><a class="likes" title="Share on Facebook" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.the-art-of-web.com%2Fjavascript%2Fcreating-sounds%2F"><span>5<span> Shares</span></span></a><a class="reddit" title="Post to Reddit" target="_blank" href="http://www.reddit.com/submit?title=Creating+Sounds+with+AudioContext&url=https%3A%2F%2Fwww.the-art-of-web.com%2Fjavascript%2Fcreating-sounds%2F"><span>0<span> Tweets</span></span></a><a class="feedback" title="User Commentc" href="#user_comments" accesskey="C"><span>3<span> Comments</span></span></a></p>
</div>
<div>
<div id="submenu"><!-- --></div>
</div>
</div>
<p>Did you know that it's now possible to generate sounds from scratch
using only JavaScript. Previously this required Flash/Shockwave or
loading an audio file.</p>
<p>Playing audio files became much easier in HTML5, but can now be done
away with entirely if you only want to play simple harmonics.</p>
<h2>Creating an oscillating soundwave</h2>
<p>The AudioContext interface is extremely powerful letting you chain
together various effects. For our purposes we are using only the
OscillatorNode (represents a periodic waveform) and gainNode (a change
in volume) to create our sounds.</p>
<p>Here we've set up two control forms, each controlling a separate
OscialltorNode (frequency, wave type) and GainNode (volume) to create a
constant tone which can then be manipulated. The code for each form is
otherwise identical.</p>
<div style="display: flex; justify-content: space-between;">
<form id="soundForm" style="width: 48%">
<fieldset>
<legend>Sound Player 1</legend>
<label>Frequency</label><span><input type="range" name="freq" value="261" min="220" max="880" oninput="myPlayer.setFrequency(this.value);"></span>
<label>Volume</label><span><input type="range" name="vol" value="50" min="0" max="200" oninput="myPlayer.setVolume(this.value/100);"></span>
<label>Wave Type</label><span>
<label><input type="radio" name="wave" value="sine" checked onclick="myPlayer.setWaveType(this.value);"> sine</label><br>
<label><input type="radio" name="wave" value="square" onclick="myPlayer.setWaveType(this.value);"> square</label><br>
<label><input type="radio" name="wave" value="sawtooth" onclick="myPlayer.setWaveType(this.value);"> sawtooth</label><br>
<label><input type="radio" name="wave" value="triangle" onclick="myPlayer.setWaveType(this.value);"> triangle</label>
</span>
<span>
<input name="play" type="button" onclick="
myPlayer.play(form.freq.value, form.vol.value/100, checkRadio(form.wave));
this.style.display = 'none';
form.stop.style.display = 'inline';
" value="Play ►">
<input name="stop" style="display: none;" type="button" onclick="
myPlayer.stop();
form.play.style = 'inline';
this.style.display = 'none';
" value="Stop ❙❙"></span>
</fieldset>
</form>
<form id="soundForm2" style="width: 48%;">
<fieldset>
<legend>Sound Player 2</legend>
<label>Frequency</label><span><input type="range" name="freq" value="392" min="220" max="880" oninput="myPlayer2.setFrequency(this.value);"></span>
<label>Volume</label><span><input type="range" name="vol" value="25" min="0" max="200" oninput="myPlayer2.setVolume(this.value/100);"></span>
<label>Wave Type</label><span>
<label><input type="radio" name="wave" value="sine" onclick="myPlayer2.setWaveType(this.value);"> sine</label><br>
<label><input type="radio" name="wave" value="square" checked onclick="myPlayer2.setWaveType(this.value);"> square</label><br>
<label><input type="radio" name="wave" value="sawtooth" onclick="myPlayer2.setWaveType(this.value);"> sawtooth</label><br>
<label><input type="radio" name="wave" value="triangle" onclick="myPlayer2.setWaveType(this.value);"> triangle</label>
</span>
<span>
<input name="play" type="button" onclick="
myPlayer2.play(form.freq.value, form.vol.value/100, checkRadio(form.wave));
this.style.display = 'none';
form.stop.style.display = 'inline';
" value="Play ►">
<input name="stop" style="display: none;" type="button" onclick="
myPlayer2.stop();
form.play.style = 'inline';
this.style.display = 'none';
" value="Stop ❙❙"></span>
</fieldset>
</form>
</div>
<div id="analyser">
</div>
<p>If you're feeling masochistic, try playing some sounds with adjacent
frequencies.</p>
<h2>AudioContext Mechanics</h2>
<p>For the effects demonstrated on this page we're using the following
interfaces:</p>
<p style="text-align: center;"><img src="/images/soundplayer.png" width="477" height="150" alt="SoundPlayer Node configuration diagram"></p>
<p>Rather than operating on them directly, we've created a
<tt>SoundPlayer</tt> class which does most of the work, including
ramping the volume up and down to avoid that annoying clicking
sound as the wave is truncated at the start and finish.</p>
<p>Complications arise when trying to play sounds in series, because
commands are processed relative to the current time
(baseAudioContext.currentTime) which represents a hardware timestamp
starting from zero once the system is activated.</p>
<h2>SoundPlayer.js class</h2>
<p>Our SoundPlayer class enables all the example on this page, plus the
sound effects in our new <a href="/javascript/graph-game/">JavaScript
Graphing Game</a>.</p>
<p>The constructor accepts an AudioContext object, after which a single
sound/note can be started and have it's properties controlled. A single
AudioContext is sufficient for all sounds on the page.</p>
<code id="box1" class="final" style="height: 400px;"><i>// Original JavaScript code by Chirp Internet: chirpinternet.eu</i>
<i>// Please acknowledge use of this code by including this header.</i>
function SoundPlayer(audioContext, filterNode) {
this.audioCtx = audioContext;
this.gainNode = this.audioCtx.createGain();
if(filterNode) {
<i>// run output through extra filter (already connected to audioContext)</i>
this.gainNode.connect(filterNode);
} else {
this.gainNode.connect(this.audioCtx.destination);
}
this.oscillator = null;
}
SoundPlayer.prototype.setFrequency = function(val, when) {
if(this.oscillator !== null) {
if(when) {
this.oscillator.frequency.setValueAtTime(val, this.audioCtx.currentTime + when);
} else {
this.oscillator.frequency.setValueAtTime(val, this.audioCtx.currentTime);
}
}
return this;
};
SoundPlayer.prototype.setVolume = function(val, when) {
if(when) {
this.gainNode.gain.exponentialRampToValueAtTime(val, this.audioCtx.currentTime + when);
} else {
this.gainNode.gain.setValueAtTime(val, this.audioCtx.currentTime);
}
return this;
};
SoundPlayer.prototype.setWaveType = function(waveType) {
this.oscillator.type = waveType;
return this;
};
SoundPlayer.prototype.play = function(freq, vol, wave, when) {
this.oscillator = this.audioCtx.createOscillator();
this.oscillator.connect(this.gainNode);
this.setFrequency(freq);
if(wave) {
this.setWaveType(wave);
}
this.setVolume(1/1000);
if(when) {
this.setVolume(1/1000, when - 0.02);
this.oscillator.start(when - 0.02);
this.setVolume(vol, when);
} else {
this.oscillator.start();
this.setVolume(vol, 0.02);
}
return this;
};
SoundPlayer.prototype.stop = function(when) {
if(when) {
this.gainNode.gain.setTargetAtTime(1/1000, this.audioCtx.currentTime + when - 0.05, 0.02);
this.oscillator.stop(this.audioCtx.currentTime + when);
} else {
this.gainNode.gain.setTargetAtTime(1/1000, this.audioCtx.currentTime, 0.02);
this.oscillator.stop(this.audioCtx.currentTime + 0.05);
}
return this;
};
</code>
<p style="margin-top: 0; text-align: right;"><small><a href="#box1" onclick="document.getElementById('box1').style['height'] = 'auto'; this.parentNode.style['display'] = 'none'; return true;">expand code box</a></small></p>
<h4>Public methods</h4>
<p>The SoundPlayer class has the following public methods:</p>
<dl>
<dt>__construct(<span><i>AudioContext</i></span>)</dt>
<dd>creates a GainNode and connects it to the destination.</dd>
<dt>play(<span><i>frequency, gain, waveType[, when]</i></span>)</dt>
<dd>creates an OscillatorNode to play the specified sound and starts playing, now or in the future.</dd>
<dt>stop(<span><i>[when]</i></span>)</dt>
<dd>stops playing, now or in the future.</dd>
<dt>setFrequency(<span><i>frequency[, when]</i></span>)</dt>
<dd>changes the frequency in Hz, now or in the future.</dd>
<dt>setVolume(<span><i>gain[, when]</i></span>)</dt>
<dd>changes the volume multiplier, now or in the future.</dd>
<dt>setWaveType(<span><i>type</i></span>)</dt>
<dd>changes the wave type (sine, square, sawtooth or triangle).</dd>
</dl>
<p>Notably, these functions can all be chained. For example, to play a
particular sound for a half second:</p>
<code><script src="<a href="/soundplayer.js">/soundplayer.js</a>"></script>
<script>
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audio = new AudioContext();
(new SoundPlayer(audio)).play(440.0, 0.8, "sine").stop(0.5);
</script></code>
<button onclick='(new SoundPlayer(audio)).play(440.0, 0.8, "sine").stop(0.5);'>Run Example ♪</button>
<p>And to play a sound with a frequency transition:</p>
<code>(new SoundPlayer(audio)).play(440, 0.5, "square").setFrequency(880, 0.1).stop(0.2);</code>
<button onclick='(new SoundPlayer(audio)).play(440, 0.5, "square").setFrequency(880, 0.1).stop(0.2);'>Run Example ♫</button>
<p>This approach is used in the piano keyboard demonstration below and,
in most browsers, the commands can even be pasted directly into the
Browser Console.</p>
<h2>Piano Keyboard</h2>
<p>Using our new SoundPlayer class we can easily attach it using event
listeners to elements on the page to play different notes. For example,
here we've set up a piano keyboard where each key plays the respective
note:</p>
<div id="piano">
<div data-frequency="261.626" data-note="C">
<div data-frequency="277.18" data-note="C#"></div>
</div>
<div data-frequency="293.665" data-note="D">
<div data-frequency="311.127"></div>
</div>
<div data-frequency="329.628" data-note="E"></div>
<div data-frequency="349.228" data-note="F">
<div data-frequency="369.994"></div>
</div>
<div data-frequency="391.995" data-note="G">
<div data-frequency="415.305"></div>
</div>
<div data-frequency="440.000" data-note="A">
<div data-frequency="466.164"></div>
</div>
<div data-frequency="493.883" data-note="B"></div>
<div data-frequency="523.251" data-note="C">
<div data-frequency="554.365"></div>
</div>
<div data-frequency="587.330" data-note="D">
<div data-frequency="622.254"></div>
</div>
<div data-frequency="659.255" data-note="E"></div>
<div data-frequency="698.457" data-note="F">
<div data-frequency="739.989"></div>
</div>
<div data-frequency="783.991" data-note="G">
<div data-frequency="830.609"></div>
</div>
<div data-frequency="880.000" data-note="A">
<div data-frequency="932.328"></div>
</div>
<div data-frequency="987.767" data-note="B"></div>
<div data-frequency="1046.50" data-note="C"></div>
</div>
<p style="text-align: center;"><small><label style="cursor: pointer;"><input type="checkbox" onclick="changePianoMode(this.checked);"> play notes on mouseover</label> (initial click needed)</small></p>
<p>Using HTML to mark up the keys as follows:</p>
<code><div id="<i>piano</i>">
<div data-frequency="261.626" data-note="C">
<div data-frequency="277.18" data-note="C#"></div>
</div>
<div data-frequency="293.665" data-note="D">
<div data-frequency="311.127" data-note="D#"></div>
</div>
<div data-frequency="329.628" data-note="E"></div>
<div data-frequency="349.228" data-note="F">
<div data-frequency="369.994" data-note="F#"></div>
</div>
<i>...</i>
</div></code>
<p>The data attributes are used to determine which note (frequency in
Hz) to play when the key is clicked, and to display the key labels.</p>
<p>The source code is simplicity itself:</p>
<code><script src="<a href="/soundplayer.js">/soundplayer.js</a>"></script>
<script>
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audio = new AudioContext();
const playNote = (e) => {
<i>// play note according to data-frequency attribute</i>
(new SoundPlayer(audio)).play(e.target.dataset.frequency, 0.8, "sine").stop(0.5);
e.cancelBubble = true;
};
for(let el of document.getElementById("<i>piano</i>").getElementsByTagName("DIV")) {
el.addEventListener("click", playNote, false);
}
</script></code>
<p>For those not familar with the new <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank">arrow functions</a> syntax, <tt>(e) =></tt> in the
above code snippets is equivalent to <tt>function(e)</tt>.</p>
<p>Depending on your system capabilities there may be some distortion
when playing overlapping notes. To reduce that we can add a <a href="https://developer.mozilla.org/en-US/docs/Web/API/DynamicsCompressorNode" target="_blank">DynamicsCompressorNode</a> to the mix:</p>
<code class="final"><script src="<a href="/soundplayer.js">/soundplayer.js</a>"></script>
<script>
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audio = new AudioContext();
<span> const compressor = audio.createDynamicsCompressor();
compressor.connect(audio.destination);</span>
const playNote = (e) => {
<i>// play note according to data-frequency attribute</i>
(new SoundPlayer(audio<span>, compressor</span>)).play(e.target.dataset.frequency, 0.8, "sine").setVolume(1/1000, 0.55).stop(0.6);
e.cancelBubble = true;
};
for(let el of document.getElementById("<i>piano</i>").getElementsByTagName("DIV")) {
el.addEventListener("click", playNote, false);
}
</script></code>
<p>Now all the notes should be clean even if you jam your hands down on
the keyboard. We've also tweaked the note decay profile.</p>
<p>What's actually happening behing the scenes is illustrated below:</p>
<p style="text-align: center;"><img src="/images/soundplayer2.png" width="640" height="150" alt="SoundPlayer Node configuration diagram"></p>
<p>So our Soundplayer class is handling the frequency, wave type and
volume, while the output (AudioContext.destination) and any intervening
filter nodes are supplied from outside code.</p>
<h2>Playing a series of notes</h2>
<p>To play notes in series (without using a buffer or
<tt>requestAnimationFrame</tt> for timing) we just need to specifiy a
start and end time in seconds.</p>
<p>You might recognise this tune, for example:</p>
<code>(new SoundPlayer(audio)).play(587.3, 0.5, "sine").stop(0.25);
(new SoundPlayer(audio)).play(587.3, 0.5, "sine", 0.3).stop(0.35);
(new SoundPlayer(audio)).play(659.3, 0.5, "sine", 0.4).stop(0.55);
(new SoundPlayer(audio)).play(587.3, 0.5, "sine", 0.6).stop(0.75);
(new SoundPlayer(audio)).play(784.0, 0.5, "sine", 0.8).stop(0.95);
(new SoundPlayer(audio)).play(740.0, 0.5, "sine", 1.0).stop(1.40);</code>
<p><button onclick='(new SoundPlayer(audio)).play(587.3, 0.5, "sine").stop(0.25);
(new SoundPlayer(audio)).play(587.3, 0.5, "sine", 0.3).stop(0.35);
(new SoundPlayer(audio)).play(659.3, 0.5, "sine", 0.4).stop(0.55);
(new SoundPlayer(audio)).play(587.3, 0.5, "sine", 0.6).stop(0.75);
(new SoundPlayer(audio)).play(784.0, 0.5, "sine", 0.8).stop(0.95);
(new SoundPlayer(audio)).play(740.0, 0.5, "sine", 1.0).stop(1.40); return false;'>Happy Birthday To You ♫</button></p>
<p>Note that Safari (12.0.3) will not play sounds automatically on page
load. Instead they are queued until a user action invokes the
AudioContext interface.</p>
<h2 id="related">Related Articles - Audio</h2>
<ul class="sectioned">
<li><span>JavaScript</span> <b>Creating Sounds with AudioContext</b></li>
</ul>
<h2>References</h2>
<ul>
<li><a href="http://marcgg.com/blog/2016/11/01/javascript-audio/" target="_blank">Generate Sounds Programmatically With Javascript</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API" target="_blank">MDN: Web Audio API</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode" target="_blank">MDN: OscillatorNode</a></li>
<li><a href="https://www.doctormix.com/blog/note-to-frequency-chart" target="_blank">Note to Frequency Chart</a></li>
</ul>
<p class="noprint"><a href="/javascript/">< JavaScript</a></p>
<script src="/soundplayer.js.pagespeed.jm.quKwRx6x0j.js"></script>
<script>
const checkRadio = (field) => {
if((typeof field.length == "undefined") && (field.type == "radio")) {
if(field.checked) return field.value;
} else {
for(let i=0; i < field.length; i++) {
if(field[i].checked) return field[i].value;
}
}
return false;
};
const changePianoMode = (active) => {
for(let el of piano.getElementsByTagName("DIV")) {
if(active) {
el.addEventListener("mouseover", playNote, false);
} else {
el.removeEventListener("mouseover", playNote, false);
}
}
};
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audio = new AudioContext();
const analyser = audio.createAnalyser();
let analyserDisplay = document.getElementById("analyser");
let myPlayer, myPlayer2;
if(analyser.getFloatTimeDomainData) {
analyser.fftSize = 512;
analyser.connect(audio.destination);
myPlayer = new SoundPlayer(audio, analyser);
myPlayer2 = new SoundPlayer(audio, analyser);
for(let i=0; i < analyser.fftSize; i++) {
analyserDisplay.appendChild(document.createElement("DIV"));
}
let dataArray = new Float32Array(analyser.fftSize);
setInterval(function() {
analyser.getFloatTimeDomainData(dataArray);
for(let i=0; i < dataArray.length; i++) {
analyserDisplay.children[i].style.height = (50 + (10 * dataArray[i])) + "px";
}
}, 500);
} else {
// getFloatTimeDomainData not supported
myPlayer = new SoundPlayer(audio);
myPlayer2 = new SoundPlayer(audio);
analyserDisplay.style.display = "none";
}
const compressor = audio.createDynamicsCompressor();
compressor.connect(audio.destination);
const playNote = (e) => {
(new SoundPlayer(audio, compressor)).play(e.target.dataset.frequency, 0.8, "sine").setVolume(1/1000, 0.55).stop(0.6);
e.cancelBubble = true;
};
let piano = document.getElementById("piano");
for(let el of piano.getElementsByTagName("DIV")) {
el.addEventListener("click", playNote, false);
}
</script>
<div class="clear"></div>
<ul id="share">
<li class="fbook"><a title="Share on Facebook" target="_blank" href="http://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fwww.the-art-of-web.com%2Fjavascript%2Fcreating-sounds%2F"><!-- --></a></li>
<li class="tweet"><a title="Tweet This" target="_blank" href="https://twitter.com/intent/tweet?text=JavaScript%3A+Creating+Sounds+with+AudioContext&url=http%3A%2F%2Fwww.the-art-of-web.com%2Fjavascript%2Fcreating-sounds%2F&via=theartofweb"></a></li>
</ul>
<script>document.getElementById("share").addEventListener("touchstart",function(e){e.target.className="hover";},{passive:true});</script>
<div id="feedback"><!-- --></div>
<h2 id="user_comments">User Comments</h2>
<a class="post_comment show-feedback">Post your comment or question</a>
<div id="comments">
<div class="comment" data-hash="e6ef5d2910f804804d76486d9b9e94ba" itemscope itemtype="http://schema.org/Comment">
<p class="comment_author"><big itemprop="author">kev</big> <span class="comment_time" itemprop="dateCreated">16 August, 2022</span></p>
<div itemprop="text"><p>how to download the sound of the frequency you change?</p></div>
</div>
<div class="comment" data-hash="ac4fa445c3dea16b8cc04ae8ccf1cfa5" itemscope itemtype="http://schema.org/Comment">
<p class="comment_author"><big itemprop="author">Paul</big> <span class="comment_time" itemprop="dateCreated">27 June, 2022</span></p>
<div itemprop="text"><p>Can I do frequency modulation.<br>
Fm = sin( a + m sin(b))</p></div>
</div>
<div class="comment" data-hash="475f40bdb6c14f6b02b7ae9c5ea14983" itemscope itemtype="http://schema.org/Comment">
<p class="comment_author"><big itemprop="author">Pete K</big> <span class="comment_time" itemprop="dateCreated">14 February, 2021</span></p>
<div itemprop="text"><p>Great stuff .. but it does not play after page loads, only when button clicked ...</p></div>
<div class="response">
<p>Most modern browsers prevent auto-playing sound, the same way they stop videos from auto-playing. It's just something we have to work with. <img src="/smilies/icon_sad.gif" width="15" height="15" alt=""></p>
</div>
</div>
</div>
<script>var loadAllCommentsAjax=function(value,target){var params={page:"/javascript/creating-sounds/"};return(new AjaxRequestXML()).post("/scripts/loadallcomments.xml",params);};var comments_onload=function(e){document.querySelectorAll("#comments .comment[data-hash]").forEach(function(current){current.style.backgroundImage="url(//www.gravatar.com/avatar/"+current.getAttribute("data-hash")+".jpg?s=48&d=mm)";});};window.addEventListener("DOMContentLoaded",comments_onload,false);</script>
<div class="clear"></div>
</main>
<footer id="copyright">
<a href="/copyright.html">© Copyright 2023</a> <a href="https://www.chirpinternet.eu/" target="_blank">Chirp Internet</a>
- Page Last Modified: 1 March 2019
- <a href="/cookies.html">Privacy & Cookies</a>
</footer>
<a class="totop" href="#content" onclick="document.getElementById('content').scrollIntoView({behavior: 'smooth'}); return false;">top</a>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-7GVHBLHJYW"></script>
<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag("js",new Date());gtag("config","G-7GVHBLHJYW");</script>
<script src="/scripts,_AjaxRequestXML.js+combined.js,q4.pagespeed.jc.2GMK_FJYoU.js"></script><script>eval(mod_pagespeed_8zQntuxrgR);</script>
<script>eval(mod_pagespeed_pRKjWkw7ND);</script>
<script>var mySuggest=new Suggestor("sitesearch","suggest","/scripts/autosuggest.xml",{regex:/^.{3,12}$/});window.onerror=function(msg,url,line){if(encodeURIComponent){var AjaxTarget="/scripts/logerror.xml";var params={"msg":msg,"url":url,"line":line};if(typeof AjaxRequestXML=="undefined"){var script=document.createElement("script");script.onload=function(){(new AjaxRequestXML()).post(AjaxTarget,params);}
script.src="/scripts/AjaxRequestXML.js";document.head.appendChild(script);return true;}else{return(new AjaxRequestXML()).post(AjaxTarget,params);}}return false;}</script>
<!-- web development by chirp internet -->
</body>
</html>
//
koh5_pano
Drag mouse to navigate.
Navigation
- Left/Right Mouse drag: Changes camera heading.
- Up/Sown Mouse drag: Changes camera pitch.
- Scroll wheel: Changes camera field of view.
- I-Key: Displays Info panel with canvas size, image size and FPS.
17.Aug.2010, Martin Wengenmayer