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

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

۱. مقدمه:

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

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

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

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

۲. کارهای مرتبط:

در این قسمت الگوریتمی که تشخیص موزیک را انجام می شود را به اختصار توضیح می دهیم.
الگوریتم مربوطه audio fingerprinting نام دارد . به این دلیل این الگوریتم به این نام خوانده می شود که از هر موزیک در دیتابیس ابتدا fingerprint خواهد شد. یعنی به صورت برگشت پذیر کدگذاری خواهد شد.

fft

در چنین برنامه هایی همواره دیتابیس هایی از آهنگ ها وجود دارد که آهنگ وارد شده با یکی از این آهنگ های دیتابیس تطبیق داده شود.
وقتی کاربر یا ادمین برنامه آهنگی به دیتابیس اضافه کند دیتابیس ۲ عمل باید روی آهنگ ها انجام دهد:
۱- ساختن constellation map از سیگنال ها.
۲- عمل hashing

ساختن constellation map:

سیگنال صوتی که توسط سیستم دریافت می شود باید توسط نمودار فرکانس-زمان نمایش داده شو برای تبدیل دامنه به فرکانس از تبدیل فوریه استفاده می شود که سیگنال را با دامنه ی فرکانسی نمایش خواهد داد. برای بالا بردن سرعت عملیات از fft که همان تبدیل فوریه سریع است استفاده می شود.
حال سیگنالی که این تغییرات را یافت می بایست نقاط peak نمودار آن(spectrogram) ذخیره شود.
نقاط peak می تواند نقاطی باشد که انرژی سیگنال در ان نقاط بیشتر است.
همچنین می توان نقاطی که دامنه ی فرکانس در آنها بیشتر است نیز می تواند نقاط peak باشد.
نقاط peak به صورت گسسته ذخیره می شوند بدین معنا کمحور زمان نیز گسسته خواهد بود.
این عمل باعث آسان تر شدن ذخیره و جست و جو خواهد بود. همچنین ذخیره کردن نقاط peak و حذف کردن بقیه تقاط باعث کاهش مقدار قابل توجهی از noise خواهد شد.

spectogram+constllation map

عمل hashing
یکی از شرایط این الگوریتم وجود بی نظمی زیاد است. بدین معنا که دیتاها باید اختلاف زیادی باهم داشته باشند. اگر ما نقاط در نمودارقبل را ذخیره کنیم اختلاف بین نقاط کم خواهد بود درنتیجه تشابه فایل ها بیشتر و تشخیص سخت تر خواهد بود.
بدین منظور نقاط موجود در constellation map را hash می کنیم.
برای hash کردن هر ۲ نقطه ی متوالی از constellation map را درنظر میگیریم و به نقطه ی اول Anchor point و به نقطه ی دوم target zone می گوییم . پس برای عمل hash ۲ مولفه ی ذکر شده به علاوه ی اختلاف زمانی بین ۲ نقطه را داریم که این ۳ مولفه را دردیتابیس ذخیره می کنیم.
اگر هر مولفه بفرض ۱۰ بیت فضا بگیرد که در جمع ۳۰ بیت خواهد شد در مقایسه با ذخیرهی صرفا نقاط ۲۰ بیت بیشتر به ازای هر نقطه خواهد گرفت .
اما سرعت سرچ کردن چندین هزار برابر خواهد شد.

hashing paramemters + time

آیدی موزیکی که در دیتابیس ذخیره می شود یک عدد ۶۴ بیتی است که ۳۲ بیت آن برای hash و ۳۲ بیت دیگر آن برای خود id و time offset است.
عملیات سرچ کردن:
پس از این که عمل hashing نیز صورت گرفت سرچ کردن موزیک آغاز می شود.
هنگامی که موزیک سمپل یا همان موزیک ناشناخته به ورودی برنامه داده می شود مانند سایر موزیک های دیتابیس عمل hashing صورت میگیرد .
سپس باید موزیک با موزیک های داخل دیتابیس مقایسه شود. برای این کار در هردنقطه ای که ۲ مولفه اول hash ها باهم برابر بودند به bin هایی دسته بندی خواهند شد که این دسته بندی براساس trackID خواهد بود.
در هر دسته این hash ها با تایم ها مطابقت داده خواهند شد که در صورت مطابقت ب عنوان matching نهایی درنظر گرفته خواهد شد.
هر کدام از این bin ها که تعداد matching بیشتری داشته باشد به عنوان موزیک تشخیص داده شاده انتخاب خواهد شد.

