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 @@
-
+
+