Cuprins:

Sintetizator cu harpă laser pe placa Zybo: 10 pași (cu imagini)
Sintetizator cu harpă laser pe placa Zybo: 10 pași (cu imagini)

Video: Sintetizator cu harpă laser pe placa Zybo: 10 pași (cu imagini)

Video: Sintetizator cu harpă laser pe placa Zybo: 10 pași (cu imagini)
Video: imbunatatire a miniorgii & upgrade minilight organ 2024, Noiembrie
Anonim
Sintetizator cu harpă laser pe placa Zybo
Sintetizator cu harpă laser pe placa Zybo

În acest tutorial vom crea o harpă laser complet funcțională utilizând senzori IR cu o interfață serială care va permite utilizatorului să schimbe reglajul și tonul instrumentului. Această harpă va fi remake-ul secolului 21 al instrumentului vechi. Sistemul a fost creat folosind o placă de dezvoltare Xilinx Zybo împreună cu Vivado Design Suites. De ce veți avea nevoie pentru a finaliza proiectul:

  • 12 senzori și emițori IR (mai mult sau mai puțin pot fi folosiți în funcție de numărul de șiruri)
  • Placă de dezvoltare Zybo Zynq-7000
  • RTOS gratuit
  • Vivado Design Suite
  • Sârmă (pentru conectarea senzorilor la placă)
  • 3 bucăți de țeavă din PVC ((2) 18 inch și (1) 8 inch)
  • 2 coate din PVC

Pasul 1: obțineți demonstrația audio Digy Zybo DMA

Partea FPGA a acestui proiect se bazează în mare parte pe proiectul demonstrativ găsit aici. Folosește acces direct la memorie pentru a trimite date direct din memorie pe care procesorul le poate scrie prin AXI Stream într-un bloc audio I2S. Următorii pași vă vor ajuta să puneți în funcțiune proiectul de demonstrație audio DMA:

  1. Poate fi necesară o nouă versiune a fișierului de bord pentru placa Zybo. Urmați aceste instrucțiuni pentru a obține noi fișiere de bord pentru Vivado.
  2. Urmați pașii 1 și 2 din instrucțiunile de pe această pagină pentru a deschide proiectul demonstrativ în Vivado. Folosiți metoda Vivado, nu transferul hardware SDK.
  3. Este posibil să primiți un mesaj care spune că unele dintre blocurile dvs. IP ar trebui actualizate. Dacă da, selectați „Afișați starea IP” și apoi în fila Stare IP selectați toate IP-urile depășite și faceți clic pe „Upgrade selectat”. Când se termină și apare o fereastră care vă întreabă dacă doriți să generați produsul de ieșire, continuați și faceți clic pe „Generați”. Dacă primiți un mesaj de avertizare critic, ignorați-l.
  4. Treceți de la design la fila surse din Vivado pentru a vedea fișierele sursă. Faceți clic dreapta pe designul blocului „design_1” și selectați „Create HDL Wrapper”. Când vi se solicită, selectați „copiați ambalajul generat pentru a permite modificările utilizatorului”. Va fi generat un fișier wrapper pentru proiect.
  5. Acum, după ce acei pași critici care au fost cumva lăsați deoparte în celălalt tutorial sunt finalizați, puteți reveni la tutorialul legat anterior și puteți continua de la pasul 4 până la final și asigurați-vă că proiectul demo rulează corect. Dacă nu aveți o modalitate de a introduce audio pentru ca acesta să înregistreze, înregistrați doar cu căștile și ascultați un sunet fuzzy de 5-10 secunde când apăsați butonul de redare. Atâta timp cât ceva iese din mufa căștilor atunci când apăsați butonul de redare, probabil că funcționează corect.

Pasul 2: Faceți câteva modificări în Vivado

Faceți câteva modificări în Vivado
Faceți câteva modificări în Vivado

