diff --git a/node-server/assets/Roman.html b/node-server/assets/Roman.html index 0180a12..d942ba0 100644 --- a/node-server/assets/Roman.html +++ b/node-server/assets/Roman.html @@ -43,7 +43,8 @@ - + + diff --git a/node-server/assets/hell_even.html b/node-server/assets/hell_even.html index f263113..eff3b9e 100644 --- a/node-server/assets/hell_even.html +++ b/node-server/assets/hell_even.html @@ -43,7 +43,8 @@ - + + diff --git a/node-server/assets/muddy_files reverse.mp3 b/node-server/assets/muddy_files reverse.mp3 new file mode 100644 index 0000000..7af9248 Binary files /dev/null and b/node-server/assets/muddy_files reverse.mp3 differ diff --git a/node-server/assets/muddy_files.html b/node-server/assets/muddy_files.html index 2edfacd..0fd3320 100644 --- a/node-server/assets/muddy_files.html +++ b/node-server/assets/muddy_files.html @@ -43,7 +43,8 @@ - + + diff --git a/node-server/assets/paradisev2 reverse.mp3 b/node-server/assets/paradisev2 reverse.mp3 new file mode 100644 index 0000000..7ea75ca Binary files /dev/null and b/node-server/assets/paradisev2 reverse.mp3 differ diff --git a/node-server/assets/script.js b/node-server/assets/script.js index de165a7..bac48dd 100644 --- a/node-server/assets/script.js +++ b/node-server/assets/script.js @@ -1,6 +1,7 @@ // 1. Sélection des éléments du DOM 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 currentTimeEl = document.getElementById('currentTime'); const durationEl = document.getElementById('duration'); @@ -11,164 +12,170 @@ const loopBtn = document.getElementById('loop'); // 2. Variables utiles let isPlaying = false; let isLooping = false; -let idleTimeout = null; -let reverseInterval = null; +let lastPosition = 0; +let stopTimeout = null; -// 3. Variables pour calculer la vitesse de rotation -let lastPosition = null; -let lastTime = null; - -// 4. Connexion Socket.io +// socket.io & arduino serial info const socket = io(); -socket.on('position', (position) => { - const now = Date.now(); - - 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); -} +const MIN_SPEED = 0.1; // seuil minimal pour commencer la lecture +const MAX_SPEED = 2; // vitesse max +const SENSITIVITY = 0.01; // ajuste la sensibilité du mapping +// Fonction pour formater le temps (min:sec) function formatTime(time) { const minutes = Math.floor(time / 60); const seconds = Math.floor(time % 60); 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 clickX = e.offsetX; - const duration = audio.duration; - audio.currentTime = (clickX / width) * duration; -} - -// Fonction pour régler la lecture selon la vitesse - -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); + const duration = audioForward.duration; + audioForward.currentTime = (clickX / width) * duration; + // En cas d'avancer, on arrête le reverse + audioReverse.pause(); + updateProgress(); }); -progress.addEventListener('click', setProgress); +// Bouton reculer de 10s (sur piste forward) 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', () => { - 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', () => { isLooping = !isLooping; loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent'; 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) { - audio.currentTime = 0; - audio.play(); + audioForward.currentTime = 0; + audioForward.play(); + } else { + vinyl.style.animationPlayState = 'paused'; + isPlaying = false; + } +}); +audioReverse.addEventListener('ended', () => { + if (isLooping) { + audioReverse.currentTime = 0; + audioReverse.play(); } else { vinyl.style.animationPlayState = 'paused'; isPlaying = false; diff --git a/node-server/assets/song to song v4 reverse.mp3 b/node-server/assets/song to song v4 reverse.mp3 new file mode 100644 index 0000000..830d052 Binary files /dev/null and b/node-server/assets/song to song v4 reverse.mp3 differ diff --git a/node-server/assets/stamina-v17 reverse.mp3 b/node-server/assets/stamina-v17 reverse.mp3 new file mode 100644 index 0000000..90f308c Binary files /dev/null and b/node-server/assets/stamina-v17 reverse.mp3 differ diff --git a/node-server/assets/stamina.html b/node-server/assets/stamina.html index 9cb3ead..b75d784 100644 --- a/node-server/assets/stamina.html +++ b/node-server/assets/stamina.html @@ -43,7 +43,8 @@ - + +