תוכן עניינים:

פרויקט גיבור גיטרה ארדואינו: 12 שלבים (עם תמונות)
פרויקט גיבור גיטרה ארדואינו: 12 שלבים (עם תמונות)

וִידֵאוֹ: פרויקט גיבור גיטרה ארדואינו: 12 שלבים (עם תמונות)

וִידֵאוֹ: פרויקט גיבור גיטרה ארדואינו: 12 שלבים (עם תמונות)
וִידֵאוֹ: גיבור גיטרה 2024, נוֹבֶמבֶּר
Anonim
פרויקט גיבור גיטרה ארדואינו
פרויקט גיבור גיטרה ארדואינו
פרויקט גיבור גיטרה ארדואינו
פרויקט גיבור גיטרה ארדואינו
פרויקט גיבור גיטרה ארדואינו
פרויקט גיבור גיטרה ארדואינו

Wij zijn Maarten Vrebos, Justin Cavanas en Wannes Stroobandt and we studderen multimedia & communicatietechnology. עבור קבוצה של פרויקטים עבור הוויק אודיו-ויזואלי & עקרונות IT, אנו יכולים לבחור גיבור גיטרה כמשתמש כשימוש עבור בקר MIDI שלנו. זה היה הכוונה שלנו לאתר הקבוצות הקיימות על החלפות. הבקר שלנו יכול להיות מוגבל כמכשיר רגיל. אנו יכולים לראות שיש לנו הרבה חומר נוסף שצריך לעבוד.

בתמונה אתה יכול לראות את כל סוגי הארגונים שלנו על נייר כדי לראות איך המוצר הסופי יצטרך לראות אחר כך תמונה של המכשיר.

אנו מכוונים לפרויקט זה המבוסס על הבאות הבאות:

slapyak.wordpress.com/guitar-hero-midi-con…

www.instructables.com/id/Converting-a-rescu…

gizmodo.com/391834/turn-your-guitar-hero-g…

פרוייקט Benodigdheden voor dit

  • 6 לחצנים קטנים
  • 7 נגדים של 1 קאוהם
  • 1 LED LED 1
  • כחול לד
  • 1 Arduino Uno R3
  • 1 LED גדול
  • 2 נוריות LED
  • 1 schuifschakelaar
  • קרש לחם אחד
  • פוטנציומטר אחד
  • 1 פרוטובורד
  • גיטאר גיבור גיטרה
  • דירוג מיטה Voldoende
  • חומר על סולדר/דרמלן/
  • Schroevendraaier

שלב 1: Componenten Verzamelen

Componenten Verzamelen
Componenten Verzamelen

לאב טיפוס שלנו (לוח קרשים) אנו מכילים את המרכיבים הבאים:

6 כפתורים

7 נגדים של 1 קאוהם

1 LED צהוב

1 LED כחול

1 Arduino Uno R3

1 LED ירוק

2 LED אדום

1 Schuifschakelaar

לוח אחד

פוטנציומטר 1

שלב 2: אב טיפוס Bouwen

אב טיפוס Bouwen
אב טיפוס Bouwen
אב טיפוס Bouwen
אב טיפוס Bouwen
אב טיפוס Bouwen
אב טיפוס Bouwen

אם יש לנו אב טיפוס לבניית כל המרכיבים שלנו המשמשים על קרש לחם, קרש לחם זה צריך להיות גם כמטרה, כך שאנו לא יכולים להתמודד עם העבודה. אב טיפוס זה יכולנו גם להתבצע באמצעות tinkercad.com, ולפי זה אנו יכולים להבחין בבירור באב טיפוס של קבוצות כלשהן.

כפתורי לחיצה קטנים 5 משמשים את הפונקציה כ -5 חבטות ולחץ כפתור גדול בשילוב עם כמה וכמה 'סנרים' חייבים להיות מובנים לאפקט ביקורת אחד. מגוון מנורות LED משמשות בדרך כלל גם כבדיקת וידואות לגבי הבטחות שהאינטראקציה שלה עשויה להצליח.

שלב 3: אב טיפוס לקוד

קוד אב טיפוס
קוד אב טיפוס

גלובאל משתנים