Așadar, acum aveți demo-ul audio DMA Digilent funcțional, dar acesta nu este deloc scopul final aici. Deci, trebuie să ne întoarcem la Vivado și să facem câteva modificări, astfel încât senzorii noștri să poată fi conectați la anteturile PMOD și să le putem folosi valoarea din partea software-ului.

  1. Deschideți diagrama bloc în Vivado
  2. Creați un bloc GPIO făcând clic dreapta în spațiul gol din diagrama bloc și selectând „Adăugați IP” din meniu. Găsiți și selectați „AXI GPIO”.
  3. Faceți dublu clic pe noul bloc IP și în fereastra de re-personalizare IP accesați fila de configurare IP. Selectați toate intrările și setați lățimea la doisprezece, deoarece vom avea 12 „corzi” pe harpa noastră și, prin urmare, vom avea nevoie de 12 senzori. Dacă doriți să utilizați mai puțini senzori sau mai mulți, reglați acest număr în mod corespunzător. De asemenea, setați întreruperea activării.
  4. Faceți clic dreapta pe noul bloc IP GPIO și selectați „rulați automatizarea conexiunii”. Bifați caseta AXI și apăsați OK. Aceasta ar trebui să conecteze automat interfața AXI, dar să lase ieșirile blocului neconectate.
  5. Pentru a face loc pentru întreruperea suplimentară, faceți dublu clic pe blocul IP xlconcat_0 și modificați numărul de porturi de la 4 la 5. Apoi puteți conecta pinul ip2intc_irpt din noul bloc GPIO la noul port neutilizat de pe blocul xlconcat.
  6. Faceți clic dreapta pe ieșirea „GPIO” a noului bloc IP GPIO și selectați „faceți extern”. Găsiți unde merge linia și faceți clic pe micul pentagon lateral și în stânga ar trebui să se deschidă o fereastră unde puteți schimba numele. Schimbați numele în „SENZORI”. Este important să utilizați același nume dacă doriți să funcționeze fișierul de constrângeri pe care îl oferim, altfel va trebui să schimbați numele în fișierul de constrângeri.
  7. Înapoi în fila surse, găsiți fișierul de constrângeri și înlocuiți-l cu cel pe care îl oferim. Puteți alege fie să înlocuiți fișierul, fie să copiați conținutul fișierului nostru de constrângeri și să-l inserați pe conținutul celui vechi. Unul dintre lucrurile importante pe care le face fișierul nostru de constrângeri este activarea rezistențelor de pullup de pe antetele PMOD. Acest lucru este necesar pentru senzorii anteriori pe care i-am folosit, însă nu toți senzorii sunt la fel. Dacă senzorii dvs. necesită rezistențe derulante, puteți schimba fiecare instanță „set_property PULLUP true” cu „set_property PULLDOWN true”. Dacă necesită o valoare a rezistenței diferită de cea de pe placă, atunci puteți elimina aceste linii și utilizați rezistențe externe. Numele pinilor se află în comentariile din fișierul de constrângeri și corespund etichetelor din prima diagramă din schemele Zybo pagină care poate fi găsită aici. Dacă doriți să utilizați pini pmod diferiți, potriviți doar numele din fișierul de constrângere cu etichetele din schemă. Utilizăm antetul PMOD JE și JD și folosim șase pini de date pe fiecare, omițând pinii 1 și 7. Aceste informații sunt importante atunci când conectați senzorii. Așa cum se arată în schemă, pinii 6 și 12 de pe PMODS sunt VCC și pinii 5 și 11 sunt măcinați.
  8. Regenerați învelișul HDL ca înainte și copiați și suprascrieți vechiul. După ce ați terminat, generați flux de biți și exportați hardware-ul ca înainte și relansați SDK-ul. Dacă sunteți întrebat dacă doriți să înlocuiți vechiul fișier hardware, răspunsul este da. Este probabil cel mai bine să aveți SDK-ul închis când exportați hardware, astfel încât să fie înlocuit corect.
  9. Lansați SDK-ul.

Pasul 3: Rulați FreeRTOS

