GO पर ऑडियो मान्यता की समस्या को कैसे हल करें

हाल ही में, BI.ZONE ने हाईलाड ++ सम्मेलन में भाग लिया। यह स्पष्ट है कि हम वहां सिर्फ दूसरे लोगों के रुख को घूरने के लिए नहीं पहुंचे, बल्कि कुछ दिलचस्प लेकर आए। कंपनी के विभिन्न विभागों के कर्मचारियों ने सम्मेलन के मेहमानों के लिए कार्य तैयार किए, जिनके समाधान के लिए हमने पुरस्कार दिए। गोलंग का एक कार्य ध्वनि पहचान के लिए समर्पित था। हमने उसके लेखक को उसके बारे में बताने के लिए कहा।

समस्या का बयान


हमारे कार्य में, हमें एक निश्चित संख्या में पटरियों को अनुक्रमित करने की आवश्यकता है और डेटाबेस में मूल रचना को इसके नमूने से खोजना है। इस मामले में, नमूना अच्छी तरह से शोर हो सकता है, खराब माइक्रोफोन पर रिकॉर्ड किया जा सकता है, इसमें एक अलग आवृत्ति हो सकती है। अधिकांश कोड पहले से ही प्रतिभागी के लिए लिखे गए हैं, उसे केवल फिंगरप्रिंट फ़ंक्शन को लागू करने की आवश्यकता है, जो फिंगरप्रिंट को ट्रैक से हटा देता है।

कैसे एक ध्वनि रिकॉर्ड करने के लिए


यह स्पष्ट है कि कोई भी ट्रैक एक यांत्रिक तरंग है जिसमें एक एनालॉग प्रकृति होती है। भौतिकी में तरंगों की दो विशेषताएं हैं: आवृत्ति और आयाम। ध्वनि तरंगों के संबंध में, सादगी के लिए, हम मान सकते हैं कि आयाम मात्रा है और आवृत्ति पिच है, हालांकि वास्तव में उच्च ध्वनि एक ही आयाम में एक व्यक्ति को जोर से लगती हैं।

यही है, भौतिकी के दृष्टिकोण से, प्रत्येक रचना को एक सतत कार्य द्वारा वर्णित किया जाता है, जिसका अर्थ है कि गीत के किसी भी मनमाने ढंग से छोटे टुकड़े में अनंत जानकारी होगी (हालांकि यदि यह किसी प्रकार का पोस्ट-पंक है, तो शायद पटरियों में थोड़ी जानकारी होगी कम)। इस वजह से, एनालॉग सिग्नल को बचाया नहीं जा सकता है, आपको इसके डिजिटलीकरण से निपटना होगा। एनालॉग सिग्नल के डिजिटलीकरण के लिए मुख्य दृष्टिकोण पल्स-कोड मॉड्यूलेशन है, जिसे इस खंड में चर्चा की जाएगी। पीसीएम में तीन चरण होते हैं: विवेक, परिमाणीकरण और कोडिंग। आइए संक्षेप में विश्लेषण करें कि उनमें से प्रत्येक पर क्या होता है।

नमूना


इसलिए, हमारे पास समय बनाम आयाम का एक कार्य है। यदि किसी के पास एक प्रश्न है, जहां आवृत्ति है, तो यह फ़ंक्शन ग्राफ के झुकता के पीछे छिपा हुआ है। वह अभी दिखाई नहीं दे रही है, लेकिन बाद में हम उसे बाहर निकाल देंगे। चूंकि हम एक एनालॉग सिग्नल के बारे में बात कर रहे हैं, फ़ंक्शन निरंतर है और संभावित तर्कों के पूरे सेट पर परिभाषित किया गया है (किसी भी वास्तविक संख्या शून्य से ट्रैक के अंत तक)। यही है, हम किसी भी समय फ़ंक्शन के मूल्य को जानते हैं, और हमारे पास बहुत सारे क्षण हैं। हमें स्पष्ट रूप से इतनी ज़रूरत नहीं है, इसलिए बस कुछ असतत सबसेट लें। ऐसा करने के लिए, हम एक निश्चित छोटे अंतराल पर सिग्नल मूल्य को बचाएंगे। यह पर्याप्त छोटा होना चाहिए ताकि हम कानों द्वारा अंतर न सुनें, लेकिन बहुत बड़ा है कि बहुत अधिक बचत न करें, क्योंकि यह भी अवांछनीय है।

