// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build darwin linux,!android // Package al provides OpenAL Soft bindings for Go. // // More information about OpenAL Soft is available at // http://www.openal.org/documentation/openal-1.1-specification.pdf. package al /* // TODO(jbd,crawshaw): Add android and windows support. #cgo darwin CFLAGS: -DGOOS_darwin #cgo linux CFLAGS: -DGOOS_linux #cgo darwin LDFLAGS: -framework OpenAL #cgo linux LDFLAGS: -lopenal #ifdef GOOS_darwin #include #include #endif #ifdef GOOS_linux #include #endif */ import "C" import "unsafe" /* On Ubuntu 14.04 'Trusty', you may have to install these libraries: sudo apt-get install libopenal-dev */ // Enable enables a capability. func Enable(capability int32) { C.alEnable(C.ALenum(capability)) } // Disable disables a capability. func Disable(capability int32) { C.alDisable(C.ALenum(capability)) } // Enabled returns true if the specified capability is enabled. func Enabled(capability int32) bool { return C.alIsEnabled(C.ALenum(capability)) == 1 } // Vector represents an vector in a Cartesian coordinate system. type Vector [3]float32 // Orientation represents the angular position of an object in a // right-handed Cartesian coordinate system. // A cross product between the forward and up vector returns a vector // that points to the right. type Orientation struct { // Forward vector is the direction that the object is looking at. Forward Vector // Up vector represents the rotation of the object. Up Vector } func orientationFromSlice(v []float32) Orientation { return Orientation{ Forward: Vector{v[0], v[1], v[2]}, Up: Vector{v[3], v[4], v[5]}, } } func (v Orientation) slice() []float32 { return []float32{v.Forward[0], v.Forward[1], v.Forward[2], v.Up[0], v.Up[1], v.Up[2]} } func geti(param int) int32 { return int32(C.alGetInteger(C.ALenum(param))) } func getf(param int) float32 { return float32(C.alGetFloat(C.ALenum(param))) } func getString(param int) string { v := C.alGetString(C.ALenum(param)) return C.GoString((*C.char)(v)) } // DistanceModel returns the distance model. func DistanceModel() int32 { return geti(paramDistanceModel) } // SetDistanceModel sets the distance model. func SetDistanceModel(v int32) { C.alDistanceModel(C.ALenum(v)) } // DopplerFactor returns the doppler factor. func DopplerFactor() float32 { return getf(paramDopplerFactor) } // SetDopplerFactor sets the doppler factor. func SetDopplerFactor(v float32) { C.alDopplerFactor(C.ALfloat(v)) } // DopplerVelocity returns the doppler velocity. func DopplerVelocity() float32 { return getf(paramDopplerVelocity) } // SetDopplerVelocity sets the doppler velocity. func SetDopplerVelocity(v float32) { C.alDopplerVelocity(C.ALfloat(v)) } // SpeedOfSound is the speed of sound in meters per second (m/s). func SpeedOfSound() float32 { return getf(paramSpeedOfSound) } // SetSpeedOfSound sets the speed of sound, its unit should be meters per second (m/s). func SetSpeedOfSound(v float32) { C.alSpeedOfSound(C.ALfloat(v)) } // Vendor returns the vendor. func Vendor() string { return getString(paramVendor) } // Version returns the version string. func Version() string { return getString(paramVersion) } // Renderer returns the renderer information. func Renderer() string { return getString(paramRenderer) } // Extensions returns the enabled extensions. func Extensions() string { return getString(paramExtensions) } // Error returns the most recently generated error. func Error() int32 { return int32(C.alGetError()) } // Source represents an individual sound source in 3D-space. // They take PCM data, apply modifications and then submit them to // be mixed according to their spatial location. type Source uint32 // GenSources generates n new sources. These sources should be deleted // once they are not in use. func GenSources(n int) []Source { s := make([]Source, n) C.alGenSources(C.ALsizei(n), (*C.ALuint)(unsafe.Pointer(&s[0]))) return s } // PlaySources plays the sources. func PlaySources(source ...Source) { C.alSourcePlayv(C.ALsizei(len(source)), (*C.ALuint)(unsafe.Pointer(&source[0]))) } // PauseSources pauses the sources. func PauseSources(source ...Source) { C.alSourcePausev(C.ALsizei(len(source)), (*C.ALuint)(unsafe.Pointer(&source[0]))) } // StopSources stops the sources. func StopSources(source ...Source) { C.alSourceStopv(C.ALsizei(len(source)), (*C.ALuint)(unsafe.Pointer(&source[0]))) } // RewindSources rewinds the sources to their beginning positions. func RewindSources(source ...Source) { C.alSourceRewindv(C.ALsizei(len(source)), (*C.ALuint)(unsafe.Pointer(&source[0]))) } // DeleteSources deletes the sources. func DeleteSources(source ...Source) { C.alDeleteSources(C.ALsizei(len(source)), (*C.ALuint)(unsafe.Pointer(&source[0]))) } // Gain returns the source gain. func (s Source) Gain() float32 { return getSourcef(s, paramGain) } // SetGain sets the source gain. func (s Source) SetGain(v float32) { setSourcef(s, paramGain, v) } // MinGain returns the source's minimum gain setting. func (s Source) MinGain() float32 { return getSourcef(s, paramMinGain) } // SetMinGain sets the source's minimum gain setting. func (s Source) SetMinGain(v float32) { setSourcef(s, paramMinGain, v) } // MaxGain returns the source's maximum gain setting. func (s Source) MaxGain() float32 { return getSourcef(s, paramMaxGain) } // SetMaxGain sets the source's maximum gain setting. func (s Source) SetMaxGain(v float32) { setSourcef(s, paramMaxGain, v) } // Position returns the position of the source. func (s Source) Position() Vector { v := Vector{} getSourcefv(s, paramPosition, v[:]) return v } // SetPosition sets the position of the source. func (s Source) SetPosition(v Vector) { setSourcefv(s, paramPosition, v[:]) } // Velocity returns the source's velocity. func (s Source) Velocity() Vector { v := Vector{} getSourcefv(s, paramVelocity, v[:]) return v } // SetVelocity sets the source's velocity. func (s Source) SetVelocity(v Vector) { setSourcefv(s, paramVelocity, v[:]) } // Orientation returns the orientation of the source. func (s Source) Orientation() Orientation { v := make([]float32, 6) getSourcefv(s, paramOrientation, v) return orientationFromSlice(v) } // SetOrientation sets the orientation of the source. func (s Source) SetOrientation(o Orientation) { setSourcefv(s, paramOrientation, o.slice()) } // State returns the playing state of the source. func (s Source) State() int32 { return getSourcei(s, paramSourceState) } // BuffersQueued returns the number of the queued buffers. func (s Source) BuffersQueued() int32 { return getSourcei(s, paramBuffersQueued) } // BuffersProcessed returns the number of the processed buffers. func (s Source) BuffersProcessed() int32 { return getSourcei(s, paramBuffersProcessed) } // OffsetSeconds returns the current playback position of the source in seconds. func (s Source) OffsetSeconds() int32 { return getSourcei(s, paramSecOffset) } // OffsetSample returns the sample offset of the current playback position. func (s Source) OffsetSample() int32 { return getSourcei(s, paramSampleOffset) } // OffsetByte returns the byte offset of the current playback position. func (s Source) OffsetByte() int32 { return getSourcei(s, paramByteOffset) } func getSourcei(s Source, param int) int32 { var v C.ALint C.alGetSourcei(C.ALuint(s), C.ALenum(param), &v) return int32(v) } func getSourcef(s Source, param int) float32 { var v C.ALfloat C.alGetSourcef(C.ALuint(s), C.ALenum(param), &v) return float32(v) } func getSourcefv(s Source, param int, v []float32) { C.alGetSourcefv(C.ALuint(s), C.ALenum(param), (*C.ALfloat)(unsafe.Pointer(&v[0]))) } func setSourcei(s Source, param int, v int32) { C.alSourcei(C.ALuint(s), C.ALenum(param), C.ALint(v)) } func setSourcef(s Source, param int, v float32) { C.alSourcef(C.ALuint(s), C.ALenum(param), C.ALfloat(v)) } func setSourcefv(s Source, param int, v []float32) { C.alSourcefv(C.ALuint(s), C.ALenum(param), (*C.ALfloat)(unsafe.Pointer(&v[0]))) } // QueueBuffers adds the buffers to the buffer queue. func (s Source) QueueBuffers(buffers []Buffer) { C.alSourceQueueBuffers(C.ALuint(s), C.ALsizei(len(buffers)), (*C.ALuint)(unsafe.Pointer(&buffers[0]))) } // UnqueueBuffers removes the specified buffers from the buffer queue. func (s Source) UnqueueBuffers(buffers []Buffer) { C.alSourceUnqueueBuffers(C.ALuint(s), C.ALsizei(len(buffers)), (*C.ALuint)(unsafe.Pointer(&buffers[0]))) } // ListenerGain returns the total gain applied to the final mix. func ListenerGain() float32 { return getListenerf(paramGain) } // ListenerPosition returns the position of the listener. func ListenerPosition() Vector { v := Vector{} getListenerfv(paramPosition, v[:]) return v } // ListenerVelocity returns the velocity of the listener. func ListenerVelocity() Vector { v := Vector{} getListenerfv(paramVelocity, v[:]) return v } // ListenerOrientation returns the orientation of the listener. func ListenerOrientation() Orientation { v := make([]float32, 6) getListenerfv(paramOrientation, v) return orientationFromSlice(v) } // SetListenerGain sets the total gain that will be applied to the final mix. func SetListenerGain(v float32) { setListenerf(paramGain, v) } // SetListenerPosition sets the position of the listener. func SetListenerPosition(v Vector) { setListenerfv(paramPosition, v[:]) } // SetListenerVelocity sets the velocity of the listener. func SetListenerVelocity(v Vector) { setListenerfv(paramVelocity, v[:]) } // SetListenerOrientation sets the orientation of the listener. func SetListenerOrientation(v Orientation) { setListenerfv(paramOrientation, v.slice()) } func getListenerf(param int) float32 { var v C.ALfloat C.alGetListenerf(C.ALenum(param), &v) return float32(v) } func getListenerfv(param int, v []float32) { C.alGetListenerfv(C.ALenum(param), (*C.ALfloat)(unsafe.Pointer(&v[0]))) } func setListenerf(param int, v float32) { C.alListenerf(C.ALenum(param), C.ALfloat(v)) } func setListenerfv(param int, v []float32) { C.alListenerfv(C.ALenum(param), (*C.ALfloat)(unsafe.Pointer(&v[0]))) } // A buffer represents a chunk of PCM audio data that could be buffered to an audio // source. A single buffer could be shared between multiple sources. type Buffer uint32 // GenBuffers generates n new buffers. The generated buffers should be deleted // once they are no longer in use. func GenBuffers(n int) []Buffer { s := make([]Buffer, n) C.alGenBuffers(C.ALsizei(n), (*C.ALuint)(unsafe.Pointer(&s[0]))) return s } // DeleteBuffers deletes the buffers. func DeleteBuffers(buffers []Buffer) { C.alDeleteBuffers(C.ALsizei(len(buffers)), (*C.ALuint)(unsafe.Pointer(&buffers[0]))) } func getBufferi(b Buffer, param int) int32 { var v C.ALint C.alGetBufferi(C.ALuint(b), C.ALenum(param), &v) return int32(v) } // Frequency returns the frequency of the buffer data in Hertz (Hz). func (b Buffer) Frequency() int32 { return getBufferi(b, paramFreq) } // Bits return the number of bits used to represent a sample. func (b Buffer) Bits() int32 { return getBufferi(b, paramBits) } // Channels return the number of the audio channels. func (b Buffer) Channels() int32 { return getBufferi(b, paramChannels) } // Size returns the size of the data. func (b Buffer) Size() int32 { return getBufferi(b, paramSize) } // BufferData buffers PCM data to the current buffer. func (b Buffer) BufferData(format uint32, data []byte, freq int32) { C.alBufferData(C.ALuint(b), C.ALenum(format), unsafe.Pointer(&data[0]), C.ALsizei(len(data)), C.ALsizei(freq)) } // Valid returns true if the buffer exists and is valid. func (b Buffer) Valid() bool { return C.alIsBuffer(C.ALuint(b)) == 1 }