לראשונה, חלק מהקוד יתחיל לשנות את הגלובליות של הסיכות של הארדואינו והיכן כל הלחצנים יכולים להיעשות.

// zet pin numbers waar mainButton (snaar) וכפתורים אחרים למילים הם: const int mainButton = A1; // gitaar snaar const int lightSensor = A0; const int buttonPin1 = 2; // מספר van pushbutton1 const int buttonPin2 = 3; // מספר ואן pushbutton2const int buttonPin3 = 4; // מספר ואן pushbutton3const int buttonPin4 = 5; // מספר van pushbutton4const int buttonPin5 = 6; // כפתור מספר ואן 5

כאן ניתן להפעיל שני מערכים שנועדו לתת להם את שם הלחצנים ולחצות.

const int aantalKnoppen = 5; const String namenKnoppen [מספרKnoppen] = {"כפתור 1", "כפתור 2", "כפתור 3", "כפתור 4", "כפתור 5"}; const int knopPinnen [מספרKnoppen] = {2, 3, 4, 5, 6};

אפשר גם לשנות את הסיכות של פיסות LED.

const int ledPin1 = 13; // מספר סיכת הלד 13

const int ledPin2 = 12; // מספר סיכת LED 12 const int ledPin3 = 11; // מספר סיכת LED 11 const int ledPin4 = 10; // מספר סיכת LED 10 const int ledPin5 = 9; // מספר סיכת LED 9 const int potPin = A5; // מספר סיכת LED A5

De laatste global variabelen dienen as 'states' for de sensors (zijn the pushbuttons ingedrukt of niet? Potentiometer, lichtsensor).

// initialize buttonStates voor de knoppen (ingedrukt of niet) int mainButtonState = 0; int buttonState1 = 0; int buttonState2 = 0; int buttonState3 = 0; int buttonState4 = 0; int buttonState5 = 0; int lightSensorState = 0; int potValue = 0; int lightValue = 0;

להכין

כעת, הגדרת פונקציית ההתקנה. זה הוא סוג הריק (נותן שום ערך חוזר) וההנחיות כאן לא יכולות להתבצע אלא פעם אחת.

על כל פונקציה יש הערות שנכתבו במה שעשיתי קונקרטית. תוספת מיוחדת למשהו פונקציונלי קונקרטי עושה הוא למצוא את ההתייחסות בארדואינו