سرعت search
سرعت search در برنامه هایی که دیتابیس انها حدود ۲۰ هزار اهنگ داشته باشد بین ۵ تا ۵۰۰ میلی ثانیه خواهد بود.که این مقدار به پارامترهای مختلفی از جمله کیفیت موزیک بستگی دارد.

۳. آزمایش‌ها:

توضیح تصویر

اجرای کد تست:
الگوریتم 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? :)
همچنین این برنامه قابلیت این را دارد که موزیک از روی فایل لود شود که نام موزیک مورد نظر را در تابع زیر وارد می کنیم:

song = djv.recognize(FileRecognizer, "Josh-Woodward--I-Want-To-Destroy-Something-Beautiful.mp3")
که موزیک تشخیص داده به صورت زیر اعلام می شود: From file we recognized: {'song_id': 2, 'song_name': 'Josh-Woodward--I-Want-To-Destroy-Something-Beautiful', 'file_sha1': 'C6364099D8E0DC297956EC9D8B2AC1B83403D407', 'confidence': 127098, 'offset_seconds': 0.0, 'match_time': 25.191730976104736, 'offset': 0} این برنامه را با ران کردن فایل example.py اجرا می کنیم. در این فایل ۲ تابع اصلی برای هر بار تشخیص آهنگ فراخوانی می شود:
djv.fingerprint_directory("mp3", [".mp3",".wma"])
که دایرکتوری قرار گرفتن موزیک هارا به آن معرفی می کنیم. همچنین فرمت هایی که در این دایرکتوری به عنوان موزیک شناخته می شوند را نیز وارد می کنیم. دیتابیس ما fingerprint های هر یک از این موزیک هارا ذخیره می کند و درصورت وجود fingerprint هر موزیک دوباره آنرا fingerprint نخواهد کرد.
if decoder.unique_hash(filename) in self.songhashes_set:    print "%s already fingerprinted, continuing..." % filename    continue
secs = 2
song = djv.recognize(MicrophoneRecognizer, seconds=secs)
این تابع موزیک را از روی میکروفون می به عنوان ورودی دریافت می کند و اهنگ را تشخیص می دهد و مشخصات آنرا به عنوان خروجی می دهد.
def recognize(self, recognizer, *options, **kwoptions):   
     r = recognizer(self)  
       return r.recognize(*options, **kwoptions)
ورودی این تابع را MicrophoneRecognizer است به این معنی که از میکروفون ورودی را دریافت میکند نه از دیسک.
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()

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

local_max = maximum_filter(arr2D, footprint=neighborhood)

سپس 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 | |
+---------+-----------------------+------+-----+---------+-------+
تست برنامه:
برای تست این برنامه معیار های تغییر ما ثانیه ی پخش شدن آهنگ و افزایش نویز و تغییر تعداد دیتا ست هاست.
برای این کار ابتدا ۵ موزیک را در فولدر دیتاست اضافه کردیم و به مرور موزیک های بیشتری اضافه کردیم و تست را شروع کردیم.
تغییر ثانیه ی پخش:
by microphone:
| Number Correct | Number of Seconds |
| ----------------- | --------------
| 1 | 40 / 50
| 2 | 42 / 50
| 3 | 44 / 50
| 4 | 47 / 50
| 5 | 47 / 50
| 6 | 50 / 50
by file :
موزیکی که لود می شود شامل چند ثانیه از هر موزیک خواهد بود.

Number Correct Number of Seconds
1 48 / 50
2 49 / 50
3 50 / 50
4 50 / 50
5 50 / 50
6 50 / 50

