Vocaloid

折角のクリスマス、Vocaloidでもあれば気を紛らわすことが出来るのに…

DTMマガジンのアレも期限が切れたし…

という事で、手近なものでVocaloidのようなものを作ってみよう

用意するもの

さて

えっと、見つけたら後は簡単なんですが…

Pythonmidiのnote_onを拾ってMBROLA形式のフォーマットに変換するだけ。

MBROLAはDiphone合成?らしいので(要は音声のつぎはぎ)データは音素+長さ+トーンという風になっている。コレは歌を歌わせろってことだよね?

さぁテキトーに組んでみよう

面倒だ

さて、ここで品質はVocaloidにも遠く及ばないがそれらしいものが出来た。

しかし、Vocaloidみたいなエディタがない。テキストを用意するのがかなり面倒。

いいや、同じフレーズ歌わせて取り敢えずテストだ。(コレが悪夢を生んだ)

できたっ

後悔なんて…
http://inajob.no-ip.org/lab/christ_c.wav

関連研究

本家でも遊んでる(一番下のOthers...のところ)

「おもしろ替え歌」こんなのも昔からあったらしい。

付録

from MidiOutStream import MidiOutStream
from MidiInFile import MidiInFile


class Transposer(MidiOutStream):
    def __init__(self):
        MidiOutStream.__init__(self)
        self.count=0;
        self.now_note=0;
        self.seq=["h","a","ts","u","n","e","m","i","k","u"]
        self.seqindex=0;
        self.target=0;  #target channel
    def note_on(self, channel=0, note=0x40, velocity=0x40):
        if channel == self.target:
            self.count=0;
            self.now_note=note;
            if self.rel_time()!=0:
                # insert rest note
                #print "_ "+str(self.rel_time())
                self.count=self.count+self.rel_time();
            #print channel, note, velocity, self.rel_time() #for debug

    def note_off(self, channel=0, note=0x40, velocity=0x40):
        if channel == self.target:
            self.count=self.count+self.rel_time();
            print self.seq[self.seqindex],self.count/5,0,self.note2freq(self.now_note),95,self.note2freq(self.now_note);
            self.seqPlus();
            print self.seq[self.seqindex],self.count,0,self.note2freq(self.now_note),95,self.note2freq(self.now_note);
            self.seqPlus();
            #print "#off->"
            #print "#",channel, note, velocity, self.rel_time()  #for debug
    def seqPlus(self):
        self.seqindex=(self.seqindex+1)%len(self.seq)
    def note2freq(self,note):
        return 440*2**((note-69)/12.0)
event_handler = Transposer()

in_file = 'hoge.mid'
midi_in = MidiInFile(event_handler, in_file)
midi_in.read()
print "_ 10"

適当なmidiを食わせるとMBROLAのjp1用のphoファイルを吐きます