वास्तव में, जब डिजिटलीकरण होता है, तो यह अंतराल नहीं होता है जो सेट होता है, लेकिन आवृत्ति, जिसे "नमूना आवृत्ति" कहा जाता है। कार्यों के आधार पर, पेशेवर ऑडियो उपकरण में फोन में नमूना आवृत्ति 8 kHz से कई हजार kHz तक हो सकती है। रिकॉर्डिंग रिकॉर्डिंग स्टूडियो के बाहर साधारण सुनने के लिए संगीत आमतौर पर 44.1 kHz या 48 kHz की आवृत्ति पर संग्रहीत किया जाता है।

परिमाणीकरण


विवेक के लिए धन्यवाद, अब हमारे पास एक निरंतर फ़ंक्शन ग्राफ के बजाय बिंदुओं का एक गुच्छा है, लेकिन हम अभी भी इसके साथ काम नहीं कर सकते हैं, हमें ध्वनि को और भी खराब करने की आवश्यकता है। आयाम बनाम समय का प्रारंभिक कार्य सातत्य आयाम की तुलना कंटीनम समय से करता है। समय के साथ, हम इसे समझ गए, और अब हमें आयाम के साथ कुछ के साथ आने की जरूरत है, क्योंकि इसके वर्तमान मूल्य वास्तविक संख्याओं के सेट पर बिखरे हुए हैं, हमारे लिए भी समस्याओं के बिना उन्हें बचाने के लिए बहुत कम हैं। उदाहरण के लिए, उनमें से, निश्चित रूप से, ऐसे तर्कहीन हैं जिन्हें हम किसी भी तरह से गोल किए बिना नहीं बचा सकते हैं।

मात्रा का ठहराव एक प्रक्रिया है जिसके दौरान हम पूर्व-चयनित सेट से मूल्यों के लिए आयामों को गोल करते हैं। बेशक, हम चाहते हैं कि एम्पलीट्यूड की संख्या दो की शक्ति हो। साधारण ऑडियो ट्रैक के लिए, 16-बिट मात्रा का उपयोग किया जाता है, अर्थात, आयामों की संख्या 65 536 (2 से 16%) होगी। व्यावसायिक ध्वनि रिकॉर्डिंग को अधिक सटीकता के साथ किया जा सकता है, लेकिन कान के कुछ लोग 24-बिट से 16-बिट मात्रा का अंतर कर सकते हैं। तो, हम दो की शक्ति लेते हैं, पूर्णांक आयामों का एक गुच्छा लेते हैं और उन्हें परिमाणीकरण स्तर कहते हैं। तब यह कहना संभव होगा कि संकेत 65 536 स्तरों (आधिकारिक ध्वनियों, सही?) पर मात्रा निर्धारित है। प्रत्येक आयाम को एक स्तर पर गोल किया जाता है, जो अंततः आपको 16 बिट्स में इसके मूल्य को संग्रहीत करने की अनुमति देता है, और कान द्वारा ऐसी रिकॉर्डिंग एनालॉग निरंतर ध्वनि से अप्रभेद्य है।

चित्रण के रूप में, आप नीचे दी गई तस्वीर देख सकते हैं, या पायथन में अपनी खुद की तस्वीरें उत्पन्न कर सकते हैं (कोड और भी कम है)। चित्रण के शीर्ष दाएं परिमाणीकरण के पांच स्तरों को दर्शाता है। यही है, ट्रैक में केवल पांच वॉल्यूम स्तर होंगे।

छवि
कुछ उदाहरण

import numpy as np import matplotlib.pyplot as plt import math as m def f(x): return m.sin(x) q = 1/2 #      k = 0 #      1/2  1/4 vf = np.vectorize(f) orig_f = vf(np.arange(0, 4 * m.pi, 0.001)) quanted_f = q * np.round(orig_f/q + k) plt.plot(orig_f) plt.plot(quanted_f) 

कोडिंग


