audio: Stream reading must be done only when buffers are available (Windows)

This commit is contained in:
Hajime Hoshi 2016-04-05 12:17:23 +09:00
parent 2d3c3e361e
commit 398d7710ae
2 changed files with 33 additions and 22 deletions

View File

@ -140,8 +140,7 @@ func (p *player) close() error {
var bs []al.Buffer var bs []al.Buffer
al.RewindSources(p.alSource) al.RewindSources(p.alSource)
al.StopSources(p.alSource) al.StopSources(p.alSource)
n := p.alSource.BuffersQueued() if n := p.alSource.BuffersQueued(); 0 < n {
if 0 < n {
bs = make([]al.Buffer, n) bs = make([]al.Buffer, n)
p.alSource.UnqueueBuffers(bs...) p.alSource.UnqueueBuffers(bs...)
p.alBuffers = append(p.alBuffers, bs...) p.alBuffers = append(p.alBuffers, bs...)

View File

@ -37,10 +37,10 @@ type header struct {
waveHdr C.WAVEHDR waveHdr C.WAVEHDR
} }
func newHeader(waveOut C.HWAVEOUT, bufferSize int) (header, error) { func newHeader(waveOut C.HWAVEOUT, bufferSize int) (*header, error) {
// NOTE: This is never freed so far. // NOTE: This is never freed so far.
buf := C.malloc(C.size_t(bufferSize)) buf := C.malloc(C.size_t(bufferSize))
h := header{ h := &header{
buffer: buf, buffer: buf,
bufferSize: bufferSize, bufferSize: bufferSize,
waveHdr: C.WAVEHDR{ waveHdr: C.WAVEHDR{
@ -50,7 +50,7 @@ func newHeader(waveOut C.HWAVEOUT, bufferSize int) (header, error) {
} }
// TODO: Need to unprepare to avoid memory leak? // TODO: Need to unprepare to avoid memory leak?
if err := C.waveOutPrepareHeader(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR { if err := C.waveOutPrepareHeader(waveOut, &h.waveHdr, C.sizeOfWavehdr); err != C.MMSYSERR_NOERROR {
return header{}, fmt.Errorf("audio: waveOutPrepareHeader error: %d", err) return nil, fmt.Errorf("audio: waveOutPrepareHeader error: %d", err)
} }
return h, nil return h, nil
} }
@ -78,9 +78,8 @@ func releaseSemaphore() {
type player struct { type player struct {
src io.Reader src io.Reader
out C.HWAVEOUT out C.HWAVEOUT
i int
buffer []byte buffer []byte
headers []header headers []*header
} }
const bufferSize = 1024 const bufferSize = 1024
@ -103,7 +102,7 @@ func newPlayer(src io.Reader, sampleRate int) (*player, error) {
src: src, src: src,
out: w, out: w,
buffer: []byte{}, buffer: []byte{},
headers: make([]header, numHeader), headers: make([]*header, numHeader),
} }
for i := 0; i < numHeader; i++ { for i := 0; i < numHeader; i++ {
var err error var err error
@ -116,22 +115,35 @@ func newPlayer(src io.Reader, sampleRate int) (*player, error) {
} }
func (p *player) proceed() error { func (p *player) proceed() error {
// TODO: Read should be called only when there are buffers available? if len(p.buffer) < bufferSize {
b := make([]byte, bufferSize) b := make([]byte, bufferSize)
n, err := p.src.Read(b) n, err := p.src.Read(b)
if 0 < n { if 0 < n {
p.buffer = append(p.buffer, b[:n]...) p.buffer = append(p.buffer, b[:n]...)
for bufferSize <= len(p.buffer) { }
sem <- struct{}{} if err != nil {
if err := p.headers[p.i].Write(p.out, p.buffer[:bufferSize]); err != nil { return err
return err
}
p.buffer = p.buffer[bufferSize:]
p.i++
p.i %= len(p.headers)
} }
} }
return err if bufferSize <= len(p.buffer) {
sem <- struct{}{}
headerToWrite := (*header)(nil)
for _, h := range p.headers {
// TODO: Need to check WHDR_DONE?
if h.waveHdr.dwFlags & C.WHDR_INQUEUE == 0 {
headerToWrite = h
break
}
}
if headerToWrite == nil {
return errors.New("audio: no available buffers")
}
if err := headerToWrite.Write(p.out, p.buffer[:bufferSize]); err != nil {
return err
}
p.buffer = p.buffer[bufferSize:]
}
return nil
} }
func (p *player) close() { func (p *player) close() {