You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测量条件为真的持续时长?音乐家练习APP时间组件实现求助

为音乐家练习APP的光标移动逻辑添加时间维度方案

很高兴能帮你完善这款面向音乐家的练习APP!结合你已经实现的if(payedNote == highlightedNote){ cursor.next(); }核心逻辑,我整理了几个实用的技术方案,都是围绕测量匹配状态的持续时长来实现时间维度的控制,贴合音乐练习的实际需求:

方案一:基础计时跟踪(适合快速落地)

这个方案通过记录匹配状态的开始时间,实时计算持续时长,达到设定阈值后触发光标移动。

实现步骤:

  • 初始化两个状态变量:
    • let currentMatchStartTime = null; // 记录匹配开始的时间戳
    • let isMatching = false; // 标记当前是否处于音符匹配状态
  • 在你的持续检测逻辑中加入时间判断:
    // 假设这是你持续检测演奏音符的循环/回调函数
    function checkNoteMatch(payedNote, highlightedNote) {
      const requiredDuration = getNoteDuration(highlightedNote); // 根据音符时值获取需要保持的时长(比如四分音符=500ms)
      
      if (payedNote === highlightedNote) {
        if (!isMatching) {
          // 首次匹配,开始计时
          currentMatchStartTime = performance.now();
          isMatching = true;
        } else {
          // 计算当前匹配持续时长
          const elapsedTime = performance.now() - currentMatchStartTime;
          if (elapsedTime >= requiredDuration) {
            // 达到要求时长,移动光标
            cursor.next();
            // 重置计时状态,准备下一个音符
            currentMatchStartTime = null;
            isMatching = false;
          }
        }
      } else {
        // 匹配中断,重置状态
        currentMatchStartTime = null;
        isMatching = false;
      }
    }
    
    // 辅助函数:根据音符类型返回对应时长(需结合当前BPM计算)
    function getNoteDuration(note) {
      const bpm = 120; // 示例速度,实际从APP设置中获取
      const quarterNoteMs = 60000 / bpm; // 四分音符的毫秒数
      // 根据音符时值返回对应时长,比如八分音符是quarterNoteMs/2,二分音符是quarterNoteMs*2
      switch(note.duration) {
        case 'quarter': return quarterNoteMs;
        case 'eighth': return quarterNoteMs / 2;
        case 'half': return quarterNoteMs * 2;
        default: return quarterNoteMs;
      }
    }
    

方案二:结合音乐节拍轴的精准控制(专业音乐场景推荐)

音乐的时间是基于节拍和速度的,单纯用绝对计时可能会和实际演奏节奏脱节。这个方案将光标移动和音乐节拍绑定,更符合音乐家的练习习惯。

实现思路:

  1. 提前根据乐谱的BPM和音符时值,生成每个音符的理论演奏时长和节拍位置。
  2. 启动一个和节拍同步的定时器(比如每拍触发一次),在每次节拍触发时检查:
    • 当前演奏的音符是否和高亮音符匹配
    • 匹配状态是否已经持续了至少该音符对应的节拍数(比如四分音符对应1拍,八分音符对应0.5拍)
  3. 当满足条件时,移动光标到下一个音符。

关键优势:

  • 光标移动完全贴合音乐节奏,不会出现“快半拍/慢半拍”的情况
  • 可以和APP内置的节拍器功能联动,让练习更规范

方案三:基于Web Audio API的高精度计时(音频输入场景)

如果你的APP是通过音频捕捉用户演奏的音符(而非MIDI输入),推荐使用Web Audio API的context.currentTime来计时,它的精度远高于系统的Date.now()或performance.now(),能避免音频处理的延迟误差。

核心代码片段:

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
let matchStartAudioTime = null;

function checkAudioNoteMatch(payedNote, highlightedNote) {
  const requiredDuration = getNoteDuration(highlightedNote);
  
  if (payedNote === highlightedNote) {
    if (!matchStartAudioTime) {
      matchStartAudioTime = audioContext.currentTime;
    } else {
      const elapsedTime = (audioContext.currentTime - matchStartAudioTime) * 1000; // 转成毫秒
      if (elapsedTime >= requiredDuration) {
        cursor.next();
        matchStartAudioTime = null;
      }
    }
  } else {
    matchStartAudioTime = null;
  }
}

额外优化建议

  • 容错机制:允许一定的时间误差(比如±100ms),避免用户因为微小的演奏偏差就触发状态重置
  • 和弦处理:如果乐谱包含和弦,需要将匹配条件调整为演奏的音符集合包含高亮的和弦音符集合,再进行时长判断
  • 视觉反馈:在匹配过程中添加进度条或动态高亮效果,让用户直观看到当前音符的演奏时长是否达标

内容的提问来源于stack exchange,提问作者NclsK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:31:45