From 5d13e6a9e23d70701ea2aaf331e702babee382e1 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Fri, 3 Nov 2023 17:25:29 +0100 Subject: [PATCH] commit to probably rewrite bpm detector --- frontend/src/client/audioProcessing.js | 0 frontend/src/client/backgroundAnim.css | 12 +--- frontend/src/client/colorPaletteExtractor.js | 7 +- frontend/src/client/showcase.html | 4 +- frontend/src/client/showcase.js | 72 ++++++++++++++++---- frontend/src/components/player.vue | 2 + 6 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 frontend/src/client/audioProcessing.js diff --git a/frontend/src/client/audioProcessing.js b/frontend/src/client/audioProcessing.js new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/client/backgroundAnim.css b/frontend/src/client/backgroundAnim.css index 0b2d7e4..e7e5827 100644 --- a/frontend/src/client/backgroundAnim.css +++ b/frontend/src/client/backgroundAnim.css @@ -9,22 +9,14 @@ background: conic-gradient( blue, green, red, blue ); animation: gradientAnim 10s infinite linear; background-position: center; + transition: all 0.1s; } .beat { height: 100%; width: 100%; background-color: rgba( 0, 0, 0, 0.2 ); - animation: beatAnim 0.6s infinite linear; -} - -@keyframes beatAnim { - 0% { - background-color: rgba( 0, 0, 0, 0.2 ); - } - 50% { - background-color: rgba( 0, 0, 0, 0 ); - } + display: none; } @keyframes gradientAnim { diff --git a/frontend/src/client/colorPaletteExtractor.js b/frontend/src/client/colorPaletteExtractor.js index cd9d2f7..5a25c81 100644 --- a/frontend/src/client/colorPaletteExtractor.js +++ b/frontend/src/client/colorPaletteExtractor.js @@ -121,7 +121,12 @@ const getColourPalette = ( imageURL ) => { canvas.width = image.width ?? 500; canvas.height = image.height ?? 500; const ctx = canvas.getContext( '2d' ); - ctx.drawImage(image, 0, 0); + try { + ctx.drawImage( image, 0, 0 ); + } catch ( err ) { + reject( err ); + return; + } /** * getImageData returns an array full of RGBA values diff --git a/frontend/src/client/showcase.html b/frontend/src/client/showcase.html index d59337c..b7627cb 100644 --- a/frontend/src/client/showcase.html +++ b/frontend/src/client/showcase.html @@ -8,6 +8,7 @@ Showcase - MusicPlayerV2 + @@ -16,6 +17,7 @@
music_note +

{{ playingSong.title }}

{{ playingSong.artist }}

@@ -42,7 +44,7 @@

Loading...

-
+
diff --git a/frontend/src/client/showcase.js b/frontend/src/client/showcase.js index 4d84231..9e3860c 100644 --- a/frontend/src/client/showcase.js +++ b/frontend/src/client/showcase.js @@ -11,6 +11,11 @@ createApp( { pos: 0, queuePos: 0, colourPalette: [], + startTime: 0, + offsetTime: 0, + progressBar: 0, + timeTracker: null, + timeCorrector: null, }; }, computed: { @@ -25,9 +30,25 @@ createApp( { } }, methods: { + startTimeTracker () { + this.startTime = new Date().getTime(); + this.timeTracker = setInterval( () => { + this.pos += 0.075; + this.progressBar = this.pos / this.playingSong.duration * 1000; + }, 75 ); + + this.timeCorrector = setInterval( () => { + this.pos = this.oldPos + ( new Date().getTime() - this.startTime ) / 1000; + this.progressBar = this.pos / this.playingSong.duration * 1000; + }, 5000 ); + }, + stopTimeTracker () { + clearInterval( this.timeTracker ); + clearInterval( this.timeCorrector ); + this.oldPos = this.pos; + }, connect() { let source = new EventSource( '/clientDisplayNotifier', { withCredentials: true } ); - source.onmessage = ( e ) => { let data; try { @@ -40,15 +61,22 @@ createApp( { this.playingSong = data.data.playingSong ?? {}; this.songs = data.data.songQueue ?? []; this.pos = data.data.pos ?? 0; + this.oldPos = data.data.pos ?? 0; + this.progressBar = this.pos / this.playingSong.duration * 1000; this.queuePos = data.data.queuePos ?? 0; + if ( this.isPlaying ) this.startTimeTracker(); getColourPalette( '/getSongCover?filename=' + data.data.playingSong.filename ).then( palette => { this.colourPalette = palette; this.handleBackground(); } ).catch( () => { - this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ] + this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ]; + this.handleBackground(); } ); } else if ( data.type === 'pos' ) { this.pos = data.data; + this.oldPos = data.data; + this.startTime = new Date().getTime(); + this.progressBar = data.data / this.playingSong.duration * 1000; } else if ( data.type === 'isPlaying' ) { this.isPlaying = data.data; this.handleBackground(); @@ -60,7 +88,8 @@ createApp( { this.colourPalette = palette; this.handleBackground(); } ).catch( () => { - this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ] + this.colourPalette = [ { 'r': 255, 'g': 0, 'b': 0 }, { 'r': 0, 'g': 255, 'b': 0 }, { 'r': 0, 'g': 0, 'b': 255 } ]; + this.handleBackground(); } ); } else if ( data.type === 'queuePos' ) { this.queuePos = data.data; @@ -80,20 +109,39 @@ createApp( { }, false ); }, handleBackground() { + // TODO: Consider using mic and realtime-bpm-analyzer let colours = {}; - for ( let i = 0; i < 3; i++ ) { - colours[ i ] = 'rgb(' + this.colourPalette[ i ].r + ',' + this.colourPalette[ i ].g + ',' + this.colourPalette[ i ].b + ')'; - } - $( '.background' ).css( 'background', `conic-gradient( ${ colours[ 0 ] }, ${ colours[ 1 ] }, ${ colours[ 2 ] }, ${ colours[ 0 ] } } )` ); - if ( this.playingSong.bpm && this.isPlaying ) { - $( '.beat' ).show(); - $( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm ); - } else { - $( '.beat' ).hide(); + if ( this.colourPalette[ 0 ] ) { + for ( let i = 0; i < 3; i++ ) { + colours[ i ] = 'rgb(' + this.colourPalette[ i ].r + ',' + this.colourPalette[ i ].g + ',' + this.colourPalette[ i ].b + ')'; + } } + $( '#background' ).css( 'background', `conic-gradient( ${ colours[ 0 ] }, ${ colours[ 1 ] }, ${ colours[ 2 ] }, ${ colours[ 0 ] } )` ); + // if ( this.playingSong.bpm && this.isPlaying ) { + // $( '.beat' ).show(); + // $( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm ); + // $( '.beat' ).css( 'animation-delay', this.pos % ( 60 / this.playingSong.bpm * this.pos ) ); + // } else { + // $( '.beat' ).hide(); + // } } }, mounted() { this.connect(); + // Initialize Web Audio API components + const audioContext = new ( window.AudioContext || window.webkitAudioContext )(); + // Start audio analysis + navigator.mediaDevices.getUserMedia( { audio: true } ).then( ( stream ) => { + + } ); + }, + watch: { + isPlaying( value ) { + if ( value ) { + this.startTimeTracker(); + } else { + this.stopTimeTracker(); + } + } } } ).mount( '#app' ); diff --git a/frontend/src/components/player.vue b/frontend/src/components/player.vue index c3a2742..d9993c3 100644 --- a/frontend/src/components/player.vue +++ b/frontend/src/components/player.vue @@ -325,7 +325,9 @@ export default { }, setPos( pos ) { let musicPlayer = document.getElementById( 'music-player' ); + this.playbackPos = pos; musicPlayer.currentTime = pos; + this.sendUpdate( 'pos' ); }, showFancyView() { this.$emit( 'update', { 'type': 'fancyView', 'status': true } );