audio: Create an independent goroutine for enqueuing

This commit is contained in:
Hajime Hoshi 2016-05-26 02:41:00 +09:00
parent 12d62621e9
commit 644dfcd0fd

View File

@ -182,7 +182,6 @@ import "C"
import ( import (
"errors" "errors"
"sync"
"unsafe" "unsafe"
) )
@ -193,8 +192,8 @@ type Player struct {
audioTrack C.jobject audioTrack C.jobject
buffer []byte buffer []byte
bufferSize int bufferSize int
m sync.Mutex
chErr chan error chErr chan error
chBuffer chan []byte
} }
func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) { func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
@ -204,6 +203,7 @@ func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
bytesPerSample: bytesPerSample, bytesPerSample: bytesPerSample,
buffer: []byte{}, buffer: []byte{},
chErr: make(chan error), chErr: make(chan error),
chBuffer: make(chan []byte),
} }
if err := runOnJVM(func(vm, env, ctx uintptr) error { if err := runOnJVM(func(vm, env, ctx uintptr) error {
audioTrack := C.jobject(nil) audioTrack := C.jobject(nil)
@ -219,6 +219,38 @@ func NewPlayer(sampleRate, channelNum, bytesPerSample int) (*Player, error) {
}); err != nil { }); err != nil {
return nil, err return nil, err
} }
go func() {
for bufInBytes := range p.chBuffer {
var bufInShorts []int16
if p.bytesPerSample == 2 {
bufInShorts = make([]int16, len(bufInBytes)/2)
for i := 0; i < len(bufInShorts); i++ {
bufInShorts[i] = int16(bufInBytes[2*i]) | (int16(bufInBytes[2*i+1]) << 8)
}
}
if err := runOnJVM(func(vm, env, ctx uintptr) error {
msg := (*C.char)(nil)
switch p.bytesPerSample {
case 1:
msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), C.jobject(ctx),
p.audioTrack, C.int(p.bytesPerSample),
unsafe.Pointer(&bufInBytes[0]), C.int(len(bufInBytes)))
case 2:
msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), C.jobject(ctx),
p.audioTrack, C.int(p.bytesPerSample),
unsafe.Pointer(&bufInShorts[0]), C.int(len(bufInShorts)))
}
if msg != nil {
return errors.New(C.GoString(msg))
}
return nil
}); err != nil {
p.chErr <- err
return
}
}
}()
return p, nil return p, nil
} }
@ -232,38 +264,9 @@ func (p *Player) Proceed(data []byte) error {
if len(p.buffer) < p.bufferSize { if len(p.buffer) < p.bufferSize {
return nil return nil
} }
bufInBytes := p.buffer[:p.bufferSize] buf := p.buffer[:p.bufferSize]
var bufInShorts []int16 p.chBuffer <- buf
if p.bytesPerSample == 2 {
bufInShorts = make([]int16, len(bufInBytes)/2)
for i := 0; i < len(bufInShorts); i++ {
bufInShorts[i] = int16(bufInBytes[2*i]) | (int16(bufInBytes[2*i+1]) << 8)
}
}
p.buffer = p.buffer[p.bufferSize:] p.buffer = p.buffer[p.bufferSize:]
go func() {
p.m.Lock()
defer p.m.Unlock()
if err := runOnJVM(func(vm, env, ctx uintptr) error {
msg := (*C.char)(nil)
switch p.bytesPerSample {
case 1:
msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), C.jobject(ctx),
p.audioTrack, C.int(p.bytesPerSample),
unsafe.Pointer(&bufInBytes[0]), C.int(len(bufInBytes)))
case 2:
msg = C.writeToAudioTrack(C.uintptr_t(vm), C.uintptr_t(env), C.jobject(ctx),
p.audioTrack, C.int(p.bytesPerSample),
unsafe.Pointer(&bufInShorts[0]), C.int(len(bufInShorts)))
}
if msg != nil {
return errors.New(C.GoString(msg))
}
return nil
}); err != nil {
p.chErr <- err
}
}()
return nil return nil
} }