Files
50ohm-contents-dl/contents/html/quantisierung_und_sampling.html
T
Matthias Jung d730759102 refactor: sampling and quantisation
summarized three sections to one
2026-08-13 16:43:20 +02:00

199 lines
5.3 KiB
HTML

<script src="https://www.50ohm.de/assets/chartjs/4.4.1/chart.min.js"></script>
<style>
.sq-applet {
width: 100%;
max-width: 100%;
min-width: 0;
box-sizing: border-box;
display: grid;
gap: .8rem;
font-size: 15px;
container-type: inline-size;
}
.sq-applet .sq-controls {
display: grid;
grid-template-columns: minmax(9.5em, 1.2fr) minmax(8em, 2fr) minmax(7.5em, auto);
gap: .55rem .8rem;
align-items: center;
min-width: 0;
}
.sq-applet label,
.sq-applet output {
margin: 0;
line-height: 1.2;
white-space: nowrap;
}
.sq-applet label {
font-weight: 600;
}
.sq-applet input[type="range"] {
display: block;
width: 100%;
min-width: 0;
margin: 0;
}
.sq-applet output {
display: block;
min-width: 7.5em;
text-align: left;
font-variant-numeric: tabular-nums;
}
.sq-applet .sq-chart-wrap {
position: relative;
width: 100%;
height: clamp(220px, 43cqw, 360px);
min-width: 0;
min-height: 0;
}
.sq-applet canvas {
position: absolute;
inset: 0;
display: block;
width: 100% !important;
height: 100% !important;
}
@container (max-width: 520px) {
.sq-applet .sq-controls {
grid-template-columns: minmax(7.5em, auto) minmax(6em, 1fr) 6.8em;
gap: .45rem .55rem;
}
.sq-applet output {
min-width: 6.8em;
}
}
</style>
<div class="sq-applet" aria-label="Sampling und Quantisierung ausprobieren">
<div class="sq-controls">
<label>Zeit-Sampling:</label>
<input data-sq-time type="range" value="4" min="1" max="10" step="1" aria-label="Samplingrate">
<output data-sq-time-output>16 Samples/s</output>
<label>Wert-Quantisierung:</label>
<input data-sq-value type="range" value="16" min="1" max="16" step="1" aria-label="Quantisierungsbits">
<output data-sq-value-output>16 Bit</output>
</div>
<div class="sq-chart-wrap">
<canvas data-sq-chart aria-label="Zeitkontinuierliches sowie zeit- und wertdiskretes Signal"></canvas>
</div>
<script>
(function () {
const applet = document.currentScript.closest('.sq-applet');
const timeInput = applet.querySelector('[data-sq-time]');
const valueInput = applet.querySelector('[data-sq-value]');
const timeOutput = applet.querySelector('[data-sq-time-output]');
const valueOutput = applet.querySelector('[data-sq-value-output]');
const canvas = applet.querySelector('[data-sq-chart]');
const amplitude = 100;
const duration = 1;
const chart = new Chart(canvas, {
type: 'scatter',
data: {
datasets: [
{
label: 'Wert- und zeitdiskretes Signal',
data: [],
borderColor: '#00AEDF',
borderWidth: 2,
pointRadius: 0,
showLine: true,
stepped: true
},
{
label: 'Zeitkontinuierliches Signal',
data: [],
borderColor: '#999999',
borderWidth: 2,
pointRadius: 0,
showLine: true,
tension: .1
}
]
},
options: {
animation: false,
responsive: true,
maintainAspectRatio: false,
interaction: { mode: null },
plugins: {
legend: {
position: 'top',
labels: {
boxWidth: 28,
boxHeight: 10,
padding: 12,
font: { size: 12 }
}
}
},
scales: {
y: {
min: -120,
max: 120,
ticks: {
maxTicksLimit: 5,
callback: function (value) { return value + '%'; }
}
},
x: {
min: 0,
max: duration,
title: { display: true, text: 'Zeit' },
ticks: {
stepSize: 1,
callback: function (value) { return value + ' s'; }
}
}
}
}
});
function update() {
const samples = Math.pow(2, Number(timeInput.value));
const bits = Number(valueInput.value);
const levels = Math.pow(2, bits);
const sampleDistance = duration / samples;
const quantizationStep = 2 * amplitude / levels;
const continuous = [];
const quantized = [];
for (let x = 0; x <= duration + 1e-9; x += 1 / 128) {
continuous.push({ x: x, y: amplitude * Math.sin(2 * Math.PI * x) });
}
for (let x = 0; x <= duration + 1e-9; x += sampleDistance) {
const value = amplitude * Math.sin(2 * Math.PI * x);
const quantizedValue = Math.max(
-amplitude,
Math.min(amplitude, Math.sign(value) * quantizationStep * Math.floor(Math.abs(value) / quantizationStep + 1))
);
quantized.push({ x: x, y: quantizedValue });
}
chart.data.datasets[0].data = quantized;
chart.data.datasets[1].data = continuous;
chart.update('none');
timeOutput.textContent = samples + ' Samples/s';
valueOutput.textContent = bits + ' Bit';
}
timeInput.addEventListener('input', update);
valueInput.addEventListener('input', update);
update();
}());
</script>
</div>