Vizualizimi audio në JavaScript me p5.js

Këtë herë mendova të vizualizoja audion nga JavaScript. Nuk ka asnjë arsye pse doja ta bëja këtë në radhë të parë! por, mendova se do të ishte interesante të bëja dhe në këtë proces, të mësoja diçka të re. Ja çfarë mësova.

Kushtet paraprake -

  1. Kuptimi bazë rreth JavaScript dhe node.js
  2. Njohuritë bazë matematikore janë avantazh.

Ju mund ta klononi projektin nga këtu dhe ta ndiqni.



git clone https://github.com/nishanc/audio-visualization.git

Konfigurimi i projektit me p5.js

Ne po e bëjmë këtë nga "p5.js", e reklamuar si "një bibliotekë JavaScript për kodim krijues, me fokus në bërjen e kodimit të aksesueshëm dhe gjithëpërfshirës për artistët, dizajnerët, edukatorët, fillestarët dhe këdo tjetër!". Epo, më duhet të them se ky është me të vërtetë rasti. Mund të bëni manipulime grafike me më pak rreshta kodi dhe ato janë të lehta për t'u kuptuar.

Mund të filloni shumë lehtë, fragmenti i mëposhtëm tregon një faqe shembulli HTML me p5.js

sketch.js duket kështu.

Mund të mësoni më shumë rreth kësaj në p5js.org/get-started. Por në këtë tutorial ne do të përdorim një server të zhvillimit të nyjeve (me express) për të ekzekutuar kodin tonë (instaloni Node dhe Git nëse nuk e keni bërë tashmë.). Për të filluar, mund të klononi kryerjen e parë të magazinës së mësipërme të github duke ekzekutuar komandat e mëposhtme me radhë. Hapni një dosje të re nga terminali/cmd dhe ekzekutoni,

git init
git remote add origin https://github.com/nishanc/audio-visualization 
git fetch origin 6c0f21158014b5bc8b21350db3fd9a5422447cd3
git reset --hard FETCH_HEAD

Kjo do t'ju japë strukturën e mëposhtme të drejtorisë.

Në të njëjtin terminal, rivendosni paketat npm me,

npm i

Tani mund ta ekzekutoni serverin me,

node server.js

Shkoni te http://localhost:3000 dhe do të shihni diçka të tillë. E cila është një elips që ndjek treguesin tuaj të miut.

createCanvas() krijon një element kanavacë në dokument dhe vendos dimensionet e tij në pixel. Funksioni background() vendos ngjyrën e përdorur për sfondin e kanavacës p5.js. ellipse() vizaton një elips (ovale) në ekran. Një elipsë me gjerësi dhe lartësi të barabartë është një rreth. Si parazgjedhje, dy parametrat e parë përcaktojnë vendndodhjen, dhe parametrat e tretë dhe të katërt përcaktojnë gjerësinë dhe lartësinë e formës. Variabli i sistemit mouseX përmban gjithmonë pozicionin aktual horizontal të miut, në raport me (0, 0) të kanavacës. Variabli i sistemit mouseY përmban gjithmonë pozicionin vertikal aktual të miut, në raport me (0, 0) të kanavacës.

Mirë. Tani e dimë se me çfarë kemi të bëjmë. le të vazhdojmë.

Po merr hyrjen e mikrofonit.

Përpara se të vizualizojmë ndonjë audio, le të shohim se si mund të marrim hyrjen e mikrofonit.

Ne mund të marrim mikrofonin e përdoruesit duke përdorur p5.AudioIn() dhe amplituda/volumi i përgjithshëm nga getLevel(). Më pas vizatojmë një elips në qendër të kanavacës (lartësia/2, gjerësia/2) me rreze vol*500, sepse volumi është një notim midis 0-1 , kështu që ne duhet ta shndërrojmë atë në një numër të madh.

Merrni amplitudë nga skedari audio.

në rregull! tani do të përpiqemi të bëjmë të njëjtën gjë për një skedar audio. Krijoni një dosje të re me emrin audio inpublic folder dhe shtoni një skedar mp3. Më pas krijoni një emër funksioni preload() dhe lexoni këngën.

function preload() {  
    song = loadSound('audio/the-alphabeat.mp3');
}

Pastaj në setup() filloni të luani këngën dhe merrni amplituda e saj duke përdorur p5.Amplitude() që mat volumin midis 0.0 dhe 1.0. Dëgjon të gjithë p5sound si parazgjedhje, ose përdorni setInput() për të dëgjuar një burim specifik tingulli.

function setup() {  
    createCanvas(600, 600)
    song.play();    
    amp = new p5.Amplitude();
}

Tani në vend të mic.getLevel() mund të themi amp.getLevel() në funksionin draw().

Amplituda e grafikut.

Tani do të grafikojmë amplituda në kanavacë. Për të krijuar një grafik na duhet historia e amplitudës. Pra, krijoni një grup bosh në rreshtin 2.

let volHistory = [];

Në funksionin e tërheqjes, shtyni secilën vlerë të amplitudës në këtë grup. Më pas kalojmë nëpër grup dhe vizatojmë një point() në koordinatat x dhe y, x jepet nga indeksi i grupit dhe y është një map() i krijuar për të hartuar amplituda (0–1) në vlerat midis kanavacës height dhe 0

let vol = amp.getLevel();
volHistory.push(vol);
for (let x = 0; x < volHistory.length; x++) {
     stroke(255)
     let y = map(volHistory[x], 0, 1, height, 0);
     point(x, y);
}

Në vend të një pike, tani do të vizatojmë një vijë. Përdorimi i funksioneve beginShape() dhe endShape() mundëson krijimin e formave më komplekse. beginShape() fillon regjistrimin e kulmeve për një formë dhe endShape() ndalon regjistrimin. Të gjitha format ndërtohen duke lidhur një sërë kulmesh. vertex() përdoret për të specifikuar koordinatat e kulmit për pikat, drejtëzat, trekëndëshat, katërkëndëshat dhe shumëkëndëshat. Pra, zëvendësoni point() me vertex(). Funksioni i përfunduar draw është si më poshtë.

Vini re gjendjen if. Ju mund të keni vënë re se kur vizatojmë grafikun me pikë, ai shkon deri në fund të kanavacës dhe ndalet. Kjo për shkak se grupi ynë volHistory është më i gjatë se gjerësia e kanavacës. Pra, ajo që ne bëjmë është nëse volHistory është më e gjatë se width, në pozicionin 0, hiqni artikullin 1 duke përdorur splice(0,1), artikulli i parë i grupit do të hiqet duke krijuar hapësirë ​​për artikullin e ri në fund.

Grafiku radial.

Tani le të modifikojmë grafikun linear në një grafik radial. Për ta arritur këtë duhet të dini lidhjen ndërmjet rrezes, këndit të rrethit me rrafshin kartezian.

Ju e dini që ne kemi nevojë për koordinatat x dhe y për të vizatuar një kulm. Nëse e dini rrezen r, në rastin tonë është amplituda dhe këndi - θ, kjo është një detyrë e lehtë.

Siç e dini, ne mund të mos përdorim amplituda ashtu siç është sepse është shumë e vogël (midis 0-1), kështu që ne do të hartojmë 010 dhe 1300. Numri maksimal i artikujve që mund të ketë grupi volHistory është gjithashtu 360, që korrespondon me numrin total të shkallëve në një rreth. translate() specifikon një sasi për të zhvendosur objektet brenda dritares së ekranit. Parametri x specifikon përkthimin majtas/djathtas, parametri y specifikon përkthimin lart/poshtë. Ne gjithashtu duam të vendosim modalitetin aktual të p5 në gradë duke përdorur angleMode(DEGREES); (modaliteti i parazgjedhur është RADIANS) në funksionin setup().

Vizualizimi i amplitudës për çdo frekuencë.

Për ta bërë këtë, ne do të përdorim p5.FFT(). FFT do të thotë "Transformimi i shpejtë i Furierit". Analiza Fourier konverton një sinjal nga domeni i tij origjinal (shpesh koha ose hapësira) në një paraqitje në fushën e frekuencës dhe anasjelltas. Ky operacion është i dobishëm në shumë fusha, por llogaritja e tij drejtpërdrejt nga përkufizimi është shpesh shumë e ngadaltë për të qenë praktike. Një algoritëm e shpejtë i transformimit të Furierit arrin të reduktojë "kompleksitetin". Kjo është gjithçka që duhet të dini.

Si fillim, le të riemërtojmë ampfft dhe në vend të p5.Amplitude() do të përdorim një p5.FFT(). Kjo kërkon dy argumente, new p5.FFT([smoothing], [bins]) smooth është një vlerë midis 0.0 dhe 1.0, ne do ta vendosim atë në 0.9 (përdoret për të zbutur analizën FFT duke mesatarizuar me kornizën e fundit të analizës). bins është në thelb numri i frekuencave / brezave që duam të heqim, parazgjedhja është 1024. Ne do ta vendosim atë në 128. Gjithashtu, do të përdorim funksionin analyze() për të marrë spektrin e frekuencës. Ai kthen një grup vlerash amplitude (midis 0 dhe 255) në të gjithë spektrin e frekuencës.

[75, 73, 74, 63, 54, 61, 71, 97, 122, 121, 116, 117, 127, 142, 151, 160, 182, 189, 215, 254, 255, 245, 183, 144, 136, 132, 124, 120, 127, 137, 140, 129, 126, 136, 133, 135, 151, 180, 184, 197, 203, 183, 145, 129, 118, 105, 106, 100, 104, 117, 131, 126, 131, 123, 144, 150, 148, 149, 166, 191, 197, 176, 129, 117, 117, 106, 115, 120, 115, 118, 125, 127, 127, 135, 135, 136, 138, 137, 168, 202, 206, 181, 137, 134, 141, 131, 128, 137, 140, 151, 153, 145, 154, 148, 145, 147, 148, 152, 198, 229, …]

Ajo që ne po përpiqemi të bëjmë është të vizatojmë një vijë për çdo brez frekuencash. Lartësia e secilës rresht është e barabartë me amplituda e atij brezi. Duke përdorur funksionin map() si më parë, do ta vendosim këtë vlerë në height të kanavacës. Dhe unë kam shtuar një buton për të ndaluar dhe luajtur audion. sketch.js i modifikuar është si më poshtë.

Është grumbulluar së bashku apo jo? Le të kemi pak hapësirë ​​midis tyre. Nëse duam ta zgjerojmë këtë linjë 128 (madhësia e koshit që kemi vendosur më herët) në të gjithë width të kanavacës, hapësira midis secilës rresht duhet të jetë width/128.

Krijoni një ndryshore të re dhe vendoseni në width/128 në funksionin setup().

space_between_lines = width / 128;

Dhe në draw() zëvendësoni linjën,

line(i, height, i, y);

me ,

line(i * space_between_lines, height, i * space_between_lines, y);

Tani do të merrni diçka të tillë.

Në vend të vijave mund të vizatoni drejtkëndësha duke përdorur rect()

Shtoni colorMode(HSB);në funksionin setup(). Pastaj në draw() zëvendëso,

line(i * space_between_lines, height, i * space_between_lines, y);

me,

fill(i,255,255); //remove stroke(255);
rect(i * space_between_lines, y, space_between_lines, height - y);

Prodhimi do të duket diçka si kjo.

Nëse dëshironi të ktheni spektrin në boshtin x, ndryshoni vijën e mësipërme si më poshtë.

rect(width - (i * space_between_lines), y, space_between_lines, height - y);

Mundohuni të ndryshoni vlerat dhe të dilni me një dizajn tuajin kreativ. Me pak ndryshim provoni nëse mund të krijoni efektin e mëposhtëm.

Kodi për këtë dalje është në degën symmetric-spectrum, Klononi magazinë dhe ndërroni degën duke përdorur git checkout symmetric-spectrum

Epo kjo është ajo. Shpresoj se keni mësuar diçka! Qëndroni të sigurt!.