ebiten/exp/audio/inner/audio_openal.go

109 lines
2.5 KiB
Go

// Copyright 2015 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !js,!windows
package internal
import (
"fmt"
"log"
"runtime"
"sync"
"time"
"github.com/timshannon/go-openal/openal"
)
var channelsMutex = sync.Mutex{}
func withChannels(f func()) {
channelsMutex.Lock()
defer channelsMutex.Unlock()
f()
}
func initialize() {
// Creating OpenAL device must be done after initializing UI. I'm not sure the reason.
ch := make(chan struct{})
go func() {
runtime.LockOSThread()
device := openal.OpenDevice("")
context := device.CreateContext()
context.Activate()
if err := openal.Err(); err != nil {
log.Printf("OpenAL initialize error: %v", err)
close(ch)
// Graceful ending: Audio is not available on Travis CI.
return
}
audioEnabled = true
sources := openal.NewSources(MaxChannel)
close(ch)
const bufferSize = 2048
emptyBytes := make([]byte, bufferSize)
for _, source := range sources {
// 3 is the least number?
// http://stackoverflow.com/questions/14932004/play-sound-with-openalstream
const bufferNum = 4
buffers := openal.NewBuffers(bufferNum)
for _, buffer := range buffers {
buffer.SetData(openal.FormatStereo16, emptyBytes, SampleRate)
source.QueueBuffer(buffer)
}
source.Play()
if err := openal.Err(); err != nil {
panic(fmt.Sprintf("OpenAL error: %v", err))
}
}
for {
oneProcessed := false
for ch, source := range sources {
processed := source.BuffersProcessed()
if processed == 0 {
continue
}
oneProcessed = true
buffers := make([]openal.Buffer, processed)
source.UnqueueBuffers(buffers)
for _, buffer := range buffers {
b := make([]byte, bufferSize)
copy(b, loadChannelBuffer(ch, bufferSize))
buffer.SetData(openal.FormatStereo16, b, SampleRate)
source.QueueBuffer(buffer)
}
if source.State() == openal.Stopped {
source.Rewind()
source.Play()
}
}
if !oneProcessed {
time.Sleep(1 * time.Millisecond)
}
}
}()
<-ch
}
func start() {
// Do nothing
}