@@ -52,6 +52,29 @@ WAVEFORMATEX pcmFormat =
5252#define GMDLS_FILEBUFFER_SIZE 1024 *1024 *10
5353const char * lpGMDLSSuffix = " \\ drivers\\ gm.dls" ;
5454char lpGMDLSBuffer[GMDLS_FILEBUFFER_SIZE ]; // 10Mb is enough for reading in
55+
56+ // Convert a DLS Level 1 timecent value (16.16 fixed-point lScale) to seconds.
57+ // timecents = lScale / 65536; seconds = 2 ^ (timecents / 1200)
58+ // Clamped to ±10 octaves to guard against extreme / garbage values.
59+ static inline float gmdls_tc_to_sec (int32_t lScale)
60+ {
61+ double tc = (double )lScale / 65536.0 ;
62+ if (tc < -12000.0 ) tc = -12000.0 ;
63+ if (tc > 12000.0 ) tc = 12000.0 ;
64+ return (float )pow (2.0 , tc / 1200.0 );
65+ }
66+
67+ // Map a DLS WLOOP ulType to the internal loopType convention:
68+ // DLS 0 (forward) -> 1
69+ // DLS 1 (release/bidi) -> 2
70+ // Returns 0 for unsupported types (caller should reject such loops).
71+ static inline uint8_t gmdls_loop_type (uint32_t dlsType)
72+ {
73+ if (dlsType == 0 ) return 1 ; // forward loop
74+ if (dlsType == 1 ) return 2 ; // release / bidirectional loop
75+ return 0 ;
76+ }
77+
5578#endif // _WIN32
5679#endif // GMDLS_SKIP
5780
@@ -355,13 +378,13 @@ void _64klang_Init(uint8_t* songStream, void* patchData, uint32_t const1Offset,
355378 uint32_t lType = *(uint32_t *)(buf + lb + 4 );
356379 uint32_t lSt = *(uint32_t *)(buf + lb + 8 );
357380 uint32_t lLen = *(uint32_t *)(buf + lb + 12 );
358- // DLS loop types: 0= forward, 1=release (no-sustain bidi in some impls)
381+ // DLS loop type 0 = forward, 1 = release/bidirectional
359382 if (lType == 0 || lType == 1 )
360383 {
361384 // Scale raw sample indices by 2x upsampling factor
362385 GMDLS_LoopData[numWaves].loopStart = lSt * 2 ;
363386 GMDLS_LoopData[numWaves].loopEnd = (lSt + lLen) * 2 ;
364- GMDLS_LoopData[numWaves].loopType = (lType == 0 ) ? 1 : 2 ;
387+ GMDLS_LoopData[numWaves].loopType = gmdls_loop_type (lType) ;
365388 GMDLS_LoopData[numWaves].sourcePriority = 1 ; // wave-level
366389 }
367390 }
@@ -524,7 +547,7 @@ void _64klang_Init(uint8_t* songStream, void* patchData, uint32_t const1Offset,
524547 {
525548 rLoopStart = lSt * 2 ;
526549 rLoopEnd = (lSt + lLen) * 2 ;
527- rLoopType = (lType == 0 ) ? 1 : 2 ;
550+ rLoopType = gmdls_loop_type (lType); // 1=forward, 2=release/bidi
528551 rHasLoop = true ;
529552 }
530553 }
@@ -566,24 +589,15 @@ void _64klang_Init(uint8_t* songStream, void* patchData, uint32_t const1Offset,
566589 if (src != 0 || ctrl != 0 )
567590 continue ;
568591
569- // Time values: timecents -> seconds = 2^(tc/1200)
570- // where tc = lScale/65536 (16.16 fixed-point)
571- double tc;
572592 switch (dst)
573593 {
574594 case 0x0104 : // EG1_ATTACK_TIME
575- tc = (double )scale / 65536.0 ;
576- if (tc < -12000.0 ) tc = -12000.0 ;
577- if (tc > 12000.0 ) tc = 12000.0 ;
578- envAttack = (float )pow (2.0 , tc / 1200.0 );
579- envValid |= 1 ;
595+ envAttack = gmdls_tc_to_sec (scale);
596+ envValid |= 1 ;
580597 break ;
581598 case 0x0105 : // EG1_DECAY_TIME
582- tc = (double )scale / 65536.0 ;
583- if (tc < -12000.0 ) tc = -12000.0 ;
584- if (tc > 12000.0 ) tc = 12000.0 ;
585- envDecay = (float )pow (2.0 , tc / 1200.0 );
586- envValid |= 2 ;
599+ envDecay = gmdls_tc_to_sec (scale);
600+ envValid |= 2 ;
587601 break ;
588602 case 0x010A : // EG1_SUSTAIN_LEVEL
589603 // DLS Level 1: hundredths of a percent
@@ -594,14 +608,11 @@ void _64klang_Init(uint8_t* songStream, void* patchData, uint32_t const1Offset,
594608 if (lin > 1.0 ) lin = 1.0 ;
595609 envSustain = (float )lin;
596610 }
597- envValid |= 4 ;
611+ envValid |= 4 ;
598612 break ;
599613 case 0x0107 : // EG1_RELEASE_TIME
600- tc = (double )scale / 65536.0 ;
601- if (tc < -12000.0 ) tc = -12000.0 ;
602- if (tc > 12000.0 ) tc = 12000.0 ;
603- envRelease = (float )pow (2.0 , tc / 1200.0 );
604- envValid |= 8 ;
614+ envRelease = gmdls_tc_to_sec (scale);
615+ envValid |= 8 ;
605616 break ;
606617 }
607618 }
0 commit comments