├── .gitignore ├── LICENSE ├── README └── openal ├── alcCore.go ├── buffer.go ├── core.go ├── data └── welcome.wav ├── errors.go ├── example_test.go ├── listener.go ├── local.h ├── openal_test.go ├── source.go ├── util.go ├── wrapper.c └── wrapper.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.6 2 | *.8 3 | *.o 4 | *.so 5 | *.cgo?.* 6 | _cgo_* 7 | _obj 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | OpenAL bindings for Go. 2 | ==================================== 3 | 4 | I've forked this library from https://github.com/phf/go-openal 5 | and have started changing it quite a bit from the original library. 6 | 7 | I don't have any experience with the original OpenAl libraries, so 8 | I'm going to be rearranging this a bit to fit my needs. 9 | 10 | 11 | To install simply install the openal and alc libs appropriately for 12 | your platform, or build them from scratch, then run 13 | 14 | go get -u github.com/timshannon/go-openal/ 15 | 16 | 17 | *Note, as of commit 0a4cd0b this library is no longer compatible with Go 1.3.3 and older.* 18 | -------------------------------------------------------------------------------- /openal/alcCore.go: -------------------------------------------------------------------------------- 1 | // Forked by Tim Shannon 2012 2 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // C-level binding for OpenAL's "alc" API. 7 | // 8 | // Please consider using the Go-level binding instead. 9 | // 10 | // Note that "alc" introduces the exact same types as "al" 11 | // but with different names. Check the documentation of 12 | // openal/al for more information about the mapping to 13 | // Go types. 14 | // 15 | // XXX: Sadly we have to returns pointers for both Device 16 | // and Context to avoid problems with implicit assignments 17 | // in clients. It's sad because it makes the overhead a 18 | // lot higher, each of those calls triggers an allocation. 19 | package openal 20 | 21 | //#cgo linux LDFLAGS: -lopenal 22 | //#cgo darwin LDFLAGS: -framework OpenAL 23 | //#include 24 | //#include "local.h" 25 | /* 26 | ALCdevice *walcOpenDevice(const char *devicename) { 27 | return alcOpenDevice(devicename); 28 | } 29 | const ALCchar *alcGetString( ALCdevice *device, ALCenum param ); 30 | void walcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, void *data) { 31 | alcGetIntegerv(device, param, size, data); 32 | } 33 | ALCdevice *walcCaptureOpenDevice(const char *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize) { 34 | return alcCaptureOpenDevice(devicename, frequency, format, buffersize); 35 | } 36 | ALCint walcGetInteger(ALCdevice *device, ALCenum param) { 37 | ALCint result; 38 | alcGetIntegerv(device, param, 1, &result); 39 | return result; 40 | } 41 | */ 42 | import "C" 43 | import "unsafe" 44 | 45 | const ( 46 | Frequency = 0x1007 // int Hz 47 | Refresh = 0x1008 // int Hz 48 | Sync = 0x1009 // bool 49 | MonoSources = 0x1010 // int 50 | StereoSources = 0x1011 // int 51 | ) 52 | 53 | // The Specifier string for default device? 54 | const ( 55 | DefaultDeviceSpecifier = 0x1004 56 | DeviceSpecifier = 0x1005 57 | Extensions = 0x1006 58 | ) 59 | 60 | // ? 61 | const ( 62 | MajorVersion = 0x1000 63 | MinorVersion = 0x1001 64 | ) 65 | 66 | // ? 67 | const ( 68 | AttributesSize = 0x1002 69 | AllAttributes = 0x1003 70 | ) 71 | 72 | // Capture extension 73 | const ( 74 | CaptureDeviceSpecifier = 0x310 75 | CaptureDefaultDeviceSpecifier = 0x311 76 | CaptureSamples = 0x312 77 | ) 78 | 79 | type Device struct { 80 | // Use uintptr instead of *C.ALCdevice. 81 | // On Mac OS X, this value is 0x18 and might cause crash with a raw pointer. 82 | handle uintptr 83 | } 84 | 85 | func (self *Device) getError() uint32 { 86 | return uint32(C.alcGetError((*C.struct_ALCdevice_struct)(unsafe.Pointer(self.handle)))) 87 | } 88 | 89 | // Err() returns the most recent error generated 90 | // in the AL state machine. 91 | func (self *Device) Err() error { 92 | switch code := self.getError(); code { 93 | case 0x0000: 94 | return nil 95 | case 0xA001: 96 | return ErrInvalidDevice 97 | case 0xA002: 98 | return ErrInvalidContext 99 | case 0xA003: 100 | return ErrInvalidEnum 101 | case 0xA004: 102 | return ErrInvalidValue 103 | case 0xA005: 104 | return ErrOutOfMemory 105 | default: 106 | return ErrorCode(code) 107 | } 108 | } 109 | 110 | func OpenDevice(name string) *Device { 111 | // TODO: turn empty string into nil? 112 | // TODO: what about an error return? 113 | p := C.CString(name) 114 | h := C.walcOpenDevice(p) 115 | C.free(unsafe.Pointer(p)) 116 | return &Device{uintptr((unsafe.Pointer)(h))} 117 | } 118 | 119 | func (self *Device) cHandle() *C.struct_ALCdevice_struct { 120 | return (*C.struct_ALCdevice_struct)(unsafe.Pointer(self.handle)) 121 | } 122 | 123 | func (self *Device) CloseDevice() bool { 124 | //TODO: really a method? or not? 125 | return C.alcCloseDevice(self.cHandle()) != 0 126 | } 127 | 128 | func (self *Device) CreateContext() *Context { 129 | // TODO: really a method? 130 | // TODO: attrlist support 131 | c := C.alcCreateContext(self.cHandle(), nil) 132 | return &Context{uintptr(unsafe.Pointer(c))} 133 | } 134 | 135 | func (self *Device) GetIntegerv(param uint32, size uint32) (result []int32) { 136 | result = make([]int32, size) 137 | C.walcGetIntegerv(self.cHandle(), C.ALCenum(param), C.ALCsizei(size), unsafe.Pointer(&result[0])) 138 | return 139 | } 140 | 141 | func (self *Device) GetInteger(param uint32) int32 { 142 | return int32(C.walcGetInteger(self.cHandle(), C.ALCenum(param))) 143 | } 144 | 145 | type CaptureDevice struct { 146 | Device 147 | sampleSize uint32 148 | } 149 | 150 | func CaptureOpenDevice(name string, freq uint32, format Format, size uint32) *CaptureDevice { 151 | // TODO: turn empty string into nil? 152 | // TODO: what about an error return? 153 | p := C.CString(name) 154 | h := C.walcCaptureOpenDevice(p, C.ALCuint(freq), C.ALCenum(format), C.ALCsizei(size)) 155 | C.free(unsafe.Pointer(p)) 156 | return &CaptureDevice{Device{uintptr(unsafe.Pointer(h))}, uint32(format.SampleSize())} 157 | } 158 | 159 | // XXX: Override Device.CloseDevice to make sure the correct 160 | // C function is called even if someone decides to use this 161 | // behind an interface. 162 | func (self *CaptureDevice) CloseDevice() bool { 163 | return C.alcCaptureCloseDevice(self.cHandle()) != 0 164 | } 165 | 166 | func (self *CaptureDevice) CaptureCloseDevice() bool { 167 | return self.CloseDevice() 168 | } 169 | 170 | func (self *CaptureDevice) CaptureStart() { 171 | C.alcCaptureStart(self.cHandle()) 172 | } 173 | 174 | func (self *CaptureDevice) CaptureStop() { 175 | C.alcCaptureStop(self.cHandle()) 176 | } 177 | 178 | func (self *CaptureDevice) CaptureTo(data []byte) { 179 | C.alcCaptureSamples(self.cHandle(), unsafe.Pointer(&data[0]), C.ALCsizei(uint32(len(data))/self.sampleSize)) 180 | } 181 | 182 | func (self *CaptureDevice) CaptureToInt16(data []int16) { 183 | C.alcCaptureSamples(self.cHandle(), unsafe.Pointer(&data[0]), C.ALCsizei(uint32(len(data))*2/self.sampleSize)) 184 | } 185 | 186 | func (self *CaptureDevice) CaptureMono8To(data []byte) { 187 | self.CaptureTo(data) 188 | } 189 | 190 | func (self *CaptureDevice) CaptureMono16To(data []int16) { 191 | self.CaptureToInt16(data) 192 | } 193 | 194 | func (self *CaptureDevice) CaptureStereo8To(data [][2]byte) { 195 | C.alcCaptureSamples(self.cHandle(), unsafe.Pointer(&data[0]), C.ALCsizei(uint32(len(data))*2/self.sampleSize)) 196 | } 197 | 198 | func (self *CaptureDevice) CaptureStereo16To(data [][2]int16) { 199 | C.alcCaptureSamples(self.cHandle(), unsafe.Pointer(&data[0]), C.ALCsizei(uint32(len(data))*4/self.sampleSize)) 200 | } 201 | 202 | func (self *CaptureDevice) CaptureSamples(size uint32) (data []byte) { 203 | data = make([]byte, size*self.sampleSize) 204 | self.CaptureTo(data) 205 | return 206 | } 207 | 208 | func (self *CaptureDevice) CaptureSamplesInt16(size uint32) (data []int16) { 209 | data = make([]int16, size*self.sampleSize/2) 210 | self.CaptureToInt16(data) 211 | return 212 | } 213 | 214 | func (self *CaptureDevice) CapturedSamples() (size uint32) { 215 | return uint32(self.GetInteger(CaptureSamples)) 216 | } 217 | 218 | ///// Context /////////////////////////////////////////////////////// 219 | 220 | // Context encapsulates the state of a given instance 221 | // of the OpenAL state machine. Only one context can 222 | // be active in a given process. 223 | type Context struct { 224 | // Use uintptr instead of *C.ALCcontext 225 | // On Mac OS X, this value is 0x19 and might cause crash with a raw pointer. 226 | handle uintptr 227 | } 228 | 229 | // A context that doesn't exist, useful for certain 230 | // context operations (see OpenAL documentation for 231 | // details). 232 | var NullContext Context 233 | 234 | func (self *Context) cHandle() *C.struct_ALCcontext_struct { 235 | return (*C.struct_ALCcontext_struct)(unsafe.Pointer(self.handle)) 236 | } 237 | 238 | // Renamed, was MakeContextCurrent. 239 | func (self *Context) Activate() bool { 240 | return C.alcMakeContextCurrent(self.cHandle()) != alFalse 241 | } 242 | 243 | // Renamed, was ProcessContext. 244 | func (self *Context) Process() { 245 | C.alcProcessContext(self.cHandle()) 246 | } 247 | 248 | // Renamed, was SuspendContext. 249 | func (self *Context) Suspend() { 250 | C.alcSuspendContext(self.cHandle()) 251 | } 252 | 253 | // Renamed, was DestroyContext. 254 | func (self *Context) Destroy() { 255 | C.alcDestroyContext(self.cHandle()) 256 | self.handle = uintptr(unsafe.Pointer(nil)) 257 | } 258 | 259 | // Renamed, was GetContextsDevice. 260 | func (self *Context) GetDevice() *Device { 261 | return &Device{uintptr(unsafe.Pointer(C.alcGetContextsDevice(self.cHandle())))} 262 | } 263 | 264 | // Renamed, was GetCurrentContext. 265 | func CurrentContext() *Context { 266 | return &Context{uintptr(unsafe.Pointer(C.alcGetCurrentContext()))} 267 | } 268 | -------------------------------------------------------------------------------- /openal/buffer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package openal 6 | 7 | /* 8 | #include 9 | #cgo darwin LDFLAGS: -framework OpenAL 10 | #include "local.h" 11 | #include "wrapper.h" 12 | */ 13 | import "C" 14 | import "unsafe" 15 | 16 | // Buffers are storage space for sample data. 17 | type Buffer uint32 18 | 19 | // Attributes that can be queried with Buffer.Geti(). 20 | const ( 21 | alFrequency = 0x2001 22 | alBits = 0x2002 23 | alChannels = 0x2003 24 | alSize = 0x2004 25 | ) 26 | 27 | type Buffers []Buffer 28 | 29 | // NewBuffers() creates n fresh buffers. 30 | // Renamed, was GenBuffers. 31 | func NewBuffers(n int) (buffers Buffers) { 32 | buffers = make(Buffers, n) 33 | C.walGenBuffers(C.ALsizei(n), unsafe.Pointer(&buffers[0])) 34 | return 35 | } 36 | 37 | // Delete() deletes the given buffers. 38 | func (self Buffers) Delete() { 39 | n := len(self) 40 | C.walDeleteBuffers(C.ALsizei(n), unsafe.Pointer(&self[0])) 41 | } 42 | 43 | // Renamed, was Bufferf. 44 | func (self Buffer) setf(param int32, value float32) { 45 | C.alBufferf(C.ALuint(self), C.ALenum(param), C.ALfloat(value)) 46 | } 47 | 48 | // Renamed, was Buffer3f. 49 | func (self Buffer) set3f(param int32, value1, value2, value3 float32) { 50 | C.alBuffer3f(C.ALuint(self), C.ALenum(param), C.ALfloat(value1), C.ALfloat(value2), C.ALfloat(value3)) 51 | } 52 | 53 | // Renamed, was Bufferfv. 54 | func (self Buffer) setfv(param int32, values []float32) { 55 | C.walBufferfv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 56 | } 57 | 58 | // Renamed, was Bufferi. 59 | func (self Buffer) seti(param int32, value int32) { 60 | C.alBufferi(C.ALuint(self), C.ALenum(param), C.ALint(value)) 61 | } 62 | 63 | // Renamed, was Buffer3i. 64 | func (self Buffer) set3i(param int32, value1, value2, value3 int32) { 65 | C.alBuffer3i(C.ALuint(self), C.ALenum(param), C.ALint(value1), C.ALint(value2), C.ALint(value3)) 66 | } 67 | 68 | // Renamed, was Bufferiv. 69 | func (self Buffer) setiv(param int32, values []int32) { 70 | C.walBufferiv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 71 | } 72 | 73 | // Renamed, was GetBufferf. 74 | func (self Buffer) getf(param int32) float32 { 75 | return float32(C.walGetBufferf(C.ALuint(self), C.ALenum(param))) 76 | } 77 | 78 | // Renamed, was GetBuffer3f. 79 | func (self Buffer) get3f(param int32) (value1, value2, value3 float32) { 80 | var v1, v2, v3 float32 81 | C.walGetBuffer3f(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&v1), 82 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 83 | value1, value2, value3 = v1, v2, v3 84 | return 85 | } 86 | 87 | // Renamed, was GetBufferfv. 88 | func (self Buffer) getfv(param int32, values []float32) { 89 | C.walGetBufferfv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 90 | return 91 | } 92 | 93 | // Renamed, was GetBufferi. 94 | func (self Buffer) geti(param int32) int32 { 95 | return int32(C.walGetBufferi(C.ALuint(self), C.ALenum(param))) 96 | } 97 | 98 | // Renamed, was GetBuffer3i. 99 | func (self Buffer) get3i(param int32) (value1, value2, value3 int32) { 100 | var v1, v2, v3 int32 101 | C.walGetBuffer3i(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&v1), 102 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 103 | value1, value2, value3 = v1, v2, v3 104 | return 105 | } 106 | 107 | // Renamed, was GetBufferiv. 108 | func (self Buffer) getiv(param int32, values []int32) { 109 | C.walGetBufferiv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 110 | } 111 | 112 | type Format uint32 113 | 114 | func (f Format) SampleSize() int { 115 | switch f { 116 | case FormatMono8: 117 | return 1 118 | case FormatMono16: 119 | return 2 120 | case FormatStereo8: 121 | return 2 122 | case FormatStereo16: 123 | return 4 124 | default: 125 | return 1 126 | } 127 | } 128 | 129 | // Format of sound samples passed to Buffer.SetData(). 130 | const ( 131 | FormatMono8 Format = 0x1100 132 | FormatMono16 Format = 0x1101 133 | FormatStereo8 Format = 0x1102 134 | FormatStereo16 Format = 0x1103 135 | ) 136 | 137 | // SetData() specifies the sample data the buffer should use. 138 | // For FormatMono16 and FormatStereo8 the data slice must be a 139 | // multiple of two bytes long; for FormatStereo16 the data slice 140 | // must be a multiple of four bytes long. The frequency is given 141 | // in Hz. 142 | // Renamed, was BufferData. 143 | func (self Buffer) SetData(format Format, data []byte, frequency int32) { 144 | C.alBufferData(C.ALuint(self), C.ALenum(format), unsafe.Pointer(&data[0]), 145 | C.ALsizei(len(data)), C.ALsizei(frequency)) 146 | } 147 | 148 | func (self Buffer) SetDataInt16(format Format, data []int16, frequency int32) { 149 | C.alBufferData(C.ALuint(self), C.ALenum(format), unsafe.Pointer(&data[0]), 150 | C.ALsizei(len(data)*2), C.ALsizei(frequency)) 151 | } 152 | 153 | func (self Buffer) SetDataMono8(data []byte, frequency int32) { 154 | C.alBufferData(C.ALuint(self), C.ALenum(FormatMono8), unsafe.Pointer(&data[0]), 155 | C.ALsizei(len(data)), C.ALsizei(frequency)) 156 | } 157 | 158 | func (self Buffer) SetDataMono16(data []int16, frequency int32) { 159 | C.alBufferData(C.ALuint(self), C.ALenum(FormatMono16), unsafe.Pointer(&data[0]), 160 | C.ALsizei(len(data)*2), C.ALsizei(frequency)) 161 | } 162 | 163 | func (self Buffer) SetDataStereo8(data [][2]byte, frequency int32) { 164 | C.alBufferData(C.ALuint(self), C.ALenum(FormatStereo8), unsafe.Pointer(&data[0]), 165 | C.ALsizei(len(data)*2), C.ALsizei(frequency)) 166 | } 167 | 168 | func (self Buffer) SetDataStereo16(data [][2]int16, frequency int32) { 169 | C.alBufferData(C.ALuint(self), C.ALenum(FormatStereo16), unsafe.Pointer(&data[0]), 170 | C.ALsizei(len(data)*4), C.ALsizei(frequency)) 171 | } 172 | 173 | // NewBuffer() creates a single buffer. 174 | // Convenience function, see NewBuffers(). 175 | func NewBuffer() Buffer { 176 | return Buffer(C.walGenBuffer()) 177 | } 178 | 179 | // Delete() deletes a single buffer. 180 | // Convenience function, see DeleteBuffers(). 181 | func (self Buffer) Delete() { 182 | C.walDeleteSource(C.ALuint(self)) 183 | } 184 | 185 | // GetFrequency() returns the frequency, in Hz, of the buffer's sample data. 186 | // Convenience method. 187 | func (self Buffer) GetFrequency() uint32 { 188 | return uint32(self.geti(alFrequency)) 189 | } 190 | 191 | // GetBits() returns the resolution, either 8 or 16 bits, of the buffer's sample data. 192 | // Convenience method. 193 | func (self Buffer) GetBits() uint32 { 194 | return uint32(self.geti(alBits)) 195 | } 196 | 197 | // GetChannels() returns the number of channels, either 1 or 2, of the buffer's sample data. 198 | // Convenience method. 199 | func (self Buffer) GetChannels() uint32 { 200 | return uint32(self.geti(alChannels)) 201 | } 202 | 203 | // GetSize() returns the size, in bytes, of the buffer's sample data. 204 | // Convenience method. 205 | func (self Buffer) GetSize() uint32 { 206 | return uint32(self.geti(alSize)) 207 | } 208 | -------------------------------------------------------------------------------- /openal/core.go: -------------------------------------------------------------------------------- 1 | // Forked by Tim Shannon 2012 2 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Go binding for OpenAL's "al" API. 7 | // 8 | // See http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm 9 | // for details about OpenAL not described here. 10 | // 11 | // OpenAL types are (in principle) mapped to Go types as 12 | // follows: 13 | // 14 | // ALboolean bool (al.h says char, but Go's bool should be compatible) 15 | // ALchar uint8 (although al.h suggests int8, Go's uint8 (aka byte) seems better) 16 | // ALbyte int8 (al.h says char, implying that char is signed) 17 | // ALubyte uint8 (al.h says unsigned char) 18 | // ALshort int16 19 | // ALushort uint16 20 | // ALint int32 21 | // ALuint uint32 22 | // ALsizei int32 (although that's strange, it's what OpenAL wants) 23 | // ALenum int32 (although that's strange, it's what OpenAL wants) 24 | // ALfloat float32 25 | // ALdouble float64 26 | // ALvoid not applicable (but see below) 27 | // 28 | // We also stick to these (not mentioned explicitly in 29 | // OpenAL): 30 | // 31 | // ALvoid* unsafe.Pointer (but never exported) 32 | // ALchar* string 33 | // 34 | // Finally, in places where OpenAL expects pointers to 35 | // C-style arrays, we use Go slices if appropriate: 36 | // 37 | // ALboolean* []bool 38 | // ALvoid* []byte (see Buffer.SetData() for example) 39 | // ALint* []int32 40 | // ALuint* []uint32 []Source []Buffer 41 | // ALfloat* []float32 42 | // ALdouble* []float64 43 | // 44 | // Overall, the correspondence of types hopefully feels 45 | // natural enough. Note that many of these types do not 46 | // actually occur in the API. 47 | // 48 | // The names of OpenAL constants follow the established 49 | // Go conventions: instead of AL_FORMAT_MONO16 we use 50 | // FormatMono16 for example. 51 | // 52 | // Conversion to Go's camel case notation does however 53 | // lead to name clashes between constants and functions. 54 | // For example, AL_DISTANCE_MODEL becomes DistanceModel 55 | // which collides with the OpenAL function of the same 56 | // name used to set the current distance model. We have 57 | // to rename either the constant or the function, and 58 | // since the function name seems to be at fault (it's a 59 | // setter but doesn't make that obvious), we rename the 60 | // function. 61 | // 62 | // In fact, we renamed plenty of functions, not just the 63 | // ones where collisions with constants were the driving 64 | // force. For example, instead of the Sourcef/GetSourcef 65 | // abomination, we use Getf/Setf methods on a Source type. 66 | // Everything should still be easily recognizable for 67 | // OpenAL hackers, but this structure is a lot more 68 | // sensible (and reveals that the OpenAL API is actually 69 | // not such a bad design). 70 | // 71 | // There are a few cases where constants would collide 72 | // with the names of types we introduced here. Since the 73 | // types serve a much more important function, we renamed 74 | // the constants in those cases. For example AL_BUFFER 75 | // would collide with the type Buffer so it's name is now 76 | // Buffer_ instead. Not pretty, but in many cases you 77 | // don't need the constants anyway as the functionality 78 | // they represent is probably available through one of 79 | // the convenience functions we introduced as well. For 80 | // example consider the task of attaching a buffer to a 81 | // source. In C, you'd say alSourcei(sid, AL_BUFFER, bid). 82 | // In Go, you can say sid.Seti(Buffer_, bid) as well, but 83 | // you probably want to say sid.SetBuffer(bid) instead. 84 | // 85 | // TODO: Decide on the final API design; the current state 86 | // has only specialized methods, none of the generic ones 87 | // anymore; it exposes everything (except stuff we can't 88 | // do) but I am not sure whether this is the right API for 89 | // the level we operate on. Not yet anyway. Anyone? 90 | package openal 91 | 92 | /* 93 | #cgo linux LDFLAGS: -lopenal 94 | #cgo windows LDFLAGS: -lopenal32 95 | #cgo darwin LDFLAGS: -framework OpenAL 96 | #include 97 | #include "local.h" 98 | #include "wrapper.h" 99 | */ 100 | import "C" 101 | import "unsafe" 102 | 103 | // General purpose constants. None can be used with SetDistanceModel() 104 | // to disable distance attenuation. None can be used with Source.SetBuffer() 105 | // to clear a Source of buffers. 106 | const ( 107 | None = 0 108 | alFalse = 0 109 | alTrue = 1 110 | ) 111 | 112 | // GetInteger() queries. 113 | const ( 114 | alDistanceModel = 0xD000 115 | ) 116 | 117 | // GetFloat() queries. 118 | const ( 119 | alDopplerFactor = 0xC000 120 | alDopplerVelocity = 0xC001 121 | alSpeedOfSound = 0xC003 122 | ) 123 | 124 | // GetString() queries. 125 | const ( 126 | alVendor = 0xB001 127 | alVersion = 0xB002 128 | alRenderer = 0xB003 129 | alExtensions = 0xB004 130 | ) 131 | 132 | // Shared Source/Listener properties. 133 | const ( 134 | AlPosition = 0x1004 135 | AlVelocity = 0x1006 136 | AlGain = 0x100A 137 | ) 138 | 139 | func GetString(param int32) string { 140 | return C.GoString(C.walGetString(C.ALenum(param))) 141 | } 142 | 143 | func getBoolean(param int32) bool { 144 | return C.alGetBoolean(C.ALenum(param)) != alFalse 145 | } 146 | 147 | func getInteger(param int32) int32 { 148 | return int32(C.alGetInteger(C.ALenum(param))) 149 | } 150 | 151 | func getFloat(param int32) float32 { 152 | return float32(C.alGetFloat(C.ALenum(param))) 153 | } 154 | 155 | func getDouble(param int32) float64 { 156 | return float64(C.alGetDouble(C.ALenum(param))) 157 | } 158 | 159 | // Renamed, was GetBooleanv. 160 | func getBooleans(param int32, data []bool) { 161 | C.walGetBooleanv(C.ALenum(param), unsafe.Pointer(&data[0])) 162 | } 163 | 164 | // Renamed, was GetIntegerv. 165 | func getIntegers(param int32, data []int32) { 166 | C.walGetIntegerv(C.ALenum(param), unsafe.Pointer(&data[0])) 167 | } 168 | 169 | // Renamed, was GetFloatv. 170 | func getFloats(param int32, data []float32) { 171 | C.walGetFloatv(C.ALenum(param), unsafe.Pointer(&data[0])) 172 | } 173 | 174 | // Renamed, was GetDoublev. 175 | func getDoubles(param int32, data []float64) { 176 | C.walGetDoublev(C.ALenum(param), unsafe.Pointer(&data[0])) 177 | } 178 | 179 | // GetError() returns the most recent error generated 180 | // in the AL state machine. 181 | func getError() uint32 { 182 | return uint32(C.alGetError()) 183 | } 184 | 185 | // Renamed, was DopplerFactor. 186 | func SetDopplerFactor(value float32) { 187 | C.alDopplerFactor(C.ALfloat(value)) 188 | } 189 | 190 | // Renamed, was DopplerVelocity. 191 | func SetDopplerVelocity(value float32) { 192 | C.alDopplerVelocity(C.ALfloat(value)) 193 | } 194 | 195 | // Renamed, was SpeedOfSound. 196 | func SetSpeedOfSound(value float32) { 197 | C.alSpeedOfSound(C.ALfloat(value)) 198 | } 199 | 200 | // Distance models for SetDistanceModel() and GetDistanceModel(). 201 | const ( 202 | InverseDistance = 0xD001 203 | InverseDistanceClamped = 0xD002 204 | LinearDistance = 0xD003 205 | LinearDistanceClamped = 0xD004 206 | ExponentDistance = 0xD005 207 | ExponentDistanceClamped = 0xD006 208 | ) 209 | 210 | // SetDistanceModel() changes the current distance model. 211 | // Pass "None" to disable distance attenuation. 212 | // Renamed, was DistanceModel. 213 | func SetDistanceModel(model int32) { 214 | C.alDistanceModel(C.ALenum(model)) 215 | } 216 | 217 | ///// Crap /////////////////////////////////////////////////////////// 218 | 219 | // These functions are wrapped and should work fine, but they 220 | // have no purpose: There are *no* capabilities in OpenAL 1.1 221 | // which is the latest specification. So we removed from from 222 | // the API for now, it's complicated enough without them. 223 | // 224 | //func Enable(capability int32) { 225 | // C.alEnable(C.ALenum(capability)); 226 | //} 227 | // 228 | //func Disable(capability int32) { 229 | // C.alDisable(C.ALenum(capability)); 230 | //} 231 | // 232 | //func IsEnabled(capability int32) bool { 233 | // return C.alIsEnabled(C.ALenum(capability)) != alFalse; 234 | //} 235 | 236 | // These constants are documented as "not yet exposed". We 237 | // keep them here in case they ever become valid. They are 238 | // buffer states. 239 | // 240 | //const ( 241 | // Unused = 0x2010; 242 | // Pending = 0x2011; 243 | // Processed = 0x2012; 244 | //) 245 | 246 | // These functions would work fine, but they are not very 247 | // useful since we have distinct Source and Buffer types. 248 | // Leaving them out reduces API complexity, a good thing. 249 | // 250 | //func IsSource(id uint32) bool { 251 | // return C.alIsSource(C.ALuint(id)) != alFalse; 252 | //} 253 | // 254 | //func IsBuffer(id uint32) bool { 255 | // return C.alIsBuffer(C.ALuint(id)) != alFalse; 256 | //} 257 | -------------------------------------------------------------------------------- /openal/data/welcome.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timshannon/go-openal/e0ed4c67cffe43abb9f48479938df07e8f2cf9ca/openal/data/welcome.wav -------------------------------------------------------------------------------- /openal/errors.go: -------------------------------------------------------------------------------- 1 | package openal 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | var ( 9 | ErrInvalidName = errors.New("openal: invalid name") 10 | ErrInvalidEnum = errors.New("openal: invalid enum") 11 | ErrInvalidValue = errors.New("openal: invalid value") 12 | ErrInvalidOperation = errors.New("openal: invalid operation") 13 | 14 | ErrInvalidContext = errors.New("openal: invalid context") 15 | ErrInvalidDevice = errors.New("openal: invalid device") 16 | ErrOutOfMemory = errors.New("openal: out of memory") 17 | ) 18 | 19 | type ErrorCode uint32 20 | 21 | func (e ErrorCode) Error() string { 22 | return fmt.Sprintf("openal: error code %x", uint32(e)) 23 | } 24 | 25 | // Err() returns the most recent error generated 26 | // in the AL state machine. 27 | func Err() error { 28 | switch code := getError(); code { 29 | case 0x0000: 30 | return nil 31 | case 0xA001: 32 | return ErrInvalidName 33 | case 0xA002: 34 | return ErrInvalidEnum 35 | case 0xA003: 36 | return ErrInvalidValue 37 | case 0xA004: 38 | return ErrInvalidOperation 39 | default: 40 | return ErrorCode(code) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /openal/example_test.go: -------------------------------------------------------------------------------- 1 | package openal_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/timshannon/go-openal/openal" 6 | "io/ioutil" 7 | "time" 8 | ) 9 | 10 | func ExamplePlay() { 11 | device := openal.OpenDevice("") 12 | defer device.CloseDevice() 13 | 14 | context := device.CreateContext() 15 | defer context.Destroy() 16 | context.Activate() 17 | 18 | source := openal.NewSource() 19 | defer source.Pause() 20 | source.SetLooping(false) 21 | 22 | buffer := openal.NewBuffer() 23 | 24 | if err := openal.Err(); err != nil { 25 | fmt.Println(err) 26 | return 27 | } 28 | 29 | data, err := ioutil.ReadFile("data/welcome.wav") 30 | if err != nil { 31 | fmt.Println(err) 32 | return 33 | } 34 | 35 | buffer.SetData(openal.FormatMono16, data, 44100) 36 | 37 | source.SetBuffer(buffer) 38 | source.Play() 39 | for source.State() == openal.Playing { 40 | // loop long enough to let the wave file finish 41 | time.Sleep(time.Millisecond * 100) 42 | } 43 | source.Delete() 44 | fmt.Println("sound played") 45 | // Output: sound played 46 | } 47 | 48 | func ExampleMonitor() { 49 | const ( 50 | frequency = 44100 51 | format = openal.FormatStereo16 52 | captureSize = 512 53 | buffersCount = 10 54 | ) 55 | mic := openal.CaptureOpenDevice("", frequency, format, frequency*2) 56 | mic.CaptureStart() 57 | defer mic.CloseDevice() 58 | 59 | device := openal.OpenDevice("") 60 | defer device.CloseDevice() 61 | 62 | context := device.CreateContext() 63 | context.Activate() 64 | defer context.Destroy() 65 | 66 | source := openal.NewSource() 67 | source.SetLooping(false) 68 | defer source.Stop() 69 | 70 | buffers := openal.NewBuffers(buffersCount) 71 | samples := make([]byte, captureSize*format.SampleSize()) 72 | 73 | start := time.Now() 74 | for time.Since(start) < time.Second { // play for 1 second 75 | if err := openal.Err(); err != nil { 76 | fmt.Println("error:", err) 77 | return 78 | } 79 | // Get any free buffers 80 | if prcessed := source.BuffersProcessed(); prcessed > 0 { 81 | buffersNew := make(openal.Buffers, prcessed) 82 | source.UnqueueBuffers(buffersNew) 83 | buffers = append(buffers, buffersNew...) 84 | } 85 | if len(buffers) == 0 { 86 | continue 87 | } 88 | 89 | if mic.CapturedSamples() >= captureSize { 90 | mic.CaptureTo(samples) 91 | buffer := buffers[len(buffers)-1] 92 | buffers = buffers[:len(buffers)-1] 93 | buffer.SetData(format, samples, frequency) 94 | source.QueueBuffer(buffer) 95 | 96 | // If we have enough buffers, start playing 97 | if source.State() != openal.Playing { 98 | if source.BuffersQueued() > 2 { 99 | source.Play() 100 | } 101 | } 102 | } 103 | } 104 | fmt.Println(source.State()) 105 | // Output: Playing 106 | } 107 | -------------------------------------------------------------------------------- /openal/listener.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package openal 6 | 7 | /* 8 | #include 9 | #cgo darwin LDFLAGS: -framework OpenAL 10 | #include "local.h" 11 | #include "wrapper.h" 12 | */ 13 | import "C" 14 | import "unsafe" 15 | 16 | // Listener properties. 17 | const ( 18 | AlOrientation = 0x100F 19 | ) 20 | 21 | // Listener represents the singleton receiver of 22 | // sound in 3d space. 23 | // 24 | // We "fake" this type so we can provide OpenAL 25 | // listener calls as methods. This is convenient 26 | // and makes all those calls consistent with the 27 | // way they work for Source and Buffer. You can't 28 | // make new listeners, there's only one! 29 | type Listener struct{} 30 | 31 | // Renamed, was Listenerf. 32 | func (self Listener) Setf(param int32, value float32) { 33 | C.alListenerf(C.ALenum(param), C.ALfloat(value)) 34 | } 35 | 36 | // Renamed, was Listener3f. 37 | func (self Listener) Set3f(param int32, value1, value2, value3 float32) { 38 | C.alListener3f(C.ALenum(param), C.ALfloat(value1), C.ALfloat(value2), C.ALfloat(value3)) 39 | } 40 | 41 | // Renamed, was Listenerfv. 42 | func (self Listener) Setfv(param int32, values []float32) { 43 | C.walListenerfv(C.ALenum(param), unsafe.Pointer(&values[0])) 44 | } 45 | 46 | // Renamed, was Listeneri. 47 | func (self Listener) Seti(param int32, value int32) { 48 | C.alListeneri(C.ALenum(param), C.ALint(value)) 49 | } 50 | 51 | // Renamed, was Listener3i. 52 | func (self Listener) Set3i(param int32, value1, value2, value3 int32) { 53 | C.alListener3i(C.ALenum(param), C.ALint(value1), C.ALint(value2), C.ALint(value3)) 54 | } 55 | 56 | // Renamed, was Listeneriv. 57 | func (self Listener) Setiv(param int32, values []int32) { 58 | C.walListeneriv(C.ALenum(param), unsafe.Pointer(&values[0])) 59 | } 60 | 61 | // Renamed, was GetListenerf. 62 | func (self Listener) Getf(param int32) float32 { 63 | return float32(C.walGetListenerf(C.ALenum(param))) 64 | } 65 | 66 | // Renamed, was GetListener3f. 67 | func (self Listener) Get3f(param int32) (v1, v2, v3 float32) { 68 | C.walGetListener3f(C.ALenum(param), unsafe.Pointer(&v1), 69 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 70 | return 71 | } 72 | 73 | // Renamed, was GetListenerfv. 74 | func (self Listener) Getfv(param int32, values []float32) { 75 | C.walGetListenerfv(C.ALenum(param), unsafe.Pointer(&values[0])) 76 | return 77 | } 78 | 79 | // Renamed, was GetListeneri. 80 | func (self Listener) Geti(param int32) int32 { 81 | return int32(C.walGetListeneri(C.ALenum(param))) 82 | } 83 | 84 | // Renamed, was GetListener3i. 85 | func (self Listener) Get3i(param int32) (v1, v2, v3 int32) { 86 | C.walGetListener3i(C.ALenum(param), unsafe.Pointer(&v1), 87 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 88 | return 89 | } 90 | 91 | // Renamed, was GetListeneriv. 92 | func (self Listener) Getiv(param int32, values []int32) { 93 | C.walGetListeneriv(C.ALenum(param), unsafe.Pointer(&values[0])) 94 | } 95 | 96 | ///// Convenience //////////////////////////////////////////////////// 97 | 98 | // Convenience method, see Listener.Setf(). 99 | func (self Listener) SetGain(gain float32) { 100 | self.Setf(AlGain, gain) 101 | } 102 | 103 | // Convenience method, see Listener.Getf(). 104 | func (self Listener) GetGain() (gain float32) { 105 | return self.Getf(AlGain) 106 | } 107 | 108 | // Convenience method, see Listener.Setfv(). 109 | func (self Listener) SetPosition(vector *Vector) { 110 | self.Set3f(AlPosition, vector[x], vector[y], vector[z]) 111 | } 112 | 113 | // Convenience method, see Listener.Getfv(). 114 | func (self Listener) GetPosition(result *Vector) { 115 | result[x], result[y], result[z] = self.Get3f(AlPosition) 116 | } 117 | 118 | // Convenience method, see Listener.Setfv(). 119 | func (self Listener) SetVelocity(vector *Vector) { 120 | self.Set3f(AlVelocity, vector[x], vector[y], vector[z]) 121 | } 122 | 123 | // Convenience method, see Listener.Getfv(). 124 | func (self Listener) GetVelocity(result *Vector) { 125 | result[x], result[y], result[z] = self.Get3f(AlVelocity) 126 | } 127 | 128 | // Convenience method, see Listener.Setfv(). 129 | func (self Listener) SetOrientation(at *Vector, up *Vector) { 130 | tempSlice[0] = at[x] 131 | tempSlice[1] = at[y] 132 | tempSlice[2] = at[z] 133 | tempSlice[3] = up[x] 134 | tempSlice[4] = up[y] 135 | tempSlice[5] = up[z] 136 | self.Setfv(AlOrientation, tempSlice) 137 | } 138 | 139 | // Convenience method, see Listener.Getfv(). 140 | func (self Listener) GetOrientation(resultAt, resultUp *Vector) { 141 | self.Getfv(AlOrientation, tempSlice) 142 | resultAt[x] = tempSlice[0] 143 | resultAt[y] = tempSlice[1] 144 | resultAt[z] = tempSlice[2] 145 | resultUp[x] = tempSlice[3] 146 | resultUp[y] = tempSlice[4] 147 | resultUp[z] = tempSlice[5] 148 | } 149 | -------------------------------------------------------------------------------- /openal/local.h: -------------------------------------------------------------------------------- 1 | #ifdef __APPLE__ 2 | #include 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | -------------------------------------------------------------------------------- /openal/openal_test.go: -------------------------------------------------------------------------------- 1 | package openal_test 2 | 3 | import ( 4 | "github.com/timshannon/go-openal/openal" 5 | "testing" 6 | ) 7 | 8 | func TestGetVendor(t *testing.T) { 9 | device := openal.OpenDevice("") 10 | defer device.CloseDevice() 11 | 12 | context := device.CreateContext() 13 | defer context.Destroy() 14 | context.Activate() 15 | 16 | vendor := openal.GetVendor() 17 | 18 | if err := openal.Err(); err != nil { 19 | t.Fatal(err) 20 | } else if vendor == "" { 21 | t.Fatal("empty vendor returned") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /openal/source.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package openal 6 | 7 | /* 8 | #include 9 | #cgo darwin LDFLAGS: -framework OpenAL 10 | #include "local.h" 11 | #include "wrapper.h" 12 | */ 13 | import "C" 14 | import ( 15 | "fmt" 16 | "unsafe" 17 | ) 18 | 19 | type State int32 20 | 21 | func (s State) String() string { 22 | switch s { 23 | case Initial: 24 | return "Initial" 25 | case Playing: 26 | return "Playing" 27 | case Paused: 28 | return "Paused" 29 | case Stopped: 30 | return "Stopped" 31 | default: 32 | return fmt.Sprintf("%x", int32(s)) 33 | } 34 | } 35 | 36 | // Results from Source.State() query. 37 | const ( 38 | Initial State = 0x1011 39 | Playing State = 0x1012 40 | Paused State = 0x1013 41 | Stopped State = 0x1014 42 | ) 43 | 44 | // Results from Source.Type() query. 45 | const ( 46 | Static = 0x1028 47 | Streaming = 0x1029 48 | Undetermined = 0x1030 49 | ) 50 | 51 | // TODO: Source properties. 52 | // Regardless of what your al.h header may claim, Pitch 53 | // only applies to Sources, not to Listeners. And I got 54 | // that from Chris Robinson himself. 55 | const ( 56 | AlSourceRelative = 0x202 57 | AlConeInnerAngle = 0x1001 58 | AlConeOuterAngle = 0x1002 59 | AlPitch = 0x1003 60 | AlDirection = 0x1005 61 | AlLooping = 0x1007 62 | AlBuffer = 0x1009 63 | AlMinGain = 0x100D 64 | AlMaxGain = 0x100E 65 | AlReferenceDistance = 0x1020 66 | AlRolloffFactor = 0x1021 67 | AlConeOuterGain = 0x1022 68 | AlMaxDistance = 0x1023 69 | AlSecOffset = 0x1024 70 | AlSampleOffset = 0x1025 71 | AlByteOffset = 0x1026 72 | ) 73 | 74 | // Sources represent sound emitters in 3d space. 75 | type Source uint32 76 | 77 | type Sources []Source 78 | 79 | // NewSources() creates n sources. 80 | // Renamed, was GenSources. 81 | func NewSources(n int) (sources Sources) { 82 | sources = make(Sources, n) 83 | C.walGenSources(C.ALsizei(n), unsafe.Pointer(&sources[0])) 84 | return 85 | } 86 | 87 | // Delete deletes the sources. 88 | func (self Sources) Delete() { 89 | n := len(self) 90 | C.walDeleteSources(C.ALsizei(n), unsafe.Pointer(&self[0])) 91 | } 92 | 93 | // Renamed, was SourcePlayv. 94 | func (self Sources) Play() { 95 | C.walSourcePlayv(C.ALsizei(len(self)), unsafe.Pointer(&self[0])) 96 | } 97 | 98 | // Renamed, was SourceStopv. 99 | func (self Sources) Stop() { 100 | C.walSourceStopv(C.ALsizei(len(self)), unsafe.Pointer(&self[0])) 101 | } 102 | 103 | // Renamed, was SourceRewindv. 104 | func (self Sources) Rewind() { 105 | C.walSourceRewindv(C.ALsizei(len(self)), unsafe.Pointer(&self[0])) 106 | } 107 | 108 | // Renamed, was SourcePausev. 109 | func (self Sources) Pause() { 110 | C.walSourcePausev(C.ALsizei(len(self)), unsafe.Pointer(&self[0])) 111 | } 112 | 113 | // Renamed, was Sourcef. 114 | func (self Source) Setf(param int32, value float32) { 115 | C.alSourcef(C.ALuint(self), C.ALenum(param), C.ALfloat(value)) 116 | } 117 | 118 | // Renamed, was Source3f. 119 | func (self Source) Set3f(param int32, value1, value2, value3 float32) { 120 | C.alSource3f(C.ALuint(self), C.ALenum(param), C.ALfloat(value1), C.ALfloat(value2), C.ALfloat(value3)) 121 | } 122 | 123 | // Renamed, was Sourcefv. 124 | func (self Source) Setfv(param int32, values []float32) { 125 | C.walSourcefv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 126 | } 127 | 128 | // Renamed, was Sourcei. 129 | func (self Source) Seti(param int32, value int32) { 130 | C.alSourcei(C.ALuint(self), C.ALenum(param), C.ALint(value)) 131 | } 132 | 133 | // Renamed, was Source3i. 134 | func (self Source) Set3i(param int32, value1, value2, value3 int32) { 135 | C.alSource3i(C.ALuint(self), C.ALenum(param), C.ALint(value1), C.ALint(value2), C.ALint(value3)) 136 | } 137 | 138 | // Renamed, was Sourceiv. 139 | func (self Source) Setiv(param int32, values []int32) { 140 | C.walSourceiv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 141 | } 142 | 143 | // Renamed, was GetSourcef. 144 | func (self Source) Getf(param int32) float32 { 145 | return float32(C.walGetSourcef(C.ALuint(self), C.ALenum(param))) 146 | } 147 | 148 | // Renamed, was GetSource3f. 149 | func (self Source) Get3f(param int32) (v1, v2, v3 float32) { 150 | C.walGetSource3f(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&v1), 151 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 152 | return 153 | } 154 | 155 | // Renamed, was GetSourcefv. 156 | func (self Source) Getfv(param int32, values []float32) { 157 | C.walGetSourcefv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 158 | } 159 | 160 | // Renamed, was GetSourcei. 161 | func (self Source) Geti(param int32) int32 { 162 | return int32(C.walGetSourcei(C.ALuint(self), C.ALenum(param))) 163 | } 164 | 165 | // Renamed, was GetSource3i. 166 | func (self Source) Get3i(param int32) (v1, v2, v3 int32) { 167 | C.walGetSource3i(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&v1), 168 | unsafe.Pointer(&v2), unsafe.Pointer(&v3)) 169 | return 170 | } 171 | 172 | // Renamed, was GetSourceiv. 173 | func (self Source) Getiv(param int32, values []int32) { 174 | C.walGetSourceiv(C.ALuint(self), C.ALenum(param), unsafe.Pointer(&values[0])) 175 | } 176 | 177 | // Delete deletes the source. 178 | // Convenience function, see DeleteSources(). 179 | func (self Source) Delete() { 180 | C.walDeleteSource(C.ALuint(self)) 181 | } 182 | 183 | // Renamed, was SourcePlay. 184 | func (self Source) Play() { 185 | C.alSourcePlay(C.ALuint(self)) 186 | } 187 | 188 | // Renamed, was SourceStop. 189 | func (self Source) Stop() { 190 | C.alSourceStop(C.ALuint(self)) 191 | } 192 | 193 | // Renamed, was SourceRewind. 194 | func (self Source) Rewind() { 195 | C.alSourceRewind(C.ALuint(self)) 196 | } 197 | 198 | // Renamed, was SourcePause. 199 | func (self Source) Pause() { 200 | C.alSourcePause(C.ALuint(self)) 201 | } 202 | 203 | // Renamed, was SourceQueueBuffers. 204 | func (self Source) QueueBuffers(buffers Buffers) { 205 | C.walSourceQueueBuffers(C.ALuint(self), C.ALsizei(len(buffers)), unsafe.Pointer(&buffers[0])) 206 | } 207 | 208 | // Renamed, was SourceUnqueueBuffers. 209 | func (self Source) UnqueueBuffers(buffers Buffers) { 210 | C.walSourceUnqueueBuffers(C.ALuint(self), C.ALsizei(len(buffers)), unsafe.Pointer(&buffers[0])) 211 | } 212 | 213 | ///// Convenience //////////////////////////////////////////////////// 214 | 215 | // NewSource() creates a single source. 216 | // Convenience function, see NewSources(). 217 | func NewSource() Source { 218 | return Source(C.walGenSource()) 219 | } 220 | 221 | // Convenience method, see Source.QueueBuffers(). 222 | func (self Source) QueueBuffer(buffer Buffer) { 223 | C.walSourceQueueBuffer(C.ALuint(self), C.ALuint(buffer)) 224 | } 225 | 226 | // Convenience method, see Source.QueueBuffers(). 227 | func (self Source) UnqueueBuffer() Buffer { 228 | return Buffer(C.walSourceUnqueueBuffer(C.ALuint(self))) 229 | } 230 | 231 | // Source queries. 232 | // TODO: SourceType isn't documented as a query in the 233 | // al.h header, but it is documented that way in 234 | // the OpenAL 1.1 specification. 235 | const ( 236 | AlSourceState = 0x1010 237 | AlBuffersQueued = 0x1015 238 | AlBuffersProcessed = 0x1016 239 | AlSourceType = 0x1027 240 | ) 241 | 242 | // Convenience method, see Source.Geti(). 243 | func (self Source) BuffersQueued() int32 { 244 | return self.Geti(AlBuffersQueued) 245 | } 246 | 247 | // Convenience method, see Source.Geti(). 248 | func (self Source) BuffersProcessed() int32 { 249 | return self.Geti(AlBuffersProcessed) 250 | } 251 | 252 | // Convenience method, see Source.Geti(). 253 | func (self Source) State() State { 254 | return State(self.Geti(AlSourceState)) 255 | } 256 | 257 | // Convenience method, see Source.Geti(). 258 | func (self Source) Type() int32 { 259 | return self.Geti(AlSourceType) 260 | } 261 | 262 | // Convenience method, see Source.Getf(). 263 | func (self Source) GetGain() (gain float32) { 264 | return self.Getf(AlGain) 265 | } 266 | 267 | // Convenience method, see Source.Setf(). 268 | func (self Source) SetGain(gain float32) { 269 | self.Setf(AlGain, gain) 270 | } 271 | 272 | // Convenience method, see Source.Getf(). 273 | func (self Source) GetMinGain() (gain float32) { 274 | return self.Getf(AlMinGain) 275 | } 276 | 277 | // Convenience method, see Source.Setf(). 278 | func (self Source) SetMinGain(gain float32) { 279 | self.Setf(AlMinGain, gain) 280 | } 281 | 282 | // Convenience method, see Source.Getf(). 283 | func (self Source) GetMaxGain() (gain float32) { 284 | return self.Getf(AlMaxGain) 285 | } 286 | 287 | // Convenience method, see Source.Setf(). 288 | func (self Source) SetMaxGain(gain float32) { 289 | self.Setf(AlMaxGain, gain) 290 | } 291 | 292 | // Convenience method, see Source.Getf(). 293 | func (self Source) GetReferenceDistance() (distance float32) { 294 | return self.Getf(AlReferenceDistance) 295 | } 296 | 297 | // Convenience method, see Source.Setf(). 298 | func (self Source) SetReferenceDistance(distance float32) { 299 | self.Setf(AlReferenceDistance, distance) 300 | } 301 | 302 | // Convenience method, see Source.Getf(). 303 | func (self Source) GetMaxDistance() (distance float32) { 304 | return self.Getf(AlMaxDistance) 305 | } 306 | 307 | // Convenience method, see Source.Setf(). 308 | func (self Source) SetMaxDistance(distance float32) { 309 | self.Setf(AlMaxDistance, distance) 310 | } 311 | 312 | // Convenience method, see Source.Getf(). 313 | func (self Source) GetPitch() float32 { 314 | return self.Getf(AlPitch) 315 | } 316 | 317 | // Convenience method, see Source.Setf(). 318 | func (self Source) SetPitch(pitch float32) { 319 | self.Setf(AlPitch, pitch) 320 | } 321 | 322 | // Convenience method, see Source.Getf(). 323 | func (self Source) GetRolloffFactor() (gain float32) { 324 | return self.Getf(AlRolloffFactor) 325 | } 326 | 327 | // Convenience method, see Source.Setf(). 328 | func (self Source) SetRolloffFactor(gain float32) { 329 | self.Setf(AlRolloffFactor, gain) 330 | } 331 | 332 | // Convenience method, see Source.Geti(). 333 | func (self Source) GetLooping() bool { 334 | return self.Geti(AlLooping) != alFalse 335 | } 336 | 337 | var bool2al map[bool]int32 = map[bool]int32{true: alTrue, false: alFalse} 338 | 339 | // Convenience method, see Source.Seti(). 340 | func (self Source) SetLooping(yes bool) { 341 | self.Seti(AlLooping, bool2al[yes]) 342 | } 343 | 344 | // Convenience method, see Source.Geti(). 345 | func (self Source) GetSourceRelative() bool { 346 | return self.Geti(AlSourceRelative) != alFalse 347 | } 348 | 349 | // Convenience method, see Source.Seti(). 350 | func (self Source) SetSourceRelative(yes bool) { 351 | self.Seti(AlSourceRelative, bool2al[yes]) 352 | } 353 | 354 | // Convenience method, see Source.Setfv(). 355 | func (self Source) SetPosition(vector *Vector) { 356 | self.Set3f(AlPosition, vector[x], vector[y], vector[z]) 357 | } 358 | 359 | // Convenience method, see Source.Getfv(). 360 | func (self Source) GetPosition(result *Vector) { 361 | result[x], result[y], result[z] = self.Get3f(AlPosition) 362 | } 363 | 364 | // Convenience method, see Source.Setfv(). 365 | func (self Source) SetDirection(vector *Vector) { 366 | self.Set3f(AlDirection, vector[x], vector[y], vector[z]) 367 | } 368 | 369 | // Convenience method, see Source.Getfv(). 370 | func (self Source) GetDirection(result *Vector) { 371 | result[x], result[y], result[z] = self.Get3f(AlDirection) 372 | } 373 | 374 | // Convenience method, see Source.Setfv(). 375 | func (self Source) SetVelocity(vector *Vector) { 376 | self.Set3f(AlVelocity, vector[x], vector[y], vector[z]) 377 | } 378 | 379 | // Convenience method, see Source.Getfv(). 380 | func (self Source) GetVelocity(result *Vector) { 381 | result[x], result[y], result[z] = self.Get3f(AlVelocity) 382 | } 383 | 384 | // Convenience method, see Source.Getf(). 385 | func (self Source) GetOffsetSeconds() float32 { 386 | return self.Getf(AlSecOffset) 387 | } 388 | 389 | // Convenience method, see Source.Setf(). 390 | func (self Source) SetOffsetSeconds(offset float32) { 391 | self.Setf(AlSecOffset, offset) 392 | } 393 | 394 | // Convenience method, see Source.Geti(). 395 | func (self Source) GetOffsetSamples() int32 { 396 | return self.Geti(AlSampleOffset) 397 | } 398 | 399 | // Convenience method, see Source.Seti(). 400 | func (self Source) SetOffsetSamples(offset int32) { 401 | self.Seti(AlSampleOffset, offset) 402 | } 403 | 404 | // Convenience method, see Source.Geti(). 405 | func (self Source) GetOffsetBytes() int32 { 406 | return self.Geti(AlByteOffset) 407 | } 408 | 409 | // Convenience method, see Source.Seti(). 410 | func (self Source) SetOffsetBytes(offset int32) { 411 | self.Seti(AlByteOffset, offset) 412 | } 413 | 414 | // Convenience method, see Source.Getf(). 415 | func (self Source) GetInnerAngle() float32 { 416 | return self.Getf(AlConeInnerAngle) 417 | } 418 | 419 | // Convenience method, see Source.Setf(). 420 | func (self Source) SetInnerAngle(offset float32) { 421 | self.Setf(AlConeInnerAngle, offset) 422 | } 423 | 424 | // Convenience method, see Source.Getf(). 425 | func (self Source) GetOuterAngle() float32 { 426 | return self.Getf(AlConeOuterAngle) 427 | } 428 | 429 | // Convenience method, see Source.Setf(). 430 | func (self Source) SetOuterAngle(offset float32) { 431 | self.Setf(AlConeOuterAngle, offset) 432 | } 433 | 434 | // Convenience method, see Source.Getf(). 435 | func (self Source) GetOuterGain() float32 { 436 | return self.Getf(AlConeOuterGain) 437 | } 438 | 439 | // Convenience method, see Source.Setf(). 440 | func (self Source) SetOuterGain(offset float32) { 441 | self.Setf(AlConeOuterGain, offset) 442 | } 443 | 444 | // Convenience method, see Source.Geti(). 445 | func (self Source) SetBuffer(buffer Buffer) { 446 | self.Seti(AlBuffer, int32(buffer)) 447 | } 448 | 449 | // Convenience method, see Source.Geti(). 450 | func (self Source) GetBuffer() (buffer Buffer) { 451 | return Buffer(self.Geti(AlBuffer)) 452 | } 453 | -------------------------------------------------------------------------------- /openal/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Convenience functions in pure Go. 6 | // 7 | // Not all convenience functions are here: those that need 8 | // to call C code have to be in core.go instead due to cgo 9 | // limitations, while those that are methods have to be in 10 | // core.go due to language limitations. They should all be 11 | // here of course, at least conceptually. 12 | 13 | package openal 14 | 15 | import "strings" 16 | 17 | // Convenience Interface. 18 | type Vector [3]float32 19 | 20 | var tempSlice = make([]float32, 6) 21 | 22 | const ( 23 | x = iota 24 | y 25 | z 26 | ) 27 | 28 | // Convenience function, see GetInteger(). 29 | func GetDistanceModel() int32 { 30 | return getInteger(alDistanceModel) 31 | } 32 | 33 | // Convenience function, see GetFloat(). 34 | func GetDopplerFactor() float32 { 35 | return getFloat(alDopplerFactor) 36 | } 37 | 38 | // Convenience function, see GetFloat(). 39 | func GetDopplerVelocity() float32 { 40 | return getFloat(alDopplerVelocity) 41 | } 42 | 43 | // Convenience function, see GetFloat(). 44 | func GetSpeedOfSound() float32 { 45 | return getFloat(alSpeedOfSound) 46 | } 47 | 48 | // Convenience function, see GetString(). 49 | func GetVendor() string { 50 | return GetString(alVendor) 51 | } 52 | 53 | // Convenience function, see GetString(). 54 | func GetVersion() string { 55 | return GetString(alVersion) 56 | } 57 | 58 | // Convenience function, see GetString(). 59 | func GetRenderer() string { 60 | return GetString(alRenderer) 61 | } 62 | 63 | // Convenience function, see GetString(). 64 | func GetExtensions() string { 65 | return GetString(alExtensions) 66 | } 67 | 68 | func GetExtensionsSlice() []string { 69 | return strings.Split(GetExtensions(), " ") 70 | } 71 | 72 | func IsExtensionPresent(ext string) bool { 73 | return strings.Index(GetExtensions(), ext) >= 0 74 | } 75 | -------------------------------------------------------------------------------- /openal/wrapper.c: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #include "local.h" 6 | #include "wrapper.h" 7 | 8 | const char *walGetString(ALenum param) { 9 | return alGetString(param); 10 | } 11 | 12 | void walGetBooleanv(ALenum param, void* data) { 13 | alGetBooleanv(param, data); 14 | } 15 | 16 | void walGetIntegerv(ALenum param, void* data) { 17 | alGetIntegerv(param, data); 18 | } 19 | 20 | void walGetFloatv(ALenum param, void* data) { 21 | alGetFloatv(param, data); 22 | } 23 | 24 | void walGetDoublev(ALenum param, void* data) { 25 | alGetDoublev(param, data); 26 | } 27 | 28 | // Listeners 29 | 30 | void walListenerfv(ALenum param, const void* values) { 31 | alListenerfv(param, values); 32 | } 33 | 34 | void walListeneriv(ALenum param, const void* values) { 35 | alListeneriv(param, values); 36 | } 37 | 38 | ALfloat walGetListenerf(ALenum param) { 39 | ALfloat result; 40 | alGetListenerf(param, &result); 41 | return result; 42 | } 43 | 44 | void walGetListener3f(ALenum param, void *value1, void *value2, void *value3) { 45 | alGetListener3f(param, value1, value2, value3); 46 | } 47 | 48 | void walGetListenerfv(ALenum param, void* values) { 49 | alGetListenerfv(param, values); 50 | } 51 | 52 | ALint walGetListeneri(ALenum param) { 53 | ALint result; 54 | alGetListeneri(param, &result); 55 | return result; 56 | } 57 | 58 | void walGetListener3i(ALenum param, void *value1, void *value2, void *value3) { 59 | alGetListener3i(param, value1, value2, value3); 60 | } 61 | 62 | void walGetListeneriv(ALenum param, void* values) { 63 | alGetListeneriv(param, values); 64 | } 65 | 66 | // Sources 67 | 68 | void walGenSources(ALsizei n, void *sources) { 69 | alGenSources(n, sources); 70 | } 71 | 72 | void walDeleteSources(ALsizei n, const void *sources) { 73 | alDeleteSources(n, sources); 74 | } 75 | 76 | void walSourcefv(ALuint sid, ALenum param, const void* values) { 77 | alSourcefv(sid, param, values); 78 | } 79 | 80 | void walSourceiv(ALuint sid, ALenum param, const void* values) { 81 | alSourceiv(sid, param, values); 82 | } 83 | 84 | ALfloat walGetSourcef(ALuint sid, ALenum param) { 85 | ALfloat result; 86 | alGetSourcef(sid, param, &result); 87 | return result; 88 | } 89 | 90 | void walGetSource3f(ALuint sid, ALenum param, void *value1, void *value2, void *value3) { 91 | alGetSource3f(sid, param, value1, value2, value3); 92 | } 93 | 94 | void walGetSourcefv(ALuint sid, ALenum param, void* values) { 95 | alGetSourcefv(sid, param, values); 96 | } 97 | 98 | ALint walGetSourcei(ALuint sid, ALenum param) { 99 | ALint result; 100 | alGetSourcei(sid, param, &result); 101 | return result; 102 | } 103 | 104 | void walGetSource3i(ALuint sid, ALenum param, void *value1, void *value2, void *value3) { 105 | alGetSource3i(sid, param, value1, value2, value3); 106 | } 107 | 108 | void walGetSourceiv(ALuint sid, ALenum param, void* values) { 109 | alGetSourceiv(sid, param, values); 110 | } 111 | 112 | void walSourcePlayv(ALsizei ns, const void *sids) { 113 | alSourcePlayv(ns, sids); 114 | } 115 | 116 | void walSourceStopv(ALsizei ns, const void *sids) { 117 | alSourceStopv(ns, sids); 118 | } 119 | 120 | void walSourceRewindv(ALsizei ns, const void *sids) { 121 | alSourceRewindv(ns, sids); 122 | } 123 | 124 | void walSourcePausev(ALsizei ns, const void *sids) { 125 | alSourcePausev(ns, sids); 126 | } 127 | 128 | void walSourceQueueBuffers(ALuint sid, ALsizei numEntries, const void *bids) { 129 | alSourceQueueBuffers(sid, numEntries, bids); 130 | } 131 | 132 | void walSourceUnqueueBuffers(ALuint sid, ALsizei numEntries, void *bids) { 133 | alSourceUnqueueBuffers(sid, numEntries, bids); 134 | } 135 | 136 | // Buffers 137 | 138 | void walGenBuffers(ALsizei n, void *buffers) { 139 | alGenBuffers(n, buffers); 140 | } 141 | 142 | void walDeleteBuffers(ALsizei n, const void *buffers) { 143 | alDeleteBuffers(n, buffers); 144 | } 145 | 146 | void walBufferfv(ALuint bid, ALenum param, const void* values) { 147 | alBufferfv(bid, param, values); 148 | } 149 | 150 | void walBufferiv(ALuint bid, ALenum param, const void* values) { 151 | alBufferiv(bid, param, values); 152 | } 153 | 154 | ALfloat walGetBufferf(ALuint bid, ALenum param) { 155 | ALfloat result; 156 | alGetBufferf(bid, param, &result); 157 | return result; 158 | } 159 | 160 | void walGetBuffer3f(ALuint bid, ALenum param, void *value1, void *value2, void *value3) { 161 | alGetBuffer3f(bid, param, value1, value2, value3); 162 | } 163 | 164 | void walGetBufferfv(ALuint bid, ALenum param, void* values) { 165 | alGetBufferfv(bid, param, values); 166 | } 167 | 168 | ALint walGetBufferi(ALuint bid, ALenum param) { 169 | ALint result; 170 | alGetBufferi(bid, param, &result); 171 | return result; 172 | } 173 | 174 | void walGetBuffer3i(ALuint bid, ALenum param, void *value1, void *value2, void *value3) { 175 | alGetBuffer3i(bid, param, value1, value2, value3); 176 | } 177 | 178 | void walGetBufferiv(ALuint bid, ALenum param, void* values) { 179 | alGetBufferiv(bid, param, values); 180 | } 181 | 182 | // Singulars 183 | 184 | ALuint walGenSource(void) { 185 | ALuint source; 186 | alGenSources(1, &source); 187 | return source; 188 | } 189 | 190 | void walDeleteSource(ALuint source) { 191 | alDeleteSources(1, &source); 192 | } 193 | 194 | ALuint walGenBuffer(void) { 195 | ALuint buffer; 196 | alGenBuffers(1, &buffer); 197 | return buffer; 198 | } 199 | 200 | void walDeleteBuffer(ALuint buffer) { 201 | alDeleteBuffers(1, &buffer); 202 | } 203 | 204 | void walSourceQueueBuffer(ALuint sid, ALuint bid) { 205 | alSourceQueueBuffers(sid, 1, &bid); 206 | } 207 | 208 | ALuint walSourceUnqueueBuffer(ALuint sid) { 209 | ALuint result; 210 | alSourceUnqueueBuffers(sid, 1, &result); 211 | return result; 212 | } 213 | -------------------------------------------------------------------------------- /openal/wrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef _GO_WRAPPER_AL_ 2 | #define _GO_WRAPPER_AL_ 3 | 4 | // Copyright 2009 Peter H. Froehlich. All rights reserved. 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file. 7 | 8 | // It's sad but the OpenAL C API uses lots and lots of typedefs 9 | // that require wrapper functions (using basic C types) for cgo 10 | // to grok them. So there's a lot more C code here than I would 11 | // like... 12 | 13 | const char *walGetString(ALenum param); 14 | void walGetBooleanv(ALenum param, void* data); 15 | void walGetIntegerv(ALenum param, void* data); 16 | void walGetFloatv(ALenum param, void* data); 17 | void walGetDoublev(ALenum param, void* data); 18 | 19 | // We don't define wrappers for these because we have 20 | // no clue how to make Go grok C function pointers at 21 | // runtime. So for now, OpenAL extensions can not be 22 | // used from Go. If you have an idea for how to make 23 | // it work, be sure to email! I suspect we'd need a 24 | // mechanism for generating cgo-style stubs at runtime, 25 | // sounds like work. 26 | // 27 | // ALboolean alIsExtensionPresent( const ALchar* extname ); 28 | // void* alGetProcAddress( const ALchar* fname ); 29 | // ALenum alGetEnumValue( const ALchar* ename ); 30 | 31 | // Listeners 32 | 33 | void walListenerfv(ALenum param, const void* values); 34 | void walListeneriv(ALenum param, const void* values); 35 | ALfloat walGetListenerf(ALenum param); 36 | void walGetListener3f(ALenum param, void *value1, void *value2, void *value3); 37 | void walGetListenerfv(ALenum param, void* values); 38 | ALint walGetListeneri(ALenum param); 39 | void walGetListener3i(ALenum param, void *value1, void *value2, void *value3); 40 | void walGetListeneriv(ALenum param, void* values); 41 | 42 | // Sources 43 | 44 | void walGenSources(ALsizei n, void *sources); 45 | void walDeleteSources(ALsizei n, const void *sources); 46 | void walSourcefv(ALuint sid, ALenum param, const void* values); 47 | void walSourceiv(ALuint sid, ALenum param, const void* values); 48 | ALfloat walGetSourcef(ALuint sid, ALenum param); 49 | void walGetSource3f(ALuint sid, ALenum param, void *value1, void *value2, void *value3); 50 | void walGetSourcefv(ALuint sid, ALenum param, void* values); 51 | ALint walGetSourcei(ALuint sid, ALenum param); 52 | void walGetSource3i(ALuint sid, ALenum param, void *value1, void *value2, void *value3); 53 | void walGetSourceiv(ALuint sid, ALenum param, void* values); 54 | void walSourcePlayv(ALsizei ns, const void *sids); 55 | void walSourceStopv(ALsizei ns, const void *sids); 56 | void walSourceRewindv(ALsizei ns, const void *sids); 57 | void walSourcePausev(ALsizei ns, const void *sids); 58 | void walSourceQueueBuffers(ALuint sid, ALsizei numEntries, const void *bids); 59 | void walSourceUnqueueBuffers(ALuint sid, ALsizei numEntries, void *bids); 60 | 61 | // Buffers 62 | 63 | void walGenBuffers(ALsizei n, void *buffers); 64 | void walDeleteBuffers(ALsizei n, const void *buffers); 65 | void walBufferfv(ALuint bid, ALenum param, const void* values); 66 | void walBufferiv(ALuint bid, ALenum param, const void* values); 67 | ALfloat walGetBufferf(ALuint bid, ALenum param); 68 | void walGetBuffer3f(ALuint bid, ALenum param, void *value1, void *value2, void *value3); 69 | void walGetBufferfv(ALuint bid, ALenum param, void* values); 70 | ALint walGetBufferi(ALuint bid, ALenum param); 71 | void walGetBuffer3i(ALuint bid, ALenum param, void *value1, void *value2, void *value3); 72 | void walGetBufferiv(ALuint bid, ALenum param, void* values); 73 | 74 | // For convenience we offer "singular" versions of the following 75 | // calls as well, which require different wrappers if we want to 76 | // be efficient. The main reason for "singular" versions is that 77 | // Go doesn't allow us to treat a variable as an array of size 1. 78 | 79 | ALuint walGenSource(void); 80 | void walDeleteSource(ALuint source); 81 | ALuint walGenBuffer(void); 82 | void walDeleteBuffer(ALuint buffer); 83 | void walSourceQueueBuffer(ALuint sid, ALuint bid); 84 | ALuint walSourceUnqueueBuffer(ALuint sid); 85 | 86 | #endif 87 | --------------------------------------------------------------------------------