func (c *Context) Play() { c.Lock() defer c.Unlock() n := c.source.BuffersProcessed() if n > 0 { rm, split := c.queue[:n], c.queue[n:] c.queue = split c.source.UnqueueBuffers(rm...) al.DeleteBuffers(rm...) } for len(c.queue) < QUEUE { b := al.GenBuffers(1) buf := make([]byte, NS*CZ) for n := 0; n < NS*CZ; n += CZ { v := int16(float32(32767) * c.oscilator()) binary.LittleEndian.PutUint16(buf[n:n+2], uint16(v)) } b[0].BufferData(Fmt, buf, SampleRate) c.source.QueueBuffers(b...) c.queue = append(c.queue, b...) } if c.source.State() != al.Playing { al.PlaySources(c.source) } }
func CloseDevice() error { al.DeleteBuffers(hwa.buf.bufs) al.DeleteSources(hwa.source) al.CloseDevice() hwa = nil return nil }
func (c *Context) Close() { c.Lock() defer c.Unlock() al.StopSources(c.source) c.source.UnqueueBuffers(c.queue...) al.DeleteBuffers(c.queue...) c.queue = nil al.DeleteSources(c.source) }
func (p *Player) prepare(offset int64, force bool) error { p.mu.Lock() if !force && p.prep { p.mu.Unlock() return nil } p.mu.Unlock() if p.t.hasHeader { offset += headerSize } if _, err := p.t.src.Seek(offset, 0); err != nil { return err } var bufs []al.Buffer // TODO(jbd): Limit the number of buffers in use, unqueue and reuse // the existing buffers as buffers are processed. buf := make([]byte, 128*1024) size := offset for { n, err := p.t.src.Read(buf) if n > 0 { size += int64(n) b := al.GenBuffers(1) b[0].BufferData(formatCodes[p.t.format], buf[:n], int32(p.t.samplesPerSecond)) bufs = append(bufs, b[0]) } if err == io.EOF { break } if err != nil { return err } } p.mu.Lock() if len(p.bufs) > 0 { p.source.UnqueueBuffers(p.bufs...) al.DeleteBuffers(p.bufs...) } p.sizeBytes = size p.bufs = bufs p.prep = true if len(bufs) > 0 { p.source.QueueBuffers(bufs...) } p.mu.Unlock() return nil }
// Close closes the device and frees the underlying resources // used by the player. // It should be called as soon as the player is not in-use anymore. func (p *Player) Close() error { if p == nil { return nil } if p.source != 0 { al.DeleteSources(p.source) } p.mu.Lock() if len(p.bufs) > 0 { al.DeleteBuffers(p.bufs...) } p.mu.Unlock() p.t.src.Close() return nil }
func (p *Player) prepare(background bool, offset int64, force bool) error { p.mu.Lock() if !force && p.prep { p.mu.Unlock() return nil } p.mu.Unlock() if p.t.hasHeader { offset += headerSize } if _, err := p.t.src.Seek(offset, 0); err != nil { return err } var bufs []al.Buffer // TODO(jbd): Limit the number of buffers in use, unqueue and reuse // the existing buffers as buffers are processed. buf := make([]byte, 128*1024) size := offset for { n, err := p.t.src.Read(buf) if n > 0 { size += int64(n) b := al.GenBuffers(1) if !background && p.t.format == Stereo16 { inputBuffer := bytes.NewBuffer(buf) outputBuffer := new(bytes.Buffer) var left, right int16 // TODO: this might not be the best way to convert Stereo16 to Mono16, but it's something for converted := 0; converted < n; converted += 4 { binary.Read(inputBuffer, binary.LittleEndian, &left) binary.Read(inputBuffer, binary.LittleEndian, &right) binary.Write(outputBuffer, binary.LittleEndian, int16((int32(left)+int32(right))/2)) } b[0].BufferData(formatCodes[Mono16], outputBuffer.Bytes(), int32(p.t.samplesPerSecond/2)) } else { b[0].BufferData(formatCodes[p.t.format], buf[:n], int32(p.t.samplesPerSecond)) } bufs = append(bufs, b[0]) } if err == io.EOF { break } if err != nil { return err } } p.mu.Lock() if len(p.bufs) > 0 { p.source.UnqueueBuffers(p.bufs...) al.DeleteBuffers(p.bufs...) } p.sizeBytes = size p.bufs = bufs p.prep = true if len(bufs) > 0 { p.source.QueueBuffers(bufs...) } p.mu.Unlock() return nil }
// DestroyKey cleans up any resources for the key when destorying the key. func (k *PianoKey) DestroyKey(glctx gl.Context) { glctx.DeleteBuffer(k.glBuf) al.DeleteSources(k.soundSources...) al.DeleteBuffers(k.soundBuffers) al.CloseDevice() }