कोडिंग चरण में, हम पिछले चरणों के परिणामों को समझने योग्य रूप में सहेजते हैं। इससे पहले की सभी क्रियाएं आमतौर पर विशेष उपकरणों द्वारा की जाती हैं, लेकिन हम चाहते हैं कि कंप्यूटर पर एक फ़ाइल हो या मेमोरी में एक सरणी जहां आयाम हो। तदनुसार, इस स्तर पर, उपकरणों के संकेतों को संख्याओं की एक सरणी में बदल दिया जाता है, जिसे हम भविष्य में पीसीएम (पल्स कोड मॉड्यूलेशन) कहेंगे। इसके सूचकांक सशर्त समय (नमूनाकरण के बाद अंतराल सूचकांक) हैं, और एम्पलीट्यूड इसमें संग्रहीत किए जाते हैं, जो कि परिमाणीकरण स्तर पर पूर्णांकों तक पहुंचते हैं।

फूरियर रूपांतरण


प्रारंभ में, हमारे पास एक यांत्रिक तरंग और इसे डिजिटाइज़ करने की इच्छा थी, लेकिन अब हमारे पास एक डिजीटल सिग्नल और इसके साथ आवृत्तियों को प्राप्त करने की इच्छा है। फूरियर रूपांतरण का उपयोग करके वांछित प्राप्त किया जा सकता है। बस के मामले में, मैं इस समस्या में इसके लागू मूल्य को फिर से बताऊंगा। फूरियर रूपांतरण आपको किसी भी फ़ंक्शन को लेने और इसे साइन और कॉशन के योग में विघटित करने की अनुमति देता है। हम इसमें रुचि रखते हैं, क्योंकि साइनसोइड और कोसाइन तरंगें कंपन के बारे में हैं, और ध्वनि कंपन के बारे में है। यही है, फूरियर रूपांतरण का उपयोग करते हुए, आप एक जटिल दोलन के घटकों को प्राप्त कर सकते हैं, उनके आयाम और आवृत्ति का पता लगा सकते हैं, बस यह देखकर कि गुणांक साइन और साइन (या कोसाइन) तर्कों के सामने क्या हैं। उदाहरण के लिए, ऐसी लहर है।

छवि
लहर

वास्तव में, हम जानते हैं कि यह फ़ंक्शन 10sin (3x) + sin (x) + 4sin (4x) + 20sin (2x) द्वारा परिभाषित किया गया है, लेकिन यह अब है, और वास्तविक ध्वनि तरंग में ऐसे शब्दों के असंख्य होते हैं, और हम सक्षम होना चाहेंगे इसके साथ काम करो। तो, चलो फूरियर रूपांतरण के माध्यम से फूरियर रूपांतरण के माध्यम से इस फ़ंक्शन को चलाते हैं और आयाम स्पेक्ट्रम को देखते हैं।

छवि
आयाम स्पेक्ट्रम

यह चार साइन जैसा दिखता है। यह देखना आसान है कि ग्राफ साइन के गुणांक और उनके तर्कों से मेल खाता है।

यह स्पष्ट किया जाना चाहिए कि वास्तव में यह फूरियर की शक्ति का प्रदर्शन नहीं था, बल्कि इसके असतत संस्करण, संकेतों के लिए उपयुक्त था जो अपने सभी विवेकों और मात्राओं के साथ पल्स-कोड मॉड्यूलेशन के माध्यम से गया था। यह असतत फूरियर रूपांतरण के लिए एक एल्गोरिथ्म पेश करने के लिए बेहतर होगा, तो चलिए सिर्फ इस तथ्य पर सहमत होते हैं कि डीएफटी नामक एक ऐसी चीज है, साथ ही इसके संशोधन, तेजी से फूरियर रूपांतरण (एफएफटी)। इस मामले में, एफएफटी की लागू भावना निम्नानुसार है: एल्गोरिथ्म इनपुट पर पीसीएम का एक टुकड़ा प्राप्त करता है और एम्पलीट्यूड वाले एक सरणी देता है, और आवृत्ति डिब्बे सूचक हैं। रूपांतरण के असतत होने के बाद से यह केवल आवृत्तियों नहीं, आवृत्ति के डिब्बे की बात है। संक्षेप में, यह उम्मीद करना बहुत अच्छा था कि आप पूरे लेख में संकेत को दोहरा सकते हैं, और फिर समस्याओं और अशुद्धियों के बिना बस आवृत्तियों को प्राप्त कर सकते हैं। वास्तव में, फ्रीक्वेंसी बिन आवृत्तियों का एक पूरा गुच्छा है जिसे FFT एक दूसरे से अलग नहीं कर सकता है।

