๐ŸŒŸ p5.js ์‚ฌ์šด๋“œ : ๋งˆ์ดํฌ ์ž…๋ ฅ ๋ฐ›๊ธฐ

BamgasiJMยท2025๋…„ 12์›” 19์ผ

p5.js Art

๋ชฉ๋ก ๋ณด๊ธฐ
10/67
post-thumbnail

โ—† ์„ค๊ณ„

  • ์บ”๋ฒ„์Šค ํฌ๊ธฐ : 800 x 800
  • ๋ฐฐ๊ฒฝ ์ƒ‰์ƒ : grayscale 15, ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค 40์˜ ์•ŒํŒŒ๊ฐ’ ์ฃผ์–ด์„œ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ํŽ˜์ด๋“œ ์•„์›ƒ
  • ์‚ฌ์šด๋“œ ๋ฐ˜์‘ํ•˜๋Š” ์›์˜ ๋ฐ˜์ง€๋ฆ„ : ์ตœ์†Œ 100100 ~ ์ตœ๋Œ€ 330330
  • ์›์˜ ์ƒ‰์ƒ : grayscable 255, alpha 150
  • ์ž…๋ ฅ๊ฐ’ : amp.getLevel() โ†’ 0.1 ~ 0.3 ์ •๋„๋กœ ์„ค์ •
  • ์‚ฌ์šด๋“œ ๊ฐ’ โ†’ ์› ๋ฐ˜์ง€๋ฆ„์œผ๋กœ ๋ณ€ํ™˜ ๋กœ์ง : map(), constrain() ์‚ฌ์šฉ

โ—† ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด

p5.js์—์„œ ๋งˆ์ดํฌ ์ž…๋ ฅ์„ ์‹œ๊ฐํ™”ํ•  ๋•Œ๋Š” ์•„๋ž˜ ๋‘ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

1. p5.AudioIn

  • ์‚ฌ์šฉ์ž์˜ ๋งˆ์ดํฌ ์ž…๋ ฅ์„ ๋ฐ›์•„์˜ค๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ € ๋ณด์•ˆ ์ •์ฑ…์ƒ ์‚ฌ์šฉ์ž์˜ ์ œ์Šค์ฒ˜(ํ™”๋ฉด ํด๋ฆญ ๋“ฑ) ์ดํ›„์— ํ™œ์„ฑํ™”๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. p5.Amplitude

  • ํ˜„์žฌ ์˜ค๋””์˜ค ์‹ ํ˜ธ์˜ ํ‰๊ท  ์ง„ํญ์„ 0.00.0 ~ 1.01.0 ๋ฒ”์œ„๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์‹œ๊ฐ„ ์˜ค๋””์˜ค ๋ ˆ๋ฒจ์„ ์ธก์ •ํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผํŒŒ์ˆ˜ ๋ถ„์„์ด ์•„๋‹Œ ์ „์ฒด ์Œ๋Ÿ‰์˜ ํฌ๊ธฐ๋งŒ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.

โ—† ๋ผˆ๋Œ€ ์ฝ”๋“œ

  • ์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
let mic;
let amp;

function setup() {
  createCanvas(800, 800);
  background(15);
  
  // ๋งˆ์ดํฌ ์ž…๋ ฅ ๊ฐ์ฒด ์ƒ์„ฑ
  mic = new p5.AudioIn();
  mic.start();
  
  // ์ง„ํญ์„ ๋ถ„์„ํ•˜๋Š” ๊ฐ์ฒด ์ƒ์„ฑ
  amp = new p5.Amplitude();
  amp.setInput(mic);
}

function draw() {
  background(15, 40);
  
  // ํ˜„์žฌ ๋งˆ์ดํฌ ์ž…๋ ฅ ๋ ˆ๋ฒจ (0.0 ~ 1.0)์„ ์ €์žฅํ•˜๋Š” ๋ณ€์ˆ˜
  let level = amp.getLevel();

  // ๋ ˆ๋ฒจ ๊ฐ’์„ ๋ฐ˜์ง€๋ฆ„์„ ๋ณ€ํ™˜
  // ์ž…๋ ฅ ๋ฒ”์œ„(0 - 0.3)์„ ๋ฐ˜์ง€๋ฆ„ ๋ฒ”์œ„(30 - 330)์œผ๋กœ ๋งตํ•‘
  // ๋ฐ˜์ง€๋ฆ„์„ 30 - 330 ๋ฒ”์œ„๋กœ ์ œํ•œ
  let radius = map(level, 0, 0.3, 30, 330);
  radius = constrain(radius, 30, 330);
  
  noStroke();
  fill(255, 150);
  
  ellipse(width / 2, height / 2, radius * 2, radius * 2);
}

// ๋ธŒ๋ผ์šฐ์ €์˜ ์˜ค๋””์˜ค ์ปจํ…์ŠคํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•œ ์•ก์…˜
function mousePressed() {
  getAudioContext().resume();
}

์ด๋ ‡๊ฒŒ ๊ธฐ๋ณธ ๋ผˆ๋Œ€๋ฅผ ์žก๊ณ  ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋งˆ์ดํฌ ๊ถŒํ•œ๋„ ์ฃผ์—ˆ์ง€๋งŒ ๋ฐ˜์‘์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด์œ ๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๋ณด์•ˆ ์ •์ฑ… ๋•Œ๋ฌธ์œผ๋กœ ๋‹ค์Œ์˜ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด์•ผ์ง€ ์ •์ƒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

โ— ๋งˆ์šฐ์Šค๋ฅผ ํด๋ฆญํ•ด์•ผ๋งŒ ๋งˆ์ดํฌ๊ฐ€ ์‹œ์ž‘๋˜๋„๋ก ๋ช…์‹œ
โ— AudioContext ์ƒํƒœ๋ฅผ ์ง์ ‘ ํ™•์ธ

Sound Interactive Circle

let mic;
let amp;
let started = false;   // ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ false๋กœ ์„ค์ •

function setup() {
  createCanvas(800, 800);
  background(15);

  mic = new p5.AudioIn();
  amp = new p5.Amplitude();
}

function draw() {
  background(15, 40);

  if (!started) {
    fill(200);
    textAlign(CENTER, CENTER);
    textSize(16);
    text("ํ™”๋ฉด์„ ํด๋ฆญํ•˜๋ฉด ๋งˆ์ดํฌ๊ฐ€ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค", width / 2, height / 2);
    return;
  }

  let level = amp.getLevel();

  let radius = map(level, 0.0, 0.2, 30, 330);
  radius = constrain(radius, 30, 330);

  noStroke();
  fill(255, 150);
  ellipse(width / 2, height / 2, radius * 2, radius * 2);
}

function mousePressed() {
  // ์˜ค๋””์˜ค ์ปจํ…์ŠคํŠธ ๊ฐ•์ œ ์‹œ์ž‘
  userStartAudio();

  mic.start(() => {
    amp.setInput(mic);
    started = true;    		 // ์ƒํƒœ๋ฅผ true๋กœ ์ „ํ™˜
    console.log("๋งˆ์ดํฌ ์‹œ์ž‘๋จ");
  });
}

์ž…๋ ฅ ๋ ˆ๋ฒจ์„ ์กฐ์ •ํ•˜์—ฌ ๋น„์ฃผ์–ผ๋ผ์ด์ œ์ด์…˜์— ๋ณ€ํ™”๋ฅผ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
map(level, 0.0, 0.2, 30, 330);
์—์„œ ๋ ˆ๋ฒจ ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ 0.0 ~ 0.2๋กœ ์„ค์ •ํ•˜์˜€๋Š”๋ฐ, ์ด ์ˆ˜์น˜๋ฅผ ์ž‘์€ ์†Œ๋ฆฌ์—๋„ ํฌ๊ฒŒ ๋ฐ˜์‘ํ•˜๋„๋ก ๋ฏผ๊ฐ๋„๋ฅผ ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜ ๋ฐ˜๋Œ€๋กœ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฏผ๊ฐ : 0.002 - 0.07
  • ๋‘”๊ฐ : 0.1 - 0.7

โ—† ์ดํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ

๋‹ค์Œ ๋‹จ๊ณ„๋กœ๋Š”

  • ๋ถ€๋“œ๋Ÿฌ์šด ๋ณ€ํ™”๋ฅผ ์œ„ํ•œ lerp ์ ์šฉ
  • ์ „์ฒด ๋ ˆ๋ฒจ๊ฐ’์ด ์•„๋‹Œ FFT(๊ณ ์† ํ‘ธ๋ฆฌ์— ๋ณ€ํ™˜)๊ธฐ๋ฐ˜์œผ๋กœ ํ˜•ํƒœ๋ฅผ ๋ณ€ํ™˜
  • ๋ ˆ๋ฒจ ๊ฐ’์— ๋”ฐ๋ผ ์ƒ‰ ๋ณ€ํ™”, ๋…ธ์ด์ฆˆ ๊ฐ’ ๋ณ€ํ™”, ์†๋„ ๋ณ€ํ™”
    ๋“ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
profile
Coding Art with Blender / oF / Processing / p5.js / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€