今天來整理利用p5.sound.js在音訊波形資料的操作
一般來說,音訊除了音量大小的數值之外,就是波形的資料,分別為
頻譜波形 spectrum 及振幅波形 waveform
在前一篇介紹讀取麥克風音量大小數值時,發現在iOS的手機,此功能會失效
也就是 mic.getLevel() 會讀不到資料,
因此,改用 FFT 的 waveform的功能,也就是將 波形振幅取正值再加以平均,就可以獲得音量大小數值了。
另外麥克風的啟動,需要透過手動點擊螢幕來打開麥克風的收音。
像是 getAudioContext().suspend();
還有
let isUserStarted = false;
function touchStarted() {
if (!isUserStarted) {
userStartAudio().then(() => {
mic.start();
});
}
isUserStarted = true;
}
以下是完整的程式
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<!-- keep the line below for OpenProcessing compatibility -->
<!-- <script src="https://openprocessing.org/openprocessing_sketch.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/addons/p5.sound.js"></script>
<script src="mySketch2.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body></body>
</html>
CSS
html,
body {
margin: 0;
padding: 0;
}
JS
let mic, fft;
let isUserStarted = false;
let amplitude;
let size1 = 0;
let recorder;
let soundFile;
let n = 0;
function setup() {
getAudioContext().suspend(); //--- 關閉預設Audio的功能
createCanvas(710, 400);
noFill();
// 建立 AudioIn 物件
mic = new p5.AudioIn();
mic.getSources(gotSources);
// mic.start();
//-- 建立 FFT 物件
fft = new p5.FFT();
fft.setInput(mic);
//amplitude = new p5.Amplitude();
textSize(24);
recorder = new p5.SoundRecorder(); //--- 建立錄音物件
recorder.setInput(mic); //-- 設定錄音音源來源
soundFile = new p5.SoundFile(); //-- 建立錄音檔案物件
}
function gotSources(devices) { //--- 取得音源裝置清單---
//console.log(devices);
let device_name = "外接麥克風";
devices.forEach( (dev, index) => {
console.log(dev.label);
if(dev.kind == 'audioinput'){
mic.setSource(0); //--- 設定音源裝置來源---
}
});
}
function draw() {
background(0);
let spectrum = fft.analyze(); //--- 取得音源 spectrum 音訊資料---
let waveform1 = fft.waveform(); //--- 取得音源 waveform 音訊資料---
//-- spectrum ------
beginShape();
for (i = 0; i < spectrum.length; i++) {
vertex(i, map(spectrum[i], 0, 255, height, 0));
}
endShape();
//-- waveform ------
let level = 0;
beginShape();
for (i = 0; i < waveform1.length; i++) {
let x = map(i, 0, waveform1.length, 0, width);
let y = map( waveform1[i], -1, 1, 0, height);
vertex(x,y);
level += abs(waveform1[i]);
}
endShape();
let level1 = level/waveform1.length; //--- 計算平均值
if(n==1){
let size0 = map(level1, 0, 1, 0, 2000);
fill(255);
text(nfc(size0, 2), 50, 50);
size1 = size1 + (size0-size1)*0.1;
noFill();
stroke(255);
ellipse(width/2-100, height/2, size1, size1);
}
}
function touchStarted() {
if (!isUserStarted) {
userStartAudio().then(() => {
print('mic started!');
mic.start(); //--- 開啟麥克風
n = 1;
console.log(n);
});
isUserStarted = true;
}
}
function keyPressed(e) {
console.log(e);
if(e.key == '1'){
recorder.record(soundFile); //--- 開啟錄音
console.log(recorder);
console.log(soundFile);
} else if(e.key == '2'){
recorder.stop(); //--- 停止錄音
} else if(e.key == '3'){
soundFile.play(); //--- 播放儲存錄音檔
save(soundFile, 'mySound.wav'); //--- 儲存錄音檔
}
}
執行結果
參考資料
マイク入力と録音 p5.sound.js サウンド
https://himco.jp/2020/01/11/5:マイク入力-p5-sound-js-サウンド/
測試網址
https://www.moc2718.com/web1109/index.html
Web Audio API
https://webaudio.github.io/web-audio-api/