Compare commits

...

211 Commits

Author SHA1 Message Date
Chris Robinson ea90f781ff Release 1.10.622 2009-11-08 21:36:44 -08:00
Chris Robinson c1b161b44b Handle NULL effect objects as AL_EFFECT_NULL effects 2009-11-05 20:50:56 -08:00
Chris Robinson aa84b2e328 Handle setting AL_EFFECT_NULL effect types on a slot 2009-11-05 18:22:43 -08:00
Chris Robinson ebc1602816 Use the DXSDK_DIR variable when set 2009-11-02 14:57:48 -08:00
Chris Robinson dcd6a55529 Use a realtime clock for measuring time 2009-11-01 10:03:05 -08:00
Chris Robinson fb258a7416 Properly lock the device when setting it disconnected 2009-11-01 09:29:20 -08:00
Chris Robinson 5aed927887 Watch for stream and context failures from pulse, and report disconnects 2009-10-31 20:05:15 -07:00
Chris Robinson d964bb9f2f Fix length calculation for pulse 2009-10-31 19:30:12 -07:00
Chris Robinson 87dc7a5b97 Set a proper channel map for PulseAudio 2009-10-31 19:29:41 -07:00
Chris Robinson ae63ca481d Mix all updates PulseAudio requests 2009-10-31 17:59:30 -07:00
Chris Robinson 8e599103b6 Watch for buffer attribute changes from PulseAudio 2009-10-31 17:57:35 -07:00
Chris Robinson af0140e260 Use signals to watch for state changes
This partially reverts commit 617b6728d3
2009-10-31 17:52:26 -07:00
Chris Robinson 9d43907710 Properly free the device name 2009-10-31 13:25:26 -07:00
Chris Robinson a3fcd67a82 Remove some unneeded buffer fields, make padding a constant amount 2009-10-25 08:31:28 -07:00
Chris Robinson fe3a43e2d4 Remove the format and frequency from the source, get them manually 2009-10-25 06:26:19 -07:00
Chris Robinson e095047b02 Small fixups 2009-10-25 06:16:21 -07:00
Chris Robinson 31a106344f Calculate more store only once per loop 2009-10-25 05:34:47 -07:00
Chris Robinson b0a82aa420 Store the buffer format and frequency in the source when updated 2009-10-25 05:03:22 -07:00
Chris Robinson c003d6032d Retreive and store source params once per mix update 2009-10-25 04:39:36 -07:00
Chris Robinson 1665595138 Remove unneeded bufferlistitem properties 2009-10-25 02:59:31 -07:00
Chris Robinson bbccf76b45 Dereference left over buffers and slots when sources are released 2009-10-24 07:09:44 -07:00
Chris Robinson 1f47fa9243 Try 32-bit float before 16-bit, and stereo before mono 2009-10-24 03:20:47 -07:00
Chris Robinson 7b24a12a66 Check for the -pthread switch instead of using _REENTRANT 2009-10-23 10:36:32 -07:00
Chris Robinson 921e7ac3e9 Store the buffer handle directly in the source and buffer queue list 2009-10-22 09:31:26 -07:00
Chris Robinson 8d807add41 Store the bufferID in the buffer struct 2009-10-22 08:53:59 -07:00
Chris Robinson 8501fce38b Remove unused source fields 2009-10-21 15:40:09 -07:00
Chris Robinson 55d7984582 Set the calculated source parameters directly 2009-10-21 15:31:21 -07:00
Chris Robinson 8dbac9c0bd Store the calculated source parameters in the source struct 2009-10-21 14:25:54 -07:00
Chris Robinson 47b8510b0c Don't assume 16-bit samples 2009-10-21 13:50:53 -07:00
Chris Robinson 4e399b41cd Calculate source filter coefficients with the source parameters 2009-10-21 13:08:50 -07:00
Chris Robinson bdec1e037f Remove unnecessary variable 2009-10-21 12:48:04 -07:00
Chris Robinson 9924cce466 Make sure the ALSA device list is reset if no cards are found 2009-10-21 11:53:45 -07:00
Chris Robinson d3ecbd75af Clear the echo and delay lines even if the buffer doesn't change size 2009-10-21 02:03:33 -07:00
Chris Robinson 75b65ab2a2 Remove the Frequency field from the context 2009-10-20 13:47:55 -07:00
Chris Robinson eca8825ab4 Explicitly suspend the context being processed for mixing 2009-10-20 13:38:02 -07:00
Chris Robinson 9f9b7cf885 Make sure the context is properly locked while updating slots and sends 2009-10-20 13:02:28 -07:00
Chris Robinson cd695d7f15 Allow creating multiple contexts on a device 2009-10-20 12:58:19 -07:00
Chris Robinson 9c0ae597cd Make sure the effect slots and source sends are properly updated
Slots need to be updated due to possible frequency changes, and source sends
need to be updated in case some active sends were disabled
2009-10-20 12:53:07 -07:00
Chris Robinson 4461b4c56f Be more tolerant with resetting the fragment size 2009-10-20 12:28:51 -07:00
Chris Robinson 93361118b7 Store a device's contexts in a dynamic array 2009-10-20 11:54:04 -07:00
Chris Robinson 50f963f6c6 Don't try to clamp the listener-to-source velocity for local sources
Local sources will always have a 0 VLS value
2009-10-20 11:03:16 -07:00
Chris Robinson 67c3e47ed4 Avoid handling NaN when scaling float samples for output 2009-10-20 09:48:09 -07:00
Chris Robinson f14cf8289e Add a method to update device-dependant effect parameters.
The effect state's update method will be called afterwards
2009-10-20 08:31:44 -07:00
Chris Robinson 790aa68621 Reduce indentation for CalcSourceParams 2009-10-19 13:25:40 -07:00
Chris Robinson 6d1d61026d Be context-agnostic in the effect Create functions
This allows the effect Update functions to handle the playback frequency being
changed. By default the effects assume a maximum frequency of 192khz, however,
it can go higher at the cost of the sample buffers being cleared and the risk
of an abort() if reallocation fails
2009-10-19 07:46:53 -07:00
Chris Robinson a4e3ca933b EINTR is not a fatal write error 2009-10-19 00:33:00 -07:00
Chris Robinson 1fb58f9f8e Fix OSS and Solaris playback loop check 2009-10-17 22:17:59 -07:00
Chris Robinson 86e0b9386d Remove duplicate check in ALSA mmap playback 2009-10-16 10:57:58 -07:00
Chris Robinson c7c4cf221a Make the dry buffer part of the device 2009-10-09 01:06:33 -07:00
Chris Robinson d6e439244a Rename SetALCError for consistency 2009-10-07 04:32:14 -07:00
Chris Robinson 5ff225fa1b Add missing ) in pulseaudio backend 2009-10-02 07:34:49 -07:00
Chris Robinson 2a77e840cc Fix type casts for 7.1 output 2009-09-30 16:02:49 -07:00
Chris Robinson 00272883f6 Fallback to 16-bit or 8-bit, or mono, if ALSA doesn't accept the request 2009-09-27 08:35:10 -07:00
Chris Robinson bd6f3b1273 Report disconnect if the device fails to reset 2009-09-27 04:58:42 -07:00
Chris Robinson 4e9767bb22 Don't store the ALSA format 2009-09-27 04:03:11 -07:00
Chris Robinson 1d54b7a266 Fix capture, too 2009-09-27 03:57:19 -07:00
Chris Robinson c9506d939a Make sure ALSA properly loads, and fix the thread stop condition 2009-09-27 01:12:42 -07:00
Chris Robinson 21217824b7 Avoid duplicate error handling 2009-09-27 00:58:11 -07:00
Chris Robinson 8024df2991 Load backend libs on-demand 2009-09-27 00:21:40 -07:00
Chris Robinson f72b6fe717 Release 1.9.563 2009-09-26 01:42:21 -07:00
Chris Robinson 8d29d25d60 Condense some local variables 2009-09-24 14:51:40 -07:00
Chris Robinson af8e7ab984 Check the source start position in alSourcePlayv instead of the mixer 2009-09-24 12:24:10 -07:00
Chris Robinson 4289d5de7d Parse the attribute list and reset the device before creating the context 2009-09-24 11:31:01 -07:00
Chris Robinson 83734aff0e Slightly improve the multi-channel mixing loops 2009-09-24 08:52:51 -07:00
Chris Robinson 617b6728d3 Remove the state callbacks and watch for changes synchronously 2009-09-24 00:26:41 -07:00
Chris Robinson 7a8fd6cb20 Get rid of unnecessary messages from pulseaudio 2009-09-23 08:34:15 -07:00
Chris Robinson 55da339586 Properly clean up the pulse device 2009-09-23 08:19:00 -07:00
Chris Robinson 774eae0f2f Silence unused parameter warning 2009-09-23 07:10:23 -07:00
Chris Robinson 201b108a54 Attempt to reload backend libs when probing, if they didn't initially load 2009-09-23 01:33:58 -07:00
Chris Robinson bdbdbcea26 Update in properly-sized chunks for PulseAudio 2009-09-23 01:24:10 -07:00
Chris Robinson f6c1a21cf0 Properly flip the backend entries when sorting the device list 2009-09-22 04:42:46 -07:00
Chris Robinson c953072a15 Fix reset condition check 2009-09-22 00:16:21 -07:00
Chris Robinson 93f3e9357b (Re)allocate and clear the stereo-to-binaural filter as needed 2009-09-21 23:52:59 -07:00
Chris Robinson 8ea8b49464 Avoid locking a NULL context when a device is disconnected 2009-09-21 23:31:04 -07:00
Chris Robinson 62cef44dcb Reinitialize the stereo-to-binaural filter after resetting the device 2009-09-21 23:25:26 -07:00
Chris Robinson a2edc95207 Properly set the number of sends requested by the app 2009-09-21 23:18:39 -07:00
Chris Robinson 4cd41e3e08 Don't allow setting an invalid auxiliary send 2009-09-21 23:09:31 -07:00
Chris Robinson b641f993ac Hide the wave writer device if no output file is set 2009-09-21 05:03:40 -07:00
Chris Robinson e2905b6bc9 Properly handle forced 32-bit float output with DSound 2009-09-21 02:57:17 -07:00
Chris Robinson e11b59a80f Return imediately if trying to set an unknown format 2009-09-21 02:53:33 -07:00
Chris Robinson 0ae02e8ad4 Support floating point capture for backends that can handle it 2009-09-21 02:31:33 -07:00
Chris Robinson 2cbdffab86 Create the ALSA capture ring buffer with the proper size 2009-09-21 02:14:32 -07:00
Chris Robinson 86eefdb2a8 Mix all pending periods at once instead of one at a time 2009-09-20 00:44:39 -07:00
Chris Robinson 750399ccd7 Let verify_state restore from an ALSA underrun 2009-09-20 00:40:23 -07:00
Chris Robinson fb97ca6022 Remove left-over backend-specific period options 2009-09-16 23:29:32 -07:00
Chris Robinson cbcaa54173 Store the number of periods in the device instead of the buffer size
Also keep all the fields in sync
2009-09-16 22:58:54 -07:00
Chris Robinson 94e3fca702 Remove unnecessary parameters, and rename methods 2009-09-16 00:24:44 -07:00
Chris Robinson ffff104554 Restore the device frequency using the stream info 2009-09-16 00:08:11 -07:00
Chris Robinson 307a9dd1b2 Update the frequency with what the stream actually got set with 2009-09-15 23:14:14 -07:00
Chris Robinson 5dff8ea820 Properly terminate PortAudio when closing 2009-09-15 22:45:27 -07:00
Chris Robinson 49648fe22d Make a GetConfigValueBool function and use it 2009-09-15 22:18:13 -07:00
Chris Robinson 9f037e8980 Pass the device to aluMixData 2009-09-15 19:30:27 -07:00
Chris Robinson 12f81bcbb9 Move the stereo-to-binaural filter to the device 2009-09-15 19:06:47 -07:00
Chris Robinson 6636131d3b Pass the frame count to aluMixData 2009-09-15 18:19:00 -07:00
Chris Robinson eeea9631ce Split the source mixing loop into a separate function
Helps reduce the function size and indentation levels
2009-09-15 17:56:31 -07:00
Chris Robinson f9d228c30a Add missing context checks 2009-09-12 20:22:03 -07:00
Chris Robinson d516f8c4bd Update comment 2009-09-12 20:02:45 -07:00
Chris Robinson 5d1c3a0c63 Fix wave writer backend 2009-09-12 19:58:36 -07:00
Chris Robinson 396f2d6050 Mix the proper size for every update, and notify disconnects 2009-09-12 19:36:16 -07:00
Chris Robinson e25b01c3a2 Start Solaris playback when a context is ready 2009-09-12 18:19:52 -07:00
Chris Robinson b29a24afb0 Move the default out-of-tree build dir to build 2009-09-12 17:54:27 -07:00
Chris Robinson d6d1dba3d2 Initialize OpenAL with a constructor call instead of first-use 2009-09-12 17:49:08 -07:00
Chris Robinson 8b36a9d121 Get rid of deinit code duplication 2009-09-12 17:29:35 -07:00
Chris Robinson 59ed9338d8 Add support for the in-progress ALC_EXT_thread_local_context extension 2009-09-12 16:45:46 -07:00
Chris Robinson b444dea63b Fix compilation for Windows 2009-08-28 06:33:59 -07:00
Chris Robinson 1816c8bd37 Make a copy of the default device name for the app
The pointer to it could otherwise change if the device list is rebuilt, which
would be bad if the app has it
2009-08-27 20:13:35 -07:00
Chris Robinson c27948a7ee Don't free a NULL handle 2009-08-27 19:01:12 -07:00
Chris Robinson 832dc8a585 Remove unnecessary vars and rework device name checks 2009-08-27 18:55:18 -07:00
Chris Robinson bb121e68a6 Rebuild device lists when retrieving them 2009-08-27 06:09:33 -07:00
Chris Robinson 1ec26fd789 Dynamically allocate device lists 2009-08-27 03:55:36 -07:00
Chris Robinson 4ff4a7e3b9 Close some libs when deinitializing 2009-08-27 03:12:54 -07:00
Chris Robinson 6bb14e45ce Store a copy of the device name in the device 2009-08-27 02:53:09 -07:00
Chris Robinson 45dc804819 Store copies of the device names in the individual backends 2009-08-27 01:47:41 -07:00
Chris Robinson 81db01ebf1 Add a method to deinitialize backends 2009-08-26 23:45:00 -07:00
Chris Robinson 06c576a945 Support disconnect for OSS and Solaris 2009-08-26 21:49:38 -07:00
Chris Robinson 929b025fd6 Support disconnect for ALSA playback and capture
As a consequence for capture, mmap is no longer supported. Later on, supporting
mmap capture to write directly into the ring buffer is a possibility.
2009-08-26 21:27:10 -07:00
Chris Robinson 7976de05a5 Add base support for ALC_EXT_disconnect
Individual backends need to be updated to handle disconnection events
2009-08-26 19:15:17 -07:00
Chris Robinson 70c88879ab Add ALC_EXT_disconnect to alext.h 2009-08-26 18:29:25 -07:00
Chris Robinson 276ee63b99 Define PATH_MAX if it isn't already 2009-08-19 12:59:40 -07:00
Chris Robinson 487f0dde75 Print source and auxiliary slot debug warnings from alcDestroyContext 2009-08-16 16:11:22 -07:00
Chris Robinson c8f700930a More modifications and fixes for context checks 2009-08-16 16:02:13 -07:00
Chris Robinson decbe4df45 Modify some context checks 2009-08-16 15:09:36 -07:00
Chris Robinson 462f27c129 Use a function to retrieve the current context in an already-locked state
This should help prevent race-conditions with a context being destroyed between
breing retrieved and locked
2009-08-16 14:09:23 -07:00
Chris Robinson 2d1191697a Fix the Solaris backend 2009-08-16 13:16:41 -07:00
Chris Robinson 0b5a0d1e79 Reset the target if the databuffer being deleted is currently selected 2009-08-16 11:12:13 -07:00
Chris Robinson 0b7eb9f118 Add in-progress working extension AL_EXTX_sample_buffer_object 2009-08-16 00:54:08 -07:00
Chris Robinson dc26261065 Support 32-bit float output 2009-08-15 13:20:35 -07:00
Chris Robinson 9bea67fb1c Use a function to convert float to unsigned byte 2009-08-15 11:33:38 -07:00
Chris Robinson 8246bc3418 Use a custom function to get the requested format 2009-08-15 10:32:54 -07:00
Chris Robinson 01e32b58da Fix some size checks 2009-08-15 10:01:55 -07:00
Chris Robinson 9d05ff0468 Verify the device pointer is a valid device 2009-08-15 09:55:08 -07:00
Chris Robinson 510ccc7f17 Store the effect and filter lists in the device 2009-08-15 09:39:18 -07:00
Chris Robinson 43067ed2b8 Store the buffer list in the device 2009-08-15 09:14:08 -07:00
Chris Robinson 4e4c9aef15 Calculate the buffer size and frame size when needed 2009-08-14 13:08:25 -07:00
Chris Robinson 4031ee5ef0 Fix speaker override check 2009-08-14 07:27:19 -07:00
Chris Robinson e079291202 Remove unnecessary function parameters 2009-08-13 19:36:14 -07:00
Chris Robinson 826c641668 Hold the lock while finding a capture device to open 2009-08-13 19:19:16 -07:00
Chris Robinson 6ae845fd9e Don't let the device frequency change when PortAudio gets a new context 2009-08-13 17:13:37 -07:00
Chris Robinson a78fd58dca Create PulseAudio's playback stream when the AL context is created 2009-08-13 17:08:47 -07:00
Chris Robinson a8ae610489 Set context frequency only if it successfully starts 2009-08-13 15:35:10 -07:00
Chris Robinson b86a1e5797 Add a note about app and system defaults 2009-08-13 13:48:06 -07:00
Chris Robinson 45552a68ce Hold the lock while initializing context playback 2009-08-13 13:32:42 -07:00
Chris Robinson d46655fbb2 Support the ALC_FREQUENCY context attribute 2009-08-13 13:28:35 -07:00
Chris Robinson 87fee8c504 Start DSound playback at context creation 2009-08-13 13:11:05 -07:00
Chris Robinson 9ff0617807 Don't clamp the wave writer's update size 2009-08-13 12:35:42 -07:00
Chris Robinson 243939f94f Allow delaying playback start until context creation, and don't use UpdateSize to store the buffer size
This will make it possible to support the context attributes (frequency,
refresh, etc) for some backends
2009-08-13 12:28:46 -07:00
Chris Robinson 739385bd89 Add AL_EXT_BUFFER_DATA_STATIC to alext.h 2009-08-13 10:10:34 -07:00
Chris Robinson 32060f53cd Reset the buffer played count when the queue is removed via the AL_BUFFER property 2009-08-11 14:16:30 -07:00
Chris Robinson 4ee3972f15 Update queued buffer states when source looping is toggled 2009-08-11 07:57:18 -07:00
Chris Robinson 00a9cf4a85 Remove more unneeded variables 2009-07-07 21:11:13 -07:00
Chris Robinson 1dcd538ad9 Remove unneeded variables 2009-07-07 21:01:41 -07:00
Chris Robinson a8973514ba Don't load functions if libpulse failed to open 2009-07-07 12:51:18 -07:00
Chris Robinson 0ac9e57d28 Store the requested mono/stereo source count and sends in the device
Although the properties are set as context attributes, they are queried from
the device. If multiple contexts per device are ever supported, it would not
be straight forward about where to read the values from. This way, the
attributes can be treated as device-specific attributes that are updated when
a new context is created.
2009-07-06 03:09:01 -07:00
Chris Robinson 5460e85c40 Set the right access mode for non-mmap capture 2009-07-02 20:50:12 -07:00
Chris Robinson 432f0ba34c Specify the right format for ALSA recording 2009-07-02 20:32:19 -07:00
Chris Robinson 7e01e53445 Fix parsing of layout configuration string 2009-07-02 20:31:36 -07:00
Chris Robinson 043fe6edd2 Release 1.8.466 2009-06-07 22:30:08 -07:00
Chris Robinson ef68e5d0ff Protect ring buffer access with the lock 2009-06-07 21:34:05 -07:00
Chris Robinson c6f3a4e062 Move a couple inline functions into the header 2009-06-07 20:16:41 -07:00
Chris Robinson 87ed53c7f6 Don't read deprecated config files 2009-06-07 20:12:01 -07:00
Alam Arias 89e9437b84 add check for _WAVEFORMATEXTENSIBLE_ and define _WIN32_IE before inlcuding any header 2009-06-07 19:43:42 -07:00
Chris Robinson 1454c46b5f Use a thread-safe static inline function for printing 2009-06-07 15:42:15 -07:00
Chris Robinson 0fac1e9115 Store the max number of auxiliary slots in the device 2009-06-07 14:53:22 -07:00
Chris Robinson f3a3358e63 Fix for MSVC
MSVC won't accept zero-sized arrays at the end of structs, if that struct is
used in another struct that's not also at the end. This wastes a float for each
FILTER object
2009-06-06 23:33:53 -07:00
Chris Robinson 3c122b0bef Set an error if effect creation fails 2009-05-31 11:54:49 -07:00
Chris Robinson 7940003d06 Set an error if NaN is given for panning values 2009-05-31 11:34:07 -07:00
Chris Robinson 45b16ff456 Use the generic FILTER object for the master effect filter
Also fix a couple comments
2009-05-30 12:54:53 -07:00
Chris Robinson 9341f4f884 Fixup panning gain calculations
Clamp the panning vector magnitude to 1, and use an energy-reduction method as
the vector magnitude increases (to simulate reverb area occlusion)
2009-05-30 00:32:17 -07:00
Chris Robinson 2c20f26784 Apply slot gain on slot output, not input 2009-05-29 16:51:00 -07:00
Chris Robinson 2a21a449b4 Slot gain changes should have an immediate effect 2009-05-29 13:50:58 -07:00
Chris Robinson 74dc7090fd Don't expose effect-specific structures 2009-05-29 13:30:50 -07:00
Chris Robinson e12ac95d69 Use the MIN/MAX/DEFAULT macros for checking and setting the effect parameters 2009-05-29 12:40:08 -07:00
Chris Robinson 34ea7eba9e Add preliminary support for the EAX Reverb effect
Not all parameters are supported yet, though it is a little more fuctional than
standard reverb
2009-05-29 01:32:54 -07:00
Chris Robinson 6d3ba44f55 Don't update the devicevalues before returning success 2009-05-27 07:02:33 -07:00
Chris Robinson 5a8ad67660 Lock the context before getting the mmap region to update 2009-05-26 14:54:59 -07:00
Chris Robinson f1e442408b Set the correct data size 2009-05-26 14:51:57 -07:00
Chris Robinson a946af4463 Simplify ALSA PCM parameter retrieval 2009-05-26 10:08:27 -07:00
Chris Robinson e01cd92d56 Set avail_min so snd_pcm_wait will wait for the full update to be ready 2009-05-26 10:03:17 -07:00
Chris Robinson 923af8c3a6 Don't update the source's gains in the sample mixing loop
Update copies stored on the stack instead, then update the source after mixing
2009-05-26 09:23:49 -07:00
Chris Robinson ac04cf57fa Make sure _CRT_SECURE_NO_WARNINGS is always defined for MSVC 2009-05-26 06:02:40 -07:00
Chris Robinson 1f6c4e01db Properly fall back to non-mmap capture if the parameters fail 2009-05-25 16:06:03 -07:00
Chris Robinson 04135723a2 Get rid of the ugly ok() macro 2009-05-25 13:07:49 -07:00
Chris Robinson 93fbdb1e6c Redo OSS mixing loop 2009-05-25 12:12:37 -07:00
Chris Robinson c1de15f840 Update in descrete amounts using the update size 2009-05-25 12:01:14 -07:00
Chris Robinson 3be399c555 Do not open pulseaudio if it didn't load 2009-05-19 06:37:22 -07:00
Chris Robinson 1f5453075c Dynamically load PulseAudio 2009-05-19 06:35:12 -07:00
Chris Robinson 33a74f1594 Clear the filter history directly 2009-05-17 22:50:07 -07:00
Chris Robinson e4da1224cb Optionally install the sample configuration file 2009-05-17 22:36:45 -07:00
Chris Robinson 5c2a47620c Reformat the sample config file 2009-05-17 22:24:29 -07:00
Chris Robinson 1bfa7609d2 Make the filter functions global inline, and use it for echo 2009-05-16 23:34:26 -07:00
Chris Robinson 7e8501123a Set some common macros in alu.h 2009-05-16 23:26:39 -07:00
Chris Robinson c447eeb2c7 Use the source reference distance to specify full panning magnitude
Sources that are closer than the specified reference distance will not pan to
full magnitude, thus providing a smoother transition as it moves around near
the listener
2009-05-16 03:54:16 -07:00
Chris Robinson ad19cea6e0 Make sure DSSPEAKER_5POINT1 is defined 2009-05-14 05:24:18 -07:00
Chris Robinson 0ce29863e3 Prevent spawning PulseAudio if it's not already running 2009-05-06 00:19:35 -07:00
Chris Robinson 7a7a4844f4 Make the filter history buffer size flexible
This lets the filter history buffer be as big as needed for a given use, so
that it can have a size large enough for the more demanding cases, but not be
wasteful for lesser-demanding cases, while not incuring the overhead of an
added pointer indirection
2009-04-16 05:43:09 -07:00
Chris Robinson a2adbb1ab5 Add a PulseAudio backend 2009-04-16 05:17:42 -07:00
Chris Robinson a97fc792d8 Increase the default maximum number of sends to 2 2009-04-14 22:18:47 -07:00
Chris Robinson e9a6a1d6f5 Use a 2-pole filter for the wet path low-pass filter
This should help keep CPU use from increasing a lot when the number of sends
increases. Also changes the function names to reflect the difference
2009-04-14 22:04:18 -07:00
Chris Robinson f245f0ef87 Make the number of source sends variable
The highest value is clamped to MAX_SENDS
2009-04-13 20:33:41 -07:00
Chris Robinson a30f431b63 Reduce the number of send loops 2009-04-13 02:50:40 -07:00
Chris Robinson 58f48f20e2 Rename Standard Reverb to Reverb 2009-04-13 02:01:21 -07:00
Chris Robinson ee1b02b709 Fix comment regarding the 3rd echo tap 2009-04-12 18:54:26 -07:00
Chris Robinson 55c790c9ff Add the Echo effect 2009-04-12 16:01:10 -07:00
Chris Robinson 65b69f3308 Fix air absorption 2009-04-11 20:27:55 -07:00
Chris Robinson c67fbd72dd Pay attention to the MAX_SENDS value 2009-04-11 20:04:46 -07:00
Chris Robinson 30f57d0824 Make auxiliary effect slot count configurable 2009-04-11 18:16:05 -07:00
Chris Robinson 1c54018111 Move the WetBuffer into the effect slot object
This should make it easier to support multiple slots
2009-04-11 17:04:55 -07:00
Chris Robinson e80e1b6d9f Use LIB_SUFFIX when creating the default lib install dir
Thanks to Hanno Böck for pointing this out
2009-04-07 12:11:41 -07:00
Chris Robinson 437f00d6de Add missing comment markers 2009-04-07 11:41:41 -07:00
Chris Robinson fc6d6b1601 Use the square of the values when calculating the density gain 2009-03-21 10:42:42 -07:00
Chris Robinson 9306e36d52 Make sure M_PI is defined for reverb 2009-03-15 23:14:40 -07:00
42 changed files with 7855 additions and 4648 deletions
+1 -1
View File
@@ -1 +1 @@
CMakeConf
build
+739 -375
View File
File diff suppressed because it is too large Load Diff
+876 -1041
View File
File diff suppressed because it is too large Load Diff
+14 -17
View File
@@ -18,6 +18,10 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#ifdef _WIN32
#define _WIN32_IE 0x400
#endif
#include "config.h"
#include <stdlib.h>
@@ -27,8 +31,7 @@
#include "alMain.h"
#ifdef _WIN32
#define _WIN32_IE 0x400
#ifdef _WIN32_IE
#include <shlobj.h>
#endif
@@ -219,13 +222,6 @@ void ReadALConfig(void)
}
#else
f = fopen("/etc/openal/alsoft.conf", "r");
if(!f)
{
f = fopen("/etc/openal/config", "r");
if(f)
AL_PRINT("Reading /etc/openal/config; this file is deprecated\n"
"\tPlease rename it to /etc/openal/alsoft.conf\n");
}
if(f)
{
LoadConfigFromFile(f);
@@ -235,14 +231,6 @@ void ReadALConfig(void)
{
snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME"));
f = fopen(buffer, "r");
if(!f)
{
snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME"));
f = fopen(buffer, "r");
if(f)
AL_PRINT("Reading ~/.openalrc; this file is deprecated\n"
"\tPlease rename it to ~/.alsoftrc\n");
}
if(f)
{
LoadConfigFromFile(f);
@@ -325,3 +313,12 @@ float GetConfigValueFloat(const char *blockName, const char *keyName, float def)
return (float)strtod(val, NULL);
#endif
}
int GetConfigValueBool(const char *blockName, const char *keyName, float def)
{
const char *val = GetConfigValue(blockName, keyName, "");
if(!val[0]) return !!def;
return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 ||
strcasecmp(val, "on") == 0 || atoi(val) != 0);
}
+212
View File
@@ -0,0 +1,212 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 2009 by Chris Robinson.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include "alMain.h"
#include "alFilter.h"
#include "alAuxEffectSlot.h"
#include "alError.h"
#include "alu.h"
// Just a soft maximum. Being higher will cause EchoUpdate to reallocate the
// sample buffer which may cause an abort if realloc fails
#define MAX_ECHO_FREQ 192000
typedef struct ALechoState {
// Must be first in all effects!
ALeffectState state;
ALfloat *SampleBuffer;
ALuint BufferLength;
// The echo is two tap. The delay is the number of samples from before the
// current offset
struct {
ALuint delay;
} Tap[2];
ALuint Offset;
// The LR gains for the first tap. The second tap uses the reverse
ALfloat GainL;
ALfloat GainR;
ALfloat FeedGain;
FILTER iirFilter;
ALfloat history[2];
} ALechoState;
// Find the next power of 2. Actually, this will return the input value if
// it is already a power of 2.
static ALuint NextPowerOf2(ALuint value)
{
ALuint powerOf2 = 1;
if(value)
{
value--;
while(value)
{
value >>= 1;
powerOf2 <<= 1;
}
}
return powerOf2;
}
ALvoid EchoDestroy(ALeffectState *effect)
{
ALechoState *state = (ALechoState*)effect;
if(state)
{
free(state->SampleBuffer);
state->SampleBuffer = NULL;
free(state);
}
}
ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
{
ALechoState *state = (ALechoState*)effect;
ALuint maxlen, i;
// Use the next power of 2 for the buffer length, so the tap offsets can be
// wrapped using a mask instead of a modulo
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency);
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency);
maxlen = NextPowerOf2(maxlen+1);
if(maxlen != state->BufferLength)
{
void *temp;
temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat));
if(!temp)
{
alSetError(AL_OUT_OF_MEMORY);
return AL_FALSE;
}
state->BufferLength = maxlen;
}
for(i = 0;i < state->BufferLength;i++)
state->SampleBuffer[i] = 0.0f;
return AL_TRUE;
}
ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
{
ALechoState *state = (ALechoState*)effect;
ALuint frequency = Context->Device->Frequency;
ALfloat lrpan, cw, a, g;
state->Tap[0].delay = (ALuint)(Effect->Echo.Delay * frequency);
state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * frequency);
state->Tap[1].delay += state->Tap[0].delay;
lrpan = Effect->Echo.Spread*0.5f + 0.5f;
state->GainL = aluSqrt( lrpan);
state->GainR = aluSqrt(1.0f-lrpan);
state->FeedGain = Effect->Echo.Feedback;
cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / frequency);
g = 1.0f - Effect->Echo.Damping;
a = 0.0f;
if(g < 0.9999f) // 1-epsilon
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
state->iirFilter.coeff = a;
}
ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
{
ALechoState *state = (ALechoState*)effect;
const ALuint mask = state->BufferLength-1;
const ALuint tap1 = state->Tap[0].delay;
const ALuint tap2 = state->Tap[1].delay;
ALuint offset = state->Offset;
const ALfloat gain = Slot->Gain;
ALfloat samp[2], smp;
ALuint i;
for(i = 0;i < SamplesToDo;i++,offset++)
{
// Sample first tap
smp = state->SampleBuffer[(offset-tap1) & mask];
samp[0] = smp * state->GainL;
samp[1] = smp * state->GainR;
// Sample second tap. Reverse LR panning
smp = state->SampleBuffer[(offset-tap2) & mask];
samp[0] += smp * state->GainR;
samp[1] += smp * state->GainL;
// Apply damping and feedback gain to the second tap, and mix in the
// new sample
smp = lpFilter2P(&state->iirFilter, 0, smp+SamplesIn[i]);
state->SampleBuffer[offset&mask] = smp * state->FeedGain;
// Apply slot gain
samp[0] *= gain;
samp[1] *= gain;
SamplesOut[i][FRONT_LEFT] += samp[0];
SamplesOut[i][FRONT_RIGHT] += samp[1];
SamplesOut[i][SIDE_LEFT] += samp[0];
SamplesOut[i][SIDE_RIGHT] += samp[1];
SamplesOut[i][BACK_LEFT] += samp[0];
SamplesOut[i][BACK_RIGHT] += samp[1];
}
state->Offset = offset;
}
ALeffectState *EchoCreate(void)
{
ALechoState *state;
state = malloc(sizeof(*state));
if(!state)
{
alSetError(AL_OUT_OF_MEMORY);
return NULL;
}
state->state.Destroy = EchoDestroy;
state->state.DeviceUpdate = EchoDeviceUpdate;
state->state.Update = EchoUpdate;
state->state.Process = EchoProcess;
state->BufferLength = 0;
state->SampleBuffer = NULL;
state->Tap[0].delay = 0;
state->Tap[1].delay = 0;
state->Offset = 0;
state->GainL = 0.0f;
state->GainR = 0.0f;
state->iirFilter.coeff = 0.0f;
state->iirFilter.history[0] = 0.0f;
state->iirFilter.history[1] = 0.0f;
return &state->state;
}
+400 -217
View File
@@ -28,21 +28,8 @@
#include "alMain.h"
#include "alAuxEffectSlot.h"
#include "alEffect.h"
#include "alReverb.h"
#ifdef HAVE_SQRTF
#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
#else
#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
#endif
// fixes for mingw32.
#if defined(max) && !defined(__max)
#define __max max
#endif
#if defined(min) && !defined(__min)
#define __min min
#endif
#include "alError.h"
#include "alu.h"
typedef struct DelayLine
{
@@ -52,28 +39,34 @@ typedef struct DelayLine
ALfloat *Line;
} DelayLine;
struct ALverbState
{
typedef struct ALverbState {
// Must be first in all effects!
ALeffectState state;
// All delay lines are allocated as a single buffer to reduce memory
// fragmentation and management code.
ALfloat *SampleBuffer;
// Master effect gain.
ALfloat Gain;
ALuint TotalLength;
// Master effect low-pass filter (2 chained 1-pole filters).
FILTER LpFilter;
ALfloat LpHistory[2];
// Initial effect delay and decorrelation.
DelayLine Delay;
// The tap points for the initial delay. First tap goes to early
// reflections, the last four decorrelate to late reverb.
ALuint Tap[5];
struct {
// Gain for early reflections.
// Total gain for early reflections.
ALfloat Gain;
// Early reflections are done with 4 delay lines.
ALfloat Coeff[4];
DelayLine Delay[4];
ALuint Offset[4];
// The gain for each output channel based on 3D panning.
ALfloat PanGain[OUTPUTCHANNELS];
} Early;
struct {
// Gain for late reverb.
// Total gain for late reverb.
ALfloat Gain;
// Attenuation to compensate for modal density and decay rate.
ALfloat DensityGain;
@@ -89,13 +82,15 @@ struct ALverbState
ALfloat Coeff[4];
DelayLine Delay[4];
ALuint Offset[4];
// The cyclical delay lines are low-pass filtered.
ALfloat LpCoeff[4][2];
// The cyclical delay lines are 1-pole low-pass filtered.
ALfloat LpCoeff[4];
ALfloat LpSample[4];
// The gain for each output channel based on 3D panning.
ALfloat PanGain[OUTPUTCHANNELS];
} Late;
// The current read offset for all delay lines.
ALuint Offset;
};
} ALverbState;
// All delay line lengths are specified in seconds.
@@ -149,6 +144,46 @@ static ALuint NextPowerOf2(ALuint value)
return powerOf2;
}
static ALuint CalcLengths(ALuint length[13], ALuint frequency)
{
ALuint samples, totalLength, index;
// All line lengths are powers of 2, calculated from their lengths, with
// an additional sample in case of rounding errors.
// See VerbUpdate() for an explanation of the additional calculation
// added to the master line length.
samples = (ALuint)
((MASTER_LINE_LENGTH +
(LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER) *
(DECO_FRACTION * ((DECO_MULTIPLIER * DECO_MULTIPLIER *
DECO_MULTIPLIER) - 1.0f)))) *
frequency) + 1;
length[0] = NextPowerOf2(samples);
totalLength = length[0];
for(index = 0;index < 4;index++)
{
samples = (ALuint)(EARLY_LINE_LENGTH[index] * frequency) + 1;
length[1 + index] = NextPowerOf2(samples);
totalLength += length[1 + index];
}
for(index = 0;index < 4;index++)
{
samples = (ALuint)(ALLPASS_LINE_LENGTH[index] * frequency) + 1;
length[5 + index] = NextPowerOf2(samples);
totalLength += length[5 + index];
}
for(index = 0;index < 4;index++)
{
samples = (ALuint)(LATE_LINE_LENGTH[index] *
(1.0f + LATE_LINE_MULTIPLIER) * frequency) + 1;
length[9 + index] = NextPowerOf2(samples);
totalLength += length[9 + index];
}
return totalLength;
}
// Basic delay line input/output routines.
static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
{
@@ -207,13 +242,11 @@ static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *
DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
// To decorrelate the output for stereo separation, the two outputs are
// obtained from the inner delay lines.
// Output is instant by using the inputs to them instead of taking the
// result of the two delay lines directly (f[0] and f[3] instead of d[1]
// and d[2]).
// Output the results of the junction for all four lines.
out[0] = State->Early.Gain * f[0];
out[1] = State->Early.Gain * f[3];
out[1] = State->Early.Gain * f[1];
out[2] = State->Early.Gain * f[2];
out[3] = State->Early.Gain * f[3];
}
// All-pass input/output routine for late reverb.
@@ -241,8 +274,8 @@ static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index)
// Low-pass filter input/output routine for late reverb.
static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in)
{
State->Late.LpSample[index] = (State->Late.LpCoeff[index][0] * in) +
(State->Late.LpCoeff[index][1] * State->Late.LpSample[index]);
State->Late.LpSample[index] = in +
((State->Late.LpSample[index] - in) * State->Late.LpCoeff[index]);
return State->Late.LpSample[index];
}
@@ -304,11 +337,13 @@ static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
f[2] = d[2] + (State->Late.MixCoeff * ( d[0] - d[1] + d[3]));
f[3] = d[3] + (State->Late.MixCoeff * (-d[0] - d[1] - d[2]));
// Output is tapped at the input to the shortest two cyclical delay
// lines, attenuated by the late reverb gain (which is attenuated by the
// mixing coefficient x).
// Output the results of the matrix for all four cyclical delay lines,
// attenuated by the late reverb gain (which is attenuated by the 'x'
// mix coefficient).
out[0] = State->Late.Gain * f[0];
out[1] = State->Late.Gain * f[1];
out[2] = State->Late.Gain * f[2];
out[3] = State->Late.Gain * f[3];
// The delay lines are fed circularly in the order:
// 0 -> 1 -> 3 -> 2 -> 0 ...
@@ -318,124 +353,38 @@ static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
DelayLineIn(&State->Late.Delay[3], State->Offset, f[1]);
}
// This creates the reverb state. It should be called only when the reverb
// effect is loaded into a slot that doesn't already have a reverb effect.
ALverbState *VerbCreate(ALCcontext *Context)
// Process the reverb for a given input sample, resulting in separate four-
// channel output for both early reflections and late reverb.
static __inline ALvoid ReverbInOut(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
{
ALverbState *State = NULL;
ALuint samples, length[13], totalLength, index;
ALfloat taps[4];
State = malloc(sizeof(ALverbState));
if(!State)
return NULL;
// Low-pass filter the incoming sample.
in = lpFilter2P(&State->LpFilter, 0, in);
// All line lengths are powers of 2, calculated from their lengths, with
// an additional sample in case of rounding errors.
// Feed the initial delay line.
DelayLineIn(&State->Delay, State->Offset, in);
// See VerbUpdate() for an explanation of the additional calculation
// added to the master line length.
samples = (ALuint)
((MASTER_LINE_LENGTH +
(LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER) *
(DECO_FRACTION * ((DECO_MULTIPLIER * DECO_MULTIPLIER *
DECO_MULTIPLIER) - 1.0f)))) *
Context->Frequency) + 1;
length[0] = NextPowerOf2(samples);
totalLength = length[0];
for(index = 0;index < 4;index++)
{
samples = (ALuint)(EARLY_LINE_LENGTH[index] * Context->Frequency) + 1;
length[1 + index] = NextPowerOf2(samples);
totalLength += length[1 + index];
}
for(index = 0;index < 4;index++)
{
samples = (ALuint)(ALLPASS_LINE_LENGTH[index] * Context->Frequency) + 1;
length[5 + index] = NextPowerOf2(samples);
totalLength += length[5 + index];
}
for(index = 0;index < 4;index++)
{
samples = (ALuint)(LATE_LINE_LENGTH[index] *
(1.0f + LATE_LINE_MULTIPLIER) * Context->Frequency) + 1;
length[9 + index] = NextPowerOf2(samples);
totalLength += length[9 + index];
}
// Calculate the early reflection from the first delay tap.
in = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
EarlyReflection(State, in, early);
// All lines share a single sample buffer.
State->SampleBuffer = malloc(totalLength * sizeof(ALfloat));
if(!State->SampleBuffer)
{
free(State);
return NULL;
}
for(index = 0; index < totalLength;index++)
State->SampleBuffer[index] = 0.0f;
// Calculate the late reverb from the last four delay taps.
taps[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
taps[1] = DelayLineOut(&State->Delay, State->Offset - State->Tap[2]);
taps[2] = DelayLineOut(&State->Delay, State->Offset - State->Tap[3]);
taps[3] = DelayLineOut(&State->Delay, State->Offset - State->Tap[4]);
LateReverb(State, taps, late);
// Each one has its mask and start address calculated one time.
State->Gain = 0.0f;
State->Delay.Mask = length[0] - 1;
State->Delay.Line = &State->SampleBuffer[0];
totalLength = length[0];
State->Tap[0] = 0;
State->Tap[1] = 0;
State->Tap[2] = 0;
State->Tap[3] = 0;
State->Tap[4] = 0;
State->Early.Gain = 0.0f;
for(index = 0;index < 4;index++)
{
State->Early.Coeff[index] = 0.0f;
State->Early.Delay[index].Mask = length[1 + index] - 1;
State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[1 + index];
// The early delay lines have their read offsets calculated once.
State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
Context->Frequency);
}
State->Late.Gain = 0.0f;
State->Late.DensityGain = 0.0f;
State->Late.ApFeedCoeff = 0.0f;
State->Late.MixCoeff = 0.0f;
for(index = 0;index < 4;index++)
{
State->Late.ApCoeff[index] = 0.0f;
State->Late.ApDelay[index].Mask = length[5 + index] - 1;
State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[5 + index];
// The late all-pass lines have their read offsets calculated once.
State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
Context->Frequency);
}
for(index = 0;index < 4;index++)
{
State->Late.Coeff[index] = 0.0f;
State->Late.Delay[index].Mask = length[9 + index] - 1;
State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[9 + index];
State->Late.Offset[index] = 0;
State->Late.LpCoeff[index][0] = 0.0f;
State->Late.LpCoeff[index][1] = 0.0f;
State->Late.LpSample[index] = 0.0f;
}
State->Offset = 0;
return State;
// Step all delays forward one sample.
State->Offset++;
}
// This destroys the reverb state. It should be called only when the effect
// slot has a different (or no) effect loaded over the reverb effect.
ALvoid VerbDestroy(ALverbState *State)
ALvoid VerbDestroy(ALeffectState *effect)
{
ALverbState *State = (ALverbState*)effect;
if(State)
{
free(State->SampleBuffer);
@@ -444,21 +393,102 @@ ALvoid VerbDestroy(ALverbState *State)
}
}
// NOTE: Temp, remove later.
static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
{
ALint pos = 0;
ALfloat denom = aluFabs(re) + aluFabs(im);
if(denom > 0.0f)
pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
if(re < 0.0)
pos = 2 * QUADRANT_NUM - pos;
if(im < 0.0)
pos = LUT_NUM - pos;
return pos%LUT_NUM;
}
// This updates the device-dependant reverb state. This is called on
// initialization and any time the device parameters (eg. playback frequency,
// format) have been changed.
ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
{
ALverbState *State = (ALverbState*)effect;
ALuint length[13], totalLength;
ALuint index;
totalLength = CalcLengths(length, Device->Frequency);
if(totalLength != State->TotalLength)
{
void *temp;
temp = realloc(State->SampleBuffer, totalLength * sizeof(ALfloat));
if(!temp)
{
alSetError(AL_OUT_OF_MEMORY);
return AL_FALSE;
}
State->TotalLength = totalLength;
State->SampleBuffer = temp;
// All lines share a single sample buffer
State->Delay.Mask = length[0] - 1;
State->Delay.Line = &State->SampleBuffer[0];
totalLength = length[0];
for(index = 0;index < 4;index++)
{
State->Early.Delay[index].Mask = length[1 + index] - 1;
State->Early.Delay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[1 + index];
}
for(index = 0;index < 4;index++)
{
State->Late.ApDelay[index].Mask = length[5 + index] - 1;
State->Late.ApDelay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[5 + index];
}
for(index = 0;index < 4;index++)
{
State->Late.Delay[index].Mask = length[9 + index] - 1;
State->Late.Delay[index].Line = &State->SampleBuffer[totalLength];
totalLength += length[9 + index];
}
}
for(index = 0;index < 4;index++)
{
State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] *
Device->Frequency);
State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] *
Device->Frequency);
}
for(index = 0;index < State->TotalLength;index++)
State->SampleBuffer[index] = 0.0f;
return AL_TRUE;
}
// This updates the reverb state. This is called any time the reverb effect
// is loaded into a slot.
ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
{
ALverbState *State = Slot->ReverbState;
ALverbState *State = (ALverbState*)effect;
ALuint frequency = Context->Device->Frequency;
ALuint index;
ALfloat length, mixCoeff, cw, g, lpCoeff;
ALfloat length, mixCoeff, cw, g, coeff;
ALfloat hfRatio = Effect->Reverb.DecayHFRatio;
// Calculate the master gain (from the slot and master effect gain).
State->Gain = Slot->Gain * Effect->Reverb.Gain;
// Calculate the master low-pass filter (from the master effect HF gain).
cw = cos(2.0*M_PI * Effect->Reverb.HFReference / frequency);
g = __max(Effect->Reverb.GainHF, 0.0001f);
State->LpFilter.coeff = 0.0f;
if(g < 0.9999f) // 1-epsilon
State->LpFilter.coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
// Calculate the initial delay taps.
length = Effect->Reverb.ReflectionsDelay;
State->Tap[0] = (ALuint)(length * Context->Frequency);
State->Tap[0] = (ALuint)(length * frequency);
length += Effect->Reverb.LateReverbDelay;
@@ -475,11 +505,12 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
length += LATE_LINE_LENGTH[0] *
(1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER)) *
(DECO_FRACTION * (pow(DECO_MULTIPLIER, (ALfloat)index) - 1.0f));
State->Tap[1 + index] = (ALuint)(length * Context->Frequency);
State->Tap[1 + index] = (ALuint)(length * frequency);
}
// Set the early reflections gain.
State->Early.Gain = Effect->Reverb.ReflectionsGain;
// Calculate the early reflections gain (from the master effect gain, and
// reflections gain parameters).
State->Early.Gain = Effect->Reverb.Gain * Effect->Reverb.ReflectionsGain;
// Calculate the gain (coefficient) for each early delay line.
for(index = 0;index < 4;index++)
@@ -490,10 +521,11 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
// Calculate the first mixing matrix coefficient (x).
mixCoeff = 1.0f - (0.5f * pow(Effect->Reverb.Diffusion, 3.0f));
// Set the late reverb gain. Since the output is tapped prior to the
// Calculate the late reverb gain (from the master effect gain, and late
// reverb gain parameters). Since the output is tapped prior to the
// application of the delay line coefficients, this gain needs to be
// attenuated by the mix coefficient from above.
State->Late.Gain = Effect->Reverb.LateReverbGain * mixCoeff;
// attenuated by the 'x' mix coefficient from above.
State->Late.Gain = Effect->Reverb.Gain * Effect->Reverb.LateReverbGain * mixCoeff;
/* To compensate for changes in modal density and decay time of the late
* reverb signal, the input is attenuated based on the maximal energy of
@@ -514,18 +546,17 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
* for each line individually (most likely a side effect of diffusion).
*
* The final result is the square root of the ratio bound to a maximum
* value of 1 (no amplification) and attenuated by 1 / sqrt(2) to
* compensate for the four decorrelated inputs.
* value of 1 (no amplification).
*/
length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]);
g = length * (1.0f + LATE_LINE_MULTIPLIER) * 0.25f;
g = pow(10.0f, g * -60.0f / 20.0f);
g = 1.0f / (1.0f - g);
g = 1.0f / (1.0f - (g * g));
length *= 1.0f + (Effect->Reverb.Density * LATE_LINE_MULTIPLIER) * 0.25f;
length = pow(10.0f, length / Effect->Reverb.DecayTime * -60.0f / 20.0f);
length = 1.0f / (1.0f - length);
State->Late.DensityGain = 0.707106f * __min(aluSqrt(g / length), 1.0f);
length = 1.0f / (1.0f - (length * length));
State->Late.DensityGain = __min(aluSqrt(g / length), 1.0f);
// Calculate the all-pass feed-back and feed-forward coefficient.
State->Late.ApFeedCoeff = 0.6f * pow(Effect->Reverb.Diffusion, 3.0f);
@@ -565,12 +596,8 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
hfRatio = __min(hfRatio, limitRatio);
}
// Calculate the filter frequency for low-pass or high-pass depending on
// whether the HF ratio is above 1.
cw = 2.0f * M_PI * LOWPASSFREQCUTOFF / Context->Frequency;
if(hfRatio > 1.0f)
cw = M_PI - cw;
cw = cos(cw);
// Calculate the low-pass filter frequency.
cw = cos(2.0*M_PI * Effect->Reverb.HFReference / frequency);
for(index = 0;index < 4;index++)
{
@@ -578,83 +605,239 @@ ALvoid VerbUpdate(ALCcontext *Context, ALeffectslot *Slot, ALeffect *Effect)
length = LATE_LINE_LENGTH[index] * (1.0f + (Effect->Reverb.Density *
LATE_LINE_MULTIPLIER));
// Calculate the delay offset for the cyclical delay lines.
State->Late.Offset[index] = (ALuint)(length * Context->Frequency);
State->Late.Offset[index] = (ALuint)(length * frequency);
// Calculate the gain (coefficient) for each cyclical line.
State->Late.Coeff[index] = pow(10.0f, length / Effect->Reverb.DecayTime *
-60.0f / 20.0f);
// Calculate the decay equation for each low-pass filter.
g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
-60.0f / 20.0f);
if (hfRatio > 1.0f)
g = State->Late.Coeff[index] / g;
else
g = g / State->Late.Coeff[index];
g = __max(g, 0.1f);
g *= g;
// Eventually this should boost the high frequencies when the ratio
// exceeds 1.
coeff = 0.0f;
if (hfRatio < 1.0f)
{
// Calculate the decay equation for each low-pass filter.
g = pow(10.0f, length / (Effect->Reverb.DecayTime * hfRatio) *
-60.0f / 20.0f) / State->Late.Coeff[index];
g = __max(g, 0.1f);
g *= g;
// Calculate the gain (coefficient) for each low-pass filter.
lpCoeff = 0.0f;
if(g < 0.9999f) // 1-epsilon
lpCoeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
// Calculate the gain (coefficient) for each low-pass filter.
if(g < 0.9999f) // 1-epsilon
coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
// Very low decay times will produce minimal output, so apply an
// upper bound to the coefficient.
lpCoeff = __min(lpCoeff, 0.98f);
// Calculate the filter coefficients for high-pass or low-pass
// dependent on HF ratio being above 1.
if(hfRatio > 1.0f) {
State->Late.LpCoeff[index][0] = 1.0f + lpCoeff;
State->Late.LpCoeff[index][1] = -lpCoeff;
} else {
State->Late.LpCoeff[index][0] = 1.0f - lpCoeff;
State->Late.LpCoeff[index][1] = lpCoeff;
// Very low decay times will produce minimal output, so apply an
// upper bound to the coefficient.
coeff = __min(coeff, 0.98f);
}
State->Late.LpCoeff[index] = coeff;
// Attenuate the cyclical line coefficients by the mixing coefficient
// (x).
State->Late.Coeff[index] *= mixCoeff;
}
// Calculate the 3D-panning gains for the early reflections and late
// reverb (for EAX mode).
{
ALfloat earlyPan[3] = { Effect->Reverb.ReflectionsPan[0], Effect->Reverb.ReflectionsPan[1], Effect->Reverb.ReflectionsPan[2] };
ALfloat latePan[3] = { Effect->Reverb.LateReverbPan[0], Effect->Reverb.LateReverbPan[1], Effect->Reverb.LateReverbPan[2] };
ALfloat *speakerGain, dirGain, ambientGain;
ALfloat length;
ALint pos;
length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
if(length > 1.0f)
{
length = 1.0f / aluSqrt(length);
earlyPan[0] *= length;
earlyPan[1] *= length;
earlyPan[2] *= length;
}
length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
if(length > 1.0f)
{
length = 1.0f / aluSqrt(length);
latePan[0] *= length;
latePan[1] *= length;
latePan[2] *= length;
}
// This code applies directional reverb just like the mixer applies
// directional sources. It diffuses the sound toward all speakers
// as the magnitude of the panning vector drops, which is only an
// approximation of the expansion of sound across the speakers from
// the panning direction.
pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
ambientGain = (1.0 - dirGain);
for(index = 0;index < OUTPUTCHANNELS;index++)
State->Early.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
pos = aluCart2LUTpos(latePan[2], latePan[0]);
speakerGain = &Context->PanningLUT[OUTPUTCHANNELS * pos];
dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
ambientGain = (1.0 - dirGain);
for(index = 0;index < OUTPUTCHANNELS;index++)
State->Late.PanGain[index] = dirGain * speakerGain[index] + ambientGain;
}
}
// This processes the reverb state, given the input samples and an output
// buffer.
ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
{
ALverbState *State = (ALverbState*)effect;
ALuint index;
ALfloat in[4], early[2], late[2], out[2];
ALfloat early[4], late[4], out[4];
ALfloat gain = Slot->Gain;
for(index = 0;index < SamplesToDo;index++)
{
// Feed the initial delay line.
DelayLineIn(&State->Delay, State->Offset, SamplesIn[index]);
// Calculate the early reflection from the first delay tap.
in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[0]);
EarlyReflection(State, in[0], early);
// Calculate the late reverb from the last four delay taps.
in[0] = DelayLineOut(&State->Delay, State->Offset - State->Tap[1]);
in[1] = DelayLineOut(&State->Delay, State->Offset - State->Tap[2]);
in[2] = DelayLineOut(&State->Delay, State->Offset - State->Tap[3]);
in[3] = DelayLineOut(&State->Delay, State->Offset - State->Tap[4]);
LateReverb(State, in, late);
// Process reverb for this sample.
ReverbInOut(State, SamplesIn[index], early, late);
// Mix early reflections and late reverb.
out[0] = State->Gain * (early[0] + late[0]);
out[1] = State->Gain * (early[1] + late[1]);
// Step all delays forward one sample.
State->Offset++;
out[0] = (early[0] + late[0]) * gain;
out[1] = (early[1] + late[1]) * gain;
out[2] = (early[2] + late[2]) * gain;
out[3] = (early[3] + late[3]) * gain;
// Output the results.
SamplesOut[index][FRONT_LEFT] += out[0];
SamplesOut[index][FRONT_RIGHT] += out[1];
SamplesOut[index][SIDE_LEFT] += out[0];
SamplesOut[index][SIDE_RIGHT] += out[1];
SamplesOut[index][BACK_LEFT] += out[0];
SamplesOut[index][BACK_RIGHT] += out[1];
SamplesOut[index][FRONT_LEFT] += out[0];
SamplesOut[index][FRONT_RIGHT] += out[1];
SamplesOut[index][FRONT_CENTER] += out[3];
SamplesOut[index][SIDE_LEFT] += out[0];
SamplesOut[index][SIDE_RIGHT] += out[1];
SamplesOut[index][BACK_LEFT] += out[0];
SamplesOut[index][BACK_RIGHT] += out[1];
SamplesOut[index][BACK_CENTER] += out[2];
}
}
// This processes the EAX reverb state, given the input samples and an output
// buffer.
ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
{
ALverbState *State = (ALverbState*)effect;
ALuint index;
ALfloat early[4], late[4];
ALfloat gain = Slot->Gain;
for(index = 0;index < SamplesToDo;index++)
{
// Process reverb for this sample.
ReverbInOut(State, SamplesIn[index], early, late);
// Unfortunately, while the number and configuration of gains for
// panning adjust according to OUTPUTCHANNELS, the output from the
// reverb engine is not so scalable.
SamplesOut[index][FRONT_LEFT] +=
(State->Early.PanGain[FRONT_LEFT]*early[0] +
State->Late.PanGain[FRONT_LEFT]*late[0]) * gain;
SamplesOut[index][FRONT_RIGHT] +=
(State->Early.PanGain[FRONT_RIGHT]*early[1] +
State->Late.PanGain[FRONT_RIGHT]*late[1]) * gain;
SamplesOut[index][FRONT_CENTER] +=
(State->Early.PanGain[FRONT_CENTER]*early[3] +
State->Late.PanGain[FRONT_CENTER]*late[3]) * gain;
SamplesOut[index][SIDE_LEFT] +=
(State->Early.PanGain[SIDE_LEFT]*early[0] +
State->Late.PanGain[SIDE_LEFT]*late[0]) * gain;
SamplesOut[index][SIDE_RIGHT] +=
(State->Early.PanGain[SIDE_RIGHT]*early[1] +
State->Late.PanGain[SIDE_RIGHT]*late[1]) * gain;
SamplesOut[index][BACK_LEFT] +=
(State->Early.PanGain[BACK_LEFT]*early[0] +
State->Late.PanGain[BACK_LEFT]*late[0]) * gain;
SamplesOut[index][BACK_RIGHT] +=
(State->Early.PanGain[BACK_RIGHT]*early[1] +
State->Late.PanGain[BACK_RIGHT]*late[1]) * gain;
SamplesOut[index][BACK_CENTER] +=
(State->Early.PanGain[BACK_CENTER]*early[2] +
State->Late.PanGain[BACK_CENTER]*late[2]) * gain;
}
}
// This creates the reverb state. It should be called only when the reverb
// effect is loaded into a slot that doesn't already have a reverb effect.
ALeffectState *VerbCreate(void)
{
ALverbState *State = NULL;
ALuint index;
State = malloc(sizeof(ALverbState));
if(!State)
{
alSetError(AL_OUT_OF_MEMORY);
return NULL;
}
State->state.Destroy = VerbDestroy;
State->state.DeviceUpdate = VerbDeviceUpdate;
State->state.Update = VerbUpdate;
State->state.Process = VerbProcess;
State->TotalLength = 0;
State->SampleBuffer = NULL;
State->LpFilter.coeff = 0.0f;
State->LpFilter.history[0] = 0.0f;
State->LpFilter.history[1] = 0.0f;
State->Delay.Mask = 0;
State->Delay.Line = NULL;
State->Tap[0] = 0;
State->Tap[1] = 0;
State->Tap[2] = 0;
State->Tap[3] = 0;
State->Tap[4] = 0;
State->Early.Gain = 0.0f;
for(index = 0;index < 4;index++)
{
State->Early.Coeff[index] = 0.0f;
State->Early.Delay[index].Mask = 0;
State->Early.Delay[index].Line = NULL;
State->Early.Offset[index] = 0;
}
State->Late.Gain = 0.0f;
State->Late.DensityGain = 0.0f;
State->Late.ApFeedCoeff = 0.0f;
State->Late.MixCoeff = 0.0f;
for(index = 0;index < 4;index++)
{
State->Late.ApCoeff[index] = 0.0f;
State->Late.ApDelay[index].Mask = 0;
State->Late.ApDelay[index].Line = NULL;
State->Late.ApOffset[index] = 0;
State->Late.Coeff[index] = 0.0f;
State->Late.Delay[index].Mask = 0;
State->Late.Delay[index].Line = NULL;
State->Late.Offset[index] = 0;
State->Late.LpCoeff[index] = 0.0f;
State->Late.LpSample[index] = 0.0f;
}
// Panning is applied as an independent gain for each output channel.
for(index = 0;index < OUTPUTCHANNELS;index++)
{
State->Early.PanGain[index] = 0.0f;
State->Late.PanGain[index] = 0.0f;
}
State->Offset = 0;
return &State->state;
}
ALeffectState *EAXVerbCreate(void)
{
ALeffectState *State = VerbCreate();
if(State) State->Process = EAXVerbProcess;
return State;
}
+4 -2
View File
@@ -81,10 +81,11 @@ ALsizei RingBufferSize(RingBuffer *ring)
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
{
int remain = ring->length - ring->write_pos;
int remain;
EnterCriticalSection(&ring->cs);
remain = ring->length - ring->write_pos;
if((ring->read_pos-ring->write_pos+ring->length)%ring->length < len)
ring->read_pos = (ring->write_pos+len) % ring->length;
@@ -104,10 +105,11 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
{
int remain = ring->length - ring->read_pos;
int remain;
EnterCriticalSection(&ring->cs);
remain = ring->length - ring->read_pos;
if(remain < len)
{
memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), remain*ring->frame_size);
+590 -551
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -113,8 +113,6 @@ static void init(struct bs2b *bs2b)
bs2b->a1_hi = -x;
bs2b->gain = 1.0 / (1.0 - G_hi + G_lo);
bs2b_clear(bs2b);
} /* init */
/* Exported functions.
+243 -125
View File
@@ -28,23 +28,29 @@
#include <dsound.h>
#include <mmreg.h>
#ifndef _WAVEFORMATEXTENSIBLE_
#include <ks.h>
#include <ksmedia.h>
#endif
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#ifndef DSSPEAKER_5POINT1
#define DSSPEAKER_5POINT1 6
#endif
#ifndef DSSPEAKER_7POINT1
#define DSSPEAKER_7POINT1 7
#endif
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
static void *ds_handle;
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
// Since DSound doesn't report the fragment size, emulate it
static int num_frags;
typedef struct {
// DirectSound Playback Device
@@ -61,36 +67,100 @@ typedef struct {
ALCchar *name;
GUID guid;
} DevMap;
static DevMap DeviceList[16];
static const ALCchar dsDevice[] = "DirectSound Software";
static DevMap *DeviceList;
static ALuint NumDevices;
static volatile ALuint load_count;
void DSoundLoad(void)
{
if(load_count == 0)
{
#ifdef _WIN32
ds_handle = LoadLibraryA("dsound.dll");
if(ds_handle == NULL)
{
AL_PRINT("Failed to load dsound.dll\n");
return;
}
#define LOAD_FUNC(f) do { \
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
if(p##f == NULL) \
{ \
FreeLibrary(ds_handle); \
ds_handle = NULL; \
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
return; \
} \
} while(0)
#else
ds_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
}
++load_count;
}
void DSoundUnload(void)
{
if(load_count == 0 || --load_count > 0)
return;
#ifdef _WIN32
FreeLibrary(ds_handle);
#endif
ds_handle = NULL;
}
static ALuint DSoundProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
DSoundData *pData = (DSoundData*)pDevice->ExtraData;
DSBCAPS DSBCaps;
DWORD LastCursor = 0;
DWORD PlayCursor;
VOID *WritePtr1, *WritePtr2;
DWORD WriteCnt1, WriteCnt2;
DWORD BufferSize;
DWORD FrameSize;
DWORD FragSize;
DWORD avail;
HRESULT err;
BufferSize = pDevice->UpdateSize * num_frags *
aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format);
memset(&DSBCaps, 0, sizeof(DSBCaps));
DSBCaps.dwSize = sizeof(DSBCaps);
err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
if(FAILED(err))
{
AL_PRINT("Failed to get buffer caps: 0x%lx\n", err);
aluHandleDisconnect(pDevice);
return 1;
}
FrameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
FragSize = pDevice->UpdateSize * FrameSize;
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
while(!pData->killNow)
{
// Get current play and write cursors
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
avail = (PlayCursor-LastCursor+BufferSize) % BufferSize;
avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
if(avail < BufferSize/num_frags)
if(avail < FragSize)
{
Sleep(1);
continue;
}
avail -= avail%FragSize;
// Lock output buffer
WriteCnt1 = 0;
@@ -111,10 +181,8 @@ static ALuint DSoundProc(ALvoid *ptr)
if(SUCCEEDED(err))
{
// If we have an active context, mix data directly into output buffer otherwise fill with silence
SuspendContext(NULL);
aluMixData(pDevice->Context, WritePtr1, WriteCnt1, pDevice->Format);
aluMixData(pDevice->Context, WritePtr2, WriteCnt2, pDevice->Format);
ProcessContext(NULL);
aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize);
aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize);
// Unlock output buffer only when successfully locked
IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
@@ -124,7 +192,7 @@ static ALuint DSoundProc(ALvoid *ptr)
// Update old write cursor location
LastCursor += WriteCnt1+WriteCnt2;
LastCursor %= BufferSize;
LastCursor %= DSBCaps.dwBufferBytes;
}
return 0;
@@ -132,44 +200,38 @@ static ALuint DSoundProc(ALvoid *ptr)
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
{
DSBUFFERDESC DSBDescription;
DSoundData *pData = NULL;
WAVEFORMATEXTENSIBLE OutputType;
DWORD frameSize = 0;
LPGUID guid = NULL;
DWORD speakers;
HRESULT hr;
if(ds_handle == NULL)
return ALC_FALSE;
if(deviceName)
if(!deviceName)
deviceName = dsDevice;
else if(strcmp(deviceName, dsDevice) != 0)
{
int i;
for(i = 0;DeviceList[i].name;i++)
ALuint i;
for(i = 0;i < NumDevices;i++)
{
if(strcmp(deviceName, DeviceList[i].name) == 0)
{
device->szDeviceName = DeviceList[i].name;
if(i > 0)
guid = &DeviceList[i].guid;
guid = &DeviceList[i].guid;
break;
}
}
if(!DeviceList[i].name)
if(i == NumDevices)
return ALC_FALSE;
}
else
device->szDeviceName = DeviceList[0].name;
memset(&OutputType, 0, sizeof(OutputType));
DSoundLoad();
if(ds_handle == NULL)
return ALC_FALSE;
//Initialise requested device
pData = calloc(1, sizeof(DSoundData));
if(!pData)
{
SetALCError(ALC_OUT_OF_MEMORY);
alcSetError(ALC_OUT_OF_MEMORY);
DSoundUnload();
return ALC_FALSE;
}
@@ -177,25 +239,60 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
hr = pDirectSoundCreate(guid, &pData->lpDS, NULL);
if(SUCCEEDED(hr))
hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
if(SUCCEEDED(hr))
if(FAILED(hr))
{
if(*(GetConfigValue(NULL, "format", "")) == 0)
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
if(pData->lpDS)
IDirectSound_Release(pData->lpDS);
free(pData);
DSoundUnload();
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = pData;
return ALC_TRUE;
}
static void DSoundClosePlayback(ALCdevice *device)
{
DSoundData *pData = device->ExtraData;
IDirectSound_Release(pData->lpDS);
free(pData);
device->ExtraData = NULL;
DSoundUnload();
}
static ALCboolean DSoundResetPlayback(ALCdevice *device)
{
DSoundData *pData = (DSoundData*)device->ExtraData;
DSBUFFERDESC DSBDescription;
WAVEFORMATEXTENSIBLE OutputType;
DWORD frameSize = 0;
ALenum format = 0;
DWORD speakers;
HRESULT hr;
memset(&OutputType, 0, sizeof(OutputType));
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
if(SUCCEEDED(hr) && *(GetConfigValue(NULL, "format", "")) != 0)
{
if(aluChannelsFromFormat(device->Format) == 1)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
else if(aluChannelsFromFormat(device->Format) == 2)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
else if(aluChannelsFromFormat(device->Format) == 4)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
else if(aluChannelsFromFormat(device->Format) == 6)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
else if(aluChannelsFromFormat(device->Format) == 8)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
else
{
if(device->Format == AL_FORMAT_MONO8 || device->Format == AL_FORMAT_MONO16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
else if(device->Format == AL_FORMAT_STEREO8 || device->Format == AL_FORMAT_STEREO16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
else if(device->Format == AL_FORMAT_QUAD8 || device->Format == AL_FORMAT_QUAD16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
else if(device->Format == AL_FORMAT_51CHN8 || device->Format == AL_FORMAT_51CHN16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
else if(device->Format == AL_FORMAT_71CHN8 || device->Format == AL_FORMAT_71CHN16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
else
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
AL_PRINT("Unknown format: 0x%x\n", device->Format);
return ALC_FALSE;
}
}
if(SUCCEEDED(hr))
@@ -204,23 +301,29 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
if(speakers == DSSPEAKER_MONO)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_MONO8;
else
device->Format = AL_FORMAT_MONO16;
format = AL_FORMAT_MONO8;
else if(aluBytesFromFormat(device->Format) == 2)
format = AL_FORMAT_MONO16;
else if(aluBytesFromFormat(device->Format) == 4)
format = AL_FORMAT_MONO_FLOAT32;
}
else if(speakers == DSSPEAKER_STEREO)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_STEREO8;
else
device->Format = AL_FORMAT_STEREO16;
format = AL_FORMAT_STEREO8;
else if(aluBytesFromFormat(device->Format) == 2)
format = AL_FORMAT_STEREO16;
else if(aluBytesFromFormat(device->Format) == 4)
format = AL_FORMAT_STEREO_FLOAT32;
}
else if(speakers == DSSPEAKER_QUAD)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_QUAD8;
else
device->Format = AL_FORMAT_QUAD16;
format = AL_FORMAT_QUAD8;
else if(aluBytesFromFormat(device->Format) == 2)
format = AL_FORMAT_QUAD16;
else if(aluBytesFromFormat(device->Format) == 4)
format = AL_FORMAT_QUAD32;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_BACK_LEFT |
@@ -229,9 +332,11 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
else if(speakers == DSSPEAKER_5POINT1)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_51CHN8;
else
device->Format = AL_FORMAT_51CHN16;
format = AL_FORMAT_51CHN8;
else if(aluBytesFromFormat(device->Format) == 2)
format = AL_FORMAT_51CHN16;
else if(aluBytesFromFormat(device->Format) == 4)
format = AL_FORMAT_51CHN32;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
@@ -242,9 +347,11 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
else if(speakers == DSSPEAKER_7POINT1)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_71CHN8;
else
device->Format = AL_FORMAT_71CHN16;
format = AL_FORMAT_71CHN8;
else if(aluBytesFromFormat(device->Format) == 2)
format = AL_FORMAT_71CHN16;
else if(aluBytesFromFormat(device->Format) == 4)
format = AL_FORMAT_71CHN32;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
@@ -254,26 +361,28 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
SPEAKER_SIDE_LEFT |
SPEAKER_SIDE_RIGHT;
}
frameSize = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
else
format = device->Format;
frameSize = aluBytesFromFormat(format) * aluChannelsFromFormat(format);
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
OutputType.Format.nChannels = aluChannelsFromFormat(device->Format);
OutputType.Format.wBitsPerSample = aluBytesFromFormat(device->Format) * 8;
OutputType.Format.nChannels = aluChannelsFromFormat(format);
OutputType.Format.wBitsPerSample = aluBytesFromFormat(format) * 8;
OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
OutputType.Format.nSamplesPerSec = device->Frequency;
OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign;
OutputType.Format.cbSize = 0;
device->UpdateSize /= num_frags;
}
if(OutputType.Format.nChannels > 2)
if(OutputType.Format.nChannels > 2 || OutputType.Format.wBitsPerSample > 16)
{
OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
OutputType.Format.cbSize = 22;
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
if(OutputType.Format.wBitsPerSample == 32)
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
else
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
}
else
{
@@ -293,7 +402,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
DSBDescription.dwBufferBytes=device->UpdateSize * num_frags * frameSize;
DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * frameSize;
DSBDescription.lpwfxFormat=&OutputType.Format;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
}
@@ -313,42 +422,41 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
{
if (pData->DSsbuffer)
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if (pData->DSpbuffer)
IDirectSoundBuffer_Release(pData->DSpbuffer);
if (pData->lpDS)
IDirectSound_Release(pData->lpDS);
free(pData);
pData->DSpbuffer = NULL;
return ALC_FALSE;
}
device->Format = format;
return ALC_TRUE;
}
static void DSoundClosePlayback(ALCdevice *device)
static void DSoundStopPlayback(ALCdevice *device)
{
DSoundData *pData = device->ExtraData;
if(!pData->thread)
return;
pData->killNow = 1;
StopThread(pData->thread);
pData->thread = NULL;
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if (pData->DSpbuffer)
IDirectSoundBuffer_Release(pData->DSpbuffer);
IDirectSound_Release(pData->lpDS);
free(pData);
device->ExtraData = NULL;
pData->DSpbuffer = NULL;
}
static ALCboolean DSoundOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
static ALCboolean DSoundOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
{
(void)pDevice;
(void)deviceName;
(void)frequency;
(void)format;
(void)SampleSize;
return ALC_FALSE;
}
@@ -384,6 +492,8 @@ static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
BackendFuncs DSoundFuncs = {
DSoundOpenPlayback,
DSoundClosePlayback,
DSoundResetPlayback,
DSoundStopPlayback,
DSoundOpenCapture,
DSoundCloseCapture,
DSoundStartCapture,
@@ -394,61 +504,69 @@ BackendFuncs DSoundFuncs = {
static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
{
size_t *iter = data;
(void)data;
(void)drvname;
if(guid)
{
char str[128];
snprintf(str, sizeof(str), "DirectSound Software on %s", desc);
DeviceList[*iter].name = AppendAllDeviceList(str);
DeviceList[*iter].guid = *guid;
(*iter)++;
void *temp;
temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1));
if(temp)
{
DeviceList = temp;
snprintf(str, sizeof(str), "DirectSound Software on %s", desc);
AppendAllDeviceList(str);
DeviceList[NumDevices].name = strdup(str);
DeviceList[NumDevices].guid = *guid;
NumDevices++;
}
}
else
DeviceList[0].name = AppendDeviceList("DirectSound Software");
return TRUE;
}
void alcDSoundInit(BackendFuncs *FuncList)
{
size_t iter = 1;
HRESULT hr;
*FuncList = DSoundFuncs;
}
#ifdef _WIN32
ds_handle = LoadLibraryA("dsound.dll");
if(ds_handle == NULL)
void alcDSoundDeinit(void)
{
ALuint i;
for(i = 0;i < NumDevices;++i)
free(DeviceList[i].name);
free(DeviceList);
DeviceList = NULL;
NumDevices = 0;
}
void alcDSoundProbe(int type)
{
DSoundLoad();
if(!ds_handle) return;
if(type == DEVICE_PROBE)
AppendDeviceList(dsDevice);
else if(type == ALL_DEVICE_PROBE)
{
AL_PRINT("Failed to load dsound.dll\n");
return;
HRESULT hr;
ALuint i;
for(i = 0;i < NumDevices;++i)
free(DeviceList[i].name);
free(DeviceList);
DeviceList = NULL;
NumDevices = 0;
hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL);
if(FAILED(hr))
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
}
#define LOAD_FUNC(f) do { \
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
if(p##f == NULL) \
{ \
FreeLibrary(ds_handle); \
ds_handle = NULL; \
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
return; \
} \
} while(0)
#else
ds_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
num_frags = GetConfigValueInt("dsound", "periods", 4);
if(num_frags < 2) num_frags = 2;
hr = pDirectSoundEnumerateA(DSoundEnumDevices, &iter);
if(FAILED(hr))
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
DSoundUnload();
}
+135 -95
View File
@@ -47,8 +47,8 @@
#define SOUND_MIXER_WRITE MIXER_WRITE
#endif
static char *oss_device;
static char *oss_device_capture;
static const ALCchar oss_device[] = "OSS Software";
static const ALCchar oss_device_capture[] = "OSS Capture";
typedef struct {
int fd;
@@ -79,35 +79,37 @@ static ALuint OSSProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
oss_data *data = (oss_data*)pDevice->ExtraData;
int remaining = 0;
int wrote;
ALint frameSize;
ssize_t wrote;
while(!data->killNow)
frameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
while(!data->killNow && pDevice->Connected)
{
int len = data->data_size - remaining;
ALint len = data->data_size;
ALubyte *WritePtr = data->mix_data;
if(len > 0)
aluMixData(pDevice, WritePtr, len/frameSize);
while(len > 0 && !data->killNow)
{
SuspendContext(NULL);
aluMixData(pDevice->Context, data->mix_data+remaining, len, pDevice->Format);
ProcessContext(NULL);
}
wrote = write(data->fd, WritePtr, len);
if(wrote < 0)
{
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
{
AL_PRINT("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
len = 0;
}
else
Sleep(1);
continue;
}
remaining += len;
wrote = write(data->fd, data->mix_data, remaining);
if(wrote < 0)
{
AL_PRINT("write failed: %s\n", strerror(errno));
remaining = 0;
len -= wrote;
WritePtr += wrote;
}
else if(wrote > 0)
{
remaining -= wrote;
if(remaining > 0)
memmove(data->mix_data, data->mix_data+wrote, remaining);
}
else
Sleep(1);
}
return 0;
@@ -129,6 +131,7 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
if(amt < 0)
{
AL_PRINT("read failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
break;
}
if(amt == 0)
@@ -145,29 +148,15 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
int numFragmentsLogSize;
int log2FragmentSize;
unsigned int periods;
audio_buf_info info;
ALuint frameSize;
char driver[64];
int numChannels;
oss_data *data;
int ossFormat;
int ossSpeed;
char *err;
int i;
strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
{
if(strcmp(deviceName, oss_device))
return ALC_FALSE;
device->szDeviceName = oss_device;
}
else
device->szDeviceName = oss_device;
if(!deviceName)
deviceName = oss_device;
else if(strcmp(deviceName, oss_device) != 0)
return ALC_FALSE;
data = (oss_data*)calloc(1, sizeof(oss_data));
data->killNow = 0;
@@ -180,43 +169,83 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_TRUE;
}
static void oss_close_playback(ALCdevice *device)
{
oss_data *data = (oss_data*)device->ExtraData;
close(data->fd);
free(data);
device->ExtraData = NULL;
}
static ALCboolean oss_reset_playback(ALCdevice *device)
{
oss_data *data = (oss_data*)device->ExtraData;
int numFragmentsLogSize;
int log2FragmentSize;
unsigned int periods;
audio_buf_info info;
ALuint frameSize;
int numChannels;
int ossFormat;
int ossSpeed;
char *err;
int i;
switch(aluBytesFromFormat(device->Format))
{
case 1:
ossFormat = AFMT_U8;
break;
case 4:
switch(aluChannelsFromFormat(device->Format))
{
case 1: device->Format = AL_FORMAT_MONO16; break;
case 2: device->Format = AL_FORMAT_STEREO16; break;
case 4: device->Format = AL_FORMAT_QUAD16; break;
case 6: device->Format = AL_FORMAT_51CHN16; break;
case 7: device->Format = AL_FORMAT_61CHN16; break;
case 8: device->Format = AL_FORMAT_71CHN16; break;
}
/* fall-through */
case 2:
ossFormat = AFMT_S16_NE;
break;
default:
ossFormat = -1;
AL_PRINT("Unknown format?! %x\n", device->Format);
AL_PRINT("Unknown format: 0x%x\n", device->Format);
return ALC_FALSE;
}
periods = GetConfigValueInt("oss", "periods", 4);
if((int)periods <= 0)
periods = 4;
periods = device->NumUpdates;
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = device->Frequency;
log2FragmentSize = log2i(device->UpdateSize * frameSize / periods);
log2FragmentSize = log2i(device->UpdateSize * frameSize);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
log2FragmentSize = 4;
/* Subtract one period since the temp mixing buffer counts as one. Still
* need at least two on the card, though. */
if(periods > 2) periods--;
numFragmentsLogSize = (periods << 16) | log2FragmentSize;
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize), "set fragment") &&
ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
/* Don't fail if SETFRAGMENT fails. We can handle just about anything
* that's reported back via GETOSPACE */
ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize);
if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
ok(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels), "set channels") &&
ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
ok(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info), "get space")))
{
AL_PRINT("%s failed: %s\n", err, strerror(errno));
close(data->fd);
free(data);
return ALC_FALSE;
}
#undef ok
@@ -224,8 +253,6 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
if((int)aluChannelsFromFormat(device->Format) != numChannels)
{
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), numChannels);
close(data->fd);
free(data);
return ALC_FALSE;
}
@@ -233,45 +260,47 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
(ossFormat == AFMT_S16_NE && aluBytesFromFormat(device->Format) == 2)))
{
AL_PRINT("Could not set %d-bit output, got format %#x\n", aluBytesFromFormat(device->Format)*8, ossFormat);
close(data->fd);
free(data);
return ALC_FALSE;
}
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
device->ExtraData = data;
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
free(data->mix_data);
free(data);
return ALC_FALSE;
}
device->Frequency = ossSpeed;
device->UpdateSize = info.fragsize / frameSize;
device->NumUpdates = info.fragments + 1;
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
{
free(data->mix_data);
data->mix_data = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
static void oss_close_playback(ALCdevice *device)
static void oss_stop_playback(ALCdevice *device)
{
oss_data *data = (oss_data*)device->ExtraData;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
close(data->fd);
if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0)
AL_PRINT("Error resetting device: %s\n", strerror(errno));
free(data->mix_data);
free(data);
device->ExtraData = NULL;
data->mix_data = NULL;
}
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
int numFragmentsLogSize;
int log2FragmentSize;
@@ -288,14 +317,10 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
{
if(strcmp(deviceName, oss_device_capture))
return ALC_FALSE;
device->szDeviceName = oss_device_capture;
}
else
device->szDeviceName = oss_device_capture;
if(!deviceName)
deviceName = oss_device_capture;
else if(strcmp(deviceName, oss_device_capture) != 0)
return ALC_FALSE;
data = (oss_data*)calloc(1, sizeof(oss_data));
data->killNow = 0;
@@ -308,7 +333,7 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
switch(aluBytesFromFormat(format))
switch(aluBytesFromFormat(device->Format))
{
case 1:
ossFormat = AFMT_U8;
@@ -317,15 +342,18 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
ossFormat = AFMT_S16_NE;
break;
default:
ossFormat = -1;
AL_PRINT("Unknown format?! %x\n", device->Format);
AL_PRINT("Unknown format: 0x%x\n", device->Format);
close(data->fd);
free(data);
return ALC_FALSE;
}
periods = 4;
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = frequency;
log2FragmentSize = log2i(SampleSize * frameSize / periods);
ossSpeed = device->Frequency;
log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
frameSize / periods);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
@@ -363,7 +391,7 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
data->ring = CreateRingBuffer(frameSize, SampleSize);
data->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates);
if(!data->ring)
{
AL_PRINT("ring buffer create failed\n");
@@ -385,6 +413,7 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
return ALC_TRUE;
}
@@ -421,7 +450,7 @@ static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lS
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
ReadRingBuffer(data->ring, pBuffer, lSamples);
else
SetALCError(ALC_INVALID_VALUE);
alcSetError(ALC_INVALID_VALUE);
}
static ALCuint oss_available_samples(ALCdevice *pDevice)
@@ -434,6 +463,8 @@ static ALCuint oss_available_samples(ALCdevice *pDevice)
BackendFuncs oss_funcs = {
oss_open_playback,
oss_close_playback,
oss_reset_playback,
oss_stop_playback,
oss_open_capture,
oss_close_capture,
oss_start_capture,
@@ -445,9 +476,18 @@ BackendFuncs oss_funcs = {
void alc_oss_init(BackendFuncs *func_list)
{
*func_list = oss_funcs;
oss_device = AppendDeviceList("OSS Software");
AppendAllDeviceList(oss_device);
oss_device_capture = AppendCaptureDeviceList("OSS Capture");
}
void alc_oss_deinit(void)
{
}
void alc_oss_probe(int type)
{
if(type == DEVICE_PROBE)
AppendDeviceList(oss_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(oss_device);
else if(type == CAPTURE_DEVICE_PROBE)
AppendCaptureDeviceList(oss_device_capture);
}
+220 -161
View File
@@ -35,173 +35,38 @@
static void *pa_handle;
#define MAKE_FUNC(x) static typeof(x) * p##x
MAKE_FUNC(Pa_Initialize);
MAKE_FUNC(Pa_Terminate);
MAKE_FUNC(Pa_GetErrorText);
MAKE_FUNC(Pa_StartStream);
MAKE_FUNC(Pa_StopStream);
MAKE_FUNC(Pa_OpenStream);
MAKE_FUNC(Pa_CloseStream);
MAKE_FUNC(Pa_GetDefaultOutputDevice);
MAKE_FUNC(Pa_GetStreamInfo);
#undef MAKE_FUNC
static char *pa_device;
typedef struct {
PaStream *stream;
} pa_data;
static const ALCchar pa_device[] = "PortAudio Software";
static volatile ALuint load_count;
static int pa_callback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
const PaStreamCallbackFlags statusFlags, void *userData)
{
ALCdevice *device = (ALCdevice*)userData;
int frameSize;
(void)inputBuffer;
(void)timeInfo;
(void)statusFlags;
frameSize = aluBytesFromFormat(device->Format);
frameSize *= aluChannelsFromFormat(device->Format);
SuspendContext(NULL);
aluMixData(device->Context, outputBuffer, framesPerBuffer*frameSize, device->Format);
ProcessContext(NULL);
return 0;
}
static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
PaStreamParameters outParams;
pa_data *data;
int periods;
PaError err;
if(pa_handle == NULL)
return ALC_FALSE;
if(deviceName)
{
if(strcmp(deviceName, pa_device) != 0)
return ALC_FALSE;
}
device->szDeviceName = pa_device;
data = (pa_data*)calloc(1, sizeof(pa_data));
device->ExtraData = data;
outParams.device = GetConfigValueInt("port", "device", -1);
if(outParams.device < 0)
outParams.device = pPa_GetDefaultOutputDevice();
outParams.suggestedLatency = (float)device->UpdateSize /
(float)device->Frequency;
outParams.hostApiSpecificStreamInfo = NULL;
switch(aluBytesFromFormat(device->Format))
{
case 1:
outParams.sampleFormat = paUInt8;
break;
case 2:
outParams.sampleFormat = paInt16;
break;
default:
outParams.sampleFormat = -1;
AL_PRINT("Unknown format?! %x\n", device->Format);
}
periods = GetConfigValueInt("port", "periods", 4);
if((int)periods <= 0)
periods = 4;
outParams.channelCount = aluChannelsFromFormat(device->Format);
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
device->UpdateSize/periods, paNoFlag,
pa_callback, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
device->ExtraData = NULL;
free(data);
return ALC_FALSE;
}
err = pPa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
pPa_CloseStream(data->stream);
device->ExtraData = NULL;
free(data);
return ALC_FALSE;
}
device->UpdateSize /= periods;
return ALC_TRUE;
}
static void pa_close_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error stopping stream: %s\n", pPa_GetErrorText(err));
err = pPa_CloseStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error closing stream: %s\n", pPa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
}
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
{
return ALC_FALSE;
(void)device;
(void)deviceName;
(void)frequency;
(void)format;
(void)SampleSize;
}
static const BackendFuncs pa_funcs = {
pa_open_playback,
pa_close_playback,
pa_open_capture,
NULL,
NULL,
NULL,
NULL,
NULL
};
void alc_pa_init(BackendFuncs *func_list)
void pa_load(void)
{
const char *str;
PaError err;
*func_list = pa_funcs;
if(load_count == 0)
{
#ifdef HAVE_DLFCN_H
#if defined(__APPLE__) && defined(__MACH__)
# define PALIB "libportaudio.2.dylib"
#else
# define PALIB "libportaudio.so.2"
#endif
pa_handle = dlopen(PALIB, RTLD_NOW);
if(!pa_handle)
return;
dlerror();
pa_handle = dlopen(PALIB, RTLD_NOW);
if(!pa_handle)
return;
dlerror();
#define LOAD_FUNC(f) do { \
p##f = (typeof(f)*)dlsym(pa_handle, #f); \
@@ -214,26 +79,220 @@ void alc_pa_init(BackendFuncs *func_list)
} \
} while(0)
#else
str = NULL;
pa_handle = (void*)0xDEADBEEF;
str = NULL;
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(Pa_Initialize);
LOAD_FUNC(Pa_GetErrorText);
LOAD_FUNC(Pa_StartStream);
LOAD_FUNC(Pa_StopStream);
LOAD_FUNC(Pa_OpenStream);
LOAD_FUNC(Pa_CloseStream);
LOAD_FUNC(Pa_GetDefaultOutputDevice);
LOAD_FUNC(Pa_Initialize);
LOAD_FUNC(Pa_Terminate);
LOAD_FUNC(Pa_GetErrorText);
LOAD_FUNC(Pa_StartStream);
LOAD_FUNC(Pa_StopStream);
LOAD_FUNC(Pa_OpenStream);
LOAD_FUNC(Pa_CloseStream);
LOAD_FUNC(Pa_GetDefaultOutputDevice);
LOAD_FUNC(Pa_GetStreamInfo);
#undef LOAD_FUNC
if((err=pPa_Initialize()) != paNoError)
{
AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err));
return;
if((err=pPa_Initialize()) != paNoError)
{
AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err));
#ifdef HAVE_DLFCN_H
dlclose(pa_handle);
#endif
pa_handle = NULL;
return;
}
}
pa_device = AppendDeviceList("PortAudio Software");
AppendAllDeviceList(pa_device);
++load_count;
}
void pa_unload(void)
{
if(load_count == 0 || --load_count > 0)
return;
pPa_Terminate();
#ifdef HAVE_DLFCN_H
dlclose(pa_handle);
#endif
pa_handle = NULL;
}
typedef struct {
PaStream *stream;
} pa_data;
static int pa_callback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
const PaStreamCallbackFlags statusFlags, void *userData)
{
ALCdevice *device = (ALCdevice*)userData;
(void)inputBuffer;
(void)timeInfo;
(void)statusFlags;
aluMixData(device, outputBuffer, framesPerBuffer);
return 0;
}
static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
const PaStreamInfo *streamInfo;
PaStreamParameters outParams;
pa_data *data;
PaError err;
if(!deviceName)
deviceName = pa_device;
else if(strcmp(deviceName, pa_device) != 0)
return ALC_FALSE;
pa_load();
if(pa_handle == NULL)
return ALC_FALSE;
data = (pa_data*)calloc(1, sizeof(pa_data));
device->ExtraData = data;
outParams.device = GetConfigValueInt("port", "device", -1);
if(outParams.device < 0)
outParams.device = pPa_GetDefaultOutputDevice();
outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
(float)device->Frequency;
outParams.hostApiSpecificStreamInfo = NULL;
switch(aluBytesFromFormat(device->Format))
{
case 1:
outParams.sampleFormat = paUInt8;
break;
case 2:
outParams.sampleFormat = paInt16;
break;
case 4:
outParams.sampleFormat = paFloat32;
break;
default:
AL_PRINT("Unknown format: 0x%x\n", device->Format);
device->ExtraData = NULL;
free(data);
pa_unload();
return ALC_FALSE;
}
outParams.channelCount = aluChannelsFromFormat(device->Format);
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
device->UpdateSize, paNoFlag, pa_callback, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
device->ExtraData = NULL;
free(data);
pa_unload();
return ALC_FALSE;
}
streamInfo = pPa_GetStreamInfo(data->stream);
err = pPa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
pPa_CloseStream(data->stream);
device->ExtraData = NULL;
free(data);
pa_unload();
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->Frequency = streamInfo->sampleRate;
return ALC_TRUE;
}
static void pa_close_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error stopping stream: %s\n", pPa_GetErrorText(err));
err = pPa_CloseStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error closing stream: %s\n", pPa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
pa_unload();
}
static ALCboolean pa_reset_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
const PaStreamInfo *streamInfo;
streamInfo = pPa_GetStreamInfo(data->stream);
device->Frequency = streamInfo->sampleRate;
return ALC_TRUE;
}
static void pa_stop_playback(ALCdevice *device)
{
(void)device;
}
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
return ALC_FALSE;
(void)device;
(void)deviceName;
}
static const BackendFuncs pa_funcs = {
pa_open_playback,
pa_close_playback,
pa_reset_playback,
pa_stop_playback,
pa_open_capture,
NULL,
NULL,
NULL,
NULL,
NULL
};
void alc_pa_init(BackendFuncs *func_list)
{
*func_list = pa_funcs;
}
void alc_pa_deinit(void)
{
}
void alc_pa_probe(int type)
{
pa_load();
if(!pa_handle) return;
if(type == DEVICE_PROBE)
AppendDeviceList(pa_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(pa_device);
pa_unload();
}
+814
View File
@@ -0,0 +1,814 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 2009 by Konstantinos Natsakis <konstantinos.natsakis@gmail.com>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include "alMain.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <pulse/pulseaudio.h>
#if PA_API_VERSION == 11
#define PA_STREAM_ADJUST_LATENCY 0x2000U
static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
{
return (x == PA_STREAM_CREATING || x == PA_STREAM_READY);
}
static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
{
return (x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING ||
x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY);
}
#define PA_STREAM_IS_GOOD PA_STREAM_IS_GOOD
#define PA_CONTEXT_IS_GOOD PA_CONTEXT_IS_GOOD
#elif PA_API_VERSION != 12
#error Invalid PulseAudio API version
#endif
static void *pa_handle;
#define MAKE_FUNC(x) static typeof(x) * p##x
MAKE_FUNC(pa_context_unref);
MAKE_FUNC(pa_sample_spec_valid);
MAKE_FUNC(pa_stream_drop);
MAKE_FUNC(pa_strerror);
MAKE_FUNC(pa_context_get_state);
MAKE_FUNC(pa_stream_get_state);
MAKE_FUNC(pa_threaded_mainloop_signal);
MAKE_FUNC(pa_stream_peek);
MAKE_FUNC(pa_threaded_mainloop_wait);
MAKE_FUNC(pa_threaded_mainloop_unlock);
MAKE_FUNC(pa_threaded_mainloop_in_thread);
MAKE_FUNC(pa_context_new);
MAKE_FUNC(pa_threaded_mainloop_stop);
MAKE_FUNC(pa_context_disconnect);
MAKE_FUNC(pa_threaded_mainloop_start);
MAKE_FUNC(pa_threaded_mainloop_get_api);
MAKE_FUNC(pa_context_set_state_callback);
MAKE_FUNC(pa_stream_write);
MAKE_FUNC(pa_xfree);
MAKE_FUNC(pa_stream_connect_record);
MAKE_FUNC(pa_stream_connect_playback);
MAKE_FUNC(pa_path_get_filename);
MAKE_FUNC(pa_get_binary_name);
MAKE_FUNC(pa_threaded_mainloop_free);
MAKE_FUNC(pa_context_errno);
MAKE_FUNC(pa_xmalloc0);
MAKE_FUNC(pa_stream_unref);
MAKE_FUNC(pa_threaded_mainloop_accept);
MAKE_FUNC(pa_stream_set_write_callback);
MAKE_FUNC(pa_threaded_mainloop_new);
MAKE_FUNC(pa_context_connect);
MAKE_FUNC(pa_stream_get_buffer_attr);
MAKE_FUNC(pa_stream_set_buffer_attr_callback);
MAKE_FUNC(pa_stream_set_read_callback);
MAKE_FUNC(pa_stream_set_state_callback);
MAKE_FUNC(pa_stream_new);
MAKE_FUNC(pa_stream_disconnect);
MAKE_FUNC(pa_threaded_mainloop_lock);
MAKE_FUNC(pa_channel_map_init_auto);
MAKE_FUNC(pa_channel_map_parse);
#undef MAKE_FUNC
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
typedef struct {
ALCuint samples;
ALCuint frame_size;
RingBuffer *ring;
pa_buffer_attr attr;
pa_sample_spec spec;
char path_name[PATH_MAX];
const char *context_name;
const char *stream_name;
pa_threaded_mainloop *loop;
pa_stream *stream;
pa_context *context;
} pulse_data;
static const ALCchar pulse_device[] = "PulseAudio Software";
static const ALCchar pulse_capture_device[] = "PulseAudio Capture";
static volatile ALuint load_count;
void pulse_load(void) //{{{
{
if(load_count == 0)
{
#ifdef _WIN32
pa_handle = LoadLibrary("libpulse-0.dll");
#define LOAD_FUNC(x) do { \
p##x = GetProcAddress(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from libpulse-0.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#elif defined (HAVE_DLFCN_H)
const char *err;
#if defined(__APPLE__) && defined(__MACH__)
pa_handle = dlopen("libpulse.0.dylib", RTLD_NOW);
#else
pa_handle = dlopen("libpulse.so.0", RTLD_NOW);
#endif
dlerror();
#define LOAD_FUNC(x) do { \
p##x = dlsym(pa_handle, #x); \
if((err=dlerror()) != NULL) { \
AL_PRINT("Could not load %s from libpulse: %s\n", #x, err); \
dlclose(pa_handle); \
pa_handle = NULL; \
return; \
} \
} while(0)
#else
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(x) p##x = (x)
#endif
if(!pa_handle)
return;
LOAD_FUNC(pa_context_unref);
LOAD_FUNC(pa_sample_spec_valid);
LOAD_FUNC(pa_stream_drop);
LOAD_FUNC(pa_strerror);
LOAD_FUNC(pa_context_get_state);
LOAD_FUNC(pa_stream_get_state);
LOAD_FUNC(pa_threaded_mainloop_signal);
LOAD_FUNC(pa_stream_peek);
LOAD_FUNC(pa_threaded_mainloop_wait);
LOAD_FUNC(pa_threaded_mainloop_unlock);
LOAD_FUNC(pa_threaded_mainloop_in_thread);
LOAD_FUNC(pa_context_new);
LOAD_FUNC(pa_threaded_mainloop_stop);
LOAD_FUNC(pa_context_disconnect);
LOAD_FUNC(pa_threaded_mainloop_start);
LOAD_FUNC(pa_threaded_mainloop_get_api);
LOAD_FUNC(pa_context_set_state_callback);
LOAD_FUNC(pa_stream_write);
LOAD_FUNC(pa_xfree);
LOAD_FUNC(pa_stream_connect_record);
LOAD_FUNC(pa_stream_connect_playback);
LOAD_FUNC(pa_path_get_filename);
LOAD_FUNC(pa_get_binary_name);
LOAD_FUNC(pa_threaded_mainloop_free);
LOAD_FUNC(pa_context_errno);
LOAD_FUNC(pa_xmalloc0);
LOAD_FUNC(pa_stream_unref);
LOAD_FUNC(pa_threaded_mainloop_accept);
LOAD_FUNC(pa_stream_set_write_callback);
LOAD_FUNC(pa_threaded_mainloop_new);
LOAD_FUNC(pa_context_connect);
LOAD_FUNC(pa_stream_get_buffer_attr);
LOAD_FUNC(pa_stream_set_buffer_attr_callback);
LOAD_FUNC(pa_stream_set_read_callback);
LOAD_FUNC(pa_stream_set_state_callback);
LOAD_FUNC(pa_stream_new);
LOAD_FUNC(pa_stream_disconnect);
LOAD_FUNC(pa_threaded_mainloop_lock);
LOAD_FUNC(pa_channel_map_init_auto);
LOAD_FUNC(pa_channel_map_parse);
#undef LOAD_FUNC
}
++load_count;
} //}}}
void pulse_unload(void) //{{{
{
if(load_count == 0 || --load_count > 0)
return;
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined (HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
pa_handle = NULL;
} //}}}
// PulseAudio Event Callbacks //{{{
static void context_state_callback(pa_context *context, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
(void)context;
if(ppa_threaded_mainloop_in_thread(data->loop))
ppa_threaded_mainloop_signal(data->loop, 1);
}//}}}
static void stream_state_callback(pa_stream *stream, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
(void)stream;
if(ppa_threaded_mainloop_in_thread(data->loop))
ppa_threaded_mainloop_signal(data->loop, 1);
}//}}}
static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
SuspendContext(NULL);
data->attr = *(ppa_stream_get_buffer_attr(stream));
if((data->attr.tlength%data->attr.minreq) != 0)
AL_PRINT("new tlength (%d) is not a multiple of minreq (%d)!\n",
data->attr.tlength, data->attr.minreq);
Device->UpdateSize = data->attr.minreq;
Device->NumUpdates = data->attr.tlength/data->attr.minreq;
ProcessContext(NULL);
}//}}}
static void context_state_callback2(pa_context *context, void *pdata) //{{{
{
ALCdevice *Device = pdata;
if(ppa_context_get_state(context) == PA_CONTEXT_FAILED)
{
AL_PRINT("Received context failure!\n");
aluHandleDisconnect(Device);
}
}//}}}
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{
{
ALCdevice *Device = pdata;
if(ppa_stream_get_state(stream) == PA_STREAM_FAILED)
{
AL_PRINT("Received stream failure!\n");
aluHandleDisconnect(Device);
}
}//}}}
//}}}
// PulseAudio I/O Callbacks //{{{
static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
len -= len%data->attr.minreq;
if(len > 0)
{
void *buf = ppa_xmalloc0(len);
aluMixData(Device, buf, len/data->frame_size);
ppa_stream_write(stream, buf, len, ppa_xfree, 0, PA_SEEK_RELATIVE);
}
} //}}}
static void stream_read_callback(pa_stream *stream, size_t length, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
const void *buf;
if(ppa_stream_peek(stream, &buf, &length) < 0)
{
AL_PRINT("pa_stream_peek() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
return;
}
assert(buf);
assert(length);
length /= data->frame_size;
if(data->samples < length)
AL_PRINT("stream_read_callback: buffer overflow!\n");
WriteRingBuffer(data->ring, buf, (length<data->samples) ? length : data->samples);
ppa_stream_drop(stream);
} //}}}
//}}}
static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{
{
pulse_data *data = ppa_xmalloc0(sizeof(pulse_data));
pa_context_state_t state;
if(ppa_get_binary_name(data->path_name, sizeof(data->path_name)))
data->context_name = ppa_path_get_filename(data->path_name);
else
data->context_name = "OpenAL Soft";
if(!(data->loop = ppa_threaded_mainloop_new()))
{
AL_PRINT("pa_threaded_mainloop_new() failed!\n");
goto out;
}
if(ppa_threaded_mainloop_start(data->loop) < 0)
{
AL_PRINT("pa_threaded_mainloop_start() failed\n");
goto out;
}
ppa_threaded_mainloop_lock(data->loop);
device->ExtraData = data;
data->context = ppa_context_new(ppa_threaded_mainloop_get_api(data->loop), data->context_name);
if(!data->context)
{
AL_PRINT("pa_context_new() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_threaded_mainloop_unlock(data->loop);
goto out;
}
ppa_context_set_state_callback(data->context, context_state_callback, device);
if(ppa_context_connect(data->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0)
{
AL_PRINT("Context did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_context_unref(data->context);
data->context = NULL;
ppa_threaded_mainloop_unlock(data->loop);
goto out;
}
while((state=ppa_context_get_state(data->context)) != PA_CONTEXT_READY)
{
if(!PA_CONTEXT_IS_GOOD(state))
{
AL_PRINT("Context did not get ready: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_context_unref(data->context);
data->context = NULL;
ppa_threaded_mainloop_unlock(data->loop);
goto out;
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_context_set_state_callback(data->context, context_state_callback2, device);
device->szDeviceName = strdup(device_name);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
out:
if(data->loop)
{
ppa_threaded_mainloop_stop(data->loop);
ppa_threaded_mainloop_free(data->loop);
}
device->ExtraData = NULL;
ppa_xfree(data);
return ALC_FALSE;
} //}}}
static void pulse_close(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
if(data->stream)
{
ppa_stream_disconnect(data->stream);
ppa_stream_unref(data->stream);
}
ppa_context_disconnect(data->context);
ppa_context_unref(data->context);
ppa_threaded_mainloop_unlock(data->loop);
ppa_threaded_mainloop_stop(data->loop);
ppa_threaded_mainloop_free(data->loop);
DestroyRingBuffer(data->ring);
device->ExtraData = NULL;
ppa_xfree(data);
} //}}}
//}}}
// OpenAL {{{
static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{
{
if(!device_name)
device_name = pulse_device;
else if(strcmp(device_name, pulse_device) != 0)
return ALC_FALSE;
pulse_load();
if(!pa_handle)
return ALC_FALSE;
if(pulse_open(device, device_name) != ALC_FALSE)
return ALC_TRUE;
pulse_unload();
return ALC_FALSE;
} //}}}
static void pulse_close_playback(ALCdevice *device) //{{{
{
pulse_close(device);
pulse_unload();
} //}}}
static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
pa_stream_state_t state;
pa_channel_map chanmap;
ppa_threaded_mainloop_lock(data->loop);
data->frame_size = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
data->attr.minreq = data->frame_size * device->UpdateSize;
data->attr.prebuf = -1;
data->attr.maxlength = -1;
data->attr.fragsize = -1;
data->attr.tlength = data->attr.minreq * device->NumUpdates;
data->stream_name = "Playback Stream";
switch(aluBytesFromFormat(device->Format))
{
case 1:
data->spec.format = PA_SAMPLE_U8;
break;
case 2:
data->spec.format = PA_SAMPLE_S16NE;
break;
case 4:
data->spec.format = PA_SAMPLE_FLOAT32NE;
break;
default:
AL_PRINT("Unknown format: 0x%x\n", device->Format);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
data->spec.rate = device->Frequency;
data->spec.channels = aluChannelsFromFormat(device->Format);
if(ppa_sample_spec_valid(&data->spec) == 0)
{
AL_PRINT("Invalid sample format\n");
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
#ifdef _WIN32
if(!ppa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX))
{
AL_PRINT("Couldn't build map for channel count (%d)!", data->spec.channels);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
#else
switch(data->spec.channels)
{
case 1:
ppa_channel_map_parse(&chanmap, "mono");
break;
case 2:
ppa_channel_map_parse(&chanmap, "front-left,front-right");
break;
case 4:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right");
break;
case 6:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe");
break;
case 7:
ppa_channel_map_parse(&chanmap, "front-left,front-right,front-center,lfe,rear-center,side-left,side-right");
break;
case 8:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right");
break;
default:
AL_PRINT("Got unhandled channel count (%d)!", data->spec.channels);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
#endif
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, &chanmap);
if(!data->stream)
{
AL_PRINT("pa_stream_new() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
ppa_stream_set_state_callback(data->stream, stream_state_callback, device);
ppa_stream_set_write_callback(data->stream, stream_write_callback, device);
if(ppa_stream_connect_playback(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0)
{
AL_PRINT("Stream did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
data->stream = NULL;
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
while((state=ppa_stream_get_state(data->stream)) != PA_STREAM_READY)
{
if(!PA_STREAM_IS_GOOD(state))
{
AL_PRINT("Stream did not get ready: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
data->stream = NULL;
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_stream_set_state_callback(data->stream, stream_state_callback2, device);
stream_buffer_attr_callback(data->stream, device);
ppa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
} //}}}
static void pulse_stop_playback(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
if(!data->stream)
return;
ppa_threaded_mainloop_lock(data->loop);
ppa_stream_disconnect(data->stream);
ppa_stream_unref(data->stream);
data->stream = NULL;
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_name) //{{{
{
pulse_data *data;
pa_stream_state_t state;
if(!device_name)
device_name = pulse_capture_device;
else if(strcmp(device_name, pulse_capture_device) != 0)
return ALC_FALSE;
pulse_load();
if(!pa_handle)
return ALC_FALSE;
if(pulse_open(device, device_name) == ALC_FALSE)
{
pulse_unload();
return ALC_FALSE;
}
data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
data->samples = device->UpdateSize * device->NumUpdates;
data->frame_size = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
if(!(data->ring = CreateRingBuffer(data->frame_size, data->samples)))
{
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
data->attr.minreq = -1;
data->attr.prebuf = -1;
data->attr.maxlength = -1;
data->attr.tlength = -1;
data->attr.fragsize = data->frame_size * data->samples / 2;
data->stream_name = "Capture Stream";
data->spec.rate = device->Frequency;
data->spec.channels = aluChannelsFromFormat(device->Format);
switch(aluBytesFromFormat(device->Format))
{
case 1:
data->spec.format = PA_SAMPLE_U8;
break;
case 2:
data->spec.format = PA_SAMPLE_S16NE;
break;
case 4:
data->spec.format = PA_SAMPLE_FLOAT32NE;
break;
default:
AL_PRINT("Unknown format: 0x%x\n", device->Format);
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
if(ppa_sample_spec_valid(&data->spec) == 0)
{
AL_PRINT("Invalid sample format\n");
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, NULL);
if(!data->stream)
{
AL_PRINT("pa_stream_new() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
ppa_stream_set_state_callback(data->stream, stream_state_callback, device);
if(ppa_stream_connect_record(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY) < 0)
{
AL_PRINT("Stream did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
ppa_threaded_mainloop_unlock(data->loop);
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
while((state=ppa_stream_get_state(data->stream)) != PA_STREAM_READY)
{
if(!PA_STREAM_IS_GOOD(state))
{
AL_PRINT("Stream did not get ready: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
ppa_threaded_mainloop_unlock(data->loop);
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_stream_set_state_callback(data->stream, stream_state_callback2, device);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
} //}}}
static void pulse_close_capture(ALCdevice *device) //{{{
{
pulse_close(device);
pulse_unload();
} //}}}
static void pulse_start_capture(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
ppa_stream_set_read_callback(data->stream, stream_read_callback, device);
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
static void pulse_stop_capture(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
ppa_threaded_mainloop_lock(data->loop);
ppa_stream_set_read_callback(data->stream, NULL, NULL);
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{
{
pulse_data *data = device->ExtraData;
ALCuint available = RingBufferSize(data->ring);
if(available < samples)
alcSetError(ALC_INVALID_VALUE);
else
ReadRingBuffer(data->ring, buffer, samples);
} //}}}
static ALCuint pulse_available_samples(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
return RingBufferSize(data->ring);
} //}}}
BackendFuncs pulse_funcs = { //{{{
pulse_open_playback,
pulse_close_playback,
pulse_reset_playback,
pulse_stop_playback,
pulse_open_capture,
pulse_close_capture,
pulse_start_capture,
pulse_stop_capture,
pulse_capture_samples,
pulse_available_samples
}; //}}}
void alc_pulse_init(BackendFuncs *func_list) //{{{
{
*func_list = pulse_funcs;
} //}}}
void alc_pulse_deinit(void) //{{{
{
} //}}}
void alc_pulse_probe(int type) //{{{
{
pulse_load();
if(!pa_handle) return;
if(type == DEVICE_PROBE)
AppendDeviceList(pulse_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(pulse_device);
else if(type == CAPTURE_DEVICE_PROBE)
AppendCaptureDeviceList(pulse_capture_device);
pulse_unload();
} //}}}
//}}}
+92 -58
View File
@@ -37,7 +37,7 @@
#include <sys/audioio.h>
static char *solaris_device;
static const ALCchar solaris_device[] = "Solaris Software";
typedef struct {
int fd;
@@ -54,34 +54,37 @@ static ALuint SolarisProc(ALvoid *ptr)
ALCdevice *pDevice = (ALCdevice*)ptr;
solaris_data *data = (solaris_data*)pDevice->ExtraData;
int remaining = 0;
ALint frameSize;
int wrote;
while(!data->killNow)
frameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
while(!data->killNow && pDevice->Connected)
{
int len = data->data_size - remaining;
ALint len = data->data_size;
ALubyte *WritePtr = data->mix_data;
if(len > 0)
aluMixData(pDevice, WritePtr, len/frameSize);
while(len > 0 && !data->killNow)
{
SuspendContext(NULL);
aluMixData(pDevice->Context, data->mix_data+remaining, len, pDevice->Format);
ProcessContext(NULL);
}
wrote = write(data->fd, WritePtr, len);
if(wrote < 0)
{
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
{
AL_PRINT("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
len = 0;
}
else
Sleep(1);
continue;
}
remaining += len;
wrote = write(data->fd, data->mix_data, remaining);
if(wrote < 0)
{
AL_PRINT("write failed: %s\n", strerror(errno));
remaining = 0;
len -= wrote;
WritePtr += wrote;
}
else if(wrote > 0)
{
remaining -= wrote;
if(remaining > 0)
memmove(data->mix_data, data->mix_data+wrote, remaining);
}
else
Sleep(1);
}
return 0;
@@ -90,22 +93,15 @@ static ALuint SolarisProc(ALvoid *ptr)
static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
audio_info_t info;
ALuint frameSize;
char driver[64];
int numChannels;
solaris_data *data;
strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
{
if(strcmp(deviceName, solaris_device))
return ALC_FALSE;
device->szDeviceName = solaris_device;
}
else
device->szDeviceName = solaris_device;
if(!deviceName)
deviceName = solaris_device;
else if(strcmp(deviceName, solaris_device) != 0)
return ALC_FALSE;
data = (solaris_data*)calloc(1, sizeof(solaris_data));
data->killNow = 0;
@@ -118,10 +114,28 @@ static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *device
return ALC_FALSE;
}
numChannels = aluChannelsFromFormat(device->Format);
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_TRUE;
}
static void solaris_close_playback(ALCdevice *device)
{
solaris_data *data = (solaris_data*)device->ExtraData;
close(data->fd);
free(data);
device->ExtraData = NULL;
}
static ALCboolean solaris_reset_playback(ALCdevice *device)
{
solaris_data *data = (solaris_data*)device->ExtraData;
audio_info_t info;
ALuint frameSize;
int numChannels;
AUDIO_INITINFO(&info);
info.play.sample_rate = device->Frequency;
info.play.channels = numChannels;
switch(aluBytesFromFormat(device->Format))
{
@@ -129,32 +143,42 @@ static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *device
info.play.precision = 8;
info.play.encoding = AUDIO_ENCODING_LINEAR8;
break;
case 4:
switch(numChannels)
{
case 1: device->Format = AL_FORMAT_MONO16; break;
case 2: device->Format = AL_FORMAT_STEREO16; break;
case 4: device->Format = AL_FORMAT_QUAD16; break;
case 6: device->Format = AL_FORMAT_51CHN16; break;
case 7: device->Format = AL_FORMAT_61CHN16; break;
case 8: device->Format = AL_FORMAT_71CHN16; break;
}
/* fall-through */
case 2:
info.play.precision = 16;
info.play.encoding = AUDIO_ENCODING_LINEAR;
break;
default:
AL_PRINT("Unknown format?! %x\n", device->Format);
AL_PRINT("Unknown format: 0x%x\n", device->Format);
return ALC_FALSE;
}
numChannels = aluChannelsFromFormat(device->Format);
info.play.sample_rate = device->Frequency;
info.play.channels = numChannels;
frameSize = numChannels * aluBytesFromFormat(device->Format);
info.play.buffer_size = device->UpdateSize * frameSize;
info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0)
{
AL_PRINT("ioctl failed: %s\n", strerror(errno));
close(data->fd);
free(data);
return ALC_FALSE;
}
device->Frequency = info.play.sample_rate;
if(aluChannelsFromFormat(device->Format) != info.play.channels)
{
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), info.play.channels);
close(data->fd);
free(data);
return ALC_FALSE;
}
@@ -162,40 +186,39 @@ static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *device
(info.play.precision == 16 && aluBytesFromFormat(device->Format) == 2)))
{
AL_PRINT("Could not set %d-bit output, got %d\n", aluBytesFromFormat(device->Format)*8, info.play.precision);
close(data->fd);
free(data);
return ALC_FALSE;
}
device->UpdateSize = info.play.buffer_size / 4;
device->Frequency = info.play.sample_rate;
device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
device->ExtraData = data;
data->thread = StartThread(SolarisProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
free(data->mix_data);
free(data);
data->mix_data = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
static void solaris_close_playback(ALCdevice *device)
static void solaris_stop_playback(ALCdevice *device)
{
solaris_data *data = (solaris_data*)device->ExtraData;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
close(data->fd);
data->thread = NULL;
free(data->mix_data);
free(data);
device->ExtraData = NULL;
data->mix_data = NULL;
}
@@ -241,6 +264,8 @@ static ALCuint solaris_available_samples(ALCdevice *pDevice)
BackendFuncs solaris_funcs = {
solaris_open_playback,
solaris_close_playback,
solaris_reset_playback,
solaris_stop_playback,
solaris_open_capture,
solaris_close_capture,
solaris_start_capture,
@@ -252,7 +277,16 @@ BackendFuncs solaris_funcs = {
void alc_solaris_init(BackendFuncs *func_list)
{
*func_list = solaris_funcs;
solaris_device = AppendDeviceList("Solaris Software");
AppendAllDeviceList(solaris_device);
}
void alc_solaris_deinit(void)
{
}
void alc_solaris_probe(ALCboolean capture)
{
if(type == DEVICE_PROBE)
AppendDeviceList(solaris_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(solaris_device);
}
+66 -54
View File
@@ -40,7 +40,7 @@ typedef struct {
} wave_data;
static ALCchar *waveDevice;
static const ALCchar waveDevice[] = "Wave File Writer";
static ALuint WaveProc(ALvoid *ptr)
@@ -49,7 +49,6 @@ static ALuint WaveProc(ALvoid *ptr)
wave_data *data = (wave_data*)pDevice->ExtraData;
ALuint frameSize;
ALuint now, last;
size_t WriteCnt;
size_t fs;
ALuint avail;
union {
@@ -62,43 +61,40 @@ static ALuint WaveProc(ALvoid *ptr)
aluChannelsFromFormat(pDevice->Format);
last = timeGetTime();
while(!data->killNow)
while(!data->killNow && pDevice->Connected)
{
now = timeGetTime();
avail = (now-last) * pDevice->Frequency / 1000;
if(avail < pDevice->UpdateSize/4)
if(avail < pDevice->UpdateSize)
{
Sleep(1);
continue;
}
while(avail > 0)
while(avail >= pDevice->UpdateSize)
{
SuspendContext(NULL);
WriteCnt = min(data->size, avail);
aluMixData(pDevice->Context, data->buffer, WriteCnt * frameSize,
pDevice->Format);
ProcessContext(NULL);
aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
if(uSB.b[0] != 1 && aluBytesFromFormat(pDevice->Format) > 1)
{
ALubyte *bytes = data->buffer;
ALuint i;
for(i = 0;i < WriteCnt*frameSize;i++)
for(i = 0;i < data->size;i++)
fputc(bytes[i^1], data->f);
}
else
fs = fwrite(data->buffer, frameSize, WriteCnt, data->f);
fs = fwrite(data->buffer, frameSize, pDevice->UpdateSize,
data->f);
if(ferror(data->f))
{
AL_PRINT("Error writing to file\n");
data->killNow = 1;
aluHandleDisconnect(pDevice);
break;
}
avail -= WriteCnt;
avail -= pDevice->UpdateSize;
}
last = now;
}
@@ -109,23 +105,16 @@ static ALuint WaveProc(ALvoid *ptr)
static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
wave_data *data;
ALuint channels;
ALuint bits;
const char *fname;
int i;
fname = GetConfigValue("wave", "file", "");
if(!fname[0])
return ALC_FALSE;
if(deviceName)
{
if(strcmp(deviceName, waveDevice) != 0)
return ALC_FALSE;
device->szDeviceName = waveDevice;
}
else
device->szDeviceName = waveDevice;
if(!deviceName)
deviceName = waveDevice;
else if(strcmp(deviceName, waveDevice) != 0)
return ALC_FALSE;
data = (wave_data*)calloc(1, sizeof(wave_data));
@@ -137,25 +126,44 @@ static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_TRUE;
}
static void wave_close_playback(ALCdevice *device)
{
wave_data *data = (wave_data*)device->ExtraData;
fclose(data->f);
free(data);
device->ExtraData = NULL;
}
static ALCboolean wave_reset_playback(ALCdevice *device)
{
wave_data *data = (wave_data*)device->ExtraData;
ALuint channels, bits, i;
fseek(data->f, 0, SEEK_SET);
clearerr(data->f);
bits = aluBytesFromFormat(device->Format) * 8;
channels = aluChannelsFromFormat(device->Format);
switch(bits)
{
case 8:
case 16:
case 32:
if(channels == 0)
{
AL_PRINT("Unknown format?! %x\n", device->Format);
fclose(data->f);
free(data);
return ALC_FALSE;
}
break;
default:
AL_PRINT("Unknown format?! %x\n", device->Format);
fclose(data->f);
free(data);
return ALC_FALSE;
}
@@ -206,47 +214,45 @@ static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceNam
if(ferror(data->f))
{
AL_PRINT("Error writing header: %s\n", strerror(errno));
fclose(data->f);
free(data);
return ALC_FALSE;
}
data->DataStart = ftell(data->f);
device->UpdateSize = max(device->UpdateSize, 2048);
data->size = device->UpdateSize;
data->buffer = malloc(data->size * channels * bits / 8);
data->size = device->UpdateSize * channels * bits / 8;
data->buffer = malloc(data->size);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
fclose(data->f);
free(data);
return ALC_FALSE;
}
device->ExtraData = data;
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
fclose(data->f);
free(data->buffer);
free(data);
data->buffer = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
static void wave_close_playback(ALCdevice *device)
static void wave_stop_playback(ALCdevice *device)
{
wave_data *data = (wave_data*)device->ExtraData;
ALuint dataLen;
long size;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
free(data->buffer);
data->buffer = NULL;
size = ftell(data->f);
if(size > 0)
@@ -268,21 +274,13 @@ static void wave_close_playback(ALCdevice *device)
fputc((size>>24)&0xff, data->f);
}
}
fclose(data->f);
free(data->buffer);
free(data);
device->ExtraData = NULL;
}
static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
{
(void)pDevice;
(void)deviceName;
(void)frequency;
(void)format;
(void)SampleSize;
return ALC_FALSE;
}
@@ -318,6 +316,8 @@ static ALCuint wave_available_samples(ALCdevice *pDevice)
BackendFuncs wave_funcs = {
wave_open_playback,
wave_close_playback,
wave_reset_playback,
wave_stop_playback,
wave_open_capture,
wave_close_capture,
wave_start_capture,
@@ -329,7 +329,19 @@ BackendFuncs wave_funcs = {
void alc_wave_init(BackendFuncs *func_list)
{
*func_list = wave_funcs;
waveDevice = AppendDeviceList("Wave File Writer");
AppendAllDeviceList(waveDevice);
}
void alc_wave_deinit(void)
{
}
void alc_wave_probe(int type)
{
if(*(GetConfigValue("wave", "file", "")) == 0)
return;
if(type == DEVICE_PROBE)
AppendDeviceList(waveDevice);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(waveDevice);
}
+46 -18
View File
@@ -50,7 +50,8 @@ typedef struct {
} WinMMData;
static ALCchar *CaptureDeviceList[16];
static ALCchar **CaptureDeviceList;
static ALuint NumCaptureDevices;
/*
WaveInProc
@@ -175,20 +176,18 @@ static void WinMMClosePlayback(ALCdevice *device)
}
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
{
WAVEFORMATEX wfexCaptureFormat;
WinMMData *pData = NULL;
ALint lDeviceID = 0;
ALint lBufferSize;
ALint i;
(void)format;
ALuint i;
// Find the Device ID matching the deviceName if valid
if (deviceName)
{
for(i = 0;CaptureDeviceList[i];i++)
for(i = 0;i < NumCaptureDevices;i++)
{
if (!strcmp(deviceName, CaptureDeviceList[i]))
{
@@ -196,15 +195,14 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
break;
}
}
if(!CaptureDeviceList[i])
if(i == NumCaptureDevices)
return ALC_FALSE;
}
pDevice->szDeviceName = CaptureDeviceList[lDeviceID];
pData = calloc(1, sizeof(*pData));
if(!pData)
{
SetALCError(ALC_OUT_OF_MEMORY);
alcSetError(ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
@@ -214,7 +212,7 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
wfexCaptureFormat.wBitsPerSample = aluBytesFromFormat(pDevice->Format) * 8;
wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
wfexCaptureFormat.nChannels / 8;
wfexCaptureFormat.nSamplesPerSec = frequency;
wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
wfexCaptureFormat.nBlockAlign;
wfexCaptureFormat.cbSize = 0;
@@ -231,7 +229,8 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
goto failure;
// Allocate circular memory buffer for the captured audio
pData->ulCapturedDataSize = SampleSize * wfexCaptureFormat.nBlockAlign;
pData->ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates *
wfexCaptureFormat.nBlockAlign;
// Make sure circular buffer is at least 100ms in size (and an exact multiple of
// the block alignment
@@ -269,6 +268,7 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
if (pData->hWaveInThread == NULL)
goto failure;
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
return ALC_TRUE;
failure:
@@ -292,6 +292,7 @@ failure:
CloseHandle(pData->hWaveInThreadEvent);
free(pData);
pDevice->ExtraData = NULL;
return ALC_FALSE;
}
@@ -372,7 +373,7 @@ static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lS
frameSize;
if(ulSamples > ulCapturedSamples)
{
SetALCError(ALC_INVALID_VALUE);
alcSetError(ALC_INVALID_VALUE);
return;
}
@@ -413,6 +414,8 @@ static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
BackendFuncs WinMMFuncs = {
WinMMOpenPlayback,
WinMMClosePlayback,
NULL,
NULL,
WinMMOpenCapture,
WinMMCloseCapture,
WinMMStartCapture,
@@ -423,20 +426,45 @@ BackendFuncs WinMMFuncs = {
void alcWinMMInit(BackendFuncs *FuncList)
{
ALint lNumDevs;
ALint lLoop;
*FuncList = WinMMFuncs;
}
lNumDevs = waveInGetNumDevs();
for (lLoop = 0; lLoop < lNumDevs; lLoop++)
void alcWinMMDeinit()
{
ALuint lLoop;
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
free(CaptureDeviceList[lLoop]);
free(CaptureDeviceList);
CaptureDeviceList = NULL;
NumCaptureDevices = 0;
}
void alcWinMMProbe(int type)
{
ALuint lLoop;
if(type != CAPTURE_DEVICE_PROBE)
return;
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
free(CaptureDeviceList[lLoop]);
NumCaptureDevices = waveInGetNumDevs();
CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
{
WAVEINCAPS WaveInCaps;
if(waveInGetDevCaps(lLoop, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
{
char name[128];
snprintf(name, sizeof(name), "WaveIn on %s", WaveInCaps.szPname);
CaptureDeviceList[lLoop] = AppendCaptureDeviceList(name);
AppendCaptureDeviceList(name);
CaptureDeviceList[lLoop] = strdup(name);
}
else
CaptureDeviceList[lLoop] = strdup("");
}
}
+82 -6
View File
@@ -10,6 +10,7 @@ INCLUDE(CheckFunctionExists)
INCLUDE(CheckLibraryExists)
INCLUDE(CheckIncludeFile)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckCCompilerFlag)
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckTypeSize)
@@ -26,7 +27,8 @@ OPTION(OSS "Check for OSS backend" ON)
OPTION(SOLARIS "Check for Solaris backend" ON)
OPTION(DSOUND "Check for DirectSound backend" ON)
OPTION(WINMM "Check for Windows Multimedia backend" ON)
OPTION(PORTAUDIO "Check for PortAudio backend" ON)
OPTION(PORTAUDIO "Check for PortAudio backend" ON)
OPTION(PULSEAUDIO "Check for PulseAudio backend" ON)
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
@@ -34,6 +36,8 @@ OPTION(WERROR "Treat compile warnings as errors" OFF)
OPTION(EXAMPLES "Build example programs" ON)
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
IF(WIN32)
SET(LIBNAME OpenAL32)
@@ -43,11 +47,11 @@ ELSE()
ENDIF()
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "7")
SET(LIB_BUILD_VERSION "411")
SET(LIB_MINOR_VERSION "10")
SET(LIB_BUILD_VERSION "622")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
IF(NOT DEFINED LIB_INSTALL_DIR)
SET(LIB_INSTALL_DIR "lib")
SET(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
ENDIF(NOT DEFINED LIB_INSTALL_DIR)
@@ -71,12 +75,25 @@ IF(NOT CMAKE_DEBUG_POSTFIX)
FORCE)
ENDIF()
IF(NOT DXSDK_DIR)
STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}")
ELSE()
STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "${DXSDK_DIR}")
ENDIF()
IF(DXSDK_DIR)
MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}")
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${DXSDK_DIR}/Include")
INCLUDE_DIRECTORIES("${DXSDK_DIR}/Include")
LINK_DIRECTORIES("${DXSDK_DIR}/Lib")
ENDIF()
IF(MSVC)
# ???
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEBUG")
SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ELSE()
ADD_DEFINITIONS(-Wall)
CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
@@ -163,6 +180,27 @@ IF(NOT HAVE_SNPRINTF)
ADD_DEFINITIONS(-Dsnprintf=_snprintf)
ENDIF()
CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF)
IF(NOT HAVE_VSNPRINTF)
CHECK_FUNCTION_EXISTS(_vsnprintf HAVE__VSNPRINTF)
IF(NOT HAVE__VSNPRINTF)
MESSAGE(FATAL_ERROR "No vsnprintf function found, please report!")
ENDIF()
ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf)
ENDIF()
CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN)
IF(NOT HAVE_ISNAN)
CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN)
IF(NOT HAVE__ISNAN)
MESSAGE(FATAL_ERROR "No isnan function found, please report!")
ENDIF()
ADD_DEFINITIONS(-Disnan=_isnan)
ENDIF()
# Check for the dlopen API (for dynamicly loading backend libs)
IF(DLOPEN)
CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
@@ -187,22 +225,32 @@ IF(NOT HAVE_WINDOWS_H)
MESSAGE(FATAL_ERROR "No sleep function found!")
ENDIF()
CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD)
IF(HAVE_PTHREAD)
ADD_DEFINITIONS(-pthread)
SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread)
ENDIF()
# We need pthreads outside of Windows
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
IF(NOT HAVE_PTHREAD_H)
MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
ENDIF()
# Some systems need pthread_np.h to get recursive mutexes
CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H)
# _GNU_SOURCE is needed on some systems for extra attributes, and
# _REENTRANT is needed for libc thread-safety
ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_REENTRANT)
ADD_DEFINITIONS(-D_GNU_SOURCE=1)
CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD)
IF(HAVE_LIBPTHREAD)
SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
ENDIF()
CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT)
IF(HAVE_LIBRT)
SET(EXTRA_LIBS rt ${EXTRA_LIBS})
ENDIF()
ENDIF()
# Check for a 64-bit type
@@ -226,6 +274,7 @@ ENDIF()
SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
OpenAL32/alBuffer.c
OpenAL32/alDatabuffer.c
OpenAL32/alEffect.c
OpenAL32/alError.c
OpenAL32/alExtension.c
@@ -238,6 +287,7 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
SET(ALC_OBJS Alc/ALc.c
Alc/ALu.c
Alc/alcConfig.c
Alc/alcEcho.c
Alc/alcReverb.c
Alc/alcRing.c
Alc/alcThread.c
@@ -340,6 +390,24 @@ IF(PORTAUDIO)
ENDIF()
ENDIF()
# Check PortAudio backend
IF(PULSEAUDIO)
CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H)
IF(HAVE_PULSE_PULSEAUDIO_H)
CHECK_LIBRARY_EXISTS(pulse pa_context_new "" HAVE_LIBPULSE)
IF(HAVE_LIBPULSE)
SET(HAVE_PULSEAUDIO 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/pulseaudio.c)
IF(HAVE_DLFCN_H)
SET(BACKENDS "${BACKENDS} PulseAudio,")
ELSE()
SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),")
SET(EXTRA_LIBS pulse ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# This is always available
SET(BACKENDS "${BACKENDS} WaveFile")
@@ -389,6 +457,14 @@ INSTALL(FILES include/AL/al.h
INSTALL(FILES "${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
# Install alsoft.conf configuration file
IF(ALSOFT_CONFIG)
INSTALL(FILES alsoftrc.sample
DESTINATION /etc/openal
RENAME alsoft.conf
)
ENDIF()
IF(EXAMPLES)
ADD_EXECUTABLE(openal-info examples/openal-info.c)
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
+24 -2
View File
@@ -4,7 +4,6 @@
#include "AL/al.h"
#include "alEffect.h"
#include "alFilter.h"
#include "alReverb.h"
#ifdef __cplusplus
extern "C" {
@@ -16,6 +15,8 @@ extern "C" {
#define AL_EFFECTSLOT_NULL 0x0000
typedef struct ALeffectState ALeffectState;
typedef struct ALeffectslot
{
ALeffect effect;
@@ -23,7 +24,9 @@ typedef struct ALeffectslot
ALfloat Gain;
ALboolean AuxSendAuto;
ALverbState *ReverbState;
ALeffectState *EffectState;
ALfloat WetBuffer[BUFFERSIZE];
ALuint refcount;
@@ -49,6 +52,25 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
struct ALeffectState {
ALvoid (*Destroy)(ALeffectState *State);
ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device);
ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect);
ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
};
ALeffectState *NoneCreate(void);
ALeffectState *EAXVerbCreate(void);
ALeffectState *VerbCreate(void);
ALeffectState *EchoCreate(void);
#define ALEffect_Destroy(a) ((a)->Destroy((a)))
#define ALEffect_DeviceUpdate(a,b) ((a)->DeviceUpdate((a),(b)))
#define ALEffect_Update(a,b,c) ((a)->Update((a),(b),(c)))
#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e)))
#ifdef __cplusplus
}
#endif
+12 -10
View File
@@ -7,26 +7,28 @@
extern "C" {
#endif
#define UNUSED 0
#define PENDING 1
#define PROCESSED 2
#define BUFFER_PADDING 2
typedef struct ALbuffer_struct
typedef struct ALbuffer
{
ALenum format;
ALenum eOriginalFormat;
ALshort *data;
ALsizei size;
ALenum format;
ALenum eOriginalFormat;
ALsizei frequency;
ALsizei padding;
ALenum state;
ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0)
struct ALbuffer_struct *next;
// Index to itself
ALuint buffer;
struct ALbuffer *next;
} ALbuffer;
ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
ALvoid ReleaseALBuffers(ALvoid);
ALvoid ReleaseALBuffers(ALCdevice *device);
#ifdef __cplusplus
}
+55
View File
@@ -0,0 +1,55 @@
#ifndef _AL_DATABUFFER_H_
#define _AL_DATABUFFER_H_
#include "AL/al.h"
#ifdef __cplusplus
extern "C" {
#endif
#define UNMAPPED 0
#define MAPPED 1
typedef struct ALdatabuffer
{
ALubyte *data;
ALuint size;
ALenum state;
ALenum usage;
/* Index to self */
ALuint databuffer;
struct ALdatabuffer *next;
} ALdatabuffer;
ALvoid ALAPIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers);
ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers);
ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer);
ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage);
ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint buffer, ALuint start, ALsizei length, const ALvoid *data);
ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint buffer, ALuint start, ALsizei length, ALvoid *data);
ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue);
ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues);
ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue);
ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues);
ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue);
ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues);
ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue);
ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues);
ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer);
ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access);
ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer);
ALvoid ReleaseALDatabuffers(ALCdevice *device);
#ifdef __cplusplus
}
#endif
#endif
+184 -6
View File
@@ -1,3 +1,5 @@
// NOTE: The effect structure is getting too large, it may be a good idea to
// start using a union or another form of unified storage.
#ifndef _AL_EFFECT_H_
#define _AL_EFFECT_H_
@@ -22,6 +24,7 @@ extern "C" {
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
#define AL_EFFECT_EAXREVERB 0x8000
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
@@ -37,23 +40,176 @@ extern "C" {
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
#define AL_REVERB_MIN_DENSITY (0.0f)
#define AL_REVERB_MAX_DENSITY (1.0f)
#define AL_REVERB_DEFAULT_DENSITY (1.0f)
#define AL_REVERB_MIN_DIFFUSION (0.0f)
#define AL_REVERB_MAX_DIFFUSION (1.0f)
#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
#define AL_REVERB_MIN_GAIN (0.0f)
#define AL_REVERB_MAX_GAIN (1.0f)
#define AL_REVERB_DEFAULT_GAIN (0.32f)
#define AL_REVERB_MIN_GAINHF (0.0f)
#define AL_REVERB_MAX_GAINHF (1.0f)
#define AL_REVERB_DEFAULT_GAINHF (0.89f)
#define AL_REVERB_MIN_DECAY_TIME (0.1f)
#define AL_REVERB_MAX_DECAY_TIME (20.0f)
#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_REVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
#define AL_REVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
#define AL_REVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
#define AL_ECHO_DELAY 0x0001
#define AL_ECHO_LRDELAY 0x0002
#define AL_ECHO_DAMPING 0x0003
#define AL_ECHO_FEEDBACK 0x0004
#define AL_ECHO_SPREAD 0x0005
#define AL_ECHO_MIN_DELAY (0.0f)
#define AL_ECHO_MAX_DELAY (0.207f)
#define AL_ECHO_DEFAULT_DELAY (0.1f)
#define AL_ECHO_MIN_LRDELAY (0.0f)
#define AL_ECHO_MAX_LRDELAY (0.404f)
#define AL_ECHO_DEFAULT_LRDELAY (0.1f)
#define AL_ECHO_MIN_DAMPING (0.0f)
#define AL_ECHO_MAX_DAMPING (0.99f)
#define AL_ECHO_DEFAULT_DAMPING (0.5f)
#define AL_ECHO_MIN_FEEDBACK (0.0f)
#define AL_ECHO_MAX_FEEDBACK (1.0f)
#define AL_ECHO_DEFAULT_FEEDBACK (0.5f)
#define AL_ECHO_MIN_SPREAD (-1.0f)
#define AL_ECHO_MAX_SPREAD (1.0f)
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
#define AL_EAXREVERB_DENSITY 0x0001
#define AL_EAXREVERB_DIFFUSION 0x0002
#define AL_EAXREVERB_GAIN 0x0003
#define AL_EAXREVERB_GAINHF 0x0004
#define AL_EAXREVERB_GAINLF 0x0005
#define AL_EAXREVERB_DECAY_TIME 0x0006
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
#define AL_EAXREVERB_ECHO_TIME 0x000F
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
#define AL_EAXREVERB_MODULATION_TIME 0x0011
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
#define AL_EAXREVERB_HFREFERENCE 0x0014
#define AL_EAXREVERB_LFREFERENCE 0x0015
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
#define AL_EAXREVERB_MIN_DENSITY (0.0f)
#define AL_EAXREVERB_MAX_DENSITY (1.0f)
#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
#define AL_EAXREVERB_MIN_GAIN (0.0f)
#define AL_EAXREVERB_MAX_GAIN (1.0f)
#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
#define AL_EAXREVERB_MIN_GAINHF (0.0f)
#define AL_EAXREVERB_MAX_GAINHF (1.0f)
#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
#define AL_EAXREVERB_MIN_GAINLF (0.0f)
#define AL_EAXREVERB_MAX_GAINLF (1.0f)
#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_EAXREVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
#define AL_EAXREVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
enum {
REVERB = 0,
EAXREVERB = 0,
REVERB,
ECHO,
MAX_EFFECTS
};
extern ALboolean DisabledEffects[MAX_EFFECTS];
typedef struct ALeffect_struct
typedef struct ALeffect
{
// Effect type (AL_EFFECT_NULL, ...)
ALenum type;
struct {
// Shared Reverb Properties
ALfloat Density;
ALfloat Diffusion;
ALfloat Gain;
ALfloat GainHF;
ALfloat DecayTime;
@@ -65,12 +221,34 @@ typedef struct ALeffect_struct
ALfloat AirAbsorptionGainHF;
ALfloat RoomRolloffFactor;
ALboolean DecayHFLimit;
// Additional EAX Reverb Properties
ALfloat GainLF;
ALfloat DecayLFRatio;
ALfloat ReflectionsPan[3];
ALfloat LateReverbPan[3];
ALfloat EchoTime;
ALfloat EchoDepth;
ALfloat ModulationTime;
ALfloat ModulationDepth;
ALfloat HFReference;
ALfloat LFReference;
} Reverb;
struct {
ALfloat Delay;
ALfloat LRDelay;
ALfloat Damping;
ALfloat Feedback;
ALfloat Spread;
} Echo;
// Index to itself
ALuint effect;
struct ALeffect_struct *next;
struct ALeffect *next;
} ALeffect;
ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
@@ -87,7 +265,7 @@ ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALEffects(ALvoid);
ALvoid ReleaseALEffects(ALCdevice *device);
#ifdef __cplusplus
}
+41 -4
View File
@@ -9,10 +9,47 @@ extern "C" {
#endif
typedef struct {
ALfloat history[OUTPUTCHANNELS*2];
ALfloat coeff;
#ifndef _MSC_VER
ALfloat history[0];
#else
ALfloat history[1];
#endif
} FILTER;
static __inline ALfloat lpFilter4P(FILTER *iir, ALuint offset, ALfloat input)
{
ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
history[0] = output;
output = output + (history[1]-output)*a;
history[1] = output;
output = output + (history[2]-output)*a;
history[2] = output;
output = output + (history[3]-output)*a;
history[3] = output;
return output;
}
static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
{
ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
history[0] = output;
output = output + (history[1]-output)*a;
history[1] = output;
return output;
}
#define AL_FILTER_TYPE 0x8001
#define AL_FILTER_NULL 0x0000
@@ -24,7 +61,7 @@ typedef struct {
#define AL_LOWPASS_GAINHF 0x0002
typedef struct ALfilter_struct
typedef struct ALfilter
{
// Filter type (AL_FILTER_NULL, ...)
ALenum type;
@@ -35,7 +72,7 @@ typedef struct ALfilter_struct
// Index to itself
ALuint filter;
struct ALfilter_struct *next;
struct ALfilter *next;
} ALfilter;
ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
@@ -52,7 +89,7 @@ ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALFilters(ALvoid);
ALvoid ReleaseALFilters(ALCdevice *device);
#ifdef __cplusplus
}
+128 -33
View File
@@ -3,13 +3,16 @@
#include <string.h>
#include <stdio.h>
#include "alu.h"
#include <stdarg.h>
#ifdef HAVE_FENV_H
#include <fenv.h>
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#ifdef _WIN32
#ifndef _WIN32_WINNT
@@ -17,8 +20,15 @@
#endif
#include <windows.h>
typedef DWORD tls_type;
#define tls_create(x) (*(x) = TlsAlloc())
#define tls_delete(x) TlsFree((x))
#define tls_get(x) TlsGetValue((x))
#define tls_set(x, a) TlsSetValue((x), (a))
#else
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
@@ -30,6 +40,12 @@
#define IsBadWritePtr(a,b) (0)
typedef pthread_key_t tls_type;
#define tls_create(x) pthread_key_create((x), NULL)
#define tls_delete(x) pthread_key_delete((x))
#define tls_get(x) pthread_getspecific((x))
#define tls_set(x, a) pthread_setspecific((x), (a))
typedef pthread_mutex_t CRITICAL_SECTION;
static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
{
@@ -76,13 +92,22 @@ static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
* as opposed to the actual time. */
static inline ALuint timeGetTime(void)
{
struct timeval tv;
int ret;
#ifdef _POSIX_TIMERS
struct timespec ts;
ret = clock_gettime(CLOCK_REALTIME, &ts);
assert(ret == 0);
return ts.tv_nsec/1000000 + ts.tv_sec*1000;
#else
struct timeval tv;
ret = gettimeofday(&tv, NULL);
assert(ret == 0);
return tv.tv_usec/1000 + tv.tv_sec*1000;
#endif
}
static inline void Sleep(ALuint t)
@@ -98,28 +123,37 @@ static inline void Sleep(ALuint t)
#define max(x,y) (((x)>(y))?(x):(y))
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "alListener.h"
#include "alu.h"
#ifdef __cplusplus
extern "C" {
#endif
extern char _alDebug[256];
static __inline void al_print(const char *fname, unsigned int line, const char *fmt, ...)
{
const char *fn;
char str[256];
int i;
#define AL_PRINT(...) do { \
int _al_print_i; \
const char *_al_print_fn = strrchr(__FILE__, '/'); \
if(!_al_print_fn) _al_print_fn = __FILE__; \
else _al_print_fn += 1; \
_al_print_i = snprintf(_alDebug, sizeof(_alDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \
if(_al_print_i < (int)sizeof(_alDebug) && _al_print_i > 0) \
snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \
_alDebug[sizeof(_alDebug)-1] = 0; \
fprintf(stderr, "%s", _alDebug); \
} while(0)
fn = strrchr(fname, '/');
if(!fn) fn = strrchr(fname, '\\');;
if(!fn) fn = fname;
else fn += 1;
i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
if(i < (int)sizeof(str) && i > 0)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(str+i, sizeof(str)-i, fmt, ap);
va_end(ap);
}
str[sizeof(str)-1] = 0;
fprintf(stderr, "%s", str);
}
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
#define SWMIXER_OUTPUT_RATE 44100
@@ -136,8 +170,10 @@ extern char _alDebug[256];
typedef struct {
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
void (*ClosePlayback)(ALCdevice*);
ALCboolean (*ResetPlayback)(ALCdevice*);
void (*StopPlayback)(ALCdevice*);
ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*, ALCuint, ALCenum, ALCsizei);
ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*);
void (*CloseCapture)(ALCdevice*);
void (*StartCapture)(ALCdevice*);
void (*StopCapture)(ALCdevice*);
@@ -145,30 +181,85 @@ typedef struct {
ALCuint (*AvailableSamples)(ALCdevice*);
} BackendFuncs;
enum {
DEVICE_PROBE,
ALL_DEVICE_PROBE,
CAPTURE_DEVICE_PROBE
};
void alc_alsa_init(BackendFuncs *func_list);
void alc_alsa_deinit(void);
void alc_alsa_probe(int type);
void alc_oss_init(BackendFuncs *func_list);
void alc_oss_deinit(void);
void alc_oss_probe(int type);
void alc_solaris_init(BackendFuncs *func_list);
void alc_solaris_deinit(void);
void alc_solarise_probe(int type);
void alcDSoundInit(BackendFuncs *func_list);
void alcDSoundDeinit(void);
void alcDSoundProbe(int type);
void alcWinMMInit(BackendFuncs *FuncList);
void alcWinMMDeinit(void);
void alcWinMMProbe(int type);
void alc_pa_init(BackendFuncs *func_list);
void alc_pa_deinit(void);
void alc_pa_probe(int type);
void alc_wave_init(BackendFuncs *func_list);
void alc_wave_deinit(void);
void alc_wave_probe(int type);
void alc_pulse_init(BackendFuncs *func_list);
void alc_pulse_deinit(void);
void alc_pulse_probe(int type);
struct ALCdevice_struct
{
ALCboolean Connected;
ALboolean IsCaptureDevice;
ALuint Frequency;
ALuint UpdateSize;
ALuint NumUpdates;
ALenum Format;
ALCchar *szDeviceName;
// Maximum number of sources that can be created
ALuint MaxNoOfSources;
// Maximum number of slots that can be created
ALuint AuxiliaryEffectSlotMax;
// Context created on this device
ALCcontext *Context;
ALint lNumMonoSources;
ALint lNumStereoSources;
ALuint NumAuxSends;
// Linked List of Buffers for this device
struct ALbuffer *Buffers;
ALuint BufferCount;
// Linked List of Effects for this device
struct ALeffect *EffectList;
ALuint EffectCount;
// Linked List of Filters for this device
struct ALfilter *FilterList;
ALuint FilterCount;
// Linked List of Databuffers for this device
struct ALdatabuffer *Databuffers;
ALuint DatabufferCount;
// Stereo-to-binaural filter
struct bs2b *Bs2b;
ALCint Bs2bLevel;
// Dry path buffer mix
float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
// Contexts created on this device
ALCcontext **Contexts;
ALuint NumContexts;
BackendFuncs *Funcs;
void *ExtraData; // For the backend's use
@@ -178,7 +269,9 @@ struct ALCdevice_struct
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
#define ALCdevice_OpenCapture(a,b,c,d,e) ((a)->Funcs->OpenCapture((a), (b), (c), (d), (e)))
#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a)))
#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a)))
#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b)))
#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
#define ALCdevice_StartCapture(a) ((a)->Funcs->StartCapture((a)))
#define ALCdevice_StopCapture(a) ((a)->Funcs->StopCapture((a)))
@@ -195,20 +288,18 @@ struct ALCcontext_struct
struct ALeffectslot *AuxiliaryEffectSlot;
ALuint AuxiliaryEffectSlotCount;
struct ALdatabuffer *SampleSource;
struct ALdatabuffer *SampleSink;
ALenum LastError;
ALboolean InUse;
ALuint Frequency;
ALenum DistanceModel;
ALfloat DopplerFactor;
ALfloat DopplerVelocity;
ALfloat flSpeedOfSound;
ALint lNumMonoSources;
ALint lNumStereoSources;
ALfloat PanningLUT[OUTPUTCHANNELS * LUT_NUM];
ALint NumChan;
@@ -217,18 +308,16 @@ struct ALCcontext_struct
ALCdevice *Device;
const ALCchar *ExtensionList;
struct bs2b *bs2b;
ALCcontext *next;
};
ALCvoid ReleaseALC(ALCvoid);
ALCchar *AppendDeviceList(char *name);
ALCchar *AppendAllDeviceList(char *name);
ALCchar *AppendCaptureDeviceList(char *name);
void AppendDeviceList(const ALCchar *name);
void AppendAllDeviceList(const ALCchar *name);
void AppendCaptureDeviceList(const ALCchar *name);
ALCvoid SetALCError(ALenum errorCode);
ALCvoid alcSetError(ALenum errorCode);
ALCvoid SuspendContext(ALCcontext *context);
ALCvoid ProcessContext(ALCcontext *context);
@@ -236,6 +325,8 @@ ALCvoid ProcessContext(ALCcontext *context);
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
ALuint StopThread(ALvoid *thread);
ALCcontext *GetContextSuspended(void);
typedef struct RingBuffer RingBuffer;
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length);
void DestroyRingBuffer(RingBuffer *ring);
@@ -248,6 +339,10 @@ void FreeALConfig(void);
const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
int GetConfigValueInt(const char *blockName, const char *keyName, int def);
float GetConfigValueFloat(const char *blockName, const char *keyName, float def);
int GetConfigValueBool(const char *blockName, const char *keyName, float def);
ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context);
ALCcontext* ALCAPIENTRY alcGetThreadContext(void);
#ifdef __cplusplus
}
-26
View File
@@ -1,26 +0,0 @@
#ifndef _AL_REVERB_H_
#define _AL_REVERB_H_
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alAuxEffectSlot.h"
#include "alEffect.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ALverbState ALverbState;
ALverbState *VerbCreate(ALCcontext *Context);
ALvoid VerbDestroy(ALverbState *State);
ALvoid VerbUpdate(ALCcontext *Context, struct ALeffectslot *Slot, ALeffect *Effect);
ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
#ifdef __cplusplus
}
#endif
#endif
+24 -21
View File
@@ -3,8 +3,7 @@
#define AL_NUM_SOURCE_PARAMS 128
/* This cannot be changed without working on the code! */
#define MAX_SENDS 1
#define MAX_SENDS 2
#include "alFilter.h"
#include "alu.h"
@@ -25,9 +24,7 @@ extern "C" {
typedef struct ALbufferlistitem
{
ALuint buffer;
ALuint bufferstate;
ALuint flag;
struct ALbuffer *buffer;
struct ALbufferlistitem *next;
} ALbufferlistitem;
@@ -50,26 +47,21 @@ typedef struct ALsource
ALboolean bLooping;
ALenum DistanceModel;
ALuint ulBufferID;
ALboolean inuse;
ALboolean play;
ALenum state;
ALuint position;
ALuint position_fraction;
struct ALbuffer *Buffer;
struct ALbufferlistitem *queue; // Linked list of buffers in queue
ALuint BuffersInQueue; // Number of buffers in queue
ALuint TotalBufferDataSize; // Total amount of data contained in the buffers queued for this source
ALuint BuffersPlayed; // Number of buffers played on this loop
ALuint BuffersPlayed; // Number of buffers played on this loop
ALfilter DirectFilter;
struct {
struct ALeffectslot *Slot;
ALfilter WetFilter;
FILTER iirFilter;
} Send[MAX_SENDS];
ALboolean DryGainHFAuto;
@@ -77,17 +69,10 @@ typedef struct ALsource
ALboolean WetGainHFAuto;
ALfloat OuterGainHF;
FILTER iirFilter;
ALfloat AirAbsorptionFactor;
ALfloat RoomRolloffFactor;
ALfloat DopplerFactor;
// Index to itself
ALuint source;
ALint lOffset;
ALint lOffsetType;
@@ -96,9 +81,27 @@ typedef struct ALsource
// Current gains, which are ramped while mixed
ALfloat DryGains[OUTPUTCHANNELS];
ALfloat WetGain;
ALfloat WetGains[MAX_SENDS];
ALboolean FirstStart;
// Current target parameters used for mixing
struct {
ALfloat DryGains[OUTPUTCHANNELS];
ALfloat WetGains[MAX_SENDS];
ALfloat Pitch;
struct {
FILTER iirFilter;
ALfloat history[2];
} Send[MAX_SENDS];
FILTER iirFilter;
ALfloat history[OUTPUTCHANNELS*2];
} Params;
// Index to itself
ALuint source;
struct ALsource *next;
} ALsource;
+123 -3
View File
@@ -3,6 +3,48 @@
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846 /* pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#endif
#ifdef HAVE_SQRTF
#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
#else
#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
#endif
#ifdef HAVE_ACOSF
#define aluAcos(x) ((ALfloat)acosf((float)(x)))
#else
#define aluAcos(x) ((ALfloat)acos((double)(x)))
#endif
#ifdef HAVE_ATANF
#define aluAtan(x) ((ALfloat)atanf((float)(x)))
#else
#define aluAtan(x) ((ALfloat)atan((double)(x)))
#endif
#ifdef HAVE_FABSF
#define aluFabs(x) ((ALfloat)fabsf((float)(x)))
#else
#define aluFabs(x) ((ALfloat)fabs((double)(x)))
#endif
// fixes for mingw32.
#if defined(max) && !defined(__max)
#define __max max
#endif
#if defined(min) && !defined(__min)
#define __min min
#endif
#ifdef __cplusplus
extern "C" {
@@ -22,12 +64,90 @@ enum {
OUTPUTCHANNELS
};
#define BUFFERSIZE 24000
extern ALboolean DuplicateStereo;
__inline ALuint aluBytesFromFormat(ALenum format);
__inline ALuint aluChannelsFromFormat(ALenum format);
/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
* converted to AL_FORMAT_QUAD* when loaded */
static __inline ALuint aluBytesFromFormat(ALenum format)
{
switch(format)
{
case AL_FORMAT_MONO8:
case AL_FORMAT_STEREO8:
case AL_FORMAT_QUAD8_LOKI:
case AL_FORMAT_QUAD8:
case AL_FORMAT_51CHN8:
case AL_FORMAT_61CHN8:
case AL_FORMAT_71CHN8:
return 1;
case AL_FORMAT_MONO16:
case AL_FORMAT_STEREO16:
case AL_FORMAT_QUAD16_LOKI:
case AL_FORMAT_QUAD16:
case AL_FORMAT_51CHN16:
case AL_FORMAT_61CHN16:
case AL_FORMAT_71CHN16:
return 2;
case AL_FORMAT_MONO_FLOAT32:
case AL_FORMAT_STEREO_FLOAT32:
case AL_FORMAT_QUAD32:
case AL_FORMAT_51CHN32:
case AL_FORMAT_61CHN32:
case AL_FORMAT_71CHN32:
return 4;
default:
return 0;
}
}
static __inline ALuint aluChannelsFromFormat(ALenum format)
{
switch(format)
{
case AL_FORMAT_MONO8:
case AL_FORMAT_MONO16:
case AL_FORMAT_MONO_FLOAT32:
return 1;
case AL_FORMAT_STEREO8:
case AL_FORMAT_STEREO16:
case AL_FORMAT_STEREO_FLOAT32:
return 2;
case AL_FORMAT_QUAD8_LOKI:
case AL_FORMAT_QUAD16_LOKI:
case AL_FORMAT_QUAD8:
case AL_FORMAT_QUAD16:
case AL_FORMAT_QUAD32:
return 4;
case AL_FORMAT_51CHN8:
case AL_FORMAT_51CHN16:
case AL_FORMAT_51CHN32:
return 6;
case AL_FORMAT_61CHN8:
case AL_FORMAT_61CHN16:
case AL_FORMAT_61CHN32:
return 7;
case AL_FORMAT_71CHN8:
case AL_FORMAT_71CHN16:
case AL_FORMAT_71CHN32:
return 8;
default:
return 0;
}
}
ALvoid aluInitPanning(ALCcontext *Context);
ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format);
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
ALvoid aluHandleDisconnect(ALCdevice *device);
#ifdef __cplusplus
}
+99 -97
View File
@@ -29,7 +29,6 @@
#include "alAuxEffectSlot.h"
#include "alThunk.h"
#include "alError.h"
#include "alReverb.h"
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
@@ -38,20 +37,16 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot,
ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALsizei i;
ALsizei i, j;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n > 0)
{
/* NOTE: We only support one slot currently */
if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
ALCdevice *Device = Context->Device;
if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
{
// Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
@@ -64,9 +59,10 @@ ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
while(i < n)
{
*list = calloc(1, sizeof(ALeffectslot));
if(!(*list))
if(!(*list) || !((*list)->EffectState=NoneCreate()))
{
// We must have run out or memory
free(*list); *list = NULL;
alDeleteAuxiliaryEffectSlots(i, effectslots);
alSetError(AL_OUT_OF_MEMORY);
break;
@@ -74,6 +70,8 @@ ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
(*list)->Gain = 1.0;
(*list)->AuxSendAuto = AL_TRUE;
for(j = 0;j < BUFFERSIZE;j++)
(*list)->WetBuffer[j] = 0.0f;
(*list)->refcount = 0;
effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
@@ -99,13 +97,8 @@ ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
ALeffectslot *ALAuxiliaryEffectSlot;
ALsizei i;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n >= 0)
{
@@ -149,7 +142,8 @@ ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
VerbDestroy(ALAuxiliaryEffectSlot->ReverbState);
if(ALAuxiliaryEffectSlot->EffectState)
ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
free(ALAuxiliaryEffectSlot);
@@ -170,13 +164,8 @@ ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
ALCcontext *Context;
ALeffectslot **list;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return AL_FALSE;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
list = &Context->AuxiliaryEffectSlot;
while(*list && (*list)->effectslot != effectslot)
@@ -191,13 +180,8 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -237,13 +221,8 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALin
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -269,13 +248,8 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALflo
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -305,13 +279,8 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfl
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -336,13 +305,8 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, AL
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -373,13 +337,8 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, A
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -405,13 +364,8 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, AL
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -438,13 +392,8 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
{
@@ -466,39 +415,92 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
}
static ALvoid NoneDestroy(ALeffectState *State)
{ free(State); }
static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
{
return AL_TRUE;
(void)State;
(void)Device;
}
static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
{
(void)State;
(void)Context;
(void)Effect;
}
static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
{
(void)State;
(void)Slot;
(void)SamplesToDo;
(void)SamplesIn;
(void)SamplesOut;
}
ALeffectState *NoneCreate(void)
{
ALeffectState *state;
state = calloc(1, sizeof(*state));
if(!state)
{
alSetError(AL_OUT_OF_MEMORY);
return NULL;
}
state->Destroy = NoneDestroy;
state->DeviceUpdate = NoneDeviceUpdate;
state->Update = NoneUpdate;
state->Process = NoneProcess;
return state;
}
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
{
if(ALEffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
{
ALeffectState *NewState = NULL;
if(!effect || effect->type == AL_EFFECT_NULL)
NewState = NoneCreate();
else if(effect->type == AL_EFFECT_EAXREVERB)
NewState = EAXVerbCreate();
else if(effect->type == AL_EFFECT_REVERB)
NewState = VerbCreate();
else if(effect->type == AL_EFFECT_ECHO)
NewState = EchoCreate();
/* No new state? An error occured.. */
if(NewState == NULL ||
ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
{
if(NewState)
ALEffect_Destroy(NewState);
return;
}
if(ALEffectSlot->EffectState)
ALEffect_Destroy(ALEffectSlot->EffectState);
ALEffectSlot->EffectState = NewState;
}
if(!effect)
{
memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
VerbDestroy(ALEffectSlot->ReverbState);
ALEffectSlot->ReverbState = NULL;
return;
}
if(effect->type == AL_EFFECT_REVERB)
{
if(!ALEffectSlot->ReverbState)
ALEffectSlot->ReverbState = VerbCreate(Context);
VerbUpdate(Context, ALEffectSlot, effect);
}
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
}
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
{
#ifdef _DEBUG
if(Context->AuxiliaryEffectSlotCount > 0)
AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
#endif
while(Context->AuxiliaryEffectSlot)
{
ALeffectslot *temp = Context->AuxiliaryEffectSlot;
Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
// Release effectslot structure
VerbDestroy(temp->ReverbState);
if(temp->EffectState)
ALEffect_Destroy(temp->EffectState);
ALTHUNK_REMOVEENTRY(temp->effectslot);
memset(temp, 0, sizeof(ALeffectslot));
+90 -65
View File
@@ -18,8 +18,6 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
#include "config.h"
#include <stdlib.h>
@@ -30,6 +28,7 @@
#include "AL/alc.h"
#include "alError.h"
#include "alBuffer.h"
#include "alDatabuffer.h"
#include "alThunk.h"
@@ -51,9 +50,6 @@ static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, AL
* Global Variables
*/
static ALbuffer *g_pBuffers = NULL; // Linked List of Buffers
static ALuint g_uiBufferCount = 0; // Buffer Count
static const long g_IMAStep_size[89]={ // IMA ADPCM Stepsize table
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
@@ -83,16 +79,18 @@ ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
ALCcontext *Context;
ALsizei i=0;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
// Check that we are actually generation some Buffers
if (n > 0)
{
ALCdevice *device = Context->Device;
// Check the pointer is valid (and points to enough memory to store Buffer Names)
if (!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
{
ALbuffer **list = &g_pBuffers;
ALbuffer **list = &device->Buffers;
while(*list)
list = &(*list)->next;
@@ -108,8 +106,9 @@ ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
}
puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->state = UNUSED;
g_uiBufferCount++;
(*list)->buffer = puiBuffers[i];
device->BufferCount++;
i++;
list = &(*list)->next;
@@ -139,12 +138,14 @@ ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
ALsizei i;
ALboolean bFailed = AL_FALSE;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
// Check we are actually Deleting some Buffers
if (n >= 0)
{
ALCdevice *device = Context->Device;
// Check that all the buffers are valid and can actually be deleted
for (i = 0; i < n; i++)
{
@@ -178,7 +179,7 @@ ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
{
if (puiBuffers[i] && alIsBuffer(puiBuffers[i]))
{
ALbuffer **list = &g_pBuffers;
ALbuffer **list = &device->Buffers;
ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
while(*list && *list != ALBuf)
@@ -193,7 +194,7 @@ ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
// Release buffer structure
ALTHUNK_REMOVEENTRY(puiBuffers[i]);
memset(ALBuf, 0, sizeof(ALbuffer));
g_uiBufferCount--;
device->BufferCount--;
free(ALBuf);
}
}
@@ -220,15 +221,17 @@ ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint uiBuffer)
ALbuffer *ALBuf;
ALbuffer *TgtALBuf;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
if (uiBuffer)
{
ALCdevice *device = Context->Device;
TgtALBuf = (ALbuffer *)ALTHUNK_LOOKUPENTRY(uiBuffer);
// Check through list of generated buffers for uiBuffer
ALBuf = g_pBuffers;
ALBuf = device->Buffers;
while (ALBuf)
{
if (ALBuf == TgtALBuf)
@@ -259,16 +262,31 @@ ALAPI ALboolean ALAPIENTRY alIsBuffer(ALuint uiBuffer)
ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq)
{
ALCcontext *Context;
ALsizei padding = 2;
ALbuffer *ALBuf;
ALvoid *temp;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(buffer));
if(Context->SampleSource)
{
ALuint offset;
if(Context->SampleSource->state == MAPPED)
{
alSetError(AL_INVALID_OPERATION);
ProcessContext(Context);
return;
}
offset = (ALuint)data;
data = Context->SampleSource->data + offset;
}
if ((ALBuf->refcount==0)&&(data))
{
switch(format)
@@ -306,19 +324,18 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
size *= 2;
// Samples are converted to 16 bit here
temp = realloc(ALBuf->data, (padding*NewChannels + size) * sizeof(ALshort));
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * sizeof(ALshort));
if(temp)
{
ALBuf->data = temp;
ConvertDataRear(ALBuf->data, data, OrigBytes, size);
memset(&(ALBuf->data[size]), 0, padding*NewChannels*sizeof(ALshort));
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*NewChannels*sizeof(ALshort));
ALBuf->format = NewFormat;
ALBuf->eOriginalFormat = format;
ALBuf->size = size*sizeof(ALshort);
ALBuf->frequency = freq;
ALBuf->padding = padding;
}
else
alSetError(AL_OUT_OF_MEMORY);
@@ -367,19 +384,18 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
size *= 65;
// Allocate extra padding samples
temp = realloc(ALBuf->data, (padding*OrigChans + size)*sizeof(ALshort));
temp = realloc(ALBuf->data, (BUFFER_PADDING*OrigChans + size)*sizeof(ALshort));
if(temp)
{
ALBuf->data = temp;
ConvertDataIMA4(ALBuf->data, data, OrigChans, size/65);
memset(&(ALBuf->data[size]), 0, padding*sizeof(ALshort)*OrigChans);
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*sizeof(ALshort)*OrigChans);
ALBuf->format = ((OrigChans==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16);
ALBuf->eOriginalFormat = format;
ALBuf->size = size*sizeof(ALshort);
ALBuf->frequency = freq;
ALBuf->padding = padding;
}
else
alSetError(AL_OUT_OF_MEMORY);
@@ -415,12 +431,28 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
ALCcontext *Context;
ALbuffer *ALBuf;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if(alIsBuffer(buffer) && buffer != 0)
{
ALBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(buffer);
if(Context->SampleSource)
{
ALuint offset;
if(Context->SampleSource->state == MAPPED)
{
alSetError(AL_INVALID_OPERATION);
ProcessContext(Context);
return;
}
offset = (ALuint)data;
data = Context->SampleSource->data + offset;
}
if(ALBuf->data == NULL)
{
// buffer does not have any data
@@ -516,8 +548,8 @@ ALAPI void ALAPIENTRY alBufferf(ALuint buffer, ALenum eParam, ALfloat flValue)
(void)flValue;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -545,8 +577,8 @@ ALAPI void ALAPIENTRY alBuffer3f(ALuint buffer, ALenum eParam, ALfloat flValue1,
(void)flValue2;
(void)flValue3;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -572,8 +604,8 @@ ALAPI void ALAPIENTRY alBufferfv(ALuint buffer, ALenum eParam, const ALfloat* fl
(void)flValues;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -599,8 +631,8 @@ ALAPI void ALAPIENTRY alBufferi(ALuint buffer, ALenum eParam, ALint lValue)
(void)lValue;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -628,8 +660,8 @@ ALAPI void ALAPIENTRY alBuffer3i( ALuint buffer, ALenum eParam, ALint lValue1, A
(void)lValue2;
(void)lValue3;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -655,8 +687,8 @@ ALAPI void ALAPIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plVa
(void)plValues;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (alIsBuffer(buffer) && (buffer != 0))
{
@@ -680,8 +712,8 @@ ALAPI ALvoid ALAPIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pflV
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (pflValue)
{
@@ -712,8 +744,8 @@ ALAPI void ALAPIENTRY alGetBuffer3f(ALuint buffer, ALenum eParam, ALfloat* pflVa
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if ((pflValue1) && (pflValue2) && (pflValue3))
{
@@ -744,8 +776,8 @@ ALAPI void ALAPIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pflVa
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (pflValues)
{
@@ -777,8 +809,8 @@ ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValu
ALCcontext *pContext;
ALbuffer *pBuffer;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (plValue)
{
@@ -827,8 +859,8 @@ ALAPI void ALAPIENTRY alGetBuffer3i(ALuint buffer, ALenum eParam, ALint* plValue
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if ((plValue1) && (plValue2) && (plValue3))
{
@@ -859,8 +891,8 @@ ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValue
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (plValues)
{
@@ -906,7 +938,6 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
ALuint NewChannels = aluChannelsFromFormat(NewFormat);
ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
ALsizei padding = 2;
ALvoid *temp;
assert(aluBytesFromFormat(NewFormat) == 2);
@@ -920,19 +951,18 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
// Samples are converted to 16 bit here
size /= OrigBytes;
temp = realloc(ALBuf->data, (padding*NewChannels + size) * sizeof(ALshort));
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * sizeof(ALshort));
if(temp)
{
ALBuf->data = temp;
ConvertData(ALBuf->data, data, OrigBytes, size);
memset(&(ALBuf->data[size]), 0, padding*NewChannels*sizeof(ALshort));
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*NewChannels*sizeof(ALshort));
ALBuf->format = NewFormat;
ALBuf->eOriginalFormat = OrigFormat;
ALBuf->size = size*sizeof(ALshort);
ALBuf->frequency = freq;
ALBuf->padding = padding;
}
else
alSetError(AL_OUT_OF_MEMORY);
@@ -1071,17 +1101,12 @@ static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, AL
*
* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
*/
ALvoid ReleaseALBuffers(ALvoid)
ALvoid ReleaseALBuffers(ALCdevice *device)
{
ALbuffer *ALBuffer;
ALbuffer *ALBufferTemp;
#ifdef _DEBUG
if(g_uiBufferCount > 0)
AL_PRINT("exit(): deleting %d Buffer(s)\n", g_uiBufferCount);
#endif
ALBuffer = g_pBuffers;
ALBuffer = device->Buffers;
while(ALBuffer)
{
// Release sample data
@@ -1093,6 +1118,6 @@ ALvoid ReleaseALBuffers(ALvoid)
memset(ALBufferTemp, 0, sizeof(ALbuffer));
free(ALBufferTemp);
}
g_pBuffers = NULL;
g_uiBufferCount = 0;
device->Buffers = NULL;
device->BufferCount = 0;
}
+639
View File
@@ -0,0 +1,639 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 1999-2007 by authors.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "alError.h"
#include "alDatabuffer.h"
#include "alThunk.h"
/*
* alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
*
* Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
*/
ALvoid ALAPIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers)
{
ALCcontext *Context;
ALsizei i=0;
Context = GetContextSuspended();
if(!Context) return;
/* Check that we are actually generation some Databuffers */
if(n > 0)
{
ALCdevice *device = Context->Device;
/* Check the pointer is valid (and points to enough memory to store
* Databuffer Names) */
if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
{
ALdatabuffer **list = &device->Databuffers;
while(*list)
list = &(*list)->next;
/* Create all the new Databuffers */
while(i < n)
{
*list = calloc(1, sizeof(ALdatabuffer));
if(!(*list))
{
alDeleteDatabuffersEXT(i, puiBuffers);
alSetError(AL_OUT_OF_MEMORY);
break;
}
puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->databuffer = puiBuffers[i];
(*list)->state = UNMAPPED;
device->DatabufferCount++;
i++;
list = &(*list)->next;
}
}
else
alSetError(AL_INVALID_VALUE);
}
ProcessContext(Context);
}
/*
* alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
*
* Deletes the n AL Databuffers pointed to by puiBuffers
*/
ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
{
ALCcontext *Context;
ALdatabuffer *ALBuf;
ALsizei i;
ALboolean bFailed = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
/* Check we are actually Deleting some Databuffers */
if(n >= 0)
{
ALCdevice *device = Context->Device;
/* Check that all the databuffers are valid and can actually be
* deleted */
for(i = 0;i < n;i++)
{
/* Check for valid Buffer ID (can be NULL buffer) */
if(alIsDatabufferEXT(puiBuffers[i]))
{
/* If not the NULL buffer, check that it's unmapped */
ALBuf = ((ALdatabuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
if(ALBuf)
{
if(ALBuf->state != UNMAPPED)
{
/* Databuffer still in use, cannot be deleted */
alSetError(AL_INVALID_OPERATION);
bFailed = AL_TRUE;
}
}
}
else
{
/* Invalid Databuffer */
alSetError(AL_INVALID_NAME);
bFailed = AL_TRUE;
}
}
/* If all the Databuffers were valid (and unmapped), then we can
* delete them */
if(!bFailed)
{
for(i = 0;i < n;i++)
{
if(puiBuffers[i] && alIsDatabufferEXT(puiBuffers[i]))
{
ALdatabuffer **list = &device->Databuffers;
ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(puiBuffers[i]);
while(*list && *list != ALBuf)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
if(ALBuf == Context->SampleSource)
Context->SampleSource = NULL;
if(ALBuf == Context->SampleSink)
Context->SampleSink = NULL;
// Release the memory used to store audio data
free(ALBuf->data);
// Release buffer structure
ALTHUNK_REMOVEENTRY(puiBuffers[i]);
memset(ALBuf, 0, sizeof(ALdatabuffer));
device->DatabufferCount--;
free(ALBuf);
}
}
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
return;
}
/*
* alIsDatabufferEXT(ALuint uiBuffer)
*
* Checks if ulBuffer is a valid Databuffer Name
*/
ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer)
{
ALCcontext *Context;
ALdatabuffer *ALBuf;
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
/* Check through list of generated databuffers for uiBuffer */
ALBuf = Context->Device->Databuffers;
while(ALBuf && ALBuf->databuffer != uiBuffer)
ALBuf = ALBuf->next;
ProcessContext(Context);
return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE);
}
/*
* alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
*
* Fill databuffer with data
*/
ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage)
{
ALCcontext *Context;
ALdatabuffer *ALBuf;
ALvoid *temp;
Context = GetContextSuspended();
if(!Context) return;
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
if(ALBuf->state == UNMAPPED)
{
if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
usage == AL_DYNAMIC_COPY_EXT)
{
/* (Re)allocate data */
temp = realloc(ALBuf->data, size);
if(temp)
{
ALBuf->data = temp;
ALBuf->size = size;
ALBuf->usage = usage;
if(data)
memcpy(ALBuf->data, data, size);
}
else
alSetError(AL_OUT_OF_MEMORY);
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_OPERATION);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
{
pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
if(length >= 0 && start+length <= pBuffer->size)
{
if(pBuffer->state == UNMAPPED)
memcpy(pBuffer->data+start, data, length);
else
alSetError(AL_INVALID_OPERATION);
}
else
alSetError(AL_INVALID_VALUE);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALvoid *data)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
{
pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
if(length >= 0 && start+length <= pBuffer->size)
{
if(pBuffer->state == UNMAPPED)
memcpy(data, pBuffer->data+start, length);
else
alSetError(AL_INVALID_OPERATION);
}
else
alSetError(AL_INVALID_VALUE);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
{
ALCcontext *pContext;
(void)flValue;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
{
ALCcontext *pContext;
(void)flValues;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
{
ALCcontext *pContext;
(void)lValue;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
{
ALCcontext *pContext;
(void)plValues;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
{
ALCcontext *pContext;
pContext = GetContextSuspended();
if(!pContext) return;
if(pflValue)
{
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
{
ALCcontext *pContext;
pContext = GetContextSuspended();
if(!pContext) return;
if(pflValues)
{
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
pContext = GetContextSuspended();
if(!pContext) return;
if(plValue)
{
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
switch(eParam)
{
case AL_SIZE:
*plValue = pBuffer->size;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
{
ALCcontext *pContext;
pContext = GetContextSuspended();
if(!pContext) return;
if(plValues)
{
if(alIsDatabufferEXT(buffer) && buffer != 0)
{
switch (eParam)
{
case AL_SIZE:
alGetBufferi(buffer, eParam, plValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(uiBuffer))
{
pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL);
if(target == AL_SAMPLE_SOURCE_EXT)
pContext->SampleSource = pBuffer;
else if(target == AL_SAMPLE_SINK_EXT)
pContext->SampleSink = pBuffer;
else
alSetError(AL_INVALID_VALUE);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALvoid *ret = NULL;
pContext = GetContextSuspended();
if(!pContext) return NULL;
if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
{
pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
if(length >= 0 && start+length <= pBuffer->size)
{
if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
access == AL_READ_WRITE_EXT)
{
if(pBuffer->state == UNMAPPED)
{
ret = pBuffer->data + start;
pBuffer->state = MAPPED;
}
else
alSetError(AL_INVALID_OPERATION);
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_VALUE);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
return ret;
}
ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
pContext = GetContextSuspended();
if(!pContext) return;
if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
{
pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
if(pBuffer->state == MAPPED)
pBuffer->state = UNMAPPED;
else
alSetError(AL_INVALID_OPERATION);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(pContext);
}
/*
* ReleaseALDatabuffers()
*
* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
*/
ALvoid ReleaseALDatabuffers(ALCdevice *device)
{
ALdatabuffer *ALBuffer;
ALdatabuffer *ALBufferTemp;
ALBuffer = device->Databuffers;
while(ALBuffer)
{
// Release sample data
free(ALBuffer->data);
// Release Buffer structure
ALBufferTemp = ALBuffer;
ALBuffer = ALBuffer->next;
memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
free(ALBufferTemp);
}
device->Databuffers = NULL;
device->DatabufferCount = 0;
}
+669 -77
View File
File diff suppressed because it is too large Load Diff
+16 -21
View File
@@ -26,34 +26,29 @@
ALAPI ALenum ALAPIENTRY alGetError(ALvoid)
{
ALCcontext *Context;
ALenum errorCode;
ALCcontext *Context;
ALenum errorCode;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_INVALID_OPERATION;
if (Context)
{
errorCode = Context->LastError;
Context->LastError = AL_NO_ERROR;
}
else
errorCode = AL_INVALID_OPERATION;
errorCode = Context->LastError;
Context->LastError = AL_NO_ERROR;
ProcessContext(Context);
ProcessContext(Context);
return errorCode;
return errorCode;
}
ALvoid alSetError(ALenum errorCode)
{
ALCcontext *Context;
ALCcontext *Context;
Context=alcGetCurrentContext();
SuspendContext(Context);
if (Context && Context->LastError == AL_NO_ERROR)
Context->LastError = errorCode;
ProcessContext(Context);
Context = GetContextSuspended();
if(Context)
{
if(Context->LastError == AL_NO_ERROR)
Context->LastError = errorCode;
ProcessContext(Context);
}
}
+21 -8
View File
@@ -29,6 +29,7 @@
#include "alFilter.h"
#include "alEffect.h"
#include "alAuxEffectSlot.h"
#include "alDatabuffer.h"
#include "alSource.h"
#include "alBuffer.h"
#include "AL/al.h"
@@ -147,6 +148,24 @@ static ALfunction function[]= {
{ "alBufferSubDataEXT", (ALvoid *) alBufferSubDataEXT },
{ "alGenDatabuffersEXT", (ALvoid *) alGenDatabuffersEXT },
{ "alDeleteDatabuffersEXT", (ALvoid *) alDeleteDatabuffersEXT },
{ "alIsDatabufferEXT", (ALvoid *) alIsDatabufferEXT },
{ "alDatabufferDataEXT", (ALvoid *) alDatabufferDataEXT },
{ "alDatabufferSubDataEXT", (ALvoid *) alDatabufferSubDataEXT },
{ "alGetDatabufferSubDataEXT", (ALvoid *) alGetDatabufferSubDataEXT },
{ "alDatabufferfEXT", (ALvoid *) alDatabufferfEXT },
{ "alDatabufferfvEXT", (ALvoid *) alDatabufferfvEXT },
{ "alDatabufferiEXT", (ALvoid *) alDatabufferiEXT },
{ "alDatabufferivEXT", (ALvoid *) alDatabufferivEXT },
{ "alGetDatabufferfEXT", (ALvoid *) alGetDatabufferfEXT },
{ "alGetDatabufferfvEXT", (ALvoid *) alGetDatabufferfvEXT },
{ "alGetDatabufferiEXT", (ALvoid *) alGetDatabufferiEXT },
{ "alGetDatabufferivEXT", (ALvoid *) alGetDatabufferivEXT },
{ "alSelectDatabufferEXT", (ALvoid *) alSelectDatabufferEXT },
{ "alMapDatabufferEXT", (ALvoid *) alMapDatabufferEXT },
{ "alUnmapDatabufferEXT", (ALvoid *) alUnmapDatabufferEXT },
{ NULL, (ALvoid *) NULL } };
static ALenums enumeration[]={
@@ -333,14 +352,8 @@ ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
return AL_FALSE;
}
pContext = alcGetCurrentContext();
if(!pContext)
{
alSetError(AL_INVALID_OPERATION);
return AL_FALSE;
}
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return AL_FALSE;
len = strlen(extName);
ptr = pContext->ExtensionList;
+42 -43
View File
@@ -29,8 +29,6 @@
#include "alThunk.h"
#include "alError.h"
static ALfilter *g_FilterList;
static ALuint g_FilterCount;
static void InitFilterParams(ALfilter *filter, ALenum type);
@@ -40,15 +38,17 @@ ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
ALCcontext *Context;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n > 0)
{
ALCdevice *device = Context->Device;
// Check that enough memory has been allocted in the 'filters' array for n Filters
if (!IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
{
ALfilter **list = &g_FilterList;
ALfilter **list = &device->FilterList;
while(*list)
list = &(*list)->next;
@@ -68,7 +68,7 @@ ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
(*list)->filter = filters[i];
InitFilterParams(*list, AL_FILTER_NULL);
g_FilterCount++;
device->FilterCount++;
i++;
list = &(*list)->next;
@@ -85,11 +85,13 @@ ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
ALfilter *ALFilter;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n >= 0)
{
ALCdevice *device = Context->Device;
// Check that all filters are valid
for (i = 0; i < n; i++)
{
@@ -113,7 +115,7 @@ ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
ALFilter = ((ALfilter*)ALTHUNK_LOOKUPENTRY(filters[i]));
// Remove Source from list of Sources
list = &g_FilterList;
list = &device->FilterList;
while(*list && *list != ALFilter)
list = &(*list)->next;
@@ -124,7 +126,7 @@ ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
memset(ALFilter, 0, sizeof(ALfilter));
free(ALFilter);
g_FilterCount--;
device->FilterCount--;
}
}
}
@@ -138,26 +140,26 @@ ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
ALboolean AL_APIENTRY alIsFilter(ALuint filter)
{
ALCcontext *Context;
ALfilter **list;
ALfilter *list;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
list = &g_FilterList;
while(*list && (*list)->filter != filter)
list = &(*list)->next;
list = Context->Device->FilterList;
while(list && list->filter != filter)
list = list->next;
ProcessContext(Context);
return ((*list || !filter) ? AL_TRUE : AL_FALSE);
return ((list || !filter) ? AL_TRUE : AL_FALSE);
}
ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -188,8 +190,8 @@ ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -214,8 +216,8 @@ ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -261,8 +263,8 @@ ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -283,8 +285,8 @@ ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -311,8 +313,8 @@ ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -337,8 +339,8 @@ ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -378,8 +380,8 @@ ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
{
@@ -397,23 +399,20 @@ ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues
}
ALvoid ReleaseALFilters(ALvoid)
ALvoid ReleaseALFilters(ALCdevice *device)
{
#ifdef _DEBUG
if(g_FilterCount > 0)
AL_PRINT("exit(): deleting %d Filter(s)\n", g_FilterCount);
#endif
while(g_FilterList)
ALfilter *list = device->FilterList;
while(list)
{
ALfilter *temp = g_FilterList;
g_FilterList = g_FilterList->next;
ALfilter *temp = list;
list = list->next;
// Release filter structure
memset(temp, 0, sizeof(ALfilter));
free(temp);
}
g_FilterCount = 0;
device->FilterList = NULL;
device->FilterCount = 0;
}
+80 -164
View File
@@ -29,22 +29,20 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
switch (eParam)
{
switch(eParam)
{
case AL_GAIN:
if (flValue >= 0.0f)
if(flValue >= 0.0f)
pContext->Listener.Gain = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if (flValue > 0.0f)
if(flValue > 0.0f)
pContext->Listener.MetersPerUnit = flValue;
else
alSetError(AL_INVALID_VALUE);
@@ -53,14 +51,9 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
@@ -68,13 +61,11 @@ ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat fl
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
switch(eParam)
{
switch(eParam)
{
case AL_POSITION:
pContext->Listener.Position[0] = flValue1;
pContext->Listener.Position[1] = flValue2;
@@ -90,14 +81,9 @@ ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat fl
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
@@ -105,24 +91,22 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (pflValues)
if(pflValues)
{
switch(eParam)
{
switch (eParam)
{
case AL_GAIN:
if (pflValues[0] >= 0.0f)
if(pflValues[0] >= 0.0f)
pContext->Listener.Gain = pflValues[0];
else
alSetError(AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if (pflValues[0] > 0.0f)
if(pflValues[0] > 0.0f)
pContext->Listener.MetersPerUnit = pflValues[0];
else
alSetError(AL_INVALID_VALUE);
@@ -153,17 +137,12 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -173,24 +152,17 @@ ALAPI ALvoid ALAPIENTRY alListeneri(ALenum eParam, ALint lValue)
(void)lValue;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
switch (eParam)
{
switch(eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
@@ -198,13 +170,11 @@ ALAPI void ALAPIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2,
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
switch(eParam)
{
switch(eParam)
{
case AL_POSITION:
case AL_VELOCITY:
alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
@@ -213,14 +183,9 @@ ALAPI void ALAPIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2,
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
@@ -229,15 +194,13 @@ ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
ALCcontext *pContext;
ALfloat flValues[6];
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (plValues)
if(plValues)
{
switch(eParam)
{
switch (eParam)
{
case AL_POSITION:
case AL_VELOCITY:
flValues[0] = (ALfloat)plValues[0];
@@ -259,17 +222,12 @@ ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -277,15 +235,13 @@ ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (pflValue)
if(pflValue)
{
switch(eParam)
{
switch (eParam)
{
case AL_GAIN:
*pflValue = pContext->Listener.Gain;
break;
@@ -297,17 +253,12 @@ ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -315,15 +266,13 @@ ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALflo
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if ((pflValue1) && (pflValue2) && (pflValue3))
if(pflValue1 && pflValue2 && pflValue3)
{
switch(eParam)
{
switch (eParam)
{
case AL_POSITION:
*pflValue1 = pContext->Listener.Position[0];
*pflValue2 = pContext->Listener.Position[1];
@@ -339,17 +288,12 @@ ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALflo
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -357,15 +301,13 @@ ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (pflValues)
if(pflValues)
{
switch(eParam)
{
switch (eParam)
{
case AL_GAIN:
pflValues[0] = pContext->Listener.Gain;
break;
@@ -399,17 +341,12 @@ ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -417,29 +354,22 @@ ALAPI ALvoid ALAPIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (plValue)
if(plValue)
{
switch(eParam)
{
switch (eParam)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -447,15 +377,13 @@ ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plV
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if ((plValue1) && (plValue2) && (plValue3))
if(plValue1 && plValue2 && plValue3)
{
switch (eParam)
{
switch (eParam)
{
case AL_POSITION:
*plValue1 = (ALint)pContext->Listener.Position[0];
*plValue2 = (ALint)pContext->Listener.Position[1];
@@ -471,17 +399,12 @@ ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plV
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
@@ -489,15 +412,13 @@ ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (plValues)
if(plValues)
{
switch(eParam)
{
switch (eParam)
{
case AL_POSITION:
plValues[0] = (ALint)pContext->Listener.Position[0];
plValues[1] = (ALint)pContext->Listener.Position[1];
@@ -523,15 +444,10 @@ ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
+573 -850
View File
File diff suppressed because it is too large Load Diff
+271 -382
View File
@@ -23,9 +23,11 @@
#include <stdlib.h>
#include "alMain.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "alError.h"
#include "alSource.h"
#include "alState.h"
#include "alDatabuffer.h"
static const ALchar alVendor[] = "OpenAL Community";
static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
@@ -43,50 +45,34 @@ ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
{
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
switch (capability)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
switch(capability)
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
{
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
switch (capability)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
switch(capability)
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
@@ -94,26 +80,18 @@ ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
ALCcontext *Context;
ALboolean value=AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
{
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
switch (capability)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
switch(capability)
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
@@ -122,46 +100,38 @@ ALAPI ALboolean ALAPIENTRY alGetBoolean(ALenum pname)
ALCcontext *Context;
ALboolean value=AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
switch(pname)
{
SuspendContext(Context);
case AL_DOPPLER_FACTOR:
if(Context->DopplerFactor != 0.0f)
value = AL_TRUE;
break;
switch (pname)
{
case AL_DOPPLER_FACTOR:
if (Context->DopplerFactor != 0.0f)
value = AL_TRUE;
break;
case AL_DOPPLER_VELOCITY:
if(Context->DopplerVelocity != 0.0f)
value = AL_TRUE;
break;
case AL_DOPPLER_VELOCITY:
if (Context->DopplerVelocity != 0.0f)
value = AL_TRUE;
break;
case AL_DISTANCE_MODEL:
if(Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
value = AL_TRUE;
break;
case AL_DISTANCE_MODEL:
if (Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
value = AL_TRUE;
break;
case AL_SPEED_OF_SOUND:
if(Context->flSpeedOfSound != 0.0f)
value = AL_TRUE;
break;
case AL_SPEED_OF_SOUND:
if (Context->flSpeedOfSound != 0.0f)
value = AL_TRUE;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
@@ -170,42 +140,34 @@ ALAPI ALdouble ALAPIENTRY alGetDouble(ALenum pname)
ALCcontext *Context;
ALdouble value = 0.0;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return 0.0;
switch(pname)
{
SuspendContext(Context);
case AL_DOPPLER_FACTOR:
value = (double)Context->DopplerFactor;
break;
switch (pname)
{
case AL_DOPPLER_FACTOR:
value = (double)Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
value = (double)Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
value = (double)Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
value = (double)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
value = (double)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
value = (double)Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
value = (double)Context->flSpeedOfSound;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
@@ -214,42 +176,34 @@ ALAPI ALfloat ALAPIENTRY alGetFloat(ALenum pname)
ALCcontext *Context;
ALfloat value = 0.0f;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return 0.0f;
switch(pname)
{
SuspendContext(Context);
case AL_DOPPLER_FACTOR:
value = Context->DopplerFactor;
break;
switch (pname)
{
case AL_DOPPLER_FACTOR:
value = Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
value = Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
value = Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
value = (float)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
value = (float)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
value = Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
value = Context->flSpeedOfSound;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
@@ -258,42 +212,48 @@ ALAPI ALint ALAPIENTRY alGetInteger(ALenum pname)
ALCcontext *Context;
ALint value = 0;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return 0;
switch(pname)
{
SuspendContext(Context);
case AL_DOPPLER_FACTOR:
value = (ALint)Context->DopplerFactor;
break;
switch (pname)
{
case AL_DOPPLER_FACTOR:
value = (ALint)Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
value = (ALint)Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
value = (ALint)Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
value = (ALint)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
value = (ALint)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
value = (ALint)Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
value = (ALint)Context->flSpeedOfSound;
break;
case AL_SAMPLE_SOURCE_EXT:
if(Context->SampleSource)
value = (ALint)Context->SampleSource->databuffer;
else
value = 0;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
case AL_SAMPLE_SINK_EXT:
if(Context->SampleSink)
value = (ALint)Context->SampleSink->databuffer;
else
value = 0;
break;
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
@@ -301,204 +261,178 @@ ALAPI ALvoid ALAPIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(data)
{
SuspendContext(Context);
if (data)
switch(pname)
{
switch (pname)
{
case AL_DOPPLER_FACTOR:
*data = (ALboolean)((Context->DopplerFactor != 0.0f) ? AL_TRUE : AL_FALSE);
break;
case AL_DOPPLER_FACTOR:
*data = (ALboolean)((Context->DopplerFactor != 0.0f) ? AL_TRUE : AL_FALSE);
break;
case AL_DOPPLER_VELOCITY:
*data = (ALboolean)((Context->DopplerVelocity != 0.0f) ? AL_TRUE : AL_FALSE);
break;
case AL_DOPPLER_VELOCITY:
*data = (ALboolean)((Context->DopplerVelocity != 0.0f) ? AL_TRUE : AL_FALSE);
break;
case AL_DISTANCE_MODEL:
*data = (ALboolean)((Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) ? AL_TRUE : AL_FALSE);
break;
case AL_DISTANCE_MODEL:
*data = (ALboolean)((Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) ? AL_TRUE : AL_FALSE);
break;
case AL_SPEED_OF_SOUND:
*data = (ALboolean)((Context->flSpeedOfSound != 0.0f) ? AL_TRUE : AL_FALSE);
break;
case AL_SPEED_OF_SOUND:
*data = (ALboolean)((Context->flSpeedOfSound != 0.0f) ? AL_TRUE : AL_FALSE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
default:
alSetError(AL_INVALID_ENUM);
break;
}
else
{
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetDoublev(ALenum pname,ALdouble *data)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(data)
{
SuspendContext(Context);
if (data)
switch(pname)
{
switch (pname)
{
case AL_DOPPLER_FACTOR:
*data = (double)Context->DopplerFactor;
break;
case AL_DOPPLER_FACTOR:
*data = (double)Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
*data = (double)Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
*data = (double)Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
*data = (double)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
*data = (double)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
*data = (double)Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
*data = (double)Context->flSpeedOfSound;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
default:
alSetError(AL_INVALID_ENUM);
break;
}
else
{
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetFloatv(ALenum pname,ALfloat *data)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(data)
{
SuspendContext(Context);
if (data)
switch(pname)
{
switch (pname)
{
case AL_DOPPLER_FACTOR:
*data = Context->DopplerFactor;
break;
case AL_DOPPLER_FACTOR:
*data = Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
*data = Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
*data = Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
*data = (float)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
*data = (float)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
*data = Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
*data = Context->flSpeedOfSound;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
default:
alSetError(AL_INVALID_ENUM);
break;
}
else
{
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetIntegerv(ALenum pname,ALint *data)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(data)
{
SuspendContext(Context);
if (data)
switch(pname)
{
switch (pname)
{
case AL_DOPPLER_FACTOR:
*data = (ALint)Context->DopplerFactor;
break;
case AL_DOPPLER_FACTOR:
*data = (ALint)Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
*data = (ALint)Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
*data = (ALint)Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
*data = (ALint)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
*data = (ALint)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
*data = (ALint)Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
*data = (ALint)Context->flSpeedOfSound;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
case AL_SAMPLE_SOURCE_EXT:
if(Context->SampleSource)
*data = (ALint)Context->SampleSource->databuffer;
else
*data = 0;
break;
case AL_SAMPLE_SINK_EXT:
if(Context->SampleSink)
*data = (ALint)Context->SampleSink->databuffer;
else
*data = 0;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
else
{
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
// data is a NULL pointer
alSetError(AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
@@ -506,14 +440,8 @@ ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
const ALchar *value;
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if(!pContext)
{
alSetError(AL_INVALID_OPERATION);
return NULL;
}
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return NULL;
switch(pname)
{
@@ -572,74 +500,45 @@ ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
{
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (value>=0.0f)
Context->DopplerFactor = value;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
if(value >= 0.0f)
Context->DopplerFactor = value;
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
}
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
if (Context)
{
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (value>0.0f)
Context->DopplerVelocity=value;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
if(value > 0.0f)
Context->DopplerVelocity=value;
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
}
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
{
ALCcontext *pContext;
pContext = alcGetCurrentContext();
if (pContext)
{
SuspendContext(pContext);
pContext = GetContextSuspended();
if(!pContext) return;
if (flSpeedOfSound > 0.0f)
pContext->flSpeedOfSound = flSpeedOfSound;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
if(flSpeedOfSound > 0.0f)
pContext->flSpeedOfSound = flSpeedOfSound;
else
{
alSetError(AL_INVALID_OPERATION);
}
alSetError(AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
@@ -647,37 +546,27 @@ ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
ALCcontext *Context;
ALsource *Source;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
switch(value)
{
SuspendContext(Context);
case AL_NONE:
case AL_INVERSE_DISTANCE:
case AL_INVERSE_DISTANCE_CLAMPED:
case AL_LINEAR_DISTANCE:
case AL_LINEAR_DISTANCE_CLAMPED:
case AL_EXPONENT_DISTANCE:
case AL_EXPONENT_DISTANCE_CLAMPED:
Context->DistanceModel = value;
for(Source = Context->Source;Source != NULL;Source = Source->next)
Source->DistanceModel = value;
break;
switch (value)
{
case AL_NONE:
case AL_INVERSE_DISTANCE:
case AL_INVERSE_DISTANCE_CLAMPED:
case AL_LINEAR_DISTANCE:
case AL_LINEAR_DISTANCE_CLAMPED:
case AL_EXPONENT_DISTANCE:
case AL_EXPONENT_DISTANCE_CLAMPED:
Context->DistanceModel = value;
for(Source = Context->Source;Source != NULL;Source = Source->next)
Source->DistanceModel = value;
break;
default:
alSetError(AL_INVALID_VALUE);
break;
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
default:
alSetError(AL_INVALID_VALUE);
break;
}
return;
ProcessContext(Context);
}
+1 -2
View File
@@ -1,6 +1,5 @@
# Cross-compiling requires CMake 2.6 or newer. To cross-compile, first modify
# this file to set the proper settings and paths. Then use it from CMakeConf/
# like:
# this file to set the proper settings and paths. Then use it from build/ like:
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt \
# -DCMAKE_INSTALL_PREFIX=/usr/mingw32/mingw
# If you already have a toolchain file setup, you may use that instead of this
+174 -110
View File
@@ -10,140 +10,204 @@
# Option and block names are case-insenstive. The supplied values are only
# hints and may not be honored (though generally it'll try to get as close as
# possible). These are the current available settings:
# possible). Note: options that are left unset may default to app- or system-
# specified values. These are the current available settings:
format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of:
# AL_FORMAT_MONO8 (8-bit mono)
# AL_FORMAT_STEREO8 (8-bit stereo)
# AL_FORMAT_QUAD8 (8-bit 4-channel)
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
# AL_FORMAT_MONO16 (16-bit mono)
# AL_FORMAT_STEREO16 (16-bit stereo)
# AL_FORMAT_QUAD16 (16-bit 4-channel)
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
# Default is AL_FORMAT_STEREO16
## format:
# Sets the output format. Can be one of:
# AL_FORMAT_MONO8 (8-bit mono)
# AL_FORMAT_STEREO8 (8-bit stereo)
# AL_FORMAT_QUAD8 (8-bit 4-channel)
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
# AL_FORMAT_MONO16 (16-bit mono)
# AL_FORMAT_STEREO16 (16-bit stereo)
# AL_FORMAT_QUAD16 (16-bit 4-channel)
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
# AL_FORMAT_MONO32 (32-bit float mono)
# AL_FORMAT_STEREO32 (32-bit float stereo)
# AL_FORMAT_QUAD32 (32-bit float 4-channel)
# AL_FORMAT_51CHN32 (32-bit float 5.1 output)
# AL_FORMAT_61CHN32 (32-bit float 6.1 output)
# AL_FORMAT_71CHN32 (32-bit float 7.1 output)
#format = AL_FORMAT_STEREO16
cf_level = 0 # Sets the crossfeed level for stereo output. Valid values are:
# 0 - No crossfeed
# 1 - Low crossfeed
# 2 - Middle crossfeed
# 3 - High crossfeed (virtual speakers are closer to itself)
# 4 - Low easy crossfeed
# 5 - Middle easy crossfeed
# 6 - High easy crossfeed
# Default is 0. Users of headphones may want to try various
# settings. Has no effect on non-stereo modes.
## cf_level:
# Sets the crossfeed level for stereo output. Valid values are:
# 0 - No crossfeed
# 1 - Low crossfeed
# 2 - Middle crossfeed
# 3 - High crossfeed (virtual speakers are closer to itself)
# 4 - Low easy crossfeed
# 5 - Middle easy crossfeed
# 6 - High easy crossfeed
# Users of headphones may want to try various settings. Has no effect on non-
# stereo modes.
#cf_level = 0
frequency = 44100 # Sets the output frequency. Default is 44100
## frequency:
# Sets the output frequency.
#frequency = 44100
refresh = 4096 # Sets the buffer size, in frames. Default is 4096. Note that
# the actual granularity may or may not be less than this.
## period_size:
# Sets the update period size, in frames. This is the number of frames needed
# for each mixing update. If the deprecated 'refresh' option is specified and
# this isn't, the value will be calculated as size = refresh/periods.
#period_size = 1024
sources = 256 # Sets the maximum number of allocatable sources. Lower values
# may help for systems with apps that try to play more sounds
# than the CPU can handle. Default is 256
## periods:
# Sets the number of update periods. Higher values create a larger mix ahead,
# which helps protect against skips when the CPU is under load, but increases
# the delay between a sound getting mixed and being heard.
#periods = 4
stereodup = # Sets whether to duplicate stereo sounds on the rear and side
# speakers for 4+ channel output. This can make stereo sources
# substantially louder than mono or even 4+ channel sources, but
# provides a "fuller" playback quality. True, yes, on, and non-0
# values will duplicate stereo sources. 0 and anything else will
# cause stereo sounds to only play out the front speakers.
# Default is false
## sources:
# Sets the maximum number of allocatable sources. Lower values may help for
# systems with apps that try to play more sounds than the CPU can handle.
#sources = 256
drivers = # Sets the backend driver list order, comma-seperated. Unknown
# backends and duplicated names are ignored, and unlisted backends
# won't be considered for use. An empty list means the default.
# Default is:
# alsa,oss,solaris,dsound,winmm,port,wave
## stereodup:
# Sets whether to duplicate stereo sounds on the rear and side speakers for 4+
# channel output. This can make stereo sources substantially louder than mono
# or even 4+ channel sources, but provides a "fuller" playback quality. True,
# yes, on, and non-0 values will duplicate stereo sources. 0 and anything else
# will cause stereo sounds to only play out the front speakers.
#stereodup = false
excludefx = # Sets which effects to exclude, preventing apps from using them.
# This can help for apps that try to use effects which are too CPU
# intensive for the system to handle. Available effects are:
# reverb
# Default is empty (all available effects enabled)
## drivers:
# Sets the backend driver list order, comma-seperated. Unknown backends and
# duplicated names are ignored, and unlisted backends won't be considered for
# use. An empty list means the default.
#drivers = alsa,oss,solaris,dsound,winmm,port,pulse,wave
layout_STEREO = # Sets the speaker layout when using stereo output. Values are
specified in degrees, where 0 is straight in front, negative
goes left, and positive goes right. The values must define a
circular pattern, starting with the back-left at the most
negative, around the front to back-center. Unspecified
speakers will remain at their default position. Available
speakers are front-left(fl) and front-right(fr).
The default is:
fl=-90, fr=90
## excludefx:
# Sets which effects to exclude, preventing apps from using them. This can
# help for apps that try to use effects which are too CPU intensive for the
# system to handle. Available effects are: eaxreverb,reverb,echo
#excludefx =
layout_QUAD = # Sets the speaker layout when using quadriphonic output.
Available speakers are back-left(bl), front-left(fl),
front-right(fr), and back-right(br).
The default is:
bl=-135, fl=-45, fr=45, br=135
## slots:
# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot
# can use a non-negligible amount of CPU time if an effect is set on it even
# if no sources are feeding it, so this may help when apps use more than the
# system can handle.
#slots = 4
layout_51CHN = # Sets the speaker layout when using 5.1 output. Available
speakers are back-left(bl), front-left(fl), front-center(fc),
front-right(fr), and back-right(br).
The default is:
bl=-110, fl=-30, fc=0, fr=30, br=110
## sends:
# Sets the maximum number of auxiliary sends per source. The total number of
# sends possible is defined at compile time and thus can not be increased
# beyond the default (2).
#sends = 2
layout_61CHN = # Sets the speaker layout when using 6.1 output. Available
speakers are side-left(sl), front-left(fl), front-center(fc),
front-right(fr), side-right(sr), and back-center(bc).
The default is:
sl=-90, fl=-30, fc=0, fr=30, sr=90, bc=180
## layout_STEREO:
# Sets the speaker layout when using stereo output. Values are specified in
# degrees, where 0 is straight in front, negative goes left, and positive goes
# right. The values must define a circular pattern, starting with the back-
# left at the most negative, around the front to back-center. Unspecified
# speakers will remain at their default position. Available speakers are
# front-left(fl) and front-right(fr).
#layout_STEREO = fl=-90, fr=90
layout_71CHN = # Sets the speaker layout when using 7.1 output. Available
speakers are back-left(bl), side-left(sl), front-left(fl),
front-center(fc), front-right(fr), side-right(sr), and
back-right(br).
The default is:
bl=-150, sl=-90, fl=-30, fc=0, fr=30, sr=90 br=150
## laytout_QUAD:
# Sets the speaker layout when using quadriphonic output. Available speakers
# are back-left(bl), front-left(fl), front-right(fr), and back-right(br).
#layout_QUAD = bl=-135, fl=-45, fr=45, br=135
## layout_51CHN:
# Sets the speaker layout when using 5.1 output. Available speakers are back-
# left(bl), front-left(fl), front-center(fc), front-right(fr), and back-
# right(br).
#layout_51CHN = bl=-110, fl=-30, fc=0, fr=30, br=110
[alsa] # ALSA backend stuff
device = default # Sets the device name for the default playback device.
# Default is default
## layout_61CHN:
# Sets the speaker layout when using 6.1 output. Available speakers are side-
# left(sl), front-left(fl), front-center(fc), front-right(fr), side-right(sr),
# and back-center(bc).
#layout_61CHN = sl=-90, fl=-30, fc=0, fr=30, sr=90, bc=180
periods = 0 # Sets the number of update buffers for playback. A value of 0
# means auto-select. Default is 0
## layout_71CHN:
# Sets the speaker layout when using 7.1 output. Available speakers are back-
# left(bl), side-left(sl), front-left(fl), front-center(fc), front-right(fr),
# side-right(sr), and back-right(br).
#layout_71CHN = bl=-150, sl=-90, fl=-30, fc=0, fr=30, sr=90, br=150
capture = default # Sets the device name for the default capture device.
# Default is default
##
## ALSA backend stuff
##
[alsa]
mmap = true # Sets whether to try using mmap mode (helps reduce latencies and
# CPU consumption). If mmap isn't available, it will automatically
# fall back to non-mmap mode. True, yes, on, and non-0 values will
# attempt to use mmap. 0 and anything else will force mmap off.
# Default is true.
## device:
# Sets the device name for the default playback device.
#device = default
[oss] # OSS backend stuff
device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
## capture:
# Sets the device name for the default capture device.
#capture = default
periods = 4 # Sets the number of update buffers. Default is 4
## mmap:
# Sets whether to try using mmap mode (helps reduce latencies and CPU
# consumption). If mmap isn't available, it will automatically fall back to
# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0
# and anything else will force mmap off.
#mmap = true
capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp
##
## OSS backend stuff
##
[oss]
[solaris] # Solaris backend stuff
device = /dev/audio # Sets the device name for Solaris output. Default is
# /dev/audio
## device:
# Sets the device name for OSS output.
#device = /dev/dsp
[dsound] # DirectSound backend stuff
periods = 4 # Sets the number of updates for the output buffer. Default is 4
## capture:
# Sets the device name for OSS capture.
#capture = /dev/dsp
[winmm] # Windows Multimedia backend stuff
# Nothing yet...
##
## Solaris backend stuff
##
[solaris]
[port] # PortAudio backend stuff
device = -1 # Sets the device index for output. Negative values will use the
# default as given by PortAudio itself. Default is -1
## device:
# Sets the device name for Solaris output.
#device = /dev/audio
periods = 4 # Sets the number of update buffers. Default is 4
##
## DirectSound backend stuff
##
[dsound]
[wave] # Wave File Writer stuff
file = # Sets the filename of the wave file to write to. An empty name
# prevents the backend from opening, even when explicitly requested.
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
# Default is empty
##
## Windows Multimedia backend stuff
##
[winmm]
##
## PortAudio backend stuff
##
[port]
## device:
# Sets the device index for output. Negative values will use the default as
# given by PortAudio itself.
#device = -1
##
## PulseAudio backend stuff
##
[pulse]
##
## Wave File Writer stuff
##
[wave]
## file:
# Sets the filename of the wave file to write to. An empty name prevents the
# backend from opening, even when explicitly requested.
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
#file =
View File
+3
View File
@@ -22,6 +22,9 @@
/* Define if we have the PortAudio backend */
#cmakedefine HAVE_PORTAUDIO
/* Define if we have the PulseAudio backend */
#cmakedefine HAVE_PULSEAUDIO
/* Define if we have dlfcn.h */
#cmakedefine HAVE_DLFCN_H
+1 -1
View File
@@ -194,7 +194,7 @@ static void printEFXInfo(void)
const char *name;
} effects[] = {
{ AL_EFFECT_EAXREVERB, "EAX Reverb" },
{ AL_EFFECT_REVERB, "Standard Reverb" },
{ AL_EFFECT_REVERB, "Reverb" },
{ AL_EFFECT_CHORUS, "Chorus" },
{ AL_EFFECT_DISTORTION, "Distortion" },
{ AL_EFFECT_ECHO, "Echo" },
+51
View File
@@ -99,6 +99,57 @@ extern "C" {
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATAEXTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
#endif
#ifndef AL_EXT_BUFFER_DATA_STATIC
#define AL_EXT_BUFFER_DATA_STATIC 1
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#endif
#ifndef AL_EXT_sample_buffer_object
#define AL_EXT_sample_buffer_object 1
#define AL_SAMPLE_SOURCE_EXT 0x1040
#define AL_SAMPLE_SINK_EXT 0x1041
#define AL_READ_ONLY_EXT 0x1042
#define AL_WRITE_ONLY_EXT 0x1043
#define AL_READ_WRITE_EXT 0x1044
#define AL_STREAM_WRITE_EXT 0x1045
#define AL_STREAM_READ_EXT 0x1046
#define AL_STREAM_COPY_EXT 0x1047
#define AL_STATIC_WRITE_EXT 0x1048
#define AL_STATIC_READ_EXT 0x1049
#define AL_STATIC_COPY_EXT 0x104A
#define AL_DYNAMIC_WRITE_EXT 0x104B
#define AL_DYNAMIC_READ_EXT 0x104C
#define AL_DYNAMIC_COPY_EXT 0x104D
typedef ALvoid (AL_APIENTRY*PFNALGENDATABUFFERSEXTPROC)(ALsizei n,ALuint *puiBuffers);
typedef ALvoid (AL_APIENTRY*PFNALDELETEDATABUFFERSEXTPROC)(ALsizei n, const ALuint *puiBuffers);
typedef ALboolean (AL_APIENTRY*PFNALISDATABUFFEREXTPROC)(ALuint uiBuffer);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERDATAEXTPROC)(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALuint start, ALsizei length, const ALvoid *);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALuint start, ALsizei length, ALvoid *);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERFEXTPROC)(ALuint buffer, ALenum eParam, ALfloat flValue);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERFVEXTPROC)(ALuint buffer, ALenum eParam, const ALfloat* flValues);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERIEXTPROC)(ALuint buffer, ALenum eParam, ALint lValue);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERIVEXTPROC)(ALuint buffer, ALenum eParam, const ALint* plValues);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERFEXTPROC)(ALuint buffer, ALenum eParam, ALfloat *pflValue);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERFVEXTPROC)(ALuint buffer, ALenum eParam, ALfloat* pflValues);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERIEXTPROC)(ALuint buffer, ALenum eParam, ALint *plValue);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERIVEXTPROC)(ALuint buffer, ALenum eParam, ALint* plValues);
typedef ALvoid (AL_APIENTRY*PFNALSELECTDATABUFFEREXTPROC)(ALenum target, ALuint uiBuffer);
typedef ALvoid* (AL_APIENTRY*PFNALMAPDATABUFFEREXTPROC)(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access);
typedef ALvoid (AL_APIENTRY*PFNALUNMAPDATABUFFEREXTPROC)(ALuint uiBuffer);
#endif
#ifndef ALC_EXT_disconnect
#define ALC_EXT_disconnect 1
#define ALC_CONNECTED 0x313
#endif
#ifndef ALC_EXT_thread_local_context
#define ALC_EXT_thread_local_context 1
typedef ALCboolean (ALCAPIENTRY*PFNALCMAKECURRENTPROC)(ALCcontext *context);
typedef ALCcontext* (ALCAPIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
#endif
#ifdef __cplusplus
}
#endif