audio reverse add
This commit is contained in:
parent
98f3a4a02f
commit
a9c1f21fe3
@ -43,7 +43,8 @@
|
|||||||
<button id="forward">10s +</button>
|
<button id="forward">10s +</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="audio" src="song to song v4.mp3"></audio>
|
<audio id="audio-forward" src="song to song v4.mp3"></audio>
|
||||||
|
<audio id="audio-reverse" src="song to song v4 reverse.mp3"></audio>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="socket.io.min.js"></script>
|
<script src="socket.io.min.js"></script>
|
||||||
|
|||||||
@ -43,7 +43,8 @@
|
|||||||
<button id="forward">10s +</button>
|
<button id="forward">10s +</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="audio" src="paradisev2.mp3"></audio>
|
<audio id="audio-forward" src="paradisev2.mp3"></audio>
|
||||||
|
<audio id="audio-reverse" src="paradisev2 reverse.mp3"></audio>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="socket.io.min.js"></script>
|
<script src="socket.io.min.js"></script>
|
||||||
|
|||||||
BIN
node-server/assets/muddy_files reverse.mp3
Normal file
BIN
node-server/assets/muddy_files reverse.mp3
Normal file
Binary file not shown.
@ -43,7 +43,8 @@
|
|||||||
<button id="forward">10s +</button>
|
<button id="forward">10s +</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="audio" src="muddy_files.mp3"></audio>
|
<audio id="audio-forward" src="muddy_files.mp3"></audio>
|
||||||
|
<audio id="audio-reverse" src="muddy_files reverse.mp3"></audio>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
node-server/assets/paradisev2 reverse.mp3
Normal file
BIN
node-server/assets/paradisev2 reverse.mp3
Normal file
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
// 1. Sélection des éléments du DOM
|
// 1. Sélection des éléments du DOM
|
||||||
const vinyl = document.getElementById('vinyl');
|
const vinyl = document.getElementById('vinyl');
|
||||||
const audio = document.getElementById('audio');
|
const audioForward = document.getElementById('audio-forward');
|
||||||
|
const audioReverse = document.getElementById('audio-reverse');
|
||||||
const progress = document.getElementById('progress');
|
const progress = document.getElementById('progress');
|
||||||
const currentTimeEl = document.getElementById('currentTime');
|
const currentTimeEl = document.getElementById('currentTime');
|
||||||
const durationEl = document.getElementById('duration');
|
const durationEl = document.getElementById('duration');
|
||||||
@ -11,164 +12,170 @@ const loopBtn = document.getElementById('loop');
|
|||||||
// 2. Variables utiles
|
// 2. Variables utiles
|
||||||
let isPlaying = false;
|
let isPlaying = false;
|
||||||
let isLooping = false;
|
let isLooping = false;
|
||||||
let idleTimeout = null;
|
let lastPosition = 0;
|
||||||
let reverseInterval = null;
|
let stopTimeout = null;
|
||||||
|
|
||||||
// 3. Variables pour calculer la vitesse de rotation
|
// socket.io & arduino serial info
|
||||||
let lastPosition = null;
|
|
||||||
let lastTime = null;
|
|
||||||
|
|
||||||
// 4. Connexion Socket.io
|
|
||||||
const socket = io();
|
const socket = io();
|
||||||
|
|
||||||
socket.on('position', (position) => {
|
const MIN_SPEED = 0.1; // seuil minimal pour commencer la lecture
|
||||||
const now = Date.now();
|
const MAX_SPEED = 2; // vitesse max
|
||||||
|
const SENSITIVITY = 0.01; // ajuste la sensibilité du mapping
|
||||||
if (lastPosition !== null && lastTime !== null) {
|
|
||||||
const deltaPos = position - lastPosition;
|
|
||||||
const deltaTime = (now - lastTime) / 1000;
|
|
||||||
|
|
||||||
const speed = deltaPos / deltaTime;
|
|
||||||
console.log('instant speed:', speed);
|
|
||||||
|
|
||||||
clearTimeout(idleTimeout);
|
|
||||||
|
|
||||||
if (Math.abs(speed) < 15) {
|
|
||||||
stopPlayback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isReverse = speed < 0;
|
|
||||||
|
|
||||||
// Simuler reverse
|
|
||||||
if (isReverse) {
|
|
||||||
simulateReverse(Math.abs(speed));
|
|
||||||
} else {
|
|
||||||
stopReverse();
|
|
||||||
let playbackSpeed = 1 + speed * 0.0003;
|
|
||||||
playbackSpeed = Math.max(0.5, Math.min(1.5, playbackSpeed));
|
|
||||||
controlPlayback(playbackSpeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPosition = position;
|
|
||||||
lastTime = now;
|
|
||||||
|
|
||||||
// Détecter l'inactivité : si pas de mise à jour pendant 300ms → stop
|
|
||||||
idleTimeout = setTimeout(() => {
|
|
||||||
stopPlayback();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 5. Fonctions
|
|
||||||
|
|
||||||
function togglePlay() {
|
|
||||||
if (isPlaying) {
|
|
||||||
audio.pause();
|
|
||||||
vinyl.style.animationPlayState = 'paused';
|
|
||||||
} else {
|
|
||||||
audio.play();
|
|
||||||
vinyl.style.animationPlayState = 'running';
|
|
||||||
}
|
|
||||||
isPlaying = !isPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateProgress() {
|
|
||||||
const progressPercent = (audio.currentTime / audio.duration) * 100;
|
|
||||||
progress.value = progressPercent;
|
|
||||||
currentTimeEl.textContent = formatTime(audio.currentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Fonction pour formater le temps (min:sec)
|
||||||
function formatTime(time) {
|
function formatTime(time) {
|
||||||
const minutes = Math.floor(time / 60);
|
const minutes = Math.floor(time / 60);
|
||||||
const seconds = Math.floor(time % 60);
|
const seconds = Math.floor(time % 60);
|
||||||
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProgress(e) {
|
// Mise à jour de la barre de progression à partir de la piste active
|
||||||
|
function updateProgress() {
|
||||||
|
let activeAudio = isPlaying ? (audioForward.paused ? audioReverse : audioForward) : null;
|
||||||
|
if (activeAudio && activeAudio.duration) {
|
||||||
|
const progressPercent = (activeAudio.currentTime / activeAudio.duration) * 100;
|
||||||
|
progress.value = progressPercent;
|
||||||
|
currentTimeEl.textContent = formatTime(activeAudio.currentTime);
|
||||||
|
durationEl.textContent = formatTime(activeAudio.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Met à jour l’animation du vinyle selon lecture en cours
|
||||||
|
function updateVinylAnimation() {
|
||||||
|
if (!audioForward.paused || !audioReverse.paused) {
|
||||||
|
vinyl.style.animationPlayState = 'running';
|
||||||
|
} else {
|
||||||
|
vinyl.style.animationPlayState = 'paused';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour arrêter les deux audios
|
||||||
|
function stopAudio() {
|
||||||
|
audioForward.pause();
|
||||||
|
audioReverse.pause();
|
||||||
|
isPlaying = false;
|
||||||
|
updateVinylAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour contrôler la lecture en fonction de la vitesse (peut être négative)
|
||||||
|
function controlPlayback(speed) {
|
||||||
|
// Nettoyer l’ancien timeout d’arrêt
|
||||||
|
if (stopTimeout) clearTimeout(stopTimeout);
|
||||||
|
|
||||||
|
// Si vitesse proche de 0, on arrête la lecture après 1.5s d’inactivité
|
||||||
|
if (Math.abs(speed) < MIN_SPEED) {
|
||||||
|
// Lance le timeout d'arrêt si plus de mouvement
|
||||||
|
stopTimeout = setTimeout(() => {
|
||||||
|
stopAudio();
|
||||||
|
}, 1500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ici, on a une vitesse suffisante => on arrête les deux audios d'abord
|
||||||
|
audioForward.pause();
|
||||||
|
audioReverse.pause();
|
||||||
|
|
||||||
|
// Calcule la vitesse normalisée (sensibilité appliquée)
|
||||||
|
let normalizedSpeed = Math.min(MAX_SPEED, Math.abs(speed) * SENSITIVITY);
|
||||||
|
|
||||||
|
// On lit dans le bon sens
|
||||||
|
if (speed > 0) {
|
||||||
|
audioForward.playbackRate = normalizedSpeed;
|
||||||
|
audioForward.currentTime = Math.min(audioForward.currentTime, audioForward.duration);
|
||||||
|
audioForward.play();
|
||||||
|
} else {
|
||||||
|
audioReverse.playbackRate = normalizedSpeed;
|
||||||
|
audioReverse.currentTime = Math.min(audioReverse.currentTime, audioReverse.duration);
|
||||||
|
audioReverse.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
isPlaying = true;
|
||||||
|
updateVinylAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// socket.io reçoit la position de l’encodeur
|
||||||
|
socket.on('position', (position) => {
|
||||||
|
// Calcule la vitesse par rapport au dernier mouvement
|
||||||
|
let speed = position - lastPosition;
|
||||||
|
lastPosition = position;
|
||||||
|
|
||||||
|
controlPlayback(speed);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Événements généraux
|
||||||
|
|
||||||
|
// Clique sur le vinyle pour basculer lecture/pauses sur les deux audios
|
||||||
|
vinyl.addEventListener('click', () => {
|
||||||
|
if (isPlaying) {
|
||||||
|
stopAudio();
|
||||||
|
} else {
|
||||||
|
audioForward.playbackRate = 1;
|
||||||
|
audioForward.play();
|
||||||
|
isPlaying = true;
|
||||||
|
updateVinylAnimation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mise à jour de la barre de progression à chaque changement de temps (sur les deux audios)
|
||||||
|
audioForward.addEventListener('timeupdate', updateProgress);
|
||||||
|
audioReverse.addEventListener('timeupdate', updateProgress);
|
||||||
|
|
||||||
|
// Mise à jour de la durée du titre dès que l'audio est chargé (sur les deux)
|
||||||
|
audioForward.addEventListener('loadedmetadata', () => {
|
||||||
|
durationEl.textContent = formatTime(audioForward.duration);
|
||||||
|
});
|
||||||
|
audioReverse.addEventListener('loadedmetadata', () => {
|
||||||
|
durationEl.textContent = formatTime(audioReverse.duration);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Permet de cliquer sur la barre de progression (pour avancer dans la piste forward)
|
||||||
|
progress.addEventListener('click', (e) => {
|
||||||
const width = progress.clientWidth;
|
const width = progress.clientWidth;
|
||||||
const clickX = e.offsetX;
|
const clickX = e.offsetX;
|
||||||
const duration = audio.duration;
|
const duration = audioForward.duration;
|
||||||
audio.currentTime = (clickX / width) * duration;
|
audioForward.currentTime = (clickX / width) * duration;
|
||||||
}
|
// En cas d'avancer, on arrête le reverse
|
||||||
|
audioReverse.pause();
|
||||||
// Fonction pour régler la lecture selon la vitesse
|
updateProgress();
|
||||||
|
|
||||||
function controlPlayback(speed) {
|
|
||||||
stopReverse(); // On stoppe le reverse si actif
|
|
||||||
if (speed > 0) {
|
|
||||||
if (!isPlaying) {
|
|
||||||
audio.play();
|
|
||||||
vinyl.style.animationPlayState = 'running';
|
|
||||||
isPlaying = true;
|
|
||||||
}
|
|
||||||
audio.playbackRate = speed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopPlayback() {
|
|
||||||
audio.pause();
|
|
||||||
vinyl.style.animationPlayState = 'paused';
|
|
||||||
isPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function simulateReverse(speed) {
|
|
||||||
// vitesse = ticks/sec → convertir en vitesse de recul
|
|
||||||
const reverseSpeed = Math.min(speed * 0.01, 2); // seconds per step
|
|
||||||
|
|
||||||
if (!reverseInterval) {
|
|
||||||
reverseInterval = setInterval(() => {
|
|
||||||
if (audio.currentTime > 0.05) {
|
|
||||||
audio.currentTime -= reverseSpeed * 0.1;
|
|
||||||
vinyl.style.animationPlayState = 'running';
|
|
||||||
} else {
|
|
||||||
stopPlayback();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
if (!isPlaying) {
|
|
||||||
isPlaying = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audio.pause(); // on met en pause le vrai son pour éviter conflit
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopReverse() {
|
|
||||||
if (reverseInterval) {
|
|
||||||
clearInterval(reverseInterval);
|
|
||||||
reverseInterval = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Événements
|
|
||||||
|
|
||||||
vinyl.addEventListener('click', togglePlay);
|
|
||||||
audio.addEventListener('timeupdate', updateProgress);
|
|
||||||
audio.addEventListener('loadedmetadata', () => {
|
|
||||||
durationEl.textContent = formatTime(audio.duration);
|
|
||||||
});
|
});
|
||||||
progress.addEventListener('click', setProgress);
|
|
||||||
|
|
||||||
|
// Bouton reculer de 10s (sur piste forward)
|
||||||
backwardBtn.addEventListener('click', () => {
|
backwardBtn.addEventListener('click', () => {
|
||||||
audio.currentTime = Math.max(0, audio.currentTime - 10);
|
audioForward.currentTime = Math.max(0, audioForward.currentTime - 10);
|
||||||
|
audioReverse.pause();
|
||||||
|
updateProgress();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Bouton avancer de 10s (sur piste forward)
|
||||||
forwardBtn.addEventListener('click', () => {
|
forwardBtn.addEventListener('click', () => {
|
||||||
audio.currentTime = Math.min(audio.duration, audio.currentTime + 10);
|
audioForward.currentTime = Math.min(audioForward.duration, audioForward.currentTime + 10);
|
||||||
|
audioReverse.pause();
|
||||||
|
updateProgress();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Bouton pour activer/désactiver la boucle (LOOP)
|
||||||
loopBtn.addEventListener('click', () => {
|
loopBtn.addEventListener('click', () => {
|
||||||
isLooping = !isLooping;
|
isLooping = !isLooping;
|
||||||
loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent';
|
loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent';
|
||||||
loopBtn.style.color = isLooping ? '#18344b' : 'white';
|
loopBtn.style.color = isLooping ? '#18344b' : 'white';
|
||||||
|
audioForward.loop = isLooping;
|
||||||
|
audioReverse.loop = isLooping;
|
||||||
});
|
});
|
||||||
|
|
||||||
audio.addEventListener('ended', () => {
|
// Lorsque l'audio est terminé, on répète si la boucle est activée
|
||||||
|
audioForward.addEventListener('ended', () => {
|
||||||
if (isLooping) {
|
if (isLooping) {
|
||||||
audio.currentTime = 0;
|
audioForward.currentTime = 0;
|
||||||
audio.play();
|
audioForward.play();
|
||||||
|
} else {
|
||||||
|
vinyl.style.animationPlayState = 'paused';
|
||||||
|
isPlaying = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
audioReverse.addEventListener('ended', () => {
|
||||||
|
if (isLooping) {
|
||||||
|
audioReverse.currentTime = 0;
|
||||||
|
audioReverse.play();
|
||||||
} else {
|
} else {
|
||||||
vinyl.style.animationPlayState = 'paused';
|
vinyl.style.animationPlayState = 'paused';
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
|
|||||||
BIN
node-server/assets/song to song v4 reverse.mp3
Normal file
BIN
node-server/assets/song to song v4 reverse.mp3
Normal file
Binary file not shown.
BIN
node-server/assets/stamina-v17 reverse.mp3
Normal file
BIN
node-server/assets/stamina-v17 reverse.mp3
Normal file
Binary file not shown.
@ -43,7 +43,8 @@
|
|||||||
<button id="forward">10s +</button>
|
<button id="forward">10s +</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio id="audio" src="stamina-v17.mp3"></audio>
|
<audio id="audio-forward" src="stamina-v17.mp3"></audio>
|
||||||
|
<audio id="audio-reverse" src="stamina-v17 reverse.mp3"></audio>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="socket.io.min.js"></script>
|
<script src="socket.io.min.js"></script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user