// NewPlayer returns a new Player. // It initializes the underlying audio devices and the related resources. func NewPlayer(src io.ReadSeeker, format Format, sampleRate int64) (*Player, error) { device.Lock() defer device.Unlock() if device.d == nil { device.d = alc.Open("") c := device.d.CreateContext(nil) if !alc.MakeContextCurrent(c) { return nil, fmt.Errorf("player: cannot initiate a new player") } } s := al.GenSources(1) if code := al.Error(); code != 0 { return nil, fmt.Errorf("player: cannot generate an audio source [err=%x]", code) } bufs := al.GenBuffers(2) if err := lastErr(); err != nil { return nil, err } return &Player{ t: &track{format: format, src: src, rate: sampleRate}, source: s[0], bufs: bufs, }, nil }
func (p *Player) prepare(offset int64, force bool) error { p.muPrep.Lock() defer p.muPrep.Unlock() if !force && p.prep { return nil } if len(p.bufs) > 0 { p.source.UnqueueBuffers(p.bufs) al.DeleteBuffers(p.bufs) } if _, err := p.t.src.Seek(offset, 0); err != nil { return err } p.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(uint32(formatToCode[p.t.format]), buf[:n], int32(p.t.rate)) p.bufs = append(p.bufs, b[0]) } if err == io.EOF { break } if err != nil { return err } } p.size = size if len(p.bufs) > 0 { p.source.QueueBuffers(p.bufs) } p.prep = true return nil }