Web Technology > Visual Studio for Designers

頭の中に残る、かすかなメロディー。街で耳にして足を止めた曲。歌詞は曖昧で記憶にない。
その曲のタイトル、どうやって探しますか?

これからの検索サービスに必要な視点

人が検索したい対象には、2種類の情報がある。
1つは、未知の情報である。自分の知らない知識、言葉、概念、イメージ、音。
自分の外部にある、まだ知りえていない情報である。つまり、まだアクセスしたことのない情報である。
もう1つは、既知の情報である。既に知っている知識、言葉、概念、イメージ、音。
自分の脳内にあって、引き出せない情報。つまり、アクセス方法の分からない情報である。

現在の検索サービスは、自分の外部にある情報を探すサポーターだ。
未来の検索サービスは、自分の内部にある情報を探すサポーターも務めてくれるようになる。それは、探しても探しても出てこない内部の記憶を、外部に見つけて引き出すサービスだ。

個人的な記憶も、汎用的な記憶に紐付けられている。たとえば旅行やデートの想い出は、音楽、場所といった、汎用的な記憶と関連付いている。汎用的な情報の検索結果が、それに関連付いた個人的な記憶を引き出すことが往々にしてある。
内部の情報を、簡易に、人の脳に負担をかけずに、且つ迅速に検索するサービスを、XMLベースで実装して提供したベンダが、検索サービスの覇者になるのではないか。
検索速度の短縮だけが、検索エンジンの終着点ではない。末端の個人ユーザからすれば、検索速度はストレスを感じさせない程度に必要だが、もっと、きめ細かなサービスを展開してくれたら、とてもうれしい。

どのベンダも、凄く優秀なプログラマを多数抱えている。記憶力に優れていないと、あのように進化の速い会社では働けないだろう。だが、世の中には、不確かな記憶しか持てない人が大勢いて、そういう人たちの方が圧倒的に多い。記憶が曖昧な人ほど、検索サービスの格好のユーザだ。
さらに、寿命は長くなる。アンチエイジングが発達しても、脳までアンチエイジングできるものなのか。「ひどい、もの忘れ」をイメージしてほしい。「あの、あの、あの言葉なんだっけ?」「あの場所、どこだっけ?」「あの人誰だったっけ?」「あれは、いつ頃のことだったっけ?」「私は何をしていたっけ?」思い出そうとしても思い出せないことが増えていくだろう。
20代、30代の人でも、昭和前半の庶民の暮らしの中にあった情報を知らない人が増えている。最近は、卒業式で歌われる歌も、変わってきているらしい。介護職員が、担当する高齢者の、記憶をたどる支援をすることも困難になっていく。
記憶は、その場に行けば甦るかもしれない。懐かしい人に会えば甦るかもしれない。しかし、最も手っ取り早いのは、音楽ではないだろうか。だが、口ずさんだメロディーから、タイトルを当てること自体が、難しい。

また、街を歩いていて、ふと耳にしたメロディーを気に入り、CDを買いたいと思うことはないだろうか。そのメロディーからタイトルを探し当てるのは、それが流行の曲ではない限り、容易ではない。
音楽情報の検索のイメージ

「あの歌、えーっとなんだっけ、メロディーは覚えているんだけど」音から甦る記憶がある。音楽は、記憶を呼び覚ますのに、格好の媒体だ。
マシンに接続したマイクから、想い出の曲を鼻歌で録音する。
あるいはパソコンのキーボードをmidi楽器に見立てて打つ。
外部音源(キーボード)やギターから入力する。
音程を歌う声から、VoiceXMLに変換する。音程データベースに照合して検索結果を返す。Webアプリケーションにアクセスするのでなくとも、電話で結果を返すことが可能かもしれない。
あるいは、音程とリズムをMML(Music Markup Language)で記録するか、MIDI形式で保存してからMMLに変換する。
音程データは音程差の変換テーブルにより、プラスマイナスの整数値に変換する。これをあらかじめ登録しておいた音程差とリズムのデータベースと照合し、合致すれば、その音楽の作者や歌詞や背景の情報を返す、というものだ。MIDIのデータベースも整備しておき、視聴しての確認が出来れば、なおよい。