Următorul pas este să rulați FreeRTOS pe placa Zybo.

  1. Dacă nu aveți deja o copie, descărcați FreeRTOS aici și extrageți fișierele.
  2. Importați demo-ul FreeRTOS Zynq aflat la FreeRTOSv9.0.0 / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo. Procesul de import este aproape la fel ca și pentru celălalt proiect demo, totuși, deoarece demo-ul FreeRTOS Zynq se bazează pe alte fișiere din folderul FreeRTOS, nu ar trebui să copiați fișierele în spațiul de lucru. În schimb, ar trebui să plasați întregul folder FreeRTOS în dosarul proiectului.
  3. Creați un nou pachet de asistență pentru bord accesând „fișier” -> „nou” -> „pachet de asistență pentru bord”. Asigurați-vă că este selectat autonom și faceți clic pe Terminare. După un moment se va afișa o fereastră, bifați caseta de lângă lwip141 (aceasta oprește unul dintre demo-urile FreeRTOS să nu poată compila) și apăsați OK. După ce se finalizează, faceți clic dreapta pe proiectul RTOSdemo și accesați „proprietăți”, accesați fila „Referințe proiect” și bifați caseta de lângă noul bsp pe care l-ați creat. Sperăm că va fi recunoscut, dar uneori SDK-ul Xilinx poate fi ciudat în legătură cu acest gen de lucruri. Dacă totuși primiți o eroare după acest pas, lipsește xparameters.h sau ceva de genul acesta, încercați să repetați acest pas și poate ieșiți și relansați SDK-ul.

Pasul 4: Adăugați codul Laser Harp

Acum că FreeRTOS este importat, puteți aduce fișierele din proiectul laser harp în demo-ul FreeRTOS

  1. Creați un folder nou sub folderul src în demo-ul FreeRTOS și copiați și lipiți toate fișierele c furnizate, cu excepția main.c în acest folder.
  2. Înlocuiți RTOSDemo main.c cu main.c.
  3. Dacă totul este făcut corect, ar trebui să puteți rula codul harpei laser în acest moment. În scopuri de testare, intrarea butonului care a fost utilizată în proiectul demonstrativ DMA este acum utilizată pentru a reda sunete fără senzori atașați (oricare dintre cele patru butoane principale va funcționa). Va reda un șir de fiecare dată când îl apăsați și va parcurge toate șirurile din sistem prin apăsări multiple. Conectați câteva căști sau difuzoare la mufa pentru căști de pe placa Zybo și asigurați-vă că puteți auzi sunetele corzilor care vin prin apăsarea unui buton.

Pasul 5: Despre cod

Este posibil ca mulți dintre voi care citiți acest tutorial să învețe cum să configurați sunetul sau să utilizați DMA pentru a face ceva diferit sau pentru a crea un alt instrument muzical. Din acest motiv, următoarele secțiuni se dedică descrierii modului în care funcționează codul furnizat împreună cu hardware-ul descris anterior pentru a obține o ieșire audio funcțională utilizând DMA. Dacă înțelegeți de ce există piesele de cod, atunci ar trebui să le puteți ajusta pentru orice doriți să creați.

Întrerupe

Mai întâi voi menționa modul în care sunt create întreruperile în acest proiect. Modul în care am făcut-o a fost prin crearea mai întâi a unei structuri de tabele vector de întrerupere, care ține evidența ID-ului, gestionarea întreruperilor și o referință la dispozitiv pentru fiecare întrerupere. ID-urile de întrerupere provin de la xparameters.h. Manipulatorul de întreruperi este o funcție pe care am scris-o pentru DMA și GPIO, iar întreruperea I2C provine de la driverul Xlic I2C. Referința dispozitivului indică instanțele fiecărui dispozitiv pe care le inițializăm în altă parte. Aproape de sfârșitul funcției _init_audio o buclă trece prin fiecare element din tabelul vectorului de întrerupere și apelează două funcții, XScuGic_Connect () și XScuGic_Enable () pentru a conecta și a activa întreruperile. Se referă la xInterruptController, care este un controler de întrerupere creat în FreeRTOS main.c în mod implicit. Deci, practic, atașăm fiecare dintre întreruperile noastre la acest controler de întrerupere, care a fost deja creat pentru noi de FreeRTOS.

DMA