הגדרת void () {// קצב נתונים לשנייה (baud) עבור העברת נתונים serial.begin (9600); // התחל לאתחל את משתני ledPin גם כפלט pinMode (ledPin1, OUTPUT); pinMode (ledPin2, OUTPUT); pinMode (ledPin3, OUTPUT); pinMode (ledPin4, OUTPUT); pinMode (ledPin5, OUTPUT); // אתחול כל הלחצנים כקלט: pinMode (mainButton, INPUT); pinMode (buttonPin1, INPUT); pinMode (buttonPin2, INPUT); pinMode (buttonPin3, INPUT); pinMode (buttonPin4, INPUT); pinMode (buttonPin5, INPUT); pinMode (potPin, INPUT); pinMode (lightSensor, INPUT); }

ביטול פונקציה

לאחר ההתקנה () פונקציה עוקבת אחר הלולאה () פונקציה, ההנחיות שהן עומדות להופיע הופעות.

לולאת void () {// lees de staat van de pushbuttons uit (ingedrukt of niet) mainButtonState = digitalRead (mainButton); buttonState1 = digitalRead (buttonPin1); buttonState2 = digitalRead (buttonPin2); buttonState3 = digitalRead (buttonPin3); buttonState4 = digitalRead (buttonPin4); buttonState5 = digitalRead (buttonPin5);

// כל הלחצן הלחצן במערך אחד

int buttonStates = {buttonState1, buttonState2, buttonState3, buttonState4, buttonState5};

// leest de waarde uit van de potentiometer en de lichtsensor

potValue = analogRead (potPin); lightValue = analogRead (lightSensor);

// הצהיר על מערך mainStates והגדרות הסטנדרטים של ערך 0 אינץ '.

int mainStates = {0, 0, 0, 0, 0};

// loop over de array numberKnoppen

for (int i = 0; i <מספרKnoppen; i ++) {pinMode (knopPinnen , INPUT); // אתחול כל knopPinnen כקלט digitalRead (knopPinnen ); // lees de waarde van all knoppinnen uit // indien de mainswitch (snaar) ingedrukt is, print all knopnamen, all buttonstates if (mainButtonState == HIGH) {Serial.print (namenKnoppen ); Serial.print (","); Serial.println (buttonStates ); }}

שלב 4: אב טיפוס Uittesten

לאחר שהאב טיפוס נבנה הוא לפי המודל שלנו והקוד שנכתב בעיבוד, האם הזמן של אבות הטיפוס ייבדק. בסרטון ניתן לראות כל תגובה שמאפשרת להבחין במגוון נושאים וגם בשילובים אפשריים.

בסרטון השני ניתן לראות כיצד הטרולו שלנו פועל ביד עם פוטנציומטר במכשיר ואיך הם יכולים להיות מובלטים בעיבוד.

שלב 5: הפקת "ontmantelen" En Kijken Welke Componenten Gebruikt Gaan Worden

Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing
Behuizing

אם אנו משתמשים בקוד הנכון על אב הטיפוס שלנו, התחלנו להכיר את הגיבור של הגיטרה שלנו. אנו יכולים לפתוח את הפעולות הבאות עם תוכנת שרוול ולדעת אילו מרכיבים מקוריים אנו עשויים לאפשר לאפשר שימוש אחר עבור הבקר שלנו. אנו יכולים להשתמש בכפתורי הלחימה שלנו בכפתורים הקיימים. השתמשנו בטרמולו גם בשימוש עבור המוצר הסופי והכפתור הראשי שלנו (כפתור ראשוני לכל שילוב של משחקים). הלדים יסתפקו (אלה היו רק אינדיקציה כך שאנו יכולים לתקן את כל הדברים הנכונים.

שלב 6: עבודה על לחצני Originele + Dremelen

לחצני Originele + Dremelen
לחצני Originele + Dremelen

הסרטון המתאים הוא כיצד ניתן לראות כיצד שני המקצועות המקוריים פועלים כמו סוג של חבילה שאנו משתמשים בה כדי ליצור אפקט אחד לשילוב של קופנים.

על כפתורינו העצמיים כדי ליצור עבודות מקוריות, אנו יכולים למצוא את המקומות האחרונים של המקורות הגדולים כמו לראות את התמונה.

שלב 7: Solderen + לחצנים Vastlijmen

Bedrading Solderen + לחצנים Vastlijmen
Bedrading Solderen + לחצנים Vastlijmen
Bedrading Solderen + לחצנים Vastlijmen
Bedrading Solderen + לחצנים Vastlijmen
Bedrading Solderen + לחצנים Vastlijmen
Bedrading Solderen + לחצנים Vastlijmen

מכיוון שאנו לא יכולים להכיל מגוון רחב של רכיבים שונים זה בזה. לאחר שהדבר יכול לקרות כפתורים נרחבים כמו שאתה רואה את התמונות. Eens dit gebeurd can we wegaangaan to the following stap.

שלב 8: פלטות שנעשו ב- De Behuizing

פלטות שנעשו ב- De Behuizing
פלטות שנעשו ב- De Behuizing
פלטות שנעשו ב- De Behuizing
פלטות שנעשו ב- De Behuizing
פלטות שנעשו ב- De Behuizing
פלטות שנעשו ב- De Behuizing

מכיוון ש- Guitar Hero-model redelike krap was on me to work have we extra place should make d.m.v. dremelen. אז אנחנו יכולים להוציא את האחורי של הגטאר אחד שלם להסיר כך שניתן יהיה יותר מקום להקים את המדינה עבור הדירה בגיטרה. מכיוון שאנו מכילים מספר רב של מקורות לאבטוחים, שכן אנו יכולים גם להסיר את האופטימלי של המקום שניתן להשתמש בו. Op de vierde en fivede photo is to see that we in the achterkant of de gitaar one doorgang have gecreëerd for de draden die to the buttons going because de gitaar anders niet more te sluiten was. En on the last photo is to see that we the draden the recht straight verbonden be met the Arduino door one gat in the onderkant van de gitaar de behuizing verlaten.

שלב 9: דירוג Aansluiten Op Protobord

Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord
Bedrading Aansluiten Op Protobord

כל המרכיבים עם שנינו יכולים להתחבר עם protobord. זה הוא בורד זה באופן עצמאי על אותו אופן עובד כמו לוח לחם, אבל אז זה יכול להיות יעיל. אנו יכולים לשדרג את הלוח על שולחן העבודה כמו שאתה רואה הוא על התמונה השלישית. זה לוח הוא מרכז הליבה של כל הקשרים שלנו ורואים יחד (ראה תמונה 2).

שלב 10: Verstevigen

ורסטביגן
ורסטביגן

כל סיום הטאץ 'הוא הוודא כי הוא יכול להבטיח את היכולת להבטיח יציבות נוספת. על התמונה הזאת אפשר לראות איך אנחנו משתתפים בכך שהצלחנו להבחין d.m.v. dremelen achteraan de buttons verstevigen with pieces karton.

שלב 11: Code Voor Het Communiceren Met Reaper

Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper
Code Voor Het Communiceren Met Reaper

קוד זה מופיע בשני חלקים, והראשון הראשון נמצא ב- IDE (סביבת פיתוח אינטראקטיבית) שנכתבה. קוד זה יעלה לגרסה עצמאית וצריך לקבל את כל התעריפים של חיישנים ומבקר המידי כדי לאפשר לעיבוד.

העיבוד הוא החלק השני. קוד זה צריך לכל מה שאתה צריך לקבל בדלת הבית כדי להגיע אל Reaper.

ארדואינו

/* קוד זה הוא סקיצה בסיסית לתקשורת עם עיבוד באמצעות סדרה.

זהו שרטוט שבו תוכל להכניס קוד משלך

צוין לכפתורים, פוטנציומטרים או חיישנים משלך.

יש לו לחיצת יד כדי לוודא שיש לנו קשר

והפורמט בו אנו מתקשרים נקבע

חשוב לבנות את המסר באותה צורה, כך שעיבוד ידע כיצד לפרק אותו ולשלוח הודעות OSC נכונות ל- DAW שלנו

מיוצר עבור werkcollege AV&IT

אוקטובר 2017

*

/ קצב שידור

const long baudRate = 115200;

// זמן לחכות ב- ms בין הסקרים לפינים

const int loopPauseTime = 200; // מילי שניות

// ערכי התחלה וסיום עבור ההודעה שנשלחה ב- Serial

const String startString = "*", endString = "#";

const char contactCharacter = '|';

// מזהי סיכה

// משתנים גלובליים אחרים

const int aantalKnoppen = 5; const String namenKnoppen [מספרKnoppen] = {"כפתור 1", "כפתור 2", "כפתור 3", "כפתור 4", "כפתור 5"}; const int knopPinnen [מספרKnoppen] = {2, 3, 4, 5, 6}; const int mainButton = A1;

int mainButtonState = 0;

int potValue = 0;

// חיישנים אנלוגיים

const int potPin = A5; // pin voor tremolo

// אנו זקוקים לפונקציה זו כדי ליצור קשר עם סקיצת העיבוד

// שמור אותו כאן void etablContact () {while (Serial.available () <= 0) {Serial.print (contactCharacter); // שלח צ'ארה והמתן לתגובה … עיכוב (loopPauseTime); } Serial.read (); }

הגדרת בטל () {

// הגדר את pinModes לכל הסיכות עבור (int i = 0; i <מספרKnoppen; i ++) {pinMode (knopPinnen , INPUT); } pinMode (mainButton, INPUT); // לא להגיב אם אתה משתמש בחיישנים שעובדים על 3V במקום 5V // תצטרך לחבר את הסיכה 'ext' גם ל -3.3V // analogReference (EXTERNAL);

// לאתחל הודעות סדרתיות

Serial.begin (baudRate); בעוד (! סדרתי); // המתן ללחיצת יד etablContact (); }

לולאת חלל () {

// STEP 1: READ BUTTONS // סקר את כל הסיכות ומפה את הקריאה לכפתור int range המתאיםStates [מספרKnoppen]; /* buttonStates [0] = digitalRead (knopPinnen [0]); buttonStates [1] = digitalRead (knopPinnen [1]); buttonStates [2] = digitalRead (knopPinnen [2]); buttonStates [3] = digitalRead (knopPinnen [3]); buttonStates [4] = digitalRead (knopPinnen [4]); */ mainButtonState = digitalRead (mainButton); for (int i = 0; i <מספרKnoppen; i ++) {buttonStates = digitalRead (knopPinnen ); } potValue = analogRead (potPin); // דוגמאות: // float v0 = מפה (bpm, 0, 1023, 60, 250); // אם אתה רוצה להשתמש בציפה מנורמלת (למשל עבור נפח) // float v1 = map (analogRead (pin2), fromMin, fromMax, 0, 100) / 100.0;

// שלב 2: כתוב הודעה

Serial.print (startString); // התחל רצף הודעות עבור (int i = 0; i <מספרKnoppen; i ++) {if (mainButtonState == HIGH) {Serial.print (namenKnoppen ); Serial.print (","); Serial.print (buttonStates ); if (i <aantalKnoppen - 1) {Serial.print (","); }} else {buttonStates = 0; Serial.print (namenKnoppen ); Serial.print (","); Serial.print (buttonStates ); if (i <aantalKnoppen - 1) {Serial.print (","); }}} Serial.print (","); Serial.print ("טרמולו"); Serial.print (","); Serial.print (מפה (potValue, 0, 1023, 0, 100)); // כתוב את סוף ההודעה Serial.print (endString);

// חכה רגע..

עיכוב (loopPauseTime); }

מעבד

כתב ויתור: לא כל הקוד של עיבוד הסקיצה יכול להיות כאן בקובץ המלא, ראה את הקובץ: ProcessingSoundControl_handout_v6_1.pde ב bijlage

ההוראות הבאות צריכות להתקבל (אם צריך):

// Baudrate צריך אותו דבר כמו במערכון דה ארדואינו

end int baudRate = 115200;

// חפש את כתובת ה- IP בקושי (ראה צילומי מסך בביגלג ')

// עיבוד שליחויות לאתר זה ואחר קריאה מאזינים כאן //

// מחרוזת סופית remoteIP = "192.168.1.43"; //לְמָשָׁל. "127.0.0.1";

מחרוזת סופית remoteIP = "10.3.209.60";

// שימו לב ל- sendPort ומלאו זאת ב- Reaper.

// זהו היציאה שאליו העיבוד שולח ו Reaper מקשיב.

int int listenPort = 12000, sendPort = 12000;

// ה- listenPort כאן נועד לאיתור באגים באופן פעיל.

// שמות הנמל נמצאים כאן כדי לאתר באגים גם כן.

// final String portName = "/dev/ttyACM0";

final String portName = "COM5"; // "/dev/ttyUSB0";

/////////////////////// סוף של פרמטרים של משתמשים ////////////// ////

ייבוא עיבוד. סדרה.*;

יבוא java.util.*;

יבוא oscP5.*;

יבוא netP5.*;

OscP5 oscP5;

NetAddress myRemoteLocation;

CommsPort סידורי; // היציאה הטורית

message booleanArrived = false;

מחרוזת נכנסת = "", IncomingOSCMessage = "";

char char final startChar = '*', endChar = '#'; הסופי char contactCharacter = '|';

// כדי לוודא שאנחנו שולחים רק את הפרמטרים (הערכים) שמשתנים

// משתנים גלובליים אלה מסומנים כאן, אך אין // לאתחל אותם כאן! HashMap oldParams, newParams, toSendParams;

// עלינו לפצל את המסר בכל פסיק

void processIncoming () {String resVec = incoming.split (","); // נקבל זוגות שם+ערך // כך שלכל שם (+2) … נסה {for (int i = 0; i <resVec.length; i+= 2) {float value = Float.parseFloat (resVec [i+ 1]); // הכנס אותם ל- newParams.put החדש של Hashtable (resVec , ערך); }} // אם מתרחשת שגיאה, בואו נתפוס אותה יוצאת ונצא. catch (Exception ex) {println ("הודעת חריגה:" + ex); printArray (resVec); יְצִיאָה(); }}

// כדי לסנן את ההודעות שלנו

/ * אנו מוודאים שיש רק הודעת OSC-out כאשר * הודעת הקלט (סדרתית) משתנה * כלומר: אם אנו סובבים/לוחצים על הכפתור והיא משנה ערך. * אז אנו מסננים את הערכים הנכנסים שלמעשה משתנים * שימו לב: לא נמנע מקפיצות מערכים * כפי שמקורם למשל במד תאוצה או בחיישני מרחק * תצטרכו להחליק אותם בעצמכם ב- Arduino */ void filterParams () {toSendParams = new מפת גיבוב(); עבור (מפתח מחרוזת: newParams.keySet ()) {// אם המפתח כבר קיים אם (oldParams.containsKey (מפתח)) {הנוכחי של המפתח והערך אינם זהים, עדכן אם (! oldParams.get (מפתח).equals (newParams.get (מפתח))) {toSendParams.put (מפתח, newParams.get (מפתח)); }} else {// מפתח אינו קיים במערכות ישנות, אז נגיד! toSendParams.put (key, newParams.get (key)); } oldParams.put (מפתח, newParams.get (מפתח)); }}

voide makeOSC () {

עבור (מפתח מחרוזת: toSendParams.keySet ()) {OscMessage myMessage = חדש OscMessage ("/"+ מפתח); myMessage.add (toSendParams.get (מפתח)); / * שלח את ההודעה */ oscP5.send (myMessage, myRemoteLocation); }}

void translateMessage () {

processIncoming (); filterParams (); makeOSC (); } // כאשר נרצה להדפיס לחלון חלל של ShowIncoming () {// כדי לראות הודעה נכנסת, כפי שהוגדר בטקסט HashMap ("נכנס מארדואינו", 20, 20); int y = 20; עבור (מפתח מחרוזת: newParams.keySet ()) {y = y+20; טקסט (מפתח, 20, y); טקסט (newParams.get (מפתח), 300, y); }}

void showOsc () {

טקסט (IncomingOSCMessage, 300, 200); IncomingOSCMessage = ""; }

הגדרת בטל () {

גודל (1000, 800); // מילוי גודל הבמה (255); רקע (0); oldParams = HashMap חדש (); newParams = HashMap חדש (); // printArray (Serial.list ()); commsPort = new Serial (this, portName, baudRate);

/ * התחל oscP5, האזן להודעות נכנסות */

oscP5 = OscP5 חדש (זה, listenPort);

/* myRemoteLocation הוא NetAddress. ל- NetAddress יש שני פרמטרים, * כתובת ip ומספר יציאה.myRemoteLocation משמש כפרמטר ב- * oscP5.send () בעת שליחת מנות osc למחשב, התקן, * יישום אחר. שימוש ראה להלן. למטרות בדיקה יציאת ההאזנה * והיציאה של כתובת המיקום המרוחק זהה, ומכאן שתשלח * הודעות בחזרה למערכון זה. */ myRemoteLocation = NetAddress חדש (remoteIP, sendPort); }

צייר חלל () {

if (messageArrived) {רקע (0); translateMessage (); ShowIncoming (); messageArrived = false; } showOsc (); }

void serialEvent (Serial commsPort) {

// קרא בתים מהיציאה הטורית: char inChar = commsPort.readChar (); switch (inChar) {case contactCharacter: commsPort.write (contactCharacter); // לבקש עוד println ("מתחיל …"); לשבור; case startChar: incoming = ""; לשבור; case endChar: messageArrived = true; // println ("סוף הודעה"); לשבור; ברירת מחדל: נכנסת += inChar; לשבור; }}

/* הודעת osc נכנסת מועברת לשיטת oscEvent. */

void oscEvent (OscMessage theOscMessage) {float value = theOscMessage.get (0).floatValue (); // קבל את טיעון האוסק הראשון

IncomingOSCMessage += "\ n" +

String.format ("### קיבל הודעת osc:" + "addrpattern:" + theOscMessage.addrPattern () + ": %f", value); println (IncomingOSCMessage); }

שלב 12: בקר Uittesten

עכשיו הכל הוא אנגלסוט, כל הקוד הוא כתוב והכל הוא gedubbelcheckt הוא יש סוף זמן על הבקר כדי לעבוד לאט לעשות. מצא כמה הזדמנויות על Reaper וליהנות מבקר MIDI גיבור הגיטרה!

מוּמלָץ: