備忘錄_20160105(定位)
修改
回首頁
程式 2022-05-04 21:35:38 1651671338 100
嘗試語音辨識 try speech recognition-step03
嘗試語音辨識 try speech recognition-step03
fourier transform
偵測聲音,切割並繪製頻率振幅圖
20220501_fourier_transform.odt
●20220501.php
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
*
{
font-family: "WenQuanYi Zen Hei","文泉驛正黑","Heiti TC","黑體-繁","LiHei Pro","儷黑 Pro","PingFang TC","Droid Sans","Roboto","Microsoft JhengHei","微軟正黑體",sans-serif;
/* 【linux的字型】【ios字型】【android字型】【微軟正黑體】【無襯線字=黑體】 */
}
html, body
{
margin: 0;
border: 0;
padding: 0;
width: 100%;
height: 100%;
}
a:link, a:visited
{
color: blue;
text-decoration: none;
}
.divWrapper
{
padding: 1em;
}
</style>
</head>
<body>
<div class="divWrapper">
<div>
<a target="_blank" href="https://www.youtube.com/watch?v=spUNpyF58BY">可視化的傅里葉變換</a><br>
<a target="_blank" href="https://zh.wikipedia.org/zh-tw/歐拉公式">尤拉公式/歐拉公式</a><br>
</div>
<div>
<button type="button" onclick="goRecord();">錄音</button>
<button type="button" onclick="goStop();">停止</button>
</div>
<div id="divOutput"></div>
</div>
<script>
var iSampleRate=8000;
var oMediaRecorder=null;
var oaWords=null;
var iIntervalId=null;
var booStart=false;
var oLastData=null;
var booLastDataOkay=false;
if(!String.prototype.ltrim) { String.prototype.ltrim = function() { return this.replace(/^\s+/,''); }; }
if(!String.prototype.rtrim) { String.prototype.rtrim = function() { return this.replace(/\s+$/,''); }; }
if(!String.prototype.trim ) { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,''); }; }
function gebi(strId)
{
return document.getElementById(strId);
}
window.addEventListener(
"load",
function()
{
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
{
navigator.mediaDevices.getUserMedia({ audio: true})
.then
(
function(oStream)
{
oMediaRecorder=new MediaRecorder(oStream);
oMediaRecorder.ondataavailable=function(oEvent)
{
console.log(oEvent.data);
oLastData=[];
oLastData.push(oEvent.data);
getBuffer();
}
oMediaRecorder.onstop=function(oEvent)
{
}
}
)
.catch
(
function(oErr)
{
alert("遇到錯誤!"+oErr);
}
);
}
else
{
alert("您的瀏覽器不支援 getUserMedia!");
}
}
);
function goRecord()
{
gebi("divOutput").innerHTML="";
booLastDataOkay=false;
oaWords=[];
oMediaRecorder.start();
booStart=true;
iIntervalId=window.setInterval(requestBlob, 100);
}
function goStop()
{
booStart=false;
window.clearInterval(iIntervalId);
console.log(oMediaRecorder.state);
oMediaRecorder.stop();
drawWords();
}
function requestBlob()
{
if(booStart==true)
{
oMediaRecorder.stop();
oMediaRecorder.start();
}
}
function getBuffer()
{
oLastData[0].arrayBuffer()
.then
(
oBuffer=>
{
var oAC=new (window.AudioContext || window.webkitAudioContext)({sampleRate:iSampleRate});
oAC.decodeAudioData(oBuffer)
.then
(
function(oDecodedData)
{
//for(var iChannel=0; iChannel<oDecodedData.numberOfChannels; iChannel++)
for(var iChannel=0; iChannel<1; iChannel++)
{
var faData=new Float32Array(oDecodedData.getChannelData(iChannel)); // -1 ~ +1
var fMin=Math.min(...faData);
var fMax=Math.max(...faData);
if(((fMax-fMin)/2.0)>0.1)
{
/*
output(
"min="+fMin+", max="+fMax
+", channel="+iChannel
+", data length="+faData.length);
*/
if(booLastDataOkay==false)
{
oaWords.push([Array.from(faData)]);
}
else
{
oaWords[oaWords.length-1].push(Array.from(faData));
}
booLastDataOkay=true;
}
else
{
/* output("silence"); */
booLastDataOkay=false;
}
}
//output("......");
}
)
.catch
(
function(oErr)
{
//output(oErr);
}
);
}
)
.catch
(
oErr=>{ output(oErr); }
);
}
function output(strMessage)
{
gebi("divOutput").innerHTML=gebi("divOutput").innerHTML+"<br>\r\n"+strMessage;
}
function drawWords()
{
for(var iIdxWord=0; iIdxWord<oaWords.length; iIdxWord++)
{
var faCurrentWord=oaWords[iIdxWord][0];
for(var iTmp1=1; iTmp1<oaWords[iIdxWord].length; iTmp1++)
{
faCurrentWord=faCurrentWord.concat(oaWords[iIdxWord][iTmp1]);
}
// 時域
var oCanvas=document.createElement("canvas");
oCanvas.setAttribute("width", 100*oaWords[iIdxWord].length);
oCanvas.setAttribute("height", 200);
var oCtx=oCanvas.getContext("2d");
var iCanvasWidth=oCanvas.width;
var iCanvasHeight=oCanvas.height;
oCtx.beginPath();
oCtx.rect(0,0,iCanvasWidth,iCanvasHeight);
oCtx.fillStyle="black";
oCtx.fill();
oCtx.strokeStyle="white";
oCtx.beginPath();
var fMaxValue=2; // -1 ~ +1
var iIdxData=0;
var x=iIdxData/(faCurrentWord.length-1)*iCanvasWidth;
var y=(fMaxValue-(faCurrentWord[iIdxData]+(fMaxValue/2)))/fMaxValue*iCanvasHeight;
oCtx.moveTo(x,y);
for(var iIdxData=1; iIdxData<faCurrentWord.length; iIdxData++)
{
x=iIdxData/(faCurrentWord.length-1)*iCanvasWidth;
y=(fMaxValue-(faCurrentWord[iIdxData]+(fMaxValue/2)))/fMaxValue*iCanvasHeight;
oCtx.lineTo(x,y)
}
oCtx.stroke();
var oDiv3=document.createElement("div");
oDiv3.innerHTML="y-amplitude(-1~1), x-time(seconds)";
gebi("divOutput").appendChild(oDiv3);
gebi("divOutput").appendChild(oCanvas);
gebi("divOutput").appendChild(document.createElement("br"));
// 頻域
// Fourier Cosine Transform
// 先準備陣列
// 人耳 20Hz ~ 20000Hz
console.log("samples="+faCurrentWord.length);
var iFreqCount=iSampleRate/2;
var faFreq=new Array(iFreqCount);
for(var iIdxT=0; iIdxT<iFreqCount; iIdxT++)
{
var fFrequence=(iSampleRate/faCurrentWord.length)*iIdxT;
fFrequence=(iSampleRate/2)*(iIdxT/iFreqCount);
faFreq[iIdxT]=0;
for(var t=0; t<faCurrentWord.length; t++)
{
var fTime=t/iSampleRate;
faFreq[iIdxT]
=faFreq[iIdxT]
+(faCurrentWord[t]
*Math.cos(-2*Math.PI*fFrequence*fTime));
}
faFreq[iIdxT]=faFreq[iIdxT]/faCurrentWord.length;
}
var oCanvas=document.createElement("canvas");
oCanvas.setAttribute("width", 800);
oCanvas.setAttribute("height", 200);
var oCtx=oCanvas.getContext("2d");
var iCanvasWidth=oCanvas.width;
var iCanvasHeight=oCanvas.height;
oCtx.beginPath();
oCtx.rect(0,0,iCanvasWidth,iCanvasHeight);
oCtx.fillStyle="yellow";
oCtx.fill();
oCtx.strokeStyle="red";
oCtx.strokeWidth=1;
oCtx.beginPath();
var fMaxValue=0.2; // -0.1 ~ +0.1
var fMinGot=Math.min(...faFreq);
var fMaxGot=Math.max(...faFreq);
fMaxValue=Math.max(Math.abs(fMinGot),Math.abs(fMaxGot))*2;
var iIdxFreq=0;
x=iIdxFreq/(faFreq.length-1)*iCanvasWidth;
y=(fMaxGot-faFreq[iIdxFreq])/(fMaxGot-fMinGot)*iCanvasHeight;
oCtx.moveTo(x,y)
for(var iIdxFreq=1; iIdxFreq<faFreq.length; iIdxFreq++)
{
x=iIdxFreq/(faFreq.length-1)*iCanvasWidth;
y=(fMaxGot-faFreq[iIdxFreq])/(fMaxGot-fMinGot)*iCanvasHeight;
oCtx.lineTo(x,y)
}
oCtx.stroke();
var oDiv2=document.createElement("div");
oDiv2.innerHTML
="y-amplitude("+fMinGot+"~"+fMaxGot+"), x-frequency(~"+(iSampleRate/2)+"Hz)<br>";
gebi("divOutput").appendChild(oDiv2);
gebi("divOutput").appendChild(oCanvas);
gebi("divOutput").appendChild(document.createElement("br"));
}
}
</script>
</body>
</html>