Codul de inițializare DMA începe în lh_main.c. Mai întâi este declarată o instanță statică a unei structuri XAxiDma. Apoi, în funcția _init_audio () se configurează. Mai întâi se apelează funcția de configurare din proiectul demo, care se află în dma.c. Este destul de bine documentat și vine direct de la demonstrație. Apoi întreruperea se conectează și se activează. Pentru acest proiect este necesară doar întreruperea master-to-slave, deoarece toate datele sunt trimise de DMA către controlerul I2S. Dacă doriți să înregistrați sunet, veți avea nevoie și de întreruperea de la sclav la stăpân. Întreruperea master-to-slave este apelată când DMA termină de trimis orice date i-ați spus să trimită. Această întrerupere este extrem de importantă pentru proiectul nostru, deoarece de fiecare dată când DMA termină de trimis un buffer de eșantioane audio, trebuie să înceapă imediat să trimită următorul buffer, altfel ar avea loc o întârziere sonoră între trimiteri. În funcția dma_mm2s_ISR () puteți vedea cum gestionăm întreruperea. Partea importantă este aproape de final, unde folosim xSemaphoreGiveFromISR () și portYIELD_FROM_ISR () pentru a notifica _audio_task () că poate iniția următorul transfer DMA. Modul în care trimitem date audio constante este prin alternarea a două buffere. Când un buffer este transmis către blocul I2C, celălalt buffer are valorile calculate și stocate. Apoi, când întreruperea provine de la DMA, buffer-ul activ comută, iar buffer-ul scris mai recent începe să fie transferat, în timp ce bufferul transferat anterior începe să fie suprascris cu date noi. Partea cheie a funcției _audio_task este locul unde este apelat fnAudioPlay (). fnAudioPlay () preia instanța DMA, lungimea bufferului și un pointer către bufferul din care vor fi transferate datele. Câteva valori sunt trimise către registrele I2S pentru a-i informa că vin mai multe mostre. Apoi XAxiDma_SimpleTransfer () este chemat pentru a iniția transferul.

Audio I2S

audio.c și audio.h sunt locul unde are loc inițializarea I2S. Codul de inițializare I2S este o bucată destul de obișnuită de cod care plutește în mai multe locuri, s-ar putea să găsiți ușoare variații din alte surse, dar aceasta ar trebui să funcționeze. Este destul de bine documentat și nu trebuia schimbat mult pentru proiectul harpă. Demo-ul audio DMA din care provine are funcții pentru trecerea la intrările de microfon sau linie, astfel încât să le puteți utiliza dacă aveți nevoie de acea funcționalitate.

Sinteza sunetului

Pentru a descrie modul în care funcționează sinteza sunetului, voi lista fiecare dintre modelele de sunet utilizate în dezvoltare care au condus la metoda finală, deoarece vă va oferi un sentiment de ce se face așa cum se face.

Metoda 1: O perioadă de valori sinusoidale este calculată pentru fiecare șir la frecvența corespunzătoare pentru nota muzicală a acelui șir și stocată într-o matrice. De exemplu, lungimea matricei va fi perioada undei sinusoidale din eșantioane, care este egală cu # de eșantioane / ciclu. Dacă rata de eșantionare este de 48 kHz și frecvența notei este de 100 Hz, atunci există 48, 000 de eșantioane / secundă și 100 de cicluri / secundă care duc la 4800 de eșantioane pe ciclu, iar lungimea matricei va fi de 4800 de eșantioane și va conține valorile unui complet perioada sinusoidală. Când este redat șirul, buffer-ul eșantionului audio este umplut luând o valoare din matricea de unde sinusoidale și plasându-l în tamponul audio ca eșantion, apoi incrementând indexul în matricea de unde sinusoidale, astfel încât să folosim exemplul nostru anterior pe parcurs din 4800 de probe, un ciclu de undă sinusoidală este introdus în bufferul audio. O operație modulo este utilizată pe indexul matricei, astfel încât să scadă întotdeauna între 0 și lungime, iar când indexul matricei depășește un anumit prag (cum ar fi probabil 2 secunde în valoare de eșantioane) șirul este oprit. Pentru a reda mai multe șiruri de caractere în același timp, țineți evidența separată a indexului de matrice al fiecărui șir și adăugați valoarea din undele sinusoidale ale fiecărui șir împreună pentru a obține fiecare eșantion.

Metoda 2: Pentru a crea un ton mai muzical, începem cu modelul anterior și adăugăm armonici la fiecare frecvență fundamentală. Frecvențele armonice sunt frecvențe care sunt multipli întregi ai frecvenței fundamentale. Spre deosebire de momentul în care două frecvențe fără legătură sunt însumate împreună, ceea ce duce la redarea simultană a două sunete distincte, atunci când armoniile sunt adăugate, acesta continuă să sune ca un singur sunet, dar cu un ton diferit. Pentru a realiza acest lucru, de fiecare dată când adăugăm valoarea undei sinusoidale la locație (array index% array length) la proba audio, adăugăm și (2 * array index% array length) și (3 * array index% array length), și așa mai departe pentru cât de multe armonici sunt dorite. Acești indici înmulțiți vor traversa unda sinusoidală la frecvențe care sunt multipli întregi ai frecvenței inițiale. Pentru a permite un control mai mare al tonului, valorile fiecărei armonici sunt înmulțite cu o variabilă care reprezintă cantitatea de armonică din sunetul general. De exemplu, unda sinusoidală fundamentală ar putea avea valorile sale înmulțite cu 6 pentru a face mai mult un factor al sunetului general, în timp ce a 5-a armonică ar putea avea un multiplicator de 1, ceea ce înseamnă că valorile sale contribuie mult mai puțin la sunetul general.

Metoda 3: Bine, deci acum avem un ton foarte frumos pe note, dar există încă o problemă destul de crucială: ele se joacă la un volum fix pentru o durată fixă. Pentru a suna deloc ca un instrument real, volumul unei coarde care se joacă ar trebui să se descompună în timp. Pentru a realiza acest lucru, o matrice este umplută cu valorile unei funcții exponențial descompuse. Acum, când sunt create eșantioanele audio, sunetul provenit de la fiecare șir este calculat ca în metoda anterioară, dar înainte de a fi adăugat la eșantionul audio, acesta se înmulțește cu valoarea la indicele matricei acelor șiruri din matricea funcției de descompunere exponențială. Acest lucru face ca sunetul să se disipeze fără probleme în timp. Când indexul matricei ajunge la sfârșitul matricei de descompunere, șirul este oprit.

Metoda 4: Acest ultim pas este ceea ce oferă cu adevărat sunetelor de coardă sunetul lor realist de coarde. Înainte păreau plăcute, dar clar sintetizate. Pentru a încerca să emulați mai bine un șir de harpă din lumea reală, fiecărei armonici i se atribuie o rată de descompunere diferită. În șirurile reale, când șirul este lovit pentru prima dată, există un conținut ridicat de armonici de înaltă frecvență care creează genul de sunet de smulgere pe care îl așteptăm de la un șir. Aceste armonici de înaltă frecvență sunt foarte pe scurt partea principală a sunetului, sunetul șirului fiind lovit, dar se descompun foarte repede pe măsură ce armoniile mai lente preiau. Se creează o matrice de descompunere pentru fiecare număr armonic utilizat în sinteza sunetului fiecare cu propria sa rată de descompunere. Acum fiecare armonică poate fi înmulțită în mod independent cu valoarea matricei sale de dezintegrare corespunzătoare la indicele matrice al șirului și adăugată la sunet.

În general, sinteza sunetului este intuitivă, dar calculul este greu. Stocarea întregului sunet de șir în memorie simultan ar necesita prea multă memorie, dar calcularea undei sinusoidale și a funcției exponențiale între fiecare cadru ar dura mult timp pentru a ține pasul cu rata de redare audio. Un număr de trucuri sunt utilizate în cod pentru a accelera calculul. Toate matematica, cu excepția creației inițiale a tabelelor sinus și exponențiale, se realizează în format întreg, ceea ce necesită răspândirea spațiului numeric disponibil în ieșirea audio de 24 biți. De exemplu, masa sinusoidală este de amplitudine 150, astfel încât să fie netedă, dar nu atât de mare încât multe corzi jucate împreună să poată adăuga peste 24 de biți. La fel, valorile tabelului exponențial sunt înmulțite cu 80 înainte de a fi rotunjite la numere întregi și stocate. Greutățile armonice pot lua valori discrete între 0 și 10. De asemenea, toate probele sunt de fapt dublate, iar undele sinusoidale sunt indexate cu 2, înjumătățind efectiv rata de eșantionare. Aceasta limitează frecvența maximă care poate fi redată, dar a fost necesară pentru ca numărul curent de corzi și armonici să fie calculat suficient de rapid.

Crearea acestui model de sunet și punerea acestuia în funcțiune au presupus un efort considerabil din partea procesorului și ar fi fost incredibil de dificil să-l funcționezi de pe zero pe partea fpga în intervalul de timp al acestui proiect (imaginați-vă că trebuie să recreați fluxul de biți la fiecare când o bucată de verilog a fost schimbată pentru a testa sunetul). Cu toate acestea, a face acest lucru pe fpga ar putea fi probabil o modalitate mai bună de a face acest lucru, eliminând eventual problema de a nu putea calcula eșantioanele suficient de repede și de a permite mai multe șiruri, armonici și chiar efecte audio sau alte sarcini să fie rulate pe partea procesorului.

