์ปดํ“จํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์†Œ๋ฆฌ๋ฅผ ๋“ค์„๊นŒ?

    ์ปดํ“จํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์†Œ๋ฆฌ๋ฅผ ๋“ค์„๊นŒ?


    ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ํ•„์ž์˜ ์˜ˆ์ „ ์ง์—…์ด์—ˆ๋˜ ์‚ฌ์šด๋“œ ์—”์ง€๋‹ˆ์–ด์˜ ์ถ”์–ต์„ ์‚ด๋ ค์„œ ํ•œ๋ฒˆ ์˜ค๋””์˜ค์— ๋Œ€ํ•œ ์ด๋ก ์„ ์„ค๋ช…ํ•ด๋ณผ๊นŒ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ก  ์„ค๋ช…๋งŒ ํ•˜๋ฉด ๋…ธ์žผ์ด๋‹ˆ๊นŒ ์˜ค๋””์˜ค ์ด๋ก ์„ ๊ธฐ์ดˆ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Web Audio API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์˜ค๋””์˜ค ํŒŒํ˜•๊นŒ์ง€ ๊ทธ๋ ค๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

    ๋ฐ”๋กœ ์ฝ”๋”ฉ์— ๋“ค์–ด๊ฐ€๊ณ  ์‹ถ์ง€๋งŒ ์˜ค๋””์˜ค์— ๊ด€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ง€์‹์ด ์žˆ์–ด์•ผ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ๊ทธ๋ฆด ๋•Œ์˜ ๊ณผ์ •์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด๋ก ์„ ์ตœ๋Œ€ํ•œ ์ง€๋ฃจํ•˜์ง€ ์•Š๊ฒŒ ์„ค๋ช…ํ•˜๋ ค๊ณ  ํ•œ๋‹ค. ์ด๋ก ์ด ์ฝ”๋”ฉ๋ณด๋‹ค ์žฌ๋ฏธ์—†๋Š” ๊ฑด ๋งž์ง€๋งŒ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ๊ทธ๋ฆฌ๋ ค๋ฉด ์ตœ์†Œํ•œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค์ด๋‹ˆ๊นŒ ํ•œ๋ฒˆ ์“ฑ ํ์–ด๋ณด์ž.

    ์†Œ๋ฆฌ๋ž€ ๋ฌด์—‡์ผ๊นŒ?

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


    1. ์–ด๋–ค ๋ฌผ์ฒด๊ฐ€ ๋ถ€๋ฅด๋ฅด ์ง„๋™์„ ํ•œ๋‹ค. ์ด๋•Œ ์ง„๋™ ์ฃผํŒŒ์ˆ˜๋Š” ๋ญ ๋Œ€์ถฉ 440hz๋ผ๊ณ  ์น˜์ž.
    2. ๊ทธ ๋ฌผ์ฒด ์ฃผ๋ณ€์— ์žˆ๋Š” ๋งค์งˆ์ด 440hz์˜ ์ง„๋™์„ ์ „๋‹ฌํ•œ๋‹ค.(์ผ๋ฐ˜์ ์ธ ์ƒํ™ฉ์—์„œ๋Š” ์ฃผ๋กœ ๊ณต๊ธฐ)
    3. ๋งค์งˆ์ด ์ง„๋™์„ ์ „๋‹ฌํ•˜๋ฉด ์šฐ๋ฆฌ์˜ ๊ณ ๋ง‰๋„ 440hz๋กœ ์ง„๋™ํ•œ๋‹ค.
    4. ๊ทธ ์ง„๋™ ์‹ ํ˜ธ๋ฅผ ๋‹ฌํŒฝ์ด๊ด€์ด ์ „๊ธฐ ์‹ ํ˜ธ๋กœ ๋ฐ”๊ฟ”์„œ ์ฒญ์‹ ๊ฒฝ์— ์ „๋‹ฌํ•œ๋‹ค.
    5. ๋‡Œ๊ฐ€ ์‹ ํ˜ธ๋ฅผ ๋ฐ›์•„์„œ ํ•ด์„ํ•œ๋‹ค. 440hz ์ ‘์ˆ˜์™„๋ฃŒ!

    ์ด๋•Œ 1๋ฒˆ ์ˆœ์„œ์—์„œ ๋ฌผ์ฒด๊ฐ€ 1์ดˆ์— ๋ช‡ ๋ฒˆ์ด๋‚˜ ๋–จ๋ ธ๋Š”์ง€ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ํ—ค๋ฅด์ธ (herz, hz) ๋‹จ์œ„๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 10hz๋Š” 1์ดˆ์— 10๋ฒˆ ์ง„๋™์„ ํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ณ  1khz๋Š” 1์ดˆ์— 1000๋ฒˆ ์ง„๋™์„ ํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฐธ๊ณ ๋กœ ์˜ˆ์‹œ์˜ 440hz๋Š” ๋„๋ ˆ๋ฏธํŒŒ์†”๋ผ์‹œ๋„ํ•  ๋•Œ ๋ผ์Œ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์Œ์•…์„ ๋“ค์„ ๋•Œ๋Š” ํ˜„์•…๊ธฐ๋ฉด ํ˜„์˜ ์ง„๋™, ๊ด€์•…๊ธฐ๋ฉด ์ž…์ˆ ์ด๋‚˜ ๋ฆฌ๋“œ์˜ ์ง„๋™์ด ์ฆํญ๋œ ๊ฒƒ, ๋…ธ๋ž˜๋ผ๋ฉด ์„ฑ๋Œ€์˜ ์ง„๋™์„ ๋“ฃ๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์•„๋ฌด๋ฆฌ ๊ฐ์„ฑํ„ฐ์ง€๋Š” ์Œ์•…๋„ ๊ณต๋Œ์ด ์†์— ๊ฑธ๋ฆฌ๋ฉด ์ด๋ ‡๊ฒŒ ๋ถ„ํ•ด๋  ์ˆ˜ ์žˆ๋‹ค.

    s oche 우리가 듣는 아름다운 선율의 음악도 뜯어보면 그냥 진동 주파수 덩어리다.

    ์ด๋•Œ ์ด ์ง„๋™์€ ์ž์—ฐ๊ณ„์—์„œ ๋ฐœ์ƒํ•œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์•„๋‚ ๋กœ๊ทธ(Analog)์˜ ํ˜•ํƒœ๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค. ์‚ฌ์‹ค ์ž์—ฐ๊ณ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฑฐ์‹œ์ ์ธ ์‹ ํ˜ธ๋Š” ์•„๋‚ ๋กœ๊ทธ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋น›์˜ ๋ฐ๊ธฐ๊ฐ€ ๋ณ€ํ•œ๋‹ค๊ฑฐ๋‚˜ ๋ฐ”๋žŒ์˜ ์„ธ๊ธฐ๊ฐ€ ๋ณ€ํ•œ๋‹ค๊ฑฐ๋‚˜ ์†Œ๋ฆฌ์˜ ํฌ๊ธฐ๊ฐ€ ๋ณ€ํ•˜๋Š” ๋“ฑ์˜ ์‹ ํ˜ธ๋ฅผ ๋งํ•œ๋‹ค.

    ์†Œ๋ฆฌ๋Š” ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋‹ค

    ์•„๋‚ ๋กœ๊ทธ๋Š” ์‹ ํ˜ธ๋‚˜ ์ž๋ฃŒ๋ฅผ ์—ฐ์†์ ์ธ ๋ฌผ๋ฆฌ๋Ÿ‰์œผ๋กœ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ์ด๋‹ค. ์ด๊ฒŒ ์—ฐ์†์ ์ธ ๋ฌผ๋ฆฌ๋Ÿ‰์ด๋ผ๊ณ  ํ•˜๋ฉด ๋ญ”๊ฐ€ ์ „๋ฌธ์ ์ด๊ณ  ์–ด๋ ค์›Œ๋ณด์ด๋Š”๋ฐ ํ’€์–ด๋ณด๋ฉด ์‚ฌ์‹ค ๋ณ„ ๊ฑฐ ์—†๋‹ค. ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง‘์ค‘ํ•ด์•ผํ•  ๋‹จ์–ด๋Š” ๋ฌผ๋ฆฌ๋Ÿ‰์ด ์•„๋‹Œ ์—ฐ์†์ ์ด๋‹ค.

    analog 가로 축은 시간, 세로 축은 전압이다. 아날로그 신호는 아무리 쪼개도 끝이 없는 연속성을 가진다

    ๊ทธ๋ ‡๋‹ค๋ฉด ์—ฐ์†์ ์ด๋ผ๋Š” ๊ฑด ๋ฌด์Šจ ๋ง์ผ๊นŒ?

    ์—ฐ์†์„ฑ์˜ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋Š” ๋ฐ”๋กœ ์ˆ˜์ด๋‹ค. ์ž ์šฐ๋ฆฌ๊ฐ€ ์ด์ œ 1๋ถ€ํ„ฐ 2๊นŒ์ง€ ๊ฑธ์–ด๊ฐ„๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” 1์—์„œ 2๊นŒ์ง€ ๊ฑธ์–ด๊ฐ€๋Š” ๋™์•ˆ ๋ช‡๊ฐœ์˜ ์ˆ˜๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ์„๊นŒ?

    ์šฐ์„  ์ ˆ๋ฐ˜์ด ๋˜๋Š” ์œ„์น˜์— ์žˆ๋Š” 1.5๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ ์ ˆ๋ฐ˜์ธ 1.25๋„ ์žˆ์„ ๊ฒƒ์ด๋ฉฐ ๋˜ ๊ทธ๊ฒƒ์˜ ์ ˆ๋ฐ˜์ธ 1.125๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ณ„์† ์ˆ˜๋ฅผ ์ชผ๊ฐœ๋‹ค ๋ณด๋ฉด ์šฐ๋ฆฌ๋Š” ๊ฒฐ๊ตญ ์ด๊ฒŒ ์˜๋ฏธ์—†๋Š” ์‚ฝ์งˆ์ด๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ๊ฒŒ ๋œ๋‹ค. n/2๋ฅผ ๊ณ„์† ํ•œ๋“ค ๋์ด ์žˆ์„๋ฆฌ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋งŒ์•ฝ 10โˆ’1000010^{-10000} ๋‹จ์œ„๊นŒ์ง€ ์ชผ๊ฐ ๋‹ค ํ•ด๋„ ์šฐ๋ฆฌ๋Š” ๊ทธ ์ˆ˜๋ฅผ ๊ณ„์† ํ•ด์„œ ๋ฌดํ•œํžˆ ์ชผ๊ฐค ์ˆ˜ ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฐ ์„ฑ์งˆ์„ ์—ฐ์†์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

    ์ด์ œ ์—ฐ์†์ ์ด๋ผ๋Š” ๋ง์ด ์กฐ๊ธˆ ์ดํ•ด๊ฐ€ ๋˜์—ˆ๊ธธ ๋ฐ”๋ž€๋‹ค.

    ์ปดํ“จํ„ฐ๊ฐ€ ์†Œ๋ฆฌ๋ฅผ ๋“ฃ๋Š” ๋ฐฉ๋ฒ•

    ๊ทผ๋ฐ ์—ฌ๋Ÿฌ๋ถ„๋„ ์•Œ๋‹ค์‹œํ”ผ ์ปดํ“จํ„ฐ๋Š” 0๊ณผ 1๋ฐ–์— ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฐ”๋ณด๋‹ค. ์ด ๋ฐฉ์‹์„ ์šฐ๋ฆฌ๋Š” ๋””์ง€ํ„ธ(Digital)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ๊ทธ๋ž˜์„œ 0๊ณผ 1๋ฐ–์— ๋ชจ๋ฅด๋Š” ์ปดํ“จํ„ฐ๋Š” ์—ฐ์†์„ฑ์„ ๊ฐ€์ง„ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ฅผ ์ดํ•ดํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

    ๊ทธ๋ ‡๋‹ค๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์ž์—ฐ์—์„œ ๋ฐœ์ƒํ•œ ์•„๋‚ ๋กœ๊ทธ ํ˜•ํƒœ์ธ ์†Œ๋ฆฌ๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ๋“ฃ๊ฒŒ ํ•ด์ฃผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

    ๊ฐ„๋‹จํ•˜๋‹ค. ์•„๋‚ ๋กœ๊ทธ๋ฅผ ๋””์ง€ํ„ธ๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋œ๋‹ค. ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ์ธ ์†Œ๋ฆฌ๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ์•Œ์•„ ๋“ค์„ ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณผ์ •์„ ์•Œ๊ณ ๋‚˜๋ฉด Web Audio API๊ฐ€ ์šฐ๋ฆฌ์—๊ฒŒ ์ฃผ๋Š” ์ •๋ณด๋“ค์ด ๋ญ˜ ์˜๋ฏธํ•˜๋Š” ์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿผ ์ง€๊ธˆ๋ถ€ํ„ฐ ์•„๋‚ ๋กœ๊ทธ๋ฅผ ๋””์ง€ํ„ธ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ณด์ž.

    ์•„๋‚ ๋กœ๊ทธ๋ฅผ ๋””์ง€ํ„ธ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ช‡๊ฐ€์ง€ ์ˆœ์„œ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค. ์ด ์ˆœ์„œ์—์„œ ์–ด๋–ค ๊ฐ’๋“ค์„ ์‚ฌ์šฉํ•˜๋ƒ์— ๋”ฐ๋ผ์„œ ๋””์ง€ํ„ธ๋กœ ๋ณ€๊ฒฝ๋œ ์†Œ๋ฆฌ์˜ ํ•ด์ƒ๋„, ์ฆ‰ ์Œ์งˆ์ด ๊ฒฐ์ •๋œ๋‹ค. ์ด๋•Œ ๋‚˜์˜ค๋Š” ๋‹จ์–ด๊ฐ€ ๋ฐ”๋กœ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ(Sample Rate)์™€ ๋น„ํŠธ ๋ ˆ์ดํŠธ(Bit Rate)์ด๋‹ค.

    encoder 인코더 프로그램 쓸 때 뭘 만져야 할지 모르게 만드는 어려운 단어들

    ๋‹จ์–ด๋Š” ์–ด๋ ค์›Œ ๋ณด์ด์ง€๋งŒ ์‚ฌ์‹ค ๊ฐ„๋‹จํ•˜๋‹ค. ๊ฒฐ๊ตญ ์†Œ๋ฆฌ๋Š” ๊ฐ€๋กœ ์ถ•์€ ์‹œ๊ฐ„(Time), ์„ธ๋กœ ์ถ•์€ ์ง„ํญ(Amplitude)์œผ๋กœ ์ •์˜๋œ ๊ณต๊ฐ„์— ๊ทธ๋ ค์ง„ 2์ฐจ์›์˜ ์ง„๋™ ์ฃผํŒŒ์ˆ˜ ๋ฐ์ดํ„ฐ์ด๋‹ค. ์ด๋•Œ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” ๊ฐ€๋กœ ์ถ•์˜ ํ•ด์ƒ๋„, ๋น„ํŠธ ๋ ˆ์ดํŠธ๋Š” ์„ธ๋กœ ์ถ•์˜ ํ•ด์ƒ๋„๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๊ฐ’๋“ค์€ ์•„๋‚ ๋กœ๊ทธ๋ฅผ ๋””์ง€ํ„ธ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์ฒซ๋ฒˆ์งธ ๋‹จ๊ณ„์ธ ์ƒ˜ํ”Œ๋ง(Sampling)์—์„œ ํ™œ์šฉ๋œ๋‹ค.

    ์ƒ˜ํ”Œ๋ง(Sampling)

    ์ƒ˜ํ”Œ๋ง์€ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ฅผ ๋””์ง€ํ„ธ ์‹ ํ˜ธ๋กœ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•œ ์ฒซ๋ฒˆ์งธ ๋‹จ๊ณ„์ด๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ์ธ ์†Œ๋ฆฌ๋Š” ์—ฐ์†์ ์ธ ์‹ ํ˜ธ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปดํ“จํ„ฐ๊ฐ€ ์ด ์‹ ํ˜ธ๋ฅผ ๊ทธ๋Œ€๋กœ ์ดํ•ดํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋งˆ์ดํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ๋ฆฌ๋ฅผ ๋…น์Œํ•  ๋•Œ, ์ด ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋Š” ๊ฒฐ๊ตญ ์ „๊ธฐ ์‹ ํ˜ธ๋กœ ๋ณ€ํ™˜๋˜์–ด ์ปดํ“จํ„ฐ์—๊ฒŒ ์ฃผ์–ด์ง„๋‹ค. ์†Œ๋ฆฌ์˜ ์ง„๋™์ด ๋งˆ์ดํฌ ์•ˆ์— ์žˆ๋Š” ์žฅ์น˜์— ์ „๋‹ฌ๋˜๋ฉด ์ด ์žฅ์น˜๊ฐ€ ์ „์••์„ ์˜ฌ๋ ธ๋‹ค ๋‚ด๋ ธ๋‹ค ํ•˜๋ฉด์„œ ๋ณ€ํ™˜ํ•˜๋Š” ์›๋ฆฌ์ด๋‹ค.

    ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ์˜ ๋ฐ”๋ณด ์ปดํ“จํ„ฐ๋Š” ์ด๋ ‡๊ฒŒ ๊นŒ์ง€ ํ•ด์ค˜๋„ ์ด ์ „๊ธฐ ์‹ ํ˜ธ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์—†๋‹ค.

    ๊ทธ๋ž˜์„œ ์ปดํ“จํ„ฐ๋Š” ์—ฐ์†์ ์ธ ์ „๊ธฐ ์‹ ํ˜ธ๋ฅผ ์ธก์ •ํ•˜๊ธฐ ์œ„ํ•ด ํŠน์ • ํƒ€์ด๋ฐ์„ ์ •ํ•ด์„œ ์ด ํƒ€์ด๋ฐ๋งˆ๋‹ค ๋‚ด๊ฐ€ ์ „์••์„ ์ธก์ •ํ• ๊ฒŒ!๋ผ๋Š” ๊ผผ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ปดํ“จํ„ฐ๊ฐ€ ๊ผผ์ˆ˜๋ฅผ ์“ฐ๋Š” ์ด ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ณด๋ฉด ์ด๋Ÿฐ ๋Š๋‚Œ์ด๋‹ค.

    sampling

    ์œ„ ๊ทธ๋ฆผ์— ๋‚˜ํƒ€๋‚œ ๋นจ๊ฐ„ ์ ์ด ์ปดํ“จํ„ฐ๊ฐ€ ์ „์••์„ ์ธก์ •ํ•œ ํƒ€์ด๋ฐ์ด๋‹ค. ์ปดํ“จํ„ฐ๋Š” ํŠน์ • ํƒ€์ด๋ฐ์— ์ „๊ธฐ ์‹ ํ˜ธ๋ฅผ ์ธก์ •ํ•˜๊ณ  ๊ทธ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค. ๋นจ๊ฐ„ ์ ์˜ ์œ„์น˜๋ฅผ ๋ณด๋ฉด ์ € ์‹ ํ˜ธ๋Š” [10, 20, 30, 27, 19, 8...] ๋ญ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ธก์ •์ด ๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋•Œ ์ € ๋นจ๊ฐ„ ์ ์„ ๋” ์„ธ๋ฐ€ํ•˜๊ฒŒ, ์ฆ‰ ์ปดํ“จํ„ฐ๊ฐ€ ์ƒ˜ํ”Œ ์ธก์ •์„ ํ•˜๋Š” ๊ฐ„๊ฒฉ์ด ์งง์„ ์ˆ˜๋ก ์šฐ๋ฆฌ๋Š” ์›๋ž˜ ์‹ ํ˜ธ์— ๊ฐ€๊นŒ์šด ๊ฐ’์„ ์ธก์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

    high low sampling 신호 내부의 사각형이 컴퓨터가 이해한 신호의 모양이다.

    ์ด๋•Œ ์ด ์‹ ํ˜ธ๋ฅผ ์ธก์ •ํ•˜๋Š” ๊ฐ„๊ฒฉ์„ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ(Sample Rate)๋ผ๊ณ  ํ•˜๊ณ  ์‹ ํ˜ธ๋ฅผ ์ธก์ •ํ•˜๋Š” ๊ณผ์ • ์ž์ฒด๋ฅผ ์ƒ˜ํ”Œ๋ง(Sampling)์ด๋ผ๊ณ  ํ•œ๋‹ค. ๋‹น์—ฐํžˆ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๊ฐ€ ๋†’์„ ์ˆ˜๋ก ์†Œ๋ฆฌ์˜ ํ•ด์ƒ๋„, ์ฆ‰ ์Œ์งˆ์ด ๋” ์ข‹์„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ํŠนํžˆ ๋†’์€ ์ฃผํŒŒ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์†Œ๋ฆฌ, ์ฆ‰ ๊ณ ์Œ์˜ ํ•ด์ƒ๋„๊ฐ€ ํ™•์—ฐํ•˜๊ฒŒ ์ข‹์•„์ง„๋‹ค.

    ๋ณดํ†ต CD์˜ ์Œ์งˆ์ด 44.1kHz, TV๋‚˜ ๋ผ๋””์˜ค ๋ฐฉ์†ก์ด 48kHz์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ์ด๋Š” ์•ฝ 1์ดˆ์— 44,100๋ฒˆ, 48,000๋ฒˆ ์ƒ˜ํ”Œ์„ ์ธก์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ € ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” ์–ด๋–ค ๊ธฐ์ค€์œผ๋กœ ์ •ํ•˜๋Š” ๊ฑธ๊นŒ?

    ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ(Sample Rate)๋ฅผ ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž

    ๋ฐฉ๊ธˆ ์„ค๋ช…ํ–ˆ๋“ฏ์ด CD์˜ ๊ฒฝ์šฐ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๊ฐ€ 44.1kHz์ด๋‹ค. ๊ทธ ๋ง์ธ ์ฆ‰์Šจ CD์— ๋“ค์–ด๊ฐ€๋Š” ์˜ค๋””์˜ค๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ฅผ 1์ดˆ์— 44,100๋ฒˆ ์ธก์ •ํ•œ ๊ฒฐ๊ณผ๋ฌผ์ธ ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

    ํ•˜์ง€๋งŒ ์ธ๊ฐ„์ด ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์ธ ๊ฐ€์ฒญ์ฃผํŒŒ์ˆ˜๋Š” 20hz ~ 20kHz ๋ฐ–์— ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทผ๋ฐ ์™œ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” 44.1kHz, 48kHz์ฒ˜๋Ÿผ ํ›จ์”ฌ ํฌ๊ฒŒ ์žก๋Š” ๊ฒƒ์ผ๊นŒ?

    ์–ด์ฐจํ”ผ ์ธ๊ฐ„์€ 1์ดˆ์— 20,000๋ฒˆ ์ง„๋™ํ•˜๋Š” ์†Œ๋ฆฌ๊นŒ์ง€๋ฐ–์— ๋“ค์„ ์ˆ˜ ์—†์–ด์„œ 44,100๋ฒˆ ์ง„๋™ํ•˜๋Š” ์†Œ๋ฆฌ๋ฅผ ๋…น์Œํ•ด๋„ ์–ด์ฐจํ”ผ ๋“ค์„ ์ˆ˜ ์—†๋Š”๋ฐ?

    ์ด ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์€ ์†Œ๋ฆฌ์˜ ์ง„๋™ ์‚ฌ์ดํด์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€๋ฅผ ๋ณด๋ฉด ์ดํ•ด๊ฐ€ ๋œ๋‹ค.

    sine wave

    ๊ธฐ๋ณธ์ ์œผ๋กœ ์˜ค๋””์˜ค ์ฃผํŒŒ์ˆ˜๋Š” ์ด๋ ‡๊ฒŒ ํ•˜๋‚˜์˜ ์‚ฌ์ดํด ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ์ง€๋Š”๋ฐ, ์ด๋•Œ ์œ„๋กœ ์˜ฌ๋ผ๊ฐ€๋Š” + ๋ถ€๋ถ„์ด ๊ณต๊ธฐ๊ฐ€ ์••์ถ•๋˜๋Š” ๋ถ€๋ถ„์ด๊ณ  ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐ€๋Š” - ๋ถ€๋ถ„์ด ๋‹ค์‹œ ๊ณต๊ธฐ๊ฐ€ ํŒฝ์ฐฝํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค.

    ์œ„์—์„œ ๊ณ„์† ์„ค๋ช…ํ–ˆ๋˜ ๋Œ€๋กœ ์†Œ๋ฆฌ๋ž€ ๊ณง ์ง„๋™์ด๊ณ , ์šฐ๋ฆฌ๊ฐ€ ๋Š๋ผ๋Š” ๊ฒƒ์€ ๊ทธ ์ง„๋™์œผ๋กœ ์ธํ•œ ๊ณต๊ธฐ์˜ ๋–จ๋ฆผ์ด๋ฏ€๋กœ ์••์ถ• -> ํŒฝ์ฐฝ -> ์••์ถ•๊นŒ์ง€ ๋ชจ๋‘ ๋“ค์–ด์•ผ ๋–จ๋ ธ๋‹ค!๋ผ๊ณ  ๋Š๋‚„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ๋“ค์„ ์ˆ˜ ์žˆ๋Š” 20,000๋ฒˆ์˜ ์ง„๋™์€ ์ด ์‚ฌ์ดํด์ด 1์ดˆ์— 20,000๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š” ์†Œ๋ฆฌ๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

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

    ๊ทธ๋ž˜์„œ ์˜ค๋””์˜ค ์‹ ํ˜ธ์˜ ํ•œ ์‚ฌ์ดํด์„ ์ œ๋Œ€๋กœ ์ธก์ •ํ•˜๋ ค๋ฉด + ๋ฐฉํ–ฅ์˜ ๋งจ ์œ„์˜ ๊ผญ์ง€์  ํ•˜๋‚˜์™€ - ๋ฐฉํ–ฅ์˜ ๋งจ ๋ฐ‘์˜ ๊ผญ์ง€์  ํ•˜๋‚˜๋ฅผ ๋ชจ๋‘ ์ธก์ •ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์†Œ 2๋ฒˆ์€ ์ธก์ •์„ ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ธ๊ฐ„์ด ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ๊ฐ€์žฅ ๋†’์€ ์†Œ๋ฆฌ์ธ ์ดˆ๋‹น 20,000๋ฒˆ์˜ ๋–จ๋ฆผ์ธ 20kHz์„ ์ œ๋Œ€๋กœ ์ธก์ •ํ•˜๋ ค๋ฉด ์ปดํ“จํ„ฐ๋Š” ์ตœ์†Œํ•œ 1์ดˆ์— 20,000 * 2 = 40,000๋ฒˆ ์ธก์ •์„ ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    ์ด๊ฒŒ ๋ฐ”๋กœ CD๊ฐ€ ์™œ 44.1kHz์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ด์œ ๋‹ค. ์ด๊ฑธ ๋‚˜์ดํ€ด์ŠคํŠธ ์ด๋ก (Nyquist Theorem)์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ฆ‰, ๋‚˜์ดํ€ด์ŠคํŠธ ์ด๋ก ์„ ํ•œ๋งˆ๋””๋กœ ์ •๋ฆฌํ•˜์ž๋ฉด

    ์ธก์ •ํ•˜๊ณ  ์‹ถ์€ ์˜ค๋””์˜ค ์ฃผํŒŒ์ˆ˜์žˆ์ง€? ์˜ค๋””์˜ค ์‹ ํ˜ธ ์ œ๋Œ€๋กœ ๋‹ค ์‚ด๋ฆฌ๊ณ  ์‹ถ์œผ๋ฉด ์ตœ์†Œํ•œ ๊ทธ ์ฃผํŒŒ์ˆ˜๋ณด๋‹ค ๋‘๋ฐฐ๋Š” ๋” ๋น ๋ฅด๊ฒŒ ์ธก์ •ํ•ด์•ผ๋œ๋‹ค.
    ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ์ตœ์†Œํ•œ ์ธก์ •ํ•˜๊ณ  ์‹ถ์€ ์˜ค๋””์˜ค ์ฃผํŒŒ์ˆ˜์˜ ๋‘๋ฐฐ ์‚ฌ์ด์ฆˆ์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ์ค€๋น„ํ•˜๋ ด.

    ์ธ ๊ฒƒ์ด๋‹ค. ๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ๋˜ ์˜๋ฌธ์ด ์ƒ๊ธด๋‹ค. ์ € ์ด๋ก ์— ๋”ฐ๋ฅด๋ฉด ์ธ๊ฐ„์˜ ๊ฐ€์ฒญ์ฃผํŒŒ์ˆ˜๋Š” 20,000hz๋‹ˆ๊นŒ ๋”ฑ 40,000๋ฒˆ๋งŒ ์ธก์ •ํ•˜๋ฉด ์ธ๊ฐ„์ด ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ์†Œ๋ฆฌ๋Š” ๋‹ค ๋…น์Œํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์™œ 44,100๋ฒˆ์ด๋‚˜ 48,000๋ฒˆ๊นŒ์ง€ ์ธก์ •ํ•˜๋Š” ๊ฑธ๊นŒ?

    ์ž์—ฐ์—๋Š” ์ธ๊ฐ„๋งŒ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ด๋Ÿฐ ์นœ๊ตฌ๋“ค๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    dolphin 안녕하세요 자연계 고음의 절대강자입니다. 쉬즈곤 정도는 밥먹으면서도 부를 수 있슴다.

    ์‚ฌ์‹ค ์ž์—ฐ์—๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋“ฃ์ง€ ๋ชปํ•˜๋Š” ํ›จ์”ฌ ๋†’์€ ์†Œ๋ฆฌ๋“ค๋„ ์กด์žฌํ•œ๋‹ค. ๋‹จ์ง€ ์šฐ๋ฆฌ๊ฐ€ 20kHz๊นŒ์ง€๋ฐ–์— ๋ชป ๋“ค์„ ๋ฟ์ด๋‹ค. ๋ญ ๋ฐ•์ฅ๋‚˜ ๋Œ๊ณ ๋ž˜ ๊ฐ™์€ ์นœ๊ตฌ๋“ค์€ ํ›จ์”ฌ ๊ณ ์Œ์—ญ๋Œ€์˜ ์†Œ๋ฆฌ๋ฅผ ๋‚ด์ง€ ์•Š๋Š”๊ฐ€?

    ๊ทผ๋ฐ ์ด ์†Œ๋ฆฌ๊ฐ€ 40kHz์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ์ค€๋น„ํ•œ ๊ทธ๋ฆ‡์— ๋“ค์–ด์˜ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ปดํ“จํ„ฐ๋Š” 1์ดˆ์— 20,000๋ฒˆ์˜ ์‚ฌ์ดํด์„ ๋„๋Š” ์†Œ๋ฆฌ๋ฅผ ์ œ๋Œ€๋กœ ์ธก์ •ํ•˜๋ ค๊ณ  1์ดˆ์— 40,000๋ฒˆ ์ „์••์„ ์ธก์ •ํ•˜๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ ๋งŒ์•ฝ 1์ดˆ์— 30,000๋ฒˆ์˜ ์‚ฌ์ดํด์„ ๋„๋Š” ํ›จ์”ฌ ๋” ๋†’์€ ์ฃผํŒŒ์ˆ˜์˜ ์†Œ๋ฆฌ๊ฐ€ ๋“ค์–ด์™€๋ฒ„๋ฆฐ๋‹ค๋ฉด?

    nyquist error

    ์ •๋‹ต. ์ ์„ ์ด์ƒํ•œ๋ฐ๋‹ค๊ฐ€ ์ฐ๋Š”๋‹ค.

    ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ์ปดํ“จํ„ฐ๊ฐ€ ์ ์„ ์ฐ๋Š” ๊ฐ„๊ฒฉ, ์ฆ‰ ์ „์••์„ ์ธก์ •ํ•˜๋Š” ๊ฐ„๊ฒฉ๋ณด๋‹ค ๋“ค์–ด์˜จ ์‹ ํ˜ธ์˜ ์‚ฌ์ดํด์ด ๋” ์งง๋‹ค. ๊ทธ๋ž˜์„œ ์ปดํ“จํ„ฐ๊ฐ€ ์ฐ์€ ์ ์„ ๋ณด๋ฉด ์‹ ํ˜ธ์˜ ๊ผญ์ง€์ ์ด ์•„๋‹Œ ์–ด์ค‘๊ฐ„ํ•œ ์–ด๋”˜๊ฐ€์— ์ฐํžŒ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ ๋‚˜์ดํ€ด์ŠคํŠธ ์ด๋ก ์˜ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•จ์ •์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ € ์–ด์ค‘๊ฐ„ํ•œ๋ฐ ์ฐํžŒ ์ ๋“ค์„ ์ด์–ด๋ณธ ํŒŒ๋ž€์ƒ‰ ์„ ์„ ๋ณด๋ฉด ๊ฒฐ๊ตญ ๋‚ฎ์€ ์ฃผํŒŒ์ˆ˜๊ฐ€ ๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

    ์šฐ๋ฆฌ ๊ท€์— ์•„์ฃผ ์ž˜ ๋“ค๋ฆฐ๋‹ค. ์ฐธ ์†Œ๋ฆ„๋‹๋Š” ์ˆœ๊ฐ„์ด๋‹ค! ๋…น์Œํ•  ๋•Œ๋Š” ๋ถ„๋ช…ํžˆ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ๋“ค๋ ธ๋Š”๋ฐ ๋…น์Œํ•œ ๊ฑธ ๋“ค์–ด๋ณด๋‹ˆ ์ด์ƒํ•œ ์†Œ๋ฆฌ๊ฐ€ ๋…น์Œ๋˜์–ด์žˆ์œผ๋‹ˆ ๋ง์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด ํ˜„์ƒ์„ ๊ณ ์ŠคํŠธ ์ฃผํŒŒ์ˆ˜(Ghost Frequency)๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

    ์•„๋‹ˆ ๊ทธ๋Ÿฌ๋ฉด ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ํŒํŒ ์˜ฌ๋ฆฌ๋ฉด ๋˜์ž–์•„! ๋†’์€ ์†Œ๋ฆฌ๋„ ์ œ๋Œ€๋กœ ๋…น์Œ๋˜๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ์•„๋‹Œ๊ฐ€?

    ํ•˜์ง€๋งŒ ์ด ๋””์ง€ํ„ธ ์˜ค๋””์˜ค ๊ธฐ์ˆ ์ด ์ฒ˜์Œ ์‚ฌ์šฉ๋˜๊ธฐ ์‹œ์ž‘ํ•œ๊ฒŒ 1970๋…„๋Œ€์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์ž‘์ • ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ์˜ฌ๋ฆฌ๊ธฐ์—๋Š” ํ•˜๋“œ์›จ์–ด ์šฉ๋Ÿ‰์ด ๋ชป ๋”ฐ๋ผ๊ฐ”์—ˆ๋‹ค.

    ๊ทธ๋ž˜์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•์ด ๋ฐ”๋กœ LPF(Low Pass Filter)์ด๋‹ค. ์ด ํ•„ํ„ฐ๋Š” ์ „๊ธฐ ์ชฝ ๊ณต๋ถ€ํ•˜์‹  ๋ถ„๋“ค์€ ๋งค์šฐ ์ต์ˆ™ํ• ํ…๋ฐ, ๋ง ๊ทธ๋Œ€๋กœ ๋‚ฎ์€(Low) ์ฃผํŒŒ์ˆ˜๋งŒ ํ†ต๊ณผ(Pass)์‹œํ‚ค๋Š” ํ•„ํ„ฐ์ด๋‹ค. ์˜ค๋””์˜ค ๋…น์Œ์„ ํ• ๋•Œ LPF๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ธ๊ฐ„์˜ ๊ฐ€์ฒญ์ฃผํŒŒ์ˆ˜๋ณด๋‹ค ๋†’์€ ์†Œ๋ฆฌ๋Š” ๋‹ค ์ž˜๋ผ๋ฒ„๋ฆฌ๊ณ  ์ธ๊ฐ„์˜ ๊ฐ€์ฒญ์ฃผํŒŒ์ˆ˜ ์˜์—ญ์˜ ์†Œ๋ฆฌ๋งŒ ํ†ต๊ณผ์‹œํ‚ค๋ฉด ๋ฐฉ๊ธˆ ์–˜๊ธฐํ•œ ๊ณ ์ŠคํŠธ ์ฃผํŒŒ์ˆ˜๊ฐ€ ์ƒ๊ธธ ์ผ๋„ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ๊ทผ๋ฐ ๋˜ ์•„๋‚ ๋กœ๊ทธ ์‹ ํ˜ธ๋ผ๋Š” ๊ฒŒ ๊ทธ๋ ‡๊ฒŒ ๋ฌด ์ž๋ฅด๋“ฏ์ด ์‹น๋š! ์ž˜๋ฆฌ๋Š” ๊ฒŒ ์•„๋‹ˆ๋‹ค.

    cut off

    LPF๋ฅผ ์จ๋„ ๊ฒฐ๊ตญ ์ž˜๋ฆฐ ๋ถ€๋ถ„์ด ์ €๋ ‡๊ฒŒ ๋น„์Šค๋“ฌํ•˜๊ฒŒ ๊บพ์ด๋ฉด์„œ ์•ฝ๊ฐ„ ์•„์‰ฌ์šด ๋ถ€๋ถ„์ด ๋‚จ๊ฒŒ๋œ๋‹ค. ์ด๋•Œ ๊ทธ๋ฆผ์— ํ‘œ์‹œ๋œ ํ—ˆ์šฉ ๋ฒ”์œ„์ธ -3db ๋ฐ‘์œผ๋กœ ๋–จ์–ด์ง€๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ๊ณณ์„ Cut Off๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์ €๊ธฐ์—์„œ๋ถ€ํ„ฐ ์‹ ํ˜ธ๊ฐ€ ์ž˜๋ ธ๋‹ค๊ณ  ์น˜๊ฒ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿผ Cut Off๋˜๋Š” ๋ถ€๋ถ„์„ 20kHz๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ฐ‘์œผ๋กœ ๋‚ด๋ฆฌ๋ฉด 20kHz ์–ธ์ €๋ฆฌ์—์„œ ์‹ ํ˜ธ๊ฐ€ ์‚ฌ๋ผ์ง€๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ๋„ ๋“ค์ง€๋งŒ ๊ทธ ๋ฌธ์ œ ๋•Œ๋ฌธ์— 20kHz์˜ ์ฃผํŒŒ์ˆ˜ ์˜์—ญ์„ ์ „๋ถ€ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฑด ๋„ˆ๋ฌด ์•„๊น๋‹ค๊ณ  ํŒ๋‹จ์ด ๋“ค์—ˆ๋‚˜๋ณด๋‹ค.

    ๊ทธ๋ž˜์„œ Cut Off๋ฅผ ๋”ฑ 20kHz์— ๋งž์ถ”๊ณ  ๋‚จ๋Š” ๋ถ€๋ถ„์€ ๊ทธ๋ƒฅ ๊ฐ์ˆ˜ํ•˜์ž๊ณ  ํ•ฉ์˜๊ฐ€ ๋œ ๊ฒƒ์ด๋‹ค. ๋‹น์‹œ ๊ธฐ์ˆ ๋กœ ์ € ๋‚จ๋Š” ๋ถ€๋ถ„์„ ์ค„์ด๊ณ  ์ค„์—ฌ์„œ ๋งž์ถ˜๊ฒŒ ๋”ฑ 2,050hz์˜€๋‹ค.

    ๊ทธ๋Ÿผ ์ด์ œ ๋‚จ๋Š” ๋ถ€๋ถ„๊ณผ ๊ฐ€์ฒญ์ฃผํŒŒ์ˆ˜๋ฅผ ํ•ฉ์ณ๋ณด๋ฉด 22,050hz๊ฐ€ ๋œ๋‹ค. ๋‚˜์ดํ€ด์ŠคํŠธ ์ด๋ก ์— ๋”ฐ๋ฅด๋ฉด ์šฐ๋ฆฌ๋Š” ์ตœ์†Œํ•œ 2๋ฐฐ์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ์ค€๋น„ํ•ด์•ผ ์ด ์‹ ํ˜ธ๋ฅผ ์ œ๋Œ€๋กœ ์ธก์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ฒฐ๊ตญ CD์˜ ํ‘œ์ค€ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๊ฐ€ 44,100hz = 44.1kHz๊ฐ€ ๋œ ๊ฒƒ์ด๋‹ค. ๋ญ ๊ทธ ์™ธ์—๋„ ๋‹น์‹œ ๊ธฐ์ˆ ์˜ ํ•œ๊ณ„ ์™ธ์—๋„ ๊ธฐ์—…๋“ค๋ผ๋ฆฌ ์‹ธ์šฐ๊ธฐ๋„ ํ•˜๊ณ  ์–ด๋ฅธ์˜ ์‚ฌ์ •๋„ ์žˆ๋Š” ๋“ฑ ๊ตญ์ œ ํ‘œ์ค€์„ ์ •ํ•  ๋•Œ ๋Š˜ ๋ฐœ์ƒํ•˜๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ด์Šˆ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ ๋Œ€ํ‘œ์ ์ธ ๊ธฐ์ˆ ์ ์ธ ์ด์Šˆ๋Š” ์ด ์ด์œ ์˜€๋‹ค.

    ๊ทธ ํ›„ 48kHz, 96kHz, 192kHz ๋“ฑ์˜ ๋†’์€ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” ๊ทธ๋ƒฅ ๋””๋ฐ”์ด์Šค๊ฐ€ ๋ฐœ์ „ํ•˜๋ฉด์„œ ๊ธฐ์ˆ ์ ์ธ ์ œํ•œ์ด ์—†์–ด์กŒ์œผ๋‹ˆ๊นŒ โ€œ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” ํด์ˆ˜๋ก ์ข‹์ง€! ๋ฟœ๋ฟœโ€ํ•˜๋ฉด์„œ ๋Š˜๋ฆฐ ๊ฒƒ์ด๋‹ค.

    ๋น„ํŠธ ๋ ˆ์ดํŠธ(Bit Rate)

    ๋น„ํŠธ ๋ ˆ์ดํŠธ๋Š” ์ƒ˜ํ”Œ๋ง์— ๋น„ํ•˜๋ฉด ์ดˆ ๊ฐ„๋‹จํ•˜๋‹ค. ํŠนํžˆ ์šฐ๋ฆฌ ๊ฐ™์€ ๊ฐœ๋ฐœ๋žญ์ด๋“ค์—๊ฒŒ ์ต์ˆ™ํ•œ ์ด๋ฆ„์ธ Bit๊ฐ€ ๋ถ™์–ด์žˆ์ง€ ์•Š์€๊ฐ€? ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๊ฐ€ ์†Œ๋ฆฌ์˜ ๊ฐ€๋กœ ํ•ด์ƒ๋„ ์—ญํ• ์„ ํ•œ๋‹ค๋ฉด ๋น„ํŠธ ๋ ˆ์ดํŠธ๋Š” ์„ธ๋กœ ํ•ด์ƒ๋„ ์—ญํ• ์„ ํ•œ๋‹ค.

    ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋น„ํŠธ ๋ ˆ์ดํŠธ๋„ CD๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ค๋ช…ํ•˜๋Š” ๊ฒŒ ๋ณดํŽธ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ CD๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.

    CD์˜ ๋น„ํŠธ ๋ ˆ์ดํŠธ๋Š” 16bit์ธ๋ฐ ์ด๊ฑด ๋ง ๊ทธ๋Œ€๋กœ ์„ธ๋กœ๋กœ 16bit ๋งŒํผ์˜ ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์–˜๊ธฐ์ด๋‹ค. ์•„๊นŒ ์œ„์—์„œ ์„ค๋ช…ํ•œ ์ƒ˜ํ”Œ๋ง์„ ์ง„ํ–‰ํ•  ๋•Œ ์ „์••์„ ์ธก์ •ํ–ˆ์—ˆ๋‹ค. ์ด๋•Œ ์ปดํ“จํ„ฐ๊ฐ€ ์ธก์ •ํ•œ ์ด ์ „์••์˜ ๊ฐ’์„ ์–ผ๋งˆ๋‚˜ ์„ฌ์„ธํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š๋ƒ๋ฅผ ๋น„ํŠธ ๋ ˆ์ดํŠธ๊ฐ€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 16bit๋ฉด 16์ž๋ฆฌ์˜ ์ด์ง„๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๊ณ  216=655362^{16} = 65536์ด๋‹ˆ๊นŒ 0~65536๊นŒ์ง€ ์ด 65537๊ฐœ์˜ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

    bitrate 비트 레이트가 높을 수록 아날로그 신호 내부의 막대가 더 꼼꼼하게 채워지는 것을 볼 수 있다.
    +와 -를 합쳐서 비트를 세는 `signed`이기 때문에 그림에는 50% 씩만 표현되어있는 것이다.

    ๋ฌผ๋ก  ์•„๋‚ ๋กœ๊ทธ์ธ ์†Œ๋ฆฌ ์‹ ํ˜ธ๊ฐ€ ๋ณ€ํ™˜๋œ ์ „์•• ๊ฐ’์ด 123 ๊ฐ™์ด ๋”ฑ ๋–จ์–ด์ง€๋Š” ์ •์ˆ˜์ผ๋ฆฌ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” 0~65536 ์ค‘ ๊ทผ์‚ฌ์น˜๋ฅผ ์ฐพ์•„์„œ ๋ฐ”๊ฟ”์ฃผ๋Š”๋ฐ ์ด ๊ณผ์ •์„ ์–‘์žํ™”(Quantizing)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. (์–‘์ž์—ญํ•™์—์„œ ๋‚˜์˜ค๋Š” ๊ทธ ์–‘์ž๋ž‘ ๊ฐ™์€ ์˜๋ฏธ ๋งž๋‹ค.)

    ์ดํ›„ 0~65536์˜ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋œ ์ „์••์„ ์ปดํ“จํ„ฐ๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์ด์ง„์ˆ˜(Binary)๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณผ์ •์„ ๋ถ€ํ˜ธํ™”(Coding)๋ผ๊ณ  ํ•œ๋‹ค.

    ์ด๋Ÿฐ ๊ฒƒ๋“ค์€ ์šฐ๋ฆฌ๊ฐ™์€ ๊ฐœ๋ฐœ๋žญ์ด๋“ค์€ ์›Œ๋‚™ ์ต์ˆ™ํ•œ ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ •๋„๋งŒ ์„ค๋ช…ํ•˜๊ณ  ๋„˜์–ด๊ฐ€๊ฒ ๋‹ค.

    Web Audio API๋กœ ํŒŒํ˜• ๊ทธ๋ ค๋ณด๊ธฐ

    ์ž, ๋“œ๋””์–ด ๊ธธ๊ณ  ๊ธธ์—ˆ๋˜ ์†Œ๋ฆฌ ์ด๋ก ์ด ๋๋‚ฌ๋‹ค. ํ•„์ž๋Š” ๋””์ง€ํ„ธ๋กœ ๋ณ€ํ™˜๋œ ์˜ค๋””์˜ค๋ฅผ ๊ฐ€์ง€๊ณ  ํŒŒํ˜•์„ ๊ทธ๋ ค๋ณด๋Š” ๊ฒƒ์ด ๋ชฉ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— Analog to Digital๋งŒ ๋‹ค๋ค˜๊ณ  Digital to Analog๋Š” ์ด ํฌ์ŠคํŒ…์—์„œ ๋‹ค๋ฃจ์ง€ ์•Š๊ฒ ๋‹ค. ๊ทผ๋ฐ ์ด๊ฒƒ๋„ ๋‚˜๋ฆ„ ์žฌ๋ฐŒ์œผ๋ฏ€๋กœ ๋”ฐ๋กœ ์ฐพ์•„๋ณด๊ธธ ๊ฐ•์ถ”ํ•œ๋‹ค. ํ•„์ž๋Š” ์˜ค๋””์˜ค ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•ด์„œ ํ•ด๋‹น ์˜ค๋””์˜ค ํŒŒ์ผ์„ Web Audio API๋กœ ๋ถ„์„ํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฝ‘์•„๋‚ด๊ณ  svg๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒŒํ˜•์„ ๊ทธ๋ฆด ๊ฒƒ์ด๋‹ค.

    ์ฐธ๊ณ ๋กœ ํ”„๋กœ์ ํŠธ๋Š” webpack4์™€ babel7์„ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌ์„ฑํ–ˆ๋‹ค. ์ž์„ธํ•œ ์ฝ”๋“œ๋Š” ๊นƒํ—ˆ๋ธŒ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์—์„œ ํ™•์ธ ํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    ๊ธฐ๋ณธ ํ‹€ ์žก๊ธฐ

    ๊ทธ๋Ÿผ ๋จผ์ € HTML์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•˜์ž.

    <body>
      <input id="audio-uploader" type="file">
      <svg id="waveform" preserveAspectRatio="none">
        <g id="waveform-path-group"></g>
      </svg>
    </body>

    HTML์€ ์ด๊ฒŒ ๋์ด๋‹ค. ์˜ค๋””์˜ค ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•  input ์—˜๋ฆฌ๋จผํŠธ ํ•˜๋‚˜์™€ ํŒŒํ˜•์„ ๊ทธ๋ฆด svg ์—˜๋ฆฌ๋จผํŠธ ํ•˜๋‚˜๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค. ์–ด์ฐจํ”ผ ํ…Œ์ŠคํŠธ ์šฉ๋„๋ผ์„œ UI๊ฐ€ ์ค‘์š”ํ•œ๊ฒŒ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋Šฅ ๊ตฌํ˜„์— ์ถฉ์‹คํ–ˆ๋‹ค.(๋ผ๊ณ  ํฌ์žฅ์„ ํ•ด๋ด…๋‹ˆ๋‹ค)

    ์ด์ œ ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋˜๋ฉด ์‹คํ–‰๋  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜์ž.

    // index.js
    (function () {
      const inputDOM = document.getElementById('audio-uploader');
      inputDOM.onchange = e => {
        const file = e.currentTarget.files[0];
        if (file) {
          const reader = new FileReader();
          reader.onload = e => console.log(e.target.result);
          reader.readAsArrayBuffer(file);
        }
      }
    })();

    FileReader.prototype.readAsArrayBuffer ๋ฉ”์†Œ๋“œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•ํƒœ์ธ ํŒŒ์ผ์„ ํ•œ๋ฒˆ์— ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ผ์ • ๋‹จ์œ„์˜ ์ฒญํฌ(Chunk)๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. ๋ณดํ†ต ๋ญ ์„œ๋ฒ„๋กœ ํŒŒ์ผ ์—…๋กœ๋“œ ํ•œ๋‹ค๊ฑฐ๋‚˜ ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค. ์›๋ž˜๋Š” ์ด ArrayBuffer๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธฐ ์œ„ํ•œ ๋ณ„๋„์˜ ๋กœ์ง์„ ์ž‘์„ฑํ•ด์•ผํ•˜์ง€๋งŒ ์ด๋ฒˆ์— ์‚ฌ์šฉํ•  Web Audio API๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ArrayBuffer๋ฅผ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    AudioAnalyzer ํด๋ž˜์Šค ์ž‘์„ฑ

    ์ด์ œ ๋ณธ๊ฒฉ์ ์ธ Web Audio API๋ฅผ ์‚ฌ์šฉํ•ด๋ณผ ์ฐจ๋ก€์ด๋‹ค. ํ•„์ž๋Š” ๋ณ„๋„๋กœ AudioAnalyzer๋ผ๋Š” ์‹ฑ๊ธ€ํ†ค ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

    // lib/AudioAnalyzer.js
    class AudioAnalyzer {
      constructor () {
        if (!window.AudioContext) {
          const errorMsg = 'Web Audio API ์ง€์› ์•ˆ๋ผ์œ  ใ…œใ…œ';
          alert(errorMsg);
          throw new Error(errorMsg);
        }
    
        this.audioContext = new (AudioContext || webkitAudioContext)();
        this.audioBuffer = null;
        this.sampleRate = 0;
        this.peaks = [];
    
        this.waveFormBox = document.getElementById('waveform');
        this.waveFormPathGroup = document.getElementById('waveform-path-group');
      }
    
      reset () {
        this.audioContext = new (AudioContext || webkitAudioContext)();
        this.audioBuffer = null;
        this.sampleRate = 0;
        this.peaks = [];
      }
    }
    
    export default new AudioAnalyzer();

    SVG ๋ทฐ๋ฐ•์Šค๋ฅผ ์„ค์ •ํ•˜์ž

    ์ด๋ ‡๊ฒŒ ๋Œ€์ถฉ ๊ธฐ๋ณธ ํ‹€์„ ์žก์•„์ฃผ๊ณ  ๋‚˜์„œ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ๊ทธ๋ฆด svg ์—˜๋ฆฌ๋จผํŠธ์˜ ๋ทฐ๋ฐ•์Šค๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ•˜๋‚˜ ์„ ์–ธํ•  ๊ฒƒ์ด๋‹ค. ์†Œ๋ฆฌ ์‹ ํ˜ธ๋Š” ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ์— ๋”ฐ๋ผ์„œ ๋“ค์–ด์˜จ ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด๊ฐ€ ์ฒœ์ฐจ๋งŒ๋ณ„์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ทฐ๋ฐ•์Šค์˜ width๋ฅผ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ์ง€ ๋ชจ๋“  ์‹ ํ˜ธ๋ฅผ ๋ทฐ๋ฐ•์Šค์— ๋”ฑ ๋งž๊ฒŒ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

    updateViewboxSize () {
      this.waveFormBox.setAttribute('viewBox', `0 -1 ${this.sampleRate} 2`);
    }

    svg ์—˜๋ฆฌ๋จผํŠธ์˜ viewBox ์†์„ฑ์€ ์•ž์—์„œ๋ถ€ํ„ฐ min-x, min-y, width, height๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๋น„ํŠธ ๋ ˆ์ดํŠธ๋ฅผ ์„ค๋ช…ํ•  ๋•Œ ์–˜๊ธฐ ํ–ˆ๋“ฏ์ด ์˜ค๋””์˜ค ์‹ ํ˜ธ๋Š” ๋ถ€ํ˜ธ๋ฅผ ๊ฐ€์ง€๋Š” signed์ด๊ธฐ ๋•Œ๋ฌธ์— 0, 0์ด ์•„๋‹Œ 0, -1์—์„œ ๋ทฐ๋ฐ•์Šค๋ฅผ ์„ค์ •ํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  width๋Š” ์˜ค๋””์˜ค์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋กœ ์žก์•„์ค˜์„œ ์˜ค๋””์˜ค ์‹ ํ˜ธ๊ฐ€ ๋ทฐ๋ฐ•์Šค์˜ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๊ฝ‰ ์ฐจ๋„๋ก ์„ค์ •ํ•˜๊ณ  height๋Š” -1 ~ 1๊นŒ์ง€ ์žก์•„์ค˜์•ผํ•˜๋‹ˆ๊นŒ 2๋กœ ์„ค์ •ํ–ˆ๋‹ค.

    ์ด๋ ‡๊ฒŒ ์„ ์–ธํ•œ updateViewboxSize๋ฉ”์†Œ๋“œ๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ดˆ๊ธฐํ™”๋ ๋•Œ ๋ทฐ๋ฐ•์Šค ์‚ฌ์ด์ฆˆ๋„ ํ•จ๊ป˜ ์ดˆ๊ธฐํ™”๋˜๋„๋ก constructor์™€ reset ๋ฉ”์†Œ๋“œ์— ์ ๋‹นํžˆ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

    ์—…๋กœ๋“œ๋œ AudioBuffer ํ™•์ธํ•˜๊ธฐ

    ์ด์ œ input ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ†ตํ•ด ์—…๋กœ๋“œ๋œ ์˜ค๋””์˜ค ํŒŒ์ผ์„ ๋””์ฝ”๋”ฉํ•˜๋Š” ๊ท€์—ฌ์šด setter๋ฅผ ํ•˜๋‚˜ ์„ ์–ธํ•˜๋ฉด ๋œ๋‹ค.

    setAudio (audioFile) {
      this.audioContext.decodeAudioData(audioFile).then(buffer => {
        console.log(buffer);
      });
    }

    AudioContext.prototype.decodeAudioData ๋ฉ”์†Œ๋“œ๋Š” ArrayBuffer๋ฅผ ๋ฐ›์•„์„œ AudioBuffer๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. ์•„๊นŒ ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋˜ ๋Œ€๋กœ readAsArrayBuffer ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ArrayBuffer๋Š” ํ•œ๋ฒˆ์— ๋ชจ๋“  ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ฒญํฌ ๋‹จ์œ„๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— decodeAudioData๋„ ๋ณ€ํ™˜์„ ๋™๊ธฐ์ ์œผ๋กœ ํ•ด์ฃผ์ง€๋Š” ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Promise๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

    ์ด์ œ ์‹ค์ œ๋กœ ์˜ค๋””์˜ค ํŒŒ์ผ์ด ์–ด๋–ป๊ฒŒ ๋ณ€ํ™˜๋˜๋Š”์ง€ ๋ณด๊ธฐ ์œ„ํ•ด ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋ฉด AudioAnalyzer์—๊ฒŒ ์˜ค๋””์˜ค ํŒŒ์ผ์„ ๋„˜๊ธฐ๋„๋ก ๋ณ€๊ฒฝํ•ด์ฃผ์ž.

    // index.js
    import AudioAnalyzer from './lib/AudioAnalyzer';
    
    (function () {
      const inputDOM = document.getElementById('audio-uploader');
      inputDOM.onchange = e => {
        const file = e.currentTarget.files[0];
        if (file) {
          // AudioAnalyzer ์ดˆ๊ธฐํ™”
          AudioAnalyzer.reset();
          const reader = new FileReader();
          // AudioAnalyzer์—๊ฒŒ ํŒŒ์ผ ํ† ์Šค
          reader.onload = e => AudioAnalyzer.setAudio(e.target.result);
          reader.readAsArrayBuffer(file);
        }
      }
    })();

    ์ด ์ฏค ํ–ˆ์œผ๋ฉด ์ด์ œ ๋ฉ”์ธ ํ•จ์ˆ˜์—๋Š” ๋” ์ด์ƒ ๋ญ˜ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค. ์ด์ œ AudioAnalyzer๋งŒ ๊ฐ€์ง€๊ณ  ๋†€๋ฉด ๋œ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‚˜์˜ค๋Š” ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ•„์ž๊ฐ€ ์ข‹์•„ํ•˜๋Š” ๊ฐ€์ˆ˜์ธ ๊ฑฐ๋ฏธ์˜ ๊ทธ๋Œ€ ๋Œ์•„์˜ค๋ฉด.mp3 ํŒŒ์ผ์„ ์—…๋กœ๋“œ ํ•ด๋ณด์•˜๋‹ค.

    AudioBuffer {
      length: 12225071,
      duration: 277.2124943310658,
      sampleRate: 44100,
      numberOfChannels: 2
    }

    ๊ทธ๋Ÿฌ๋ฉด AudioAnalyzer์˜ setAudio ๋ฉ”์†Œ๋“œ ๋‚ด๋ถ€์—์„œ ์‹คํ–‰๋œ decodeAudioData๊ฐ€ ArrayBuffer๋ฅผ ๋ฐ›์•„์„œ AudioBuffer๋กœ ๋ณ€ํ™˜ํ•œ ๋’ค ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค. ์ด๊ฑธ ๋œฏ์–ด๋ณด๋ฉด ์œ ์šฉํ•œ ์ •๋ณด๋“ค์ด ๋“ค์–ด์žˆ๋‹ค.


    • sampleRate: ๋‹น์—ฐํžˆ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ์˜๋ฏธํ•˜๊ณ  ์ด ๊ณก์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋Š” 44,100hz์ด๋‹ค.
    • numberOfChannels: ์ด ์˜ค๋””์˜ค๊ฐ€ ๋ช‡๊ฐœ์˜ ์ฑ„๋„์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š”๋ฐ ์ด ํŒŒ์ผ์€ ๋‘ ๊ฐœ์˜ ์ฑ„๋„์ด ์žˆ๋Š” ์Šคํ…Œ๋ ˆ์˜ค ์ฑ„๋„ ์˜ค๋””์˜ค ํŒŒ์ผ์ด๋‹ค.
    • length: ํ”ผํฌ(Peak)๋“ค์˜ ๊ฐœ์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ํ”ผํฌ๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์ƒ˜ํ”Œ๋ง์„ ์ง„ํ–‰ํ•  ๋•Œ ์ „์••์„ ์ธก์ •ํ•œ ๊ฐ’์„ ์˜๋ฏธํ•œ๋‹ค.
    • duration: ์ด ์˜ค๋””์˜ค ํŒŒ์ผ์˜ ์žฌ์ƒ ๊ธธ์ด๋ฅผ ์ดˆ๋‹จ์œ„๋กœ ํ‘œ์‹œํ•ด์ค€๋‹ค. ๊ทธ๋Œ€ ๋Œ์•„์˜ค๋ฉด์€ ์•ฝ 277์ดˆ๋™์•ˆ ์žฌ์ƒ๋˜๋‚˜๋ณด๋‹ค.

    ์Œ ์—ฌ๊ธฐ์„œ ํ•œ๊ฐ€์ง€ ๊ฒฐ์ •ํ•ด์•ผํ•  ๊ฒƒ์ด ์ƒ๊ฒผ๋‹ค. ์ฑ„๋„์ด nn๊ฐœ์ธ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์™”์„ ๋•Œ ๊ทธ nn๊ฐœ์˜ ์ฑ„๋„์˜ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ๋ชจ๋‘ ํ‘œํ˜„ํ•ด์ฃผ๊ฑฐ๋‚˜ ์ฑ„๋„์„ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์„œ ํŒŒํ˜•์„ ํ‘œํ˜„ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค. ํ•„์ž๋Š” nn๊ฐœ์˜ ์ฑ„๋„์„ ๊ฐ€์ง„ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๋”๋ผ๋„ ๊ทธ ์ฑ„๋„์„ ๋ชจ๋‘ ํ•œ๊ฐœ์˜ ์ฑ„๋„๋กœ ๋จธ์ง€ํ•ด์„œ ํŒŒํ˜•์„ ๊ทธ๋ฆด ์˜ˆ์ •์ด๋‹ค.

    ํ•˜์ง€๋งŒ ์ด ํฌ์ŠคํŒ…์—์„œ ์ฑ„๋„์„ ๋จธ์ง€ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ๋ชจ๋‘ ์ด์•ผ๊ธฐํ•˜๋ฉด ๋„ˆ๋ฌด ๋ณต์žกํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ ํ•˜๋‚˜์˜ ์ฑ„๋„๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ์ง„ํ–‰ํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.

    ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ ๋ถ„์„ํ•˜๊ณ  ์ •์ œํ•˜๊ธฐ

    ์ด์ œ ํ•„์ž๋Š” ๊ธฐ๋ณธ์ ์ธ ์˜ค๋””์˜ค ๋ฐ์ดํ„ฐ์ธ AudioBuffer๋ฅผ ์–ป์—ˆ๋‹ค. ์ด์ œ ์ด ๋ฐ์ดํ„ฐ๋งŒ ์žˆ์–ด๋„ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ์ด์ œ AudioBuffer์—์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๋ฝ‘์•„์„œ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋“ค์— ํ• ๋‹นํ•ด์ฃผ์ž.

    setAudio (audioFile) {
      this.audioContext.decodeAudioData(audioFile).then(buffer => {
        // AudioBuffer ๊ฐ์ฒด๋ฅผ ๋ฉค๋ฒ„๋ณ€์ˆ˜์— ํ• ๋‹น
        this.audioBuffer = buffer;
        // ์—…๋กœ๋“œ๋œ ์˜ค๋””์˜ค์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ๋ฅผ ๋ฉค๋ฒ„๋ณ€์ˆ˜์— ํ• ๋‹น
        this.sampleRate = buffer.sampleRate;
        // ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ์— ๋งž์ถฐ์„œ svg ์—˜๋ฆฌ๋จผํŠธ ํฌ๊ธฐ ์กฐ์ •
        this.updateViewboxSize();
      });
    }

    ํ›„, ์—ฌ๊ธฐ๊นŒ์ง€ ์™”์œผ๋ฉด ํŒŒํ˜•์„ ๊ทธ๋ฆด ์ค€๋น„๊ฐ€ ๋ชจ๋‘ ๋๋‚ฌ๋‹ค. ์šฐ์„  AudioBuffer์—์„œ ์˜ค๋””์˜ค ์‹ ํ˜ธ๋ฅผ ํ•˜๋‚˜ํ•˜๋‚˜ ๋ฝ‘์•„๋ณด์ž.

    ๋จผ์ € ์˜ค๋””์˜ค ์‹ ํ˜ธ๊ฐ€ ๋“ค์–ด์žˆ๋Š” ๋ฐฐ์—ด๋ถ€ํ„ฐ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด์ž. ์•„๊นŒ ํ•„์ž๊ฐ€ AudioBuffer์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ๋ดค์„ ๋•Œ numberOfChannels๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์—ˆ๊ณ  ์ด ๊ฐ’์ด 2์ธ ์Šคํ…Œ๋ ˆ์˜ค ์ฑ„๋„์ด์—ˆ๋‹ค. ์ด ์ฑ„๋„ ๋ฐ์ดํ„ฐ๋Š” AudioBuffer.getChannelData ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

    for (let i = 0; i < this.audioBuffer.numberOfChannels; i++) {
      console.log(this.audioBuffer.getChannelData(i));
    }
    
    // Float32Array(12225071) [0, 0, 0, โ€ฆ]
    // Float32Array(12225071) [0, 0, 0, โ€ฆ]

    ์•„๋‹› ์–ด๋งˆ๋ฌด์‹œํ•œ ๊ธธ์ด์˜ Float32Array๊ฐ€ ๋‚˜์™”๋‹ค. ์ง€๊ธˆ ํ•„์ž์—๊ฒŒ ๋ณด์ด๋Š” ๊ฐ’์€ ์ „๋ถ€ 0์ด์ง€๋งŒ ๋ณดํ†ต ์Œ์•…์ด ์‹œ์ž‘ํ•˜์ž๋งˆ์ž ์ฟ ๊ณผ๊ณผ๊ด‘! ํ•˜์ง„ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Ÿฐ๊ฑฐ์ง€ ๋’ค์ชฝ ์ธ๋ฑ์Šค์˜ ์—˜๋ฆฌ๋จผํŠธ์—๋Š” ๊ฐ’์ด ์ œ๋Œ€๋กœ ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๊ณ  ์ด ๊ฐ’๋“ค์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธด ์กฐ๊ธˆ ํž˜๋“ค๊ณ  ์กฐ๊ธˆ ์†์งˆ์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

    ์šฐ์„  ์ € ๋ฐฐ์—ด์— ๋“ค์–ด์žˆ๋Š” ์›์†Œ์˜ ์ •์ฒด๊ฐ€ ๋ญ”์ง€๋ถ€ํ„ฐ ์ƒ๊ฐํ•ด๋ณด์ž. ๋ฐฐ์—ด์˜ ๊ธธ์ด์ธ 12225071๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ์นœ๊ตฌ์˜ ์ •์ฒด๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๊นŒ ์šฐ๋ฆฌ๊ฐ€ AudioBuffer๋ฅผ ํ†ตํ•ด ์ด ๊ณก์˜ ์žฌ์ƒ๊ธธ์ด(Duration)๋ฅผ ๋ดค์„ ๋•Œ ์•ฝ 277์ดˆ ์˜€๋‹ค. ์ด ๊ณก์˜ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ์™€ ์žฌ์ƒ๊ธธ์ด๋ฅผ ๊ณฑํ•ด๋ณด๋ฉด 12225071์ด ๋‚˜์˜จ๋‹ค. ์ฆ‰, ์ € ์›์†Œ๋“ค์€ ์ปดํ“จํ„ฐ๊ฐ€ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ์— ๋”ฐ๋ผ ์ธก์ •ํ•œ ์ „์••์ธ ํ”ผํฌ์ด๋‹ค.

    sampling 저 하나하나의 피크들이 전부 Float32Array의 원소로 들어가있다.

    ์ผ๋‹จ ์ € ์›์†Œ์˜ ์ •์ฒด๊ฐ€ ํ”ผํฌ๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•˜์œผ๋‹ˆ ์ด ์นœ๊ตฌ๋“ค์„ ์กฐ๊ธˆ ์ •์ œํ•ด๋ณด์ž. ์™œ ์ด๊ฑธ ์ •์ œํ•˜๋Š๋ƒ?

    12,225,071๊ฐœ์˜ ํ”ผํฌ๋ฅผ ์ „๋ถ€ ๋ Œ๋”ํ•œ๋‹ค๋Š” ๊ฒŒ ๊ณผ์—ฐ ํšจ์œจ์ ์ธ ์‹œ๊ฐํ™”์ธ๊ฐ€โ€ฆ?

    ๋ผ๋Š” ํ•ฉ๋ฆฌ์  ์˜์‹ฌ ๋•Œ๋ฌธ์ด๋‹ค. ์†”์งํžˆ ํ”ผํฌ๊ฐ€ ์ฒœ๋งŒ๊ฐœ๊ฐ€ ์ฐํžˆ๋˜ ์˜ค๋ฐฑ๋งŒ๊ฐœ๊ฐ€ ์ฐํžˆ๋˜ ์–ด์ฐจํ”ผ ์šฐ๋ฆฌ๋Š” ์กฐ๊ทธ๋งŒ ๋ชจ๋‹ˆํ„ฐ๋กœ ๋ณผ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ์ด๊ฑธ ํ•˜๋‚˜ํ•˜๋‚˜ ๋‹ค ํ‘œํ˜„ํ•ด์ค€๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ํฐ ์˜๋ฏธ๋Š” ์—†๋‹ค.

    ๊ทธ๋ž˜์„œ ํ•„์ž๋Š” ํ”ผํฌ๋“ค์„ ์ ๋‹นํžˆ ์••์ถ•ํ•  ๊ฒƒ์ด๋‹ค. ๋ชจ๋“  ํ”ผํฌ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ ๋‹นํ•œ ๊ธธ์ด์˜ ์ƒ˜ํ”Œ์„ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น ์ƒ˜ํ”Œ ์•ˆ์˜ ์ตœ๋Œ€๊ฐ’๊ณผ ์ตœ์†Œ๊ฐ’๋งŒ ์ˆ˜์ง‘ํ•  ๊ฒƒ์ด๋‹ค.

    ์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด ๋‚˜์ดํ€ด์ŠคํŠธ ์ด๋ก ์— ๋”ฐ๋ฅด๋ฉด ์–ด์ฐจํ”ผ ํ•˜๋‚˜์˜ ์‚ฌ์ดํด์„ ํ‘œํ˜„ํ• ๋•Œ ์ตœ๋Œ€๊ฐ’ ํ•œ๊ฐœ์™€ ์ตœ์†Œ๊ฐ’ ํ•œ๊ฐœ๋งŒ ์•Œ๋ฉด ์•„๋ฌด ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. ํŒŒํ˜•์˜ ํ•ด์ƒ๋„๋Š” ์กฐ๊ธˆ ๋–จ์–ด์ง€๊ฒ ์ง€๋งŒ ์ด๊ฑด ๋ญ ์ƒ์šฉ ํˆด๋„ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ํฐ ์˜๋ฏธ๋Š” ์—†๋‹ค.

    const sampleSize = peaks.length / this.sampleRate;
    const sampleStep = Math.floor(sampleSize / 10);
    
    // ์˜ˆ์‹œ๋กœ 0๋ฒˆ ์ฑ„๋„๋งŒ ๊ฐ€์ ธ์˜ด
    const peaks = this.audioBuffer.getChannelData(0);
    const resultsPeaks = [];
    
    // ๋”ฑ ์ƒ˜ํ”Œ ๋ ˆ์ดํŠธ ๊ธธ์ด์ธ 44100๊ฐœ์˜ ํ”ผํฌ๋งŒ ์ˆ˜์ง‘ํ•  ๊ฒƒ์ด๋‹ค.
    Array(this.sampleRate).fill().forEach((v, newPeakIndex) => {
      const start = Math.floor(newPeakIndex * sampleSize);
      const end = Math.floor(newPeakIndex + sampleSize);
    
      let min = peaks[0];
      let max = peaks[0];
    
      for (let sampleIndex = start; sampleIndex < end; sampleIndex += sampleStep) {
        const v = peaks[sampleIndex];
        if (v > max) {
          max = v;
        }
        else if (v < min) {
          min = v;
        }
      }
    
      resultPeaks[2 * newPeakIndex] = max;
      resultPeaks[2 * newPeakIndex + 1] = min;
    });

    ์ข€ ๋ณต์žกํ•ด๋ณด์ด์ง€๋งŒ ์ด ์ฝ”๋“œ๋ฅผ ํ•œ๋งˆ๋””๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

    1. ์ƒ˜ํ”Œ๋ ˆ์ดํŠธ ๋งŒํผ ์ดํ„ฐ๋ ˆ์ด์…˜์„ ๋ˆ๋‹ค.
    2. ํŠน์ • ๊ธธ์ด์˜ 2์ฐจ ์ƒ˜ํ”Œ ๊ตฌ๊ฐ„์„ ์ •ํ•˜๊ณ  ๊ทธ ๊ตฌ๊ฐ„ ๋‚ด์—์„œ ์ตœ๋Œ€๊ฐ’๊ณผ ์ตœ์†Œ๊ฐ’์„ ์ฐพ๋Š”๋‹ค.
    3. resultPeaks ๋ฐฐ์—ด์˜ ์ง์ˆ˜ ์ธ๋ฑ์Šค์— ์ตœ๋Œ€๊ฐ’์„, ํ™€์ˆ˜ ์ธ๋ฑ์Šค์—๋Š” ์ตœ์†Œ๊ฐ’์„ ์‚ฝ์ž…ํ•œ๋‹ค.

    resultsPeaks๋ฐฐ์—ด์— ๊ฐ’์„ ์ €์žฅํ•  ๋•Œ 2 * newPeakIndex์™€ ๊ฐ™์ด ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ 2๋ฐฐ๋กœ ํ•ด์ฃผ๋Š” ์ด์œ ๋Š” ํ”ผํฌ๋ฅผ ํ•œ๋ฒˆ ์ดํ„ฐ๋ ˆ์ด์…˜ ๋Œ ๋•Œ max์™€ min ์ตœ๋Œ€ 2๊ฐœ์˜ ๊ฐ’์„ ์ €์žฅํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

    ์ด๋ ‡๊ฒŒ ํ•ด์„œ ํ•„์ž๋Š” ์ ๋‹นํžˆ ์••์ถ•๋œ 88200 ๊ธธ์ด์˜ ํ”ผํฌ ๋ฐฐ์—ด ํ•˜๋‚˜๋ฅผ ์–ป๊ฒŒ ๋˜์—ˆ๋‹ค.

    ์ด์ œ ์ง„์งœ ๊ทธ๋ ค๋ณด์ž!

    ๊ทธ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์€ ์ƒ๊ฐ๋ณด๋‹ค ๋‹จ์ˆœํ•˜๋‹ค. ์œ„์—์„œ ๋ฝ‘์•„์˜จ ํ”ผํฌ ๋ฐฐ์—ด์„ ์ˆœํšŒ๋Œ๋ฉด์„œ ๊ทธ๋ ค์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

    SVG์˜ path ์—˜๋ฆฌ๋จผํŠธ๋Š” d ์†์„ฑ์— ๋‹ด๊ธด ๋ฌธ์ž์—ด์„ ๋ถ„์„ํ•˜์—ฌ ์„ ์„ ๊ทธ๋ ค์ค€๋‹ค. ์ด๋•Œ M์€ Move, ๊ทธ๋ฆผ์„ ๊ทธ๋ฆด ํฌ์ธํ„ฐ๋ฅผ ์˜ฎ๊ธฐ๋Š” ๋ช…๋ น์–ด์ด๊ณ  L์€ Line, ์ง€์ •ํ•œ ๊ณณ๊นŒ์ง€ ์„ ์„ ๊ธ‹๋Š” ๋ช…๋ น์–ด์ด๋‹ค.

    ์ฆ‰, ์šฐ๋ฆฌ๋Š” ํฌ์ธํ„ฐ๋ฅผ ์˜ฎ๊ธฐ๊ณ  ์„ ์„ ๊ธ‹๊ณ ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ์•„๊นŒ ํ•„์ž๊ฐ€ ์ง์ˆ˜ ์ธ๋ฑ์Šค์—๋Š” ์ตœ๋Œ€ ๊ฐ’์„ ๋‹ด๊ณ  ํ™€์ˆ˜ ์ธ๋ฑ์Šค์—๋Š” ์ตœ์†Œ๊ฐ’์„ ๋‹ด์•„์ค€ ์ด์œ ๊ฐ€ ๋ฐ”๋กœ ์—ฌ๊ธฐ์— ์žˆ๋‹ค. ์ดํ„ฐ๋ ˆ์ด์…˜์„ ๋Œ๋ฉด์„œ ์ง์ˆ˜ ์ธ๋ฑ์Šค ์ผ๋•Œ๋Š” M ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํฌ์ธํ„ฐ๋ฅผ ์˜ฎ๊ธฐ๊ณ  ํ™€์ˆ˜ ์ธ๋ฑ์Šค ์ผ๋•Œ๋Š” L ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์„ ๊ทธ๋ฆฌ๋ ค๊ณ  ํ•œ ๊ฒƒ์ด๋‹ค.

    draw () {
      if (this.audioBuffer) {
        const peaks = this.peaks;
        const totalPeaks = peaks.length;
    
        let d = '';
        for(let peakIndex = 0; peakIndex < totalPeaks; peakIndex++) {
          if (peakNumber % 2 === 0) {
            d += ` M${Math.floor(peakNumber / 2)}, ${peaks.shift()}`;
          }
          else {
            d += ` L${Math.floor(peakNumber / 2)}, ${peaks.shift()}`;
          }
        }
    
        const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        path.setAttributeNS(null, 'd', d);
    
        this.waveFormPathGroup.appendChild(path);
      }
    }

    Math.floor(peakNumber / 2)๋Š” xx์ถ•, peaks.shift()๋Š” yy์ถ•์„ ์˜๋ฏธํ•œ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ๋Œ€๋žต ์ด๋Ÿฐ ์‹์œผ๋กœ ์ž‘๋™ํ•  ๊ฒƒ์ด๋‹ค. ์•ž์— ๋ถ™์€ ์ˆซ์ž๋Š” ํ”ผํฌ์˜ ์ธ๋ฑ์Šค๋ผ๊ณ  ์ƒ๊ฐํ•˜์ž.

    1. (0, 100)์œผ๋กœ ํฌ์ธํ„ฐ ์ด๋™
    2. (0, -25)์œผ๋กœ ์„ ์„ ๊ธ‹๋Š”๋‹ค.
    3. (1, 300)์œผ๋กœ ํฌ์ธํ„ฐ ์ด๋™
    4. (1, -450)์œผ๋กœ ์„ ์„ ๊ธ‹๋Š”๋‹ค.
    5. ์ญ‰์ญ‰ ๋ฐ˜๋ณต
    svg graph 저 과정을 반복하면 대략 이런 모양의 작대기들이 그려진다

    ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆฌ๋ ค๋Š” ์˜ค๋””์˜ค ํŒŒํ˜•์€ ๋””์ง€ํ„ธ ์‹ ํ˜ธ๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์œ„์—์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ดค๋˜ ์˜ค๋””์˜ค ์‹ ํ˜ธ์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์—ฐ์†์ ์ธ ์•„๋‚ ๋กœ๊ทธ๋กœ๋Š” ํ‘œํ˜„์ด ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ ‡๊ฒŒ ์ž‘๋Œ€๊ธฐ๋ฅผ ์ญ‰์ญ‰ ๊ทธ์–ด๊ฐ€๋ฉด์„œ ํ‘œํ˜„ํ•ด์•ผํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ๋ณด๋ฉด ์ƒ๋‹นํžˆ ํ—ˆ์ ‘ํ•œ ๊ทธ๋ฆผ์ด ๋‚˜์˜ฌ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ์ € ์„ ์ด 88,200๊ฐœ๊ฐ€ ๊ฒน์ณ์žˆ์œผ๋ฉด ๊ฝค ๊ทธ๋Ÿด์‹ธํ•ด๋ณด์ธ๋‹ค.

    two dimension 작대기도 잘 그으면 예술이 된다

    ์ž, ์ด๋ ‡๊ฒŒ ์˜ค๋””์˜ค ํŒŒํ˜•์„ ์‹ฌํ”Œํ•˜๊ฒŒ ๊ทธ๋ ค๋ณด์•˜๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง€ ํ•ด๋†“๊ณ  ํ•˜๋Š” ๋ง์ธ๋ฐโ€ฆ ์‚ฌ์‹ค WaveSurfer๋ผ๊ณ  ์ด๊ฑฐ ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค. ๊ธฐ๋Šฅ๋„ ๋” ๋งŽ๋‹ค.

    ๊ทธ๋ƒฅ ๋‚ด ์†์œผ๋กœ ํ•œ๋ฒˆ ์ง์ ‘ ๊ทธ๋ ค๋ณด๊ณ  ์‹ถ์—ˆ๋‹ค.

    ์Œ์•… ์ฃผ์„ธ์š” DJ

    ํŒŒํ˜•๋งŒ ๊ทธ๋ฆฌ๊ธฐ๋Š” ์ข€ ์•„์‰ฌ์šฐ๋‹ˆ ๋ง‰๊ฐ„์„ ์ด์šฉํ•ด์„œ ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜๋งŒ ๋” ๋งŒ๋“ค์–ด๋ณด์ž. ๋ฐ”๋กœ ์ด ์Œ์•…์„ ์žฌ์ƒํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์›๋ž˜ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค ๋•Œ ํ•„์ž์˜ ์˜๋„๋Š” ์Œ์•…์ด๋ผ๋„ ์ข€ ๋“ค์œผ๋ฉด์„œ ๋งŒ๋“ค์ž์˜€๋Š”๋ฐ ์ด๊ฑฐ ๋งŒ๋“ค๋ฉด์„œ ๊ทธ๋Œ€ ๋Œ์•„์˜ค๋ฉด์„ ๋„ˆ๋ฌด ๋งŽ์ด ๋“ค์–ด์„œ ์กฐ๊ธˆ ์งˆ๋ ค๋ฒ„๋ ธ๋‹ค.(๊ฑฐ๋ฏธ ๋ˆ„๋‚˜ ๋ฏธ์•ˆโ€ฆ)

    play (buffer) {
      const sourceBuffer = this.audioContext.createBufferSource();
      sourceBuffer.buffer = buffer;
      sourceBuffer.connect(this.audioContext.destination);
      sourceBuffer.start();
    }

    AudioContext.prototype.createBufferSource ๋ฉ”์†Œ๋“œ๋Š” AudioNode ์ค‘ ํ•˜๋‚˜์ธ AudioBufferSourceNode๋ผ๋Š” ์นœ๊ตฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ธ๋ฐ, ์ด AudioNode์—๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๊ฐ€์ง€๊ณ  ๋†€์•˜๋˜ AudioBuffer๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ์ง„์งœ ์˜ค๋””์˜ค์ ์ธ ์ปจํŠธ๋กค์„ ํ•  ์ˆ˜๊ฐ€ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ์Œโ€ฆ๊ป๋ฐ๊ธฐ ๊ฐ™์€ ๋Š๋‚Œ์ด๋‹ค.

    Web Audio API๋Š” ์ด๋Ÿฐ AudioNode๋“ค์„ ์„œ๋กœ ์—ฐ๊ฒฐํ•ด์„œ ์†Œ๋ฆฌ๋ฅผ ๋ณ€์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฑธ ์‚ฌ์šฉํ•ด์„œ ์ปดํ”„๋ ˆ์„œ๋‚˜ ๋ฆฌ๋ฒ„๋ธŒ ๊ฐ™์€ ์˜ค๋””์˜ค ์ดํŽ™ํ„ฐ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์Œ์—๋Š” ํ•œ๋ฒˆ ์˜ค๋””์˜ค ์ดํŽ™ํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•ด์•ผ๊ฒ ๋‹ค.

    ์™„์„ฑ๋œ ์ƒ˜ํ”Œ์˜ ์†Œ์Šค๋Š” ํ•„์ž์˜ ๊นƒํ—ˆ๋ธŒ ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ์—์„œ, ๋ผ์ด๋ธŒ ๋ฐ๋ชจ๋Š” ์—ฌ๊ธฐ์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์ด์ƒ์œผ๋กœ ์ปดํ“จํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์†Œ๋ฆฌ๋ฅผ ๋“ค์„๊นŒ? ํฌ์ŠคํŒ…์„ ๋งˆ์นœ๋‹ค.

    Evan Moon

    ๐Ÿข ๊ฑฐ๋ถ์ด์ฒ˜๋Ÿผ ์‚ด์ž

    ๊ฐœ๋ฐœ์„ ์ž˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ๊ฐ€ ์•„๋‹Œ ๊ฐœ๋ฐœ์„ ์ฆ๊ธฐ๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค. ์‚ฌ์†Œํ•œ ์ƒ๊ฐ ์ •๋ฆฌ๋ถ€ํ„ฐ ํŠœํ† ๋ฆฌ์–ผ, ์‚ฝ์งˆ๊ธฐ ์ •๋„๋ฅผ ์ฃผ๋กœ ๋„์ ์ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.