درنتیجه بدیل نویز داشتن صدای میکروفون نسبت به صدای اصلی نتایج درست کمتری خواهد داد.
تغییر نویز:
نویز شامل صداهایی است که از شدت صدای موزیک کمتر باشند.
نویز حتی می تواند موزیک دیگری باشد که در بک گراند موزیک اصلی پخش می شود.
| 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. مفهوم نمایه سازی

  2. Audio Fingerprinting with Python and Numpy

  3. Echoprint

  4. Pydub(python library)

  5. MySQL on Ubuntu

  6. Duplicate songs detector via audio fingerprinting

محمد حسن سوهان آجینی

سلام
بخش مقدمه قابل قبول است. هر چند جا برای توضیح بیشتر وجود داشت.
در بخش کارهای مرتبط رعایت چند مورد باید رعایت شود:
۱- زیرنویس مناسبی برای عکس‌ها تهیه شود. در حال حاضر هیچ توضیح مناسبی برای تصاویر وجود ندارد.
۲- هیچ یک از مراجع مورد استفاده‌ی شما، مرجع قابل استنادی نیستند! در واقع می‌بایست آنها را در بخش پیوندهای مفید می‌آوردید.
۳- طبق مورد ۲، شما از هیچ مرجعی برای نوشتن متن استفاده نکرده‌اید.
۴- موارد ذکرشده در بخش «کارهای مرتبط»، تنها شامل پیش‌پردازش اولیه‌ی سیگنال است. اما هیچ کار مربوط به پیدا کردن اثر انگشتی را ذکر نکردید.

تایید شده

با سلام و عرض خسته نباشید بابت تلاش های انجام گرفته
مرحله پیاده سازی کامل بود و کد اجرا میشد.
اما درمورد نحوه اجرای الگوریتم توضیح کافی داده نشد و پس از اینکه گفته بودید یکی از کار های اولیه تبدیل سیگنال پیوسته به گسسته می باشد، مراحل بعدی انجام این کار را توضیح نداده بودید که چگونه سیستم متوجه یک شباهت در صدا ها میشود.
و یا درمورد پیاده سازی گفته شد از الگوریتم fingerprint استفاده میشود که توضیح کاملی داده نشده بود، اما درمورد پیاده سازی کامل و بدون مشکل بود

محمد حسن سوهان آجینی

سلام
بزرگترین ایراد موجود در این کار، ارایه ندادن جزییات روش مورد استفاده است. خواننده‌ای که با روش fingerprint آشنا نیست، پس از مطاله‌ی این گزارش، هیچ دانشی از الگوریتم را درک نخواهد کرد و چیزی به دانش او اضافه نخواهد شد! با توجه به اینکه در نقد قبلی عرض شد که بخش «کارهای مرتبط» شامل روش پیش پردازش است و توضیحات ناقص هستند، انتظار می‌رفت در این مرحله توضیحات بهتری/بیشتری در مورد الگوریتم fingerprint ارایه می‌دادید.

ضمن اینکه ایرادات نگارشی موجود را برطرف خواهید کرد، ذکر موراد زیر در گزارش نهایی شما لازم هستند:
۱- برای نویزی کردن داده‌ها، از چه نوع نویز و با چه شدتی استفاده کردید؟
۲- تعداد موزیک‌های مورد آزمایش را با یک مرجع مقایسه کنید. این تعداد از موزیک‌ها، بسیار محدود هستند و جواب گرفتن روی آن دشواری خاصی ندارد.
۳- در مورد زمان اجرای کد توضیحاتی بدهید. یکی از چالش‌های این زمینه، اجرای کد در کمترین زمان ممکن است. اگر این مورد جزو چالش‌های مورد نظر شما نیست، این نکته رادر گزارش خود ذکر کنید.

تایید شده

