[{"data":1,"prerenderedAt":549},["ShallowReactive",2],{"navigation_docs":3,"-reference-composables":47,"-reference-composables-surround":546},[4,26],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Data modes","\u002Fgetting-started\u002Fdata-modes","1.getting-started\u002F3.data-modes","i-lucide-git-fork",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Reference","i-lucide-book-open","\u002Freference","2.reference",[32,37,42],{"title":33,"path":34,"stem":35,"icon":36},"Props, events & methods","\u002Freference\u002Fprops","2.reference\u002F1.props","i-lucide-sliders-horizontal",{"title":38,"path":39,"stem":40,"icon":41},"Gradients","\u002Freference\u002Fgradients","2.reference\u002F2.gradients","i-lucide-palette",{"title":43,"path":44,"stem":45,"icon":46},"Composables & protocol","\u002Freference\u002Fcomposables","2.reference\u002F3.composables","i-lucide-plug",{"id":48,"title":43,"body":49,"description":539,"extension":540,"links":541,"meta":542,"navigation":543,"path":44,"seo":544,"stem":45,"__hash__":545},"docs\u002F2.reference\u002F3.composables.md",{"type":50,"value":51,"toc":532},"minimark",[52,61,68,71,236,242,264,373,380,384,393,398,476,481,501,504,509,528],[53,54,55,56,60],"p",{},"The data pipelines are also available standalone, if you want to drive your own rendering\nor combine them with ",[57,58,59],"code",{},"mode=\"external\"",".",[62,63,65],"h2",{"id":64},"uselocalaudiooptions",[57,66,67],{},"useLocalAudio(options?)",[53,69,70],{},"Captures mic or display audio and runs the WASM FFT.",[72,73,78],"pre",{"className":74,"code":75,"language":76,"meta":77,"style":77},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const {\n  fftData,        \u002F\u002F Ref\u003CUint8Array> — magnitudes 0–255\n  isActive, sourceType, devices, activeDeviceId,\n  getDevices,     \u002F\u002F () => Promise\u003CAudioDevice[]>\n  start,          \u002F\u002F (deviceId?) => Promise\u003Cvoid>  — microphone\n  startDisplay,   \u002F\u002F () => Promise\u003Cvoid>           — tab\u002Fsystem audio\n  stop\n} = useLocalAudio({ fftSize: 2048, bins: 80, startFreq: 100, endFreq: 18000 })\n","ts","",[57,79,80,93,107,131,142,153,164,170],{"__ignoreMap":77},[81,82,85,89],"span",{"class":83,"line":84},"line",1,[81,86,88],{"class":87},"spNyl","const",[81,90,92],{"class":91},"sMK4o"," {\n",[81,94,96,100,103],{"class":83,"line":95},2,[81,97,99],{"class":98},"sTEyZ","  fftData",[81,101,102],{"class":91},",",[81,104,106],{"class":105},"sHwdD","        \u002F\u002F Ref\u003CUint8Array> — magnitudes 0–255\n",[81,108,110,113,115,118,120,123,125,128],{"class":83,"line":109},3,[81,111,112],{"class":98},"  isActive",[81,114,102],{"class":91},[81,116,117],{"class":98}," sourceType",[81,119,102],{"class":91},[81,121,122],{"class":98}," devices",[81,124,102],{"class":91},[81,126,127],{"class":98}," activeDeviceId",[81,129,130],{"class":91},",\n",[81,132,134,137,139],{"class":83,"line":133},4,[81,135,136],{"class":98},"  getDevices",[81,138,102],{"class":91},[81,140,141],{"class":105},"     \u002F\u002F () => Promise\u003CAudioDevice[]>\n",[81,143,145,148,150],{"class":83,"line":144},5,[81,146,147],{"class":98},"  start",[81,149,102],{"class":91},[81,151,152],{"class":105},"          \u002F\u002F (deviceId?) => Promise\u003Cvoid>  — microphone\n",[81,154,156,159,161],{"class":83,"line":155},6,[81,157,158],{"class":98},"  startDisplay",[81,160,102],{"class":91},[81,162,163],{"class":105},"   \u002F\u002F () => Promise\u003Cvoid>           — tab\u002Fsystem audio\n",[81,165,167],{"class":83,"line":166},7,[81,168,169],{"class":98},"  stop\n",[81,171,173,176,179,183,186,189,193,196,200,202,205,207,210,212,215,217,220,222,225,227,230,233],{"class":83,"line":172},8,[81,174,175],{"class":91},"}",[81,177,178],{"class":91}," =",[81,180,182],{"class":181},"s2Zo4"," useLocalAudio",[81,184,185],{"class":98},"(",[81,187,188],{"class":91},"{",[81,190,192],{"class":191},"swJcz"," fftSize",[81,194,195],{"class":91},":",[81,197,199],{"class":198},"sbssI"," 2048",[81,201,102],{"class":91},[81,203,204],{"class":191}," bins",[81,206,195],{"class":91},[81,208,209],{"class":198}," 80",[81,211,102],{"class":91},[81,213,214],{"class":191}," startFreq",[81,216,195],{"class":91},[81,218,219],{"class":198}," 100",[81,221,102],{"class":91},[81,223,224],{"class":191}," endFreq",[81,226,195],{"class":91},[81,228,229],{"class":198}," 18000",[81,231,232],{"class":91}," }",[81,234,235],{"class":98},")\n",[62,237,239],{"id":238},"usewebsocketfftoptions",[57,240,241],{},"useWebSocketFft(options?)",[53,243,244,245,249,250,253,254,257,258,261,262,60],{},"Connects to a WebSocket that streams ",[246,247,248],"strong",{},"raw PCM"," and computes the FFT in-browser via WASM\n(distinct from the component's ",[57,251,252],{},"websocket"," mode, which expects ",[246,255,256],{},"pre-computed"," FFT). Feed\nits ",[57,259,260],{},"fftData"," into the component with ",[57,263,59],{},[72,265,267],{"className":74,"code":266,"language":76,"meta":77,"style":77},"const {\n  fftData, fftDataLeft, fftDataRight, isConnected,\n  connect,        \u002F\u002F (url) => void\n  disconnect,\n  processSamples  \u002F\u002F (Float32Array) => void — feed PCM manually\n} = useWebSocketFft({ fftSize: 2048, bins: 80, overlap: 0.5, autoReconnect: true })\n",[57,268,269,275,296,306,313,321],{"__ignoreMap":77},[81,270,271,273],{"class":83,"line":84},[81,272,88],{"class":87},[81,274,92],{"class":91},[81,276,277,279,281,284,286,289,291,294],{"class":83,"line":95},[81,278,99],{"class":98},[81,280,102],{"class":91},[81,282,283],{"class":98}," fftDataLeft",[81,285,102],{"class":91},[81,287,288],{"class":98}," fftDataRight",[81,290,102],{"class":91},[81,292,293],{"class":98}," isConnected",[81,295,130],{"class":91},[81,297,298,301,303],{"class":83,"line":109},[81,299,300],{"class":98},"  connect",[81,302,102],{"class":91},[81,304,305],{"class":105},"        \u002F\u002F (url) => void\n",[81,307,308,311],{"class":83,"line":133},[81,309,310],{"class":98},"  disconnect",[81,312,130],{"class":91},[81,314,315,318],{"class":83,"line":144},[81,316,317],{"class":98},"  processSamples  ",[81,319,320],{"class":105},"\u002F\u002F (Float32Array) => void — feed PCM manually\n",[81,322,323,325,327,330,332,334,336,338,340,342,344,346,348,350,353,355,358,360,363,365,369,371],{"class":83,"line":155},[81,324,175],{"class":91},[81,326,178],{"class":91},[81,328,329],{"class":181}," useWebSocketFft",[81,331,185],{"class":98},[81,333,188],{"class":91},[81,335,192],{"class":191},[81,337,195],{"class":91},[81,339,199],{"class":198},[81,341,102],{"class":91},[81,343,204],{"class":191},[81,345,195],{"class":91},[81,347,209],{"class":198},[81,349,102],{"class":91},[81,351,352],{"class":191}," overlap",[81,354,195],{"class":91},[81,356,357],{"class":198}," 0.5",[81,359,102],{"class":91},[81,361,362],{"class":191}," autoReconnect",[81,364,195],{"class":91},[81,366,368],{"class":367},"sfNiH"," true",[81,370,232],{"class":91},[81,372,235],{"class":98},[53,374,375,376,379],{},"The raw WASM FFT processor is also exported from ",[57,377,378],{},"vue-fft-visualizer\u002Fwasm"," for direct use.",[62,381,383],{"id":382},"websocket-protocol","WebSocket protocol",[53,385,386,389,390,392],{},[57,387,388],{},"mode=\"websocket\""," expects a server that sends ",[246,391,256],{}," FFT frames.",[53,394,395],{},[246,396,397],{},"1. Config message (JSON), once on connect:",[72,399,403],{"className":400,"code":401,"language":402,"meta":77,"style":77},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{ \"type\": \"config\", \"mode\": \"fft\", \"bins\": 80, \"fps\": 120 }\n","json",[57,404,405],{"__ignoreMap":77},[81,406,407,409,412,415,418,420,422,426,428,430,432,435,437,439,441,444,446,448,450,453,455,457,459,461,463,466,468,470,473],{"class":83,"line":84},[81,408,188],{"class":91},[81,410,411],{"class":91}," \"",[81,413,414],{"class":87},"type",[81,416,417],{"class":91},"\"",[81,419,195],{"class":91},[81,421,411],{"class":91},[81,423,425],{"class":424},"sfazB","config",[81,427,417],{"class":91},[81,429,102],{"class":91},[81,431,411],{"class":91},[81,433,434],{"class":87},"mode",[81,436,417],{"class":91},[81,438,195],{"class":91},[81,440,411],{"class":91},[81,442,443],{"class":424},"fft",[81,445,417],{"class":91},[81,447,102],{"class":91},[81,449,411],{"class":91},[81,451,452],{"class":87},"bins",[81,454,417],{"class":91},[81,456,195],{"class":91},[81,458,209],{"class":198},[81,460,102],{"class":91},[81,462,411],{"class":91},[81,464,465],{"class":87},"fps",[81,467,417],{"class":91},[81,469,195],{"class":91},[81,471,472],{"class":198}," 120",[81,474,475],{"class":91}," }\n",[53,477,478],{},[246,479,480],{},"2. Binary FFT frames, continuously:",[482,483,484,495,498],"ul",{},[485,486,487,488,491,492,494],"li",{},"One ",[57,489,490],{},"uint8"," (0–255) per frequency bin — ",[57,493,452],{}," bytes per frame",[485,496,497],{},"0 = silence, 255 = maximum amplitude",[485,499,500],{},"Typically 100 Hz – 18 kHz, exponentially spaced",[53,502,503],{},"For best results the server should capture at 48 kHz+, apply a Hann\u002FHamming window, compute\na 1024–2048-point FFT, map to exponentially-spaced bands, apply A-weighting, convert to dB,\nnormalize to 0–255, and stream at 60–120 fps.",[505,506,508],"h3",{"id":507},"reference-servers","Reference servers",[53,510,511,512,515,516,519,520,523,524,527],{},"The repository's ",[57,513,514],{},"backend-examples\u002F"," has servers that capture system audio, compute FFT, and\nstream it: ",[246,517,518],{},"Python"," (pyalsaaudio + numpy, incl. a Raspberry Pi variant), ",[246,521,522],{},"Node.js","\n(node-audiorecorder + fft.js), and ",[246,525,526],{},"Rust"," (cpal + rustfft).",[529,530,531],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":77,"searchDepth":95,"depth":95,"links":533},[534,535,536],{"id":64,"depth":95,"text":67},{"id":238,"depth":95,"text":241},{"id":382,"depth":95,"text":383,"children":537},[538],{"id":507,"depth":109,"text":508},"The standalone data pipelines and the WebSocket FFT protocol.","md",null,{},{"icon":46},{"title":43,"description":539},"p5VmAQEU6DPrTZMtUTn29k-gnFqqbz-0gQvzCzTbWKU",[547,541],{"title":38,"path":39,"stem":40,"description":548,"icon":41,"children":-1},"Color the bars with a built-in preset or your own CSS-color stops.",1784469224092]