ตัวอย่างนี้เขียนขึ้นมาด้วยภาษา Groovy ผมใช้เป็นกรณีศึกษาในการศึกษาภาษา Groovy และทดลองอ่านไฟล์ Nick Karaoke หรือ NCN เหมาะสำหรับผู้สนใจจะนำไปศึกษาค้นคว้าต่อไป
 
 
import javax.sound.midi.*

def txt = new File('Lyrics/0/','00001.LYR').readBytes()
def dat = new File('Cursor/0/','00001.CUR').readBytes()
def mid = new File('Song/0/','00001.MID')
def sequence = MidiSystem.getSequence(mid) // get sequence from midi file
def sequencer = MidiSystem.getSequencer() // get midi player from system

def s = new String(txt, 'TIS-620') // read text in thai format
def index = s.indexOf('\r\n\r\n') + 4 // check position that is the 4th line
def ts = s.substring(index) // cut txt head
def maxx = ts.size() <= dat.size() /2 ? ts.size() : dat.size() /2 // use less size
def cur = [:]
def cc = 0
def k // cursor position
for(int i = 0; i+1 < maxx; i++) {
    def b1 = dat[i*2]
    def b2 = dat[i*2+1]
    if(b1 == 0xff || b2 == 0xff) continue
    k = (long) ((b1 + (b2 << 8)) * sequence.resolution / 24 ) // cursor position formular
    while (cur.containsKey(k)) k ++ // select new key because sometimes cursor position is duplicate
    def ch = ts.charAt(cc)
    if (ch == '\r') {
        cc++
        maxx --
    }
    cur[k] = ts.charAt(cc) // map cursorposition and lyric charactor
    cc++
}
for(int i = maxx; i < ts.size(); i++ ) { // incase that is some lyrics has no cursor
    while(cur.containsKey(k)) k++
    if(cc >= ts.size()) break
    def ch = ts.charAt(cc)
    if (ch == '\r') {
        cc++
        maxx --
    }
    cur[k] = ts.charAt(cc)
    cc++
}

sequencer.open()
sequencer.sequence = sequence

def soundbank = null
if(args.size() > 0) {
    print 'Loading Sound Bank ' + args[0] + ' '
    File file = new File(args[0])
    soundbank = MidiSystem.getSoundbank(file) // loda soundfont
    println 'done.'           
}

def receiver
def transmitter = sequencer.transmitter // get transmitter
def synthesizer
if (! (sequencer in Synthesizer)) { // set default synthesizer
    println 'using default synthesizer'
    synthesizer = MidiSystem.synthesizer
    synthesizer.open()
    receiver = synthesizer.receiver
    sequencer.transmitter.receiver = receiver
}else { // use synthesizer from the song
    println 'using song synthesizer'
    synthesizer = sequencer
}
if (soundbank != null) { // set soundfont
    synthesizer.open()
    println "soundbank supported: " + synthesizer.isSoundbankSupported(soundbank)
    print 'loading instruments...'
    synthesizer.loadAllInstruments(soundbank)
    println 'done.'
}

def end = false
sequencer.addMetaEventListener([ // set listener to trick system to end
    meta: { e ->
        if(e.getType() == 47) {
            sequencer.close()
            end = true
        }
    }
] as MetaEventListener)

sequencer.start() // start playing

println 'tick per beat ' + sequence.resolution
println '\033[34m' + s.substring(0, index) // print song header text

def lyr = s.substring(index).split('\n')
def step = sequence.resolution / 8
def ref = 0
def count = 0
def ncount = 1
print '\033[30m' + lyr[0] + '\r' // print song first line
cur.each {
    def current = it.key
    if(current > ref) {
        ref = current
        count = 0
    } else {
        count++
        current = ref + step * count
    }
    // check if sequence is in position
    while(sequencer.tickPosition < current) { // if tick position is in the position waiting
        Thread.sleep(200)
        if(end) break
    }
    def value = it.value
    print '\033[31m' + value // print song text when meet the tick position
    if(value == '\n' && ncount < lyr.size()) {
        print '\033[30m' + lyr[ncount]
        ncount++
    }
}

println '\033[30m'

Comment

Comment:

Tweet