نمایه‌سازی صوتی

تغییرات پروژه از تاریخ 1396/08/29 تا تاریخ 1396/10/07
پیدا کردن یک قطعه آهنگ با شنیدن بخشی از آن، نیاز به نمایه‌سازی مجموعه آهنگ‌ها دارد، درست مثل جستجوی واژه‌ها.

# مقدمه:
گاهی در بین راه  یا  در رستوران , در تاکسی آهنگی را  می شنویم که جذبمان می کند . اما نه می توانیم خواننده ی آن  و نه  متن آن را تشخیص بدهیم.
برای رفع این مشکل application  هایی مانند shazam , google sound search وجود دارد که با پخش موزیک برای آن , مشخصات موزیک مربوطه را پیدا
می کند.

 Shazam Entertainment Ltd: 
 یک شرکت توسعه نرم افزار بریتانیا است که
برنامه ای را ایجاد می کند که می تواند موسیقی، فیلم، تبلیغات و برنامه های
تلویزیونی را براساس نمونه ای کوتاه و با استفاده از میکروفون در دستگاه شناسایی
کند. این نرم افزار برای ویندوز، macOS و گوشی های هوشمند در دسترس است

Google sound search :
 برنامه ای برای دستگاهای اندرویدی است که به صورت widget   قابل استفاده است که پخش موزیک
برای آن , نام و  خواننده ی موزیک مربوطه
را  به کاربر  اعلام می کند.

این application ها علاوه بر تطبیق دادن صدا با آهنگ مربوطه , می بایست  noise را از صدای پخش شده نیز بگیرد .
در این نوع  application ها کار اصلی تبدیل سیگنال پیوسته به گسسته است  که امروزه کارت صدای کامپیوتر ها این کار را انجام می دهند.
# کارهای مرتبط:

