@@ -24,19 +24,20 @@ export function Player({ music, musicList }: PlayerProps) {
2424 const [ duration , setDuration ] = useState ( 0 ) ;
2525 const [ timePosition , setTimePosition ] = useState ( 0 ) ;
2626 const [ playbackRate , setPlaybackRate ] = useState ( 1 ) ;
27- const [ source , setSource ] = useState < MediaElementAudioSourceNode | null > ( null ) ;
27+ const [ source , setSource ] = useState < MediaElementAudioSourceNode | null > (
28+ null
29+ ) ;
2830 const [ analyserNode , setAnalyserNode ] = useState < AnalyserNode | null > ( null ) ;
2931 const [ isCircular , setIsCircular ] = useState ( false ) ;
30- const [ eqGains , setEqGains ] = useState < number [ ] > ( [ 0 , 0 , 0 , 0 , 0 ] ) ; // イコライザーゲイン
32+ const [ eqGains , setEqGains ] = useState < number [ ] > ( [ 0 , 0 , 0 , 0 , 0 ] ) ;
3133
3234 const audioRef = useRef < HTMLAudioElement > ( null ) ;
3335 const audioCtxRef = useRef < AudioContext | null > ( null ) ;
3436 const timePositionRef = useRef < HTMLInputElement > ( null ) ;
3537 const spectrumRef = useRef < HTMLCanvasElement > ( null ) ;
3638 const animationFrameRef = useRef < number > ( null ) ;
37- const eqFiltersRef = useRef < BiquadFilterNode [ ] > ( [ ] ) ; // イコライザーフィルター参照
39+ const eqFiltersRef = useRef < BiquadFilterNode [ ] > ( [ ] ) ;
3840
39- // 音声メタデータの読み込み
4041 useEffect ( ( ) => {
4142 if ( ! audioRef . current ) return ;
4243
@@ -55,7 +56,6 @@ export function Player({ music, musicList }: PlayerProps) {
5556 } ;
5657 } , [ ] ) ;
5758
58- // 再生位置の更新
5959 useEffect ( ( ) => {
6060 if ( ! audioRef . current ) return ;
6161
@@ -70,16 +70,16 @@ export function Player({ music, musicList }: PlayerProps) {
7070 } ;
7171 } , [ ] ) ;
7272
73- // AudioContextとアナライザー、イコライザーフィルターの初期化
7473 useEffect ( ( ) => {
7574 if ( ! audioRef . current ) return ;
7675
7776 audioCtxRef . current = new AudioContext ( ) ;
78- const elementSource = audioCtxRef . current . createMediaElementSource ( audioRef . current ) ;
77+ const elementSource = audioCtxRef . current . createMediaElementSource (
78+ audioRef . current
79+ ) ;
7980 const analyser = audioCtxRef . current . createAnalyser ( ) ;
80- analyser . fftSize = 2 ** 5 ;
81+ analyser . fftSize = 2 ** 8 ;
8182
82- // イコライザーフィルターの作成
8383 const eqFilters : BiquadFilterNode [ ] = [
8484 audioCtxRef . current . createBiquadFilter ( ) ,
8585 audioCtxRef . current . createBiquadFilter ( ) ,
@@ -88,16 +88,14 @@ export function Player({ music, musicList }: PlayerProps) {
8888 audioCtxRef . current . createBiquadFilter ( ) ,
8989 ] ;
9090
91- // 各フィルターの設定
9291 const frequencies = [ 60 , 250 , 1000 , 4000 , 16000 ] ;
9392 eqFilters . forEach ( ( filter , index ) => {
94- filter . type = ' peaking' ;
93+ filter . type = " peaking" ;
9594 filter . frequency . value = frequencies [ index ] ;
9695 filter . Q . value = 1.5 ;
9796 filter . gain . value = eqGains [ index ] ;
9897 } ) ;
9998
100- // チェーンの接続:ソース → フィルター1 → フィルター2 → ... → アナライザー → 出力先
10199 let previousNode : AudioNode = elementSource ;
102100 eqFilters . forEach ( ( filter ) => {
103101 previousNode . connect ( filter ) ;
@@ -110,7 +108,6 @@ export function Player({ music, musicList }: PlayerProps) {
110108 setAnalyserNode ( analyser ) ;
111109 eqFiltersRef . current = eqFilters ;
112110
113- // クリーンアップ
114111 return ( ) => {
115112 if ( animationFrameRef . current ) {
116113 cancelAnimationFrame ( animationFrameRef . current ) ;
@@ -128,11 +125,8 @@ export function Player({ music, musicList }: PlayerProps) {
128125 filter . disconnect ( ) ;
129126 } ) ;
130127 } ;
131- // オーディオアナライザーのエラーを回避するために、依存配列を空にしている
132- // eslint-disable-next-line react-hooks/exhaustive-deps
133128 } , [ ] ) ;
134129
135- // イコライザーゲインの更新
136130 useEffect ( ( ) => {
137131 if ( ! audioCtxRef . current || eqFiltersRef . current . length === 0 ) return ;
138132
@@ -141,9 +135,14 @@ export function Player({ music, musicList }: PlayerProps) {
141135 } ) ;
142136 } , [ eqGains ] ) ;
143137
144- // スペクトル視覚化(変更なし、簡略化のため省略)
145138 useEffect ( ( ) => {
146- if ( ! source || ! analyserNode || playState !== "play" || ! spectrumRef . current ) return ;
139+ if (
140+ ! source ||
141+ ! analyserNode ||
142+ playState !== "play" ||
143+ ! spectrumRef . current
144+ )
145+ return ;
147146
148147 const canvas = spectrumRef . current ;
149148 const canvasCtx = canvas . getContext ( "2d" ) ;
@@ -171,7 +170,6 @@ export function Player({ music, musicList }: PlayerProps) {
171170 const renderFrame = ( ) => {
172171 if ( ! analyserNode || ! canvasCtx ) return ;
173172
174- animationFrameRef . current = requestAnimationFrame ( renderFrame ) ;
175173 analyserNode . getByteFrequencyData ( dataArray ) ;
176174 canvasCtx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
177175
@@ -196,7 +194,12 @@ export function Player({ music, musicList }: PlayerProps) {
196194 canvasCtx . strokeStyle = `hsla(${ hue } , 100%, 50%, 0.8)` ;
197195 canvasCtx . lineWidth = barWidthCirc ;
198196 canvasCtx . fillStyle = `hsla(${ hue } , 100%, 50%, 0.8)` ;
199- canvasCtx . fillRect ( innerRadius , - barWidthCirc / 2 , barHeight , barWidthCirc ) ;
197+ canvasCtx . fillRect (
198+ innerRadius ,
199+ - barWidthCirc / 2 ,
200+ barHeight ,
201+ barWidthCirc
202+ ) ;
200203 canvasCtx . restore ( ) ;
201204 }
202205 } else {
@@ -205,16 +208,30 @@ export function Player({ music, musicList }: PlayerProps) {
205208 for ( let i = 0 ; i < bufferLength ; i ++ ) {
206209 const barHeight = ( dataArray [ i ] / 255 ) * canvas . height ;
207210 const hue = ( i / bufferLength ) * 360 ;
208- const gradient = canvasCtx . createLinearGradient ( 0 , canvas . height , 0 , 0 ) ;
211+ const gradient = canvasCtx . createLinearGradient (
212+ 0 ,
213+ canvas . height ,
214+ 0 ,
215+ 0
216+ ) ;
209217 gradient . addColorStop ( 0 , `hsla(${ hue } , 100%, 50%, 0.8)` ) ;
210218 gradient . addColorStop ( 1 , `hsla(${ hue } , 100%, 50%, 0.2)` ) ;
211219
212220 canvasCtx . fillStyle = gradient ;
213- canvasCtx . fillRect ( x , canvas . height - barHeight , barWidth - 1 , barHeight ) ;
221+ canvasCtx . fillRect (
222+ x ,
223+ canvas . height - barHeight ,
224+ barWidth - 1 ,
225+ barHeight
226+ ) ;
214227 x += barWidth ;
215228 }
216229 }
230+
231+ animationFrameRef . current = requestAnimationFrame ( renderFrame ) ;
217232 } ;
233+
234+ // 初回描画を即座に開始
218235 renderFrame ( ) ;
219236
220237 return ( ) => {
@@ -263,12 +280,18 @@ export function Player({ music, musicList }: PlayerProps) {
263280
264281 const handleSkipForward = ( ) => {
265282 if ( ! audioRef . current ) return ;
266- audioRef . current . currentTime = Math . min ( audioRef . current . currentTime + 10 , duration ) ;
283+ audioRef . current . currentTime = Math . min (
284+ audioRef . current . currentTime + 10 ,
285+ duration
286+ ) ;
267287 } ;
268288
269289 const handleSkipBackward = ( ) => {
270290 if ( ! audioRef . current ) return ;
271- audioRef . current . currentTime = Math . max ( audioRef . current . currentTime - 5 , 0 ) ;
291+ audioRef . current . currentTime = Math . max (
292+ audioRef . current . currentTime - 5 ,
293+ 0
294+ ) ;
272295 } ;
273296
274297 const handleNextTrack = ( ) => {
@@ -323,8 +346,10 @@ export function Player({ music, musicList }: PlayerProps) {
323346 window . location . href = `/music/${ trackId } ` ;
324347 } ;
325348
326- // イコライザーゲイン変更ハンドラー
327- const handleEqChange = ( index : number , e : React . ChangeEvent < HTMLInputElement > ) => {
349+ const handleEqChange = (
350+ index : number ,
351+ e : React . ChangeEvent < HTMLInputElement >
352+ ) => {
328353 const newGains = [ ...eqGains ] ;
329354 newGains [ index ] = parseFloat ( e . target . value ) ;
330355 setEqGains ( newGains ) ;
@@ -354,19 +379,39 @@ export function Player({ music, musicList }: PlayerProps) {
354379
355380 < div className = { styles [ "player-controls" ] } >
356381 < div className = { styles [ "control-buttons" ] } >
357- < button type = "button" onClick = { handlePreviousTrack } className = { styles [ "control-button" ] } >
382+ < button
383+ type = "button"
384+ onClick = { handlePreviousTrack }
385+ className = { styles [ "control-button" ] }
386+ >
358387 < PreviousMusic />
359388 </ button >
360- < button type = "button" onClick = { handleSkipBackward } className = { styles [ "control-button" ] } >
389+ < button
390+ type = "button"
391+ onClick = { handleSkipBackward }
392+ className = { styles [ "control-button" ] }
393+ >
361394 < SkipToBack />
362395 </ button >
363- < button type = "button" onClick = { handleTogglePlay } className = { styles [ "play-button" ] } >
396+ < button
397+ type = "button"
398+ onClick = { handleTogglePlay }
399+ className = { styles [ "play-button" ] }
400+ >
364401 { playState === "stop" ? < PlayButton /> : < StopButton /> }
365402 </ button >
366- < button type = "button" onClick = { handleSkipForward } className = { styles [ "control-button" ] } >
403+ < button
404+ type = "button"
405+ onClick = { handleSkipForward }
406+ className = { styles [ "control-button" ] }
407+ >
367408 < SkipToForward />
368409 </ button >
369- < button type = "button" onClick = { handleNextTrack } className = { styles [ "control-button" ] } >
410+ < button
411+ type = "button"
412+ onClick = { handleNextTrack }
413+ className = { styles [ "control-button" ] }
414+ >
370415 < NextMusic />
371416 </ button >
372417 </ div >
@@ -426,8 +471,6 @@ export function Player({ music, musicList }: PlayerProps) {
426471 < span > { formatTime ( duration ) } </ span >
427472 </ div >
428473
429- { /* イコライザーコントロール */ }
430-
431474 < details >
432475 < summary > { t ( "equalizer" ) } </ summary >
433476 < div className = { styles [ "eq-controls" ] } >
@@ -511,8 +554,12 @@ export function Player({ music, musicList }: PlayerProps) {
511554 </ div >
512555 ) }
513556 < div className = { styles [ "music-list-info" ] } >
514- < span className = { styles [ "music-list-title" ] } > { track . title } </ span >
515- < span className = { styles [ "music-list-artist" ] } > { track . artist } </ span >
557+ < span className = { styles [ "music-list-title" ] } >
558+ { track . title }
559+ </ span >
560+ < span className = { styles [ "music-list-artist" ] } >
561+ { track . artist }
562+ </ span >
516563 </ div >
517564 </ li >
518565 ) ) }
0 commit comments