// Called when the number of buffered 'AudioData' objects increases by 1 func (audio *SDLAudio) bufferAdd() { audio.mutex.Lock() { audio.bufSize++ // Unpause SDL audio if we have BUFSIZE_IDEAL 'AudioData' objects if !audio.sdlAudioUnpaused && (audio.bufSize == BUFSIZE_IDEAL) { sdl_audio.PauseAudio(false) audio.sdlAudioUnpaused = true } } audio.mutex.Unlock() }
func NewAudio() *Audio { as = sdl_audio.AudioSpec{ Freq: 44100, Format: sdl_audio.AUDIO_S16SYS, Channels: 1, Out_Silence: 0, Samples: uint16(SampleSize), Out_Size: 0, } if sdl_audio.OpenAudio(&as, nil) < 0 { log.Fatal(sdl.GetError()) } sdl_audio.PauseAudio(false) return &Audio{ samples: make([]int16, SampleSize), } }
func (a *Audio) Run() { as := sdl_audio.AudioSpec{ Freq: 44100, Format: sdl_audio.AUDIO_S16SYS, Channels: 1, Out_Silence: 0, Samples: uint16(SampleSize), Out_Size: 0, } if sdl_audio.OpenAudio(&as, nil) < 0 { log.Fatal(sdl.GetError()) } sdl_audio.PauseAudio(false) for { select { case s := <-a.sample: a.AppendSample(s) } } }
func NewAudio(frequency int, sampleSize int) (audio *SDLAudio, err error) { spec := sdl_audio.AudioSpec{ Freq: frequency, Format: sdl_audio.AUDIO_S16SYS, Channels: 1, Out_Silence: 0, Samples: uint16(sampleSize), Out_Size: 0, } if sdl_audio.OpenAudio(&spec, nil) < 0 { err = errors.New(sdl.GetError()) return } sdl_audio.PauseAudio(false) audio = &SDLAudio{ samples: make([]int16, sampleSize), input: make(chan int16), } return }
func (a *Audio) Close() { fmt.Println("Closing!") sdl_audio.PauseAudio(true) sdl_audio.CloseAudio() }
// Forward 'AudioData' objects from 'audio.data' to 'audio.playback' func forwarderLoop(evtLoop *spectrum.EventLoop, audio *SDLAudio) { audioDataChannel := audio.data playback_closed := false shutdown.Add(1) for { select { case <-evtLoop.Pause: // Remove all enqueued AudioData objects loop: for { select { case <-audio.playback: default: break loop } } audio.mutex.Lock() { if !audio.sdlAudioUnpaused { // Unpause SDL Audio. This is needed in order to avoid // a potential deadlock on 'sdl_audio.SendAudio_int16()'. // (If audio is paused, 'sdl_audio.SendAudio_int16()' waits indefinitely.) sdl_audio.PauseAudio(false) audio.sdlAudioUnpaused = true } } audio.mutex.Unlock() close(audio.playback) playback_closed = true <-audio.playbackLoopFinished sdl_audio.CloseAudio() audio.mutex.Lock() forwarderLoopFinished := audio.forwarderLoopFinished audio.mutex.Unlock() if forwarderLoopFinished != nil { forwarderLoopFinished <- 0 } evtLoop.Pause <- 0 case <-evtLoop.Terminate: // Terminate this Go routine if evtLoop.App().Verbose { evtLoop.App().PrintfMsg("audio forwarder loop: exit") } evtLoop.Terminate <- 0 shutdown.Done() return case audioData := <-audioDataChannel: if audioData != nil { if !playback_closed { audio.bufferAdd() audio.playback <- audioData } } else { // Prevent any future sends via the 'audio.data' channel close(audio.data) // Replace 'audioDataChannel' with nil, // so that future executions of the 'select' statement ignore the "<-audioDataChannel" case audioDataChannel = nil // Go to the '<-evtLoop.Pause' case done := evtLoop.Delete() go func() { <-done }() } } } }
func (audio *SDLAudio) Close() { sdl_audio.PauseAudio(true) sdl_audio.CloseAudio() }
func (audio *SDLAudio) TogglePaused() { audio.paused = !audio.paused sdl_audio.PauseAudio(audio.paused) }