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

גלאי תו מוזיקלי: 3 שלבים
גלאי תו מוזיקלי: 3 שלבים

וִידֵאוֹ: גלאי תו מוזיקלי: 3 שלבים

וִידֵאוֹ: גלאי תו מוזיקלי: 3 שלבים
וִידֵאוֹ: מוזיקה מרגיעה ומרפאה עם גלי אלפא לשחרור מתח נפשי ופיזי, לרגיעה, שינה עמוקה 🌙 מוזיקה למדיטציה 2024, נוֹבֶמבֶּר
Anonim
Image
Image

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

פרטים

עבור פרויקט זה, הפלט האנלוגי מגלאי מודול הקול נשלח לקלט האנלוגי A0 של ה- Arduino Uno. האות האנלוגי נדגם וכמת (דיגיטציה). קוד מתאם, שקלול וכוונון משמש לאיתור תדר בסיסי באמצעות 3 התקופות הראשונות. לאחר מכן משווים את התדר הבסיסי המשוער לתדרים בטווחי האוקטבות 3, 4 ו -5 כדי לקבוע את תדירות התווים המוזיקליים הקרובים ביותר. לבסוף ההערה הניחשת לתדירות הקרובה ביותר מודפסת למסך.

הערה: הוראה זו מתמקדת רק בבניית הפרויקט. למידע נוסף אודות הפרטים והצדקות העיצוב, אנא בקר בקישור זה: מידע נוסף

אספקה

  • (1) Arduino Uno (או Genuino Uno)
  • (1) חיישן מיקרופון DEVMO תואם מודול זיהוי צליל ברגישות גבוהה
  • (1) לוח לחם ללא הלחמה
  • (1) כבל USB-A ל- B
  • חוטי מגשר
  • מקור מוזיקלי (פסנתר, מקלדת או אפליקציית paino עם רמקולים)
  • (1) מחשב או מחשב נייד

שלב 1: בנה את החומרה לגלאי התווים המוזיקליים

הגדר את גלאי התווים המוזיקליים
הגדר את גלאי התווים המוזיקליים

שימוש ב- Arduino Uno, חוטי חיבור, לוח לחם ללא הלחמה וחיישן מיקרופון DEVMO חיישן מודול זיהוי צליל ברגישות גבוהה (או דומה) יוצרים את המעגל המוצג בתמונה זו

שלב 2: תכנת את גלאי התווים המוזיקליים

ב- IDE של Arduino, הוסף את הקוד הבא.

gistfile1.txt