यह ध्यान देने योग्य है कि पुस्तकों और लेखों से एल्गोरिथ्म को फिर से लिखने पर एफएफटी अक्सर गलत तरीके से लिखे जाते हैं। नीचे एफएफटी के साथ काम करने के लिए एक अधिक सही कोड है, जो कि हम उनके समाधान में प्रतिभागियों से उम्मीद करते हैं।

 import "github.com/mjibson/go-dsp/fft" ... blocksCount := len(pcm) / fftWindowSize for i := 0; i < blocksCount; i++ { complexArray := fft.FFTReal(pcm[i*fftWindowSize : i*fftWindowSize+fftWindowSize]) // use complexArray... } 

आधुनिक तकनीक आपको कुछ ही लाइनों में तेजी से फूरियर रूपांतरण लिखने की अनुमति देती है। एफएफटी का उपयोग आकार fftWindowSize के खंडों के लिए किया जाता है और जटिल संख्याओं की एक सरणी देता है, जिसका उपयोग हम भविष्य में फिंगरप्रिंटिंग के लिए करेंगे।

सामान्य तौर पर, फूरियर रूपांतरण पूरी समस्या में सबसे पतला स्थान है। सबसे पहले, बिन आकार $ \ frac {आवृत्ति \ नमूनाकरण} {आकार \ खिड़की} $ है। तदनुसार, आप खिड़की को बड़ा कर सकते हैं और अधिक आवृत्तियों को प्राप्त कर सकते हैं, जो अच्छा है, लेकिन, निश्चित रूप से, नकारात्मक परिणाम हैं। खिड़की के आकार में वृद्धि इस तथ्य की ओर ले जाती है कि हम बड़े अंतराल पर पीसीएम का विश्लेषण करते हैं और छोटी अवधि की आवाज़ खो देते हैं। विभिन्न परिस्थितियों में, यह बार-बार कार्यक्रम को खराब कर सकता है यदि लघु ध्वनियां रचना का हिस्सा थीं, या यह सिर्फ शोर होने पर सुधार हो सकता है। या शायद कुछ भी प्रभावित नहीं करते हैं। ऐसी कठिन परिस्थिति में, प्रोग्रामर को निर्णायक रूप से कार्य करना चाहिए: कुछ अच्छे नंबर लें, जैसे $ 2 ^ 9 $ या $ 2 ^ {10} $, और उन पेचीदगियों से परेशान न होने की कोशिश करें जहाँ इसकी आवश्यकता नहीं है। समस्या को हल करने के लिए पर्याप्त है, लेकिन एक गंभीर अनुप्रयोग में आपको अभी भी कुछ हेमिंग विंडो का उपयोग करना होगा और बहुत कुछ सोचना होगा।

फिंगरप्रिंटिंग


कार्य यह सीखना है कि कैसे एक हैश है कि एक ट्रैक करने के लिए मैप किया जा सकता है और जो परिवर्तन के लिए असंवेदनशील है, रचना की आवृत्तियों और आयाम हैं। वे बहुत अलग हो सकते हैं: थोड़ा सा शोर, सभी आवृत्तियों की एक पारी, समानांतर में एक और गाना बजाना, और इसी तरह। आपको यह भी विचार करने की आवश्यकता है कि डेटाबेस में एक साथ कई समान ट्रैक हो सकते हैं जिन्हें एक दूसरे से अलग करने की आवश्यकता होती है। या हो सकता है कि सभी ट्रैक अलग-अलग होंगे, और समस्या यह स्थापित करने के लिए नहीं होगी कि कौन अधिक उपयुक्त है, लेकिन यह समझने के लिए कि कोई भी उपयुक्त नहीं है। सामान्य तौर पर, रचनात्मकता के लिए एक निश्चित गुंजाइश है।

आप विभिन्न तरीकों से प्रिंट ले सकते हैं। मान लीजिए कि कई अलग-अलग संकेतकों की सूची के रूप में एक हैश बनाते हैं। उनमें से, उदाहरण के लिए, शून्य-सिग्नल क्रॉसिंग की औसत संख्या, बीपीएम, औसत आवृत्ति मान हो सकते हैं। मैंने Musicbrainz के पिछले संस्करणों में ऐसा किया था, और इस दृष्टिकोण की समस्याएं यहां लिखी गई हैं । और आप अधिक अमूर्त अवधारणाओं पर विचार कर सकते हैं, जैसे कि ताल, ईएम एल्गोरिथ्म ( लेख ) का उपयोग करके ट्रैक का विश्लेषण करना। सामान्य तौर पर, अभिव्यक्ति की पूर्ण स्वतंत्रता। दुर्भाग्य से, प्रस्तावित एल्गोरिदम के अधिकांश, जाहिरा तौर पर, एक सार्वजनिक कार्यान्वयन नहीं है, इसलिए बस उन्हें लेने और तुलना करने से काम नहीं चलेगा।

इस लेख में मुख्यधारा के कार्यान्वयन का वर्णन किया गया है। यह विशेष रूप से अच्छा है कि आप इस एल्गोरिथ्म को कई लाइनों में लागू कर सकते हैं। उदाहरण के लिए, मूल लेख में, आवृत्तियों को 6 अंतराल में विभाजित करने का प्रस्ताव है, प्रत्येक में अधिकतम आयाम खोजें, सभी छह का औसत लें और औसत से अधिक होने वाले डिब्बे को बचाएं, लेकिन कई अन्य कार्यान्वयन संभव हैं।

 var freqBins = [...]int16{40, 80, 120, 180, 300} func getKeyPoints(frame []freq_domain) int { highScores := make([]float64, len(freqBins)) recordPoints := make([]uint, len(freqBins)) for bin := freqBins[0]; bin < freqBins[len(freqBins)-1]; bin++ { magnitude := frame[bin] binIdx := 0 for freqBins[binIdx] < bin { binIdx++ } if magnitude > highScores[binIdx] { highScores[binIdx] = magnitude recordPoints[binIdx] = (uint)(bin) } } return hash(recordPoints) } 

उपरोक्त फ़ंक्शन फिंगरप्रिंटिंग एल्गोरिथ्म को लागू करता है। अंत में, आवृत्तियों की एक सरणी (या बल्कि, डिब्बे) `हैश ()` फ़ंक्शन को पास की जाती है, जो एक संख्या में कई संख्याओं की एक सरणी को चालू करना चाहिए। आप इसे किसी भी उपयुक्त तरीके से कर सकते हैं, आप md5 का उपयोग करके भी प्रयास कर सकते हैं (हालाँकि यह एक बुरा विचार है)।

परीक्षण के बारे में


कई परीक्षण मामले तैयार किए गए थे:

  1. एक ट्रैक के साथ सामान्य दिखावा। मूल और नमूना पूरी तरह से मेल खाते हैं।
  2. दो पटरियों के साथ एक और दिखावा। मूल के नमूने के साथ मेल खाता है।
  3. पटरियों की एक बड़ी संख्या को अनुक्रमित किया जाता है, सभी को वैकल्पिक रूप से खोजा जाता है।
  4. बड़ी संख्या में पटरियों को लोड किया जाता है, उन्हें खोजा जाता है, लेकिन डाउनस्मलिंग के बाद।
  5. ट्रैक्स को डाउनसम्पलिंग के बाद अनुक्रमित किया जाता है, मूल खोजे जाते हैं।
  6. कई समान ट्रैक्स को अनुक्रमित किया, एक समान की तलाश में, लेकिन डेटाबेस में नहीं।
  7. कई पटरियों को अनुक्रमित किया जाता है, उन्हें खोजा जाता है, लेकिन शोर के साथ।


कुछ रोचक लिंक


https://metacpan.org/pod/Audio::Ofa::Util
https://www.researchgate.net/publication/228347102_A_Review_of_Audio_Fingerprinting
http://www.freshmeat.net/projects/songprint
https://link.springer.com/article/10.1007/s11265-005-4152-2
https://github.com/acoustid/chromaprint
https://laplacian.wordpress.com/2009/01/10/how-shazam-works/

Source: https://habr.com/ru/post/hi480092/


All Articles