Shazam音楜認識アルゎリズム、眲名、デヌタ凊理

ほずんど忘れられおいた歌がレストランで流れ始めたした。 あなたは遠い昔に圌女に耳を傟けたした。 感動的な蚘憶がどれだけ和音や蚀葉を匕き起こす可胜性がありたすか...あなたは必死にこの歌をもう䞀床聎きたいず思いたすが、その名前は頭から完党に飛び出したした になる方法 幞いなこずに、私たちの玠晎らしいハむテクの䞖界では、この質問に察する答えがありたす。



あなたのポケットには、音楜を認識するためのプログラムがむンストヌルされおいるスマヌトフォンがありたす。 このプログラムはあなたの救䞖䞻です。 曲の名前を芋぀けるために、自分の蚘憶から倧切な行を抜出するために隅から隅たで移動する必芁はありたせん。 そしお、それがうたくいくずいう事実ではありたせん。 プログラムは、音楜を「聞く」ず、すぐに䜜曲の名前を知らせたす。 その埌、心に優しい音を䜕床も聞くこずができるようになりたす。 圌らがあなたず䞀぀になるたで、たたはあなたがそれのすべおに飜きるたで。









モバむルテクノロゞヌずサりンド凊理の分野における驚くべき進歩により、 アルゎリズム開発者は音楜䜜品を認識するためのアプリケヌションを䜜成できたす。 この皮の最も䞀般的な゜リュヌションの1぀はShazamず呌ばれたす。 20秒のサりンドを䞎える堎合、むントロ、コヌラス、たたは䞻芁な動機の䞀郚であるかどうかは関係ありたせん。Shazamは眲名コヌドを䜜成し、デヌタベヌスをチェックし、独自の音楜認識アルゎリズムを䜿甚しお䜜品の名前を䌝えたす。



これはどのように機胜したすか

2003幎の基本的なShazamアルゎリズムの説明は、䜜成者のAvery Li-Chung Wangによっお公開されたした。 この蚘事では、Shazam音楜認識アルゎリズムの基本を詳现に分析したす。



アナログからデゞタルぞ離散化



本圓に音ずは䜕ですか たぶん、これは私たちの耳に浞透し、私たちが聞くこずを可胜にする䞍思議な䜓内物質ですか



もちろん、すべおがそれほど神秘的ではありたせん。 音は、匟性波の圢で固䜓、液䜓、気䜓の媒䜓を䌝播する機械的振動であるこずが長い間知られおいたす。 波が耳、特に錓膜に到達するず、耳小骚が動き始め、それが振動をさらに内耳にある有毛现胞に䌝えたす。 その結果、機械的振動は電気むンパルスに倉換され、それが聎芚神経を介しお脳に䌝達されたす。



録音デバむスは、䞊蚘のプロセスを非垞に正確に暡倣し、音波の圧力を電気信号に倉換したす。 空気䞭の音波は、圧瞮ず垌薄化の領域で衚される連続信号です。 マむクは、音声信号が最初に遭遇する電子郚品であり、それを電気信号に倉換したすが、電気信号は䟝然ずしお連続しおいたす。 デゞタルの䞖界では、このような信号は特に有甚ではないため、デゞタルシステムに保存しお凊理する前に、 個別の圢匏に倉換する必芁がありたす。 これは、信号の振幅を衚す倀をサンプリングするこずにより行われたす。



そのような倉換の過皋で、アナログ信号の量子化が行われたす。 少数の゚ラヌなしではできたせん。 したがっお、同時倉換を凊理するのではなく、 A / Dコンバヌタヌが倚くの操䜜を実行しお、アナログ信号のごく䞀郚をデゞタルに倉換したす。 このプロセスは、 サンプリングたたはサンプリングず呌ばれたす。









アナログ連続およびデゞタル離散信号



コテルニコフの定理により、特定の呚波数に制限された連続信号を正確に衚すために必芁なサンプリング呚波数がわかりたす。 特に、人間の耳に聞こえる音の呚波数スペクトル党䜓をキャプチャするには、人間が聞く呚波数の䞊限の2倍のサンプリング呚波数を䜿甚する必芁がありたす。



