I've got a system together and it seems to be working pretty well for handling positional sound. If anyone whose interested could give it a try and let me know if flames leap out the back or not it would be much appreciated.
I've built it as a module and you will need minib3d installed as a module as well (I can't stand non-colored functions...). But you can easily strip out the module stuff at the top and make it work as an include or an import.
you can download it here
http://ima747.gotdns.com/blitzmax/minib3dsoundv1.0.zip
or here's the code if you want to copy and paste (just remember it's a module, so you need to toch it up a little if you do that)
I've built it as a module and you will need minib3d installed as a module as well (I can't stand non-colored functions...). But you can easily strip out the module stuff at the top and make it work as an include or an import.
you can download it here
http://ima747.gotdns.com/blitzmax/minib3dsoundv1.0.zip
or here's the code if you want to copy and paste (just remember it's a module, so you need to toch it up a little if you do that)
SuperStrict Rem bbdoc: MiniB3D Sound about: If there is no more emiter object then we can't update any sound point attached to that object, so those sound points are removed on the assumption that a dead entity can't make a sound.<br> If you want a sound to continue from a point even if you kill the object that the sound is attached to then create and attach a attach a pivot to the entity and then attach the sound to the pivot. Then if you remove the entity the pivot with the sound will remain. You can then remove the pivot when the sound is finnished. End Rem Module ima.minib3dsound ModuleInfo "Version: 1.0" ModuleInfo "Author: Logan Chittenden" ModuleInfo "License: You are free to use this code as you please." ModuleInfo "History: 1.0 Initial Release" Import sidesign.minib3d Import brl.audio '############################################################################################## Types Rem bbdoc: SoundPoint Type about: A SoundPoint is a point that plays a sound in 3D space End Rem Type SoundPoint Rem bbdoc: The point the sound is coming from End Rem Field RelativeSoundPoint:TPivot Rem bbdoc: The angle to the sound from the listening entity End Rem Field ListenAngularDifference:TPivot Rem bbdoc: The channel the sound is playing in End Rem Field SoundChannel:TChannel Rem bbdoc: The Entity that is emiting the sound End Rem Field EmiterObject:TEntity Rem bbdoc: The "loudness" of the sound End Rem Field Loudness:Float Rem bbdoc: The base volume of the sound End Rem Field MasterVolume:Float Rem bbdoc: The distance from the listen point to the sound EmitterObject End Rem Field Distance:Float Rem bbdoc: The angle from the listen point to the EmitterObject End Rem Field Angle:Float Rem bbdoc: The pan point of the sound End Rem Field Pan:Float Rem bbdoc: The pan bump about: When calculating the sound channels pan this number will be added to the new pan End Rem Field PanBump:Float Rem bbdoc: The depth point of the sound End Rem Field Depth:Float Rem bbdoc: The depth bump about: When calculating the sound channels depth this number will be added to the new pan End Rem Field DepthBump:Float Rem bbdoc: The play rate of the sound End Rem Field Rate:Float = 1 Rem bbdoc: The play rate bump about: When calculating the sound channels play rate this number will be added to the new rate End Rem Field RateBump:Float Rem bbdoc: The volume of the sound End Rem Field Volume:Float Rem bbdoc: The volume bump about: When calculating the sound channels volume this number will be added to the new volume End Rem Field VolumeBump:Float Rem bbdoc: Creates a new sound point about: To create a sound use Start3DSound to allow for future changes to the system End Rem Function Create:SoundPoint(TheSound:TSound, NoisyEntity:TEntity, EntityLoudness:Float=1, Volume:Float=1) Local theTemp:SoundPoint = New SoundPoint theTemp.RelativeSoundPoint = CreatePivot(HearingPoint.ListenPoint) ' parented to the listen point so we can get angles and distance relative to that theTemp.ListenAngularDifference = CreatePivot(HearingPoint.ListenPoint) ' used to calculate angle off of the listen point towards the sound theTemp.EmiterObject = NoisyEntity theTemp.SoundChannel = AllocChannel() theTemp.MasterVolume = Volume theTemp.Loudness = EntityLoudness CueSound(TheSound, theTemp.SoundChannel) theTemp.UpdatePosition() ResumeChannel(theTemp.SoundChannel) ListAddLast(SoundPointsList, theTemp) Return(theTemp) End Function Method UpdatePosition() Local LastDistance:Float If EmiterObject Then ' Update the point the sound is coming from to that of the emiting object's global position PositionEntity(RelativeSoundPoint, EntityX(EmiterObject, True), EntityY(EmiterObject, True), EntityZ(EmiterObject, True), True) ' Get and correct the angle off of the listen point towards where the sound is comming from PointEntity(ListenAngularDifference, RelativeSoundPoint) ' update the angle Angle = EntityYaw(ListenAngularDifference) ' angle will always be in range of -180 to +180 ' Get the distance from the listen point to the sound point LastDistance = Distance ' store the last distance incase we need to do doppler Distance = EntityDistance(ListenAngularDifference, RelativeSoundPoint) ' Pan is based on yaw angle off of the listen point towards the sound source Pan = (-Angle)/90 Pan:+PanBump If Pan > 1 Then ' past 90 deg Pan = 1-(Pan-1) ElseIf Pan < -1 Then ' past -90 deg Pan = -1-(Pan+1) End If ' Depth is based on how far along Z axis (ahead or behind) ' the point is in Local coords (which are relative To the listenpoint's postion and angle) Depth = EntityZ(RelativeSoundPoint)/HearingPoint.SoundFalloffEnd Depth:+DepthBump If Depth > 1 Then ' over maximum Depth = 1 ElseIf Depth < -1 Then Depth = -1 End If ' If the doppler effect is enabled by having a dopplerscale If HearingPoint.DopplerScale = 0 Then Rate = (343.7+(LastDistance - Distance))/343.7 ElseIf HearingPoint.DopplerScale > -1 Then Rate = (343.7+((LastDistance - Distance)*HearingPoint.DopplerScale))/343.7 SetChannelRate(SoundChannel, Rate) Else ' not using standard or Exaggerated doppler, set the rate to 1 Rate = 1 End If Rate:+RateBump ' Volume is based on distance from the listen point to the relative sound point, modified by ' the master volume of the sound (how loud it is) Volume = MasterVolume-(Distance/(HearingPoint.SoundFalloffEnd*Loudness)) Volume:+VolumeBump If Volume > 1 Then Volume = 1 ElseIf Volume < 0 Then Volume = 0 End If PauseChannel(SoundChannel) ' the pause and resume reduce crackling SetChannelPan(SoundChannel, Pan) SetChannelRate(SoundChannel, Rate) SetChannelDepth(SoundChannel, Depth) SetChannelVolume(SoundChannel, Volume) ResumeChannel(SoundChannel) Else Stop() End If End Method Rem bbdoc: Updates the sound channel and it's positional information, as well as clearing the channel if the sound is done playing about: To update all sounds at once use Update3DSounds() End Rem Method Update() If SoundChannel Then UpdatePosition() If Not ChannelPlaying(SoundChannel) Then Stop() End If Else Stop() End If End Method Rem bbdoc: Stops a sound and removes it from the sound system about: This will stop a sound point while playing and free it's resources End Rem Method Stop() StopChannel(SoundChannel) ListRemove(SoundPointsList, Self) End Method Method Delete() StopChannel(SoundChannel) FreeEntity(RelativeSoundPoint) End Method End Type '# A HearingPointType is a point to where the sound travels. i.e. the center of a head Type ListeningPoint Field ListenPoint:TEntity ' the microphone, should be attached to the camera Field SoundFalloffEnd:Float ' Sounds are silent past this point Field DopplerScale:Float ' How far you have to move to double or half the sound rate. 0 to dissable doppler effect End Type '############################################################################################## Variables Private Global HearingPoint:ListeningPoint = New ListeningPoint ' the point where sound is heard Global SoundPointsList:TList ' all currently active 3d sounds '############################################################################################## Functions Public Rem bbdoc: Setup the 3D sound system about: Call this before any other 3D sound calls<br> The sound system can be re-initialized later without loosing the sounds currently playing, however the positional information of the sound points will be wrong untill the next call to Update3DSounds()<br> <br> <b>ListeningEntity</b> is the entity you will hear sound through.<br> <b>MaxRange</b> is the maximum distance a sound will be before it is silent<br> <b>ExaggerateDopplerScale</b> <i>optional</i> is the amound to exagerate the doppler effect bye. A value of -1 will dissable the doppler effect. A value of 0 will use accurate doppler effect (1 unit = 1 meter). The value will be dependent on the speeds of objects in your program. A recommended starting value is 4, which will multipley any movement my 4x in the doppler effect. End Rem Function Init3DSound(ListeningEntity:TEntity, MaxRange:Float, ExaggerateDopplerScale:Float=-1) Local tempSoundPoint:SoundPoint If Not HearingPoint Then HearingPoint = New HearingPoint End If HearingPoint.ListenPoint = ListeningEntity HearingPoint.SoundFalloffEnd = MaxRange HearingPoint.DopplerScale = ExaggerateDopplerScale If SoundPointsList Then For tempSoundPoint = EachIn SoundPointsList ' update all sound points to listen from the new point EntityParent(tempSoundPoint.RelativeSoundPoint, HearingPoint.ListenPoint) ' re-attach relative point EntityParent(tempSoundPoint.ListenAngularDifference, HearingPoint.ListenPoint) ' re-attach angle diff point PositionEntity(tempSoundPoint.ListenAngularDifference, 0, 0, 0) ' re-center the angle diff point Next Else SoundPointsList = CreateList() End If End Function Rem bbdoc: Updates all the 3D sound channels about: Should be called (optimaly) once per loop, preferably after positions and collisions have been handled. End Rem Function Update3DSounds() Local tempSoundPoint:SoundPoint For tempSoundPoint = EachIn SoundPointsList tempSoundPoint.Update() Next End Function Rem bbdoc: Attaches a sound to an entity and starts it playing. returns: Sound Point so you can control it further. You can ignore the return value as it is held in the sound system. about: <b>TheSound</b> is the sound you wish to play.<br> <b>NoisyEntity</b> is the entity that is making the sound.<br> <b>Loudness</b> <i>optional</i> determines how loud a sound is. Louder sounds will cary farther. Distance is proportional to the MaxRange set durring Init3DSound. A value of 1 will cary to the MaxRange. <b>Volume</b> <i>optional</i> sets a master volume for the sound End Rem Function Start3DSound:SoundPoint(TheSound:TSound, NoisyEntity:TEntity, Loudness:Float=1, Volume:Float=1) Local tempSoundPoint:SoundPoint tempSoundPoint = SoundPoint.Create(TheSound, NoisyEntity, Loudness, Volume) Return(tempSoundPoint) End Function