1- import React , { useEffect , useRef } from 'react'
1+ import React , { useEffect , useRef } from 'react' ;
22import { useSelector } from 'react-redux' ;
33import { DisplayStatus } from '../../../react-redux&middleware/redux/typesImports' ;
44import { RootState } from '../../../store' ;
55import Meyda from 'meyda' ;
66import { MeydaAnalyzer } from 'meyda/dist/esm/meyda-wa' ;
77
8-
9- var audioContext : AudioContext ;
10- var analyser : MeydaAnalyzer ;
11- var source : MediaStreamAudioSourceNode ;
12- var rafId : number ;
13- var canvas : HTMLCanvasElement ;
14- var canvasCtx : CanvasRenderingContext2D ;
15-
168const LOUDNESS_THRESHOLD = 15 ;
179const HISTORY_LENGTH = 80 ;
1810const MFCC_COEFFICIENTS = 25 ;
1911const FFT_SIZE = 512 ;
20- var history_write_index = 0 ;
2112
2213class Moment {
2314 mfcc : Float32Array ;
@@ -29,93 +20,93 @@ class Moment {
2920 }
3021}
3122
32- var history : Moment [ ] = new Array ( HISTORY_LENGTH ) ;
33- for ( var i = 0 ; i < HISTORY_LENGTH ; i ++ ) {
34- history [ i ] = new Moment ( ) ;
35- }
23+ let audioContext : AudioContext ;
24+ let analyser : MeydaAnalyzer ;
25+ let source : MediaStreamAudioSourceNode ;
26+ let rafId : number ;
3627
37- var theme : DisplayStatus ;
28+ const history : Moment [ ] = Array . from ( { length : HISTORY_LENGTH } , ( ) => new Moment ( ) ) ;
29+ let history_write_index = 0 ;
3830
3931export function MFCCVisual ( props : any ) {
4032 const canvasRef = useRef < HTMLCanvasElement | null > ( null ) ;
41-
42- theme = useSelector ( ( state : RootState ) => {
43- return state . DisplayReducer as DisplayStatus ;
44- } ) ;
33+ const theme = useSelector ( ( state : RootState ) => state . DisplayReducer as DisplayStatus ) ;
4534
4635 useEffect ( ( ) => {
4736 audioContext = new ( window . AudioContext || window . webkitAudioContext ) ( ) ;
4837
49- navigator . mediaDevices . getUserMedia ( {
50- audio : true ,
51- video : false
52- } ) . then ( newMediaStream => {
53- source = audioContext . createMediaStreamSource ( newMediaStream ) ;
54-
55- analyser = Meyda . createMeydaAnalyzer ( {
56- audioContext : audioContext ,
57- source : source ,
58- bufferSize : FFT_SIZE ,
59- numberOfMFCCCoefficients : MFCC_COEFFICIENTS ,
60- featureExtractors : [
61- 'loudness' ,
62- 'spectralCentroid' ,
63- 'mfcc' ,
64- ] ,
65- callback : ( features : {
66- loudness : { specific : Float32Array , total : number } ,
67- spectralCentroid : number ,
68- mfcc : Float32Array ,
69- } ) => {
70- if ( features . loudness . total >= LOUDNESS_THRESHOLD ) {
71- history [ history_write_index ] . mfcc . set ( features . mfcc ) ;
72- history [ history_write_index ] . centroid = features . spectralCentroid ;
73- history_write_index = ( history_write_index + 1 ) % HISTORY_LENGTH ;
74- }
75- }
38+ navigator . mediaDevices
39+ . getUserMedia ( { audio : true , video : false } )
40+ . then ( ( mediaStream ) => {
41+ source = audioContext . createMediaStreamSource ( mediaStream ) ;
42+
43+ analyser = Meyda . createMeydaAnalyzer ( {
44+ audioContext,
45+ source,
46+ bufferSize : FFT_SIZE ,
47+ numberOfMFCCCoefficients : MFCC_COEFFICIENTS ,
48+ featureExtractors : [ 'loudness' , 'spectralCentroid' , 'mfcc' ] ,
49+ callback : ( features ) => {
50+ if ( features . loudness . total >= LOUDNESS_THRESHOLD ) {
51+ history [ history_write_index ] . mfcc . set ( features . mfcc ) ;
52+ history [ history_write_index ] . centroid = features . spectralCentroid ;
53+ history_write_index = ( history_write_index + 1 ) % HISTORY_LENGTH ;
54+ }
55+ } ,
56+ } ) ;
57+
58+ analyser . start ( ) ;
7659 } ) ;
7760
78- analyser . start ( ) ;
79- } ) ;
80-
8161 rafId = requestAnimationFrame ( draw ) ;
8262
83- // setup canvas
84- canvas = canvasRef . current ! ;
85- canvasCtx = canvas . getContext ( '2d' ) ! ;
86-
8763 return ( ) => {
8864 cancelAnimationFrame ( rafId ) ;
8965 analyser . stop ( ) ;
9066 source . disconnect ( ) ;
91- }
67+ } ;
9268 } , [ ] ) ;
9369
94- const draw = ( ) => { // the draw function
70+ const draw = ( ) => {
9571 requestAnimationFrame ( draw ) ;
96-
97- canvasCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
98-
99- const sliceWidth = canvas . width / MFCC_COEFFICIENTS ;
100- const sliceHeight = canvas . height / HISTORY_LENGTH ;
101- history . forEach ( ( moment , index ) => {
102- const row = ( HISTORY_LENGTH - history_write_index + index ) % HISTORY_LENGTH ;
103- console . log ( moment . centroid ) ;
104- const centroid = Math . round ( 720 * moment . centroid / FFT_SIZE ) ;
105- moment . mfcc . forEach ( ( data , col ) => {
72+
73+ const canvas = canvasRef . current ! ;
74+ const canvasCtx = canvas . getContext ( '2d' ) ! ;
75+
76+ // Set dull white background
77+ canvasCtx . fillStyle = '#D3D3D3' ;
78+ canvasCtx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
79+
80+ const sliceWidth = canvas . width / HISTORY_LENGTH ;
81+ const sliceHeight = canvas . height / MFCC_COEFFICIENTS ;
82+
83+ for ( let i = 0 ; i < HISTORY_LENGTH ; i ++ ) {
84+ const historyIndex = ( history_write_index - i + HISTORY_LENGTH ) % HISTORY_LENGTH ; // Map newest to right
85+ const x = canvas . width - sliceWidth * ( i + 1 ) ; // Calculate position from right to left
86+ const moment = history [ historyIndex ] ;
87+
88+ moment . mfcc . forEach ( ( data , row ) => {
89+ //const intensity = Math.min(data / 20, 1); // Normalize MFCC value
90+ //const brightness = intensity * 255; // Map intensity to brightness
91+
92+ // Grayscale color mapping
93+ ///canvasCtx.fillStyle = `rgb(${brightness}, ${brightness}, ${brightness})`;
10694 const intensity = data / 255 ;
107- canvasCtx . fillStyle = `hsl(${ centroid } deg 100% 50% / ${ intensity } )` ;
95+ const centroid = Math . round ( ( 720 * moment . centroid ) / FFT_SIZE ) ;
96+ canvasCtx . fillStyle = `hsl(${ centroid } deg 100% 60% / ${ Math . min ( intensity * 10 , 1 ) } )` ;
97+
98+ // Draw rectangle for each coefficient
10899 canvasCtx . fillRect (
109- col * sliceWidth ,
100+ x ,
110101 row * sliceHeight ,
111102 sliceWidth ,
112103 sliceHeight
113104 ) ;
114105 } ) ;
115- } ) ;
116- }
106+ }
107+ } ;
108+
109+
117110
118- return < canvas width = { props . visualWidth }
119- height = { props . visualHeight }
120- ref = { canvasRef } />
111+ return < canvas width = { props . visualWidth } height = { props . visualHeight } ref = { canvasRef } /> ;
121112}
0 commit comments