در این برنامه ها  کار اصلی تبدیل سیگنال  دیجیتال به آنالوگ است.
فررض کنید سیگنال  زیر به عنوان   ورودی به  برنامه  داده می شود.![](https://boute.s3.amazonaws.com/286-large0.png)
کامپیوتر سیگنال ورودی را در هر مدت زمان مشخص 1 بار که  به آن sample rate گفته می شود از ورودی می خواند و ذخیره  می کند.که به آن sample ' گفته  می شود. 
ب طور مثال اگر sample rate 1 باشد , شکل سیگنال به صورت زیر خواهد شد.
![توضیح تصویر](https://boute.s3.amazonaws.com/286-large.png)
اصولا sample rate می بایست 2 برابر بیشترین فرکانس  صورت باشد (44,100khz)
## Time-Domain and Frequency-Domain:
دامنه ی ما  می تواند زمان یا فرکانس باشد. الگوریتم اجرای این برنامه نیاز به دامنه ی فرکانسی دارد. از این رو باید دامنه را فرکانسی کنیم ![توضیح تصویر](https://boute.s3.amazonaws.com/286-toptal-blog-image-1422943240761.jpg.png)
برای این کار از تبدیل فوریه گسسته  استفاده  می کنیم .
![توضیح تصویر](https://boute.s3.amazonaws.com/286-444.png)
حال هر کدام از  sample هارا دسته  بندی می کنیم. هر چند sample یک data chunck است . 
برنامه  با استفده از این data chunck  ها موزیک را سرچ  می کند.

# آزمایش‌ها

# کارهای آینده

# مراجعاده از این data chunck  ها موزیک را سرچ  می کند.

# آزمایش‌ها:
***اجرای کد تست:***
الگوریتم fingerprinting را با استفاده  از پایتون و دیتابیس mysql پیاده یازی کرده ایم. 

در این برنامه تعدادی  آهنگ به عنوان دیتا ست در فولدر mp3 دارد و با پخش موزیک برای برنامه از طریق میکروفون لپتاپ درصورت تطبیق اهنگ با هر یک از آهنگ های دیتاست برنامه نام آهنگ را به عنوان خروجی چاپ می کند.
From mic with 2 seconds we recognized: {'song_id': 1, 'song_name': 'Brad-Sucks--Total-Breakdown', 'file_sha1': '02A83F248EFDA76A46C8B2AC97798D2CE9BC1FBE', 'confidence': 1, 'offset_seconds': 92.69406, 'offset': 1996}
درصورت پخش نشدن موزیک خروجی زیر را خواهد داد:
Nothing recognized -- did you play the song out loud so your mic could hear it? :)
این برنامه را با ران کردن  فایل example.py  اجرا می کنیم.
در این فایل ۲ تابع اصلی برای هر بار تشخیص آهنگ فراخوانی می شود:
<pre>
djv.fingerprint_directory("mp3", [".mp3",".wma"])
</pre>
که دایرکتوری قرار گرفتن موزیک هارا به آن معرفی می کنیم. همچنین فرمت هایی که در این دایرکتوری به عنوان موزیک شناخته می شوند را نیز وارد می کنیم.
 دیتابیس ما fingerprint های هر یک از این موزیک هارا ذخیره می کند و درصورت وجود fingerprint هر موزیک  دوباره آنرا fingerprint نخواهد کرد.
<pre>
if decoder.unique_hash(filename) in self.songhashes_set:    print "%s already fingerprinted, continuing..." % filename    continue
</pre>
<pre>
secs = 2
song = djv.recognize(MicrophoneRecognizer, seconds=secs)
</pre>
این تابع موزیک را از روی میکروفون می به عنوان ورودی دریافت می کند و اهنگ را تشخیص می دهد  و مشخصات آنرا به عنوان خروجی می دهد.
<pre>
def recognize(self, recognizer, *options, **kwoptions):   
	 r = recognizer(self)  
	   return r.recognize(*options, **kwoptions)
</pre>
ورودی این تابع را MicrophoneRecognizer است به این معنی که از میکروفون ورودی را دریافت میکند نه از دیسک.
<pre>
def recognize(self, seconds=10):  
  self.start_recording()  
    for i in range(0, int(self.samplerate / self.chunksize    * seconds)):     
       self.process_recording()     
         self.stop_recording()    
     return self.recognize_recording()
</pre>

در این تابع به اندازه یself.samplerate / self.chunksize    * seconds  صدا را از ورودی می خواند.
 در تابع recognize_recording تابع find_matches فراخوانی شده است که عمل fingerprint را روی موزیک ها انجام می دهد.و تابع align matches بررسی میکند که  fingerprint با موزیک داده شده برابر است  یا ن.
 در تابع fingerprint از توابع ماژول numpy برای تبدیل فوریه سریع(FFT) استفاده شده است .
پس از تبدیل فوریه الگوریتم باید local maximum  هارا بیابد و انهارا ذخیره کند و با استفاده از تابع زیر  این کارا می کند.

<pre>
local_max = maximum_filter(arr2D, footprint=neighborhood)
</pre>
سپس hash می کند و در دیتابیس ذخیره می کند.
+---------+-----------------------+------+-----+---------+-------+
| Field   | Type                  | Null | Key | Default | Extra |
+---------+-----------------------+------+-----+---------+-------+
| hash    | binary(10)            | NO   | PRI | NULL    |       |
| song_id | mediumint(8) unsigned | NO   | PRI | NULL    |       |
| offset  | int(10) unsigned      | NO   | PRI | NULL    |       |
+---------+-----------------------+------+-----+---------+-------+
***تست برنامه:***
برای تست این برنامه معیار های تغییر ما ثانیه ی پخش شدن آهنگ و افزایش نویز و تغییر تعداد دیتا ست هاست.
برای این کار ابتدا ۵ موزیک را در فولدر دیتاست اضافه کردیم و به مرور موزیک های بیشتری اضافه کردیم و تست را  شروع کردیم.
تغییر ثانیه ی پخش:

| Number Correct | Number of Seconds  |
| ----------------- | -------------- 
| 1                 | 15 / 20        
| 2                 | 17 / 20        
| 3                 | 17 / 20        
| 4                 | 17 / 20        
| 5                 | 19 / 20        
| 6                 | 20 / 20        
تغییر نویز:

| Number Correct |         noise   |
| ----------------- | -------------- 
| 1                 | 20 / 20        
| 2                 | 17 / 20        
| 3                 | 16 / 20        
تغییر تعداد اهنگ های دیتا ست با ۵ ثانیه  :

| Number Correct | Number of Songs   |
| ----------------- | --------------  
| 5                 |   5 / 5         
| 7                 | 7 / 7           
| 10                 | 10 / 10        
| 15                 | 15 / 15        
| 20                 | 19 / 20        

پیوست کد:
https://github.com/mehraveh/audio-finger-printing

# کارهای آینده:
در این برنامه موزیک هایی که در دیتابیس نیستند را به احبار به یمی از موزیک های دیتابیس مپ می کند که درآینده این مشکل حل خواهد شد.
پیوست کد:

# مراجع
http://www.ee.columbia.edu/%7Edpwe/papers/Wang03-shazam.pdf
http://www.cs.cmu.edu/%7Eyke/musicretrieval/
      

# پیوندهای مفید:
https://www.bbc.co.uk/education/guides/zpfdwmn/revision/3
https://www.toptal.com/algorithms/shazam-it-music-processing-fingerprinting-and-recognition
https://en.wikipedia.org/wiki/Time_domain
https://en.wikipedia.org/wiki/Sampling_%28signal_processing%29

      

# پیوندهای مفید
![توضیح تصویر]()
1.  [مفهوم نمایه سازی](http://fa.wikipedia.org/wiki/%D9%86%D9%85%D8%A7%DB%8C%D9%87)

2.  [Audio Fingerprinting with Python and Numpy](http://willdrevo.com/fingerprinting-and-audio-recognition-with-python.html)

3.  [Echoprint](http://echoprint.me/how)

4.  [Pydub(python library)](http://pydub.com/)

5.  [MySQL on Ubuntu](http://www.cs.wcupa.edu/rkline/index/mysql-lin.html)

6.  [Duplicate songs detector via audio fingerprinting](http://www.codeproject.com/Articles/206507/Duplicates-detector-via-audio-fingerprinting)