Pasul 6: Cablarea senzorilor

Cablarea senzorilor
Cablarea senzorilor

Pentru a crea șirurile am folosit senzori IR de fascicul de rupere care vor detecta când se joacă șirul. Ne-am comandat senzorii de pe următorul link. Senzorii au un cablu de alimentare, de împământare și de date, în timp ce emițătorii au doar un cablu de alimentare și de împământare. Am folosit pinii de 3,3 V și de masă de la antetele PMOD pentru a alimenta atât emițătorii, cât și senzorii. Pentru a alimenta toți senzorii și emițătorii este necesar să conectați toți senzorii și emițătorul în paralel. Cablurile de date de la senzori vor trebui să meargă fiecare la propriul pin PMOD.

Pasul 7: Construirea scheletului

Construirea scheletului
Construirea scheletului

Pentru a crea forma harpei, cele trei piese sunt folosite ca schelet pentru a plasa senzorii și emițătorii. Pe una dintre cele două bucăți de țeavă din PVC de 18 inci aliniați senzorii și emițătorii în ordine alternativă la 1,5 inci unul de celălalt și apoi lipiți-i pe țeavă. Pe cealaltă țeavă din PVC de 18 inci aliniați senzorii și emițătorii în ordine alternativă, dar asigurați-vă că ați compensat comanda (adică dacă prima țeavă a avut mai întâi un senzor, a doua ar trebui să aibă mai întâi un emițător și invers). Va fi necesar să lipiți fire mai lungi pe date, alimentare și fire de masă pentru a vă asigura că vor putea ajunge la bord.

Pasul 8: Construirea exteriorului din lemn

Construirea exteriorului din lemn
Construirea exteriorului din lemn

Acest pas este opțional, dar este foarte recomandat. Exteriorul din lemn nu numai că face harpa să arate frumos, ci și protejează senzorii și firele de deteriorări. Cadrul din lemn poate fi creat de un inel dreptunghiular sfânt din lemn. Interiorul dreptunghiului trebuie să aibă o deschidere de cel puțin 1-1 / 2 inci pentru a se potrivi țeava și scheletul senzorului. Odată ce cadrul este construit, găuriți două găuri care vor permite firele de la senzor și emițătoare să fie conectate cu placa.

* Notă: Se recomandă adăugarea de puncte de acces pentru a putea scoate și introduce scheletul țevii în cazul în care trebuie să se facă reparații sau să fie necesare mici ajustări.

Pasul 9: Asamblarea tuturor pieselor

Punând toate piesele împreună
Punând toate piesele împreună

Odată ce toți pașii anteriori sunt finalizați, este timpul să construiți harpa. Mai întâi așezați scheletul țevii în interiorul exteriorului din lemn. Apoi conectați firele pentru senzori și emițătoare în locația corectă de pe placă. Apoi deschideți SDK-ul și faceți clic pe butonul de depanare pentru a programa placa. Odată ce placa este programată, conectați o pereche de căști sau un difuzor. În funcție de senzorul care ajunge în portul pmod, corzile harpei dvs. vor fi, probabil, în neregulă pentru început. Deoarece poate fi dificil să spunem ce fir merge la ce senzor atunci când sunt implicate atât de multe fire, am inclus o modalitate de a mapa numerele șirurilor pentru a întrerupe pozițiile de biți din software. Găsiți „static int sensor_map [NUM_STRINGS]” și reglați valorile din matrice până când șirurile se joacă de la cel mai mic la cel mai mare în ordine.

Meniul poate fi utilizat deschizând un terminal serial (de ex. RealTerm) și setați rata de transmisie la 115200 și afișajul la ANSI. Meniul poate fi navigat folosind tastele w și s pentru a vă deplasa în sus și în jos și tastele a și d pentru a modifica valorile.

Pasul 10: ROCK OUT

Odată ce harpa este pe deplin funcțională. Stăpânește harpa și ascultă sunetul dulce al propriei tale muzici!

Recomandat: