Jelajahi Sumber

Added OpenALSourceId() method to TOpenALAudioChannel

Mark Sibly 9 tahun lalu
induk
melakukan
7f91f83a38
1 mengubah file dengan 415 tambahan dan 402 penghapusan
  1. 415 402
      mod/brl.mod/openalaudio.mod/openalaudio.bmx

+ 415 - 402
mod/brl.mod/openalaudio.mod/openalaudio.bmx

@@ -1,402 +1,415 @@
-
-Strict
-
-Rem
-bbdoc: Audio/OpenAL audio 
-about:
-The OpenAL audio module provide OpenAL drivers for use with the #audio module.
-End Rem
-Module BRL.OpenALAudio
-
-ModuleInfo "Version: 1.05"
-ModuleInfo "Author: Mark Sibly"
-ModuleInfo "License: zlib/libpng"
-ModuleInfo "Copyright: Blitz Research Ltd"
-ModuleInfo "Modserver: BRL"
-
-ModuleInfo "History: 1.05 Release"
-ModuleInfo "History: Fixed default channel volume,pan,rate"
-ModuleInfo "History: Fixed behaviour of channel going out of scope"
-ModuleInfo "History: 1.04 Release"
-ModuleInfo "History: Fixed channel playing to return true if active (playing or paused)"
-ModuleInfo "History: 1.03 Release"
-ModuleInfo "History: Added (synced) alDeleteBuffers"
-ModuleInfo "History: 1.02 Release"
-ModuleInfo "History: Added EnableOpenALAudio"
-ModuleInfo "History: 1.01 Initial Release"
-
-Import BRL.Math
-Import BRL.Audio
-Import Pub.OpenAL
-
-Private
-
-Const CLOG=False
-
-'list of all non-static sources
-Global _sources:TOpenALSource
-
-Function CheckAL()
-	Local err$
-	Select alGetError()
-	Case AL_NO_ERROR
-		Return True
-	Case AL_INVALID_NAME
-		err="INVALID_NAME"
-	Case AL_INVALID_ENUM
-		err="INVALID_ENUM"
-	Case AL_INVALID_VALUE
-		err="INVALID_VALUE"
-	Case AL_INVALID_OPERATION
-		err="INVALID_OPERATION"
-	Case AL_OUT_OF_MEMORY
-		err="OUT_OF_MEMORY"
-	Default
-		err="?????"
-	End Select
-	If CLOG WriteStdout "OpenAL Error: "+err+"~n"
-	Return False
-End Function
-
-Type TOpenALSource
-
-	Field _succ:TOpenALSource,_id,_seq,_sound:TOpenALSound,_avail
-	
-	Method Playing()
-		Local st
-		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
-		Return st=AL_PLAYING
-	End Method
-			
-	Method Paused()
-		Local st
-		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
-		Return st=AL_PAUSED Or st=AL_INITIAL
-	End Method
-	
-	Method Active()	
-		Local st
-		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
-		Return st=AL_PLAYING Or st=AL_PAUSED Or st=AL_INITIAL
-	End Method
-	
-	Method LogState()
-		Local st
-		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
-		Select st
-		Case AL_PAUSED WriteStdout "AL_PAUSED~n"
-		Case AL_INITIAL WriteStdout "AL_INITIAL~n"
-		Case AL_STOPPED WriteStdout "AL_STOPPED~n"
-		Case AL_PLAYING WriteStdout "AL_PLAYING~n"
-		Default WriteStdout "AL_DUNNO, st="+st+"~n"
-		End Select
-	End Method
-	
-End Type
-
-Function EnumOpenALDevices$[]()
-	Local p:Byte Ptr=alcGetString( 0,ALC_DEVICE_SPECIFIER )
-	If Not p Return
-	Local devs$[100],n
-	While p[0] And n<100
-		Local sz
-		Repeat
-			sz:+1
-		Until Not p[sz]
-		devs[n]=String.FromBytes( p,sz )
-		n:+1
-		p:+sz+1
-	Wend
-	Return devs[..n]
-End Function
-
-Public
-
-Type TOpenALSound Extends TSound
-
-	Method Delete()
-		alDeleteBuffers 1,Varptr _buffer
-		CheckAL
-		If CLOG WriteStdout "Deleted OpenAL buffer "+_buffer+"~n"
-	End Method
-
-	Method Play:TOpenALChannel( alloced_channel:TChannel=Null )
-		Local t:TOpenALChannel=Cue( alloced_channel )
-		t.SetPaused False
-		Return t
-	End Method
-
-	Method Cue:TOpenALChannel( alloced_channel:TChannel=Null )
-		Local t:TOpenALChannel=TOpenALChannel( alloced_channel )
-		If t
-			Assert t._static
-		Else
-			t=TOpenALChannel.Create( False )
-		EndIf
-		t.Cue Self
-		Return t
-	End Method
-
-	Function Create:TOpenALSound( sample:TAudioSample,flags )
-		Local alfmt
-		Select sample.format
-		Case SF_MONO8
-			alfmt=AL_FORMAT_MONO8
-		Case SF_MONO16LE
-			alfmt=AL_FORMAT_MONO16
-?BigEndian
-			sample=sample.Convert( SF_MONO16BE )
-?
-		Case SF_MONO16BE
-			alfmt=AL_FORMAT_MONO16
-?LittleEndian
-			sample=sample.Convert( SF_MONO16LE )
-?
-		Case SF_STEREO8
-			alfmt=AL_FORMAT_STEREO8
-		Case SF_STEREO16LE
-			alfmt=AL_FORMAT_STEREO16
-?BigEndian
-			sample=sample.Convert( SF_STEREO16BE )
-?
-		Case SF_STEREO16BE
-			alfmt=AL_FORMAT_STEREO16
-?LittleEndian
-			sample=sample.Convert( SF_STEREO16LE )
-?
-		End Select
-		
-		Local buffer=-1
-		alGenBuffers 1,Varptr buffer
-		CheckAL
-		
-		If CLOG WriteStdout "Generated OpenAL buffer "+buffer+"~n"
-		
-		alBufferData buffer,alfmt,sample.samples,sample.length*BytesPerSample[sample.format],sample.hertz
-		CheckAL
-		
-		Local t:TOpenALSound=New TOpenALSound
-		t._buffer=buffer
-		If (flags & 1) t._loop=1
-		Return t
-	End Function
-
-	Field _buffer,_loop
-
-End Type
-
-Type TOpenALChannel Extends TChannel
-
-	Method Delete()
-		If _seq<>_source._seq Return
-		
-		If _static	'LEAKED!
-			Stop	'Just in case...		
-			Return
-		EndIf
-		
-		If Not _source.Playing()
-			alSourceStop _source._id
-			alSourcei _source._id,AL_BUFFER,0
-			_source._sound=Null
-		EndIf
-
-	End Method
-
-	Method Stop()
-		If _seq<>_source._seq Return
-	
-		_source._seq:+1
-
-		alSourceStop _source._id
-		alSourcei _source._id,AL_BUFFER,0
-		_source._sound=Null
-		
-		If _static
-			_source._avail=True
-			_source._succ=_sources
-			_sources=_source
-		EndIf
-	End Method
-	
-	Method SetPaused( paused )
-		If _seq<>_source._seq Return
-
-		If paused
-			alSourcePause _source._id
-		Else
-			If _source.Paused() alSourcePlay _source._id
-		EndIf
-	End Method
-	
-	Method SetVolume( volume# )
-		If _seq<>_source._seq Return
-
-		alSourcef _source._id,AL_GAIN,volume
-	End Method
-	
-	Method SetPan( pan# )
-		If _seq<>_source._seq Return
-
-		pan:*90
-		alSource3f _source._id,AL_POSITION,Sin(pan),0,-Cos(pan)
-	End Method
-	
-	Method SetDepth( depth# )
-		If _seq<>_source._seq Return
-	End Method
-	
-	Method SetRate( rate# )
-		If _seq<>_source._seq Return
-
-		alSourcef _source._id,AL_PITCH,rate
-	End Method
-	
-	Method Playing()
-		If _seq<>_source._seq Return
-
-		Return _source.Playing()
-	End Method
-
-	Method Cue( sound:TOpenALSound )	
-		If _seq<>_source._seq Return
-
-		_source._sound=sound
-		alSourceRewind _source._id
-		alSourcei _source._id,AL_LOOPING,sound._loop
-		alSourcei _source._id,AL_BUFFER,sound._buffer
-	End Method
-	
-	Function Create:TOpenALChannel( static )
-	
-		Local source:TOpenALSource=_sources,pred:TOpenALSource
-		While source
-			If source._avail Or Not source.Active()
-				source._seq:+1
-				If pred pred._succ=source._succ Else _sources=source._succ
-				If CLOG WriteStdout "Recycling OpenAL source "+source._id+"~n"
-				If CLOG source.LogState
-				alSourceRewind source._id	'return to FA_INITIAL state
-				If CLOG source.LogState
-				alSourcei source._id,AL_BUFFER,0
-				source._sound=Null
-				Exit
-			EndIf
-			pred=source
-			source=source._succ
-		Wend
-		
-		If Not source
-			source=New TOpenALSource
-
-			alGenSources 1,Varptr source._id
-			CheckAL
-
-			If source._id
-				If CLOG WriteStdout "Generated OpenAL source "+source._id+"~n"
-			Else
-				If CLOG WriteStdout "Failed to generate OpenAL source~n"
-			EndIf
-		EndIf
-		
-		Local t:TOpenALChannel=New TOpenALChannel
-		t._source=source
-		t._seq=source._seq
-		t._static=static
-		If source._id
-			alSourcei source._id,AL_SOURCE_RELATIVE,True
-			alSourcef source._id,AL_GAIN,1
-			alSourcef source._id,AL_PITCH,1
-			alSource3f source._id,AL_POSITION,0,0,1
-			If Not static
-				source._avail=False
-				source._succ=_sources
-				_sources=source
-			EndIf
-		Else
-			t._seq:+1
-		EndIf
-		Return t
-	End Function
-	
-	Field _source:TOpenALSource,_seq,_static
-	
-End Type
-
-Type TOpenALAudioDriver Extends TAudioDriver
-
-	Method Name$()
-		Return _name
-	End Method
-	
-	Method Startup()
-		_device=0
-		If _devname
-			_device=alcOpenDevice( _devname )
-		Else If OpenALInstalled()
-			_device=alcOpenDevice( Null )
-			If Not _device
-				_device=alcOpenDevice( "Generic Hardware" )
-				If Not _device
-					_device=alcOpenDevice( "Generic Software" )
-				EndIf
-			EndIf
-		EndIf
-		If _device
-			_context=alcCreateContext( _device,Null )
-			If _context
-				alcMakeContextCurrent _context
-				alDistanceModel AL_NONE
-				Return True
-			EndIf
-			alcCloseDevice( _device )
-		EndIf
-	End Method
-	
-	Method Shutdown()
-		_sources=Null
-		alcDestroyContext _context
-		alcCloseDevice _device
-	End Method
-
-	Method CreateSound:TOpenALSound( sample:TAudioSample,flags )
-		Return TOpenALSound.Create( sample,flags )
-	End Method
-	
-	Method AllocChannel:TOpenALChannel()
-		Return TOpenALChannel.Create( True )
-	End Method
-	
-	Function Create:TOpenALAudioDriver( name$,devname$ )
-		Local t:TOpenALAudioDriver=New TOpenALAudioDriver
-		t._name=name
-		t._devname=devname
-		Return t
-	End Function
-	
-	Field _name$,_devname$,_device,_context
-
-End Type
-
-If OpenALInstalled() TOpenALAudioDriver.Create "OpenAL",""
-
-Rem
-bbdoc: Enable OpenAL Audio
-returns: True if successful
-about:
-After successfully executing this command, OpenAL audio drivers will be added
-to the array of drivers returned by #AudioDrivers.
-End Rem
-Function EnableOpenALAudio()
-	Global done,okay
-	If done Return okay
-	If OpenALInstalled() And alcGetString
-		For Local devname$=EachIn EnumOpenALDevices()
-			TOpenALAudioDriver.Create( "OpenAL "+devname,devname )
-		Next
-		TOpenALAudioDriver.Create "OpenAL Default",String.FromCString( alcGetString( 0,ALC_DEFAULT_DEVICE_SPECIFIER ) )
-		okay=True
-	EndIf
-	done=True
-	Return okay
-End Function
+
+Strict
+
+Rem
+bbdoc: Audio/OpenAL audio 
+about:
+The OpenAL audio module provide OpenAL drivers for use with the #audio module.
+End Rem
+Module BRL.OpenALAudio
+
+ModuleInfo "Version: 1.05"
+ModuleInfo "Author: Mark Sibly"
+ModuleInfo "License: zlib/libpng"
+ModuleInfo "Copyright: Blitz Research Ltd"
+ModuleInfo "Modserver: BRL"
+
+ModuleInfo "History: 1.05 Release"
+ModuleInfo "History: Fixed default channel volume,pan,rate"
+ModuleInfo "History: Fixed behaviour of channel going out of scope"
+ModuleInfo "History: 1.04 Release"
+ModuleInfo "History: Fixed channel playing to return true if active (playing or paused)"
+ModuleInfo "History: 1.03 Release"
+ModuleInfo "History: Added (synced) alDeleteBuffers"
+ModuleInfo "History: 1.02 Release"
+ModuleInfo "History: Added EnableOpenALAudio"
+ModuleInfo "History: 1.01 Initial Release"
+
+Import BRL.Math
+Import BRL.Audio
+Import Pub.OpenAL
+
+Private
+
+Const CLOG=False
+
+'list of all non-static sources
+Global _sources:TOpenALSource
+
+Function CheckAL()
+	Local err$
+	Select alGetError()
+	Case AL_NO_ERROR
+		Return True
+	Case AL_INVALID_NAME
+		err="INVALID_NAME"
+	Case AL_INVALID_ENUM
+		err="INVALID_ENUM"
+	Case AL_INVALID_VALUE
+		err="INVALID_VALUE"
+	Case AL_INVALID_OPERATION
+		err="INVALID_OPERATION"
+	Case AL_OUT_OF_MEMORY
+		err="OUT_OF_MEMORY"
+	Default
+		err="?????"
+	End Select
+	If CLOG WriteStdout "OpenAL Error: "+err+"~n"
+	Return False
+End Function
+
+Type TOpenALSource
+
+	Field _succ:TOpenALSource,_id,_seq,_sound:TOpenALSound,_avail
+	
+	Method Playing()
+		Local st
+		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
+		Return st=AL_PLAYING
+	End Method
+			
+	Method Paused()
+		Local st
+		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
+		Return st=AL_PAUSED Or st=AL_INITIAL
+	End Method
+	
+	Method Active()	
+		Local st
+		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
+		Return st=AL_PLAYING Or st=AL_PAUSED Or st=AL_INITIAL
+	End Method
+	
+	Method LogState()
+		Local st
+		alGetSourcei _id,AL_SOURCE_STATE,Varptr st
+		Select st
+		Case AL_PAUSED WriteStdout "AL_PAUSED~n"
+		Case AL_INITIAL WriteStdout "AL_INITIAL~n"
+		Case AL_STOPPED WriteStdout "AL_STOPPED~n"
+		Case AL_PLAYING WriteStdout "AL_PLAYING~n"
+		Default WriteStdout "AL_DUNNO, st="+st+"~n"
+		End Select
+	End Method
+	
+End Type
+
+Function EnumOpenALDevices$[]()
+	Local p:Byte Ptr=alcGetString( 0,ALC_DEVICE_SPECIFIER )
+	If Not p Return
+	Local devs$[100],n
+	While p[0] And n<100
+		Local sz
+		Repeat
+			sz:+1
+		Until Not p[sz]
+		devs[n]=String.FromBytes( p,sz )
+		n:+1
+		p:+sz+1
+	Wend
+	Return devs[..n]
+End Function
+
+Public
+
+Type TOpenALSound Extends TSound
+
+	Method Delete()
+		alDeleteBuffers 1,Varptr _buffer
+		CheckAL
+		If CLOG WriteStdout "Deleted OpenAL buffer "+_buffer+"~n"
+	End Method
+
+	Method Play:TOpenALChannel( alloced_channel:TChannel=Null )
+		Local t:TOpenALChannel=Cue( alloced_channel )
+		t.SetPaused False
+		Return t
+	End Method
+
+	Method Cue:TOpenALChannel( alloced_channel:TChannel=Null )
+		Local t:TOpenALChannel=TOpenALChannel( alloced_channel )
+		If t
+			Assert t._static
+		Else
+			t=TOpenALChannel.Create( False )
+		EndIf
+		t.Cue Self
+		Return t
+	End Method
+
+	Function Create:TOpenALSound( sample:TAudioSample,flags )
+		Local alfmt
+		Select sample.format
+		Case SF_MONO8
+			alfmt=AL_FORMAT_MONO8
+		Case SF_MONO16LE
+			alfmt=AL_FORMAT_MONO16
+?BigEndian
+			sample=sample.Convert( SF_MONO16BE )
+?
+		Case SF_MONO16BE
+			alfmt=AL_FORMAT_MONO16
+?LittleEndian
+			sample=sample.Convert( SF_MONO16LE )
+?
+		Case SF_STEREO8
+			alfmt=AL_FORMAT_STEREO8
+		Case SF_STEREO16LE
+			alfmt=AL_FORMAT_STEREO16
+?BigEndian
+			sample=sample.Convert( SF_STEREO16BE )
+?
+		Case SF_STEREO16BE
+			alfmt=AL_FORMAT_STEREO16
+?LittleEndian
+			sample=sample.Convert( SF_STEREO16LE )
+?
+		End Select
+		
+		Local buffer=-1
+		alGenBuffers 1,Varptr buffer
+		CheckAL
+		
+		If CLOG WriteStdout "Generated OpenAL buffer "+buffer+"~n"
+		
+		alBufferData buffer,alfmt,sample.samples,sample.length*BytesPerSample[sample.format],sample.hertz
+		CheckAL
+		
+		Local t:TOpenALSound=New TOpenALSound
+		t._buffer=buffer
+		If (flags & 1) t._loop=1
+		Return t
+	End Function
+
+	Field _buffer,_loop
+
+End Type
+
+Rem
+bbdoc: OpenAL audio channel Type
+End Rem
+Type TOpenALChannel Extends TChannel
+
+	Method Delete()
+		If _seq<>_source._seq Return
+		
+		If _static	'LEAKED!
+			Stop	'Just in case...		
+			Return
+		EndIf
+		
+		If Not _source.Playing()
+			alSourceStop _source._id
+			alSourcei _source._id,AL_BUFFER,0
+			_source._sound=Null
+		EndIf
+
+	End Method
+
+	Method Stop()
+		If _seq<>_source._seq Return
+	
+		_source._seq:+1
+
+		alSourceStop _source._id
+		alSourcei _source._id,AL_BUFFER,0
+		_source._sound=Null
+		
+		If _static
+			_source._avail=True
+			_source._succ=_sources
+			_sources=_source
+		EndIf
+	End Method
+	
+	Method SetPaused( paused )
+		If _seq<>_source._seq Return
+
+		If paused
+			alSourcePause _source._id
+		Else
+			If _source.Paused() alSourcePlay _source._id
+		EndIf
+	End Method
+	
+	Method SetVolume( volume# )
+		If _seq<>_source._seq Return
+
+		alSourcef _source._id,AL_GAIN,volume
+	End Method
+	
+	Method SetPan( pan# )
+		If _seq<>_source._seq Return
+
+		pan:*90
+		alSource3f _source._id,AL_POSITION,Sin(pan),0,-Cos(pan)
+	End Method
+	
+	Method SetDepth( depth# )
+		If _seq<>_source._seq Return
+	End Method
+	
+	Method SetRate( rate# )
+		If _seq<>_source._seq Return
+
+		alSourcef _source._id,AL_PITCH,rate
+	End Method
+	
+	Method Playing()
+		If _seq<>_source._seq Return
+
+		Return _source.Playing()
+	End Method
+
+	Method Cue( sound:TOpenALSound )	
+		If _seq<>_source._seq Return
+
+		_source._sound=sound
+		alSourceRewind _source._id
+		alSourcei _source._id,AL_LOOPING,sound._loop
+		alSourcei _source._id,AL_BUFFER,sound._buffer
+	End Method
+	
+	Rem
+	bbdoc: Get native openal source id
+	returns: The native openal source id for the channel, or 0 if the channel
+	has been stopped using #Stop.
+	End Rem
+	Method OpenALSourceId()
+		If _seq<>_source._seq Return 0
+		Return _source._id
+	End Method
+	
+	Function Create:TOpenALChannel( static )
+	
+		Local source:TOpenALSource=_sources,pred:TOpenALSource
+		While source
+			If source._avail Or Not source.Active()
+				source._seq:+1
+				If pred pred._succ=source._succ Else _sources=source._succ
+				If CLOG WriteStdout "Recycling OpenAL source "+source._id+"~n"
+				If CLOG source.LogState
+				alSourceRewind source._id	'return to FA_INITIAL state
+				If CLOG source.LogState
+				alSourcei source._id,AL_BUFFER,0
+				source._sound=Null
+				Exit
+			EndIf
+			pred=source
+			source=source._succ
+		Wend
+		
+		If Not source
+			source=New TOpenALSource
+
+			alGenSources 1,Varptr source._id
+			CheckAL
+
+			If source._id
+				If CLOG WriteStdout "Generated OpenAL source "+source._id+"~n"
+			Else
+				If CLOG WriteStdout "Failed to generate OpenAL source~n"
+			EndIf
+		EndIf
+		
+		Local t:TOpenALChannel=New TOpenALChannel
+		t._source=source
+		t._seq=source._seq
+		t._static=static
+		If source._id
+			alSourcei source._id,AL_SOURCE_RELATIVE,True
+			alSourcef source._id,AL_GAIN,1
+			alSourcef source._id,AL_PITCH,1
+			alSource3f source._id,AL_POSITION,0,0,1
+			If Not static
+				source._avail=False
+				source._succ=_sources
+				_sources=source
+			EndIf
+		Else
+			t._seq:+1
+		EndIf
+		Return t
+	End Function
+	
+	Field _source:TOpenALSource,_seq,_static
+	
+End Type
+
+Type TOpenALAudioDriver Extends TAudioDriver
+
+	Method Name$()
+		Return _name
+	End Method
+	
+	Method Startup()
+		_device=0
+		If _devname
+			_device=alcOpenDevice( _devname )
+		Else If OpenALInstalled()
+			_device=alcOpenDevice( Null )
+			If Not _device
+				_device=alcOpenDevice( "Generic Hardware" )
+				If Not _device
+					_device=alcOpenDevice( "Generic Software" )
+				EndIf
+			EndIf
+		EndIf
+		If _device
+			_context=alcCreateContext( _device,Null )
+			If _context
+				alcMakeContextCurrent _context
+				alDistanceModel AL_NONE
+				Return True
+			EndIf
+			alcCloseDevice( _device )
+		EndIf
+	End Method
+	
+	Method Shutdown()
+		_sources=Null
+		alcDestroyContext _context
+		alcCloseDevice _device
+	End Method
+
+	Method CreateSound:TOpenALSound( sample:TAudioSample,flags )
+		Return TOpenALSound.Create( sample,flags )
+	End Method
+	
+	Method AllocChannel:TOpenALChannel()
+		Return TOpenALChannel.Create( True )
+	End Method
+	
+	Function Create:TOpenALAudioDriver( name$,devname$ )
+		Local t:TOpenALAudioDriver=New TOpenALAudioDriver
+		t._name=name
+		t._devname=devname
+		Return t
+	End Function
+	
+	Field _name$,_devname$,_device,_context
+
+End Type
+
+If OpenALInstalled() TOpenALAudioDriver.Create "OpenAL",""
+
+Rem
+bbdoc: Enable OpenAL Audio
+returns: True if successful
+about:
+After successfully executing this command, OpenAL audio drivers will be added
+to the array of drivers returned by #AudioDrivers.
+End Rem
+Function EnableOpenALAudio()
+	Global done,okay
+	If done Return okay
+	If OpenALInstalled() And alcGetString
+		For Local devname$=EachIn EnumOpenALDevices()
+			TOpenALAudioDriver.Create( "OpenAL "+devname,devname )
+		Next
+		TOpenALAudioDriver.Create "OpenAL Default",String.FromCString( alcGetString( 0,ALC_DEFAULT_DEVICE_SPECIFIER ) )
+		okay=True
+	EndIf
+	done=True
+	Return okay
+End Function