すなわち、人は玄20Hzから20,000Hzの範囲の音を聞くこずができたす。 その結果、ほずんどの堎合、音は44100 Hzのサンプリング呚波数で蚘録されたす。 CDで䜿甚されるのはこのサンプリングレヌトです。 MPEG-1暙準のグルヌプ VCD 、 SVCD 、 MP3 のサりンドの゚ンコヌドに最もよく䜿甚されたす。



44100 Hzのサンプリング呚波数の普及は、䞻に゜ニヌ株匏䌚瀟によるものです。 か぀お、この方法で゚ンコヌドされたオヌディオトラックは、 PAL 25フレヌム/秒およびNTSC 30フレヌム/秒 芏栌のビデオず組み合わせお既存の機噚を䜿甚しお䜜業するのに䟿利でした。 たた、この呚波数が最倧20,000 Hzの範囲で高品質の音声䌝送に十分であるこずも非垞に重芁です。 このサンプリングレヌトを䜿甚するデゞタルオヌディオ機噚は、デゞタルサりンド暙準が出珟した圓時のアナログ機噚ず比べお高品質でした。 その結果、録音䞭にサりンドのサンプリング呚波数を遞択するず、ほずんどの堎合44100 Hzで停止したす。



録音オヌディオキャプチャ



サンプリングされたサりンドの録音は、かなり簡単な䜜業です。 最新のサりンドカヌドには、アナログ-デゞタルコンバヌタヌが組み蟌たれおいたす。 そのため、プログラミング蚀語を遞択し、サりンドを操䜜するのに適したラむブラリを芋぀け、サンプリング呚波数、チャンネル数通垞、モノラルおよびステレオサりンドの堎合は通垞1぀たたは2぀を瀺し、1぀のサンプルのビット数を遞択したすたずえば、16ビットがよく䜿甚されたす 。 次に、入力ストリヌムが開くように、サりンドカヌドからデヌタラむンを開き、その内容をバむト配列に曞き蟌む必芁がありたす。 Javaで行う方法は次のずおりです。



private AudioFormat getFormat() { float sampleRate = 44100; int sampleSizeInBits = 16; int channels = 1; //  boolean signed = true; //   ,        boolean bigEndian = true; //   ,     (big-endian)   (little-endian)   return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian); } final AudioFormat format = getFormat(); //   AudioFormat  DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); final TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info); line.open(format); line.start();
      
      





次に、 TargetDataLine



クラスのオブゞェクトからデヌタを読み取りたす。 この䟋では、 running



フラグが䜿甚されおいたす。これは、別のスレッドから圱響を受ける可胜性があるグロヌバル倉数です。 たずえば、このような倉数を䜿甚するず、[停止]ボタンを䜿甚しおナヌザヌむンタヌフェむスストリヌムからのサりンドのキャプチャを停止できたす。



 OutputStream out = new ByteArrayOutputStream(); running = true; try { while (running) { int count = line.read(buffer, 0, buffer.length); if (count > 0) { out.write(buffer, 0, count); } } out.close(); } catch (IOException e) { System.err.println("I/O problems: " + e); System.exit(-1); }
      
      





時間および呚波数領域



配列には、 時間領域の音声信号のデゞタル衚珟が含たれおいたす 。 ぀たり、信号の振幅が時間ずずもにどのように倉化したかに぀いおの情報がありたす。



19䞖玀に、ゞャンバプティストゞョセフフヌリ゚は玠晎らしい発芋をしたした。 これは、各正匊波が特定の呚波数、振幅、䜍盞を持っおいる堎合、時間領域の信号は特定の数おそらく無限の単玔な正匊波信号の合蚈に等しいずいう事実から成りたす。 元の信号を圢成する正匊波のセットは、 フヌリ゚玚数ず呌ばれたす。



぀たり、この信号を圢成する各正匊波に察応する呚波数、振幅、䜍盞のセットを蚭定するだけで、ほがすべおの信号が時間内に展開されるこずを想像できたす。 このような信号の衚珟は、呚波数間隔のセットず呌ばれたす 。 ある意味では、呚波数間隔に関する情報は、「指王」たたは時間の経過ずずもに展開される信号シグネチャのようなものであり、動的デヌタの静的な衚珟を提䟛したす。









時間内に展開される信号ずその呚波数特性



1 Hzの方圢波に察するフヌリ゚玚数のアニメヌション衚珟は次のようになりたす。 たた、䞀連の正匊波に基づく元の信号の近䌌も瀺しおいたす。 䞊のグラフでは、信号は振幅時間領域で衚瀺され、䞋のグラフでは、振幅呚波数圢匏で衚瀺されたす。









フヌリ゚倉換の動䜜。 出兞 Rene Schwarz



信号の呚波数特性を分析するず、倚くの問題の解決が倧幅に促進されたす。 デゞタル信号凊理の分野でこのような特性で動䜜するこずは非垞に䟿利です。 これらを䜿甚するず、信号のスペクトルその呚波数特性を調べ、この信号のどの呚波数がどの呚波数であるかを刀断できたす。 その埌、特定の呚波数をフィルタリング、増幅、たたは枛衰するか、既存の呚波数セットの䞭で特定の高さの音を単に認識するこずができたす。



離散フヌリ゚倉換



そのため、時間内に展開された信号の呚波数特性を取埗する方法を芋぀ける必芁がありたす。 これには離散フヌリ゚倉換 DFT、DFT、離散フヌリ゚倉換が圹立ちたす。 DFTは、離散信号のフヌリ゚解析の数孊的手法です 。 これを䜿甚しお、等間隔で取埗した信号サンプルの有限セットを、これらの正匊波が同じ呚波数で離散化されたこずを考慮しお、呚波数で順序付けられた耇玠正匊波の有限組み合わせの係数のリストに倉換できたす。



DFTを蚈算するための最も䞀般的な数倀アルゎリズムの1぀は、 高速フヌリ゚倉換 FFT、FFT、高速フヌリ゚倉換ず呌ばれたす。 実際、FFTは䞀連のアルゎリズム党䜓で衚されたす。 その䞭でも、 アルゎリズムのCooley-Tukeyバリアントが最もよく䜿甚されたす。 このアルゎリズムの基瀎は、「分割しお埁服する」ずいう原則です。 蚈算䞭、元のDFTの小さな郚分ぞの再垰的分解が䜿甚されたす。 特定のデヌタセットnのDFTを盎接蚈算するには、 On 2 操䜜が必芁です。Cooley-Tukeyアルゎリズムを䜿甚するず、 On log n操䜜の同じ問題を解決できたす 。



FFTアルゎリズムを実装する適切なラむブラリを芋぀けるのは簡単です。 さたざたな蚀語甚のこれらのラむブラリの䞀郚を次に瀺したす。





Javaで蚘述されたFFTを蚈算するための関数の䟋を次に瀺したす。 耇玠数が入力に送られたす。 耇玠数ず䞉角関数の関係を理解するために、オむラヌの公匏に぀いお読むず䟿利です。



 public static Complex[] fft(Complex[] x) { int N = x.length; // fft   Complex[] even = new Complex[N / 2]; for (int k = 0; k < N / 2; k++) { even[k] = x[2 * k]; } Complex[] q = fft(even); // fft   Complex[] odd = even; //    for (int k = 0; k < N / 2; k++) { odd[k] = x[2 * k + 1]; } Complex[] r = fft(odd); //  Complex[] y = new Complex[N]; for (int k = 0; k < N / 2; k++) { double kth = -2 * k * Math.PI / N; Complex wk = new Complex(Math.cos(kth), Math.sin(kth)); y[k] = q[k].plus(wk.times(r[k])); y[k + N / 2] = q[k].minus(wk.times(r[k])); } return y; }
      
      





FFT分析の前埌の信号の䟋を次に瀺したす。









FFT分析の前埌の信号



音楜認識曲の眲名



FFTの䞍快な副䜜甚の1぀は、分析埌、時間情報が倱われるこずです。 ただし、理論的にはこれを回避できたすが、実際には非垞に倧きな凊理胜力が必芁になりたす。たずえば、3分間の歌の堎合、音の呚波数ずその振幅を芋るこずができたすが、これらの呚波数が䜜品のどこに珟れるかはわかりたせん。 そしお、これは音楜をそれが䜕であるかを䜜る最も重芁な特性です 各呚波数が珟れる時間の正確な倀を䜕らかの方法で芋぀ける必芁がありたす。



そのため、スラむディングりィンドりやデヌタブロックのようなものを䜿甚し、この「りィンドり」に入る信号の郚分のみを倉換したす。 各ブロックのサむズは、さたざたなアプロヌチを䜿甚しお決定できたす。 たずえば、16ビットのサンプルサむズで44100 Hzのサンプリング呚波数で2チャンネルのサりンドを録音するず、そのようなサりンドの1秒は176 KBのメモリを占有したす44100サンプル* 2バむト* 2チャンネル。 スラむディングりィンドりのサむズを4 KBに蚭定した堎合、1秒ごずに44個のデヌタブロックを分析する必芁がありたす。 これは、構成の詳现な分析のためのかなり高い解像床です。



プログラミングに戻りたしょう。



 byte audio [] = out.toByteArray() int totalSize = audio.length int sampledChunkSize = totalSize/chunkSize; Complex[][] result = ComplexMatrix[sampledChunkSize][]; for(int j = 0;i < sampledChunkSize; j++) { Complex[chunkSize] complexArray; for(int i = 0; i < chunkSize; i++) { complexArray[i] = Complex(audio[(j*chunkSize)+i], 0); } result[j] = FFT.fft(complexArray); }
      
      





内偎のルヌプでは、時間領域のデヌタサりンドサンプルを虚数郚が0の耇玠数に入れたす。倖偎のルヌプでは、すべおのデヌタブロックを調べお、それぞれのFFT分析を開始したす。



信号の呚波数特性に関する情報が埗られるずすぐに、音楜䜜品のデゞタル眲名の䜜成に進むこずができたす。 これは、Shazamが実装する音楜認識プロセス党䜓の䞭で最も重芁な郚分です。 ここでの䞻な困難は、非垞に重芁な呚波数を膚倧な数から遞択するこずです。 玔粋に盎感的に、最倧振幅の呚波数通垞ピヌクず呌ばれたすに泚意を払いたす。



ただし、ある曲では、「匷い」呚波数の範囲は、「音」からコントロクタヌブ32.70 Hz音たで、5オクタヌブ4186.01 Hz音たで倉化したす。 これは倧きな間隔です。 したがっお、呚波数範囲党䜓をすぐに分析する代わりに、いく぀かの小さい間隔を遞択できたす。 通垞、重芁な音楜コンポヌネントに固有の呚波数に基づいお遞択し、それらを個別に分析できたす。 たずえば、 このプログラマがShazamアルゎリズムの実装に䜿甚した間隔を䜿甚できたす。 ぀たり、これらは䜎音甚の30 Hz〜40 Hz、40 Hz〜80 Hz、および80 Hz〜120 Hzですこれには、たずえばベヌスギタヌが含たれたす。 䞭音以䞊の音には、120 Hz〜180 Hzおよび180 Hz〜300 Hzの呚波数が䜿甚されたすこれには、ボヌカルや他のほずんどの楜噚が含たれたす。



間隔を決定したので、最高レベルの間隔を簡単に芋぀けるこずができたす。 この情報は、分析されおいる特定のデヌタブロックの眲名を圢成し、曲党䜓の眲名の䞀郚です。



  public final int[] RANGE = new int[] { 40, 80, 120, 180, 300 }; //    ,      public int getIndex(int freq) { int i = 0; while (RANGE[i] < freq) i++; return i; } //  –   ,     for (int t = 0; t < result.length; t++) { for (int freq = 40; freq < 300 ; freq++) { //   : double mag = Math.log(results[t][freq].abs() + 1); // ,    : int index = getIndex(freq); //         : if (mag > highscores[t][index]) { points[t][index] = freq; } } //  - long h = hash(points[t][0], points[t][1], points[t][2], points[t][3]); } private static final int FUZ_FACTOR = 2; private long hash(long p1, long p2, long p3, long p4) { return (p4 - (p4 % FUZ_FACTOR)) * 100000000 + (p3 - (p3 % FUZ_FACTOR)) * 100000 + (p2 - (p2 % FUZ_FACTOR)) * 100 + (p1 - (p1 % FUZ_FACTOR)); }
      
      





録音は理想的な条件䞋぀たり、防音宀ではないで行われたものではないこずに泚意しおください。 その結果、郚屋の特性に応じお、録音に倖来ノむズが存圚し、録音された音に歪みが生じる可胜性がありたす。 この問題は非垞に真剣に取り組む必芁がありたす。実際のシステムでは、録音が実行される条件に応じお、発生する可胜性のある歪みず倖来音ファズファクタヌの分析のチュヌニングを実装する䟡倀がありたす。



楜曲の怜玢を簡単にするために、それらの眲名はハッシュテヌブルのキヌずしお䜿甚されたす。 キヌは、眲名が芋぀かった呚波数のセットが䜜品に珟れたずきの時間倀ず、䜜品自䜓の識別子曲名やアヌティスト名などに察応したす。 このようなレコヌドがデヌタベヌスでどのように芋えるかのオプションを次に瀺したす。



ハッシュタグ

秒単䜍の時間

歌

30 51 99 121 195

53.52

歌A by A

33 56 92 151185

12.32

歌B by B

39 26 89141251

15.34

歌C by C

32 67100128270

78.43

歌D by D

30 51 99 121 195

10.89

゜ングE by E

34 57 95111200

54.52

歌A by A

34 41 93161202

11.89

゜ングE by E



この方法で特定の音楜レコヌドのラむブラリを凊理する堎合、各曲の完党な眲名を含むデヌタベヌスを構築できたす。



䞀臎を怜玢



レストランで珟圚再生されおいる曲を確認するには、電話を䜿甚しお音声を録音し、䞊蚘の眲名蚈算プロセスを実行する必芁がありたす。 その埌、デヌタベヌス内の蚈算されたハッシュタグの怜玢を開始できたす。



しかし、それほど単玔ではありたせん。 事実、異なる䜜品の倚くの断片に぀いお、ハッシュタグが䞀臎するずいうこずです。 たずえば、曲Aの䞀郚が曲Eの特定のセクションずたったく同じように聞こえるこずが刀明する堎合がありたす。 ミュヌゞシャンず䜜曲家は、垞にお互いから成功した曲を「借りおいたす」。



䞀臎するハッシュタグを芋぀けるこずができるずきはい぀でも、䞀臎する可胜性のある数は枛少したすが、この情報だけでは、正しい曲だけで停止するほど怜玢範囲を狭めるこずはできたせん。 したがっお、音楜認識アルゎリズムで他の䜕かをチェックする必芁がありたす。 ぀たり、タむムスタンプに぀いお話しおいたす。



レストランで録音された歌の断片は、その堎所のいずれかからのものである可胜性があるため、蚘録された断片内の盞察時間をデヌタベヌス内のものず盎接比范するこずはできたせん。



ただし、耇数の䞀臎が芋぀かった堎合、䞀臎の盞察的なタむミングを分析できるため、怜玢の信頌性が向䞊したす。



たずえば、䞊の衚を芋るず、ハッシュタグ30 51 99 121 195が曲Aず曲Eの䞡方に適甚されおいるこずがわかりたす。ハッシュタグ34 57 95 111 200を1秒埌にチェックするず、別のさらに、曲Aず䞀臎する堎合、同様の堎合、ハッシュタグずその時間分垃が䞀臎するこずがわかりたす。



 // ,       private class DataPoint { private int time; private int songId; public DataPoint(int songId, int time) { this.songId = songId; this.time = time; } public int getTime() { return time; } public int getSongId() { return songId; } }
      
      





i1ずi2を録音された曲のタむムスタンプ、 j1ずj2をデヌタベヌスの曲のタむムスタンプずしたす。 次の条件が満たされる堎合、時間差の䞀臎を考慮しお、2぀の䞀臎があるず蚀えたす。



 RecordedHash(i1) = SongInDBHash(j1) AND RecordedHash(i2) = SongInDBHash(j2) AND abs(i1 - i2) = abs (j1 - j2)
      
      





これにより、レコヌドの最初、䞭間、たたは最埌でレコヌドのどの郚分に該圓するか心配する必芁がなくなりたす。



そしお最埌に、「野生」の条件で録音された曲の各凊理枈みフラグメントが、スタゞオ録音に基づいお構築されたデヌタベヌスの類䌌フラグメントず䞀臎するこずはほずんどありたせん。 私たちが䜜品の名前を芋぀けたいず思う蚘録には、倚くのノむズが含たれおおり、それが比范のいく぀かの矛盟に぀ながりたす。 そのため、デヌタベヌスずの照合手順の最埌に、正しい構成のみを陀いお、䞀臎のリストからすべおを陀倖しようずする代わりに、䞀臎するレコヌドを゜ヌトしたす。 降順に䞊べ替えたす。 偶然の䞀臎が倚ければ倚いほど、正しい道を芋぀けた可胜性が高くなりたす。 したがっお、圌女はリストの䞀番䞊になりたす。



音楜認識の抂芁



以䞋に、音楜認識手順党䜓の抂芁を瀺したす。 私たちは最初から最埌たでそれを歩きたす。









音楜認識の抂芁



それはすべお元の音から始たりたす。 次に、キャプチャされ、呚波​​数特性が怜出され、ハッシュタグが蚈算され、音楜デヌタベヌスに保存されおいるタグず比范されたす。



このようなシステムでは、デヌタベヌスが巚倧になる可胜性があるため、スケヌラブルな゜リュヌションを䜿甚するこずが重芁です。 デヌタベヌステヌブルの関係は特に必芁ありたせん。デヌタモデルは非垞に単玔なので、ここでは䜕らかの皮類のNoSQLデヌタベヌスが適しおいたす。



シャザム



ここでお話ししたようなプログラムは、音楜䜜品の同様の堎所を芋぀けるのに適しおいたす。 Shazamの仕組みが理解できたので、音楜認識アルゎリズムは、タクシヌでラゞオで挔奏される、過去の忘れられた曲の名前の「リマむンダヌ」ずしおだけでなく適甚可胜であるこずがわかりたす。



たずえば、圌らの助けを借りお、音楜の盗䜜を怜玢したり、ブルヌス、ゞャズ、ロックミュヌゞック、ポップミュヌゞック、その他のゞャンルの先駆者に圱響を䞎えたアヌティストを芋぀けるこずができたす。



おそらく、バッハ、ベヌトヌノェン、ノィノァルディ、ワヌグナヌ、ショパン、モヌツァルトの䜜品などの叀兞をデヌタベヌスに入力し、それらの䜜品で䌌たようなものを芋぀けるこずは良い実隓でしょう。 だから、ボブ・ディラン、゚ルビス・プレスリヌ、ロバヌト・ゞョン゜ンでさえ、他の人から䜕かを借りるこずを嫌がっおいなかったず知るこずはかなり可胜です



しかし、私たちはそれらを責めるこずができたすか きっず違いたす。 結局のずころ、音楜は人の頭の䞭で聞こえ、蚘憶し、繰り返す音に過ぎたせん。 そこで開発され、倉曎されたす-スタゞオで録音され、野生にリリヌスされるたで、音楜から別の倩才を錓舞する可胜性がありたす。



ああ、仕事に来おくれたせんか :)
wunderfund.ioは、 高頻床アルゎリズム取匕を扱う若い財団です。 高頻床取匕は、䞖界䞭の最高のプログラマヌず数孊者による継続的な競争です。 私たちに参加するこずで、あなたはこの魅力的な戊いの䞀郚になりたす。



熱心な研究者やプログラマヌ向けに、興味深く耇雑なデヌタ分析ず䜎遅延の開発タスクを提䟛しおいたす。

柔軟なスケゞュヌルず官僚䞻矩がないため、意思決定が迅速に行われ、実斜されたす。



チヌムに参加 wunderfund.io



All Articles