Javascript Fade Audio
heinetz
- javascript
Hallo Forum,
ich habe in einer REACT-Komponente einen Mute-Button für ein Video einbaut. Die Methode ist schlicht:
mute = muted => this.setState({ muted });
Nun soll der Sound nicht abrupt aus- und angehen, sondern ein- und ausgefaded werden.
Mein Versuch:
mute = muted => {
console.log('mute()');
console.log(this.intro.current.volume);
this.intro.current.volume = 0.5;
const fadeAudio = setTimeout(() => {
if (this.intro.current.volume >= 0) {
console.log(this.intro.current.volume);
this.intro.current.volume = this.intro.current.volume - 0.1;
console.log(this.intro.current.volume);
} else {
clearTimeout(fadeAudio);
this.setState({ muted });
}
}, 100);
};
... scheint grundsätzlich zu funktionieren. Die Ausgabe sieht aber so aus:
0.5
0.4
0.30000000000000004
0.10000000000000003
2.7755575615628914e-17
Das Incrementieren scheint irgendwie fehlerhaft zu sein, was ich nicht verstehe. Wo ich mir auch nicht sicher bin, ist der Timeout. Wird der auf diese Weise sauber wieder entfernt?
danke für Tipps und
gruss, heinetz
Hallo heinetz,
... scheint grundsätzlich zu funktionieren. Die Ausgabe sieht aber so aus:
0.5
0.4
0.30000000000000004
0.10000000000000003
2.7755575615628914e-17Das Incrementieren scheint irgendwie fehlerhaft zu sein, was ich nicht verstehe.
https://wiki.selfhtml.org/wiki/Programmiertechnik/Rechnerarithmetik
Bis demnächst
Matthias
@@Matthias Apsel
0.5
0.4
0.30000000000000004
0.10000000000000003
2.7755575615628914e-17https://wiki.selfhtml.org/wiki/Programmiertechnik/Rechnerarithmetik
Und darin wird der Sprung von 0.3 auf 0.1 erklärt?
LLAP 🖖
Hallo Gunnar Bittersmann,
Und darin wird der Sprung von 0.3 auf 0.1 erklärt?
Die fehlende 0.2 ist ein cnp-Fehler 😀
Bis demnächst
Matthias
Lieber heinetz,
0.5 0.4 0.30000000000000004 0.10000000000000003 2.7755575615628914e-17
dazu hat Dir Matthias schon etwas verlinkt.
Wo ich mir auch nicht sicher bin, ist der Timeout. Wird der auf diese Weise sauber wieder entfernt?
Vielleicht, vielleicht auch nicht. Warum nicht so?
mute = muted => {
let volume = 50; // percentage
const fadeAudio = () => {
if (volume > 0) {
volume -= 10; // -10%
if (volume < 0) {
volume = 0
}
this.intro.current.volume = volume / 100;
setTimeout(fadeAudio, 100);
} else {
this.setState({ muted: muted });
}
};
fadeAudio();
};
Liebe Grüße
Felix Riesterer
Hallo Felix,
die "mach erstmal und zieh's dann gerade" Technik finde ich suboptimal, darum würde ich die Logik ein bisschen variieren:
const fadeAudio = () => {
if (volume > 10) {
volume -= 10;
this.intro.current.volume = volume / 100;
// volume ist nun noch größer 0, neuen Aufruf buchen
setTimeout(fadeAudio, 100);
} else {
volume = 0;
this.setState({ muted: muted });
}
};
(edit: setState für muted nachgetragen)
Dass man so einen Test weniger hat, ist ein netter (aber für Laufzeit irrelevanter) Nebeneffekt.
Rolf
Lieber Rolf,
die "mach erstmal und zieh's dann gerade" Technik finde ich suboptimal
OK, das geht tatsächlich besser.
const fadeAudio = () => { if (volume > 10) { volume -= 10; // volume ist nun noch größer 0, neuen Aufruf buchen setTimeout(fadeAudio, 100); } else { volume = 0; } this.intro.current.volume = volume / 100; };
Hier wird die Sache mit this.setState({ muted: muted });
nicht mehr berücksichtigt. Der Player ist also nicht mehr auf lautlos gestellt, was bei volume=0 aber sinnvoll ist.
Dass man so einen Test weniger hat, ist ein netter (aber für Laufzeit irrelevanter) Nebeneffekt.
Stimmt. Danke für die Optimierung.
Liebe Grüße
Felix Riesterer
Hallo Felix,
danke für den Hinweis auf mein Versäumnis. Das Muting hatte ich vergessen und habe es nachgetragen.
Rolf
Lieber Rolf,
Das Muting hatte ich vergessen und habe es nachgetragen.
aha, jetzt sehe ich's auch. Aber der Player bekommt keine Lautstärke mit dem Wert 0 mehr. Mein Verbesserungsvorschlag:
const fadeAudio = () => {
if (volume > 10) {
volume -= 10;
// volume ist nun noch größer 0, neuen Aufruf buchen
setTimeout(fadeAudio, 100);
} else {
volume = 0;
this.setState({ muted: muted });
}
// Lautstärke tatsächlich verändern
this.intro.current.volume = volume / 100;
};
Liebe Grüße
Felix Riesterer
Hallo heinetz,
sehe ich es richtig, dass Du die Zeile mit 0.200...004 zu kopieren vergessen hast?
Die Prozenttechnik von Felix funktioniert deshalb besser, weil das IEEE 754 Format Zahlen ohne Nachkommastellen immer fehlerfrei darstellen kann (solange sie nicht zu groß sind).
Wenn Du bei Fließkommazahlen bleibst, müsstest Du current.volume > 0.15
testen (dann ist es 0.2 oder mehr). Wenn dieser Test zutrifft, ziehst Du 0.1 ab. Andernfalls setzt Du es hart auf 0. Felix tut sich
Deine Abfrage von current.volume >= 0
ist auf jeden Fall falsch, weil dadurch eine negative Lautstärke entsteht. Das ist sicherlich kein definierter Wert. Wenn die Audio-Library gutmütig ist, macht sie 0 draus. Aber es könnte auch eine Exception geworfen werden.
Was deiner Funktion auch fehlt, ist der rekursive setTimeout Aufruf. Der gehört in den Teil, wo Du 0.1 abziehst, und es ist sinnvoll, wenn man die Funktion, die in setTimeout hinterlegt wird, namentlich ansprechbar ist. Wie das geht, zeigt Dir ebenfalls Felix.
clearTimeout braucht man nur dann, wenn man einen gebuchten setTimeout stornieren will. Das ist aber nur ausnahmsweise der Fall. Mit setTimeout bucht man einen einmaligen Aufruf der angegebenen Funktion; für eine periodische Wiederholung nimmt man setInterval (was man mit clearInterval beenden muss) oder man bucht in der Funktion, die von setTimeout aufgerufen wird, den nächsten Aufruf.
Rolf