User guide4 min read

NCN Lyric File Format Specification (.lyr) & Mapping Guide

Complete technical guide for NCN format .lyr text files, TIS-620/Windows-874 charset decoding, header line extraction, and character-by-character timing mapping with .cur files.

1. NCN Lyric Specification (.lyr)

The NCN .lyr file format is a line-delimited text specification designed for Thai karaoke playback. The file MUST be decoded using the Windows-874 (TIS-620) character encoding standard to properly render Thai tone marks (ไม้เอก, ไม้โท, ไม้ตรี, ไม้จัตวา) and vowels without character corruption.

Line Structure Definition of .lyr File

  1. 1
    Line 0 (Song Title): Song title string (e.g. 'คู่ชีวิต').
  2. 2
    Line 1 (Artist Name): Artist/Performer name (e.g. 'COCKTAIL').
  3. 3
    Line 2 (Key Signature): Musical key notation (e.g. 'Cm', 'G', 'F#m').
  4. 4
    Line 3 Onwards (Lyric Verses): Sentence lines of the song lyrics. Words and syllables are delimited by spaces. Lines from index 3 onwards contain the actual printable lyric text.

2. End-to-End Mapping Algorithm: How .mid, .lyr, and .cur Connect

A common question in karaoke software development is: How do three separate files (.mid, .lyr, .cur) combine to create synchronized lyric highlighting? Here is the exact step-by-step algorithm executed during song loading:

Character-to-Tick Sequential Integration Workflow

  1. 1
    1. Extract PPQ Resolution: The player parses the MIDI header (MThd) to retrieve ticksPerBeat (e.g. 480 PPQ).
  2. 2
    2. Convert Cursor Array to Real Ticks: Binary entries from .cur are decoded and converted to MIDI ticks via formula: ticks[i] = Math.round((cursor[i] * ticksPerBeat) / 24).
  3. 3
    3. Clean Lyric Lines: Lines 0-2 are extracted for metadata (Title, Artist, Key). Lines 3+ are preserved as actual lyrics.
  4. 4
    4. Iterate & Map Characters 1-to-1: For each lyric verse, append a space (lyr + ' ') and split into individual characters. Walk through each character and assign the next sequential tick from the ticks array (LyricEvent { text: char, tick: ticks[tickIndex++] }).
  5. 5
    5. Real-Time Highlighting: During Web Audio playback, when currentTick >= event.tick, the active character is highlighted on screen instantly.