-
Notifications
You must be signed in to change notification settings - Fork 0
/
aquestalk_windows.go
76 lines (70 loc) · 1.49 KB
/
aquestalk_windows.go
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
package aquestalk
import (
"reflect"
"sync"
"syscall"
"unsafe"
)
// Synthe synthesizes voice with an engine a.k.a. "Yukkuri".
func Synthe(koe string, speed int32) ([]byte, error) {
err := dllInit()
if err != nil {
return nil, err
}
pKoe := append([]byte(koe), 0)
var size int32
r1, _, err := dllSynthe.Call(uintptr(unsafe.Pointer(&pKoe[0])), uintptr(speed), uintptr(unsafe.Pointer(&size)))
if nr, ok := err.(syscall.Errno); !ok || nr != 0 {
return nil, nr
}
if r1 == 0 {
return nil, errno(size)
}
pWav := toBytes(r1, size)
p := make([]byte, len(pWav))
copy(p, pWav)
dllFree.Call(r1)
return p, nil
}
func toBytes(p uintptr, size int32) []byte {
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: p,
Len: int(size),
Cap: int(size),
}))
}
// DLLName declares name of DLL. You can change this only before call Synthe().
var DLLName = "AquesTalk.dll"
var (
dllOnce sync.Once
dllPtr *syscall.DLL
dllSynthe *syscall.Proc
dllFree *syscall.Proc
dllErr error
)
func dllInit() error {
dllOnce.Do(func() {
if dllErr != nil || dllPtr != nil {
return
}
dll, err := syscall.LoadDLL(DLLName)
if err != nil {
dllErr = err
return
}
pSynthe, err := dll.FindProc("AquesTalk_Synthe_Utf8")
if err != nil {
dll.Release()
dllErr = err
return
}
pFreeWave, err := dll.FindProc("AquesTalk_FreeWave")
if err != nil {
dll.Release()
dllErr = err
return
}
dllPtr, dllSynthe, dllFree, dllErr = dll, pSynthe, pFreeWave, nil
})
return dllErr
}