با سلام
بخش مقدمه را می توانستید بیشتر توضیح بدید و انگیزه بیشتری برای خواندن ادامه متن ایجاد کنید
بخش کارهای مرتبط خوب بود . اما باید به مقالات مربوطه ارجاع می دادید
در بخش آزمایش ها به طور کامل کد را پیاده سازی کردید و پایه کار را به درستی و کامل انجام دادید . اما کاش از تصاویر، نمودار ها و جداول گویا و قابل فهم استفاده می کردید. همینطور متن نیز تا حدی به هم ریخته بود .
در بخش مراجع تنها نام کامل مقالات استفاده شده باید ذکر شوند. لینک ها باید به بخش پیوند ها انتقال یابند
در کل کار شما خوب بود . خسته نباشید!

رد شده

الگوریتم به خوبی توضیح داده شده است. همچنین در بخش مقدمه هم به اختصار در مورد کاربرد مسئله توضیح داده شده است.
متن نوشته در جاهای مختلف دچار به‌هم ریختگی شده‌اند و توضیحات بخش پیاده‌سازی کمی سردرگم کننده‌اند.
کد به خوبی اجرا می‌شود و کارکردن با آن ساده است. به علاوه در متن به خوبی بخش‌های مختلف آن توضیح داده شده است که البته بهتر بود داخل کد و در گیت‌هاب توضیح داده می‌شد.
در مجموع پروژه به صورت کامل و به خوبی انجام شده است.

رد شده

سلام
کدی که برای این پروژه زدید بسیار خوب بود همچنین استفاده از مقاله برای کدها هم ارزشمند بود فقط در کل کاش تمیز تر مینوشتید و نکات نگارشی و جدول کشی را بیشتر رعایت میکردید تا ارزش کدی که زدید را کامل نمایان میکرد.
خسته نباشید

رد شده

سلام، توضیحاتتون نحوه‌ی پیاده‌سازیتون خوب بود . کدتون هم خیلی تمیز و قابل فهم بود.
فقط جدول‌هایی که گذاشته بودید رو درست متوجه نشدم و اینکه اگر ارجاع‌هاتون را در متن مشخص می‌کردید بهتر بود.
خسته نباشید

محمد حسن سوهان آجینی

سلام
نقایص فازهای قبلی به خوبی تکمیل شدند. ضمن تشکر از زحماتی که برای انجام این پروژه کشیدید، نکات زیر جای بررسی بیشتری داشتند:
۱- عکس‌ها مناسب نیستند و منظور مناسبی را به مخاطب منتقل نمی‌کنند. مثلا عکسی که برای spectogram+constllation map آورده‌اید صرفا log سیستم است و تصویر spectrogram و constellation نیستند. (ضمنا به املای غلط کلمات نیز توجه کنید!) حداقل از عکس‌های آماده‌ی چارچوبی که روی آن کار می‌کردید استفاده می‌کردید! (https://github.com/worldveil/dejavu/raw/master/plots/spectrogram_peaks.png)
۲- جداول نامرتب هستند. نحوه‌ی نمایش پیوندها مناسب نیستند (مثلا در مرجع اول، به جای لینک، باید نام مقاله و نویسنده‌های آن و غیره را می‌آوردید). همچنین نامرتبی‌هایی در بخش پیوندها وجود دارند.
۳- نوع نویز و شدت نویز همچنان مبهم است! در نوع نویز می‌بایست یکی از انواع شناخته شده‌ی نویز (مثلا نویز رنگی، نویز babble و غیره) و در شدت به میزان سیگنال به نویز بر جسب db اشاره می‌کردید.
۴- با توجه به اینکه در پیاده‌سازی، از کد بیس آماده‌ی deja vu استفاده کرده‌اید، لازم بود تا یکی از چالش‌های نمایه سازی را به عنوان هدف انتخاب می‌کردید و به بررسی پارامترها و الگوریتم‌ها برای بهبود آن می‌پرداختید! متاسفانه در فاز آخر تنها به رفع نقایص فاز اول پرداخته‌اید و ادامه‌ی آزمایش‌ها را رها کرده‌اید.

رد شده

سلام توضیحات می‌توانست کامل تر باشد . میتوانست الگوریتم کامل‌تر شرح داده شود. نمایش نتایج و آزمایشات هم به خوبی انجام ‌نشده بود.