@@ -56,9 +56,13 @@ function startRecording() {
5656 time ++ ;
5757 } , 1000 ) ;
5858 } , 3000 ) ;
59+
5960 let audioContext = new window . AudioContext ( ) ;
6061 gumStream = stream ;
6162 input = audioContext . createMediaStreamSource ( stream ) ;
63+
64+ startMicVisualizer ( stream , audioContext ) ;
65+
6266 recorder = new WebAudioRecorder ( input , {
6367 workerDir : "/static/js/libraries/WebAudioRecorder.js/" ,
6468 encoding : "mp3" ,
@@ -126,3 +130,91 @@ $(document).ready(function () {
126130 return "Do you really want to close?" ;
127131 } ;
128132} ) ;
133+
134+ function startMicVisualizer ( stream , audioContext ) {
135+ const canvasElement = document . querySelector ( "#mic-visualizer-canvas" ) ;
136+ const canvasVisializerCxt = canvasElement . getContext ( "2d" ) ;
137+ const volumeLevelElement = document . querySelector ( "#volume-level-box" ) ;
138+
139+ const audioStream = audioContext . createMediaStreamSource ( stream ) ;
140+ const analyser = audioContext . createAnalyser ( ) ;
141+ const fftSize = 128 ;
142+
143+ analyser . fftSize = fftSize ;
144+ audioStream . connect ( analyser ) ;
145+
146+ const bufferLength = analyser . frequencyBinCount ;
147+
148+ let frequencyArray = new Uint8Array ( bufferLength ) ;
149+
150+ const setUpCanvas = function ( ) {
151+ canvasVisializerCxt . fillStyle = "rgb(255 255 255)" ;
152+ canvasVisializerCxt . fillRect ( 0 , 0 , canvasElement . width , canvasElement . height ) ;
153+
154+ canvasVisializerCxt . lineWidth = 1.5 ;
155+ canvasVisializerCxt . strokeStyle = "rgb(0 0 0)" ;
156+
157+ canvasVisializerCxt . beginPath ( ) ;
158+ }
159+
160+ const doDraw = function ( ) {
161+ requestAnimationFrame ( doDraw ) ;
162+
163+ setUpCanvas ( ) ;
164+
165+ const sliceWidth = ( canvasElement . width * 1.0 ) / ( bufferLength + 1 ) ;
166+
167+ canvasVisializerCxt . moveTo ( 0 , canvasElement . height / 2 ) ;
168+
169+ let x = 0 + sliceWidth ;
170+
171+ analyser . getByteFrequencyData ( frequencyArray ) ;
172+
173+ let direction = 1 ;
174+
175+ for ( let i = 0 ; i < bufferLength ; i ++ ) {
176+ const v = frequencyArray [ i ] / ( canvasElement . height * 2 ) ;
177+ const y = ( v * canvasElement . height ) / 2 ;
178+
179+ canvasVisializerCxt . lineTo ( x , canvasElement . height / 2 + y * direction ) ;
180+
181+ x += sliceWidth ;
182+ direction *= - 1 ;
183+ }
184+
185+ canvasVisializerCxt . lineTo ( canvasElement . width , canvasElement . height / 2 ) ;
186+ canvasVisializerCxt . stroke ( ) ;
187+ }
188+
189+ const showVolume = function ( ) {
190+ setTimeout ( showVolume , 500 ) ;
191+
192+ analyser . getByteFrequencyData ( frequencyArray ) ;
193+ let total = 0
194+
195+ for ( let i = 0 ; i < bufferLength ; i ++ ) {
196+ let x = frequencyArray [ i ] ;
197+ total += x * x ;
198+ }
199+
200+ const rms = Math . sqrt ( total / bufferLength ) ;
201+ let db = 20 * ( Math . log ( rms ) / Math . log ( 10 ) ) ;
202+
203+ db = Math . max ( db , 0 ) ;
204+
205+ let status = "" ;
206+
207+ // добавить эти поля в локаль
208+ if ( db == 0 ) {
209+ status = "Ваш микрофон не работает" ;
210+ }
211+ else if ( db <= 35 ) { // или другое значение/проверка (например только по средним частотам)
212+ status = "Пожалуйста, говорите громче" ; // проверить, что пауза достаточно продолжительна
213+ }
214+
215+ volumeLevelElement . innerHTML = `db: ${ db . toFixed ( 1 ) } ${ status } ` ;
216+ }
217+
218+ doDraw ( ) ;
219+ showVolume ( ) ;
220+ }
0 commit comments