{"ast":null,"code":"var _jsxFileName = \"D:\\\\Project\\\\UC_Trains_Voice\\\\react-demo\\\\src\\\\gavt\\\\GavtCali.tsx\",\n  _s = $RefreshSig$();\nimport React, { useState, useEffect, useRef } from 'react';\nimport { Link, useNavigate } from 'react-router-dom';\nimport { Divider, Steps, Breadcrumb, Button, message, Table } from 'antd';\nimport { AudioOutlined, PlayCircleOutlined, PauseCircleOutlined } from '@ant-design/icons';\nimport { useFreq } from './FreqContext';\nimport { computeLPC, addToRunningLPC, returnAndClearFormants } from './lib/lpc';\nimport { jsxDEV as _jsxDEV, Fragment as _Fragment } from \"react/jsx-dev-runtime\";\nconst stepsTitles = ['Instruction', 'Before You Start', 'Record Your Voice', 'Complete'];\nconst stepsDescriptions = [`This module will record your production of different vowel sounds so we can provide resonance targets customized to your voice. \n    If you do not want to complete this procedure right now, or if you experience any technical difficulty, \n    you can use resonance targets derived from a published reference sample of cis women or men (under the “Reference Targets” tab). \n    It should take around five minutes to complete the customization process.`, `To measure your resonance for a vowel, we want you to sustain JUST the vowel sound for about two seconds. \n    (We will give you a key word to identify the vowel, but you should produce only the vowel sound, not the whole word.) \n    Try to produce the vowel in a way that feels natural and comfortable to you. We will use our measurements from this production as a baseline for any changes in resonance. \n    Everyone's vowels will be a bit different depending on their dialect or language background. That's OK!\n    When you are ready to produce the vowel, click “start” and sustain the vowel for about two seconds, then click “stop.” `, `Follow the steps to record your voice. Click button to start, pronounce just the vowel for around 2 seconds, then click to stop. \n    Click play to listen to your recording. If you are satisfied with the recording, continue to record the next vowel.\n    If you are not satisfied, you can re-record the vowel. After you have recorded all the vowels, click “Next” to complete the calibration process`, `You're done with calibration! Now you can start practicing matching a target resonance.\n     You will later be asked what type of target you would like to match, such as slightly darker \n     or moderately brighter. If you are satisfied with the calibration result, click “Save and Back to HOME” \n     to save the calibration result and return to the GAVT home page.`];\nconst recordingSteps = [{\n  key: '/i/',\n  title: '“ee” like in “seed”'\n}, {\n  key: '/ɪ/',\n  title: '“ih” like in “hid”'\n}, {\n  key: '/ɛ/',\n  title: '“eh” like in “head”'\n}, {\n  key: '/æ/',\n  title: '“ae” like in “sad”  '\n}, {\n  key: '/ɑ/',\n  title: '“ah” like in “god”'\n}, {\n  key: '/ɔ/',\n  title: '“aw” like in “lawn”'\n}, {\n  key: '/ʌ/',\n  title: '“uh” like in “bud”'\n}, {\n  key: '/u/',\n  title: ' “ooh” like in “spoon” '\n}, {\n  key: '/ʊ/',\n  title: ' “oo” like in “good” '\n}];\nconst GavtCali = () => {\n  _s();\n  const [currentStep, setCurrentStep] = useState(0);\n  const [audioURLs, setAudioURLs] = useState({}); // Store the audio URL for each vowel\n  const [mediaRecorder, setMediaRecorder] = useState(null);\n  const [recordingStates, setRecordingStates] = useState({});\n  const [results, setResults] = useState({});\n  const activeRecordingStepKeyRef = useRef(null); // Store the key of the active recording step\n  const navigate = useNavigate();\n  const {\n    freqData,\n    updateFreqData\n  } = useFreq();\n  useEffect(() => {\n    // ----------------- Recorder -------------------\n    async function setupRecorder() {\n      try {\n        const stream = await navigator.mediaDevices.getUserMedia({\n          audio: true\n        });\n        const recorder = new MediaRecorder(stream);\n        setMediaRecorder(recorder);\n        let audioChunks = [];\n        recorder.ondataavailable = event => {\n          audioChunks.push(event.data);\n        };\n        recorder.onstop = () => {\n          const audioBlob = new Blob(audioChunks, {\n            type: 'audio/mp4'\n          });\n          const newAudioURL = URL.createObjectURL(audioBlob);\n          console.log('Audio Blob:', audioBlob, 'Audio URL:', newAudioURL);\n          const key = activeRecordingStepKeyRef.current;\n          if (key) {\n            setAudioURLs(prev => ({\n              ...prev,\n              [key]: newAudioURL\n            }));\n            console.log(`Recording for ${key} complete!`);\n          }\n          activeRecordingStepKeyRef.current = null;\n          audioChunks = [];\n        };\n      } catch (error) {\n        console.error('Error setting up the media recorder:', error);\n      }\n    }\n    setupRecorder();\n    return () => {\n      mediaRecorder === null || mediaRecorder === void 0 ? void 0 : mediaRecorder.stream.getTracks().forEach(track => track.stop());\n    };\n  }, []);\n  const toggleRecording = key => {\n    console.log(`Toggling recording for ${key}...`);\n    const isRecording = recordingStates[key];\n    if (!isRecording && mediaRecorder) {\n      mediaRecorder.start();\n      setRecordingStates(prev => ({\n        ...prev,\n        [key]: true\n      }));\n      activeRecordingStepKeyRef.current = key;\n    } else if (isRecording && mediaRecorder) {\n      mediaRecorder.stop();\n      setRecordingStates(prev => ({\n        ...prev,\n        [key]: false\n      }));\n    }\n  };\n  const handlePlayback = audioUrl => {\n    new Audio(audioUrl).play();\n  };\n  const renderRecordingControls = stepKey => {\n    const isRecording = recordingStates[stepKey];\n    const currentRecording = audioURLs[stepKey];\n    const anyRecordingActive = Object.values(recordingStates).some(state => state); // Check if any recording is active\n\n    return /*#__PURE__*/_jsxDEV(\"div\", {\n      children: currentRecording ? /*#__PURE__*/_jsxDEV(_Fragment, {\n        children: [/*#__PURE__*/_jsxDEV(Button, {\n          icon: /*#__PURE__*/_jsxDEV(PlayCircleOutlined, {}, void 0, false, {\n            fileName: _jsxFileName,\n            lineNumber: 141,\n            columnNumber: 23\n          }, this),\n          onClick: () => handlePlayback(currentRecording),\n          children: \"Play\"\n        }, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 140,\n          columnNumber: 13\n        }, this), /*#__PURE__*/_jsxDEV(Button, {\n          icon: /*#__PURE__*/_jsxDEV(AudioOutlined, {}, void 0, false, {\n            fileName: _jsxFileName,\n            lineNumber: 147,\n            columnNumber: 23\n          }, this),\n          onClick: () => {\n            console.log(`Deleting recording for ${stepKey}`);\n            setAudioURLs(prev => {\n              const newUrls = {\n                ...prev\n              };\n              delete newUrls[stepKey];\n              return newUrls;\n            });\n            setRecordingStates(prev => ({\n              ...prev,\n              [stepKey]: false\n            }));\n          },\n          children: \"Re-record\"\n        }, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 146,\n          columnNumber: 13\n        }, this)]\n      }, void 0, true) : /*#__PURE__*/_jsxDEV(Button, {\n        icon: isRecording ? /*#__PURE__*/_jsxDEV(PauseCircleOutlined, {}, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 163,\n          columnNumber: 33\n        }, this) : /*#__PURE__*/_jsxDEV(AudioOutlined, {}, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 163,\n          columnNumber: 59\n        }, this),\n        onClick: () => toggleRecording(stepKey),\n        shape: \"circle\",\n        type: isRecording ? \"default\" : \"primary\",\n        disabled: anyRecordingActive && !isRecording // Disable other recording buttons when one is active\n      }, void 0, false, {\n        fileName: _jsxFileName,\n        lineNumber: 162,\n        columnNumber: 11\n      }, this)\n    }, void 0, false, {\n      fileName: _jsxFileName,\n      lineNumber: 137,\n      columnNumber: 9\n    }, this);\n  };\n  const allRecordingsComplete = recordingSteps.every(step => audioURLs[step.key]);\n  const handleAnalyzeAll = async () => {\n    const newResults = {};\n    for (const key of Object.keys(audioURLs)) {\n      const audioUrl = audioURLs[key];\n      const response = await fetch(audioUrl);\n      const audioData = await response.arrayBuffer();\n      const audioContext = new (window.AudioContext || window.webkitAudioContext)();\n      // This is the full-length audio file\n      const audioArray = await audioContext.decodeAudioData(audioData);\n\n      // This is the average F2 formant frequency for the audio file.\n      const formant = calculateF2(audioArray);\n      newResults[key] = formant !== null ? formant : 0;\n    }\n    setResults(newResults);\n    console.log('Analysis complete:', newResults);\n    localStorage.setItem('latestTestResult', JSON.stringify(newResults));\n    setCurrentStep(currentStep + 1);\n  };\n  const calculateF2 = audioBuffer => {\n    // `audioBuffer` and this type are the full-length audio file, not the chunk.\n    const channelData = audioBuffer.getChannelData(0);\n    const sampleRate = audioBuffer.sampleRate;\n\n    // Threshold for detecting voiced sound. Should be discussed with the team.\n    const threshold = 0.1;\n\n    // For the voice detection, find the start and end timestamps of the voiced sound\n    let startTime = null;\n    let endTime = null;\n    for (let i = 0; i < channelData.length; i++) {\n      if (Math.abs(channelData[i]) > threshold) {\n        if (startTime === null) {\n          startTime = i / sampleRate; // Convert sample index to time\n        }\n        endTime = i / sampleRate; // Convert sample index to time\n      }\n    }\n    if (startTime !== null && endTime !== null) {\n      // console.log(`Voiced sound detected from ${startTime} to ${endTime} in ${audioBuffer}`);\n      const startSample = Math.floor(startTime * sampleRate);\n      const endSample = Math.ceil(endTime * sampleRate);\n\n      // Extract the voiced sound segment\n      const soundSegment = channelData.slice(startSample, endSample);\n      const chunkSize = 512;\n\n      // Split the voiced sound segment into chunks and analyze each chunk\n      for (let i = 0; i < soundSegment.length; i += chunkSize) {\n        const chunk = soundSegment.slice(i, i + chunkSize);\n\n        // Skip the last chunk if it's too short\n        if (chunk.length < chunkSize) continue;\n\n        // Compute LPC coefficients for the chunk\n        const lpcCoefficients = computeLPC(chunk);\n\n        // Accumulate the LPC coefficients for the voiced sound segment\n        addToRunningLPC(lpcCoefficients);\n      }\n      const f2 = returnAndClearFormants(true);\n      return f2;\n    }\n    return null;\n  };\n\n  // ----------------- Draw Table -------------------\n\n  const columns = [{\n    title: 'Vowel',\n    dataIndex: 'vowel',\n    key: 'vowel'\n  }, {\n    title: 'Result',\n    dataIndex: 'result',\n    key: 'result'\n  }];\n  const dataSource = Object.keys(results).map(key => ({\n    key,\n    vowel: key,\n    result: results[key]\n  }));\n\n  // ----------------- Handle Save -------------------\n  const handleSaveAndReturn = () => {\n    const latestTestResult = JSON.parse(localStorage.getItem('latestTestResult') || '{}');\n    console.log(`Latest test result: ${latestTestResult}`);\n    if (latestTestResult) {\n      // localStorage.setItem('caliBaseline', JSON.stringify(latestTestResult));\n      const updates = {\n        caliBaseline: latestTestResult\n      };\n      updateFreqData(updates);\n      message.success('Calibration baseline updated successfully! Will return to Gavt Home in 3 seconds...');\n    }\n    setTimeout(() => navigate('/gavt'), 3000);\n    ;\n  };\n\n  // ----------------- Step Setting -------------------\n  const renderStepContent = () => {\n    if (currentStep === 2) {\n      return /*#__PURE__*/_jsxDEV(\"div\", {\n        children: [/*#__PURE__*/_jsxDEV(\"p\", {\n          children: stepsDescriptions[currentStep]\n        }, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 286,\n          columnNumber: 13\n        }, this), /*#__PURE__*/_jsxDEV(Steps, {\n          current: -1,\n          direction: \"vertical\",\n          children: recordingSteps.map(step => /*#__PURE__*/_jsxDEV(Steps.Step, {\n            title: step.title,\n            description: renderRecordingControls(step.key)\n          }, step.key, false, {\n            fileName: _jsxFileName,\n            lineNumber: 289,\n            columnNumber: 15\n          }, this))\n        }, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 287,\n          columnNumber: 13\n        }, this)]\n      }, void 0, true, {\n        fileName: _jsxFileName,\n        lineNumber: 285,\n        columnNumber: 9\n      }, this);\n    } else {\n      return /*#__PURE__*/_jsxDEV(\"p\", {\n        children: stepsDescriptions[currentStep]\n      }, void 0, false, {\n        fileName: _jsxFileName,\n        lineNumber: 295,\n        columnNumber: 14\n      }, this);\n    }\n  };\n  return /*#__PURE__*/_jsxDEV(\"div\", {\n    style: {\n      display: 'flex',\n      flexDirection: 'column',\n      alignItems: 'center',\n      marginTop: '20px',\n      width: '80%'\n    },\n    children: [/*#__PURE__*/_jsxDEV(Breadcrumb, {\n      style: {\n        marginBottom: '20px',\n        alignSelf: 'start'\n      },\n      items: [{\n        title: /*#__PURE__*/_jsxDEV(Link, {\n          to: \"/gavt\",\n          children: \"Gavt Home\"\n        }, void 0, false, {\n          fileName: _jsxFileName,\n          lineNumber: 304,\n          columnNumber: 25\n        }, this)\n      }, {\n        title: 'Calibration'\n      }]\n    }, void 0, false, {\n      fileName: _jsxFileName,\n      lineNumber: 301,\n      columnNumber: 9\n    }, this), /*#__PURE__*/_jsxDEV(Steps, {\n      progressDot: true,\n      current: currentStep,\n      items: stepsTitles.map((title, index) => ({\n        key: index.toString(),\n        title\n      }))\n    }, void 0, false, {\n      fileName: _jsxFileName,\n      lineNumber: 308,\n      columnNumber: 9\n    }, this), /*#__PURE__*/_jsxDEV(Divider, {}, void 0, false, {\n      fileName: _jsxFileName,\n      lineNumber: 310,\n      columnNumber: 9\n    }, this), renderStepContent(), currentStep === 3 && /*#__PURE__*/_jsxDEV(Table, {\n      dataSource: dataSource,\n      columns: columns,\n      pagination: false\n    }, void 0, false, {\n      fileName: _jsxFileName,\n      lineNumber: 314,\n      columnNumber: 13\n    }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n      style: {\n        marginTop: '20px'\n      },\n      children: [/*#__PURE__*/_jsxDEV(Button, {\n        disabled: currentStep === 0,\n        onClick: () => setCurrentStep(currentStep - 1),\n        children: \"Previous\"\n      }, void 0, false, {\n        fileName: _jsxFileName,\n        lineNumber: 317,\n        columnNumber: 13\n      }, this), /*#__PURE__*/_jsxDEV(Button, {\n        type: \"primary\",\n        onClick: () => {\n          if (currentStep === 2) {\n            handleAnalyzeAll();\n          } else if (currentStep === 3) {\n            handleSaveAndReturn();\n          } else {\n            setCurrentStep(currentStep + 1);\n          }\n        },\n        disabled: currentStep === 2 && !allRecordingsComplete,\n        style: {\n          marginLeft: \"20px\"\n        },\n        children: currentStep === stepsTitles.length - 1 ? 'Save and Back to HOME' : 'Next'\n      }, void 0, false, {\n        fileName: _jsxFileName,\n        lineNumber: 318,\n        columnNumber: 13\n      }, this)]\n    }, void 0, true, {\n      fileName: _jsxFileName,\n      lineNumber: 316,\n      columnNumber: 9\n    }, this)]\n  }, void 0, true, {\n    fileName: _jsxFileName,\n    lineNumber: 300,\n    columnNumber: 5\n  }, this);\n};\n_s(GavtCali, \"d0BeNjFKKWdnuLTX/y72Y/xE3Lg=\", false, function () {\n  return [useNavigate, useFreq];\n});\n_c = GavtCali;\nexport default GavtCali;\nvar _c;\n$RefreshReg$(_c, \"GavtCali\");","map":{"version":3,"names":["React","useState","useEffect","useRef","Link","useNavigate","Divider","Steps","Breadcrumb","Button","message","Table","AudioOutlined","PlayCircleOutlined","PauseCircleOutlined","useFreq","computeLPC","addToRunningLPC","returnAndClearFormants","jsxDEV","_jsxDEV","Fragment","_Fragment","stepsTitles","stepsDescriptions","recordingSteps","key","title","GavtCali","_s","currentStep","setCurrentStep","audioURLs","setAudioURLs","mediaRecorder","setMediaRecorder","recordingStates","setRecordingStates","results","setResults","activeRecordingStepKeyRef","navigate","freqData","updateFreqData","setupRecorder","stream","navigator","mediaDevices","getUserMedia","audio","recorder","MediaRecorder","audioChunks","ondataavailable","event","push","data","onstop","audioBlob","Blob","type","newAudioURL","URL","createObjectURL","console","log","current","prev","error","getTracks","forEach","track","stop","toggleRecording","isRecording","start","handlePlayback","audioUrl","Audio","play","renderRecordingControls","stepKey","currentRecording","anyRecordingActive","Object","values","some","state","children","icon","fileName","_jsxFileName","lineNumber","columnNumber","onClick","newUrls","shape","disabled","allRecordingsComplete","every","step","handleAnalyzeAll","newResults","keys","response","fetch","audioData","arrayBuffer","audioContext","window","AudioContext","webkitAudioContext","audioArray","decodeAudioData","formant","calculateF2","localStorage","setItem","JSON","stringify","audioBuffer","channelData","getChannelData","sampleRate","threshold","startTime","endTime","i","length","Math","abs","startSample","floor","endSample","ceil","soundSegment","slice","chunkSize","chunk","lpcCoefficients","f2","columns","dataIndex","dataSource","map","vowel","result","handleSaveAndReturn","latestTestResult","parse","getItem","updates","caliBaseline","success","setTimeout","renderStepContent","direction","Step","description","style","display","flexDirection","alignItems","marginTop","width","marginBottom","alignSelf","items","to","progressDot","index","toString","pagination","marginLeft","_c","$RefreshReg$"],"sources":["D:/Project/UC_Trains_Voice/react-demo/src/gavt/GavtCali.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\r\nimport { Link, useNavigate } from 'react-router-dom';\r\n\r\nimport { Divider, Steps, Breadcrumb, Button, message, Table } from 'antd';\r\nimport { AudioOutlined, PlayCircleOutlined, PauseCircleOutlined } from '@ant-design/icons';\r\n\r\nimport { useFreq } from './FreqContext';\r\nimport { computeLPC, extractFormants, durandKerner, addToRunningLPC, returnAndClearFormants} from './lib/lpc';\r\n\r\nconst stepsTitles = [\r\n  'Instruction',\r\n  'Before You Start',\r\n  'Record Your Voice',\r\n  'Complete'\r\n];\r\n\r\nconst stepsDescriptions = [\r\n    `This module will record your production of different vowel sounds so we can provide resonance targets customized to your voice. \r\n    If you do not want to complete this procedure right now, or if you experience any technical difficulty, \r\n    you can use resonance targets derived from a published reference sample of cis women or men (under the “Reference Targets” tab). \r\n    It should take around five minutes to complete the customization process.`,\r\n\r\n    `To measure your resonance for a vowel, we want you to sustain JUST the vowel sound for about two seconds. \r\n    (We will give you a key word to identify the vowel, but you should produce only the vowel sound, not the whole word.) \r\n    Try to produce the vowel in a way that feels natural and comfortable to you. We will use our measurements from this production as a baseline for any changes in resonance. \r\n    Everyone's vowels will be a bit different depending on their dialect or language background. That's OK!\r\n    When you are ready to produce the vowel, click “start” and sustain the vowel for about two seconds, then click “stop.” `,\r\n\r\n    `Follow the steps to record your voice. Click button to start, pronounce just the vowel for around 2 seconds, then click to stop. \r\n    Click play to listen to your recording. If you are satisfied with the recording, continue to record the next vowel.\r\n    If you are not satisfied, you can re-record the vowel. After you have recorded all the vowels, click “Next” to complete the calibration process`,\r\n\r\n    `You're done with calibration! Now you can start practicing matching a target resonance.\r\n     You will later be asked what type of target you would like to match, such as slightly darker \r\n     or moderately brighter. If you are satisfied with the calibration result, click “Save and Back to HOME” \r\n     to save the calibration result and return to the GAVT home page.`\r\n];\r\n\r\nconst recordingSteps = [\r\n  { key: '/i/', title: '“ee” like in “seed”' },\r\n  { key: '/ɪ/', title: '“ih” like in “hid”' },\r\n  { key: '/ɛ/', title: '“eh” like in “head”' },\r\n  { key: '/æ/', title: '“ae” like in “sad”  ' },\r\n  { key: '/ɑ/', title: '“ah” like in “god”' },\r\n  { key: '/ɔ/', title: '“aw” like in “lawn”' },\r\n  { key: '/ʌ/', title: '“uh” like in “bud”' },\r\n  { key: '/u/', title: ' “ooh” like in “spoon” ' },\r\n  { key: '/ʊ/', title: ' “oo” like in “good” ' }\r\n];\r\n\r\ndeclare global {\r\n  interface Window {\r\n    webkitAudioContext: typeof AudioContext;\r\n  }\r\n}\r\n\r\ninterface AudioURLs {\r\n  [key: string]: string;\r\n}\r\n\r\ninterface AnalysisResults {\r\n    [key: string]: number;\r\n}\r\n\r\nconst GavtCali: React.FC = () => {\r\n  const [currentStep, setCurrentStep] = useState(0);\r\n  const [audioURLs, setAudioURLs] = useState<AudioURLs>({}); // Store the audio URL for each vowel\r\n  const [mediaRecorder, setMediaRecorder] = useState<MediaRecorder | null>(null);\r\n  const [recordingStates, setRecordingStates] = useState<Record<string, boolean>>({});\r\n  const [results, setResults] = useState<AnalysisResults>({});\r\n  const activeRecordingStepKeyRef = useRef<string | null>(null); // Store the key of the active recording step\r\n  const navigate = useNavigate();\r\n  const { freqData, updateFreqData } = useFreq();\r\n\r\n  useEffect(() => {\r\n    // ----------------- Recorder -------------------\r\n    async function setupRecorder() {\r\n      try {\r\n        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n        const recorder = new MediaRecorder(stream);\r\n        setMediaRecorder(recorder);\r\n  \r\n        let audioChunks: BlobPart[] = [];\r\n  \r\n        recorder.ondataavailable = (event: BlobEvent) => {\r\n          audioChunks.push(event.data);\r\n        };\r\n  \r\n        recorder.onstop = () => {\r\n            const audioBlob = new Blob(audioChunks, { type: 'audio/mp4' });\r\n            const newAudioURL = URL.createObjectURL(audioBlob);\r\n            console.log('Audio Blob:', audioBlob, 'Audio URL:', newAudioURL);\r\n            const key = activeRecordingStepKeyRef.current;\r\n            if (key) {\r\n              setAudioURLs(prev => ({ ...prev, [key]: newAudioURL }));\r\n              console.log(`Recording for ${key} complete!`);\r\n            }\r\n            activeRecordingStepKeyRef.current = null;\r\n            audioChunks = [];\r\n          };\r\n      } catch (error) {\r\n        console.error('Error setting up the media recorder:', error);\r\n      }\r\n    }\r\n  \r\n    setupRecorder();\r\n  \r\n    return () => {\r\n      mediaRecorder?.stream.getTracks().forEach(track => track.stop());\r\n    };\r\n  }, []); \r\n\r\n  const toggleRecording = (key: string) => {\r\n    console.log(`Toggling recording for ${key}...`)\r\n    const isRecording = recordingStates[key];\r\n\r\n    if (!isRecording && mediaRecorder) {\r\n      mediaRecorder.start();\r\n      setRecordingStates(prev => ({ ...prev, [key]: true }));\r\n      activeRecordingStepKeyRef.current = key;\r\n    } else if (isRecording && mediaRecorder) {\r\n      mediaRecorder.stop();\r\n      setRecordingStates(prev => ({ ...prev, [key]: false }));\r\n    }\r\n  };\r\n\r\n  const handlePlayback = (audioUrl: string) => {\r\n    new Audio(audioUrl).play();\r\n  };\r\n\r\n  const renderRecordingControls = (stepKey: string) => {\r\n    const isRecording = recordingStates[stepKey];\r\n    const currentRecording = audioURLs[stepKey];\r\n    const anyRecordingActive = Object.values(recordingStates).some(state => state); // Check if any recording is active\r\n\r\n    return (\r\n        <div>\r\n        {currentRecording ? (\r\n          <>\r\n            <Button\r\n                icon={<PlayCircleOutlined />}\r\n                onClick={() => handlePlayback(currentRecording)}\r\n            >\r\n              Play\r\n            </Button>\r\n            <Button\r\n                icon={<AudioOutlined />}\r\n                onClick={() => {\r\n                    console.log(`Deleting recording for ${stepKey}`);\r\n                    setAudioURLs(prev => {\r\n                        const newUrls = { ...prev };\r\n                        delete newUrls[stepKey];\r\n                        return newUrls;\r\n                    });\r\n                    setRecordingStates(prev => ({ ...prev, [stepKey]: false }));\r\n                }}\r\n            >\r\n              Re-record\r\n            </Button>\r\n          </>\r\n        ) : (\r\n          <Button\r\n            icon={isRecording ? <PauseCircleOutlined /> : <AudioOutlined />}\r\n            onClick={() => toggleRecording(stepKey)}\r\n            shape='circle'\r\n            type={isRecording ? \"default\" : \"primary\"}\r\n            disabled={anyRecordingActive && !isRecording} // Disable other recording buttons when one is active\r\n          >\r\n          </Button>\r\n        )}\r\n      </div>\r\n    );\r\n  };\r\n\r\n  const allRecordingsComplete = recordingSteps.every(step => audioURLs[step.key])\r\n\r\n  const handleAnalyzeAll = async () => {\r\n    const newResults: AnalysisResults = {};\r\n    for (const key of Object.keys(audioURLs)) {\r\n      const audioUrl = audioURLs[key];\r\n      const response = await fetch(audioUrl);\r\n      const audioData = await response.arrayBuffer();\r\n      const audioContext = new (window.AudioContext || window.webkitAudioContext)();\r\n      // This is the full-length audio file\r\n      const audioArray = await audioContext.decodeAudioData(audioData);\r\n\r\n      // This is the average F2 formant frequency for the audio file.\r\n      const formant = calculateF2(audioArray);\r\n      newResults[key] = formant !== null ? formant : 0;\r\n    }\r\n    setResults(newResults);\r\n    console.log('Analysis complete:', newResults);\r\n    localStorage.setItem('latestTestResult', JSON.stringify(newResults));\r\n    setCurrentStep(currentStep + 1);\r\n  };\r\n\r\n  const calculateF2 = (audioBuffer: AudioBuffer): number | null => {\r\n    // `audioBuffer` and this type are the full-length audio file, not the chunk.\r\n    const channelData = audioBuffer.getChannelData(0);\r\n    const sampleRate = audioBuffer.sampleRate;\r\n\r\n    // Threshold for detecting voiced sound. Should be discussed with the team.\r\n    const threshold = 0.1; \r\n\r\n    // For the voice detection, find the start and end timestamps of the voiced sound\r\n    let startTime: number | null = null;\r\n    let endTime: number | null = null;\r\n\r\n    for (let i = 0; i < channelData.length; i++) {\r\n      if (Math.abs(channelData[i]) > threshold) {\r\n          if (startTime === null) {\r\n              startTime = i / sampleRate; // Convert sample index to time\r\n          }\r\n          endTime = i / sampleRate; // Convert sample index to time\r\n      }\r\n    }\r\n\r\n    if (startTime !== null && endTime !== null) {\r\n      // console.log(`Voiced sound detected from ${startTime} to ${endTime} in ${audioBuffer}`);\r\n      const startSample = Math.floor(startTime * sampleRate);\r\n      const endSample = Math.ceil(endTime * sampleRate);\r\n\r\n      // Extract the voiced sound segment\r\n      const soundSegment = channelData.slice(startSample, endSample);\r\n\r\n      const chunkSize = 512;\r\n\r\n      // Split the voiced sound segment into chunks and analyze each chunk\r\n      for (let i = 0; i < soundSegment.length; i += chunkSize) {\r\n\r\n        const chunk = soundSegment.slice(i, i + chunkSize);\r\n\r\n        // Skip the last chunk if it's too short\r\n        if (chunk.length < chunkSize) continue;\r\n\r\n        // Compute LPC coefficients for the chunk\r\n        const lpcCoefficients = computeLPC(chunk);\r\n\r\n        // Accumulate the LPC coefficients for the voiced sound segment\r\n        addToRunningLPC(lpcCoefficients);\r\n      }\r\n\r\n      const f2 = returnAndClearFormants(true);\r\n      return f2;\r\n    }\r\n\r\n    return null;\r\n\r\n  }\r\n\r\n  // ----------------- Draw Table -------------------\r\n\r\n  const columns = [\r\n    { title: 'Vowel', dataIndex: 'vowel', key: 'vowel' },\r\n    { title: 'Result', dataIndex: 'result', key: 'result' }\r\n  ];\r\n\r\n  const dataSource = Object.keys(results).map(key => ({\r\n    key,\r\n    vowel: key,\r\n    result: results[key]\r\n  }));\r\n\r\n  // ----------------- Handle Save -------------------\r\n  const handleSaveAndReturn = () => {\r\n    const latestTestResult = JSON.parse(localStorage.getItem('latestTestResult') || '{}');\r\n    console.log(`Latest test result: ${latestTestResult}`);\r\n    if ( latestTestResult ) {\r\n        // localStorage.setItem('caliBaseline', JSON.stringify(latestTestResult));\r\n        const updates = {\r\n          caliBaseline: latestTestResult\r\n        }\r\n        updateFreqData(updates);\r\n        message.success('Calibration baseline updated successfully! Will return to Gavt Home in 3 seconds...');\r\n    }\r\n    setTimeout(()=>navigate('/gavt'), 3000);\r\n    ;\r\n  };\r\n\r\n\r\n  // ----------------- Step Setting -------------------\r\n  const renderStepContent = () => {\r\n    if (currentStep === 2) {\r\n      return (    \r\n        <div>\r\n            <p>{stepsDescriptions[currentStep]}</p>\r\n            <Steps current={-1} direction=\"vertical\">\r\n            {recordingSteps.map(step => (\r\n              <Steps.Step key={step.key} title={step.title} description={renderRecordingControls(step.key)} />\r\n            ))}\r\n          </Steps>\r\n        </div>\r\n      );\r\n    } else {\r\n      return <p>{stepsDescriptions[currentStep]}</p>;\r\n    }\r\n  };\r\n\r\n  return (\r\n    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '20px', width: '80%' }}>\r\n        <Breadcrumb\r\n            style={{ marginBottom: '20px', alignSelf: 'start' }}\r\n            items={[\r\n                {title: <Link to=\"/gavt\">Gavt Home</Link>,},\r\n                {title:'Calibration',}\r\n            ]}\r\n        />\r\n        <Steps progressDot current={currentStep} items={stepsTitles.map((title, index) => ({ key: index.toString(), title }))} />\r\n\r\n        <Divider />\r\n\r\n        {renderStepContent()}\r\n        {currentStep === 3 && (\r\n            <Table dataSource={dataSource} columns={columns} pagination={false}/>\r\n        )}\r\n        <div style={{ marginTop: '20px' }}>\r\n            <Button disabled={currentStep === 0} onClick={() => setCurrentStep(currentStep - 1)}>Previous</Button>\r\n            <Button\r\n                type=\"primary\"\r\n                onClick={() => {\r\n                    if (currentStep === 2) {\r\n                        handleAnalyzeAll();\r\n                    } else if (currentStep === 3) {\r\n                        handleSaveAndReturn();\r\n                    } else {\r\n                        setCurrentStep(currentStep + 1);\r\n                    }}\r\n                }\r\n                disabled={ currentStep === 2 && !allRecordingsComplete }\r\n                style={{ marginLeft: \"20px\" }}>\r\n                {currentStep === stepsTitles.length - 1 ? 'Save and Back to HOME' : 'Next'}\r\n            </Button>\r\n        </div>\r\n    </div>\r\n  );\r\n};\r\n\r\nexport default GavtCali;\r\n"],"mappings":"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","ignoreList":[]},"metadata":{},"sourceType":"module","externalDependencies":[]}