3e367060创建于 8月6日历史提交
/*
 * Copyright (c) 2026 Huawei Device Co., Ltd.
 * Licensed under Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with License.
 * You may obtain a copy of License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import Logger from './Logger';

const TAG = 'LrcParser';

export interface LrcLine {
  time: number;
  text: string;
}

export class LrcParser {
  private lrcLines: LrcLine[] = [];

  // [Start parse]
  parse(lrcContent: string): void {
    Logger.info(TAG, 'Start parsing LRC file');
    this.lrcLines = [];
    if (!lrcContent || lrcContent.length === 0) {
      Logger.error(TAG, 'LRC file content is empty');
      return;
    }

    const lines: string[] = lrcContent.split('\n');
    for (const line of lines) {
      const trimmedLine: string = line.trim();
      if (trimmedLine.length === 0) {
        continue;
      }

      const match = trimmedLine.match(/\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)/);
      if (match) {
        const minutes: number = parseInt(match[1]);
        const seconds: number = parseInt(match[2]);
        const milliseconds: number = parseInt(match[3].padEnd(3, '0'));
        const text: string = match[4].trim();
        const time: number = minutes * 60 * 1000 + seconds * 1000 + milliseconds;
        
        this.lrcLines.push({ time, text });
      }
    }

    this.lrcLines.sort((a, b) => a.time - b.time);
    Logger.info(TAG, `LRC file parsing completed, total ${this.lrcLines.length} lines`);
  }
  // [End parse]

  getLrcLines(): LrcLine[] {
    return this.lrcLines;
  }

  getCurrentLineIndex(currentTime: number): number {
    if (this.lrcLines.length === 0) {
      return -1;
    }

    let left: number = 0;
    let right: number = this.lrcLines.length - 1;
    let result: number = -1;

    while (left <= right) {
      const mid = Math.floor((left + right) / 2);
      if (this.lrcLines[mid].time <= currentTime) {
        result = mid;
        left = mid + 1;
      } else {
        right = mid - 1;
      }
    }
    return result;
  }

  getCurrentLine(currentTime: number): LrcLine | null {
    const index: number = this.getCurrentLineIndex(currentTime);
    if (index >= 0 && index < this.lrcLines.length) {
      return this.lrcLines[index];
    }
    return null;
  }

  clear(): void {
    this.lrcLines = [];
    Logger.info(TAG, 'Cleared lyric data');
  }
}