@@ -109,94 +109,82 @@ export class SNParserNode<
109109 }
110110
111111 /**
112- * 向上查找拍号(若未设置则返回 4/4)
112+ * 通用的向上查找属性方法
113113 *
114- * 从当前节点开始向上追溯父节点,查找最近定义的拍号
114+ * 从父节点开始向上追溯,查找最近定义的属性
115115 *
116- * @returns 拍号对象,包含 numerator(分子)和 denominator(分母)
116+ * @param propName - 属性名称
117+ * @param defaultValue - 默认值
118+ * @param validator - 可选的验证函数
119+ * @returns 找到的属性值或默认值
117120 */
118- getTimeSignature ( ) : { numerator : number ; denominator : number } {
119- // 从当前节点开始向上遍历父节点链
121+ protected findInheritedProp < T > (
122+ propName : string ,
123+ defaultValue : T ,
124+ validator ?: ( value : any ) => boolean ,
125+ ) : T {
120126 let current : SNParserNode | undefined = this . parent ;
121127 while ( current ) {
122- const props = current . props as SNMusicProps | SNScoreProps | undefined ;
123- if (
124- props ?. timeSignature &&
125- typeof props . timeSignature . numerator === 'number' &&
126- typeof props . timeSignature . denominator === 'number'
127- ) {
128- return {
129- numerator : props . timeSignature . numerator ,
130- denominator : props . timeSignature . denominator ,
131- } ;
128+ const props = current . props as any ;
129+ const value = props ?. [ propName ] ;
130+
131+ if ( value !== undefined ) {
132+ // 如果提供了验证器,使用验证器检查
133+ if ( validator ? validator ( value ) : true ) {
134+ return value as T ;
135+ }
132136 }
133137 current = current . parent ;
134138 }
135- // 如果找不到,返回默认值 4/4
136- return { numerator : 4 , denominator : 4 } ;
139+ return defaultValue ;
137140 }
138141
139142 /**
140- * 向上查找调号 (若未设置则返回 C 大调 )
143+ * 向上查找拍号 (若未设置则返回 4/4 )
141144 *
142- * 从当前节点开始向上追溯父节点,查找最近定义的调号
145+ * @returns 拍号对象,包含 numerator(分子)和 denominator(分母)
146+ */
147+ getTimeSignature ( ) : { numerator : number ; denominator : number } {
148+ return this . findInheritedProp (
149+ 'timeSignature' ,
150+ { numerator : 4 , denominator : 4 } ,
151+ ( value ) =>
152+ typeof value ?. numerator === 'number' &&
153+ typeof value ?. denominator === 'number' ,
154+ ) ;
155+ }
156+
157+ /**
158+ * 向上查找调号(若未设置则返回 C 大调)
143159 *
144160 * @returns 调号对象,包含 letter(字母)和 symbol(符号)
145161 */
146162 getKeySignature ( ) : { letter : string ; symbol : 'natural' | 'sharp' | 'flat' } {
147- // 从当前节点开始向上遍历父节点链
148- let current : SNParserNode | undefined = this . parent ;
149- while ( current ) {
150- const props = current . props as SNMusicProps | SNScoreProps | undefined ;
151- if ( props ?. keySignature ) {
152- return props . keySignature ;
153- }
154- current = current . parent ;
155- }
156- // 如果找不到,返回默认值 C 大调
157- return { letter : 'C' , symbol : 'natural' } ;
163+ return this . findInheritedProp ( 'keySignature' , {
164+ letter : 'C' ,
165+ symbol : 'natural' ,
166+ } ) ;
158167 }
159168
160169 /**
161170 * 向上查找速度(若未设置则返回 120 BPM)
162171 *
163- * 从当前节点开始向上追溯父节点,查找最近定义的速度
164- *
165172 * @returns 速度对象,包含 value(值)和 unit(单位)
166173 */
167174 getTempo ( ) : { value : number ; unit : 'BPM' } {
168- // 从当前节点开始向上遍历父节点链
169- let current : SNParserNode | undefined = this . parent ;
170- while ( current ) {
171- const props = current . props as SNMusicProps | SNScoreProps | undefined ;
172- if ( props ?. tempo ) {
173- return props . tempo ;
174- }
175- current = current . parent ;
176- }
177- // 如果找不到,返回默认值 120 BPM
178- return { value : 120 , unit : 'BPM' } ;
175+ return this . findInheritedProp ( 'tempo' , { value : 120 , unit : 'BPM' } ) ;
179176 }
180177
181178 /**
182179 * 向上查找时间单位(若未设置则返回默认值)
183180 *
184- * 从当前节点开始向上追溯父节点,查找最近定义的时间单位
185- *
186181 * @returns 时间单位对象,包含 ticksPerWhole 和 ticksPerBeat
187182 */
188183 getTimeUnit ( ) : { ticksPerWhole : number ; ticksPerBeat : number } {
189- // 从当前节点开始向上遍历父节点链
190- let current : SNParserNode | undefined = this . parent ;
191- while ( current ) {
192- const props = current . props as SNMusicProps | SNScoreProps | undefined ;
193- if ( props ?. timeUnit ) {
194- return props . timeUnit ;
195- }
196- current = current . parent ;
197- }
198- // 如果找不到,返回默认值
199- return { ticksPerWhole : 48 , ticksPerBeat : 12 } ;
184+ return this . findInheritedProp ( 'timeUnit' , {
185+ ticksPerWhole : 48 ,
186+ ticksPerBeat : 12 ,
187+ } ) ;
200188 }
201189
202190 /**
@@ -215,20 +203,6 @@ export class SNParserNode<
215203 transpose ?: number ;
216204 [ key : string ] : unknown ;
217205 } > {
218- // 从当前节点开始向上遍历父节点链
219- // 注意:从子节点到父节点遍历,子节点的定义会覆盖父节点的定义
220- let current : SNParserNode | undefined = this . parent ;
221- const voicesMap = new Map <
222- string ,
223- {
224- voiceNumber : string ;
225- name ?: string ;
226- clef ?: 'treble' | 'bass' | 'alto' | 'tenor' ;
227- transpose ?: number ;
228- [ key : string ] : unknown ;
229- }
230- > ( ) ;
231-
232206 // 收集所有父节点的声部定义(从子节点到父节点)
233207 const allVoices : Array < {
234208 voiceNumber : string ;
@@ -238,22 +212,23 @@ export class SNParserNode<
238212 [ key : string ] : unknown ;
239213 } > = [ ] ;
240214
215+ let current : SNParserNode | undefined = this . parent ;
241216 while ( current ) {
242217 const props = current . props as SNScoreProps | undefined ;
243218 if ( props ?. voices && props . voices . length > 0 ) {
244- // 收集声部定义(从子节点到父节点)
245219 allVoices . push ( ...props . voices ) ;
246220 }
247221 current = current . parent ;
248222 }
249223
250- // 从子节点到父节点合并声部定义(子节点的定义会覆盖父节点的定义 )
251- // 由于 allVoices 是从子节点到父节点收集的,所以后面的定义会覆盖前面的定义
224+ // 按 voiceNumber 合并(子节点定义覆盖父节点定义 )
225+ const voicesMap = new Map < string , ( typeof allVoices ) [ 0 ] > ( ) ;
252226 for ( const voice of allVoices ) {
253- voicesMap . set ( voice . voiceNumber , { ...voice } ) ;
227+ if ( ! voicesMap . has ( voice . voiceNumber ) ) {
228+ voicesMap . set ( voice . voiceNumber , { ...voice } ) ;
229+ }
254230 }
255231
256- // 返回声部定义数组
257232 return Array . from ( voicesMap . values ( ) ) ;
258233 }
259234}
0 commit comments