Beispiel:Sound-Oszi.html
Aus SELFHTML-Wiki
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Sound-Oszi</title>
<style>
h1 { margin:0 }
#StartPauseWeiter { position: fixed; top: .5em; right: .5em; padding: .5em; font-size: 1rem; }
#plot_t, #plot_f { width: 95vw; height: 45vh; margin: 5px auto; }
</style>
<!-- Damit das Beispiel auch in der Frickl-Ansicht funktioniert, werden die Scripte per Javascript nachgeladen und der Eventlistener von DOMContentLoaded auf load geändert. -->
<!-- <script src="/extensions/Selfhtml/example.php/Beispiel:JS-Anw-FktPlot-grafik_svg.js"></script>
<script src="/extensions/Selfhtml/example.php/Beispiel:JS-Anw-FktPlot-plot.js"></script>-->
<script>
var SW = {};
SW.loadjs = function (jsfile) {
var s = document.createElement("script");
s.src = "/extensions/Selfhtml/example.php/Beispiel:"+jsfile;
s.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(s);
}
SW.loadjs("JS-Anw-FktPlot-grafik_svg.js");
SW.loadjs("JS-Anw-FktPlot-plot.js");
let audioCtx, analyser, plot_t, plot_f, animationFrame, lastVisualize = 0;
let dataArray_t, bufferLength_t, dataArray_f, bufferLength_f;
let t_werte = [], f_werte = [], t_scale, f_scale;
function initAudio() {
// Verbindung zum Mikrofon herstellen
navigator.mediaDevices.getUserMedia ({ audio: true })
.then(function(stream) {
// Audio-Schnittstelle einrichten
audioCtx = new AudioContext({sampleRate: 22050});
// Analyser für Abfrage der Zeitdaten und die Spektralanalyse einrichten
analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = 0;
analyser.fftSize = 1024;
// Analyser mit Audiostream verknüpfen
const source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
// Rest initialisieren
initVisualize();
initPlot();
initStartPauseWeiterButton();
})
.catch(function(error) {
console.error('The following getUserMedia error occured: ' + error);
});
} // initAudio
function initVisualize() {
// Sound-Daten Abruf und Plot vorberteiten
bufferLength_t = analyser.fftSize;
dataArray_t = new Float32Array(bufferLength_t);
bufferLength_f = analyser.frequencyBinCount;
dataArray_f = new Float32Array(bufferLength_f);
} // initVisualize
function initPlot() {
// Plot-Funktion einrichten
const canvas_t = document.querySelector('#plot_t');
canvas_t.setAttribute('width', canvas_t.offsetWidth);
canvas_t.setAttribute('height', canvas_t.offsetHeight);
plot_t = new SW.plot(canvas_t, "t", "ampl");
t_scale = [{t: 0, ampl: -1}, {t: bufferLength_t/audioCtx.sampleRate, ampl: 1}];
for(let i=0; i<bufferLength_t; i++) t_werte[i] = { t: i/audioCtx.sampleRate, ampl: 0 } ;
const canvas_f = document.querySelector('#plot_f');
canvas_f.setAttribute('width', canvas_f.offsetWidth);
canvas_f.setAttribute('height', canvas_f.offsetHeight);
plot_f = new SW.plot(canvas_f, "f", "spekt");
plot_f.fillopac = 0;
f_scale = [{f: 0, spekt: -100} ,{f: .5*audioCtx.sampleRate, spekt: -10}];
for(let i=0; i<bufferLength_f; i++) f_werte[i] = { f: 0.5*i*audioCtx.sampleRate/bufferLength_f, spekt: 0 } ;
} // initPlot
function initStartPauseWeiterButton() {
// Der Start/Pause/Weiter-Button
document.querySelector('#StartPauseWeiter').addEventListener("click", function() {
if(this.innerHTML == "Pause") {
window.cancelAnimationFrame(animationFrame);
this.innerHTML = "Weiter";
}
else {
visualize();
this.innerHTML = "Pause";
}
});
} // initStartPauseWeiterButton
function visualize(timestamp) {
// Mess- und Anzeigeschleife
animationFrame = window.requestAnimationFrame(visualize);
if((timestamp - lastVisualize) > 100) {
lastVisualize = timestamp;
// Zeit- und Frequenzdaten abrufen
getData();
// und plotten
draw_t();
draw_f();
}
} // visualize
function getData() {
// Zeit- und Frequenzdaten abrufen
analyser.getFloatTimeDomainData(dataArray_t);
analyser.getFloatFrequencyData(dataArray_f);
// das Frequenzarray enthält schon mal den Wert "-Infinity"
dataArray_f.forEach((v, i, a) => {
if(v < -100) a[i] = -100;
});
} // getData
function draw_t() {
// Zeitdiagramm
dataArray_t.forEach((v, i, a) => { t_werte[i].ampl = v; });
plot_t.clear();
plot_t.scale(t_scale);
plot_t.frame(40, 30, "Zeit", "Amplitude");
plot_t.plot(t_werte, "#f00");
} // draw_t
function draw_f() {
// Frequenzdiagramm
dataArray_f.forEach((v, i, a) => { f_werte[i].spekt = v; });
plot_f.clear();
plot_f.scale(f_scale);
plot_f.frame(40, 30, "Frequenz", "Amplitude in dB");
plot_f.plot(f_werte, "#f00");
} // draw_f
document.addEventListener("DOMContentLoaded", initAudio);
</script>
</head>
<body>
<header>
<h1>Sound-Oszi - 28. 4. 2026</h1>
</header>
<main>
<figure id="plot_t"></figure>
<figure id="plot_f"></figure>
<button type="button" id="StartPauseWeiter">Start</button>
</main>
</body>
</html>