上の図の中で、いちばん手っ取り早くできる、パソコンのキーボードから入力するサンプルを作ってみた。
このサンプル、最初は、Webアプリケーションではなく、Excelで入力してXML保存したデータを検索する、ローカルアプリケーションとして作るつもりだった。Visual Studio Tools for Office Systemを使う方法もアリだと考えていた。
なぜなら、5年以上前、PWS+VBScriptで(仕事として)開発した「未来ページ」という簡易企業CMSツールでは、Windowsのディテクティヴ・モードを使って、6割程度の音声入力が可能だった。今では音声合成エンジンも音声入力技術も向上しているはずだから、音程を歌う声から音階を保存して、検索結果を返すローカルアプリケーションは、容易に開発出来るはずなのだ。
アイデアは早く公開したい。なにしろ、思いついてから2年もメモの中に埋もれていたのである。
しかし、ローカルアプリケーションでは、本にでも収録しない限り、目に触れない。本は、この6月にも出るので、収録は出来るのだが、ページ数が既にかなりあふれていて、解説を載せる余地がない。
そこで、Webアプリケーションで公開しようと思った。

個人では、著作権の消滅した曲しかデータベースとして使えないので、サンプルしか作れない。
だが、ケータイへの音楽配信システムが既に構築されているわけだから、打ち込みされた音楽データは無尽蔵にあるはずだ。ベンダなら、音楽データを変換してデータベースを整備することは可能だろう。

あの歌なんだっけ?サンプル

使いかた

ここでは、著作権の消滅している次の曲を、サンプルデータとして用意している。

紅葉、ふるさと、荒城の月、仰げば尊し、大きな古時計、朧月夜、きよしこの夜、さくらさくら、早春賦、七つの子、浜辺の歌、花、蛍の光、我は海の子。
(1) 図のように、キーボードのA~J、Q~I に、音階を示すシールを貼っておく。数字の「3」「4」のキーには、各々、「#」と「♭」のシールを貼る。鍵盤を見なくても演奏ができる人は、貼る必要はない。
パソコンのキーボードからの入力方法
(2) [Caps Lock]で、英数大文字にロックする。
(3) 1個目の入力ボックス内をクリックしてカーソルを置く。
(4) キーボードのシールを目印に、鍵盤楽器を弾く要領で、演奏する(=入力する)。サビの部分や、印象に残っている部分だけでかまわない。何フレーズも弾くと、記憶違いの場合や、間違えて入力した場合に、検索結果が返されないことがある。
#や♭は、キーを押す前に挿入する。例えば、1オクターブ下の「ソ#」は、先に「#」を入力し、「#G」のように弾く(=入力する)。
1個の入力ボックス内のデータ制限は設けていないが、1小節か1フレーズ単位で、次の入力ボックスに移動して入力する方が分かりやすいだろう。入力ボックスは4個用意した。
パソコンのキーボードからの入力方法
たとえば、「荒城の月」の最初のフレーズが印象に残っている場合は、
EEYUIUYRREWE
(ミミラシドシラファファミレミ)と入力する。
あるいは、
GGKW4EWQ4H4HGFG
(ソソドレ4ミレド4ラ4ラソファソ)と入力しても、かまわない。
もちろん、途中の1フレーズだけ、1小節だけを入力してもかまわない。
(5) [検索]ボタンをクリックする。検索結果が返される。
サンプルデータベースにない曲については、入力しても検索結果は返されない(当然だが)。
処理方法

XMLは、GridViewにコードレスで読み込めるよう、データが属性値のみの構造とした。

<?xml version="1.0" encoding="UTF-8"?>
<dataroot update="2006年5月3日">
<song title="紅葉" composer="岡野貞一" score1="EWQWEQGQJQWTEWQWEWQWEQGQJQWTEWQTERTYTETYTEWQWEWTYTEWQGQJQEWQ" />
<song title="ふるさと" composer="岡野貞一" score1="QQQWEWEERTRTYEREWWJQWQWGQWEERERYTRETTTQWERRWQ" />
<song title="荒城の月" composer="滝 廉太郎" score1="EEYUIUYRREWEEEYUIUYRWEEHQQJHRREWERREEEYUIUYRWEEH" score2="GGQW4EWQ4H4HGFGGGQW4EWQ4HFGGAD4D4SA4H4HGFG4H4HGGGQW4EWQ4HFGGA" />
<song />繰り返し
</dataroot>

