Beispiel:Sound-Oszi.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
<!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>