HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0710
penn音楽データからコードを解析する1未解決


penn

リンク

2009/7/10(Fri) 22:00:57|NO.26322

タイトルのとおりです

VBMP3.dllを利用したメディアプレイヤーを作っていて
現在、ビジュアライザーの製作をしています
で、スペクトラムからコード音を割り出そうと頑張っているのですが、うまくいきません

自分なりに考えた方法は
・ベースの音はコードの根音のはず⇒スペクトラムから低音のみデータを取り出す

なのですが
・ベースの周波数帯が一定じゃない、他の楽器とかぶる
・仮に根音がAとわかっても Am?Am7?Am9? 区別ができない
などの理由で失敗しています

どなたか、方法がわかる方、お願いします
このようなソフトはたくさん出回っているので、無理ではないと思うのですが・・・


実はこのプログラム、1年ほど前にもここの力を借りて考えてみたのですが
どうしても解決できずほったらかしてありました
最近、また頑張ってみようかと挑戦しましたが、うまくいきません



この記事に返信する


New Monkey

リンク

2009/7/11(Sat) 23:52:25|NO.26335

かなり難しいんじゃないでしょうか。

まずVBMP3ではおそらく無理だと思います。
なぜかというと、VBMP3のFFTは256バンド(512点サンプル)なので、44100Hzの音源の場合、周波数分解能が44100/2/256=86.13Hzとなります。
http://www.palm.org/f_pal/f_pal_special/sp011_pyrol_scale.html を見ると分かるように、これでは音階を区別するのに(特に低音部で)全然足りないことになります。

最大4096バンド(8192点サンプル)までのFFTが可能な、bass.dllというFreeの音楽再生ライブラリがあります。
周波数分解能は44100/2/4096=5.38Hzまで向上します。
試しにこれを使って音階を表示するプログラムを作ってみましたが、それでもWaveGeneなどで人工的に作成した和音を判別するのが精一杯で、
いろいろな音が混ざっている実際の音楽のコード判別となるとちょっと無理な感じです。

この先は、さらに周波数分解能を上げる(低音部では5.38Hzでもきつい)か、
音楽理論に基づいてアルゴリズムを工夫する必要があると思います。


#module #defcfunc todouble int p1 temp = 0.0 lpoke temp, 4, (p1 & 0x80000000) | (((p1 & 0x7fffffff) >> 3) + ((p1 & 0x7fffffff) ! 0) * 0x38000000) lpoke temp, 0, p1 << 29 return temp #global // 参考 : http://sprocket.babyblue.jp/html/hsp_koneta3.htm#tofloat #uselib "bass.dll" #func BASS_Init "BASS_Init" sptr, sptr, sptr, sptr, sptr #func BASS_Free "BASS_Free" #func BASS_StreamCreateFile "BASS_StreamCreateFile" sptr, sptr, sptr, sptr, sptr #func BASS_StreamFree "BASS_StreamFree" sptr #func BASS_ChannelPlay "BASS_ChannelPlay" sptr, sptr #func BASS_ChannelStop "BASS_ChannelStop" sptr #func BASS_ChannelGetData "BASS_ChannelGetData" sptr, sptr, sptr #define BASS_DATA_FFT8192 $80000005 // 8192 sample FFT onexit *Exit screen 0, 20 * 39, 480 dim buf, 4096//FFTデータ取得バッファ dim onkai, 39//39の音階の周波数 onkai(0) = 110.0 repeat 39 - 1 onkai(cnt + 1) = onkai(cnt) * 1.05946309436 loop dim index, 39//39の音階がそれぞれFFTバッファの何番目の要素に対応するか i = 0 repeat 4096 if (onkai(i) >= (double(44100) / 2 / 4096 * (double(cnt) - 0.5))) & (onkai(i) < (double(44100) / 2 / 4096 * double(cnt + 1) - 0.5)) { index(i) = cnt i++ if i >= 39 { break } } loop dim kokken, 39//黒鍵テーブル kokken = 0,1,0, 0,1,0,1,0,0,1,0,1,0,1,0, 0,1,0,1,0,0,1,0,1,0,1,0, 0,1,0,1,0,0,1,0,1,0,1,0 dim onmei, 39//音名テーブル onmei = "F#","G","G#", "A","B","H","C","C#","D","D#","E","F","F#","G","G#", "A","B","H","C","C#","D","D#","E","F","F#","G","G#", "A","B","H","C","C#","D","D#","E","F","F#","G","G#" //鍵盤描画 color 0, 0, 0 font "MS UI Gothic", 8 line 20 * 39, ginfo_winy - 150, 0, ginfo_winy - 150 repeat 39 color 0, 0, 0 line 20 * cnt, ginfo_winy, 20 * cnt, ginfo_winy - 150 if kokken(cnt) = 1 { boxf 20 * (cnt + 1), ginfo_winy, 20 * cnt, ginfo_winy - 150} color 128, 128, 128 pos 20 * cnt + 5, ginfo_winy - 30 mes onmei(cnt) pos 20 * cnt + 1, ginfo_winy - 20 mes strf("%3.1f", onkai(cnt)) pos 20 * cnt + 5, ginfo_winy - 10 mes index(cnt) loop //ファイル選択 dialog "wav;*.mp3", 16, "" if stat = 0 { end } fileName = refstr //初期化&再生 BASS_Init -1, 44100, 0, hwnd, 0 BASS_StreamCreateFile 0, varptr(fileName), 0, 0, 0 hStream = stat BASS_ChannelPlay hStream, 1 *Main //FFTデータ取得 BASS_ChannelGetData hStream, varptr(buf), BASS_DATA_FFT8192 redraw 0 color 255, 255, 255 : boxf 0, 0, ginfo_winx, ginfo_winy - 150 - 1 //各音階に対応するFFTバッファの要素の値の大きさをグラフで描画 repeat 39 color 255, 0, 0 val = int(todouble(buf(index(cnt))) /*+ todouble(buf(index(cnt) - 1)) * 0.5 + todouble(buf(index(cnt) + 1)) * 0.5*/ * 500) //多少の周波数のずれは認めたほうがいいかも?(/*〜*/内) boxf 20 * cnt + 5, ginfo_winy - 160, 20 * cnt + 5 + 10, ginfo_winy - 160 - val loop redraw 1 await 1 goto *Main *Exit BASS_ChannelStop hStream BASS_StreamFree hStream BASS_Free end



ONION software Copyright 1997-2023(c) All rights reserved.