/*
שם קובץ/סקיצה: MusicalNoteDetector
מספר גירסה: v1.0 נוצר 7 ביוני, 2020
המחבר המקורי: קלייד א. לטסום, PhD, PE, MEM
תיאור: קוד/מערכון זה מציג את התדירות המשוערת כמו גם את התו המוזיקלי המנוגן במקלדת אלקטרונית או באפליקציית פסנתר. עבור פרויקט זה, הפלט האנלוגי מה
גלאי מודול הקול נשלח לכניסה האנלוגית A0 של ה- Arduino Uno. האות האנלוגי נדגם וכמות (דיגיטציה). קוד מתאם, שקלול וכוונון משמש
מצא תדר בסיסי באמצעות 3 התקופות הראשונות. לאחר מכן משווים את התדר היסודי המשוער לתדרים בטווחי האוקטבות 3, 4 ו -5 כדי לקבוע את המחזמר הקרוב ביותר
תדירות הערה. לבסוף ההערה הניחשת לתדירות הקרובה ביותר מודפסת למסך.
רישיון: תוכנית זו הינה תוכנה חינמית; אתה יכול להפיץ אותו מחדש ו/או לשנות אותו בהתאם לתנאי הרישיון הציבורי הכללי של GNU (GPL), גירסה 3, או כל גירסה מאוחרת יותר.
גרסה לבחירתך, כפי שפורסמה על ידי קרן התוכנה החופשית.
הערות: זכויות יוצרים (ג) 2020 מאת C. A. Lettsome Services, LLC
למידע נוסף בקר בכתובת https://clydelettsome.com/blog 2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/
*/
#define SAMPLES 128 // Max 128 עבור Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = מבוסס על Nyquist, חייב להיות פי 2 מהתדירות הגבוהה ביותר הצפויה.
#define OFFSETSAMPLES 40 // משמש למטרות כיוון
#define TUNER -3 // כוונן עד ש- C3 הוא 130.50
float samplingPeriod;
מיקרו שניות ארוכות ללא סימן;
int X [דוגמאות]; // צור וקטור בגודל SAMPLES בכדי להחזיק ערכים אמיתיים
float autoCorr [SAMPLES]; // צור וקטור בגודל SAMPLES בכדי להחזיק ערכים דמיוניים
float storageNoteFreq [12] = {130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94};
int sumOffSet = 0;
int offSet [OFFSETSAMPLES]; // ליצור וקטור אופסט
int avgOffSet; // ליצור וקטור אופסט
int i, k, periodEnd, periodBegin, period, aduster, noteLocation, octaveRange;
float maxValue, minValue;
סכום ארוך;
int thresh = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, סה"כ;
בייט state_machine = 0;
int samplesPerPeriod = 0;
הגדרת חלל ()
{
Serial.begin (115200); // 115200 קצב שידור עבור הצג הסידורי
}
לולאת חלל ()
{
//*****************************************************************
// מדור כיול
//*****************************************************************
Serial.println ("Calabrating. נא לא לשחק כל תווים במהלך הכיול.");
עבור (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // קורא את הערך מהפין האנלוגי 0 (A0), כמת אותו ושמור אותו כמונח אמיתי.
//Serial.println(offSet ); // השתמש בזה כדי להתאים את מודול זיהוי הקול לכמחצית או 512 כאשר לא מושמע צליל.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// התכונן לקבל קלט מ- A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("לספור לאחור.");
עיכוב (1000); // השהה למשך 1 שניות
Serial.println ("3");
עיכוב (1000); // השהה למשך 1 שניות
Serial.println ("2");
עיכוב (1000); // הפסקה למשך 1
Serial.println ("1");
עיכוב (1000); // השהה למשך 1 שניות
Serial.println ("שחק את ההערה שלך!");
עיכוב (250); // הפסקה למשך 1/4 שנייה לזמן תגובה
//*****************************************************************
// אסוף דגימות מדגם A0 עם תקופת הדגימה של הדגימה
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // נקודה במיקרו שניות
עבור (i = 0; i <SAMPLES; i ++)
{
microSeconds = micros (); // מחזירה את מספר המיקרו -שניות מאז שהלוח Arduino החל להריץ את התסריט הנוכחי.
X = analogRead (0); // קורא את הערך מהפין האנלוגי 0 (A0), כמת אותו ושמור אותו כמונח אמיתי.
/ *זמן ההמתנה שנותר בין הדגימות במידת הצורך תוך שניות */
בעוד (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// אל תעשה כלום רק חכה
}
}
//*****************************************************************
// פונקציית מתאם אוטומטי
//*****************************************************************
עבור (i = 0; i <SAMPLES; i ++) // i = עיכוב
{
סכום = 0;
עבור (k = 0; k <SAMPLES - i; k ++) // התאמת אות עם אות מושהה
{
סכום = סכום + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] הוא האות ו- X [k+i] הוא הגרסה המתעכבת
}
autoCorr = סכום / דוגמאות;
// מכונת המדינה לראשונה לאתר שיא
אם (state_machine == 0 && i == 0)
{
דוש = autoCorr * 0.5;
מכונת מצב = 1;
}
אחרת אם (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, מצא תקופה אחת לשימוש במחזור הראשון
{
maxValue = autoCorr ;
}
אחרת אם (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
מכונת מצב = 2;
numOfCycles = 1;
samplesPerPeriod = (periodBegin - 0);
period = samplesPerPeriod;
מתאם = TUNER+(50.04 * exp (-0.102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-מתאם; // f = fs/N
}
אחרת אם (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, מצא 2 תקופות למחזור הראשון והשני
{
maxValue = autoCorr ;
}
אחרת אם (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
מכונת מצב = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-מתאם; // f = (2*fs)/(2*N)
maxValue = 0;
}
אחרת אם (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, מצא 3 תקופות למחזור הראשון, השני וה -3.
{
maxValue = autoCorr ;
}
אחרת אם (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
state_machine = 4;
numOfCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-מתאם; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// ניתוח תוצאות
//*****************************************************************
אם (samplesPerPeriod == 0)
{
Serial.println ("הממ ….. אני לא בטוח. אתה מנסה לרמות אותי?");
}
אַחֵר
{
// להכין את פונקציית הניפוח
סה"כ = 0;
אם (signalFrequency! = 0)
{
סה"כ = 1;
}
אם (signalFrequency2! = 0)
{
סה"כ = סה"כ + 2;
}
אם (signalFrequency3! = 0)
{
סה"כ = סה"כ + 3;
}
// לחשב את התדירות באמצעות פונקציית הניפוח
signalFrequencyGuess = ((1/סה"כ) * signalFrequency) + ((2/סה"כ) * signalFrequency2) + ((3/סה"כ) * signalFrequency3); // מצא תדר משוקלל
Serial.print ("הפתק ששיחקת הוא בערך");
Serial.print (signalFrequencyGuess); // הדפס את ניחוש התדרים.
Serial.println ("הרץ");
// מצא טווח אוקטבה על סמך הניחוש
OctaveRange = 3;
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storageNoteFreq [11] +7))
{
עבור (i = 0; i <12; i ++)
{
storageNoteFreq = 2 * storageNoteFreq ;
}
OctaveRange ++;
}
// מצא את הפתק הקרוב ביותר
minValue = 10000000;
noteLocation = 0;
עבור (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// הדפס את הפתק
Serial.print ("אני חושב ששיחקת");
אם (noteLocation == 0)
{
Serial.print ("C");
}
אחרת אם (noteLocation == 1)
{
Serial.print ("C#");
}
אחרת אם (noteLocation == 2)
{
Serial.print ("D");
}
אחרת אם (noteLocation == 3)
{
Serial.print ("D#");
}
אחרת אם (noteLocation == 4)
{
Serial.print ("E");
}
אחרת אם (noteLocation == 5)
{
Serial.print ("F");
}
אחרת אם (noteLocation == 6)
{
Serial.print ("F#");
}
אחרת אם (noteLocation == 7)
{
Serial.print ("G");
}
אחרת אם (noteLocation == 8)
{
Serial.print ("G#");
}
אחרת אם (noteLocation == 9)
{
Serial.print ("A");
}
אחרת אם (noteLocation == 10)
{
Serial.print ("A#");
}
אחרת אם (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//עצור כאן. לחץ על כפתור האיפוס ב- Arduino כדי להפעיל מחדש
//*****************************************************************
בעוד (1);
}

הצג rawgistfile1.txt המתארח אצל ❤ על ידי GitHub

שלב 3: הגדר את גלאי התווים המוזיקליים

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

מוּמלָץ: