Render file playback through the OpenAL owner
This commit is contained in:
committed by
Brandon McGinty
parent
8c0887d562
commit
db31ba33de
+25
-62
@@ -10,22 +10,19 @@ import (
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/barnard/gumble/gumble"
|
||||
"git.stormux.org/storm/barnard/gumble/go-openal/openal"
|
||||
)
|
||||
|
||||
// Player handles file playback and mixing with microphone audio
|
||||
type Player struct {
|
||||
client *gumble.Client
|
||||
filename string
|
||||
audioChan chan gumble.AudioBuffer
|
||||
stopChan chan struct{}
|
||||
mutex sync.Mutex
|
||||
playing bool
|
||||
errorFunc func(error)
|
||||
client *gumble.Client
|
||||
filename string
|
||||
audioChan chan gumble.AudioBuffer
|
||||
stopChan chan struct{}
|
||||
mutex sync.Mutex
|
||||
playing bool
|
||||
errorFunc func(error)
|
||||
|
||||
// Local playback
|
||||
localSource *openal.Source
|
||||
localBuffers openal.Buffers
|
||||
localPlayback func([]byte)
|
||||
}
|
||||
|
||||
// New creates a new file player
|
||||
@@ -44,6 +41,14 @@ func (p *Player) SetErrorFunc(f func(error)) {
|
||||
p.errorFunc = f
|
||||
}
|
||||
|
||||
// SetLocalPlayback sets the callback that plays file audio locally. The
|
||||
// callback is called with nil when playback stops and should release resources.
|
||||
func (p *Player) SetLocalPlayback(f func([]byte)) {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
p.localPlayback = f
|
||||
}
|
||||
|
||||
func (p *Player) reportError(err error) {
|
||||
p.mutex.Lock()
|
||||
errorFunc := p.errorFunc
|
||||
@@ -65,14 +70,6 @@ func (p *Player) PlayFile(filename string) error {
|
||||
|
||||
p.filename = filename
|
||||
|
||||
// Initialize local playback
|
||||
source := openal.NewSource()
|
||||
p.localSource = &source
|
||||
p.localSource.SetGain(1.0)
|
||||
|
||||
// Create buffers for local playback
|
||||
p.localBuffers = openal.NewBuffers(64)
|
||||
|
||||
// Start the file reading goroutine
|
||||
p.playing = true
|
||||
p.stopChan = make(chan struct{})
|
||||
@@ -93,15 +90,8 @@ func (p *Player) Stop() error {
|
||||
close(p.stopChan)
|
||||
p.playing = false
|
||||
|
||||
// Clean up local playback
|
||||
if p.localSource != nil {
|
||||
p.localSource.Stop()
|
||||
p.localSource.Delete()
|
||||
p.localSource = nil
|
||||
}
|
||||
if p.localBuffers != nil {
|
||||
p.localBuffers.Delete()
|
||||
p.localBuffers = nil
|
||||
if p.localPlayback != nil {
|
||||
p.localPlayback(nil)
|
||||
}
|
||||
|
||||
// Drain the audio channel
|
||||
@@ -129,32 +119,12 @@ func (p *Player) GetAudioFrame() []int16 {
|
||||
}
|
||||
}
|
||||
|
||||
// playLocalAudio plays audio through the local OpenAL source
|
||||
func (p *Player) playLocalAudio(data []byte) {
|
||||
if p.localSource == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Reclaim processed buffers
|
||||
if n := p.localSource.BuffersProcessed(); n > 0 {
|
||||
reclaimedBufs := make(openal.Buffers, n)
|
||||
p.localSource.UnqueueBuffers(reclaimedBufs)
|
||||
p.localBuffers = append(p.localBuffers, reclaimedBufs...)
|
||||
}
|
||||
|
||||
// If we have available buffers, queue more audio
|
||||
if len(p.localBuffers) > 0 {
|
||||
buffer := p.localBuffers[len(p.localBuffers)-1]
|
||||
p.localBuffers = p.localBuffers[:len(p.localBuffers)-1]
|
||||
|
||||
// Set buffer data as stereo
|
||||
buffer.SetData(openal.FormatStereo16, data, gumble.AudioSampleRate)
|
||||
p.localSource.QueueBuffer(buffer)
|
||||
|
||||
// Start playing if not already
|
||||
if p.localSource.State() != openal.Playing {
|
||||
p.localSource.Play()
|
||||
}
|
||||
p.mutex.Lock()
|
||||
localPlayback := p.localPlayback
|
||||
p.mutex.Unlock()
|
||||
if localPlayback != nil {
|
||||
localPlayback(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,15 +174,8 @@ func (p *Player) readFileAudio() {
|
||||
// File finished playing
|
||||
p.mutex.Lock()
|
||||
p.playing = false
|
||||
// Clean up local playback
|
||||
if p.localSource != nil {
|
||||
p.localSource.Stop()
|
||||
p.localSource.Delete()
|
||||
p.localSource = nil
|
||||
}
|
||||
if p.localBuffers != nil {
|
||||
p.localBuffers.Delete()
|
||||
p.localBuffers = nil
|
||||
if p.localPlayback != nil {
|
||||
p.localPlayback(nil)
|
||||
}
|
||||
p.mutex.Unlock()
|
||||
cmd.Wait()
|
||||
|
||||
@@ -82,6 +82,8 @@ type Stream struct {
|
||||
micAGC *audio.AGC
|
||||
micAGCRight *audio.AGC
|
||||
filePlayer FilePlayer
|
||||
localSource *openal.Source
|
||||
localBuffers openal.Buffers
|
||||
recorderMu sync.RWMutex
|
||||
errorFunc func(error) // called on capture errors
|
||||
recorder Recorder
|
||||
@@ -200,6 +202,54 @@ func (s *Stream) SetNoiseProcessor(np NoiseProcessor) {
|
||||
|
||||
func (s *Stream) SetFilePlayer(fp FilePlayer) {
|
||||
s.filePlayer = fp
|
||||
if player, ok := fp.(interface{ SetLocalPlayback(func([]byte)) }); ok {
|
||||
player.SetLocalPlayback(s.playLocalAudio)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Stream) playLocalAudio(data []byte) {
|
||||
s.render(func() {
|
||||
if data == nil {
|
||||
if s.localSource != nil {
|
||||
s.localSource.Stop()
|
||||
queued := s.localSource.BuffersQueued()
|
||||
if queued > 0 {
|
||||
buffers := make(openal.Buffers, queued)
|
||||
s.localSource.UnqueueBuffers(buffers)
|
||||
s.localBuffers = append(s.localBuffers, buffers...)
|
||||
}
|
||||
s.localSource.Delete()
|
||||
s.localSource = nil
|
||||
}
|
||||
if len(s.localBuffers) > 0 {
|
||||
s.localBuffers.Delete()
|
||||
s.localBuffers = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
if s.localSource == nil {
|
||||
source := openal.NewSource()
|
||||
source.SetGain(1)
|
||||
s.localSource = &source
|
||||
s.localBuffers = openal.NewBuffers(64)
|
||||
}
|
||||
if n := s.localSource.BuffersProcessed(); n > 0 {
|
||||
buffers := make(openal.Buffers, n)
|
||||
s.localSource.UnqueueBuffers(buffers)
|
||||
s.localBuffers = append(s.localBuffers, buffers...)
|
||||
}
|
||||
if len(s.localBuffers) == 0 {
|
||||
return
|
||||
}
|
||||
last := len(s.localBuffers) - 1
|
||||
buffer := s.localBuffers[last]
|
||||
s.localBuffers = s.localBuffers[:last]
|
||||
buffer.SetData(openal.FormatStereo16, data, gumble.AudioSampleRate)
|
||||
s.localSource.QueueBuffer(buffer)
|
||||
if s.localSource.State() != openal.Playing {
|
||||
s.localSource.Play()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Stream) GetFilePlayer() FilePlayer {
|
||||
|
||||
Reference in New Issue
Block a user