@@ -7,6 +7,7 @@ type Volume float32
77
88var (
99 // VolumeUseInstVol tells the system to use the volume stored on the instrument
10+ // This is useful for trackers and other musical applications
1011 VolumeUseInstVol = Volume (math .Inf (- 1 ))
1112)
1213
@@ -21,31 +22,33 @@ type Int24 struct {
2122
2223// ToSample returns a volume as a typed value supporting the bits per sample provided
2324func (v Volume ) ToSample (bitsPerSample int ) interface {} {
25+ val := v .withOverflowProtection ()
2426 switch bitsPerSample {
2527 case 8 :
26- return int8 (v * 128.0 )
28+ return int8 (val * 128.0 )
2729 case 16 :
28- return int16 (v * 32678.0 )
30+ return int16 (val * 32678.0 )
2931 case 24 :
30- s := int32 (v * 8388608.0 )
32+ s := int32 (val * 8388608.0 )
3133 return Int24 {Hi : int8 (s >> 16 ), Lo : uint16 (s & 65535 )}
3234 case 32 :
33- return int32 (v * 2147483648.0 )
35+ return int32 (val * 2147483648.0 )
3436 }
3537 return 0
3638}
3739
3840// ToIntSample returns a volume as an int32 value ranged to the bits per sample provided
3941func (v Volume ) ToIntSample (bitsPerSample int ) int32 {
42+ val := v .withOverflowProtection ()
4043 switch bitsPerSample {
4144 case 8 :
42- return int32 (v * 128.0 )
45+ return int32 (val * 128.0 )
4346 case 16 :
44- return int32 (v * 32678.0 )
47+ return int32 (val * 32678.0 )
4548 case 24 :
46- return int32 (v * 8388608.0 )
49+ return int32 (val * 8388608.0 )
4750 case 32 :
48- return int32 (v * 2147483648.0 )
51+ return int32 (val * 2147483648.0 )
4952 }
5053 return 0
5154}
@@ -69,3 +72,16 @@ func (m Matrix) Apply(samp ...Volume) Matrix {
6972 }
7073 return o
7174}
75+
76+ func (v Volume ) withOverflowProtection () float64 {
77+ val := float64 (v )
78+ if math .Abs (val ) <= 1.0 {
79+ // likely case
80+ return val
81+ } else if math .Signbit (val ) {
82+ // overflow, negative
83+ return - 1.0
84+ }
85+ // overflow, positive
86+ return 1.0
87+ }
0 commit comments