barnard/gumble/go-openal/openal/core.go

257 lines
7.4 KiB
Go

// Forked by Tim Shannon 2012
// Copyright 2009 Peter H. Froehlich. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Go binding for OpenAL's "al" API.
//
// See http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm
// for details about OpenAL not described here.
//
// OpenAL types are (in principle) mapped to Go types as
// follows:
//
// ALboolean bool (al.h says char, but Go's bool should be compatible)
// ALchar uint8 (although al.h suggests int8, Go's uint8 (aka byte) seems better)
// ALbyte int8 (al.h says char, implying that char is signed)
// ALubyte uint8 (al.h says unsigned char)
// ALshort int16
// ALushort uint16
// ALint int32
// ALuint uint32
// ALsizei int32 (although that's strange, it's what OpenAL wants)
// ALenum int32 (although that's strange, it's what OpenAL wants)
// ALfloat float32
// ALdouble float64
// ALvoid not applicable (but see below)
//
// We also stick to these (not mentioned explicitly in
// OpenAL):
//
// ALvoid* unsafe.Pointer (but never exported)
// ALchar* string
//
// Finally, in places where OpenAL expects pointers to
// C-style arrays, we use Go slices if appropriate:
//
// ALboolean* []bool
// ALvoid* []byte (see Buffer.SetData() for example)
// ALint* []int32
// ALuint* []uint32 []Source []Buffer
// ALfloat* []float32
// ALdouble* []float64
//
// Overall, the correspondence of types hopefully feels
// natural enough. Note that many of these types do not
// actually occur in the API.
//
// The names of OpenAL constants follow the established
// Go conventions: instead of AL_FORMAT_MONO16 we use
// FormatMono16 for example.
//
// Conversion to Go's camel case notation does however
// lead to name clashes between constants and functions.
// For example, AL_DISTANCE_MODEL becomes DistanceModel
// which collides with the OpenAL function of the same
// name used to set the current distance model. We have
// to rename either the constant or the function, and
// since the function name seems to be at fault (it's a
// setter but doesn't make that obvious), we rename the
// function.
//
// In fact, we renamed plenty of functions, not just the
// ones where collisions with constants were the driving
// force. For example, instead of the Sourcef/GetSourcef
// abomination, we use Getf/Setf methods on a Source type.
// Everything should still be easily recognizable for
// OpenAL hackers, but this structure is a lot more
// sensible (and reveals that the OpenAL API is actually
// not such a bad design).
//
// There are a few cases where constants would collide
// with the names of types we introduced here. Since the
// types serve a much more important function, we renamed
// the constants in those cases. For example AL_BUFFER
// would collide with the type Buffer so it's name is now
// Buffer_ instead. Not pretty, but in many cases you
// don't need the constants anyway as the functionality
// they represent is probably available through one of
// the convenience functions we introduced as well. For
// example consider the task of attaching a buffer to a
// source. In C, you'd say alSourcei(sid, AL_BUFFER, bid).
// In Go, you can say sid.Seti(Buffer_, bid) as well, but
// you probably want to say sid.SetBuffer(bid) instead.
//
// TODO: Decide on the final API design; the current state
// has only specialized methods, none of the generic ones
// anymore; it exposes everything (except stuff we can't
// do) but I am not sure whether this is the right API for
// the level we operate on. Not yet anyway. Anyone?
package openal
/*
#cgo linux LDFLAGS: -lopenal
#cgo windows LDFLAGS: -lopenal32
#cgo darwin LDFLAGS: -framework OpenAL
#include <stdlib.h>
#include "local.h"
#include "wrapper.h"
*/
import "C"
import "unsafe"
// General purpose constants. None can be used with SetDistanceModel()
// to disable distance attenuation. None can be used with Source.SetBuffer()
// to clear a Source of buffers.
const (
None = 0
alFalse = 0
alTrue = 1
)
// GetInteger() queries.
const (
alDistanceModel = 0xD000
)
// GetFloat() queries.
const (
alDopplerFactor = 0xC000
alDopplerVelocity = 0xC001
alSpeedOfSound = 0xC003
)
// GetString() queries.
const (
alVendor = 0xB001
alVersion = 0xB002
alRenderer = 0xB003
alExtensions = 0xB004
)
// Shared Source/Listener properties.
const (
AlPosition = 0x1004
AlVelocity = 0x1006
AlGain = 0x100A
)
func GetString(param int32) string {
return C.GoString(C.walGetString(C.ALenum(param)))
}
func getBoolean(param int32) bool {
return C.alGetBoolean(C.ALenum(param)) != alFalse
}
func getInteger(param int32) int32 {
return int32(C.alGetInteger(C.ALenum(param)))
}
func getFloat(param int32) float32 {
return float32(C.alGetFloat(C.ALenum(param)))
}
func getDouble(param int32) float64 {
return float64(C.alGetDouble(C.ALenum(param)))
}
// Renamed, was GetBooleanv.
func getBooleans(param int32, data []bool) {
C.walGetBooleanv(C.ALenum(param), unsafe.Pointer(&data[0]))
}
// Renamed, was GetIntegerv.
func getIntegers(param int32, data []int32) {
C.walGetIntegerv(C.ALenum(param), unsafe.Pointer(&data[0]))
}
// Renamed, was GetFloatv.
func getFloats(param int32, data []float32) {
C.walGetFloatv(C.ALenum(param), unsafe.Pointer(&data[0]))
}
// Renamed, was GetDoublev.
func getDoubles(param int32, data []float64) {
C.walGetDoublev(C.ALenum(param), unsafe.Pointer(&data[0]))
}
// GetError() returns the most recent error generated
// in the AL state machine.
func getError() uint32 {
return uint32(C.alGetError())
}
// Renamed, was DopplerFactor.
func SetDopplerFactor(value float32) {
C.alDopplerFactor(C.ALfloat(value))
}
// Renamed, was DopplerVelocity.
func SetDopplerVelocity(value float32) {
C.alDopplerVelocity(C.ALfloat(value))
}
// Renamed, was SpeedOfSound.
func SetSpeedOfSound(value float32) {
C.alSpeedOfSound(C.ALfloat(value))
}
// Distance models for SetDistanceModel() and GetDistanceModel().
const (
InverseDistance = 0xD001
InverseDistanceClamped = 0xD002
LinearDistance = 0xD003
LinearDistanceClamped = 0xD004
ExponentDistance = 0xD005
ExponentDistanceClamped = 0xD006
)
// SetDistanceModel() changes the current distance model.
// Pass "None" to disable distance attenuation.
// Renamed, was DistanceModel.
func SetDistanceModel(model int32) {
C.alDistanceModel(C.ALenum(model))
}
///// Crap ///////////////////////////////////////////////////////////
// These functions are wrapped and should work fine, but they
// have no purpose: There are *no* capabilities in OpenAL 1.1
// which is the latest specification. So we removed from from
// the API for now, it's complicated enough without them.
//
//func Enable(capability int32) {
// C.alEnable(C.ALenum(capability));
//}
//
//func Disable(capability int32) {
// C.alDisable(C.ALenum(capability));
//}
//
//func IsEnabled(capability int32) bool {
// return C.alIsEnabled(C.ALenum(capability)) != alFalse;
//}
// These constants are documented as "not yet exposed". We
// keep them here in case they ever become valid. They are
// buffer states.
//
//const (
// Unused = 0x2010;
// Pending = 0x2011;
// Processed = 0x2012;
//)
// These functions would work fine, but they are not very
// useful since we have distinct Source and Buffer types.
// Leaving them out reduces API complexity, a good thing.
//
//func IsSource(id uint32) bool {
// return C.alIsSource(C.ALuint(id)) != alFalse;
//}
//
//func IsBuffer(id uint32) bool {
// return C.alIsBuffer(C.ALuint(id)) != alFalse;
//}