diff --git a/exp/audio/internal/driver/driver_openal.go b/exp/audio/internal/driver/driver_openal.go index 1ebc30061..a359d300e 100644 --- a/exp/audio/internal/driver/driver_openal.go +++ b/exp/audio/internal/driver/driver_openal.go @@ -21,72 +21,61 @@ import ( "io" "runtime" - "github.com/timshannon/go-openal/openal" + "golang.org/x/mobile/exp/audio/al" ) -// As x/mobile/exp/audio/al is broken on Mac OS X (https://github.com/golang/go/issues/15075), -// let's use timshannon/go-openal. - const ( maxBufferNum = 8 ) type Player struct { - alDevice *openal.Device - alSource openal.Source - alBuffers []openal.Buffer + alSource al.Source + alBuffers []al.Buffer source io.Reader sampleRate int isClosed bool - alFormat openal.Format + alFormat uint32 } -func alFormat(channelNum, bytesPerSample int) openal.Format { +func alFormat(channelNum, bytesPerSample int) uint32 { switch { case channelNum == 1 && bytesPerSample == 1: - return openal.FormatMono8 + return al.FormatMono8 case channelNum == 1 && bytesPerSample == 2: - return openal.FormatMono16 + return al.FormatMono16 case channelNum == 2 && bytesPerSample == 1: - return openal.FormatStereo8 + return al.FormatStereo8 case channelNum == 2 && bytesPerSample == 2: - return openal.FormatStereo16 + return al.FormatStereo16 } panic(fmt.Sprintf("driver: invalid channel num (%d) or bytes per sample (%d)", channelNum, bytesPerSample)) } func NewPlayer(src io.Reader, sampleRate, channelNum, bytesPerSample int) (*Player, error) { - d := openal.OpenDevice("") - if err := openal.Err(); err != nil { - return nil, err + if e := al.OpenDevice(); e != nil { + return nil, fmt.Errorf("driver: OpenAL initialization failed: %v", e) } - c := d.CreateContext() - if err := openal.Err(); err != nil { - return nil, err - } - c.Activate() - s := openal.NewSource() - if err := openal.Err(); err != nil { - return nil, err + s := al.GenSources(1) + if err := al.Error(); err != 0 { + return nil, fmt.Errorf("driver: al.GenSources error: %d", err) } p := &Player{ - alDevice: d, - alSource: s, - alBuffers: []openal.Buffer{}, + alSource: s[0], + alBuffers: []al.Buffer{}, source: src, sampleRate: sampleRate, alFormat: alFormat(channelNum, bytesPerSample), } runtime.SetFinalizer(p, (*Player).Close) - bs := openal.NewBuffers(maxBufferNum) + bs := al.GenBuffers(maxBufferNum) emptyBytes := make([]byte, bufferSize) for _, b := range bs { // Note that the third argument of only the first buffer is used. - b.SetData(p.alFormat, emptyBytes, int32(p.sampleRate)) - p.alSource.QueueBuffer(b) + b.BufferData(p.alFormat, emptyBytes, int32(p.sampleRate)) + p.alSource.QueueBuffers(b) } - p.alSource.Play() + al.PlaySources(p.alSource) return p, nil } @@ -96,19 +85,19 @@ const ( var ( tmpBuffer = make([]byte, bufferSize) - tmpAlBuffers = make([]openal.Buffer, maxBufferNum) + tmpAlBuffers = make([]al.Buffer, maxBufferNum) ) func (p *Player) Proceed() error { - if err := openal.Err(); err != nil { - return err + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: before proceed: %d", err) } processedNum := p.alSource.BuffersProcessed() if 0 < processedNum { bufs := tmpAlBuffers[:processedNum] - p.alSource.UnqueueBuffers(bufs) - if err := openal.Err(); err != nil { - return err + p.alSource.UnqueueBuffers(bufs...) + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: Unqueue in process: %d", err) } p.alBuffers = append(p.alBuffers, bufs...) } @@ -118,10 +107,10 @@ func (p *Player) Proceed() error { if 0 < n { buf := p.alBuffers[0] p.alBuffers = p.alBuffers[1:] - buf.SetData(p.alFormat, tmpBuffer[:n], int32(p.sampleRate)) - p.alSource.QueueBuffer(buf) - if err := openal.Err(); err != nil { - return err + buf.BufferData(p.alFormat, tmpBuffer[:n], int32(p.sampleRate)) + p.alSource.QueueBuffers(buf) + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: Queue in process: %d", err) } } if err != nil { @@ -129,11 +118,11 @@ func (p *Player) Proceed() error { } } - if p.alSource.State() == openal.Stopped || p.alSource.State() == openal.Initial { - p.alSource.Rewind() - p.alSource.Play() - if err := openal.Err(); err != nil { - return err + if p.alSource.State() == al.Stopped || p.alSource.State() == al.Initial { + al.RewindSources(p.alSource) + al.PlaySources(p.alSource) + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: PlaySource in process: %d", err) } } @@ -141,24 +130,23 @@ func (p *Player) Proceed() error { } func (p *Player) Close() error { - if err := openal.Err(); err != nil { - return err + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: error before closing: %d", err) } if p.isClosed { return nil } - var bs []openal.Buffer - p.alSource.Rewind() - p.alSource.Play() + var bs []al.Buffer + al.RewindSources(p.alSource) + al.StopSources(p.alSource) if n := p.alSource.BuffersQueued(); 0 < n { - bs = make([]openal.Buffer, n) - p.alSource.UnqueueBuffers(bs) + bs = make([]al.Buffer, n) + p.alSource.UnqueueBuffers(bs...) p.alBuffers = append(p.alBuffers, bs...) } - p.alDevice.CloseDevice() p.isClosed = true - if err := openal.Err(); err != nil { - return err + if err := al.Error(); err != 0 { + return fmt.Errorf("driver: error after closing: %d", err) } runtime.SetFinalizer(p, nil) return nil