@@ -72,49 +72,46 @@ const Sonogram: FC<{ audio: AudioBuffer }> = ({ audio }) => {
72
72
const canvas = useRef < HTMLCanvasElement > ( null ) ;
73
73
74
74
const fttData = useMemo ( ( ) => {
75
- const fftSize = 1024 ; // Ensure this is a power of two
75
+ const fftSize = 512 ; // Ensure this is a power of two
76
76
const fft = new FFT ( fftSize ) ;
77
77
const data = audio . getChannelData ( 0 ) ;
78
78
79
79
const chunks = Math . floor ( audio . length / fftSize ) ;
80
80
const target = new Float32Array ( fftSize * chunks ) ;
81
81
82
- const truncatedData = new Array ( fftSize ) ;
82
+ const sample = new Array ( fftSize ) ;
83
83
const out = fft . createComplexArray ( ) ;
84
84
85
- let min = Infinity ;
86
85
let max = - Infinity ;
87
86
88
87
for ( let i = 0 ; i < chunks ; i ++ ) {
89
88
const offset = i * fftSize ;
90
- for ( let i = 0 ; i < truncatedData . length ; i ++ )
91
- truncatedData [ i ] = data [ i + offset ] ;
92
- fft . realTransform ( out , truncatedData ) ;
89
+ for ( let i = 0 ; i < sample . length ; i ++ ) sample [ i ] = data [ i + offset ] ;
90
+ fft . realTransform ( out , sample ) ;
93
91
94
92
for ( let j = 0 ; j < fftSize ; j ++ ) {
95
- target [ i * fftSize + j ] = out [ j ] ;
93
+ target [ i * fftSize + j ] = Math . abs ( out [ j ] ) ;
96
94
max = Math . max ( max , target [ i * fftSize + j ] ) ;
97
- min = Math . min ( min , target [ i * fftSize + j ] ) ;
98
95
}
99
96
}
100
97
98
+ max = max / 4 ;
99
+
101
100
const image = new ImageData ( chunks , fftSize ) ;
102
101
103
102
for ( let i = 0 ; i < chunks ; i ++ ) {
104
103
for ( let j = 0 ; j < fftSize ; j ++ ) {
105
104
const idx = j * chunks + i ;
106
- const value = Math . abs ( target [ i * fftSize + j ] ) ;
107
-
108
- const scaledValue = value * 0.1 ;
105
+ const value = target [ i * fftSize + j ] ;
109
106
110
- const clamped = Math . max ( Math . min ( scaledValue , 1 ) , 0 ) ;
107
+ const scaledValue = Math . pow ( value / max , 0.3 ) ; // Apply a power scale
111
108
112
- const col = hslToRgb ( clamped / 2 , 0.9 , 0.5 ) ;
109
+ const [ r , g , b , a ] = valueToColor ( scaledValue ) ;
113
110
114
- image . data [ idx * 4 ] = col [ 0 ] ;
115
- image . data [ idx * 4 + 1 ] = col [ 1 ] ;
116
- image . data [ idx * 4 + 2 ] = col [ 2 ] ;
117
- image . data [ idx * 4 + 3 ] = clamped * 255 ;
111
+ image . data [ idx * 4 ] = r ;
112
+ image . data [ idx * 4 + 1 ] = g ;
113
+ image . data [ idx * 4 + 2 ] = b ;
114
+ image . data [ idx * 4 + 3 ] = a ;
118
115
}
119
116
}
120
117
@@ -134,28 +131,10 @@ const Sonogram: FC<{ audio: AudioBuffer }> = ({ audio }) => {
134
131
return < canvas ref = { canvas } className = { styles . waveform } /> ;
135
132
} ;
136
133
137
- function hslToRgb ( h : number , s : number , l : number ) {
138
- let r : number , g : number , b : number ;
139
-
140
- if ( s == 0 ) {
141
- r = g = b = l ; // achromatic
142
- } else {
143
- function hue2rgb ( p : number , q : number , t : number ) {
144
- if ( t < 0 ) t += 1 ;
145
- if ( t > 1 ) t -= 1 ;
146
- if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t ;
147
- if ( t < 1 / 2 ) return q ;
148
- if ( t < 2 / 3 ) return p + ( q - p ) * ( 2 / 3 - t ) * 6 ;
149
- return p ;
150
- }
151
-
152
- const q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s ;
153
- const p = 2 * l - q ;
154
-
155
- r = hue2rgb ( p , q , h + 1 / 3 ) ;
156
- g = hue2rgb ( p , q , h ) ;
157
- b = hue2rgb ( p , q , h - 1 / 3 ) ;
158
- }
159
-
160
- return [ r * 255 , g * 255 , b * 255 ] ;
134
+ function valueToColor ( value : number ) {
135
+ const r = value < 0.5 ? 0 : 255 * ( value - 0.5 ) * 2 ;
136
+ const g = value < 0.5 ? 255 * value * 2 : 255 * ( 1 - value ) * 2 ;
137
+ const b = value < 0.5 ? 255 * ( 1 - value * 2 ) : 0 ;
138
+ const a = value > 0.2 ? 255 : value * 5 * 255 ;
139
+ return [ r , g , b , a ] ;
161
140
}
0 commit comments