@@ -516,21 +516,52 @@ export class AbcParser extends BaseParser<SNAbcInput> {
516516 } ) ;
517517
518518 // 创建声部节点(只包含元数据,不包含乐谱内容)
519- const name =
520- metaLine . match ( / n a m e = " ( [ ^ " ] + ) " / ) ?. [ 1 ] || `Voice ${ voiceNumber } ` ;
521- const clefMatch = metaLine . match ( / c l e f = ( [ a - z ] + ) / ) ;
522- const clef : SNVoiceMetaClef =
523- ( clefMatch ?. [ 1 ] as SNVoiceMetaClef ) || 'treble' ;
519+ // 从 V: 定义中解析所有信息
520+ // 注意:metaLine 可能包含前导空格,需要 trim
521+ const trimmedMetaLine = ( metaLine || '' ) . trim ( ) ;
522+
523+ // 解析 name(支持 name="..." 格式)
524+ const nameMatch = trimmedMetaLine . match ( / n a m e \s * = \s * " ( [ ^ " ] + ) " / ) ;
525+ const name = nameMatch ?. [ 1 ] || undefined ;
526+
527+ // 解析 clef(支持 clef=... 格式)
528+ const clefMatch = trimmedMetaLine . match ( / c l e f \s * = \s * ( [ a - z ] + ) / ) ;
529+ const clef : SNVoiceMetaClef | undefined =
530+ ( clefMatch ?. [ 1 ] as SNVoiceMetaClef ) || undefined ;
531+
532+ // 解析 transpose(支持 transpose=... 格式)
533+ const transposeMatch = trimmedMetaLine . match (
534+ / t r a n s p o s e \s * = \s * ( [ + - ] ? \d + ) / ,
535+ ) ;
536+ const transpose = transposeMatch
537+ ? parseInt ( transposeMatch [ 1 ] , 10 )
538+ : undefined ;
539+
540+ // 尝试从 props.voices 中获取声部定义(向上覆盖)
541+ // 如果 props.voices 中有该声部的定义,使用它来覆盖或补充信息
542+ const voiceDefinition = props . voices ?. find (
543+ ( v ) => v . voiceNumber === voiceNumber ,
544+ ) ;
524545
525- const voiceId = `voice-${ voiceNumber } -${ name . toLowerCase ( ) . replace ( / \W + / g, '-' ) } ` ;
546+ // 合并信息:V: 定义优先,props.voices 作为补充
547+ // V: 定义中的值优先,如果 V: 定义中没有,则使用 props.voices 中的值
548+ const finalName =
549+ name || voiceDefinition ?. name || `Voice ${ voiceNumber } ` ;
550+ const finalClef = clef || voiceDefinition ?. clef || 'treble' ;
551+ const finalTranspose = transpose ?? voiceDefinition ?. transpose ;
552+
553+ const voiceId = `voice-${ voiceNumber } -${ finalName . toLowerCase ( ) . replace ( / \W + / g, '-' ) } ` ;
526554 const voice = new SNParserVoice ( {
527555 id : voiceId || this . getNextId ( 'voice' ) ,
528556 originStr : voiceHeader ,
529557 } ) ;
530558
559+ // 设置完整的 meta 信息
531560 voice . setMeta ( {
532- clef,
533- transpose : undefined ,
561+ voiceNumber,
562+ name : finalName ,
563+ clef : finalClef ,
564+ transpose : finalTranspose ,
534565 } ) ;
535566
536567 voiceNodesMap . set ( voiceNumber , voice ) ;
@@ -599,13 +630,20 @@ export class AbcParser extends BaseParser<SNAbcInput> {
599630 currentVoiceId = voiceNumber ;
600631 } else {
601632 // 如果声部不存在,创建默认声部
633+ // 尝试从 props.voices 中获取声部定义(向上覆盖)
634+ const voiceDefinition = props . voices ?. find (
635+ ( v ) => v . voiceNumber === voiceNumber ,
636+ ) ;
637+
602638 const defaultVoice = new SNParserVoice ( {
603639 id : this . getNextId ( 'voice' ) ,
604640 originStr : `V:${ voiceNumber } ` ,
605641 } ) ;
606642 defaultVoice . setMeta ( {
607- clef : 'treble' ,
608- transpose : undefined ,
643+ voiceNumber,
644+ name : voiceDefinition ?. name || `Voice ${ voiceNumber } ` ,
645+ clef : voiceDefinition ?. clef || 'treble' ,
646+ transpose : voiceDefinition ?. transpose ,
609647 } ) ;
610648 voiceNodesMap . set ( voiceNumber , defaultVoice ) ;
611649 currentVoiceId = voiceNumber ;
@@ -625,13 +663,20 @@ export class AbcParser extends BaseParser<SNAbcInput> {
625663 // 如果没有当前声部,创建默认声部
626664 const defaultVoiceNumber = '1' ;
627665 if ( ! voiceNodesMap . has ( defaultVoiceNumber ) ) {
666+ // 尝试从 props.voices 中获取声部定义(向上覆盖)
667+ const voiceDefinition = props . voices ?. find (
668+ ( v ) => v . voiceNumber === defaultVoiceNumber ,
669+ ) ;
670+
628671 const defaultVoice = new SNParserVoice ( {
629672 id : this . getNextId ( 'voice' ) ,
630673 originStr : `V:${ defaultVoiceNumber } ` ,
631674 } ) ;
632675 defaultVoice . setMeta ( {
633- clef : 'treble' ,
634- transpose : undefined ,
676+ voiceNumber : defaultVoiceNumber ,
677+ name : voiceDefinition ?. name || `Voice ${ defaultVoiceNumber } ` ,
678+ clef : voiceDefinition ?. clef || 'treble' ,
679+ transpose : voiceDefinition ?. transpose ,
635680 } ) ;
636681 voiceNodesMap . set ( defaultVoiceNumber , defaultVoice ) ;
637682 }
@@ -975,23 +1020,49 @@ export class AbcParser extends BaseParser<SNAbcInput> {
9751020
9761021 const { metaLine = '' , measuresContent = voiceData . trim ( ) } =
9771022 voiceMatch ?. groups || { } ;
978- const voiceNumber = voiceMatch
979- ? voiceMatch [ 1 ]
980- : Math . floor ( Math . random ( ) * 100 ) . toString ( ) ;
9811023
1024+ // 如果正则匹配失败,尝试从 voiceData 中提取 voiceNumber
1025+ // 这种情况不应该发生,但如果发生了,应该使用默认值而不是随机数
1026+ let voiceNumber = '1' ;
1027+ if ( voiceMatch ) {
1028+ voiceNumber = voiceMatch [ 1 ] ;
1029+ } else {
1030+ // 尝试从 voiceData 中查找 V:数字 格式
1031+ const fallbackMatch = voiceData . match ( / V : \s * ( \d + ) / ) ;
1032+ if ( fallbackMatch ) {
1033+ voiceNumber = fallbackMatch [ 1 ] ;
1034+ } else {
1035+ // 如果完全找不到,使用默认值 "1" 而不是随机数
1036+ voiceNumber = '1' ;
1037+ }
1038+ }
1039+
1040+ // 从 V: 定义中解析所有信息
9821041 const name = (
9831042 metaLine . match ( / n a m e = " ( [ ^ " ] + ) " / ) ?. [ 1 ] || `Voice ${ voiceNumber } `
9841043 ) . trim ( ) ;
9851044 const clefMatch = metaLine . match ( / c l e f = ( [ a - z ] + ) / ) ;
9861045 const clef : SNVoiceMetaClef =
9871046 ( clefMatch ?. [ 1 ] as SNVoiceMetaClef ) || 'treble' ;
1047+ const transposeMatch = metaLine . match ( / t r a n s p o s e = ( [ + - ] ? \d + ) / ) ;
1048+ const transpose = transposeMatch
1049+ ? parseInt ( transposeMatch [ 1 ] , 10 )
1050+ : undefined ;
9881051
9891052 const id = `voice-${ voiceNumber } -${ name . toLowerCase ( ) . replace ( / \W + / g, '-' ) } ` ;
9901053 const voice = new SNParserVoice ( {
9911054 id : id || this . getNextId ( 'voice' ) ,
9921055 originStr : voiceData ,
9931056 } ) ;
9941057
1058+ // 设置完整的 meta 信息
1059+ voice . setMeta ( {
1060+ voiceNumber,
1061+ name,
1062+ clef,
1063+ transpose,
1064+ } ) ;
1065+
9951066 const lyricLines : Array < {
9961067 verse : number ;
9971068 content : string ;
@@ -1083,8 +1154,10 @@ export class AbcParser extends BaseParser<SNAbcInput> {
10831154
10841155 return voice
10851156 . setMeta ( {
1157+ voiceNumber,
1158+ name,
10861159 clef,
1087- transpose : undefined ,
1160+ transpose,
10881161 } )
10891162 . addChildren (
10901163 musicMeasures . map ( ( measureData , i ) => {
0 commit comments