サンプルなので、非常に単純な処理しか書いていない。
小節ごとに区切った方が入力しやすいので、画面上にTextBoxコントロールを4小節分、4個レイアウトしている。
TextBoxコントロールに入力された値を連結する。
XMLファイルを読み込み、score1もしくはscore2の属性値に、入力された値が含まれるかどうかを調べ、含まれていれば、"title"属性値と、"composer"属性値を返す。
返された値を、GridViewコントロールに表示している。
あとは、[クリア]ボタンがクリックされた時の処理として、TextBoxと変数内に代入されている値をクリアしているだけだ。
なにしろ、Visual Studio 2005では、基本的な処理であれば、コードをほとんど書く必要がない。これだけで済む。

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim sound1 As String = TextBox1.Text
Dim sound2 As String = TextBox2.Text
Dim sound3 As String = TextBox3.Text
Dim sound4 As String = TextBox4.Text
Dim allSound As String = sound1 & sound2 & sound3 & sound4
XmlDataSource1.XPath = "dataroot/song[contains(@score1,'" & allSound & "') or contains(@score2,'" & allSound & "')]"
GridView1.Visible = True
XmlDataSource1.DataBind()
End Sub

音程の差異の変換テーブルにより、DBの属性値を1個に絞る方法

本来は、1オクターブ下で弾いても、1オクターブ上で弾いても、同じ結果を返すべきだろう。
また、「荒城の月」が、
イ短調で、EEYUIUYRREWE(ミミラシドシラファファミレミ)と入力されるか、 ハ短調で、GGKW4EWQ4H4HGFG(ソソドレ4ミレド4ラ4ラソファソ)と入力されるか、 ホ短調で、JJE4RT4RE(シシミ#ファソ#ファミ)と入力されるか、 予測することができない(他にもあるが、おおむね、この3種だろう)。
とりあえず、サンプルではイ短調とハ短調のデータを属性値として、
score1="EEYUIUYRREWEEEYUIUYRWEEHQQJHRREWERREEEYUIUYRWEEH" score2="GGQW4EWQ4H4HGFGGGQW4EWQ4HFGGAD4D4SA4H4HGFG4H4HGGGQW4EWQ4HFGGA" のように記録しているが、ユーザの入力方法を予測してDBを作る方法は、スマートではない。

では、どうすればよいかといえば、
(1)XML文書の内容を、音階ではなく、次の音との差とする。つまり、最初の文字を「0」として、変換テーブルにある数値により、次の数値から前の数値を減算して差を算出し、差の数値をカンマ区切りで列記したデータを記録した、XML文書を作成しておく。たとえば、「荒城の月」であれば、
EEYUIUY(ミミラシドシラ)と弾けば、変換テーブルの数値によれば、4,4,9,11,12,11,9となる。最初の文字を「0」とすれば、その差のデータは、0,0,5,2,1,-1,-2となる。これをXMLデータとして記録する。
この方法であれば、GGKW4EWQ(ソソドレ♭ミレド)と入力しても、数値差異対応表の数値によれば-5,-5,0,2,3,2,0となり、また、JJE4RT4RE(シシミ#ファソ#ファミ)と入力しても、数値差異対応表によれば-1 -1 4 6 7 6 4となり、その差のデータは常に0,0,5,2,1,-1,-2となる。
つまり、XMLファイルには、0,0,5,2,1,-1,-2で始まるデータのみ記録しておけば、score1属性とscore2属性のように、2種類の属性を列記する必要はない。
数値差異対応表を、別個のXMLファイルとして作り、変換テーブルとして扱えば、0,0,5,2,1,-1,-2という、1個の属性値さえ記録されていれば、照合できるようになる。
(2)入力されたデータを、カンマ区切りにする。但し、「3」(=#)が入力された時、および「4」(=♭)が入力された時、つまり文字列内に3または4が見つかったのみ、条件分岐により2桁区切りとする。
(2)カンマで区切られた全ての文字列を、変換テーブルにある数値に置き換える。
(3)最初の文字を「0」として、次の数値から前の数値を減算し、その差を算出して、変数に代入しておく。
(4)変数に代入された値が、XMLファイル内の属性値に含まれている場合は、title属性値と、"composer"属性値を返す。さらに、midiを試聴できるようにする。

以上のような処理を書けば、スマートなサンプルプログラムが出来上がる。
しかし、現在、企画設計の仕事が複数重なり、目が回りそうなほど忙しい。このサンプルとページも連休の数時間をあてて何とか作った。そのような状況なので、先に、サンプルとアイデアだけ載せておく次第。

音程差を数値化する変換テーブル
もどる