Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

3D Sound Demo - using OpenAL

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • 3D Sound Demo - using OpenAL

    Save this as "OpenAlDemo.bas"
    Code:
     
    '**************************************
    '   "OpenAlDemo.bas"
    
    'Notes:
    
    ! This demo might GPF and crash your computer, especially if run in the
    ! debugger!  Save all open files before running this.
    
    'You can get the OpenAl and Alut binaries, SDK and (PDF) manuals from:
    'www.openal.org
    
    'OpenAl Archives (about 9MB of messages):
    'http://opensource.creative.com/pipermail/openal/
    
    'The OpenAl functions are in two main categories: one with the prefix "al",
    'and the other with "alc". They each have their own set of equates too.
    
    'Don't pass a closed device to alcGetError, or it will GPF
    
    'alcOpenDevice GPFs (and crashes the computer) with dynamic and Asciz
    'strings, but not with string equates, for some reason.
    
    'To globally disable checking for "al" errors REM-out or delete "%Debug".
    'To remove all the error-checking calls for "al" (not "alc") imports, do
    'a replace-all of " : alge" with "", then delete the Sub "alge".
    
    'alGetError and alcGetError are called very frequently for your use while
    'debugging. This demo doesn't respond to many of the error values it
    'retrieves.
    
    'This uses part of "motor_a8.wav" from the OpenAl SDK.
    
    'This used to freeze or GPF when calling alcOpenDevice, but it seems fine now.
    'This was using PBEdit's debugger, but that might not have been related.
    'It's something to watch out for. It never had a problem after running a demo
    'from the OpenAl SDK, for some reason.
    
    'Mono WAV files are preferrable for use with 3D sound, because adding stereo
    'effects to sound is what the 3D sound hardware/software is for in the first
    'place. Also, stereo WAVs are converted to mono anyway before any effects are
    'applied and that means extra large files to load and more processing to do
    'to them with no benefit whatsoever.
    
    'It's usually preferrable to use WAVs which are recorded with no natural
    'acoustics in them, because they might still be audible after artificial 3D
    'effects are added.
    ' It could be helpful in some cases though, to have some natural acoustics if the
    'original acoustics are the kind you need and if they don't need to be changed
    'during use, for example.
    
    '   Coordinate system: (from OpenAl specification)
    'OpenAL -- like OpenGL -- uses a right-handed Cartesian coordinate system (RHS),
    'where in a frontal default view X (thumb) points right, Y (index finger) points
    'up, and Z (middle finger) points towards the viewer/camera. To switch from a
    'left handed coordinate system (LHS) to a right handed coordinate systems, flip
    'the sign on the Z coordinate.
    
    'This code is Public domain by TheirCorp 2006
    '**************************************
    
    #Compile Exe "OpenAlDemo.exe"
    #Dim All
    #Register All
    '#Debug Error On
    '#Tools On
    
    %Debug              = 1
    %PrintErrorsToFile  = 1 '(instead of a messagebox)
    
    #Include "OpenAl.inc"
    
    '**************************************
    
    'Take your pick... , or let the demo find out what's available.
    $WaveDevice =   "Generic Hardware"
    '$WaveDevice =   "Generic Software"
    '$WaveDevice =   "DirectSound3D"
    
    'WAV files
    $WavMotor   = "Motor.wav"
    $WavHonk    = "Horn.wav"
    
    '**************************************
    
    Function PBMain() As Long
    Local n           As Long
    Local b           As Byte
    Local eaxSet      As Dword 'pointer to function
    Local alcError    As Long
    Local SingVal     As Single
    Local Buffers()   As Dword
    Local Context     As Dword
    Local Device      As Dword
    Local FormatCode  As Long  'the WAV format code
    Local DataPtr     As Long  'pointer to WAV data
    Local DataSize    As Long  'size of WAV data
    Local Frequency   As Long  'frequency
    Local LoopFlag    As Long  'looping
    Local Sources()   As Dword 'source
    Local ThreeSing   As THREESINGLES
    Local SixSing     As SIXSINGLES
    'Local EaxBufProp  As EAXBUFFERPROPERTIES
    Local ls          As String
    Local ts          As String
    
    'extensions to check for
    Data "al_ext_offset"
    Data "AL_EXT_LINEAR_DISTANCE"
    Data "AL_EXT_EXPONENT_DISTANCE"
    Data "alc_EXT_capTure"
    Data "EAX2.0"
    
    
        '--------------------------------------------------
        '   Check for available hardware devices and "software devices"
        '--------------------------------------------------
        'Check for Direct Sound 3D
        'b = 0 : ls = "" : ts = ""      'In case these are altered above
        n = LoadLibrary("DSOUND3D.DLL")
        If n Then
            FreeLibrary(n)
            Incr b
            ts = "DirectSound3D"    ' "ts" holds a clean list of the device names, because "ls" needs extra formatting for display
            ls = Format$(b) & ".  " & $Dq & ts & $Dq & $CrLf
            ts = ts & ","
        End If
    
        'Enumerate devices using OpenAl
        'If sent NULL instead of a string for &ALC_DEVICE_SPECIFIER, alcGetString returns
        'a list of NULL-terminated device names. The list itself is terminated by two NULLs.
        Device = alcGetString(0, %ALC_DEVICE_SPECIFIER) ' "Device" is being used as a string pointer here, since it's still available
        If Device Then
    
            Do
                Incr b  'b holds the device count
                n = lstrlen(ByVal Device)
                If n Then
                    ts = ts & Peek$(Device, n) & ","
                    ls = ls & Format$(b) & ".  " & $Dq & Peek$(Device, n) & $Dq & $CrLf
                Else
                    Exit Do
                End If
    
                Device = Device + n + 1
    
            Loop While n
    
        End If
    
    
        ts = Trim$(ts, Any ", ")
        If b > 1 Then       'Found more than one, so offer a selection
            ls = "Enter the number of the device to use:" & $CrLf & $CrLf & ls
            n = Val(InputBox$(ls, "The following devices were found:", "1"))
            n = Max&(Min&(n, ParseCount(ts)), 1)
    
        ElseIf b = 1 Then   'Found one, so show it, then use it
            MsgBox "The following device was found: """ & ts & """"
            n = 1
    
        Else                'Nothing found so exit
            MsgBox "No devices found. Exiting program..."
            Exit Function
    
        End If
    
        ls = Parse$(ts, n)    'Get the selected device's name
    
    
        '--------------------------------------------------
        '   Setup the demo
        '--------------------------------------------------
        If 1 Then 'This block-IF is to make it easy to skip code in case of errors
    
            '--------------------------------------------------
            '   Open a device and get a current context
            '--------------------------------------------------
    
            !' NOTE: In the debugger, alcOpenDevice often GPFs (and crashes the computer) with
            !' dynamic and Asciz strings, but not with equates.
            'Also: alcOpenDevice doesn't like being stepped through in the debugger, so set a
            'breakpoint beyond it and run through it.
    
            !' Use this when running in the debugger to avoid GPFs
            'Device = alcOpenDevice($WaveDevice)     'Open a device (in debugger)
    
            !' You can use this when not running in the debugger
            Device = alcOpenDevice(ByVal StrPtr(ls))     'Open a device (not in the debugger)
    
            If Device = 0 Then
                MsgBox ls & " was not found. Try another one."
                Exit Function
            End If
    
            alcError = alcGetError(ByVal Device)        'Clear any existing error value
            Context = alcCreateContext(Device, ByVal 0) 'Create a context
            alcError = alcGetError(ByVal Device)
    
            alcMakeContextCurrent(Context)  'Make the created context current
            alcError = alcGetError(ByVal Device)
    
    
            '--------------------------------------------------
            '   Get and display available extensions
            '--------------------------------------------------
            '"alIsExtensionPresent" seems to need a context to be made current, so it was put here.
            ls = $CrLf & _
            "******************************************" & $CrLf & _
            "           Present Extensions:" & $CrLf & _
            "******************************************" & $CrLf & $CrLf
            For n = 1 To DataCount
                b = alIsExtensionPresent(Read$(n))
                ls = ls & IIf$(b = %AL_TRUE, "(YES):  ", "(NO) :  ") & Read$(n) & $CrLf
            Next n
            MsgBox ls
            alge    'clear the current error value
    
    
            '--------------------------------------------------
            '   Set listener properties
            '--------------------------------------------------
            ThreeSing.x = 0 : ThreeSing.y = 0 : ThreeSing.z = 0
            alListenerfv(%AL_POSITION, ByVal VarPtr(ThreeSing)) : alge 'Set listener position
            alListenerfv(%AL_VELOCITY, ByVal VarPtr(ThreeSing)) : alge 'Set listener velocity
    
            'Set listener orientation: the direction he/she's facing, then the head's orientation
            SixSing.fx = -1 'Forward x
            SixSing.fy = 0  'Forward y
            SixSing.fz = 0  'Forward z
            SixSing.ux = 0  'Up x
            SixSing.uy = 1  'Up y
            SixSing.uz = 0  'Up z
            alListenerfv(%AL_ORIENTATION, ByVal VarPtr(SixSing)) : alge
    
    
            '--------------------------------------------------
            '   Generate and load buffers with WAV data
            '--------------------------------------------------
            'These are referred to as "names", but that term doesn't seem to fit them very well
            ReDim Sources(%NUM_SOURCES - 1)  'DIM-ension array of source "names"
            ReDim Buffers(%NUM_BUFFERS - 1)  'DIM-ension array of buffer "names"
    
            alGenBuffers(%NUM_BUFFERS, Buffers(0)) : alge   'Generate the needed number of buffers
            If alError Then Exit If     'Couldn't create the buffers
    
            'Load "motor.wav" into buffer 0
            If Len(Dir$($WavMotor)) = 0 Then Exit If                                                'Make sure "motor.wav" is present
            alutLoadWAVFile($WavMotor, FormatCode, DataPtr, DataSize, Frequency, LoopFlag)          'Load it into a temporary data buffer
            alBufferData(Buffers(%Buffer_Motor), FormatCode, DataPtr, DataSize, Frequency) : alge   'Load it into the second buffer generated above
            If alError Then Exit If     'Couldn't buffer the WAV data
            alutUnloadWAV(FormatCode, DataPtr, DataSize, Frequency)                                 'Free the temporary buffer
    
            'Load "horn.wav" into buffer 1
            If Len(Dir$($WavHonk)) = 0 Then Exit If                                                 'Make sure "horn.wav" is present
            alutLoadWAVFile($WavHonk, FormatCode, DataPtr, DataSize, Frequency, LoopFlag)           'Load it into a temporary data buffer
            alBufferData(Buffers(%Buffer_Horn), FormatCode, DataPtr, DataSize, Frequency) : alge    'Load it into the second buffer generated above
            If alError Then Exit If     'Couldn't buffer the WAV data
            alutUnloadWAV(FormatCode, DataPtr, DataSize, Frequency)                                 'Free the temporary buffer
    
            '--------------------------------------------------
            '   Generate sources, assign buffers and adjust their initial settings
            '--------------------------------------------------
            alGenSources(%NUM_SOURCES, Sources(%Source_Motor)) : alge   'Generate the needed number of sources
            If alError Then Exit If     'Couldn't generate the sources
    
            alSourcei(Sources(%Source_Motor), %AL_BUFFER, CLng(Buffers(%Buffer_Motor))) : alge  'Assign motor's buffer to a source
            If alError Then Exit If     'Couldn't assign the buffer
            alSourcei(Sources(%Source_Horn), %AL_BUFFER, CLng(Buffers(%Buffer_Horn))) : alge    'Assign horn's buffer to the other source
            If alError Then Exit If     'Couldn't assign the buffer
    
    
            'Lower the gain for the "no effects" part of the demo
            alSourcef(Sources(%Source_Motor), %AL_GAIN, 0.3) : alge
            alSourcef(Sources(%Source_Horn), %AL_GAIN, 0.3) : alge
    
    
            '--------------------------------------------------
            '   Listen with no effects
            '--------------------------------------------------
            MsgBox "Here are the two waves played together, with no effects (at half volume)" & $CrLf & $CrLf & _
                   "Press ""Okay"" to hear them."
            alSourcePlay Sources(%Source_Motor) : alge  'Play the motor
            alSourcePlay Sources(%Source_Horn) : alge   'Play the horn
            Sleep 500                                   'Let them finish playing
            alSourceStop Sources(%Source_Motor) : alge  'Stop the motor
            alSourceStop Sources(%Source_Horn) : alge   'Stop the horn
    
            MsgBox "That was the two waves played together with no effects applied" & $CrLf & _
                   "(at half volume). The longest WAV is about 1/3 second." & $CrLf & $CrLf & _
                   "Press ""Okay"" to listen with the effects applied" & $CrLf & _
                   "It will last for around 10 seconds (just wait for" & $CrLf & _
                   "the next messagebox to appear)." & $CrLf & $CrLf & _
                    "The demo simulates a car driving down an alley from" & $CrLf & _
                    "your right side and honking as it passes you."
    
    
            '--------------------------------------------------
            '   Apply all the effects to the WAV buffers
            '--------------------------------------------------
            'Apply acoustic effects to the motor
            alSourcei(Sources(%Source_Motor), %AL_LOOPING, 1) : alge     'Turn motor's looping on
            alSourcef(Sources(%Source_Motor), %AL_GAIN, 1.0) : alge      'Set the motor's gain to 1.0
            alSourcef(Sources(%Source_Motor), %AL_PITCH, 1.0) : alge     'Set the motor's pitch to 1.0
    
            'Apply acoustic effects to the horn
            alSourcei(Sources(%Source_Horn), %AL_LOOPING, 0) : alge      'Make sure horn's looping is off
            alSourcef(Sources(%Source_Horn), %AL_GAIN, 1.0) : alge       'Set the horn's gain to 1.0
            alSourcef(Sources(%Source_Horn), %AL_PITCH, 1.0) : alge      'Set the horn's pitch to 1.0
    
            '--------------------------------------------------
            '   Here are some predefined acoustic environments
            '   try as many as you like...
            '   "Alley" acoustics was chosen for this demo.
            '--------------------------------------------------
            'n = %EAX_ENVIRONMENT_GENERIC
            'n = %EAX_ENVIRONMENT_PADDEDCELL
            'n = %EAX_ENVIRONMENT_ROOM
            'n = %EAX_ENVIRONMENT_BATHROOM
            'n = %EAX_ENVIRONMENT_LIVINGROOM
            'n = %EAX_ENVIRONMENT_STONEROOM
            'n = %EAX_ENVIRONMENT_AUDITORIUM
            'n = %EAX_ENVIRONMENT_CONCERTHALL
            'n = %EAX_ENVIRONMENT_CAVE
            'n = %EAX_ENVIRONMENT_ARENA
            'n = %EAX_ENVIRONMENT_HANGAR
            'n = %EAX_ENVIRONMENT_CARPETEDHALLWAY
            'n = %EAX_ENVIRONMENT_HALLWAY
            'n = %EAX_ENVIRONMENT_STONECORRIDOR
            n = %EAX_ENVIRONMENT_ALLEY
            'n = %EAX_ENVIRONMENT_FOREST
            'n = %EAX_ENVIRONMENT_CITY
            'n = %EAX_ENVIRONMENT_MOUNTAINS
            'n = %EAX_ENVIRONMENT_QUARRY
            'n = %EAX_ENVIRONMENT_PLAIN
            'n = %EAX_ENVIRONMENT_PARKINGLOT
            'n = %EAX_ENVIRONMENT_SEWERPIPE
            'n = %EAX_ENVIRONMENT_UNDERWATER
            'n = %EAX_ENVIRONMENT_DRUGGED
            'n = %EAX_ENVIRONMENT_DIZZY
            'n = %EAX_ENVIRONMENT_PSYCHOTIC
            'n = %EAX_ENVIRONMENT_COUNT
    
    
            '--------------------------------------------------
            '   Apply the predefined environment to the listener
            '--------------------------------------------------
            eaxSet = alGetProcAddress("EAXSet") 'Get the address of "EAXSet"
            If eaxSet Then                      'If eaxSet is a valid code pointer then go ahead...
                Call Dword eaxSet Using CallEaxSet($DSPROPSETID_EAX20_ListenerProperties, %DSPROPERTY_EAXLISTENER_ENVIRONMENT Or %DSPROPERTY_EAXLISTENER_IMMEDIATE, 0, VarPtr(n), 4)
            End If
    
    
            !'**************************************************
            !'               The main demo
            !'**************************************************
            '--------------------------------------------------
            '   This demo simulates a car driving down an alley from
            '   your right side and honking as it passes you.
            '--------------------------------------------------
            n = 0
            For SingVal = -50 To 50 Step 0.5
    
                '--------------------------------------------------
                'Add doppler effects (you can exagerate these as much as you want, for added effect)
                ThreeSing.z = -Sgn(SingVal) * 10
                ThreeSing.x = 0
                alSourcefv(Sources(%Source_Motor), %AL_VELOCITY, ByVal VarPtr(ThreeSing)) : alge    'Update motor's velocity
                alSourcefv(Sources(%Source_Horn), %AL_VELOCITY, ByVal VarPtr(ThreeSing)) : alge     'Update horn's velocity
    
                '--------------------------------------------------
                'Set positions of sources
                ThreeSing.z = SingVal
                ThreeSing.x = -2
                alSourcefv(Sources(%Source_Motor), %AL_POSITION, ByVal VarPtr(ThreeSing)) : alge    'Update motor's position
                alSourcefv(Sources(%Source_Horn), %AL_POSITION, ByVal VarPtr(ThreeSing)) : alge     'Update horn's position
    
                '--------------------------------------------------
                'Start the car
                If n = 0 Then alSourcePlay Sources(%Source_Motor) : n = 1 : alge     'Start the motor on the first loop
    
                '--------------------------------------------------
                'Honk the horn when about 2.5 meters away, and still approaching
                If (n < 2) And (SingVal > -2.5) Then alSourcePlay Sources(%Source_Horn) : n = 2 : alge
    
                '--------------------------------------------------
                Sleep 50    'Don't make it reprocess the WAV data too frequently.
    
            Next SingVal
    
            !'**************************************************
            !'               End of the main demo
            !'**************************************************
    
            alSourceStop Sources(%Source_Motor) : alge   'Stop the motor
            alSourceStop Sources(%Source_Horn) : alge    'Stop the horn
    
            MsgBox "End of demonstration."
    
        End If  'If 1
    
    
        '--------------------------------------------------
        '   Clean up
        '--------------------------------------------------
        'A buffer can't be deleted while attached to a source, so replace them with NULL buffers
        alSourcei(Sources(%Source_Motor), %AL_BUFFER, 0) : alge     'Assign a NULL buffer to clear the motor's source
        alSourcei(Sources(%Source_Horn), %AL_BUFFER, 0) : alge      'Assign a NULL buffer to clear the horn's source
        alDeleteBuffers %NUM_BUFFERS, Buffers(0) : alge             'Delete all the buffers
    
        alDeleteSources %NUM_SOURCES, Sources(%Source_Motor) : alge 'Delete all the sources
    
        alcError = alcGetError(ByVal Device)    'Clear existing error value
    
        Context = alcGetCurrentContext()        'Get active context
        alcError = alcGetError(ByVal Device)
    
        alcMakeContextCurrent(0)                'Disable the context
        alcError = alcGetError(ByVal Device)
    
        Device = alcGetContextsDevice(Context)  'Get device for active context
        alcError = alcGetError(ByVal Device)
    
        alcDestroyContext Context               'Destroy the context
        alcError = alcGetError(ByVal Device)
    
        alcCloseDevice(ByVal Device)            'Close the device
    
        'NOTE: never pass a closed device to alcGetError, or it will GPF
    
    End Function
    
    '**************************************
    Save this as "OpenAl.inc"
    Code:
    %NUM_SOURCES    = 2
    %NUM_BUFFERS    = 2
    %Buffer_Motor   = 0
    %Buffer_Horn    = 1
    %Source_Motor   = 0
    %Source_Horn    = 1
    
    'This generates a compiler error when some values are out of range
    #If (%NUM_SOURCES = 0) Or (%NUM_BUFFERS = 0)
    ! You must have at least one buffer and one source.
    ! Set %NUM_SOURCES and %NUM_BUFFERS as needed.
    #EndIf
    
    '**************************************
    %MAX_PATH       = 260
    
    
    'Official OpenAl equates
    %AL_INVALID                            = -1&
    %AL_INVALID_VALUE                      = &HA003
    %AL_NONE                               = 0
    %AL_FALSE                              = 0
    %AL_TRUE                               = 1
    
    'Indicate Source has relative coordinates.
    %AL_SOURCE_RELATIVE                        = &H202
    
    'Directional source, inner cone angle, in degrees.
    'Range:    [0-360]
    'Default:  360
    %AL_CONE_INNER_ANGLE                       = &H1001
    
    'Directional source, outer cone angle, in degrees.
    'Range:    [0-360]
    'Default:  360
    %AL_CONE_OUTER_ANGLE                       = &H1002
    
    
    'Specify the pitch to be applied, either at source,
    ' or on mixer results, at listener.
    'Range:   [0.5-2.0]
    'Default: 1.0
    %AL_PITCH                              = &H1003
    
    'Specify the current location in three dimensional space.
    'OpenAL, like OpenGL, uses a right handed coordinate system,
    ' where in a frontal default view X (thumb) points right,
    ' Y points up (index finger), and Z points towards the
    ' viewer/camera (middle finger).
    'To switch from a left handed coordinate system, flip the
    ' sign on the Z coordinate.
    'Listener position is always in the world coordinate system.
    %AL_POSITION                           = &H1004
    
    'Specify the current direction.
    %AL_DIRECTION                          = &H1005
    
    'Specify the current velocity in three dimensional space.
    %AL_VELOCITY                           = &H1006
    
    'Indicate whether source is looping.
    'Type: ALboolean?
    'Range:   [AL_TRUE, AL_FALSE]
    'Default: FALSE.
    %AL_LOOPING                            = &H1007
    
    'Indicate the buffer to provide sound samples.
    'Type: ALuint.
    'Range: any valid Buffer id.
    %AL_BUFFER                             = &H1009
    
    
    'Indicate the gain (volume amplification) applied.
    'Type:   ALfloat.
    'Range:  ]0.0-  ]
    'A value of 1.0 means un-attenuated/unchanged.
    'Each division by 2 equals an attenuation of -6dB.
    'Each multiplicaton with 2 equals an amplification of +6dB.
    'A value of 0.0 is meaningless with respect to a logarithmic
    ' scale; it is interpreted as zero volume - the channel
    ' is effectively disabled.
    %AL_GAIN                               = &H100A
    
    'Indicate minimum source attenuation
    'Type: ALfloat
    'Range:  [0.0 - 1.0]
    'Logarthmic
    %AL_MIN_GAIN                           = &H100D
    
    'Indicate maximum source attenuation
    'Type: ALfloat
    'Range:  [0.0 - 1.0]
    'Logarthmic
    %AL_MAX_GAIN                           = &H100E
    
    'Indicate listener orientation.
    'at/up
    %AL_ORIENTATION                        = &H100F
    
    'Specify the channel mask. (Creative)
    'Type: ALuint
    'Range: [0 - 255]
    %AL_CHANNEL_MASK                       = &H3000
    
    'Source state information.
    %AL_SOURCE_STATE                           = &H1010
    %AL_INITIAL                                = &H1011
    %AL_PLAYING                                = &H1012
    %AL_PAUSED                                 = &H1013
    %AL_STOPPED                                = &H1014
    
    'Buffer Queue params
    %AL_BUFFERS_QUEUED                         = &H1015
    %AL_BUFFERS_PROCESSED                      = &H1016
    
    'Source buffer position information
    %AL_SEC_OFFSET                             = &H1024
    %AL_SAMPLE_OFFSET                          = &H1025
    %AL_BYTE_OFFSET                            = &H1026
    
    'Source type (Static, Streaming or undetermined)
    'Source is Static if a Buffer has been attached using AL_BUFFER
    'Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers
    'Source is undetermined when it has the NULL buffer attached
    %AL_SOURCE_TYPE                            = &H1027
    %AL_STATIC                                 = &H1028
    %AL_STREAMING                              = &H1029
    %AL_UNDETERMINED                           = &H1030
    
    'Sound samples: format specifier.
    %AL_FORMAT_MONO8                       = &H1100
    %AL_FORMAT_MONO16                      = &H1101
    %AL_FORMAT_STEREO8                     = &H1102
    %AL_FORMAT_STEREO16                    = &H1103
    
    'source specific reference distance
    'Type: ALfloat
    'Range:  0.0 - +inf
    'At 0.0, no distance attenuation occurs.  Default is
    '1.0.
    %AL_REFERENCE_DISTANCE                     = &H1020
    
    'source specific rolloff factor
    'Type: ALfloat
    'Range:  0.0 - +inf
    %AL_ROLLOFF_FACTOR                         = &H1021
    
    'Directional source, outer cone gain.
    'Default:  0.0
    'Range:    [0.0 - 1.0]
    'Logarithmic
    %AL_CONE_OUTER_GAIN                        = &H1022
    
    'Indicate distance above which sources are not
    'attenuated using the inverse clamped distance model.
    'Default: +inf
    'Type: ALfloat
    'Range:  0.0 - +inf
    %AL_MAX_DISTANCE                           = &H1023
    
    'Sound samples: frequency, in units of Hertz [Hz].
    'This is the number of samples per second. Half of the
    ' sample frequency marks the maximum significant
    ' frequency component.
    %AL_FREQUENCY                              = &H2001
    %AL_BITS                                   = &H2002
    %AL_CHANNELS                               = &H2003
    %AL_SIZE                                   = &H2004
    
    'Buffer state.
    'Not supported for public use (yet).
    %AL_UNUSED                                 = &H2010
    %AL_PENDING                                = &H2011
    %AL_PROCESSED                              = &H2012
    
    'Errors:
    %AL_NO_ERROR                               = %AL_FALSE
    
    'Invalid Name paramater passed to AL call.
    %AL_INVALID_NAME                           = &HA001
    
    'Invalid parameter passed to AL call.
    %AL_ILLEGAL_ENUM                           = &HA002
    %AL_INVALID_ENUM                           = &HA002
    
    'Invalid enum parameter value.
    %AL_INVALID_VALUE                          = &HA003
    
    'Illegal call.
    %AL_ILLEGAL_COMMAND                        = &HA004
    %AL_INVALID_OPERATION                      = &HA004
    
    
    'No mojo.
    %AL_OUT_OF_MEMORY                          = &HA005
    
    'Context strings
    %AL_VENDOR                                 = &HB001
    %AL_VERSION                                = &HB002
    %AL_RENDERER                               = &HB003
    %AL_EXTENSIONS                             = &HB004
    
    '   Global tweakage.
    
    'Doppler scale.  Default 1.0
    %AL_DOPPLER_FACTOR                         = &HC000
    
    'Tweaks speed of propagation.
    %AL_DOPPLER_VELOCITY                       = &HC001
    
    'Speed of Sound in units per second
    %AL_SPEED_OF_SOUND                         = &HC003
    
    'Distance models
    'used in conjunction with DistanceModel
    'implicit: NONE, which disances distance attenuation.
    %AL_DISTANCE_MODEL                         = &HD000
    %AL_INVERSE_DISTANCE                       = &HD001
    %AL_INVERSE_DISTANCE_CLAMPED               = &HD002
    %AL_LINEAR_DISTANCE                        = &HD003
    %AL_LINEAR_DISTANCE_CLAMPED                = &HD004
    %AL_EXPONENT_DISTANCE                      = &HD005
    %AL_EXPONENT_DISTANCE_CLAMPED              = &HD006
    
    '**************************************
    '   ALC equates
    %ALC_INVALID                            = 0
    %ALC_FALSE                              = 0
    %ALC_TRUE                               = 1
    
    %ALC_FREQUENCY                            = &H1007
    %ALC_REFRESH                              = &H1008
    %ALC_SYNC                                 = &H1009
    %ALC_MONO_SOURCES                         = &H1010
    %ALC_STEREO_SOURCES                       = &H1011
    
    'ALC errors
    %ALC_NO_ERROR                             = %ALC_FALSE
    %ALC_INVALID_DEVICE                       = &HA001
    %ALC_INVALID_CONTEXT                      = &HA002
    %ALC_INVALID_ENUM                         = &HA003
    %ALC_INVALID_VALUE                        = &HA004
    %ALC_OUT_OF_MEMORY                        = &HA005
    
    
    'The Specifier string for default device
    %ALC_DEFAULT_DEVICE_SPECIFIER          = &H1004
    %ALC_DEVICE_SPECIFIER                  = &H1005
    %ALC_EXTENSIONS                        = &H1006
    %ALC_MAJOR_VERSION                     = &H1000
    %ALC_MINOR_VERSION                     = &H1001
    %ALC_ATTRIBUTES_SIZE                   = &H1002
    %ALC_ALL_ATTRIBUTES                    = &H1003
    
    'Capture extension
    %ALC_CAPTURE_DEVICE_SPECIFIER          = &H310
    %ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER  = &H311
    %ALC_CAPTURE_SAMPLES                   = &H312
    
    
    '**************************************
    '   EAX equates
    
    'used by DSPROPERTY_EAXLISTENER_ENVIRONMENT
    %EAX_ENVIRONMENT_GENERIC                      = 0
    %EAX_ENVIRONMENT_PADDEDCELL                   = 1
    %EAX_ENVIRONMENT_ROOM                         = 2
    %EAX_ENVIRONMENT_BATHROOM                     = 3
    %EAX_ENVIRONMENT_LIVINGROOM                   = 4
    %EAX_ENVIRONMENT_STONEROOM                    = 5
    %EAX_ENVIRONMENT_AUDITORIUM                   = 6
    %EAX_ENVIRONMENT_CONCERTHALL                  = 7
    %EAX_ENVIRONMENT_CAVE                         = 8
    %EAX_ENVIRONMENT_ARENA                        = 9
    %EAX_ENVIRONMENT_HANGAR                       = 10
    %EAX_ENVIRONMENT_CARPETEDHALLWAY              = 11
    %EAX_ENVIRONMENT_HALLWAY                      = 12
    %EAX_ENVIRONMENT_STONECORRIDOR                = 13
    %EAX_ENVIRONMENT_ALLEY                        = 14
    %EAX_ENVIRONMENT_FOREST                       = 15
    %EAX_ENVIRONMENT_CITY                         = 16
    %EAX_ENVIRONMENT_MOUNTAINS                    = 17
    %EAX_ENVIRONMENT_QUARRY                       = 18
    %EAX_ENVIRONMENT_PLAIN                        = 19
    %EAX_ENVIRONMENT_PARKINGLOT                   = 20
    %EAX_ENVIRONMENT_SEWERPIPE                    = 21
    %EAX_ENVIRONMENT_UNDERWATER                   = 22
    %EAX_ENVIRONMENT_DRUGGED                      = 23
    %EAX_ENVIRONMENT_DIZZY                        = 24
    %EAX_ENVIRONMENT_PSYCHOTIC                    = 25
    %EAX_ENVIRONMENT_COUNT                        = 26
    
    %DSPROPERTY_EAXLISTENER_NONE                  = 0
    %DSPROPERTY_EAXLISTENER_ALLPARAMETERS         = 1
    %DSPROPERTY_EAXLISTENER_ROOM                  = 2
    %DSPROPERTY_EAXLISTENER_ROOMHF                = 3
    %DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR     = 4
    %DSPROPERTY_EAXLISTENER_DECAYTIME             = 5
    %DSPROPERTY_EAXLISTENER_DECAYHFRATIO          = 6
    %DSPROPERTY_EAXLISTENER_REFLECTIONS           = 7
    %DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY      = 8
    %DSPROPERTY_EAXLISTENER_REVERB                = 9
    %DSPROPERTY_EAXLISTENER_REVERBDELAY           = 10
    %DSPROPERTY_EAXLISTENER_ENVIRONMENT           = 11
    %DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE       = 12
    %DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION  = 13
    %DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF       = 14
    %DSPROPERTY_EAXLISTENER_FLAGS                 = 15
    
    %DSPROPERTY_EAXBUFFER_NONE                    = 0
    %DSPROPERTY_EAXBUFFER_ALLPARAMETERS           = 1
    %DSPROPERTY_EAXBUFFER_DIRECT                  = 2
    %DSPROPERTY_EAXBUFFER_DIRECTHF                = 3
    %DSPROPERTY_EAXBUFFER_ROOM                    = 4
    %DSPROPERTY_EAXBUFFER_ROOMHF                  = 5
    %DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR       = 6
    %DSPROPERTY_EAXBUFFER_OBSTRUCTION             = 7
    %DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO      = 8
    %DSPROPERTY_EAXBUFFER_OCCLUSION               = 9
    %DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO        = 10
    %DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO      = 11
    %DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF         = 12
    %DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR     = 13
    %DSPROPERTY_EAXBUFFER_FLAGS                   = 14
    %DSPROPERTY_EAX_BUFFERPROPERTY                = 15
    
    'EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722}
    $DSPROPSETID_EAX20_BufferProperties = Guid$("{0306A6A7-B224-11d2-99E5-0000E8D8C722}")
    'use this if your compiler doesn't support "GUID$"
    '$DSPROPSETID_EAX20_BufferProperties = Chr$(&HA7, &HA6, &H06, &H03, &H24, &HB2, &HD2, &H11, &H99, &HE5, &H00, &H00, &HE8, &HD8, &HC7, &H22)
    
    'Listener properties {0306A6A8-B224-11D2-99E5-0000E8D8C722}
    $DSPROPSETID_EAX20_ListenerProperties = Guid$("{0306A6A8-B224-11D2-99E5-0000E8D8C722}")
    'use this if your compiler doesn't support "GUID$"
    '$DSPROPSETID_EAX20_ListenerProperties = Chr$(&HA8, &HA6, &H06, &H03, &H24, &HB2, &HD2, &H11, &H99, &HE5, &H00, &H00, &HE8, &HD8, &HC7, &H22)
    
    %DSPROPERTY_EAXLISTENER_IMMEDIATE = &H00000000  'changes take effect immediately
    %DSPROPERTY_EAXLISTENER_DEFERRED  = &H80000000  'changes take effect later
    %DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS = %DSPROPERTY_EAXLISTENER_NONE Or %DSPROPERTY_EAXLISTENER_IMMEDIATE
    
    %DSPROPERTY_EAXBUFFER_IMMEDIATE = &H00000000 'changes take effect immediately
    %DSPROPERTY_EAXBUFFER_DEFERRED  = &H80000000 'changes take effect later
    %DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS = %DSPROPERTY_EAXBUFFER_NONE Or %DSPROPERTY_EAXBUFFER_IMMEDIATE
    
    '**************************************
    
    Type EAXBUFFERPROPERTIES Dword
        lDirect As Long                 'direct path level
        lDirectHF As Long               'direct path level at high frequencies
        lRoom As Long                   'room effect level
        lRoomHF As Long                 'room effect level at high frequencies
        flRoomRolloffFactor As Single   'like DS3D flRolloffFactor but for room effect
        lObstruction As Long            'main obstruction control (attenuation at high frequencies)
        flObstructionLFRatio As Single  'obstruction low-frequency level re. main control
        lOcclusion As Long              'main occlusion control (attenuation at high frequencies)
        flOcclusionLFRatio As Single    'occlusion low-frequency level re. main control
        flOcclusionRoomRatio As Single  'occlusion room effect level re. main control
        lOutsideVolumeHF As Long        'outside sound cone level at high frequencies
        flAirAbsorptionFactor As Single 'multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
        dwFlags As Dword                'modifies the behavior of properties
    End Type
    
    'for coordinates, for example
    Type THREESINGLES Dword
        x As Single
        y As Single
        z As Single
    End Type
    
    'for orientation, for example
    Type SIXSINGLES Dword
        fx As Single
        fy As Single
        fz As Single
        ux As Single
        uy As Single
        uz As Single
    End Type
    
    
    '**************************************
    '   Call DWord prototype (this might not work for all calls, as is)
    Declare Function CallEaxSet(ListPropGuid As Asciz * 17, ByVal Param As Long, ByRef Value As Dword, ByVal pParam2 As Dword, ByVal szParam2 As Long) As Long
    
    '   OpenAl32.DLL imports
    Declare Function alIsExtensionPresent Lib "OpenAl32.DLL" Alias "alIsExtensionPresent"(ExtNam As Asciz * 9) As Long
    Declare Function alGetProcAddress Lib "OpenAl32.DLL" Alias "alGetProcAddress"(ProcName As Asciz * 40) As Dword
    Declare Function alGetError Lib "OpenAl32.DLL" Alias "alGetError"() As Long
    
    Declare Sub alGenBuffers Lib "OpenAl32.DLL" Alias "alGenBuffers"(ByVal NumBuffers As Long, ByRef FirstBuffer As Dword)
    Declare Sub alBufferData Lib "OpenAl32.DLL" Alias "alBufferData"(ByVal IdBuff As Dword, ByVal FormatCode As Long, ByVal BufferPtr As Dword, ByVal BufferSize As Dword, ByVal Frequency As Long)
    Declare Sub alDeleteBuffers Lib "OpenAl32.DLL" Alias "alDeleteBuffers"(ByVal NumBuffs As Long, ByRef FirstBuffer As Dword)
    
    Declare Sub alGenSources Lib "OpenAl32.DLL" Alias "alGenSources"(ByVal NumSources As Long, ByRef FirstSource As Dword)
    Declare Sub alSourcePlay Lib "OpenAl32.DLL" Alias "alSourcePlay"(ByVal IdSource As Dword)
    Declare Sub alSourceStop Lib "OpenAl32.DLL" Alias "alSourceStop"(ByVal IdSource As Dword)
    Declare Sub alDeleteSources Lib "OpenAl32.DLL" Alias "alDeleteSources"(ByVal NumSources As Dword, ByRef FirstSource As Long)
    Declare Sub alSourcef Lib "OpenAl32.DLL" Alias "alSourcef"(ByVal IdSource As Dword, ByVal Param As Long, ByVal Value As Single)
    Declare Sub alSource3f Lib "OpenAl32.DLL" Alias "alSource3f"(ByVal IdSource As Dword, ByVal Param As Long, ByVal Value1 As Single, ByVal Value2 As Single, ByVal Value3 As Single)
    '"Values" is essentially an array of three Singles
    Declare Sub alSourcefv Lib "OpenAl32.DLL" Alias "alSourcefv"(ByVal IdSource As Dword, ByVal Param As Long, ByRef ThrSin As THREESINGLES)
    Declare Sub alSourcei Lib "OpenAl32.DLL" Alias "alSourcei"(ByVal IdSource As Dword, ByVal Param As Long, ByVal Value As Long)
    
    Declare Sub alListenerf Lib "OpenAl32.DLL" Alias "alListenerf"(ByVal Param As Long, ByVal Value As Single)
    Declare Sub alListener3f Lib "OpenAl32.DLL" Alias "alListener3f"(ByVal Param As Long, ByVal Value1 As Single, ByVal Value2 As Single, ByVal Value3 As Single)
    '"Values" is essentially an array of three Singles
    Declare Sub alListenerfv Lib "OpenAl32.DLL" Alias "alListenerfv"(ByVal Param As Long, ByRef ThrSin As THREESINGLES)
    Declare Sub alListeneri Lib "OpenAl32.DLL" Alias "alListeneri"(ByVal Param As Long, ByVal Value As Long)
    
    'ALCDevice parameters are treated as pointers to device names and so they're passed ByVal
    Declare Function alcOpenDevice Lib "OpenAl32.DLL" Alias "alcOpenDevice"(DeviceName As Asciz * 40) As Dword
    Declare Function alcCloseDevice Lib "OpenAl32.DLL" Alias "alcCloseDevice"(DeviceName As Asciz * 40) As Long
    Declare Function alcCreateContext Lib "OpenAl32.DLL" Alias "alcCreateContext"(ByVal ALCdevice As Dword, ByRef AttrList As Dword) As Dword
    Declare Function alcMakeContextCurrent Lib "OpenAl32.DLL" Alias "alcMakeContextCurrent"(ByVal ALCContext As Dword) As Dword
    Declare Function alcGetContextsDevice Lib "OpenAl32.DLL" Alias "alcGetContextsDevice"(ByVal ALCContext As Dword) As Dword
    Declare Function alcGetCurrentContext Lib "OpenAl32.DLL" Alias "alcGetCurrentContext"() As Dword
    Declare Sub alcDestroyContext Lib "OpenAl32.DLL" Alias "alcDestroyContext"(ByVal ALCContext As Dword)
    Declare Function alcGetString Lib "OpenAl32.DLL" Alias "alcGetString"(ByVal pALCdevice As Dword, ByVal parm As Long) As Dword
    Declare Function alcGetError Lib "OpenAl32.DLL" Alias "alcGetError"(DeviceName As Asciiz * 40) As Long
    
    '   alut.DLL imports
    Declare Sub alutLoadWAVFile Lib "alut.DLL" Alias "alutLoadWAVFile"(WaveFileName As Asciz * %MAX_PATH, ByRef FormatCode As Long, ByRef DataBuffer As Long, ByRef DataSize As Long, ByRef Frequency As Long, ByRef LoopFlag As Long)
    Declare Sub alutUnloadWAV Lib "alut.DLL" Alias "alutUnloadWAV"(ByVal FormatCode As Long, ByVal pDataBuffer As Long, ByVal DataSize As Long, ByVal Frequency As Long)
    
    '   Winmm.DLL imports
    Declare Function waveInGetNumDevs Lib "Winmm.DLL" Alias "waveInGetNumDevs"() As Dword
    Declare Function waveOutGetNumDevs Lib "Winmm.DLL" Alias "waveOutGetNumDevs"() As Dword
    
    
    Declare Function LoadLibrary Lib "KERNEL32.DLL" Alias "LoadLibraryA" (lpLibFileName As Asciiz) As Long
    Declare Function FreeLibrary Lib "KERNEL32.DLL" Alias "FreeLibrary" (ByVal hLibModule As Dword) As Long
    Declare Function lstrlen Lib "KERNEL32.DLL" Alias "lstrlenA" (lpString As Asciiz) As Long
    
    '**************************************
    
    Sub alge()  'checks for errors after calls to "al" (not "alc") imports
    #If %Def(%Debug)
    
        Dim alError  As Global Long
        Static cnt  As Long
        Local ls    As String
    
        Incr cnt
        alError = alGetError()
        Select Case alError
            Case %AL_INVALID
                ls = "Invalid"
            Case %AL_INVALID_VALUE
                ls = "Invalid value"
            Case %AL_INVALID_NAME
                ls = "Invalid name"
            Case %AL_ILLEGAL_ENUM
                ls = "Illegal enum"
            Case %AL_INVALID_ENUM
                ls = "Invalid enum"
            Case %AL_ILLEGAL_COMMAND
                ls = "Illegal command"
            Case %AL_INVALID_OPERATION
                ls = "Invalid operation"
            Case %AL_OUT_OF_MEMORY
                ls = "Out of memory"
            Case %AL_NO_ERROR
                ls = ""
            Case Else 'unknown error
                ls = "(unknown)"
        End Select
    
        If Len(ls) Then
            ls = "Error: " & ls & $CrLf & "...at ""al"" call number: " & Format$(cnt)
    
    #If %Def(%PrintErrorsToFile)
            Static ff   As Long
            If ff = 0 Then
                ff = FreeFile
                Open "AlError.Log" For Output As #ff
                Print# ff, "Error log for calls to ""al"" imports."
                Print# ff, "Time and Date: " & Time$ & ", " & Date$
                Print# ff,
            End If
            Print# ff, ls
    #Else
            MsgBox ls
    #EndIf
    
        End If
    
    #EndIf
    End Sub
    
    '**************************************
    Save this as "WavsBinBas.bas"
    Running this will create a zip file containing the WAV files needed
    by the demo.
    Code:
    ' File    : Wavs.zip
    ' Len     : 9884
    ' Created : 01-29-2006 - 15:37:56 using BinBas GUI 2.02
    
    #Compile Exe
    
    Sub BinBas1( T As String )
    
    Dim a&: For a& = 1 To DataCount: T = T & Read$( a& ): Next a&
    
    Data 504B0304140002000800E6B1383445D635B79E140000901B0000090000004D6F746F722E7761762D
    Data 59DD6B22E99AEF73B7977BBFB0BBEC39ECCC4577D3214D279004A260824154145C3F405D95554111
    Data AD23165575615551D65255285285148A0A7EA020264442129A342481A4499AA67B68986166186638
    Data 7FC9FE9E9A2DD39D5856E9FB3EEFF3FB7A0D798F8EFEF75F5EBCF82F57C4F33FE5BFFFFB3FBF78F1
    Data E22F78FC47E485F3EF2F2FFEE945EEBFFFFEDF595C130E0682E1683253AC542AD55AAD5A29177399
    Data 4CB6444F986AAD5AADD61A0D8E97544D6D2912DF606A38EA82ACEA46B7DBEDB475DD303A9D6EBBAD
    Data E10A4D516451925B78D1B4FB83C16838E875AD1E1E56AF6B68BA819BCC9ED9B58693C97834C6AB9D
    Data 366E37AD5EC768E3C241BFD7338D36EEED77B526CBD6D9062F2A9A8613B63DE89BDD5ECFEEF7CC8E
    Data 351CD856B7A3AB783B8C415324DD686BAD96660D47C37E4713388E1764A36D9978CB6EABD914595E
    Data 6A19BADEE974F496C8D6AAA56C3A934D0443917038E40FF84FFCF809A012C15030188AC6D3E94422
    Data 1C0C4752C958C47FE4DADBDD73FB42915834148AC4E3D14828180A8702C1682257AE5472A9443496
    Data C864738562A9542C140BF952A3294AA2C8F3A2614F1667E7EBD96436199AAAD4145B1AEAA8757A83
    Data 81D5D66445D5F476BBD3ED628293C97C359FCE168BF9A46FA1B2DDDE60685BA8E178361D0E502A0B
    Data B5EA58F668686ACD062BB6542C489367055154F00766CCB34C83651B9CC07358B23A2D54A558CC17
    Data 4AC552B954CC67D278E42B8D3AC3D4EB4C5D68A22C4D8E6D4A12FEC2584554A863DA839E814A6209
    Data 5BB2E28CB6D5324CB36DD8037B349DCD87D3C974D43507B4AA7D0B03EDF66CD36A352BF954A15229
    Data 162A4C8D61795EA85579AE5E29633482C0D699523691CEE792C51A27894DB6900EFB7CB162AD5C2D
    Data 1533C9E091EBC0ED8F1518A658CE2493B1582255A9339CD0C0B0EB68C86A03EF5617345DE2154DE2
    Data AA4CAD5CE1054951D1569D8E6D1A9A2136984AA55C2E57EBBC24F182C8B32C3AA029EB5ABB63F5FB
    Data 9D96D292B1264D96E1B45EBF3F98AF17E3B6A2085C8D41A3337C53D2ACBEDD96C566ABAD1BD66084
    Data 6277DB7A4B92049A4C5394355DA74E36D1EBA83F8722F3A2DCD2D1D3A6D9C58F533434BFD8141403
    Data 77CA4D7459B5CE356975448EC1D8AAA54211FFD7599E164F95B806D76CA24F9A82C063B83C014711
    Data 857A319FCB57EA1CC7D64AF962B5C1F2CDA6202A6DF4C37864A309744D5565E70E8C80D64857F1B1
    Data 5253601B585C7C4A2E934EE78BA54AAD813741E74B02A620B0954236938C46C2A1703491C9E70BF9
    Data 543C914CA5D2A9743A9588C762F1783C8167742293CB176BD57C2A1646932771512A932BD5185ACC
    Data 669363AA956A858E1A2BA003B9260AD1364DC0D832144906CA4CCBECAA8A24292DA3DB1F8C004A4B
    Data 57891AB44E7F3C992FA793C5E9D5EDFDD3D3C3DD879B9B8BD319B57CBB8B3643F1C7B3E5F9E6E292
    Data 8EEB8BCDF9E97ABD3CDD5C6C56D391DD1F4E96E73873B65A2EA640D562BE5C2CD6CB5157621B820A
    Data CCF4FA3D43D55AA2C0B19833DA9A1ABB510389B14C311D8B4442447791E0C989F7C87B7CB8FF767B
    Data 7BCFE305E683DEE313AFD7777CECDE7BB7FDEAD59B37DB6FF7F677DEEEECBB4EFC5EB7DBE539F67A
    Data 03E190EFE86067F7F0D07D78B8F76E77DFE5F1788E8E8EBC1E6F28912F15D2F15804CD9B2F561A54
    Data 28516039009ED811CCD71DCED7A798D7E6E2FAF6FEFEF1F1E1EEE6FDD5D5FBDB8F9F7FF8F6F5D3E3
    Data EDEDEDFDE3D3D3C7A7E7E7E78FF7B737EF6F6EEF1E1E9E9E3F7FFBF9B75FBE7D797A7CC071777D75
    Data B9395D4E0796811ED075ADD5AC574AC5227ED0FCF96C26456B988C4763F118D638934CC4C227EEC3
    Data BDB7AF5FBED9DE7EF7EEDDDB773BEFDE6EBFC5D07777F07BEBD5EBADAD977FFDD77FFBEB7FBEDCDA
    Data 7179038100C8D01F8EA772A572B5924F6332354EC69A0C27D3C57C319F4FC7136AC3E56673757171
    Data 71767A717671F5E1E1F9C73FFEF1C72FDF3E61B85F3E3FDD5F5F5C5CDEDE7DFCFAC3CF7FFCF1EBEF
    Data 3F7DFEF2F0F0F1D3C7BBEB9BBB87CF9F9FEECE1793E974319B8C4693C9A0DBE26A18762291C46853
    Data E9442C160A4523E8C6B0DFEF3B3E3CC282ECEF1E78FC41EFE1FEC181CBED3E3CF2BA5D7BDB6FBEDF
    Data 7AB3BBB3B38753877BBB3B6ED781CB130884025ED7CEEE3BB73791CBA6A2A170B258AD95F3F94C26
    Data 432D5CA8828EEA245E5AC71E8EC6F3E572361B59860A1843992CBB3FEA835F47E3E962B53A3BDB5C
    Data 9E9FADD6EBD3B3F56A319B2D37EFDF5F5F5D6F30EDCD7AB55AAEE698C068B65A9F9F6FCE4E4FCF36
    Data E76B54077DDC315A22F100CF3910550087B6DA9278A093A90132605D501118560241424B996A0143
    Data 0D8563A835DBA815212019942101106680C64C369FCD668B957AA38ED18B225A9BC927689D51AE4C
    Data 269703BB9789E2A1DCA54A31138F40D20358C2642A0E21CB178A380A855C2E0B9427E251F4462295
    Data 435DA0EF0D96E31AD5628E9401F285D154CBE54AB5DEA01281FB49308D962C4BA220EB80B70D1557
    Data 1545522144E0FF4ED7C28F3D9C8C66F3F962325B9F5E5C5E9C2FC73660381A8F27A3C170345F9D12
    Data 78F1C2E6FDF51DA08E826E36E767CBC57C046698CD178BC9A06F8F27B3E964D4C727D8C321E40E3A
    Data 6EEA32985194254582B87140B3502BE6F3B942B9C643528AD0DD8853B502E80E930DFABC3E989958
    Data BA582962AED91C142F99CE4393818B443C095CE673E803D0591CF213080622B124843E968670E592
    Data 5419D4068540EB1013A27C21BF1FDD18C315855C2A99A105C1DDE95CB9566F2A866959B60D670389
    Data 869D1980C1AC3E9A670481849F8196F6C6CBD373F4CBE5055A08E0BF7AEF1C3737EF2FCE37975757
    Data 5760B2D3F562369D4D9DC95B5DB88136BA45111BC534108156C081E1637418523AEBB076341C38F1
    Data FA31AE041D007B2CECF39E9C9C10608E3C87FB7B7BFBBBBB3BBBFB87C7C148349A00980B6802DC5A
    Data AA32A4062416AA6EF5C0D8C37EBFD71D8E1610F5D9EAF4EAFDF5E5E6EAEAFAFDDDFDE3E7C7C72F4F
    Data 0F3737B70F9FBF3C7F7AFA0AE03E3F7CB8BFB9018A2F31EAD57A3C18C3E2F54CDB8663D03445E399
    Data 5ABDC1EAA6D1E2997C3A5D84E0156B952CEC116C13E0ECDADFD9019023109A30953E1E4BC6C3C163
    Data D79EDB1BC1F492C07FA650A99369C944C361343216370D3280D70A613D8819E020981A5B2FA1DDAB
    Data 985309B0104449EB985D05525D87FCC306D57109DF94D54EBB3F5DCE26E3FEB0ABA98A2CB5CCE178
    Data BC58AE17A3C9D0EA9883D17CBE72FA10A6B0A59B83C96C369B0C467617A601AB37E8B55B42032811
    Data 14ADDD857384F968A0824D14515155C01C33AE30BCA8B5E142D5A6002C816120CA2AF41DAE98BC29
    Data 7E41D7CC8EA680AACB4507630C69BA085186D8330D4804F40AB7424D610174D8C10E1C5E250B1284
    Data F6C2A7A2F12A4CBD5ACC67D3906AF46C2A1E4B80E7B1FAE8D2442A8B2B708AC42D94C816CA559880
    Data 7C8A161E42048FE7D8824A113D9E4864AB020C892CD64BF90259111270B20904B1A6E87CBE093F6A
    Data F5303D47D76197ECC160D0EF0FE1D7FB8309A9C0D8361DD7D32378AFC0862B74F0744E6D3CE88237
    Data 40A770E5EDDE68069A1CF56CD826DD90110E64D568A38E2DBDD78783EC0F6773541B02698F801F4D
    Data E61BF05F1D181A7360DB43936A8AB1B39C04CF0CCFC3317033F0F69C20CB586E81675024C0229DCC
    Data 1472D964381C250F934AE14C22E40F06FDBE40241C0D0305F158C8E7DADDDD7DBBBDE33AF292D5F7
    Data 07F0BA3F1483DEE0AF70225D2C00F6D1086C6AB94447B90C338B8FABD7EA9CD49D9E9E2DC604D19E
    Data A9939FE3C8B289AD36306F1105209F20B40C87D3E918AC371C4FC6B0277DCBB4503188C91288395D
    Data 8D892D7A741D52C17A6EC325CA708D0A0E24269846E4018DACAA80F6C062C0B281B032803D682B8D
    Data 805101367299643C990394D1E5F0618CE3F739880B18923892DC2AEC6ABB8D6C6442D286A3E97408
    Data 94777478C6A64A760C5007086643A425DB6CABBA009B8A8531D0EED562190D5F693400C26AB55C44
    Data DA094692888388135CAD944D6673E52224A95CC7AF98FFD87D142F31B889A9E4A1384459500FD069
    Data 2E1D0EA5CA02662693CE4007592C1E19C746A34AF2D29264057148D154C3B668C9B1A2082298039C
    Data 9342960975E1EAE07D9EDA526D0FA633AA9F21B2A4848201E6B2312F035EBF5E65385E9424987DC4
    Data 019D87DD637996322BDE1F4CAC23B8D69079300E548AFC39560D415357C93A530AD334123A499445
    Data C1B90B065FEED8C4C82A0B83856AC384632C0AD22ED2260700F34D05408788A33D357380E6B0019C
    Data 2EC106F2DF6C54C1B9954613DAC993FF04EA3932CFC4BD70C630EEB20C2DA77081B56BD43129A64C
    Data 428D14596F3AAF1144A9134119D06530401DEF502F4018523034B04B71B47BCC71B4F07B200B3C09
    Data 23C186C1AD70FA7835912D379071F2D91C8E4C32120C06C2893CDE09F108515100241139E426DF80
    Data 9FC7FA6020C8C99823B2BA5323CBD1246BB458CEA6A30109BED9EB8F97ABF5D9D9F9D97C3C5FACCF
    Data 2FE1541F9E3E7F7D7EBC39031740D0A7E8FDF972B5383DBFFC7077FFE1FAFAFCF2FAEA6A0325BCBE
    Data DE40FDAFEF1FEF1F6FAFD6B3616F389C0C1DC91F8C807FA1562A32027AD7EAC131B7885D11990A80
    Data 7706BA57AA94B114B9543C14F0B90F48E3F6DD273EFF89C773B0B3F5EEF0E8E4C477EC761F79BD7E
    Data 9FC7B5BBFDFABBEFBFFBEEFBD7BBBBEFB6E07DDF6EBFFCEE6F64729DE75B5BAFDF1E80088E8F5C6E
    Data F87A8FDBEDF1FA4E42C96CBE002F056D718851D10021CCBFA51A661F091C0887E343E8585FDE3EDE
    Data 3FDCDFDFDE3E7C7CFEF4F9D3D3D3F3D79FFFF1C7EFBFFCF4EB2F3FFFF8F5EB279CFCFAEDC79F7EFA
    Data F1A7DF7EFFFD57FCFEF1874F4F1F3F3EDCDDDF7EF8704DCA7F01B708E7095182B7626BC554182414
    Data 4B66B2003CE2562212F09F1C793C6E971B828E18F26E77EFE0F0F0E0D0E572EDEFEDBC7DF3F2FB97
    Data 6FDEBC7EF5FAF5ABEFFE06F3BE0D5BBFF5E6D5CB576FB6DEEEE14AB72F108A923A400D00390153E8
    Data F6888E7ABD1E0CDBA83F992E37971F308107CA1AB0B097F7771FBF7CF9FAE32FBFFFE3D7DFBE7D7A
    Data 7E7ABA79FCFCC3AFBFFE86697DFBFAF5CBB72FCF1F60656EEE9E3FDD5D2CE1679653C011A881D131
    Data 5468ABD3E78524BA91F243360B53998CF9FDB0E4C787871E5F04BF76F70EF7F70FF7DC07BB7FFA13
    Data 2CDC0EA6B4B7BB8DF5401C3938F6FA0311849030542F958A06E08AE3A9385C5E38814002D325CAB2
    Data DC6C3638DAAAA08D876EB707BB3519F6613907D099AED65235A36DF63A6D8B764E9650FBB3F3CD66
    Data 73B6B9BA797FB946130F467D1CA305DAF16CBD9ECFC6706C7D3038240E9E156D08C3ABEA502943A3
    Data 6C2ECAC40710CCA6F3E1600CE8A301156B1B9A2CD14955161AA449F0FB0D8834669E4B27607742E1
    Data 483C992DD6482A909131EC1AF51674269785B187DD81DC00B940653882C3816D96EC92FFC8ED39F2
    Data 41B600EB5030E0F7F97105EC5E3AF7A797C73550BC12713FCB940919B53A2B085C1DC0E6D1B53091
    Data 267A75E2E831CD7688F0368126C1AD918BB7D1CD88E498F29028CEEC8F17AB05400D151FD9B4F361
    Data 8E8676073E5F2471322CA0138A369943DC60F4E7C8DD282CEA369E4E26B41D3481D347EE81903B1B
    Data 756066AB639090A18C6647066F22EFC0FF10893515C474F82D506CB554C8E7E06ED3D00D62B14834
    Data 12CB94AB55B8DE02324FAE54AB15D2915028E80F4552E94211FD847C07501C2280BB3C2750EF240A
    Data 5CAE141C79CC9030A6A9FAF47F26010B19439563CE26076214197F302704ACC68A70EFB01F906D47
    Data BDC75358708A2298DD821C23B2CB108D359FC1C0135CAFAE2F2F2F915D88C92E4EE7D3D912790FA9
    Data 6F359F4EC64348BADD333165152E4512F846399BCE50F022275100A263D13839751A09C696024D87
    Data B09E881788B22020CC04A49D8845A261DF91C7750070EC011DC768A170D4197CBE5425858084D56A
    Data AC4CFB7464AFC09EF3D93902E8F9D5F9F91C0C35595DDCDCDEDEDF7FF88828FEF8081B7F7B77FBE1
    Data 1E6CF5747FF7700F1BFF1BE2F9FDFD66B13A9B0DA658C0F1A04B466E68A0B5E516D8182C5C4E2632
    Data D96C2C994B47E2690C3A934D2743DEDDDDC363174685111F79037EC84C20E83B72798E022760AE30
    Data 501B0A85703E9E88C660C7F2C06B259B8885BDEE9320AC69389A4816EB2C0003A7A9A8224BB680B6
    Data 914D826D072DDBEE2235A14B68CF4C545B72DB4218C752C0BA183AE408D9108D3CB26D987943EFD8
    Data 03DA3F984CC7BD8EDE81CF41FCA2ED67B9D5E9635AB0933A9815078FA241F815477105165C485B76
    Data BACC3992C743FED1E4788D768CA41674AFD3C6E721CF8882484F691F5095D832E231DE08960BF250
    Data 8125742801D6C4D9C06361529B10752401CBD4550819843CFF279B3B0E3E45593D8D149A40224B93
    Data 8D4743C422B114D17D22164FD1B95C3E8F6E4698A70D3C78FE064C0D656F9692031C2E1C3BC5601E
    Data C6205F4102D569F71C342442C09DBD01144E242BA9EBA026B840A5A5992360B937846A41B74E97A0
    Data 013CEDD2E62E2A8A9C0E930317BF3E03472EA77647C7B444B9292ADD11EE40199D646B22E50FFAE3
    Data 31EDADB7DAF094C3C978B6980E4C724D06EDEDD316A40C33A7A22BA793F97C38A4ECC490B154616B
    Data 5598ACB6AED376721B1617998361AA08F054064AE4D11032768E36DDBDC7AEDDAD37B4EF767C72EC
    Data 714138F0E2F1FED66B28B6874E793CA0031027E23AA4E5F8C41708F8FC3E883ED2EF49289E2E5411
    Data 4361CF58D8CD02E18613691F030AFEFF0F3878E895AC9B7D9A3CA08B4C335F9C6D2E36A767A7B4EB
    Data 7379714E661F335CE1390CCEF5D539F87131EE535A46C81FD076BC899068210621EE8A6C85D8B8CE
    Data 8B8E558538800B1496A83E9D04BF87A10429C7CA952981636510F74A6007D2832AEFA42E5D432CA2
    Data DC089191251E68C779270C5A44A6B220880A41BEDFB788B411997ACE56D5A08B8F5278A680741788
    Data 80DF0AE423199E768F11A59972B50286CD226C8743D178389ACD33709DE5743CE0F38552D46859C4
    Data 4924A7582A87AE4623C185962BACA42A3CA1456DB75BE875AC591381A751E1E04D7985A24ADBEA5A
    Data A3E918965CE259F4688315288CCBEDAEAED3B706B4236C280A6D889BCEF73DBD166D5FC93A62470F
    Data B3EA6A22B2002A502A548596D1432E990D3B0A40C5D62118D053783064A00610512E576B75587AEE
    Data CF7D7D32CECE97164E93AB78883C265B82EDE7E0A381F1765B335A1CA484329C2401E5B40DA7511E
    Data D1601D285FD0571B30C07F7E196341D3C131A63DB03B2ACF54CBD5BA0024A9547762051DFC800149
    Data 8A86A06662451C7DA32D5895100ACEAFD7CA50F63247DFA9D0572C7090E872E4B5FC8BFF03504B03
    Data 041400020008005233691B44E8E9862E1100006C15000008000000486F726E2E776176ED57775CD4
    Data 57B6BF6E4C4C7137311A93552348C48E80800D29D27B87A1C38033C0304399C2F4C2F4CECC30C350
    Data 6628030C1D0401E9620144112496602F51D35C4BD6683631B96F3465F3796F372F7FECE7F3FE7967
    Data E67ECE2DE7DE73BEA77C3EBF1315E8E777E03D0010FBE37CD138A2F53B00804596DFA358F0722C02
    Data AF83034822D2D322231449E552B148281489250AB54655A21072B96CA6A85457DD373D5D918C2423
    Data F3DB3A18445284A7EB5FC052C7809040448CDD9BEF5A2FB70ACDCC178873135131EEC922ADF90A84
    Data FF28314EEA8F423876F7EBE1F9A3A9FEDCBEB9EF211C5A2AEFB722C356BFDE4356314C8B29E8586B
    Data 7F72E83200962FDBA2EF4DCA1B4B0D9BA500B79952F9447910E1B02E553BA5239FFCB6DB7CFB0E84
    Data 702603C2C0BFC32BAB7AAE39E637586FBC07C39D8FE73A0E32C1B230F00E6A3DF8C8D66EEBEA6D51
    Data B9F914A64822EF6C6B31F2244CC5C8B0F9BCE5765D037C4917BCC7A1026C04E07006003C7700FCEC
    Data 0008F3D8901FEC7BED92D307571F06939F0E85F14FF3CBAEBF50EA7BEAE5AD8B9631292C26A50F9E
    Data 0560D74B2F02B0D60B809DBE16BD28C72DA939B98629FD14843A00E1568BF45A0819F01008B04C8F
    Data 3CFEA229AFEFB9B6F21A7C3AFE591EF6422070440290606379030CC257017614B8C25A9039605DC3
    Data 07AFCF2CA4844D9F51128F3FAAAFB9FC42F91908E76F4278FB5B08EDBBE1530801F8FC1D001F020B
    Data 8CB8FD00BC1F0380B53F006FC42E02CB360D4E066E3F075D3D21AC380F27061F8D5A5EB083B0D5C2
    Data 0202CC758760C75A8FB94C802C02E0CDC825160BB0B600705681A50C83FF6E7E60AE180FA1D402C2
    Data 0742150F1678C1FB20D182E54B085D40DDB36D75F041C2EE10B0D90180D0D4249CEFF248AFC503D0
    Data 155C7CB8F23EDC012E1940CF2CD83337585D31548C636A7498D6ABF33F3EB87E63E1DE2338943907
    Data 7B87BFD3EE9BBF08802E02B0EE00600FC07A0056FBDBC6C52453A2B62054C9F823979F4EA90F5D18
    Data 31CF5C3F333167C9A61F20FC3EF432BC73134EBD5A7DF2FD807800B686835F69E95BEEC96B40026E
    Data 2F735C965236D67BFC9105AB8B185EE88310D1F62DA1FD5AA1CF38FCA2E8E39B7E003B8B70E4C5EE
    Data 4CB624BF0576AA7615D8E9FA5A8244D21208F2A14EF7031FE01A32D45A47A7894FC979E7EA0289AD
    Data 465EFBD4D8A3BF9D7B0A4D1B33EF5F9769FB0B36943CEB5C0C8053AED9B8FD8501AB2CE5E3568908
    Data 16E57EB83D2B3C4256DD3935AE291DD3A12A668E378EDEBB3677CB62D05400FAF6A51EF8B5337075
    Data B7949D25787FF20C7969FF1A9FCD71F4C0B89A12BBE07E6DA27C7EBAF102840FB0A84FEE9FF9EC73
    Data B340653EACCE11DF8751AF3534BBF37AAC81B7CD9BB4248BFAC2F5603BC90EACE7657BAA2F7565E4
    Data F2CBEEDCA364D46B8AAA6BE8E9F8BE0916A94A822F37491BFADA2FC11FF7AF9DAF5CD50D0B011ABF
    Data 3CAF3665CB5BEB504191EA3C4BEA386DB059F5812F5DE9135E92618368D614AADB7A273A7986E31A
    Data 74DFB399BA8153633310DE599F700D41819F822D358B6D2BDE05604FD61EB0CD52017F0D5CF98E5B
    Data 92D69812C4A946F92AE69AE97513A3B3108EE06B4C9D101A54273482F3B01D7CF4840416E022508B
    Data 003C4BEE517DAD9C76DA6DF9AB3D2AD42A24AFF4F663E1266E5B8E098EA7B25532AD061521995585
    Data D42FD0121A5B0855CF2175DD68C39B124804DA7180185A0F645F28FFB20B13149D9F13B261B91D92
    Data 1EBD657B69AFCB47CAF6F468A19EAB6A199A3A5888348CD5549EBB6654DF8655EB8E7EBFDA154E02
    Data FAE3B556B52EC036CB16F8E0B7BEF7A18D9BDB470E212C6AB154C84787251806F5E583B5A52D2D53
    Data CF9F0891C76E76CCC3095AF57757EDBDC602D7DDBBBFF8D5A1705040B5D40C1BE5E3E4E0B1EAF538
    Data 7194670CB598C2317D35E7BEE1F097D5C3F7AA0FA894FC46CDDE9885CBB9F8E9E6B4DC19287CAFED
    Data 5946EEDF5520D3F42176660F88E5E414084A825EB129AAE462127C0F64A5A46426F86769740CBE88
    Data 892548A41583FD7A635BA5ACBCA1A6FAD8F3CFE37C6E0C64DC7CB0F28DB38A8DC7870040210276AC
    Data 58EDED6BE351E463ED129D9B8DC41B7A5901AC01599A64BA556AE8EAEEE938F2E5D5E29C939F771D
    Data FEE6196FB5ECB853F079C65262A5757AE30AE01AE515199E8CF77AC38DE5BD2E9F978B67D3784DED
    Data FAA1C92CCCCCA4F9E4692EAD45415517631443A622CDF8F501FB8009E4EE5B8F9DD7B7A759A9F3C1
    Data DACC14640842C04D4C8BDF16A9CDE78FD176669452A33D110A83A058AF953028AAB27CFA9173BDFA
    Data DA56BDE8E87383BDE174B418B679F5742FCB5DD80B345A3BE7A0BDE1BBC06A2A6AB32F8110178020
    Data B150E9F2A30D859C0E556EF5844959A5A93A7971ECFC4241C275384BD11E8BF79EBDE4F00E3D78AF
    Data 0909D6C5EDF3F5D91B1AEFE2C743DB2268E119466912C34448EBBD35DC5387959E1F6AF964381973
    Data B843C4A45334A6DE3BC37BD2BA2213AE37D8E61F767333A580AD786EAA432C3BC611DFA54AF30BAB
    Data 6AE09ABB8B92B3B2F5A6647F79378FDD6EA65B425057A7AF1BE928169E7EA8DC5377CC9FF6658587
    Data E6609E91FF96133D53DD1EB80313E6909E62E5C0A644179616041C60A61F28AD50EACB186C534991
    Data BE9E4D35D4A9EA07BA7BDA2BAA14E2961AB95E9E7D809D1C80C344C5A1E834442C363B369DC520D0
    Data 08851C0E9EAAE01550A55291425B5DCDC269AA58F20651A14842E7B170749D289F232F22F2D8040A
    Data 8BC611D109540E83CCE2D2294C369BC3134AF864BA88CB160BA90C1E93C1A191593C169DCD613058
    Data 2CA64582CD61B3D86C16CBC22CFCC59AC362B239AC5FF62DFF97E3FFE93F41EC174EFDD9D32F67EC
    Data 9F9CFECBFA3F4F1CCEBFDCFDF7871CF6BFB9C0F9DF54FD11F4AC3F26F4AB3758BFEF15D66F9DF9D3
    Data C53F4EACDFDDFFD9989FF96F01FC3718EC7F39FD3F48ADFF1103F6AF46FFE6E09F2BF63F4F7E83F7
    Data F7A2CBFEAD965F3893C9FCE96526E30531593FA5158BC9E21473B97C3E8FC7B5108F2710595A073E
    Data B7B898C5E68BC425E5D515C579147A215B27A7332839E8B49080D80C0C065388890F8F8B0D4FCE27
    Data D2789CC27C7C168AC415E9FBCECE19E97A2DB7E7E3667D6F83B65E988C16E88DC3F73FC90DD15083
    Data D4BDE4C21A6A2835F3ED150984B4D87C629AEF76F7E8706C951029D3A6B0CD080776254DA12B40F2
    Data 7445388D9E4C6B32F3340D4D67E15D9A604E8A3AF71531AE5912CDA70791C6CB83E99508724BEC47
    Data 99919B3350AEDE88C8E8F08878542E9E42623085A50A198B412FE0572A456D7F832718C69BCF1FF7
    Data 4D5C21A2664E86EE476C4CABD8B3288EE70A7660F7AD0BCB0A8D27C7D3FBE45EA86179BCE6101DA9
    Data D6E175CDA3F0B9207D7A61D2D2FAD49C5A189163C8E40213CFD605B17EE9EE1D60D9BE84F8ADEEE9
    Data 295E2E484C70425E1EB1AC4C700CC20DF6B02916C29C82AFC46567A3D6C9CEDD6AAC1DA8A1923A1B
    Data C9E55D27DBEA8C591AB5C7DEAC64ABBDF92E1B37AD4B9F6A01A03F1A1C831B96346212EB825FCFEB
    Data 2F8DA2B7EB08CCEE464E79EFD98B1F77743DBFA89BFAFE82E902AC8819BE3E030D80687C13F12406
    Data EC73DC22B202AFA2922C1D53D007B6B1C91B5CBD300715A1D9A7AADD4457CCB22347351D079B2024
    Data D3E0151D8487D3F3F8C69E839878B6C9718DCC178094885DB62B10D44DC083FFC15BE9125624811E
    Data 2B6469E0F33D34A866C22709E3A78295D728DB3ABF6B653E849D0E3B06CAA287EFB62722107B114E
    Data 8B77E5A0C8D488204230E2F2FC9F9DEF5010F0F692C0D3618147B0368A26BDBC52472A2A561593DA
    Data BAC74EF50FF40D0C4ECF49A85327AA0E4DE415CD73815BD3369B5119D818F167E7FDE04FD911D118
    Data 14811417452D462BDA8F4FE8E51DBD15D583873BDAC76E5C3CBD00A126EBC98FAD9FFD88F63F42F7
    Data A404026B54DC9A57D66C5EB6669FCDDB3B5CBD730FD87BB0508915CD64526D7BFDE0FCDD1F2AFC66
    Data BFD19F87F5E8D36DC4E1C6D4C2734FCAC5B326D7DD86FAD05C416A1A2172A5C72EB043CED8E890ED
    Data E32B90EBF5F6564766184367C2F7968B09E545EEA453AD396563E434659D4CDCD53570FEC8D8D5D9
    Data A2C0F20B6DC25A333261E013C61B96B64FD826B47FDF7EB393AFDDE2B51C491C5199B2270D9F802F
    Data ADEA1834896ADB19D496E116E3F0CCF8A8A5E3FC5C93AE393BDC7FABCDC126C3DBCA6E09D8B3CB39
    Data 2FE06DAB6D6BAC22112134720CB581E4C9E961614D93ED0D57E0B35664E9F9A9E39F0C29A51AB399
    Data 9357756FD2397888175EADB5B6453A062B03C0324C9EED1A0C71FBAA0C193AEBE08414CD95B75CED
    Data C7328C7C69959C9C2B1EA92748AA688C1A9DCCDCD4BEF07C6057D63426E4D23DDF0DB2744F4D65E6
    Data AE0D08623CB52C61E53A9F90FDFB1CDDB3348CC022558C07BB81C72E6FEA39AC13B4743318530BED
    Data C6FEC1DE93DFC0AA6D15FD51C3B078511173258EBF04D8A5173A6F8CF559F297E048BB7D09941A71
    Data 72B6A604896E1CD1085B86FAE67FB8A7E034578CC3737CD34141D5F91BF8C5B4054FEFA783C0B175
    Data B75D4D0408A27A7B85F9F979EF89290CF7C2B0DA3F3D9512DCA0A34C7EA6C4C9A46A1D3F2DBB7104
    Data 973DDC8B2A6AD3D00F3EBA121F334974187DE065352658ADAA5CBD6D6436633D1A9B42A064C4EEB4
    Data 8BA290C25C133B643BE26A556958A55AA46F1D1CD461A98D9DE54DB3A3257577EFE322EF74BE570A
    Data A9AB46BADFCD50AF5B9490B6696B419693D38E9D31BE3B7DB2F94C8594CBCA8EC3B575AA8C077515
    Data 8DADF35F4F64B3E6275AAE7F66A41F7AD0B0856C76CEFAAE01C475D9AC52228023978D0AD8171064
    Data 6D47E3854764F3391C59FFA7E576C917260DA74E32493A81D2447013DF6841EAC685E9C22B37E2DD
    Data CE4F47EA3E4D7CBB84656F6C5EFD2E995EC4D4B05D3E8890557072A3E30AB251A84C44125B25E14A
    Data D99402B6446E1A68293598B4727D6D8D69F2D18877D11D0DE771EB2B091713E32ED18143417CC40E
    Data EBDD493E5BD3A97B1D82500539B9C54D2D3931159DE4AC86633A597D477B47D7D4AD7EACE0F26CE3
    Data 8987F349BBBBAB36D3A7E3B66A28DB247CF02A223232390957E06C954971F111D0B10C2EA3A4B3B1
    Data FA684DBC7EB6A3F34C335E6562F3A5F82253B7945937FAB17A13EDB06FF6D3FE0F11AD1E3E55914B
    Data BCB3D10722F354B4F4CC40379A1C67EA48F06328F223BC730D65747195824361EBC438CDE46483A6
    Data CE2C939DBB8BF51D3387F73EA5A74F933F6C3AB8C2A52DC72E2CD03B71F32B8162CB77373D2B320A
    Data 45A364E1AA471438752B95D433A8521B4AEA674F0D5F3C1823FAC7371D7473BD3FE64AF34A17E6BE
    Data 3483DBE2FD11DE51BE9EC988BD4861B80B0117C6AC23A5A8AB5045A7CF75B789701D67CC8317D431
    Data D2BECA620A916BA81AB8A174E01BF7F3AE92EDF5555B51B5AEAF857118A1AE38BABF5F4957719457
    Data 41AB52D1A7CFC8C9C96B94052498EB898A1E4D7E3E4D59632C6B1AAAA2EA2E5F3C1031AEF768BD85
    Data 0BE928CB33C5BF1E81CD6E136F08C87174CEF67F3F4294162F29490AA593A3A9AD066D75255B7B48
    Data 2EE9AAA16A065A6A4ECC1D3B313ED183D59E51288F2A9C53654EAE85EE2B9C12E909B6EE89BBADA2
    Data 389969798958312943504B882F6EAAAD681A3FDF8365CF750A27CE72B91DA5EACA6CF4F11B391E3D
    Data E59EA52752ECE8382FA36AF97B197989E1486CB04B20918666D699F041E25A96F9504E6AA3065DA2
    Data 0C4EE930D325957472A94EA8AC2C33CE7C51E5AD1D0EA33CAEDF9453E387EEC78793FCC30D99FE8D
    Data A5ABF795473892A2ACD135B828B52634445A8A2D2C2F2B693414EB6AF094CE3681C46C2AA99BFF62
    Data 2823AB43CD989B4F0B95A44709E3DF76E448A22305F8DDEE85E488540E55A42616A878A9C4722595
    Data 57A2565774CE8EA2527AEAE823A70A73AAE9F9F57CA7C4364E94B2312D9054948A63608872661E93
    Data 8FC92EE6930A599674AF3D34260E28EE21F34F1B2259BA0C02376CBF409F9D55CA8F4FA2D0B20862
    Data 814C5E542467A1191A1E9E21930B4A6A47075061CD8D39A6D3A4283533858FDF155BC64BA294E2A2
    Data D10C3C9AC2E1ABB9056C6941AE484A25D1650A91AAE374B51F6E888D3FD51B5160446264D1F62443
    Data 6186429616974FC9CA66B3653A469E4070205FCA2592794AB1A8AC7FB830F0BF00504B0102140014
    Data 0002000800E6B1383445D635B79E140000901B00000900000000000000000020000000000000004D
    Data 6F746F722E776176504B010214001400020008005233691B44E8E9862E1100006C15000008000000
    Data 00000000000000000000C5140000486F726E2E776176504B050600000000020002006D0000001926
    Data 00000000
    
    End Sub
    
    Function PBMain
    
        Dim a As Long, FO As Long, T As String
    
        FO = FreeFile: Open "Wavs.zip" For Output As #FO
    
        If Err Then
    #If %Def( %Pb_Cc32 )
            StdOut "Error:" & Str$( Err ) & ", Press any key.."
            WaitKey$
            Exit Function
    #Else
            MsgBox "Error:" & Str$( Err ), 16, "Wavs.zip"
            Exit Function
    #EndIf
        End If
    
        BinBas1 T
    
        For a = 1 To Len( T ) Step 2: Print #FO, Chr$( Val( "&H" & Mid$( T, a , 2 ) ) ); : Next a
    
        Close #FO
    
    End Function

    • TheirCorp's SourceForge project
      includes:
    • API Helper --- a code generator for the Win32 API
    • "Flex" --- an editor with novel features
    • GDI Debug --- catches programming errors that could lead
      to resource leaks
    • TheirEdit --- an editor for PowerBASIC code
    • TheirSheet --- a spreadsheet
    • SrcFrmt --- a source code formatter
    • Tooltipper --- a tooltip code generator



    ------------------
    Tony Burcham
    TheirCorp


    [This message has been edited by Tony Burcham (edited January 31, 2006).]
    TheirCorp's projects at SourceForge

    TheirCorp's website

    sigpic

  • #2
    You can download the zip file from:OpenAlDemo.zip

    • TheirCorp's SourceForge project
      includes:
    • API Helper --- a code generator for the Win32 API
    • "Flex" --- an editor with novel features
    • GDI Debug --- catches programming errors that could lead
      to resource leaks
    • TheirEdit --- an editor for PowerBASIC code
    • TheirSheet --- a spreadsheet
    • SrcFrmt --- a source code formatter
    • Tooltipper --- a tooltip code generator



    ------------------
    Tony Burcham
    TheirCorp


    [This message has been edited by Tony Burcham (edited January 31, 2006).]
    TheirCorp's projects at SourceForge

    TheirCorp's website

    sigpic

    Comment


    • #3
      Update to Tony's code:

      Code:
      '**************************************
      '   "OpenALDemo.bas"
      
      'By Tony Burcham
      'https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/25481-3d-sound-demo-using-openal#post25481
      
      'Modified by Jim Fritts on 2020 JUN 14
      'to work with PBWIN10.4 and J. Roca includes III_107
      'To get ALUT.dll   go to here...
      'https://www.dll4free.com/alut.dll.html
      
      'Provided Zip contents:
      ' "Motor.wav"    6.89 KB
      ' "Horn.wav"     5.35 KB
      ' ALUT.dll       5.10.2914.0 32bit   5KB   English
      ' OpenAL32.DLL   6.14.357.24 32bit   106KB English
      ' OpenAlDemo.bas 27.7 KB
      ' OpenALDemo.exe 51.5 KB
      ' Wrap_oal.dll   2.2.0.5     32bit   434KB English
      
      'Thank you Tony and Jose
      '
      'Tony's Notes:
      
      '! This demo might GPF and crash your computer, especially if run in the
      '! debugger!  Save all open files before running this.
      
      'You can get the OpenAL and ALut binaries, SDK and (PDF) manuals from:
      'www.openal.org
      
      'OpenAL Archives (about 9MB of messages):
      'http://opensource.creative.com/pipermail/openal/
      
      'The OpenAL functions are in two main categories: one with the prefix "al",
      'and the other with "alc". They each have their own set of equates too.
      
      'Don't pass a closed device to alcGetError, or it will GPF
      
      'alcOpenDevice GPFs (and crashes the computer) with dynamic and Asciz
      'strings, but not with string equates, for some reason.
      
      'To globally disable checking for "al" errors REM-out or delete "%Debug".
      'To remove all the error-checking calls for "al" (not "alc") imports, do
      'a replace-all of " : alge" with "", then delete the Sub "alge".
      
      'alGetError and alcGetError are called very frequently for your use while
      'debugging. This demo doesn't respond to many of the error values it
      'retrieves.
      
      'This uses part of "motor_a8.wav" from the OpenAL SDK.
      
      'This used to freeze or GPF when calling alcOpenDevice, but it seems fine now.
      'This was using PBEdit's debugger, but that might not have been related.
      'It's something to watch out for. It never had a problem after running a demo
      'from the OpenAL SDK, for some reason.
      
      'Mono WAV files are preferrable for use with 3D sound, because adding stereo
      'effects to sound is what the 3D sound hardware/software is for in the first
      'place. Also, stereo WAVs are converted to mono anyway before any effects are
      'applied and that means extra large files to load and more processing to do
      'to them with no benefit whatsoever.
      
      'It's usually preferrable to use WAVs which are recorded with no natural
      'acoustics in them, because they might still be audible after artificial 3D
      'effects are added.
      ' It could be helpful in some cases though, to have some natural acoustics if the
      'original acoustics are the kind you need and if they don't need to be changed
      'during use, for example.
      
      '   Coordinate system: (from OpenAL specification)
      'OpenAL -- like OpenGL -- uses a right-handed Cartesian coordinate system (RHS),
      'where in a frontal default view X (thumb) points right, Y (index finger) points
      'up, and Z (middle finger) points towards the viewer/camera. To switch from a
      'left handed coordinate system (LHS) to a right handed coordinate systems, flip
      'the sign on the Z coordinate.
      
      'This code is Public domain by TheirCorp 2006
      '**************************************
      
      #COMPILE EXE "OpenALDemo.exe"
      #DIM ALL
      #REGISTER ALL
      '#Debug Error On
      '#Tools On
      
      %Debug              = 1
      %PrintErrorsToFile  = 1 '(instead of a messagebox)
      
      #INCLUDE "Win32API.inc"
      #INCLUDE "Alc.inc"
      #INCLUDE "Al.inc"
      #INCLUDE "Alut.inc"
      
      GLOBAL alError  AS LONG
      
      '**************************************
      
      'Take your pick... , or let the demo find out what's available.
      $WaveDevice =   "Generic Hardware"
      '$WaveDevice =   "Generic Software"
      '$WaveDevice =   "DirectSound3D"
      
      'WAV files
      $WavMotor   = "Motor.wav"
      $WavHonk    = "Horn.wav"
      
      %NUM_SOURCES    = 2
      %NUM_BUFFERS    = 2
      %Buffer_Motor   = 0
      %Buffer_Horn    = 1
      %Source_Motor   = 0
      %Source_Horn    = 1
      
      'This generates a compiler error when some values are out of range
      #IF (%NUM_SOURCES = 0) OR (%NUM_BUFFERS = 0)
      '! You must have at least one buffer and one source.
      '! Set %NUM_SOURCES and %NUM_BUFFERS as needed.
      #ENDIF
      
      '**************************************
      '   EAX equates
      
      'used by DSPROPERTY_EAXLISTENER_ENVIRONMENT
      %EAX_ENVIRONMENT_GENERIC                      = 0
      %EAX_ENVIRONMENT_PADDEDCELL                   = 1
      %EAX_ENVIRONMENT_ROOM                         = 2
      %EAX_ENVIRONMENT_BATHROOM                     = 3
      %EAX_ENVIRONMENT_LIVINGROOM                   = 4
      %EAX_ENVIRONMENT_STONEROOM                    = 5
      %EAX_ENVIRONMENT_AUDITORIUM                   = 6
      %EAX_ENVIRONMENT_CONCERTHALL                  = 7
      %EAX_ENVIRONMENT_CAVE                         = 8
      %EAX_ENVIRONMENT_ARENA                        = 9
      %EAX_ENVIRONMENT_HANGAR                       = 10
      %EAX_ENVIRONMENT_CARPETEDHALLWAY              = 11
      %EAX_ENVIRONMENT_HALLWAY                      = 12
      %EAX_ENVIRONMENT_STONECORRIDOR                = 13
      %EAX_ENVIRONMENT_ALLEY                        = 14
      %EAX_ENVIRONMENT_FOREST                       = 15
      %EAX_ENVIRONMENT_CITY                         = 16
      %EAX_ENVIRONMENT_MOUNTAINS                    = 17
      %EAX_ENVIRONMENT_QUARRY                       = 18
      %EAX_ENVIRONMENT_PLAIN                        = 19
      %EAX_ENVIRONMENT_PARKINGLOT                   = 20
      %EAX_ENVIRONMENT_SEWERPIPE                    = 21
      %EAX_ENVIRONMENT_UNDERWATER                   = 22
      %EAX_ENVIRONMENT_DRUGGED                      = 23
      %EAX_ENVIRONMENT_DIZZY                        = 24
      %EAX_ENVIRONMENT_PSYCHOTIC                    = 25
      %EAX_ENVIRONMENT_COUNT                        = 26
      
      %DSPROPERTY_EAXLISTENER_NONE                  = 0
      %DSPROPERTY_EAXLISTENER_ALLPARAMETERS         = 1
      %DSPROPERTY_EAXLISTENER_ROOM                  = 2
      %DSPROPERTY_EAXLISTENER_ROOMHF                = 3
      %DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR     = 4
      %DSPROPERTY_EAXLISTENER_DECAYTIME             = 5
      %DSPROPERTY_EAXLISTENER_DECAYHFRATIO          = 6
      %DSPROPERTY_EAXLISTENER_REFLECTIONS           = 7
      %DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY      = 8
      %DSPROPERTY_EAXLISTENER_REVERB                = 9
      %DSPROPERTY_EAXLISTENER_REVERBDELAY           = 10
      %DSPROPERTY_EAXLISTENER_ENVIRONMENT           = 11
      %DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE       = 12
      %DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION  = 13
      %DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF       = 14
      %DSPROPERTY_EAXLISTENER_FLAGS                 = 15
      
      %DSPROPERTY_EAXBUFFER_NONE                    = 0
      %DSPROPERTY_EAXBUFFER_ALLPARAMETERS           = 1
      %DSPROPERTY_EAXBUFFER_DIRECT                  = 2
      %DSPROPERTY_EAXBUFFER_DIRECTHF                = 3
      %DSPROPERTY_EAXBUFFER_ROOM                    = 4
      %DSPROPERTY_EAXBUFFER_ROOMHF                  = 5
      %DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR       = 6
      %DSPROPERTY_EAXBUFFER_OBSTRUCTION             = 7
      %DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO      = 8
      %DSPROPERTY_EAXBUFFER_OCCLUSION               = 9
      %DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO        = 10
      %DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO      = 11
      %DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF         = 12
      %DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR     = 13
      %DSPROPERTY_EAXBUFFER_FLAGS                   = 14
      %DSPROPERTY_EAX_BUFFERPROPERTY                = 15
      
      '**************************************
      'EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722}
      $DSPROPSETID_EAX20_BufferProperties = GUID$("{0306A6A7-B224-11d2-99E5-0000E8D8C722}")
      
      'Listener properties {0306A6A8-B224-11D2-99E5-0000E8D8C722}
      $DSPROPSETID_EAX20_ListenerProperties = GUID$("{0306A6A8-B224-11D2-99E5-0000E8D8C722}")
      
      %DSPROPERTY_EAXLISTENER_IMMEDIATE = &H00000000  'changes take effect immediately
      %DSPROPERTY_EAXLISTENER_DEFERRED  = &H80000000  'changes take effect later
      %DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS = %DSPROPERTY_EAXLISTENER_NONE OR %DSPROPERTY_EAXLISTENER_IMMEDIATE
      
      %DSPROPERTY_EAXBUFFER_IMMEDIATE = &H00000000 'changes take effect immediately
      %DSPROPERTY_EAXBUFFER_DEFERRED  = &H80000000 'changes take effect later
      %DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS = %DSPROPERTY_EAXBUFFER_NONE OR %DSPROPERTY_EAXBUFFER_IMMEDIATE
      
      'for coordinates, for example
      TYPE THREESINGLES DWORD
          x AS SINGLE
          y AS SINGLE
          z AS SINGLE
      END TYPE
      
      'for orientation, for example
      TYPE SIXSINGLES DWORD
          fx AS SINGLE
          fy AS SINGLE
          fz AS SINGLE
          ux AS SINGLE
          uy AS SINGLE
          uz AS SINGLE
      END TYPE
      
      TYPE EAXBUFFERPROPERTIES DWORD
          lDirect               AS LONG   'direct path level
          lDirectHF             AS LONG   'direct path level at high frequencies
          lRoom                 AS LONG   'room effect level
          lRoomHF               AS LONG   'room effect level at high frequencies
          flRoomRolloffFactor   AS SINGLE 'like DS3D flRolloffFactor but for room effect
          lObstruction          AS LONG   'main obstruction control (attenuation at high frequencies)
          flObstructionLFRatio  AS SINGLE 'obstruction low-frequency level re. main control
          lOcclusion            AS LONG   'main occlusion control (attenuation at high frequencies)
          flOcclusionLFRatio    AS SINGLE 'occlusion low-frequency level re. main control
          flOcclusionRoomRatio  AS SINGLE 'occlusion room effect level re. main control
          lOutsideVolumeHF      AS LONG   'outside sound cone level at high frequencies
          flAirAbsorptionFactor AS SINGLE 'multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
          dwFlags               AS DWORD  'modifies the behavior of properties
      END TYPE
      
      
      '**************************************
      
      FUNCTION PBMAIN() AS LONG
      LOCAL n           AS LONG
      LOCAL b           AS BYTE
      LOCAL eaxSet      AS DWORD 'pointer to function
      LOCAL alcError    AS LONG
      LOCAL SingVal     AS SINGLE
      LOCAL Buffers()   AS DWORD
      LOCAL Contextx    AS DWORD
      LOCAL Device      AS DWORD
      LOCAL FormatCode  AS LONG  'the WAV format code
      LOCAL DataPtr     AS LONG  'pointer to WAV data
      LOCAL DataSize    AS LONG  'size of WAV data
      LOCAL Frequency   AS LONG  'frequency
      LOCAL LoopFlag    AS LONG  'looping
      LOCAL Sources()   AS DWORD 'source
      LOCAL ThreeSing   AS THREESINGLES
      LOCAL SixSing     AS SIXSINGLES
      LOCAL EaxBufProp  AS EAXBUFFERPROPERTIES
      LOCAL ls          AS STRING
      LOCAL ts          AS STRING
      
      'extensions to check for
      DATA "al_ext_offset"
      DATA "AL_EXT_LINEAR_DISTANCE"
      DATA "AL_EXT_EXPONENT_DISTANCE"
      DATA "alc_EXT_capTure"
      DATA "EAX2.0"
      
          '--------------------------------------------------
          '   Check for available hardware devices and "software devices"
          '--------------------------------------------------
          'Check for Direct Sound 3D
          'b = 0 : ls = "" : ts = ""      'In case these are altered above
          n = LoadLibrary("DSOUND3D.DLL")
          IF n THEN
              FreeLibrary(n)
              INCR b
              ts = "DirectSound3D"    ' "ts" holds a clean list of the device names, because "ls" needs extra formatting for display
              ls = FORMAT$(b) & ".  " & $DQ & ts & $DQ & $CRLF
              ts = ts & ","
          END IF
      
          'Enumerate devices using OpenAL
          'If sent NULL instead of a string for &ALC_DEVICE_SPECIFIER, alcGetString returns
          'a list of NULL-terminated device names. The list itself is terminated by two NULLs.
          Device = alcGetString(0, %ALC_DEVICE_SPECIFIER) ' "Device" is being used as a string pointer here, since it's still available
          IF Device THEN
      
              DO
                  INCR b  'b holds the device count
                  n = lstrlen(BYVAL Device)
                  IF n THEN
                      ts = ts & PEEK$(Device, n) & ","
                      ls = ls & FORMAT$(b) & ".  " & $DQ & PEEK$(Device, n) & $DQ & $CRLF
                  ELSE
                      EXIT DO
                  END IF
      
                  Device = Device + n + 1
      
              LOOP WHILE n
      
          END IF
      
      
          ts = TRIM$(ts, ANY ", ")
          IF b > 1 THEN       'Found more than one, so offer a selection
              ls = "Enter the number of the device to use:" & $CRLF & $CRLF & ls
              n = VAL(INPUTBOX$(ls, "The following devices were found:", "1"))
              n = MAX&(MIN&(n, PARSECOUNT(ts)), 1)
      
          ELSEIF b = 1 THEN   'Found one, so show it, then use it
              MSGBOX "The following device was found: """ & ts & """"
              n = 1
      
          ELSE                'Nothing found so exit
              MSGBOX "No devices found. Exiting program..."
              EXIT FUNCTION
      
          END IF
      
          ls = PARSE$(ts, n)    'Get the selected device's name
      
      
          '--------------------------------------------------
          '   Setup the demo
          '--------------------------------------------------
          IF 1 THEN 'This block-IF is to make it easy to skip code in case of errors
      
              '--------------------------------------------------
              '   Open a device and get a current context
              '--------------------------------------------------
      
              ' NOTE: In the debugger, alcOpenDevice often GPFs (and crashes the computer) with
              ' dynamic and Asciz strings, but not with equates.
              'Also: alcOpenDevice doesn't like being stepped through in the debugger, so set a
              'breakpoint beyond it and run through it.
      
              ' Use this when running in the debugger to avoid GPFs
              'Device = alcOpenDevice($WaveDevice)     'Open a device (in debugger)
      
              ' You can use this when not running in the debugger
              Device = alcOpenDevice(BYVAL STRPTR(ls))     'Open a device (not in the debugger)
      
              IF Device = 0 THEN
                  MSGBOX ls & " was not found. Try another one."
                  EXIT FUNCTION
              END IF
      
              alcError = alcGetError(BYVAL Device)        'Clear any existing error value
              Contextx = alcCreateContext(Device, BYVAL 0) 'Create a context
              alcError = alcGetError(BYVAL Device)
      
              alcMakeContextCurrent(Contextx)  'Make the created context current
              alcError = alcGetError(BYVAL Device)
      
      
              '--------------------------------------------------
              '   Get and display available extensions
              '--------------------------------------------------
              '"alIsExtensionPresent" seems to need a context to be made current, so it was put here.
              ls = $CRLF & _
              "******************************************" & $CRLF & _
              "           Present Extensions:" & $CRLF & _
              "******************************************" & $CRLF & $CRLF
              FOR n = 1 TO DATACOUNT
                  b = alIsExtensionPresent(READ$(n))
                  ls = ls & IIF$(b = %AL_TRUE, "(YES):  ", "(NO) :  ") & READ$(n) & $CRLF
              NEXT n
              MSGBOX ls
              alge    'clear the current error value
      
      
              '--------------------------------------------------
              '   Set listener properties
              '--------------------------------------------------
              ThreeSing.x = 0 : ThreeSing.y = 0 : ThreeSing.z = 0
              alListenerfv(%AL_POSITION, BYVAL VARPTR(ThreeSing)) : alge 'Set listener position
              alListenerfv(%AL_VELOCITY, BYVAL VARPTR(ThreeSing)) : alge 'Set listener velocity
      
              'Set listener orientation: the direction he/she's facing, then the head's orientation
              SixSing.fx = -1 'Forward x
              SixSing.fy = 0  'Forward y
              SixSing.fz = 0  'Forward z
              SixSing.ux = 0  'Up x
              SixSing.uy = 1  'Up y
              SixSing.uz = 0  'Up z
              alListenerfv(%AL_ORIENTATION, BYVAL VARPTR(SixSing)) : alge
      
      
              '--------------------------------------------------
              '   Generate and load buffers with WAV data
              '--------------------------------------------------
              'These are referred to as "names", but that term doesn't seem to fit them very well
              REDIM Sources(%NUM_SOURCES - 1)  'DIM-ension array of source "names"
              REDIM Buffers(%NUM_BUFFERS - 1)  'DIM-ension array of buffer "names"
      
              alGenBuffers(%NUM_BUFFERS, Buffers(0)) : alge   'Generate the needed number of buffers
              IF alError THEN EXIT IF     'Couldn't create the buffers
      
              'Load "motor.wav" into buffer 0
              IF LEN(DIR$($WavMotor)) = 0 THEN EXIT IF                                                'Make sure "motor.wav" is present
              alutLoadWAVFile($WavMotor, FormatCode, DataPtr, DataSize, Frequency, LoopFlag)          'Load it into a temporary data buffer
              alBufferData(Buffers(%Buffer_Motor), FormatCode, DataPtr, DataSize, Frequency) : alge   'Load it into the second buffer generated above
              IF alError THEN EXIT IF     'Couldn't buffer the WAV data
              alutUnloadWAV(FormatCode, DataPtr, DataSize, Frequency)                                 'Free the temporary buffer
      
              'Load "horn.wav" into buffer 1
              IF LEN(DIR$($WavHonk)) = 0 THEN EXIT IF                                                 'Make sure "horn.wav" is present
              alutLoadWAVFile($WavHonk, FormatCode, DataPtr, DataSize, Frequency, LoopFlag)           'Load it into a temporary data buffer
              alBufferData(Buffers(%Buffer_Horn), FormatCode, DataPtr, DataSize, Frequency) : alge    'Load it into the second buffer generated above
              IF alError THEN EXIT IF     'Couldn't buffer the WAV data
              alutUnloadWAV(FormatCode, DataPtr, DataSize, Frequency)                                 'Free the temporary buffer
      
              '--------------------------------------------------
              '   Generate sources, assign buffers and adjust their initial settings
              '--------------------------------------------------
              alGenSources(%NUM_SOURCES, Sources(%Source_Motor)) : alge   'Generate the needed number of sources
              IF alError THEN EXIT IF     'Couldn't generate the sources
      
              alSourcei(Sources(%Source_Motor), %AL_BUFFER, CLNG(Buffers(%Buffer_Motor))) : alge  'Assign motor's buffer to a source
              IF alError THEN EXIT IF     'Couldn't assign the buffer
              alSourcei(Sources(%Source_Horn), %AL_BUFFER, CLNG(Buffers(%Buffer_Horn))) : alge    'Assign horn's buffer to the other source
              IF alError THEN EXIT IF     'Couldn't assign the buffer
      
      
              'Lower the gain for the "no effects" part of the demo
              alSourcef(Sources(%Source_Motor), %AL_GAIN, 0.3) : alge
              alSourcef(Sources(%Source_Horn), %AL_GAIN, 0.3) : alge
      
      
              '--------------------------------------------------
              '   Listen with no effects
              '--------------------------------------------------
              MSGBOX "Here are the two waves played together, with no effects (at half volume)" & $CRLF & $CRLF & _
                     "Press ""Okay"" to hear them."
              alSourcePlay Sources(%Source_Motor) : alge  'Play the motor
              alSourcePlay Sources(%Source_Horn) : alge   'Play the horn
              SLEEP 500                                   'Let them finish playing
              alSourceStop Sources(%Source_Motor) : alge  'Stop the motor
              alSourceStop Sources(%Source_Horn) : alge   'Stop the horn
      
              MSGBOX "That was the two waves played together with no effects applied" & $CRLF & _
                     "(at half volume). The longest WAV is about 1/3 second." & $CRLF & $CRLF & _
                     "Press ""Okay"" to listen with the effects applied" & $CRLF & _
                     "It will last for around 10 seconds (just wait for" & $CRLF & _
                     "the next messagebox to appear)." & $CRLF & $CRLF & _
                      "The demo simulates a car driving down an alley from" & $CRLF & _
                      "your right side and honking as it passes you."
      
      
              '--------------------------------------------------
              '   Apply all the effects to the WAV buffers
              '--------------------------------------------------
              'Apply acoustic effects to the motor
              alSourcei(Sources(%Source_Motor), %AL_LOOPING, 1) : alge     'Turn motor's looping on
              alSourcef(Sources(%Source_Motor), %AL_GAIN, 1.0) : alge      'Set the motor's gain to 1.0
              alSourcef(Sources(%Source_Motor), %AL_PITCH, 1.0) : alge     'Set the motor's pitch to 1.0
      
              'Apply acoustic effects to the horn
              alSourcei(Sources(%Source_Horn), %AL_LOOPING, 0) : alge      'Make sure horn's looping is off
              alSourcef(Sources(%Source_Horn), %AL_GAIN, 1.0) : alge       'Set the horn's gain to 1.0
              alSourcef(Sources(%Source_Horn), %AL_PITCH, 1.0) : alge      'Set the horn's pitch to 1.0
      
              '--------------------------------------------------
              '   Here are some predefined acoustic environments
              '   try as many as you like...
              '   "Alley" acoustics was chosen for this demo.
              '--------------------------------------------------
              'n = %EAX_ENVIRONMENT_GENERIC
              'n = %EAX_ENVIRONMENT_PADDEDCELL
              'n = %EAX_ENVIRONMENT_ROOM
              'n = %EAX_ENVIRONMENT_BATHROOM
              'n = %EAX_ENVIRONMENT_LIVINGROOM
              'n = %EAX_ENVIRONMENT_STONEROOM
              'n = %EAX_ENVIRONMENT_AUDITORIUM
              'n = %EAX_ENVIRONMENT_CONCERTHALL
              'n = %EAX_ENVIRONMENT_CAVE
              'n = %EAX_ENVIRONMENT_ARENA
              'n = %EAX_ENVIRONMENT_HANGAR
              'n = %EAX_ENVIRONMENT_CARPETEDHALLWAY
              'n = %EAX_ENVIRONMENT_HALLWAY
              'n = %EAX_ENVIRONMENT_STONECORRIDOR
              n = %EAX_ENVIRONMENT_ALLEY
              'n = %EAX_ENVIRONMENT_FOREST
              'n = %EAX_ENVIRONMENT_CITY
              'n = %EAX_ENVIRONMENT_MOUNTAINS
              'n = %EAX_ENVIRONMENT_QUARRY
              'n = %EAX_ENVIRONMENT_PLAIN
              'n = %EAX_ENVIRONMENT_PARKINGLOT
              'n = %EAX_ENVIRONMENT_SEWERPIPE
              'n = %EAX_ENVIRONMENT_UNDERWATER
              'n = %EAX_ENVIRONMENT_DRUGGED
              'n = %EAX_ENVIRONMENT_DIZZY
              'n = %EAX_ENVIRONMENT_PSYCHOTIC
              'n = %EAX_ENVIRONMENT_COUNT
      
      
              '--------------------------------------------------
              '   Apply the predefined environment to the listener
              '--------------------------------------------------
              eaxSet = alGetProcAddress("EAXSet") 'Get the address of "EAXSet"
              IF eaxSet THEN                      'If eaxSet is a valid code pointer then go ahead...
                  CALL DWORD eaxSet USING CallEaxSet($DSPROPSETID_EAX20_ListenerProperties, %DSPROPERTY_EAXLISTENER_ENVIRONMENT OR %DSPROPERTY_EAXLISTENER_IMMEDIATE, 0, VARPTR(n), 4)
              END IF
      
              '**************************************************
              '               The main demo
              '**************************************************
              '--------------------------------------------------
              '   This demo simulates a car driving down an alley from
              '   your right side and honking as it passes you.
              '--------------------------------------------------
              n = 0
              FOR SingVal = -50 TO 50 STEP 0.5
      
                  '--------------------------------------------------
                  'Add doppler effects (you can exagerate these as much as you want, for added effect)
                  ThreeSing.z = -SGN(SingVal) * 10
                  ThreeSing.x = 0
                  alSourcefv(Sources(%Source_Motor), %AL_VELOCITY, BYVAL VARPTR(ThreeSing)) : alge    'Update motor's velocity
                  alSourcefv(Sources(%Source_Horn), %AL_VELOCITY, BYVAL VARPTR(ThreeSing)) : alge     'Update horn's velocity
      
                  '--------------------------------------------------
                  'Set positions of sources
                  ThreeSing.z = SingVal
                  ThreeSing.x = -2
                  alSourcefv(Sources(%Source_Motor), %AL_POSITION, BYVAL VARPTR(ThreeSing)) : alge    'Update motor's position
                  alSourcefv(Sources(%Source_Horn), %AL_POSITION, BYVAL VARPTR(ThreeSing)) : alge     'Update horn's position
      
                  '--------------------------------------------------
                  'Start the car
                  IF n = 0 THEN alSourcePlay Sources(%Source_Motor) : n = 1 : alge     'Start the motor on the first loop
      
                  '--------------------------------------------------
                  'Honk the horn when about 2.5 meters away, and still approaching
                  IF (n < 2) AND (SingVal > -2.5) THEN alSourcePlay Sources(%Source_Horn) : n = 2 : alge
      
                  '--------------------------------------------------
                  SLEEP 50    'Don't make it reprocess the WAV data too frequently.
      
              NEXT SingVal
      
              '!'**************************************************
              '!'               End of the main demo
              '!'**************************************************
      
              alSourceStop Sources(%Source_Motor) : alge   'Stop the motor
              alSourceStop Sources(%Source_Horn) : alge    'Stop the horn
      
              MSGBOX "End of demonstration."
      
          END IF  'If 1
      
      
          '--------------------------------------------------
          '   Clean up
          '--------------------------------------------------
          'A buffer can't be deleted while attached to a source, so replace them with NULL buffers
          alSourcei(Sources(%Source_Motor), %AL_BUFFER, 0) : alge     'Assign a NULL buffer to clear the motor's source
          alSourcei(Sources(%Source_Horn), %AL_BUFFER, 0) : alge      'Assign a NULL buffer to clear the horn's source
          alDeleteBuffers %NUM_BUFFERS, Buffers(0) : alge             'Delete all the buffers
      
          alDeleteSources %NUM_SOURCES, Sources(%Source_Motor) : alge 'Delete all the sources
      
          alcError = alcGetError(BYVAL Device)    'Clear existing error value
      
          Contextx = alcGetCurrentContext()        'Get active context
          alcError = alcGetError(BYVAL Device)
      
          alcMakeContextCurrent(0)                'Disable the context
          alcError = alcGetError(BYVAL Device)
      
          Device = alcGetContextsDevice(Contextx)  'Get device for active context
          alcError = alcGetError(BYVAL Device)
      
          alcDestroyContext Contextx               'Destroy the context
          alcError = alcGetError(BYVAL Device)
      
          alcCloseDevice(BYVAL Device)            'Close the device
      
          'NOTE: never pass a closed device to alcGetError, or it will GPF
      
      END FUNCTION
      
      '**************************************
      
      '**************************************
      '   Call DWord prototype (this might not work for all calls, as is)
      DECLARE FUNCTION CallEaxSet(ListPropGuid AS ASCIZ * 17, BYVAL Param AS LONG, BYREF Value AS DWORD, BYVAL pParam2 AS DWORD, BYVAL szParam2 AS LONG) AS LONG
      
      '   alut.DLL imports
      DECLARE SUB alutLoadWAVFile LIB "alut.DLL" ALIAS "alutLoadWAVFile"(WaveFileName AS ASCIZ * %MAX_PATH, BYREF FormatCode AS LONG, BYREF DataBuffer AS LONG, BYREF DataSize AS LONG, BYREF Frequency AS LONG, BYREF LoopFlag AS LONG)
      DECLARE SUB alutUnloadWAV LIB "alut.DLL" ALIAS "alutUnloadWAV"(BYVAL FormatCode AS LONG, BYVAL pDataBuffer AS LONG, BYVAL DataSize AS LONG, BYVAL Frequency AS LONG)
      
      '**************************************
      
      SUB alge()  'checks for errors after calls to "al" (not "alc") imports
      #IF %DEF(%Debug)
      
          DIM alError  AS GLOBAL LONG
          STATIC cnt  AS LONG
          LOCAL ls    AS STRING
      
          INCR cnt
          alError = alGetError()
          SELECT CASE alError
              CASE %AL_INVALID
                  ls = "Invalid"
              CASE %AL_INVALID_VALUE
                  ls = "Invalid value"
              CASE %AL_INVALID_NAME
                  ls = "Invalid name"
              CASE %AL_ILLEGAL_ENUM
                  ls = "Illegal enum"
              CASE %AL_INVALID_ENUM
                  ls = "Invalid enum"
              CASE %AL_ILLEGAL_COMMAND
                  ls = "Illegal command"
              CASE %AL_INVALID_OPERATION
                  ls = "Invalid operation"
              CASE %AL_OUT_OF_MEMORY
                  ls = "Out of memory"
              CASE %AL_NO_ERROR
                  ls = ""
              CASE ELSE 'unknown error
                  ls = "(unknown)"
          END SELECT
      
          IF LEN(ls) THEN
              ls = "Error: " & ls & $CRLF & "...at ""al"" call number: " & FORMAT$(cnt)
      
      #IF %DEF(%PrintErrorsToFile)
              STATIC ff   AS LONG
              IF ff = 0 THEN
                  ff = FREEFILE
                  OPEN "AlError.Log" FOR OUTPUT AS #ff
                  PRINT# ff, "Error log for calls to ""al"" imports."
                  PRINT# ff, "Time and Date: " & TIME$ & ", " & DATE$
                  PRINT# ff,
              END IF
              PRINT# ff, ls
      #ELSE
              MSGBOX ls
      #ENDIF
      
          END IF
      
      #ENDIF
      END SUB
      Last edited by Jim Fritts; 17 Jun 2020, 06:18 PM.

      Comment


      • #4
        Retracted
        Last edited by Jim Fritts; 15 Jun 2020, 12:07 AM.

        Comment


        • #5
          Provided Zip contents:

          Code:
           "Motor.wav"    6.89 KB
           "Horn.wav"     5.35 KB
           ALUT.dll       5.10.2914.0 32bit   5KB   English
           OpenAL32.DLL   6.14.357.24 32bit   106KB English
           OpenAlDemo.bas 27.7 KB
           OpenALDemo.exe 51.5 KB
           Wrap_oal.dll   2.2.0.5     32bit   434KB English
          OpenALDemo.zip

          Thank you Tony and Jose.

          Comment

          Working...
          X