-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathints.go
More file actions
111 lines (91 loc) · 2.17 KB
/
ints.go
File metadata and controls
111 lines (91 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package libktn
import (
"math"
)
type Uint7 uint8
type Uint14 uint16
type Uint28 uint32
//Local constants.
const (
sysexByteMax = 0x7F
sysexByteFactor = 0x80
sysexShortMax = 0x3FFF
sysexWordMax = 0xFFFFFFF
)
//Converts from a 7bit sysex to an integer.
func MakeUint7(sysex byte) (Uint7, error) {
if sysex > sysexByteMax {
return 0, ErrOutOfBounds
}
return Uint7(sysex), nil
}
//Converts from an integer to 7bit sysex.
func (u Uint7) Sysex() ([]byte, error) {
if u > sysexByteMax {
return nil, ErrOutOfBounds
}
return []byte{byte(u)}, nil
}
//Converts from 2x7bit sysex to an integer.
func MakeUint14(sysex []byte) (Uint14, error) {
if len(sysex) != 2 {
return 0, SliceLengthError{2}
}
msb, errmsb := MakeUint7(sysex[0])
if errmsb != nil {
return 0, errmsb
}
lsb, errlsb := MakeUint7(sysex[1])
if errlsb != nil {
return 0, errlsb
}
return Uint14(msb)*sysexByteFactor + Uint14(lsb), nil
}
//Converts from an integer to 2x7bit sysex.
func (u Uint14) Sysex() ([]byte, error) {
if u > sysexShortMax {
return nil, ErrOutOfBounds
}
return []byte{
byte((u / sysexByteFactor) % sysexByteFactor),
byte(u % sysexByteFactor),
}, nil
}
//Converts from 4x7bit sysex to an integer.
func MakeUint28(sysex []byte) (Uint28, error) {
if len(sysex) != 4 {
return 0, SliceLengthError{4}
}
//Convert each byte first.
b := make([]Uint7, 4)
for i := range sysex {
x, err := MakeUint7(sysex[i])
if err != nil {
return 0, err
}
b[i] = x
}
//Invert our for loop since this is what power to raise the factor to.
//[0x80^3, 0x80^2, 0x80^1, 0x80^0]
acc := Uint28(0)
for i := len(b) - 1; i >= 0; i-- {
j := len(b) - i - 1
acc += Uint28(b[j]) * uint28Pow(sysexByteFactor, Uint28(i))
}
return acc, nil
}
//Converts from an integer to 4x7bit sysex.
func (u Uint28) Sysex() ([]byte, error) {
if u > sysexWordMax {
return nil, ErrOutOfBounds
}
return []byte{
byte((u / uint28Pow(sysexByteFactor, 3)) % sysexByteFactor),
byte((u / uint28Pow(sysexByteFactor, 2)) % sysexByteFactor),
byte((u / sysexByteFactor) % sysexByteFactor),
byte(u % sysexByteFactor),
}, nil
}
func uint28Pow(b, p Uint28) Uint28 {
return Uint28(math.Pow(float64(b), float64(p)))
}