--- tags: 程式設計,第十三章,學生版,互動藝術程式創作入門,Creative Coding --- # 章節 13 - 學生版_使用者影音互動 - 即時串流聲音 ## 單元介紹 目標 * 學習如何抓取跟分析聲音製作互動 * 瞭解如何抓取與繪製使用者的即時影片 * 學習如何把即時影像轉成即時抽象畫 * 能夠追蹤影像中的顏色 ## 課程重點 ### 使用麥克風 #### p5.AudioIn * 建立一個新的麥克風 ```javascript= let mic = new p5.AudioIn() mic.start() ``` --- ![](https://i.imgur.com/rxW4iTI.gif) ### 圓隨著聲音大小聲放大縮小 --- ```javascript= var micLevel = mic.getLevel() fill(255) text(micLevel,50,50) r = lerp(r, micLevel*500,0.02) if(micLevel>0.1){ fill(255,0,0) } ``` --- ### 上圖太快速,讓接收顯示的資訊更為平滑 ![](https://i.imgur.com/4844g9U.gif) ### 使用 lerp 讓接收的資訊更平滑 ```javascript= let micLevel = mic.getLevel() r = lerp(r, micLevel*5000, 0.05) ellipse(width/2, height/2 ,r) ``` --- 完整程式碼 ```javascript= var mic function setup() { createCanvas(windowWidth, windowHeight); background(100); mic = new p5.AudioIn() mic.start() } function draw() { //circle(mouseX, mouseY, 20); background(0); var micLevel = mic.getLevel() ellipse(width/2,height/2,micLevel*500) } ``` --- ### 超過某個範圍會變紅色的圓 ![](https://i.imgur.com/X7CFDJf.gif) --- #### 完整程式碼 ```javascript= var mic function setup() { createCanvas(windowWidth, windowHeight); background(100); mic = new p5.AudioIn() mic.start() } function draw() { //circle(mouseX, mouseY, 20); background(0); var micLevel = mic.getLevel() ellipse(width/2,height/2,micLevel*500) } ``` --- ### 聲音大小聲可以放大縮小 ![](https://i.imgur.com/cAUQu0l.gif) --- #### 完整程式碼 ```javascript= var mic function setup() { createCanvas(windowWidth, windowHeight); background(100); mic = new p5.AudioIn() mic.start() } var r = 10 function draw() { background(0); var micLevel = mic.getLevel() fill(255) text(micLevel,50,50) r = lerp(r, micLevel*500,0.02) if(micLevel>0.1){ fill(255,0,0) } push() translate(width/2,height/2) noFill() stroke(255) for (var i =0;i<20;i++){ //ellipse(0,0,i*r/10) rotate(r*PI/1000) arc(0,0,i*r,i*r,0,PI) } pop() } ``` --- 加上lerp()函數 ![](https://i.imgur.com/AVAYeof.gif) --- #### 完整程式碼 ```javascript= var mic function setup() { createCanvas(windowWidth, windowHeight); background(100); mic = new p5.AudioIn() mic.start() } var r = 10 function draw() { background(0); var micLevel = mic.getLevel() fill(255) text(micLevel,50,50) r = lerp(r, micLevel*500,0.02) if(micLevel>0.1){ fill(255,0,0) } push() translate(width/2,height/2) noFill() stroke(255) for (var i =0;i<20;i++){ //ellipse(0,0,i*r/10) rotate(r*PI/1000) arc(0,0,i*r,i*r,0,PI) } pop() } ``` --- 把ellipse指令改為arc圓弧 ![](https://i.imgur.com/y0FQ0HJ.gif) --- ![](https://i.imgur.com/ZYMdVhJ.png) --- #### 完整程式碼 ```javascript= ``` --- ### 旋轉半弧的角度 ![](https://i.imgur.com/cwfrOi3.gif) --- #### 完整程式碼 ```javascript= ``` --- ### 不用除以某數 ![](https://i.imgur.com/8gikrnf.gif) --- ```javascript= for(var i=0;i<20;i++){ rotate(lerpedMicLevel*PI); //不要除以某數 arc(0, 0,i*(5+lerpedMicLevel*500), i*(5+lerpedMicLevel*500), 0,PI); } ``` --- 加上顏色 ![](https://i.imgur.com/NQ8iIdD.gif) --- #### 完整程式碼 ```javascript= ``` --- ### 聲音大聲時反應更大 ![](https://i.imgur.com/XZjbIdT.gif) --- #### 完整程式碼 ```javascript= ``` --- ### 加上noise檔案 ![](https://i.imgur.com/oAcWyoo.gif) --- #### 完整程式碼 ```javascript= ``` --- ### 頻譜分析與繪製 ![](https://i.imgur.com/7KveYY5.gif) --- #### 完整程式碼 ```javascript= var mic,noiseTexture var colors = "ecba82-81c14b-2e933c-297045-204e4a".split("-").map(a=>"#"+a) function preload() { noiseTexture=loadImage("noise.jpg"); } function setup() { createCanvas(windowWidth, windowHeight); background(100); mic = new p5.AudioIn() mic.start() } var r = 10 function draw() { background(0); var micLevel = mic.getLevel() fill(255) text(micLevel,50,50) r = lerp(r, micLevel*500,0.02) if(micLevel>0.1){ fill(255,0,0) } push() translate(width/2,height/2) noFill() strokeWeight(5) for (var i =0;i<20;i++){ var clr = colors[i%colors.length] stroke(clr) rotate(r*PI/1000)//數字影響效果 arc(0,0,i*r,i*r,0,PI) } pop() push() blendMode(MULTIPLY) image(noiseTexture,0,0,width,height) pop() } ``` --- ![](https://i.imgur.com/8e8tUK7.gif) ```javascript= ``` --- ![](https://i.imgur.com/K7OPgqx.gif) ### 加上以下指令 ```javascript= noFill() strokeWeight(3); ``` --- ![](https://i.imgur.com/bsJkLHJ.gif) 並把vertex(i, spectrum[i]*3);改成 vertex(i, height - spectrum[i]*3) --- ### 畫布軌跡留下來 ![](https://i.imgur.com/0LqCK1c.png) 加上 ```javascript= background(0,20); ``` --- ![](https://i.imgur.com/wyedv6l.gif) ```javascript= copy(0,0,width, height,0,-1,width,height)//保留現在的圖,在下一次就會變成前一個畫面,會產生暫留感覺 ``` --- ![](https://i.imgur.com/JwtTUQL.gif) ```javascript= beginShape() for(let i = 0; i<spectrum.length*1.5;i+=5){ vertex(i, height/2 -spectrum[i]*3) } endShape() ``` --- #### 全部程式碼 ```javascript= ``` --- ### getCentroid() 取得中心頻率 * 結合顏色 ![](https://i.imgur.com/oXcWaTj.gif) --- ```javascript= let center = fft.getCentroid() colorMode(HSB) stroke(map(center,500,8000,0,400),100,100) ``` --- ### 把背景與copy()指令拿掉 ```javascript= // background(0,20); // copy(0,0,width,height,0,-1,width,height) ``` ![](https://i.imgur.com/J9F8zrY.gif) --- ### 加上frameCount與時間相關 ![](https://i.imgur.com/LeqCGkh.gif) --- #### 完整程式碼 ```javascript= ``` --- #### 把背景改為黑色,線條變細 並在迴圈前後都加上vertex ![](https://i.imgur.com/1EOz4Rx.gif) ```javascript= beginShape() vertex(0, frameCount) for(let i = 0; i<spectrum.length/1.5;i+=5){ vertex(i, frameCount -spectrum[i]) } vertex(width, frameCount) endShape() ``` --- ### 繪製陰影 ```javascript= drawingContext.shadowColor = color(0,100) drawingContext.shadowOffsetY = -5 drawingContext.shadowBlur = 20 //陰影的模糊 ``` ![](https://i.imgur.com/fYIf0zz.gif) --- #### 完整程式碼 ```javascript= ``` --- ### 使用充滿顏色不是只有框線 ![](https://i.imgur.com/tMwkbc0.gif) --- #### 完整程式碼 ```javascript= ``` --- 讓其轉動 ![](https://i.imgur.com/1bzoQt3.gif) 完整程式碼 ```javascript= ``` 章節 13 - 學生版_使用者影音互動 - 即時串流聲音.md 目前顯示的是「章節 13 - 學生版_使用者影音互動 - 即時串流聲音.md」。