Compare commits

..

973 Commits

Author SHA1 Message Date
Chris Robinson b483b1e380 Release 1.13 2011-02-15 12:10:44 -08:00
Chris Robinson d9126eeb2c Finalize the loop points extension as AL_SOFT_loop_points 2011-02-09 22:54:12 -08:00
Chris Robinson d8048e136f BufferFreq doesn't need to be a float 2011-02-09 11:19:33 -08:00
Chris Robinson fd64fea279 Use the correct winmm device ID type 2011-02-08 10:33:18 -08:00
Chris Robinson 667fd24c84 Add an option to force usage of static MSVC runtimes 2011-02-08 00:34:25 -08:00
Chris Robinson 9ffb38d6be Prevent unused variable warnings when monotonic clock isn't available 2011-02-08 00:22:22 -08:00
Chris Robinson 13397feccf Don't inline CalcLimitedHfRatio 2011-02-07 23:58:40 -08:00
Chris Robinson 57b05fb6d4 Add a missing enum value for PA_API_VERSION 11 2011-02-07 23:53:07 -08:00
Chris Robinson 41a2c25b5a Include cguid.h for GUID_NULL 2011-02-07 22:46:54 -08:00
Chris Robinson b214249290 Check for internal visibility, since that's what is used 2011-02-07 13:55:48 -08:00
Chris Robinson 8dad1c382b Add the standard "revision" number to the library name 2011-02-06 02:39:22 -08:00
Chris Robinson 6713a47d38 Fix looping on loop points 2011-02-06 01:07:37 -08:00
Chris Robinson 02e0223fe8 Re-enable channel-config-specific layout options 2011-01-23 23:57:39 -08:00
Chris Robinson 6c4add67e1 Don't duplicate the device list append function 2011-01-23 23:16:55 -08:00
Chris Robinson 2b7324c06e Avoid using a variable for array sizes and const variable initialization 2011-01-23 22:30:18 -08:00
Chris Robinson c95bd6cadf Fix loop handling when traversing the buffer queue backwards 2011-01-23 15:04:42 -08:00
Chris Robinson d73694d3e6 More improvements to the AudioIO backend 2010-12-09 23:53:32 -08:00
Chris Robinson 5d607f9484 Better check format type returned by AUDIO_SETINFO 2010-12-09 23:47:11 -08:00
Chris Robinson 816c38e9e4 Add signed 8-bit output to the AudioIO backend 2010-12-09 23:43:29 -08:00
Chris Robinson 09130e5dcd Fix some AudioIO backend warnings 2010-12-09 23:41:54 -08:00
Chris Robinson b87447787a Cleanup some ok() macros 2010-12-09 23:32:47 -08:00
Chris Robinson 5a548f8366 Another fix for float-to-int conversions 2010-12-09 22:47:06 -08:00
Chris Robinson 023658605e Constify some variables 2010-12-09 19:47:08 -08:00
Chris Robinson 031111014b Be consistent with variable name use 2010-12-09 18:09:47 -08:00
Chris Robinson b5b9303e66 Fix up some conversions 2010-12-09 17:37:57 -08:00
Chris Robinson 3deaa2fad3 Combine stereo and multi-channel templates 2010-12-09 17:14:12 -08:00
Chris Robinson c3cd4c80b2 Use a matrix when rendering to the dry buffer 2010-12-09 16:37:23 -08:00
Chris Robinson be3f3c4bf0 Make better use of the type range when converting from float 2010-12-09 05:06:29 -08:00
Chris Robinson d1ca8b4470 Use simple loops instead of several explicit lines for the mono mixer 2010-12-09 05:05:42 -08:00
Chris Robinson 72e3386c6a Be a bit more generic with the multi-channel mixer loops 2010-12-09 04:41:52 -08:00
Chris Robinson 4010a6b745 Remove some now-unused functions 2010-12-08 02:56:24 -08:00
Chris Robinson 0218957eb5 Use "internal" visibility by default
All functions callable by apps, directly or indirectly (eg, through function
pointers), are marked as "protected", and internal visibility can provide
benefits over hidden when we know functions won't be called by other modules.
2010-12-08 02:32:09 -08:00
Chris Robinson cd65ab7dfa Add an IMA4 encoder 2010-12-05 03:34:19 -08:00
Chris Robinson c4adf541c1 Set the playing flag to TRUE when the dsound buffer starts playing 2010-12-04 20:22:12 -08:00
Chris Robinson 88e3a22772 Separate device format into 'channel config' and 'sample type' components 2010-12-04 19:50:00 -08:00
Chris Robinson 191803ad53 Fix wave and null device calculations when the timer wraps 2010-12-03 23:48:59 -08:00
Chris Robinson 1b7be672fa No need to clamp the app-specified pitch 2010-12-03 23:08:26 -08:00
Chris Robinson 9581325b9c Rename SrcFmt -> UserFmt 2010-12-03 22:33:41 -08:00
Chris Robinson 59990acc2a Add functions to write (signed) byte and ushort samples to devices 2010-12-02 16:36:37 -08:00
Chris Robinson 0bf7716332 Remove incomplete EXT_buffer_sub_data, as it's (temporarily) superceded by SOFT_buffer_sub_data
The EXT version can come back when other implementations take an interest
2010-12-02 01:46:43 -08:00
Chris Robinson 3339e5dc6a Use memcpy to copy a string instead of sprintf 2010-12-02 01:12:49 -08:00
Chris Robinson 30b3f68ddf Make a function static 2010-12-02 01:05:29 -08:00
Chris Robinson 75552f2765 Remove unused macro 2010-12-01 23:21:18 -08:00
Chris Robinson 4a0bf9fd44 Template-ize the device buffer writing functions 2010-12-01 21:50:49 -08:00
Chris Robinson fa28098a83 Some general cleanups 2010-12-01 20:34:29 -08:00
Chris Robinson 646409cbdf Don't limit IMA4 decoding to 2 channels 2010-12-01 18:36:07 -08:00
Chris Robinson 9e8fb89a52 Rename OUTPUTCHANNELS to something more descriptive 2010-12-01 18:33:17 -08:00
Chris Robinson 14441e0e53 Rename some variables 2010-12-01 14:19:57 -08:00
Chris Robinson 7f5814c4d8 Use min/max to clamp the IMA4 sample and index values 2010-12-01 14:07:21 -08:00
Chris Robinson e3afc3587e Fix handling of -32768 in the muLaw encoder 2010-12-01 02:24:39 -08:00
Chris Robinson 8a52c44d15 Don'f fail if realloc returns NULL for 0 sizes 2010-12-01 02:00:41 -08:00
Chris Robinson e6e18732b5 Make sure the muLaw sample encoder is inlined 2010-11-30 18:06:54 -08:00
Chris Robinson 3f8ae8f1ce Fix IMA4 decoding 2010-11-30 16:54:30 -08:00
Chris Robinson a79129835c Fix some comments and line spacing 2010-11-30 13:04:48 -08:00
Chris Robinson 6fcaecdc9f Fix int-to-double conversion 2010-11-30 12:26:37 -08:00
Chris Robinson 8dc8090888 Make muLaw decoding work similar to encoding 2010-11-30 01:26:43 -08:00
Chris Robinson 4db2f1ec7d Implement a muLaw encoder 2010-11-30 01:20:40 -08:00
Chris Robinson 06fa030260 Rename the IMA4 block decoder function 2010-11-30 01:00:37 -08:00
Chris Robinson 018f9fc278 Handle all channel configurations for double 2010-11-30 00:32:13 -08:00
Chris Robinson c0f6d46cd8 Allow LoadData to handle IMA4 data 2010-11-30 00:28:02 -08:00
Chris Robinson 8e43b1fe04 Let the storable format enum values share the input format enum values where they overlap 2010-11-29 23:57:07 -08:00
Chris Robinson 04df919a1c Clean up muLaw format loading a bit 2010-11-29 23:46:49 -08:00
Chris Robinson f82e628f08 Allow converting IMA4 to types other than short 2010-11-29 22:55:46 -08:00
Chris Robinson 07a7c03adb Check for a couple missing input formats and remove an unneeded default case 2010-11-29 22:07:07 -08:00
Chris Robinson e800f8c0a7 Let DecomposeInputType verify the format passed to alBufferSubDataSOFT 2010-11-29 22:01:54 -08:00
Chris Robinson d02dbef9d2 Pass the input channel config and sample type to LoadData 2010-11-29 21:55:47 -08:00
Chris Robinson 55262bc6e9 Make the decompose functions return false when given an unhandled format 2010-11-29 20:34:33 -08:00
Chris Robinson 51ed22afb9 Combine two switch blocks 2010-11-29 20:17:15 -08:00
Chris Robinson 0cf32e2946 Reorder some parameters for consistency 2010-11-29 19:48:18 -08:00
Chris Robinson 693ab4d8bc Fix source offset calculations 2010-11-29 19:36:33 -08:00
Chris Robinson e4869b447c Store the decomposed source format in the buffer 2010-11-29 19:27:33 -08:00
Chris Robinson 547f356131 Keep a handle on the buffer with the format when queueing new buffers 2010-11-29 17:35:22 -08:00
Chris Robinson 017ab1b3fd Add IMA4 as a source data type 2010-11-29 17:14:22 -08:00
Chris Robinson 07ef566de1 Add support for (unsigned) int input formats 2010-11-29 17:00:22 -08:00
Chris Robinson 3c8a29a179 Reorder and rename parameters for the format decomposition functions 2010-11-29 15:19:39 -08:00
Chris Robinson f74032d244 Uninline a couple more functions 2010-11-29 15:01:27 -08:00
Chris Robinson eb489ac886 Store double formats as float
The mixer will cut it down to float anyway, so it's unnecessary and needlessly
creates more mixer functions
2010-11-28 23:07:57 -08:00
Chris Robinson 986628b8b2 Avoid temp storage 2010-11-28 22:50:27 -08:00
Chris Robinson da4f5c6f96 Uninline some functions
Also add -Winline to the compiler command line to watch for future inline problems
2010-11-28 19:52:17 -08:00
Chris Robinson f09ae196a8 Avoid making Resampler[Pre]Padding static 2010-11-28 17:37:14 -08:00
Chris Robinson 3e702ae2bc Improve static builds with MinGW 2010-11-28 16:19:11 -08:00
Chris Robinson 490d1c6a8e Prefer GCC's constructor, even in Windows 2010-11-28 14:27:07 -08:00
Chris Robinson 0e748d98d5 Rename some stuff for consistency 2010-11-28 13:08:51 -08:00
Chris Robinson c41e893361 Don't store the internal format in the buffer
The type and channel config are good enough
2010-11-28 12:53:35 -08:00
Chris Robinson 2fd8d6916b Support rear formats directly in the mixer 2010-11-27 22:55:20 -08:00
Chris Robinson b4eaf1ab5a Avoid a potential overflow when setting the source offset 2010-11-27 22:22:14 -08:00
Chris Robinson 3c8e9a7f24 Clean up the source byte offset code 2010-11-27 22:13:29 -08:00
Chris Robinson 67ec72284d Remove some unneeded muLaw special cases 2010-11-27 22:06:51 -08:00
Chris Robinson 754a122aa0 Support muLaw with LoadData 2010-11-27 22:00:24 -08:00
Chris Robinson 0486d633c6 Remove an unnecessary assert 2010-11-27 20:41:09 -08:00
Chris Robinson 09b063002b Be much more flexible with loading and converting buffer data 2010-11-27 20:33:37 -08:00
Chris Robinson 8828f4d0e5 Don't inline the decompose function 2010-11-27 15:37:51 -08:00
Chris Robinson 9495cf71fd Decompose input buffer formats and use it when converting uncompressed data 2010-11-27 15:33:33 -08:00
Chris Robinson 4d0f70439c Rename a function 2010-11-27 14:30:13 -08:00
Chris Robinson d3bb5d4fcb Add a basic WaveOut device
It can still use more work, but it seems to work
2010-11-27 14:13:40 -08:00
Chris Robinson 61315d4dfb Shorten a couple really long lines 2010-11-27 00:51:21 -08:00
Chris Robinson 2a123a4760 Support 64-bit double buffers directly 2010-11-27 00:32:53 -08:00
Chris Robinson 4689ffb72d muLaw converts to 16-bit, not float 2010-11-27 00:17:19 -08:00
Chris Robinson d2895c7985 Use the enums in a couple more places 2010-11-27 00:15:07 -08:00
Chris Robinson 6abb9d151e Use enums when selecting the mixer 2010-11-26 23:42:30 -08:00
Chris Robinson 08827efae3 Remove an unnecessary 'struct' keyword 2010-11-26 20:35:47 -08:00
Chris Robinson 16c05d2c05 Avoid some more code duplication 2010-11-26 20:22:14 -08:00
Chris Robinson 4d4d699780 Fix step calculations 2010-11-26 20:17:05 -08:00
Chris Robinson ca1ec4b221 Fix some comments 2010-11-26 18:01:29 -08:00
Chris Robinson facb922f3e Properly clamp high pitch values 2010-11-26 17:47:43 -08:00
Chris Robinson d7987677ac Subtract the fractional position separately 2010-11-26 15:51:13 -08:00
Chris Robinson 5fbbfa482f Rename some variables to be clearer 2010-11-26 12:59:45 -08:00
Chris Robinson 7287b5cd3c Make the buffer padding size dependent on the resampler 2010-11-26 02:53:15 -08:00
Chris Robinson 0692cf304d Don't allocate padding with the buffer itself 2010-11-26 02:31:17 -08:00
Chris Robinson 88ebe7e4c1 Decrease the buffer size more 2010-11-26 02:14:11 -08:00
Chris Robinson d647ed60e8 Convert a few divisions to multiplications 2010-11-26 01:35:40 -08:00
Chris Robinson 1cb29ece08 Make a FRACTIONONE macro, and use it 2010-11-26 01:21:46 -08:00
Chris Robinson de8b7fbc5f Share the interpolation functions and use them in the reverb effect 2010-11-26 01:07:54 -08:00
Chris Robinson 98d78f7ff9 Slightly improve channel gain calculations 2010-11-26 00:24:54 -08:00
Chris Robinson 3d1eb7dcad Add a missing break statement 2010-11-25 23:13:50 -08:00
Chris Robinson e1c0b5ea24 Call MixSource directly, instead of through a function pointer 2010-11-25 23:09:18 -08:00
Chris Robinson 30820c1bde Add a cubic resampler 2010-11-25 23:05:44 -08:00
Chris Robinson 46b9802902 Force the point resampler when the source plays at normal speed 2010-11-25 22:15:38 -08:00
Chris Robinson b6fb28de1a Pass a pointer to the samplers so they can read just the samples they need 2010-11-25 22:04:17 -08:00
Chris Robinson 17fc4ba5e3 Add "pre-padding" to the temp buffer
This will help to implement resamplers that want previous samples
2010-11-25 21:42:15 -08:00
Chris Robinson 596514f7aa Make the buffer queue a double-linked list 2010-11-25 18:30:57 -08:00
Chris Robinson 6e3a6f90e9 Be less wave-in-specific in the winmm backend 2010-11-25 17:37:34 -08:00
Chris Robinson fbd6439bd2 Make the first enumerated DirectSound device use the default, and fix the name 2010-11-25 14:35:32 -08:00
Chris Robinson f72c735f9e Make sure the target buffer size is frame aligned 2010-11-25 14:23:03 -08:00
Chris Robinson 9b23fc5db8 Minor rework of the template macros 2010-11-25 14:07:52 -08:00
Chris Robinson aaff188b3b Remove the cosine resampler
It's too slow when auxiliary sends are being used.
2010-11-25 13:49:51 -08:00
Chris Robinson 2595d85cca Double-up the interpolation functions (and make them use doubles) 2010-11-25 13:45:35 -08:00
Chris Robinson 2c96c29938 Rename some "template" functions 2010-11-25 13:22:54 -08:00
Chris Robinson 65919b7037 Always make sure there's a sample available to mix, for pending click removal 2010-11-25 13:17:51 -08:00
Chris Robinson f1bb7c33f1 Fix a bunch of comments 2010-11-25 12:07:12 -08:00
Chris Robinson 8e7a4046d0 Don't "convert" LOKI quad to MCFORMATS quad 2010-11-25 11:49:35 -08:00
Chris Robinson f4e0c6a348 Use a temporary stack buffer to store the source buffer data to be mixed
This makes it much easier to pack the playable buffer data so that it's a
continuous data stream. This could normally be broken up otherwise, such as
when using loop points or small queued buffers.
Currently it defaults to a 16KB stack buffer, but this can be overridden at
compile time.
2010-11-25 11:16:19 -08:00
Chris Robinson 885a5e9f90 Use 0-based access for the buffer data 2010-11-24 20:44:21 -08:00
Chris Robinson 22e3e9a18b Support 8-bit sample data in the mixer 2010-11-24 19:41:25 -08:00
Chris Robinson 445cde2dd4 Check the sample byte size after the resampler 2010-11-24 17:23:09 -08:00
Chris Robinson 3dd58cf765 Get rid of a useless union 2010-11-24 17:10:41 -08:00
Chris Robinson cd87061749 Change the mixer macros to declare functions 2010-11-24 17:07:50 -08:00
Chris Robinson 1311e051d9 Set mixer sample pos and frac when needed 2010-11-24 14:54:46 -08:00
Chris Robinson c9363832fe Fully progress the source to a stopped state when no buffers are playable 2010-11-24 10:16:53 -08:00
Chris Robinson 6ab22e7cbb Reorder some stored source params 2010-11-24 10:01:50 -08:00
Chris Robinson bb13f7f234 Make sure the buffer padding is always cleared before looking for the next buffer 2010-11-24 07:20:41 -08:00
Chris Robinson 13ba253aec Calculate ALSA buffer length with the other values 2010-11-23 07:24:27 -08:00
Chris Robinson c58469e234 Handle the timer wrapping in the wave and null output devices 2010-11-21 11:34:16 -08:00
Chris Robinson 57a03bc2b5 Use helpers to write 16- and 32-bit values 2010-11-21 06:54:41 -08:00
Chris Robinson a7b4e0b5c5 Get rid of the device timer stuff 2010-11-21 06:32:59 -08:00
Chris Robinson bbb45e326c Avoid temporary float variables 2010-11-21 03:58:37 -08:00
Chris Robinson dfe3e402a8 Pass the data pointer and proper sampler to the mixer macro 2010-11-21 03:33:33 -08:00
Chris Robinson e884da50ea Move aluMixData back to ALu.c 2010-11-21 02:51:18 -08:00
Chris Robinson 4c576631ad Hide AL_EXTX_sample_buffer_object
It hasn't been going anywhere, and it's current use is dubious. Leave the code
in for now, but it may be removed later.
2010-11-21 02:36:34 -08:00
Chris Robinson 5f6f046d25 Use a double when converting millisecond offsets to byte offsets 2010-11-07 21:41:04 -08:00
Chris Robinson 65e033c64b Increase the max number of source sends to 4, and decrease the default to 1 2010-11-06 15:08:54 -07:00
Chris Robinson 07346da740 Use the number of sends the device is configured for in more places 2010-11-06 14:27:33 -07:00
Chris Robinson c95f182a90 Remove unnecessary comments and reorder some lines 2010-11-06 14:07:30 -07:00
Chris Robinson 289c74788e Use a switch to select the appropriate channel-count mixer 2010-11-06 12:21:46 -07:00
Chris Robinson 65a8d9278d Declare a variable where it's used 2010-11-01 12:44:56 -07:00
Chris Robinson 887c830d56 Remove explicit use of -funroll-loops
I'm not sure this really helps much.
2010-10-15 15:21:23 -07:00
Chris Robinson 6db4e08efb Fix fpu state handling with _controlfp 2010-10-15 10:35:47 -07:00
Chris Robinson 4f81bce800 Improve a macro to reference its parameter 2010-10-11 12:24:28 -07:00
Chris Robinson 932fcfa8bf Fix 64-bit compilation 2010-10-11 12:24:07 -07:00
Chris Robinson 314832e35a Rename a couple more variables 2010-10-10 04:00:50 -07:00
Chris Robinson 6a9dd185e6 Improve naming and placement of a couple variables 2010-10-10 03:47:57 -07:00
Chris Robinson 2172827f43 Simplify a calculation 2010-10-09 15:24:24 -07:00
Chris Robinson 90e9cd970a Check resampler mode first when selecting the mixer 2010-09-26 13:53:02 -07:00
Chris Robinson 845ca95888 Get a variable where it's needed 2010-09-26 13:30:46 -07:00
Chris Robinson 92d8d2f8a4 Pass the device to the mix function and localize the dry mix and click buffers 2010-09-26 12:23:22 -07:00
Chris Robinson 7cd52b2857 Clarify a check 2010-09-26 01:29:28 -07:00
Chris Robinson 9fbd6c6c3f Make the SourceMix function a method of the ALsource struct 2010-09-26 01:15:27 -07:00
Chris Robinson 08fdc5fa98 Avoid updating the source in MixSource 2010-09-25 23:49:57 -07:00
Chris Robinson 7e362249ff Convert shorts so that 0 remains 0 2010-09-25 21:13:40 -07:00
Chris Robinson 9fa2db0227 Don't try to open the ALSA device a second time if the first fails 2010-09-25 20:20:10 -07:00
Chris Robinson 4c75a72a90 Avoid some code duplication 2010-09-25 20:18:07 -07:00
Chris Robinson a0b2778161 Localize more variables and remove unnecessary ones 2010-09-25 14:19:36 -07:00
Chris Robinson bc6d94cd25 Avoid sampling beyond the end of the loop 2010-09-24 23:32:50 -07:00
Chris Robinson e70141e57b Localize some variables to the mixer macros
The hope here is to help break the mixer loops into separate functions, so the
macro expansion doesn't cause the MixSource function to explode in size and
kill compilation speed.
2010-09-24 23:24:01 -07:00
Chris Robinson 2e70b82eaa Use separate mixing loops for the dry path and wet paths
This will increase CPU use a bit for sources that use auxiliary sends
(particularly with the cosine resampler), but it makes it more scalable when
adding more sends per source. Additionally, it will improve performance of
sources that don't use auxiliary sends.

The cosine resampler can probably be improved by using a lookup table instead
of calling cos() as there are 14 bits of fractional precision, so a 16384-
element float array would cover it all. This can also be reduced to a half or
quarter size if the precision loss is found to be acceptable.
2010-09-24 18:29:49 -07:00
Chris Robinson 117ed52091 Better protect against negative attenuation 2010-09-24 13:16:09 -07:00
Chris Robinson e9d5e53dbe Use ALfloat for the dry mix buffer 2010-09-23 17:44:02 -07:00
Chris Robinson e308694521 Remove an unnecessary variable 2010-09-23 16:51:30 -07:00
Chris Robinson 7e498012ff Rename some variables to be less confusing 2010-09-23 16:49:33 -07:00
Chris Robinson f98bf32be8 Fix line indentation 2010-09-23 15:08:30 -07:00
Chris Robinson 0f2ed8c84d Be consistent with a variable's use 2010-09-23 13:49:21 -07:00
Chris Robinson 8d67cdfaab Convert float to short similar to short to float 2010-09-23 08:43:39 -07:00
Chris Robinson 67ba924ed3 Store and mix signed 16-bit samples 2010-09-22 23:38:06 -07:00
Chris Robinson 764cfb6a0d Allow the mixing loop to access the different sample formats 2010-09-22 20:53:04 -07:00
Chris Robinson 4e3c945093 Compact some reused code 2010-09-22 18:49:46 -07:00
Chris Robinson 8558bc1d41 Allow accessing the buffer data as multiple data types in the mixer
Also reduces a bunch of indentation
2010-09-22 17:19:35 -07:00
Chris Robinson 03f56419d0 Duplicate stereo sources by default
The mixer is smart enough now to handle proper volume adjustments depending on
the number of output speakers
2010-09-22 11:09:34 -07:00
Chris Robinson 3ee9d24c3f Use separate macros for the different mixing loops 2010-09-22 09:38:24 -07:00
Chris Robinson 9b1ad6c873 Consolidate some code 2010-09-21 19:49:47 -07:00
Chris Robinson 97daaade8a Reduce some more indentation 2010-09-21 16:54:33 -07:00
Chris Robinson 8a1d5a21c3 Reduce some indentation 2010-09-21 15:12:08 -07:00
Chris Robinson 301a8ba3a4 Improve some range checks 2010-09-21 14:41:43 -07:00
Chris Robinson 2d4453968d Implement AL_SOFT_buffer_sub_data using the current AL_EXT_buffer_sub_data spec
This extension can be useful for some applications, but a full EXT version may
not be ready for some time. Using the SOFT moniker will help differentiate it
in case changes need to be done for the EXT version.
2010-09-21 09:43:35 -07:00
Chris Robinson a2580a85a8 Improve range checking for BufferSubData 2010-09-19 14:00:55 -07:00
Chris Robinson 8a0e15ff37 Store air absorption factor locally 2010-09-12 00:10:33 -07:00
Chris Robinson 8953a73fb1 Prevent effectiveDist from going negative 2010-09-11 23:57:15 -07:00
Chris Robinson 1a2883ae9a Pass dry-path click buffers as parameters to MixSource 2010-09-11 23:43:12 -07:00
Chris Robinson a2358ffc41 Source positions at and after the end of the buffer queue go back to 0 2010-09-09 18:27:14 -07:00
Chris Robinson 33eb2786f8 Avoid another non-descript incrementing variable 2010-09-09 16:47:54 -07:00
Chris Robinson c8ec4fd505 Avoid using a single-letter iterator value 2010-09-09 14:53:14 -07:00
Chris Robinson fe98ab5398 Combine multiple checks into one 2010-09-08 17:29:16 -07:00
Chris Robinson 76be7eb1e7 Better protect against sample overflow when converting float to short 2010-09-08 16:26:19 -07:00
Chris Robinson 6e32812bc1 Remove unnecessary check 2010-09-07 22:38:29 -07:00
Chris Robinson 50a7be6385 Fix comparison check 2010-09-07 22:23:37 -07:00
Chris Robinson 3763c95784 Add missing else 2010-09-07 16:36:42 -07:00
Chris Robinson 5fa5252648 Watch for a few more negative sizes 2010-09-07 16:33:17 -07:00
Chris Robinson 1e82561a22 Check for invalid negative sizes 2010-09-07 16:18:24 -07:00
Chris Robinson ba32a52bb6 Remove unused struct member 2010-09-07 16:07:35 -07:00
Chris Robinson 6027fda0ce Combine two arrays into one 2010-08-16 16:07:44 -07:00
Chris Robinson e5cae87502 Handle clicks by watching changes between updates 2010-08-16 14:53:21 -07:00
Chris Robinson ba0ec1b4ba Use the correct value to dereference an array 2010-08-16 11:42:18 -07:00
Chris Robinson 2acd6f52f1 Add a bit more information to the README 2010-08-15 16:55:11 -07:00
Chris Robinson b520228bc6 Consolidate some click removal calculations 2010-08-15 15:55:02 -07:00
Chris Robinson 343a8241ab Use a multiplier instead of if checks 2010-08-15 15:09:38 -07:00
Chris Robinson 00525274a0 Add click removal for wet sends 2010-08-15 14:52:12 -07:00
Chris Robinson 2915d9dbd9 Use click removal to handle harsh panning/volume changes 2010-08-15 00:19:38 -07:00
Chris Robinson 0c49e5ba56 Use click removal when starting a source 2010-08-14 22:59:55 -07:00
Chris Robinson b65bc45236 Add a corrective, click-remval sample value offset
This will hopefully be more effective and rebust at removing clicks and pops,
particularly from starts and stops in the middle of a sound. Based on an idea
by Ben Davis.
2010-08-14 21:30:14 -07:00
Chris Robinson 94b7e5a227 Rename Null Output to No Output 2010-08-13 22:06:38 -07:00
Chris Robinson 928572d384 Start the device when creating a context without specified attributes 2010-08-12 17:24:55 -07:00
Chris Robinson 2d1988bb6f Output on available channels only, for the echo and modulator effects 2010-08-09 06:12:00 -07:00
Chris Robinson e007dc3614 Fix early/late reverb panning, and only output reverb on available channels 2010-08-09 05:11:58 -07:00
Chris Robinson 2ed929eadc Update device parameters using a separate function 2010-08-09 00:28:48 -07:00
Chris Robinson f1924fa7ea Decrement context count when it's removed from the list 2010-08-08 02:48:28 -07:00
Chris Robinson df822513fa Don't re-init and re-allocate some stuff when the device is left running 2010-08-07 09:13:51 -07:00
Chris Robinson 762bdaeee1 Panning init cleanup 2010-08-07 08:49:29 -07:00
Chris Robinson 8003278a55 Combine non-attenuated source calculation functions 2010-08-07 06:57:31 -07:00
Chris Robinson 5f22d30fc9 Calculate the source stepping value with the param calculations 2010-08-07 05:43:16 -07:00
Chris Robinson d6dc855511 Set up increment once 2010-08-07 02:32:16 -07:00
Chris Robinson 8f49f2c25e Forward some more source properties instead of duplicating 2010-08-07 01:35:43 -07:00
Chris Robinson f4304ca062 Calculate the actual stepping value in the source update method 2010-08-07 00:38:02 -07:00
Chris Robinson 044662e4b7 Calculate gain steps once during a source mix 2010-08-06 07:55:00 -07:00
Chris Robinson d9d8319c22 Effectslot's Effectstate should never be NULL 2010-08-06 04:52:34 -07:00
Chris Robinson 56b094767b Remove an unnecessary check
The number of buffers played should never exceed the buffer count when playing,
and the buffer list is used later on regardless
2010-08-06 01:14:37 -07:00
Chris Robinson 98bc60cfb7 Combine stereo and stereo-duplicate mixers
Use a separate update method for stereo sources to the set appropriate channel
gains
2010-08-05 01:07:20 -07:00
Chris Robinson 2aacca76de Improve a warning message 2010-08-04 06:18:23 -07:00
Chris Robinson aea615edb3 Prevent re-probing while opening a Pulse device if no devices were found 2010-08-04 05:07:56 -07:00
Chris Robinson f6b2dfd09f Only except a NULL device name for Pulse if some devices were found 2010-08-04 04:56:07 -07:00
Chris Robinson 7f9bcfbc7d Do not enumerate PulseAudio devices if a context fails to connect 2010-08-04 04:21:39 -07:00
Chris Robinson 22cc5af1fe pa_context_errno can return a positive value 2010-08-04 04:11:38 -07:00
Chris Robinson 0dc3f1984e Move the core mixer functions to a separate source file 2010-08-03 23:19:36 -07:00
Chris Robinson e74976e645 Use a callback to specify the source update method 2010-08-03 23:10:00 -07:00
Chris Robinson 91278608c5 Add some spacing 2010-08-03 01:44:52 -07:00
Chris Robinson 8e2d765671 Move active source iteration to aluMixData 2010-08-03 01:09:02 -07:00
Chris Robinson 2af39e51f8 Separate speaker/panning initialization into another source file 2010-08-03 00:21:36 -07:00
Chris Robinson 1504cf8812 Use millisecond resolution for the Null and Wave Writer backends 2010-08-02 22:34:19 -07:00
Chris Robinson 3bece35bbd Prevent getting bad time values when pa_stream_get_time fails
Also makes sure that reported time won't go backwards
2010-08-02 22:27:32 -07:00
Chris Robinson ae41ad5d1e Use a better method to time the Null and Wave Writer backends
This better compensates for precision loss when converting milliseconds to the
sample rate
2010-08-02 20:04:52 -07:00
Chris Robinson ee61f7a55c Make sure to request a tlength that's at least minreq*2
And warn if Pulse returns a minreq that's too large
2010-08-02 17:24:40 -07:00
Chris Robinson 241ddf76d4 Enforce the device time to be a multiple of the reported resolution 2010-08-01 16:31:00 -07:00
Chris Robinson fe6e73ede9 Be a bit more verbose when a device fails to open 2010-08-01 16:20:28 -07:00
Chris Robinson 8dab4c418c Use Pulse's stream time for the device time 2010-07-31 21:33:46 -07:00
Chris Robinson 41e2c41ecc Combine duplicate lines into the mixing macro 2010-07-31 21:09:59 -07:00
Chris Robinson 30108c7855 Remove an unnecessary variable 2010-07-31 19:14:27 -07:00
Chris Robinson 40ba9db406 Only call Pulse functions from under a lock 2010-07-31 16:07:04 -07:00
Chris Robinson f1f2941511 Add experimental device attributes for apps to query
These will be part of the ALC_EXT_device_time extension. Behavior, values,
etc, are all subject to change.
2010-07-30 20:23:55 -07:00
Chris Robinson d886fb118b Signal the Pulse mainloop on underruns
Otherwise there are (rare) risks of not getting signaled after writing the
amount of free audio data the client knows about, leading to a mixer loop
lockup
2010-07-30 20:20:40 -07:00
Chris Robinson 46d46c49a8 Store the time precision with the device 2010-07-25 12:54:50 -07:00
Chris Robinson 40dd1fb853 Add a backend callback to get the device time
The method should monotonically count the number of nanoseconds the device has
active contexts
2010-07-24 19:14:32 -07:00
Chris Robinson ab77fc14d5 Make killNow volatile 2010-07-24 10:54:12 -07:00
Chris Robinson e0d0edc0fc Close the log file last during shutdown 2010-07-22 09:16:28 -07:00
Chris Robinson 7eb124d99c Keep count of the number of samples played 2010-07-22 08:11:44 -07:00
Chris Robinson 88f236ccd3 Make sure the device is stopped if there was an error setting up the first context 2010-07-21 14:50:39 -07:00
Chris Robinson 34a0c998cd Use CLOCK_MONOTONIC when available 2010-07-18 06:21:16 -07:00
Chris Robinson e658df493a Update PulseAudio using period-sized chunks
To match the behavior of other backends
2010-07-17 23:30:25 -07:00
Chris Robinson b2a257b6b0 Rename examples to utilities
There is only the one, and it more accurately reflects what it is
2010-07-17 01:02:51 -07:00
Chris Robinson cde577690a Set the backend HAVE_ macros off before checking their availability 2010-07-17 00:37:54 -07:00
Chris Robinson c85d53cfbe Remove the commit count from the version number
As it's only updated for releases, it's kinda useless
2010-07-16 00:18:21 -07:00
Chris Robinson 26127cd2f2 Use a long single buffer for WaveIn's capture buffers 2010-07-12 16:37:44 -07:00
Chris Robinson 42d9140afe Check the buffer's original format when queueing on a source 2010-07-12 15:53:11 -07:00
Chris Robinson 52ad28df92 Fix WaveIn device cleanup order 2010-07-08 17:37:35 -07:00
Chris Robinson 58ba5fd0dd Add missing static keyword to WinMM vars 2010-07-08 15:10:59 -07:00
Chris Robinson 71cc91cc4a Use the existing ring buffer methods for WaveIn 2010-07-07 02:47:29 -07:00
Chris Robinson 6db3463d17 Fix backslash alignment for the single-channel mixer macro 2010-07-06 16:32:58 -07:00
Chris Robinson 969818db6f Use a 100ms capture buffer minimum for PulseAudio, with 50ms fragments
This better matches what is given with the WaveIn backend
2010-07-04 16:27:42 -07:00
Chris Robinson d4b191d27d Avoid retrying the requested ALSA format after it failed 2010-07-04 15:48:47 -07:00
Chris Robinson 6b23f2dfa3 snd_pcm_recover should automatically re-prepare the stream as needed 2010-06-16 02:17:41 -07:00
Chris Robinson 17e6840f92 Prevent multiple WinMM devices from getting the same name, as well 2010-06-10 15:54:04 -07:00
Chris Robinson a1f987c016 Improve handling of lost DirectSound buffers 2010-06-09 23:32:35 -07:00
Chris Robinson cff805e0a3 Prevent multiple DirectSound devices from getting the same name, too 2010-06-09 23:11:34 -07:00
Chris Robinson 25a941666a Prevent multiple PulseAudio devices from getting the same name 2010-06-09 18:22:05 -07:00
Chris Robinson 8c59849ea4 Make sure the log file is set before initializing the rest of the lib 2010-06-08 02:02:48 -07:00
Chris Robinson f9e569099c Make the Wave Writer backend optional 2010-06-08 02:01:11 -07:00
Chris Robinson 6fd6e4eacf Remove unused variable 2010-06-07 03:49:21 -07:00
Chris Robinson ce07270973 Remove support for the old 'refresh' config option 2010-06-06 00:53:29 -07:00
Chris Robinson ac05863f72 Make sure the effectslot map is properly initialized 2010-06-06 00:21:13 -07:00
Chris Robinson 7f6df7695c Use an array of active sources when mixing
Prevents iterating over all allocated sources during mixing updates
2010-06-06 00:17:50 -07:00
Chris Robinson ed58571079 Use non-blocking mode for ALSA capture 2010-06-05 19:56:58 -07:00
Chris Robinson 80fbe8a788 Allow prepending backend names with - to remove them from the available devices 2010-06-05 19:33:06 -07:00
Chris Robinson 0fdec056fa Improve error recovery when capturing from ALSA 2010-06-05 17:41:33 -07:00
Chris Robinson 1915fe831f Read capture data from ALSA when querying the available sample count 2010-06-05 04:43:26 -07:00
Chris Robinson 98c01a40e6 Improve locking when calling the backend capture API 2010-06-05 04:42:05 -07:00
Chris Robinson 33234d605a Don't attempt to look for more samples from Pulse after a disconnect 2010-06-05 00:09:45 -07:00
Chris Robinson c6defe9a6d Read PulseAudio's capture data into the ring buffer when querying the sample count
This ensures we have all the samples available that the app knows about
2010-06-04 00:27:31 -07:00
Chris Robinson 244daba501 Don't overwrite data when the ring buffer overflows 2010-06-04 00:24:23 -07:00
Chris Robinson 43dadcd9e4 Use a UIntMap for the Databuffers 2010-06-03 19:35:08 -07:00
Chris Robinson 90db244b5f Skip mixing after checking looping validity 2010-06-03 03:58:04 -07:00
Chris Robinson e98f1205e5 Increase the temp buffer sizes to construct device names with 2010-05-31 19:04:41 -07:00
Chris Robinson 2205f91e5f Fix Pulse mainloop handling for device probing 2010-05-31 19:02:20 -07:00
Chris Robinson da1dee351d Update device naming to be more apparent about the device being used 2010-05-31 19:00:33 -07:00
Chris Robinson 694e9a5fec Always add the default PulseAudio device when probing 2010-05-30 23:04:04 -07:00
Chris Robinson 9ac5d8ad2d List all available PulseAudio sources 2010-05-30 21:05:05 -07:00
Chris Robinson 706b9f2357 Probe and expose all available PulseAudio sinks for the enumerate_all extension 2010-05-30 20:33:57 -07:00
Chris Robinson 55b3675dee Add a separate function to create/connect a pulseaudio context 2010-05-30 19:05:19 -07:00
Chris Robinson dc86563486 Pass the threaded main loop object to context/stream_state_callback 2010-05-30 18:19:01 -07:00
Chris Robinson ebccfa93c3 Don't unload libs when they're not needed
Some libs don't really like being unloaded and reloaded all the time, and the
benefits aren't that great
2010-05-28 23:00:59 -07:00
Chris Robinson e9f4576d4d Watch for changes to the PulseAudio sink device 2010-05-28 17:03:57 -07:00
Chris Robinson 880902fecc Add a Null Output device
This device will mix and fully process contexts as normal
2010-05-28 16:41:52 -07:00
Chris Robinson 96cf5b7282 Avoid constantly loading and unloading PortAudio
It seems this triggers a bug in the lib, causing a crash. It may not be a bad
idea to remove dynamic unloading/reloading all through-out.
2010-05-28 02:22:17 -07:00
Chris Robinson f89c9f7ea4 Connect a pulse stream on device open, to make sure the device isn't suspended
Also use the opportunity to get the stream's device's name, so later reset
calls will use the same device
2010-05-27 22:12:54 -07:00
Chris Robinson 27a4c871fd Update head dampening after a device reset 2010-05-26 23:36:55 -07:00
Chris Robinson 37190b2caf Add a function to get the frame size from a format 2010-05-24 21:51:30 -07:00
Chris Robinson c6b948323e Better watch for invalid values in alBufferSubDataEXT 2010-05-24 21:33:43 -07:00
Chris Robinson ad2957ed98 Reduce the mixing buffer size 2010-05-24 20:10:35 -07:00
Chris Robinson c469bfcb9e Make error checking consistent in alBuffer.c 2010-05-24 19:52:27 -07:00
Chris Robinson 3d16be1822 Fix alBufferiv error handling 2010-05-24 19:02:36 -07:00
Chris Robinson ad10d4ee74 Increment pointer when read 2010-05-24 17:40:16 -07:00
Chris Robinson 3ba3c1ca31 Pass the number of blocks to ConvertDataIMA4 2010-05-24 17:31:49 -07:00
Chris Robinson 4ad28964de Be careful of integer overflows when allocating buffer storage 2010-05-24 17:08:12 -07:00
Chris Robinson 15ce7fb8f7 Cleanup some variables and names 2010-05-24 03:28:00 -07:00
Chris Robinson 80a22b6484 Reorder some error checks and watch for negative buffer sizes 2010-05-24 03:20:14 -07:00
Chris Robinson 8cfac7c6b8 Don't bother storing the loop points in the source 2010-05-24 01:07:13 -07:00
Chris Robinson 9ac6b4c2c8 Be big endian safe with the IMA4 decoder 2010-05-22 15:37:32 -07:00
Chris Robinson 861a933b7b Use the ALSOFT_LOGFILE env var to specify the output for AL_PRINT 2010-05-21 18:16:27 -07:00
Chris Robinson 58e5404d61 Loop points should be specified in sample offsets 2010-05-21 15:52:35 -07:00
Chris Robinson 3676fdc4db Add mono and stereo channel masks for DSound output 2010-05-21 14:12:09 -07:00
Chris Robinson e7a555a953 Add an empty efx-creative.h header
This is for compatibility with projects that include it in Windows. Everything
from it is already defined in efx.h.
2010-05-21 11:21:35 -07:00
Chris Robinson 1e6ba29cd2 Consistency fix 2010-05-19 11:06:13 -07:00
Chris Robinson c5c83882b3 Use unsigned types when finding the source offsets 2010-05-19 10:38:28 -07:00
Chris Robinson ea3bc0518c A couple formatting fixes 2010-05-19 10:36:24 -07:00
Chris Robinson 2d46a1001e Use a map for the filter list 2010-05-18 17:54:45 -07:00
Chris Robinson 4edd7fe647 Use a map for the effects list 2010-05-18 17:41:06 -07:00
Chris Robinson ad5dfab428 Improve compatbility with latest AL_EXT_buffer_sub_data spec 2010-05-18 17:15:21 -07:00
Chris Robinson 85838c1d57 Define ARGSTACK and CALLSTACK only when needed for testing shared libs 2010-05-16 08:03:05 -07:00
Chris Robinson 4fbb3ccf66 Always look for winmm under Windows
It's needed for timeGetTime, even if the WinMM backend is disabled
2010-05-16 07:52:43 -07:00
Chris Robinson 7f533c6a25 Change inline -> __inline for MSVC 2010-05-16 06:02:27 -07:00
Chris Robinson 6dab9d54d1 Use the loop start when filling in padding data for looping sources 2010-05-13 06:52:44 -07:00
Chris Robinson 7ed5d12717 Pay attention to the source loop points 2010-05-13 04:53:21 -07:00
Chris Robinson 23b2c1f902 Only use a modulo to loop when the source is static 2010-05-13 02:12:50 -07:00
Chris Robinson 5d579dd1a8 Store loop points as uncompressed frame offsets in the source when a buffer is attached 2010-05-13 02:10:33 -07:00
Chris Robinson 0ce138341c Add initial structural support for AL_EXT_loop_points 2010-05-13 02:03:48 -07:00
Chris Robinson 61b682131e Reduce some indentation 2010-05-12 07:30:45 -07:00
Chris Robinson a53e3dda75 Don't needlessly expose a variable for the backends 2010-05-12 07:27:12 -07:00
Chris Robinson 2220c22c90 Move incomplete extension declarations to alMain.h 2010-05-12 06:59:47 -07:00
Chris Robinson e3a70e5021 Scale output of effects to compensate for device down-mixing 2010-05-12 04:56:03 -07:00
Chris Robinson af4faaf666 Use a UIntMap for the effect slot list 2010-05-12 02:20:14 -07:00
Chris Robinson f2548570b8 Store the buffer's original data size and block alignment 2010-05-12 01:36:09 -07:00
Chris Robinson d678f1d88b Store looping locally when mixing a source 2010-05-12 00:38:04 -07:00
Chris Robinson f0ce1bff3e Simplify and fix applying a source offset 2010-05-11 11:59:41 -07:00
Chris Robinson ab3c23478d Use a separate function to convert compressed bytes to frames 2010-05-11 11:06:48 -07:00
Chris Robinson 4e65e9bfa9 Only a streaming source can have a processed buffer 2010-05-11 08:53:38 -07:00
Chris Robinson 053aeee5d3 Rename a variable 2010-05-11 07:09:44 -07:00
Chris Robinson 1652dc02ab Look for the map insertion point using a binary search 2010-05-10 11:40:57 -07:00
Chris Robinson 099c2f3593 Use a simple loop to set multi-channel dry gains 2010-05-09 22:06:10 -07:00
Chris Robinson 0378422fcb Use a map to store sources and buffers
And do a lookup using a binary search instead of linear
2010-05-01 19:59:41 -07:00
Chris Robinson 0760415d08 Use doubles instead of floats for the source offset calculations 2010-04-28 17:58:20 -07:00
Chris Robinson 5730ccaa39 Combine AL and ALC function lists 2010-04-28 15:07:38 -07:00
Chris Robinson aaa7082aa8 Get the offset even if the current buffer is 0 2010-04-28 14:08:10 -07:00
Chris Robinson 5d7815beed Only apply ambient gain to available output channels 2010-04-27 11:39:54 -07:00
Chris Robinson a0ee2ccce7 Add a couple missing values to the *GetEnumValue tables 2010-04-25 08:40:37 -07:00
Chris Robinson 110be7f500 Add an option to scale the output mix 2010-04-23 07:54:43 -07:00
Chris Robinson 52663e8a44 Combine two loops into one 2010-04-23 07:23:38 -07:00
Chris Robinson 8646647b3e Update stereodup config option comment 2010-04-22 05:22:20 -07:00
Chris Robinson a04dac670e Make stereo duplication a property of the device
Further, don't use it with mono/stereo output
2010-04-20 03:57:40 -07:00
Chris Robinson 81dd71dd71 Stop and start the backend device only if new attributes are being requested 2010-04-17 00:50:28 -07:00
Chris Robinson 4d15391c88 Disable PulseAudio's write callback when disconnecting 2010-04-17 00:27:13 -07:00
Chris Robinson fc2473f826 Translate the source position separately
This is to handle the case where an app specifies the same values for the
source and listener, and expects centered panning. This fails due to floating-
point errors in the matrix, causing the result to be ever-so-slightly off of 0.

This error would normally be hidden by the position normalization, which will
not lengthen a distance shorter than the reference distance so the panning
would be nearly imperceptible. But that also fails if the reference distance
is set to 0, causing the position to expand to a full unit.

Keep the 4x4 matrix calculations, however. It will still be useful for the
requested listener matrix extension.
2010-04-16 02:09:53 -07:00
Chris Robinson 000d848f0b Return immediately when no layout is specified 2010-04-11 23:03:36 -07:00
Chris Robinson 3c5007352e More type fixes 2010-04-11 20:17:43 -07:00
Chris Robinson e0fa497948 Use a linear scaling when sending multi-channel sources to auxiliary slots 2010-04-11 15:20:46 -07:00
Chris Robinson f082c73539 Use proper types for some variables 2010-04-11 14:33:22 -07:00
Chris Robinson d4f8bd665f Only consider output speakers for the panning LUT 2010-04-11 14:23:10 -07:00
Chris Robinson 58d0db6eab Don't use LIB_INSTALL_DIR since that can be the full path 2010-04-11 12:42:47 -07:00
Chris Robinson 1544ddf0a5 Avoid reading buffer 0's size 2010-04-10 17:31:08 -07:00
Chris Robinson 488ec612bb Avoid hard-coding the channel count 2010-04-09 14:21:47 -07:00
Chris Robinson 484702a2e5 Get the speaker arrangement before setting up the channel matrix 2010-04-09 12:27:30 -07:00
Chris Robinson 371058fb9e Re-enable stereo duplication 2010-04-08 23:00:14 -07:00
Chris Robinson 97b00670f5 Use the proper type for the speaker-to-channel map 2010-04-08 18:05:24 -07:00
Chris Robinson 704b386cc5 Scale the ring modulator's mono input when expanding to multi-channel 2010-04-08 16:34:51 -07:00
Chris Robinson aace50ebf4 Store the panning LUT in the device 2010-04-08 15:58:11 -07:00
Chris Robinson 49201e892b Use a single layout for the virtual speakers
The downmix should probably be improved to take the angles into account
2010-04-08 15:41:32 -07:00
Chris Robinson 19b8deba66 Apply a scalar to the output downmix so channels don't get more than a 100% mix
All channels get the same scalar so channel balance (should be) maintained
2010-04-08 15:23:03 -07:00
Chris Robinson 068c0076af Set the device channel matrix when the device is reset 2010-04-08 15:02:03 -07:00
Chris Robinson 37c93a6ad8 Always mix internally at 8.1
The channels are remixed when writing to the output buffer. Stereo duplication
is currently broken, but this can be restored later
2010-04-08 14:47:12 -07:00
Chris Robinson 1b1c76da34 Invert device channel map array 2010-04-08 13:11:21 -07:00
Chris Robinson 5db1aec1d1 Make some functions static 2010-04-08 12:14:18 -07:00
Chris Robinson 05ca5c88ef Update alsoftrc.sample for the ring modulator 2010-04-08 10:44:35 -07:00
Chris Robinson 980167c99b Modulate with the requested waveform in the ring modulator 2010-04-08 10:37:09 -07:00
Chris Robinson 76f8c1e4e2 Implement a basic high-pass cutoff filter in the ring modulator 2010-04-08 09:36:20 -07:00
Chris Robinson b273d616ad Implement a skeleton Ring Modulator effect 2010-04-08 08:54:28 -07:00
Chris Robinson c16b895460 Fix non-dynamic PortAudio 2010-04-01 03:25:39 -07:00
Chris Robinson ec1a4884d9 Release 1.12.854 2010-03-29 22:05:21 -07:00
Chris Robinson bb4ed8b1db ALC_EXT_thread_local_context is now complete 2010-03-29 22:01:54 -07:00
Chris Robinson 4e54f93477 Make sure ALbyte and ALCbyte are signed 2010-03-28 23:24:41 -07:00
Chris Robinson 4ac1772149 No need to continue supporting _OPENAL32LIB 2010-03-28 02:12:32 -07:00
Chris Robinson 3f235c51f6 Remove a couple unnecessary lines 2010-03-26 21:58:19 -07:00
Chris Robinson 7bdf0d5156 Shorten some variable names 2010-03-26 00:41:27 -07:00
Chris Robinson d2a6fd58a3 Use unsigned types for mono and stereo source count hints 2010-03-25 18:39:16 -07:00
Chris Robinson 05098862c5 Fix comparison check 2010-03-24 23:48:38 -07:00
Chris Robinson c8dd0246da Fix alcGetEnumValue error handling 2010-03-24 22:57:35 -07:00
Chris Robinson b3c389c0a0 Constify and properly type some variables and struct members 2010-03-24 22:43:08 -07:00
Chris Robinson 15b9fc9099 Improve timing for the wave file writer 2010-03-24 22:20:55 -07:00
Chris Robinson 1c14c13c2f Fix 8-bit output with the Wave Writer 2010-03-24 16:58:58 -07:00
Chris Robinson b79b92967f Fix comment typo 2010-03-24 16:53:11 -07:00
Chris Robinson f77832fea2 Remove unnecessary NULL check 2010-03-24 03:43:37 -07:00
Chris Robinson 4ce8a17afd Reduce some indentation 2010-03-24 02:23:00 -07:00
Chris Robinson 702c62c9a2 Use a global handle to store the process-wide context 2010-03-23 21:05:29 -07:00
Chris Robinson 661059bf0f Rename alcMakeCurrent to alcSetThreadContext 2010-03-23 19:49:31 -07:00
Chris Robinson 7fb4c4ce4f Move extension function declarations to alext.h/efx.h 2010-03-23 18:21:55 -07:00
Chris Robinson 52834744fa Return if PortAudio fails to load in Windows 2010-03-23 17:45:37 -07:00
Chris Robinson 3e9934e810 Mark extension functions with AL_API/ALC_API 2010-03-23 17:44:01 -07:00
Chris Robinson 556e9b8fee Use protected visibility for exported API functions
Protected visibility is like default visibility, in that functions will be
"exported" from the library. However, it also guarantees that references to the
functions from within the library will be to the library's version, even if the
symbols are overriden by the application.
2010-03-22 23:10:29 -07:00
Chris Robinson ef92c63455 Define AL_BUILD_LIBRARY only when building the lib 2010-03-22 23:09:04 -07:00
Chris Robinson ae8858c516 Whitespace fixes 2010-03-22 15:12:20 -07:00
Chris Robinson 0691486813 Support PortAudio in Windows 2010-03-21 20:57:15 -07:00
Chris Robinson 49db3bf916 Cleanup and fixup Release* functions 2010-03-20 21:49:02 -07:00
Chris Robinson 99f28f25b0 Avoid calling alDelete* from alGen* 2010-03-20 21:38:05 -07:00
Chris Robinson 27358c8ce8 Don't expose enums for unsupported filter types 2010-03-20 20:30:43 -07:00
Chris Robinson 899fbdfe08 Add EAX Reverb and Echo parameters to the enum table 2010-03-20 20:24:50 -07:00
Chris Robinson eea23a012a Relax circular layout requirement 2010-03-20 00:54:44 -07:00
Chris Robinson 2235a53824 Reduce some indentation 2010-03-19 20:49:23 -07:00
Chris Robinson 52f82f0b94 Simplify removing the context handle from the device's context array 2010-03-19 14:53:32 -07:00
Chris Robinson a572b13743 Don't use deprecated macros 2010-03-19 14:34:18 -07:00
Chris Robinson 4340a6f8fe Remove another unnecessary assert 2010-03-19 01:35:57 -07:00
Chris Robinson 4be97dc735 Use proper storage type for the new format 2010-03-19 01:26:56 -07:00
Chris Robinson 799126df0e Use a better method to derive the offset from the data pointer 2010-03-18 19:32:03 -07:00
Alam Arias a65ec178df cast AL_SIZE value to ALint 2010-03-18 16:33:16 -07:00
Alam Arias cf4027df38 Mingw64's shlobj.h wants at least 0x501 2010-03-18 16:33:08 -07:00
Alam Arias 127b845960 DXSDK_DIR is MSVC only 2010-03-18 16:32:53 -07:00
Alam Arias e3637b8452 use ALintptrEXT in alcReverb.c 2010-03-18 16:32:49 -07:00
Alam Arias 745d36dc76 add _CRT_NONSTDC_NO_DEPRECATE define for MSVC 2010-03-18 16:32:44 -07:00
Chris Robinson 2355d6a4a0 Use ptrdiff types for databuffer offset/length handling
Should improve addressing for non-32-bit systems
2010-03-18 14:46:33 -07:00
Chris Robinson e1965fe7d9 Convert CR/LF -> LF
Spotted by Alam Arias
2010-03-18 14:23:31 -07:00
Chris Robinson 781444d12c Use size_t where appropriate
Spotted by Alam Arias
2010-03-18 14:21:06 -07:00
Chris Robinson b6571904ce Define _WIN32_IE to 0x400 only if it's a lesser value by default
Spotted by Alam Arias
2010-03-18 13:46:18 -07:00
Chris Robinson 97b25755e7 Support capture with PortAudio 2010-03-18 01:58:25 -07:00
Chris Robinson bdfafb454b Create WAVEFORMATEXTENSIBLE wave files for multi-channel and float support 2010-03-18 00:53:58 -07:00
Chris Robinson 0fee20a415 Simplifiy verification loops 2010-03-17 20:16:02 -07:00
Chris Robinson 186e0f3b04 Use a separate list for NULL-device extensions 2010-03-17 19:46:20 -07:00
Chris Robinson 2e6c5e590f Remove old comment 2010-03-17 19:28:01 -07:00
Chris Robinson 9d4e715ee7 Don't return unsupported effects from alGetEnumValue 2010-03-17 19:20:52 -07:00
Chris Robinson 932e5ec9b8 The enums are the same as with mcforamts, so advertise AL_EXT_MULAW too 2010-03-17 19:15:51 -07:00
Chris Robinson af5fb1d535 Remove unnecessary assert 2010-03-17 19:04:02 -07:00
Chris Robinson 2953daebf5 GetSourceOffset can't fail 2010-03-17 15:19:00 -07:00
Chris Robinson dd82b68175 Handle source offsets for muLaw formats 2010-03-17 15:15:12 -07:00
Chris Robinson 05a081a7b8 Allow selecting databuffer 0 2010-03-17 14:04:25 -07:00
Chris Robinson 9c417d33cc clock_gettime is available only when _POSIX_TIMERS is greater than 0 2010-03-17 12:04:33 -07:00
Chris Robinson 975f92fc84 Remove unnecessary stop call 2010-03-16 21:29:55 -07:00
Chris Robinson 0097beb84c Remove unused variable 2010-03-16 21:12:36 -07:00
Chris Robinson 65e16cc8bb Remove unneeded checks 2010-03-16 20:29:01 -07:00
Chris Robinson 2687155200 Get rid of more alIs* calls 2010-03-16 20:23:46 -07:00
Chris Robinson 49321961e8 Effect and filter ID 0 is valid 2010-03-16 19:14:05 -07:00
Chris Robinson 65f43637ce Avoid some alIs* calls while under the context lock
Instead, use functions that verify the ID by searching the object list and
returning its handle
2010-03-16 18:54:36 -07:00
Chris Robinson f37cfc486d Pass the context to alSetError 2010-03-16 17:35:51 -07:00
Chris Robinson a337a59fb8 Use alext.h for extension definitions 2010-03-16 16:25:30 -07:00
Chris Robinson ec917e8e2f Rename some struct members for consistency 2010-03-16 15:37:41 -07:00
Chris Robinson 89d84131a4 Avoid dereferencing a NULL buffer when unqueueing buffer 0 2010-03-15 16:10:21 -07:00
Chris Robinson 2033f60d24 Print an error when realloc fails 2010-03-15 14:28:38 -07:00
Chris Robinson d4159430f0 Set the buffer length for Pulse when opening the device
So it will properly scale with context frequency requests
2010-03-14 22:20:55 -07:00
Chris Robinson 14255a38fc Pulse's buffer size is not a good measurement for the update size
Lie and say 20ms instead, since there is no stable method to get such info
2010-03-14 21:45:23 -07:00
Chris Robinson 6c5f1b78d7 Reduce the mixing buffers to the next power of two 2010-03-14 03:30:42 -07:00
Chris Robinson 1f2d3a0132 Remove duplication of setting source angles 2010-03-14 03:23:18 -07:00
Chris Robinson c23e4ed412 Add support for AL_EXT_DOUBLE 2010-03-13 21:32:45 -08:00
Chris Robinson 8c0118e7ae Add support for AL_EXT_MULAW_MCFORMATS 2010-03-13 21:03:34 -08:00
Chris Robinson 9d4107a515 Add AL_EXT_MULAW_MCFORMATS tokens to alext.h 2010-03-13 18:39:12 -08:00
Chris Robinson d07b9c2c11 Rewrite openal-info
Output is mostly unchanged, however there are differences. Device-specific info
(including context-specific info) is separated from NULL-device queries, and
there is now a distinction between ALC versions of the NULL device and the
opened device. Additionally, an alternate playback device can be queried by
specifying its name as the first parameter.
2010-03-13 18:03:01 -08:00
Chris Robinson 3108a6a997 Limit PulseAudio's buffer size to the requested length 2010-03-11 09:47:26 -08:00
Chris Robinson b734cab6fc Fix the retrieval of the RW offsets using the correct functions 2010-03-10 07:33:30 -08:00
Chris Robinson 08b1bed38b Remove a couple incorrect comments 2010-03-10 07:16:53 -08:00
Chris Robinson df6320eb0a Remove duplicate copyright notice 2010-03-09 11:25:34 -08:00
Chris Robinson 80f1ec0d7e Protect some capture calls with a mutex 2010-03-09 10:14:52 -08:00
Chris Robinson 98f4f5a4f0 Add EFX types and enums to alext.h
The types and enums are in efx.h, which is included by alext.h. It's done this
way because EFX has a lot if definitions which would polute alext.h
2010-03-09 09:28:22 -08:00
Chris Robinson 8feb089f5c Build device lists only when needed 2010-03-09 06:09:29 -08:00
Chris Robinson 2ba3a88ace Probe physical devices separately from appending them to the device list 2010-03-09 05:44:18 -08:00
Chris Robinson 1f10195c47 Use powf when available 2010-03-07 22:12:33 -08:00
Chris Robinson dc40702b53 Remove unused source param count macro 2010-03-07 21:48:25 -08:00
Chris Robinson a9e0e57797 Keep UpdateSize updated when apps request a frequency 2010-02-24 18:51:57 -08:00
Chris Robinson 9b47048231 Silence some warnings 2010-02-16 05:44:39 -08:00
Chris Robinson c05a3d3549 Better handle run-time linking 2010-02-16 05:43:36 -08:00
Chris Robinson 2083884ae3 Properly check for functions in Win32 shared libs 2010-02-16 05:36:49 -08:00
Chris Robinson 2f644c7ed5 Constify some globals 2010-02-15 22:01:23 -08:00
Chris Robinson d17c4a098c Avoid probing for devices on lib initialization 2010-02-10 16:34:43 -08:00
Chris Robinson 96303893bc Set ALSA playback buffer and period size based on time
So rate adjustments won't modify the latency
2010-02-08 17:42:44 -08:00
Chris Robinson a329f9c84a Fix retrieval of the current global context when changing it 2010-02-08 16:58:26 -08:00
Chris Robinson fc96e965ae Always disable ALSA's resampler for playback
This means the frequency config option won't have an effect if the ALSA device
can't set an alternate sampling rate
2010-02-08 16:38:53 -08:00
Chris Robinson 365a62d63a Improve source write offset calculations 2010-02-07 20:11:24 -08:00
Chris Robinson 3a87c3c3ba Avoid using periods with PulseAudio, and add an option to specify its buffer length 2010-02-07 19:29:48 -08:00
Chris Robinson 54dc26b145 Enable the WinMM backend only if the lib check succeeds 2010-02-05 12:07:51 -08:00
Chris Robinson 78c1629aeb Disable ALSA's resampler when no specific output rate is requested 2010-02-05 11:45:17 -08:00
Chris Robinson bd518ed264 Make sure all requested data gets written to PulseAudio 2010-01-24 00:03:23 -08:00
Chris Robinson 56379bffac Use pa_channel_map_superset only when available with PulseAudio 0.9.15
pa_channel_map_equal can otherwise detect some compatible output modes
2010-01-22 21:20:08 -08:00
Chris Robinson 11d7a0e394 Specify the buffer size to ALSA, so the period count remains flexible
Under conditions where the period size is fixed (such as dmix), ALSA will still
attempt to provide the requested number of periods even if the requested period
size needs to be dramatically altered. In these cases, it would be better to
increase or decrease the period count, instead of growing or shrinking the
total buffer size and significantly changing the latency.
2010-01-20 01:19:32 -08:00
Chris Robinson 3ad86a1c1b Release 1.11.753 2010-01-17 17:46:27 -08:00
Chris Robinson 931f5875cd Fix speaker angle fixup 2010-01-12 09:11:46 -08:00
Chris Robinson f22b02a762 al_print doesn't need to be inline 2010-01-12 09:05:57 -08:00
Chris Robinson 505f61ff43 Properly trace the invalid speaker angle 2010-01-12 08:50:32 -08:00
Chris Robinson 0c2efa1253 Use GCC's format attribute for al_printf 2010-01-12 08:48:25 -08:00
Chris Robinson 5921e18be2 Fix some typos with the solaris backend 2010-01-12 08:28:07 -08:00
Chris Robinson 5b9e6fe440 Only allow 8- and 16-bit, and mono and stereo, wave file output 2010-01-12 08:26:25 -08:00
Chris Robinson 35ba7d70dc Consolidate some source offset handling code 2010-01-12 02:43:37 -08:00
Chris Robinson 026b4b8f4c Better handle large second offsets 2010-01-12 02:26:38 -08:00
Chris Robinson c924a50bed Don't use a flag to set an error when applying the source offset 2010-01-12 02:22:38 -08:00
Chris Robinson 574792d2e1 Fix Windows compilation 2010-01-11 23:47:03 -08:00
Chris Robinson ab2eb5a603 Check buffer size when copying padding instead of the data pointer 2010-01-11 10:58:33 -08:00
Chris Robinson 3d7f925d52 Add helpful values to the resampler enum 2010-01-11 07:02:29 -08:00
Chris Robinson 93b584ff84 Add a cosine resampler 2010-01-11 06:19:54 -08:00
Chris Robinson 705849ca73 Add an option for point resampling 2010-01-11 05:37:20 -08:00
Chris Robinson 1a57f095e8 Hold global lock during mixing only when iterating device contexts 2010-01-11 03:57:49 -08:00
Chris Robinson ac9c2e8c4a Cleanup OSS/Solaris loop a bit 2010-01-10 12:40:59 -08:00
Chris Robinson 45f8efec41 Return the default config string for empty entries 2010-01-09 06:48:43 -08:00
Chris Robinson ef7df2416d Hide OSS and Solaris devices if their files can't be stat'd 2010-01-09 06:40:50 -08:00
Chris Robinson cb113315f7 Promote AL_EXT_source_distance_model to complete 2010-01-09 03:27:16 -08:00
Chris Robinson d61f90a9c2 Make sure the device handle is valid when getting the device error 2010-01-09 03:25:13 -08:00
Chris Robinson 3d11fb219e Hold the default context extensions globally 2010-01-09 02:48:18 -08:00
Chris Robinson 4d9a368f96 Suppress connection refused errors
Since that just typically means the server isn't running
2010-01-08 01:43:27 -08:00
Chris Robinson 43220b604c Reduce some indentation 2010-01-08 01:21:57 -08:00
Chris Robinson 91f28fa87c Try the PulseAudio backend first 2010-01-08 01:08:27 -08:00
Chris Robinson 82547db2db Prepare the pcm handle after recovering 2010-01-06 23:02:28 -08:00
Chris Robinson 64ac3a4739 Use snd_pcm_recover in more places 2010-01-06 22:55:20 -08:00
Chris Robinson c90616b963 Use snd_pcm_recover to recover from certain device errors 2010-01-06 22:50:30 -08:00
Chris Robinson 0ceaa01c3d Adjust PulseAudio's capture latency 2009-12-30 15:33:16 -08:00
Chris Robinson 7d7e503603 Properly retrieve device-inspecific errors 2009-12-28 23:29:49 -08:00
Chris Robinson 7ee81eac0f Store ALC errors with the device when possible 2009-12-28 23:19:13 -08:00
Chris Robinson c9a08fc7b2 Remove some unneeded functions 2009-12-28 13:12:45 -08:00
Chris Robinson 69ab93a824 Add a function to check if a config option is set to a non-empty value 2009-12-28 13:08:15 -08:00
Chris Robinson 179b660eee Enforce a lower bound playback frequency of 8khz 2009-12-28 12:47:59 -08:00
Chris Robinson a0ef7be9a5 Improve layout parsing and allow using long names for speakers 2009-12-28 11:49:55 -08:00
Chris Robinson 2a735b14dc Add an option to spawn a PulseAudio server on request 2009-12-28 10:49:31 -08:00
Chris Robinson a294dd8d9b Be more lenient in signaling the mainloop 2009-12-28 10:15:59 -08:00
Chris Robinson dc1522282b Try to find a compatible format from Pulse's default sink 2009-12-27 11:05:59 -08:00
Chris Robinson 528a4c6a02 Update panning for existing AL contexts when creating a new one 2009-12-26 20:27:14 -08:00
Chris Robinson 1770a8b62b A NULL Pulse context won't have a valid error code 2009-12-26 12:18:16 -08:00
Chris Robinson 77a0a6de95 Wait for the buffer attrib update from pulse to finish 2009-12-26 11:30:41 -08:00
Chris Robinson c1fd977e79 Consolidate pulse capture failure path 2009-12-26 10:46:29 -08:00
Chris Robinson cbbda93292 Make sure a proper channel map is set for pulse capture 2009-12-26 09:17:03 -08:00
Chris Robinson c6340ce12d Clean up some loading checks 2009-12-26 08:49:11 -08:00
Chris Robinson 7bc739e965 Use the proper logging function 2009-12-26 08:16:25 -08:00
Chris Robinson 9f988808c7 Start and stop PortAudio's stream in the proper methods 2009-12-26 08:14:28 -08:00
Chris Robinson 6e9ce47a4b GetConfigValueBool should take an int, not a float 2009-12-26 07:42:57 -08:00
Chris Robinson 89f59c0e1c Shorten a long line 2009-12-26 07:42:16 -08:00
Chris Robinson 3793919892 Capture as much as possible directly from PulseAudio 2009-12-25 17:56:57 -08:00
Chris Robinson d1699d50f6 Add missing newline 2009-12-25 15:18:32 -08:00
Chris Robinson b94d950b1e Undefine no longer needed macro 2009-12-25 14:11:43 -08:00
Chris Robinson d3e77a0f63 Fix incorrect error check 2009-12-25 13:19:25 -08:00
Chris Robinson 965a71ee90 Only use pa_stream_set_buffer_attr_callback when available (0.9.15+) 2009-12-25 13:17:21 -08:00
Chris Robinson fd794b44b2 Use pa_stream_begin_write when available for "zero-copy" writing
Must be compiled against 0.9.16 or newer to be available. It will fall back to
the old method if the function is not available at run-time.
2009-12-25 13:11:17 -08:00
Chris Robinson c9dcba17a9 Check error returns instead of error string 2009-12-25 13:05:04 -08:00
Chris Robinson 88de4e15b3 Mark the source for updating when setting a buffer on it
Changing the buffer can change the playback format, which can require different
source parameter calculations. Queueing a buffer on a source that has no
buffers (or only buffers without a format, eg. buffer 0) has the same effect
2009-12-25 05:09:29 -08:00
Chris Robinson 7f0c6629b9 Use a 64-bit value to scale potentially-large numbers 2009-12-24 15:41:45 -08:00
Chris Robinson f6ca39403d Use the Pulse server-specified playback rate by default 2009-12-24 15:35:22 -08:00
Chris Robinson ea7cf35ea4 Use pa_xmalloc instead of pa_xmalloc0 2009-12-24 07:38:46 -08:00
Chris Robinson accea119d9 Update pulse capture ring buffer in 25ms chunks 2009-12-24 04:08:04 -08:00
Chris Robinson 6ea7b43c90 Don't force latency adjustment with PulseAudio 2009-12-23 13:59:58 -08:00
Chris Robinson ddfad996a9 Don't render mono as stereo 2009-12-21 02:59:30 -08:00
Chris Robinson d786f99094 Scale samples down when converting stereo to mono 2009-12-21 02:27:25 -08:00
Chris Robinson 008563450c Improve some indentations 2009-12-20 21:50:00 -08:00
Chris Robinson 69c238a2e6 Properly retrieve the device frequency 2009-12-20 21:19:57 -08:00
Chris Robinson b3fdf170b1 Fix header comment for AL_PITCH 2009-12-16 22:50:54 -08:00
Chris Robinson 56cc038603 Improve initial decay calculations for sends to reverb 2009-12-10 18:37:36 -08:00
Chris Robinson 4c83c689a8 Use the specified reverb air absorption value for wet sends 2009-12-10 18:22:45 -08:00
Chris Robinson 2b7953c472 Track whether a context is suspended or not 2009-12-09 12:14:53 -08:00
Chris Robinson 368ef1cea9 Store the source state locally after making sure it needs mixing 2009-12-09 11:56:53 -08:00
Chris Robinson bd696a6b37 Fix IMA ADPCM offset calculation 2009-12-09 09:50:09 -08:00
Chris Robinson a9fc272e39 Prettify CMake checks for compiler switches 2009-12-09 08:46:35 -08:00
Chris Robinson c5952d1ddc Move the pkg-config file to the base directory 2009-12-09 07:36:06 -08:00
Chris Robinson 656a406377 Use an inline function to calculate the low-pass filter coefficient 2009-12-09 07:21:59 -08:00
Chris Robinson 5fcd6cc510 Split non-attenuated source calculations into a separate function 2009-12-09 07:02:26 -08:00
Chris Robinson e09b6020a6 Fix typo for reverb creation 2009-12-09 06:46:06 -08:00
Chris Robinson 84d2d623b6 Add a head-dampening option
This simulates occlusion of the player's head for sounds coming from behind,
when outputing to mono or stereo
2009-12-08 14:18:07 -08:00
Chris Robinson 1694e5bd12 Store the original pre-clamped distance instead of re-computing it 2009-12-08 10:12:18 -08:00
Chris Robinson 5170e251f9 Use the correct wet filter history offset 2009-12-07 12:45:23 -08:00
Chris Robinson 4697e946d3 Internally store 32-bit float buffer data, and mix accordingly 2009-12-07 10:35:30 -08:00
Chris Robinson 9286e3984c Move default channel order setting out of the header 2009-12-07 04:19:33 -08:00
Chris Robinson 88f3d747b7 Add a simple README 2009-12-07 01:05:01 -08:00
Chris Robinson d4427c54ea Change internal order to match WFX 2009-12-07 00:51:27 -08:00
Chris Robinson 92ade80557 Fix 6.1 channel order 2009-12-07 00:49:56 -08:00
Chris Robinson 8138446b8c Restrict setting some wet path values to active sends only 2009-12-06 03:59:12 -08:00
Chris Robinson 58ecc7fad4 Check for potential NULL accesses with the IsBadWritePtr wrapper 2009-12-04 01:33:50 -08:00
Chris Robinson 311cc5c62f Don't wait to accept stream connections 2009-12-03 04:43:38 -08:00
Chris Robinson 4a928ea9fa Don't signal on synchronous changes and don't wait to accept context changes 2009-12-02 08:10:45 -08:00
Chris Robinson c1eb444a39 Remove some assumptions of 16-bit internal storage 2009-12-02 05:55:33 -08:00
Chris Robinson b5270e0bb3 Use a channel-map to specify the output device channel order 2009-12-02 04:03:51 -08:00
Chris Robinson 6cfc31777b Add an option for real-time priority mixing
Default to disable for now, as a safety precaution
2009-12-01 23:15:09 -08:00
Chris Robinson 0e1e8503e0 Properly accept PulseAudio's mainloop signal on connection failure 2009-12-01 22:42:43 -08:00
Chris Robinson 974d0b4e91 Fix retrieved update size from pulseaudio 2009-12-01 12:21:02 -08:00
Chris Robinson d66832a39c Accept a signal only when the pulseaudio stream/context is ready 2009-12-01 12:18:34 -08:00
Chris Robinson d5889a941f Clamp dry gain after cone attenuation is applied 2009-12-01 03:32:04 -08:00
Chris Robinson 6248e986e5 Don't complain if the length given by pulse isn't an exact multiple of the period size 2009-12-01 02:23:38 -08:00
Chris Robinson 786b98a013 Avoid setting a field redundantly 2009-11-29 23:07:04 -08:00
Chris Robinson f63d8dbf38 Enable real-time priority for ALSA, OSS, and DirectSound mixing loops 2009-11-29 23:02:21 -08:00
Chris Robinson 15aad09ce7 Check for the pthread_setschedparam function 2009-11-29 22:44:56 -08:00
Chris Robinson fdd314f7f8 Reset the kill flag after the thread has stopped 2009-11-29 10:22:12 -08:00
Chris Robinson 39b456d88c Add AL_EXT_double tokens to alext.h 2009-11-28 22:19:04 -08:00
Chris Robinson d930fb8d3d Call the Update effect method for null effects 2009-11-28 20:09:41 -08:00
Chris Robinson 3ec64eb0fd Call to the right databuffer function 2009-11-28 19:37:29 -08:00
Chris Robinson d81c9819b8 Remove unnecessary returns 2009-11-28 19:36:05 -08:00
Chris Robinson 98ce1d14c1 Update AL_EXTX_source_distance_model to require explicit enabling
The in-progress spec has been updated to reflect this
2009-11-27 20:05:21 -08:00
Chris Robinson 69f9ab88b9 Send multi-channel sources to auxiliary effect slots
They are downmixed to mono using a volume-preserving scalar, and passed
through a 1-pole low-pass filter (not chained)
2009-11-26 00:39:32 -08:00
Chris Robinson 1a0676f0eb Mark sources for updating when a new context is made from the device 2009-11-25 16:28:19 -08:00
Chris Robinson 658923175f Update source parameters only when they need changing 2009-11-25 16:21:47 -08:00
Chris Robinson 877f4340ba Base air absorption on distance attenuation, try 2 2009-11-24 21:19:11 -08:00
Chris Robinson 35a9ccb41f Revert "Base air absorption on the distance attenuation"
This reverts commit c7c2f9385f.

Fundamentally wrong. The -6dB rolloff is every doubling of the distance, and
the (scaled) -0.05dB rolloff is supposed to be every additional unit.
2009-11-24 01:39:34 -08:00
Chris Robinson c7c2f9385f Base air absorption on the distance attenuation 2009-11-23 16:25:37 -08:00
Chris Robinson d1f3dbb9a1 Make modulation index 0 map to offset 0 2009-11-23 04:14:12 -08:00
Chris Robinson cfb30fe975 Use a 4x4 matrix to transform coordinates 2009-11-23 04:13:51 -08:00
Chris Robinson 2d1b378ef2 Transform all relevant vectors for converting world-space to listener-space 2009-11-22 22:36:20 -08:00
Chris Robinson 06bbee2449 Add a function for 1-pole filtering 2009-11-22 21:20:27 -08:00
Chris Robinson 85bc300dfa ALCAPIENTRY is deprecated in favor of ALC_APIENTRY 2009-11-22 21:15:11 -08:00
Chris Robinson 0662adacb9 Fix alBufferDataStatic extension name in alext.h 2009-11-22 21:12:43 -08:00
Chris Robinson 65a153da6c Update the drivers config file comment 2009-11-22 15:43:05 -08:00
Chris Robinson c5ee010640 The echo should not take energy-attenuated input 2009-11-22 15:37:32 -08:00
Chris Robinson 1b18b4a0ee Allow unlisted backends to stay available when the drivers list ends with , 2009-11-22 01:06:05 -08:00
Chris Robinson 58765aab6b Print available devices before trying to open one 2009-11-19 19:02:16 -08:00
Chris Robinson 1483af1baa Watch for NULL and empty device lists 2009-11-19 18:49:24 -08:00
Chris Robinson 13979793f6 Display supported filters using a comma-separated listing 2009-11-19 18:46:23 -08:00
Chris Robinson 9c228e7625 Be clearer if device opening or context setup fails 2009-11-19 18:25:29 -08:00
Chris Robinson 6a667b36d1 Reorganize and improve the reverb effect
Code supplied by Christopher Fitzgerald. This update also implements the echo
and modulation parameters.
2009-11-19 14:05:04 -08:00
Chris Robinson fe37f1968d Better approximate the wet attenuation model for reverb 2009-11-19 11:06:41 -08:00
Chris Robinson 4565bdd7ce Make sure there's at least a one-sample delay for the echo's first tap 2009-11-19 10:42:41 -08:00
Chris Robinson 5f3c07ca3b Apply the reverb room rolloff factor for EAX reverb too 2009-11-19 10:29:10 -08:00
Chris Robinson 8d1da6a8ca Move NextPowerOf2 to alMain.h 2009-11-19 09:50:15 -08:00
Chris Robinson ff8e09495d Move aluCart2LUTpos to alu.h 2009-11-19 09:24:35 -08:00
Chris Robinson e868eef679 Make sure to set the new echo sample buffer and remove an unused macro 2009-11-18 17:34:08 -08:00
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
Chris Robinson 61122a5093 Release 1.7.411 2009-03-14 22:24:59 -07:00
Chris Robinson a8a4ff8af1 Constify some parameters 2009-03-13 23:08:15 -07:00
Chris Robinson 8a857c35ee Calculate filter coefficients in aluMixData 2009-03-13 22:58:54 -07:00
Chris Robinson 89ddd7d8e5 Don't modify the device struct until playback succesfully starts 2009-03-13 22:16:01 -07:00
Chris Robinson 8d0c4ccb3b The room rolloff factor can go up to 10 2009-03-13 02:12:45 -07:00
Chris Robinson 8ee47d5573 Dynamically load dsound when possible 2009-03-10 02:46:42 -07:00
Chris Robinson 9e88011417 Add a cast for setting a dummy pointer value 2009-03-10 02:20:05 -07:00
Chris Robinson f8949ee7a1 Always add the default ALSA device even if no cards are present 2009-03-10 01:46:51 -07:00
Chris Robinson 62aa2d0ba7 Only expose the default ALSA device in standard enumeration 2009-03-10 01:28:01 -07:00
Chris Robinson ace047d625 Append the card and device indices to the ALSA device strings 2009-03-10 01:21:42 -07:00
Chris Robinson d6277db209 Fix alsoftrc configuration sample comments 2009-03-10 01:08:03 -07:00
Chris Robinson 7ebb28327f Remove the SDL backend 2009-03-10 01:03:39 -07:00
Chris Robinson 86931cbde4 Add a PortAudio backend 2009-03-10 00:55:29 -07:00
Chris Robinson 6d7be151dc Remove the unneeded path from the cross-compiler commands 2009-03-06 20:09:44 -08:00
Chris Robinson 07227b9806 Use a modified reverb model that obeys the reverb parameters better 2009-03-02 18:48:23 -08:00
Chris Robinson 8348d719cd Clamp gain of multichannel sources 2009-02-10 15:15:49 -08:00
Chris Robinson 0fcefd865b Install the pkgconfig file to the correct directory 2009-02-10 14:39:48 -08:00
Chris Robinson 57c2e9b5f8 Include assert.h for assert() 2009-02-02 11:18:33 -08:00
Chris Robinson 7d7fc39035 Use calculated distance from reference for air absorption 2009-01-30 10:56:25 -08:00
Chris Robinson 351105b3df Fix incorrect comment 2009-01-30 10:53:09 -08:00
Chris Robinson cbfc33215b Use M_PI since it is sure to be defined 2009-01-27 07:11:58 -08:00
Chris Robinson 5a93b56673 Fix ignored return value warning 2009-01-26 08:10:05 -08:00
Chris Robinson 1f4c69c17a Use a matrix for up- and down-mixing channels 2009-01-25 22:11:07 -08:00
Chris Robinson f5b19fad20 Duplicate stereo onto the side channels as well as the back 2009-01-25 19:54:50 -08:00
Chris Robinson bc60818e9a Don't read stereo layout when output is mono 2009-01-25 19:33:52 -08:00
Chris Robinson f82c88f016 Add options for user-configurable speaker arrangements 2009-01-25 19:20:47 -08:00
Chris Robinson 98e86decad 6.1 uses front- and back-center, not left- and right-back channels 2009-01-24 15:13:14 -08:00
Chris Robinson aaf2c0ebd4 Seperate mixing loops depending on source channel configuration 2009-01-24 13:57:01 -08:00
Chris Robinson 778b74cae1 Reimplement panning using lookup tables, based on a patch by Christian Borss
This allows speaker positions to be specified by discrete angles around the
listener, providing more flexibility and configurability in placement.
Additional patches to take advantage of this are forthcoming.
2009-01-24 10:38:04 -08:00
Chris Robinson 43ee1edd97 Properly capitalize the libname in Win32 2009-01-10 21:23:53 -08:00
Chris Robinson dd7e23740b Remove XCOMPILEWIN32 option in favor of CMake 2.6's cross-compiling caps 2008-12-12 11:19:38 -08:00
Chris Robinson 1acd6da745 Search for SDL.h in addition to SDL/SDL.h 2008-12-12 11:09:23 -08:00
Chris Robinson 3056f91ec5 Apply the dry filter to multi-channel sources
Unlike mono sources, they use 2 chained one-pole filters instead of 4
2008-12-10 11:54:13 -08:00
Chris Robinson ed03570e1a Fix some CMake checks 2008-12-07 02:20:17 -08:00
Chris Robinson 2ec0e48d06 Protect playback device opening with a mutex lock 2008-12-07 01:07:54 -08:00
Chris Robinson 8b54d59b8c Add an SDL backend 2008-12-07 01:05:39 -08:00
Chris Robinson f6a4dbabdd Add cast for setting a dummy pointer value 2008-12-06 12:17:29 -08:00
Chris Robinson a71c291bcb Let CMAKE_DEBUG_POSTFIX be exposed for graphical CMake front-ends 2008-12-02 02:37:51 -08:00
Chris Robinson 55b9ccc2de Implement AL_EXTX_source_distance_model
As with other EXTX extensions, this is subject to change and removal as the
spec gets worked on
2008-11-25 18:56:10 -08:00
Chris Robinson 67d67a3bf6 Release 1.6.372 2008-11-21 09:16:29 -08:00
Chris Robinson 591de1ecb4 Wait until one full fragment is empty before mixing 2008-11-21 07:52:13 -08:00
Chris Robinson 3dad17c263 Make the DSound emulated fragment count configurable 2008-11-21 07:48:03 -08:00
Chris Robinson eefc18170d Fix a comment 2008-11-20 10:09:37 -08:00
Chris Robinson 5f84c5339d Fix early reflection input 2008-11-19 09:14:40 -08:00
Chris Robinson 2d461379ef Handle ALSA capture errors a bit better 2008-11-19 09:01:03 -08:00
Chris Robinson c8123756ff Simplify in-sample low-pass filter coefficient calculation 2008-11-18 06:35:00 -08:00
Chris Robinson 76c7789ee7 Fix low-pass coefficient calculation 2008-11-18 04:31:24 -08:00
Chris Robinson 13a2e6ef1f Don't calculate reverb HF limit if air absorption is 1 2008-11-18 03:26:02 -08:00
Chris Robinson 0ecb34b850 Non-cross-compiled DLLs shouldn't have lib prefixed 2008-11-18 03:24:49 -08:00
Chris Robinson 1f86c48d95 Remove outdated comments and add copyright header 2008-11-17 09:32:25 -08:00
Chris Robinson 7e1295df9a DirectSound is not explicitly dependant on windows.h 2008-11-16 04:39:12 -08:00
Chris Robinson 482b160c8a Remove unneeded macro 2008-11-16 01:07:39 -08:00
Chris Robinson 181eb95b13 Use a better dB-to-linear gain convertion 2008-11-16 00:57:35 -08:00
Chris Robinson c0ccd31a3e Implement a new reverb effect
Code created and graciously provided by Christopher Fitzgerald
2008-11-16 00:29:49 -08:00
Chris Robinson d72b132c57 Add an option to disable specific EFX effect types 2008-11-14 07:13:59 -08:00
Chris Robinson 506912aed7 Add cross-compiling option 2008-11-13 23:13:15 -08:00
Chris Robinson 670d70d3c9 Allow specifying another config file with the ALSOFT_CONF env var 2008-11-13 07:58:39 -08:00
Chris Robinson 010f7d12f4 Don't ramp gains when starting a sound from the beginning 2008-11-13 05:48:38 -08:00
Chris Robinson da684564ea Avoid unnecessary floating-point math 2008-11-11 17:59:55 -08:00
Chris Robinson fc4c867f27 Add initial AL_EXTX_buffer_sub_data support
Note that this is an in-development extension, as noted by the EXTX moniker
instead of EXT. It's behavior is subject to change, and the extension string
will be removed (replaced with the official string once it's finalized).
Developers are discouraged from using this in production code, though feel
free to play around with it.
2008-11-11 05:57:32 -08:00
Chris Robinson 9ba30c4e20 Fix Win32 thread handle leak 2008-11-05 19:42:56 -08:00
Chris Robinson 15334e56cd Be more flexible with channel count when loading IMA4 data 2008-11-02 15:30:56 -08:00
Chris Robinson ffa42ff22c Seperate data converters into reusable functions 2008-11-02 01:24:57 -07:00
Chris Robinson a7c62dbabc More padding fixes 2008-11-01 16:37:32 -07:00
Chris Robinson eda1e41152 More buffer conversion refactoring 2008-11-01 16:35:16 -07:00
Chris Robinson af5a5b76ec Padding is not dependant on the frequency cutoff anymore 2008-10-31 23:32:28 -07:00
Chris Robinson 87f3a0dc16 Restructure buffer data conversion code a bit 2008-10-31 22:13:35 -07:00
Chris Robinson 2c80a80704 Fix typo preventing capture from opening 2008-10-27 23:37:56 -07:00
Chris Robinson 301a4c4a95 Append the driver and its version to the AL version string 2008-10-25 15:48:17 -07:00
Chris Robinson 8fc4a3b724 Make sure an appropriate error is set when opening a device fails 2008-10-24 19:58:49 -07:00
Chris Robinson cb6f040005 Use plughw for capture so ALSA can convert capture data 2008-10-14 09:50:37 -07:00
Chris Robinson b91c2e4a99 Include float.h if it exists, for _RC_CHOP and _MCW_RC 2008-10-14 09:47:32 -07:00
Chris Robinson 59a71b1454 Remove another unused source member 2008-10-10 01:31:31 -07:00
Chris Robinson 36f133a5ae Use a modulo to keep the buffer position in range for looping sources
A high pitch and low buffer size can cause a lot of unnecessary iterations
otherwise, that just decrement the position
2008-10-10 01:13:32 -07:00
Chris Robinson 74a58c0d09 Clamp source position to the buffer size when it stops 2008-10-09 23:54:31 -07:00
Chris Robinson bfa1107781 Remove unneeded source member variable 2008-10-09 23:44:48 -07:00
Chris Robinson 11397f7667 Commit missing changes 2008-10-09 20:58:12 -07:00
Chris Robinson 6e9e8239ef Only send one channel through the wet path 2008-10-09 04:02:34 -07:00
Chris Robinson af9932d28b Increase max pitch to 65536
This should be safe now
2008-10-09 02:50:00 -07:00
Chris Robinson 87ff8a65e9 Simplify the lerp function 2008-10-09 02:32:47 -07:00
Chris Robinson 7b6f207790 Don't apply the wet path for multi-channel buffers 2008-10-09 02:28:52 -07:00
Chris Robinson 8672008e43 Skip mixing if the read position is beyond the end of the buffer 2008-10-09 01:17:39 -07:00
Chris Robinson c8cd193346 The wet path should be silent if no effect is set on the slot 2008-10-09 01:07:02 -07:00
Chris Robinson be292e5f0b Don't hold the whole-number position in the fractional value
This will help prevent overflows when the max pitch is increased
2008-10-02 23:53:46 -07:00
Chris Robinson 3863dcc9cb Use a new low-pass filter, based on the I3DL2 spec
Many thanks to Christopher Fitzgerald, for helping with it
2008-10-02 22:20:42 -07:00
Chris Robinson a2568409fc Implement non-mmap ALSA capture 2008-09-29 17:24:50 -07:00
Chris Robinson 6567cdd7b5 Air absorption factor is applied to the dB value, not linear gain 2008-09-22 17:01:47 -07:00
Chris Robinson 5bbf55a401 Add a variable to override the default library type with 2008-09-16 07:43:38 -07:00
Chris Robinson 4a530e2146 Fixup some source parameter calculations 2008-09-16 07:36:48 -07:00
Chris Robinson 27ba8f7b60 Fix function pointer declarations 2008-09-16 06:19:27 -07:00
Chris Robinson 6bfdb57a5b Use a 12dB/oct rolloff instead of 24 for the lowpass filter 2008-09-13 02:46:14 -07:00
Chris Robinson 26e8ea60a5 Store pi as a static const 2008-09-13 00:44:48 -07:00
Chris Robinson f4ea188ffa Fix typo to get the proper minor ALC version 2008-09-12 18:07:12 -07:00
Chris Robinson 1266580420 Print EFX info when the extension is available 2008-09-12 18:05:23 -07:00
Chris Robinson 16d96eed7b Add a Solaris playback backend 2008-09-07 14:34:14 -07:00
Chris Robinson fa76168683 Clear the end of the buffer when at the end of the queue and not looping 2008-09-06 14:08:53 -07:00
Chris Robinson 5f3329b2c9 Don't export extension function symbols from the lib 2008-09-06 13:45:27 -07:00
Chris Robinson db541f3cfa Remove unneeded source struct member 2008-08-15 17:43:07 -07:00
Chris Robinson 3e19ba6ca8 Clear channel volumes when starting a source 2008-08-15 16:33:47 -07:00
Chris Robinson ac8c082b89 Overwrite the input wet sample with the output 2008-08-14 20:44:55 -07:00
Chris Robinson 084df2a229 Allow setting the EFX doppler factor source property 2008-08-14 16:14:16 -07:00
Chris Robinson 22557070ec Ramp channel gains to remove pops and clicks from abrupt changes
Thanks to Christopher Fitzgerald for helping me work on it
2008-08-14 05:43:52 -07:00
Chris Robinson f8ef66954c Include fenv.h if it exists for fesetround 2008-08-08 08:12:41 -07:00
Chris Robinson ef59901e7c Set FPU mode to round toward zero for mixing 2008-08-08 07:32:21 -07:00
Chris Robinson cfe620ccb5 Remove unnecessary casting 2008-08-08 00:21:25 -07:00
Chris Robinson 453b015225 Prevent a 0 or negative increment for the buffer position
Thanks to Christopher Fitzgerald for pointing these last two problems out
2008-08-05 20:51:30 -07:00
Chris Robinson c1cf9ae8f6 Pass a dummy variable to CreateThread to satisfy Win9x 2008-08-05 20:19:13 -07:00
Chris Robinson f1414c650e Release 1.5.304 2008-07-27 19:58:32 -07:00
Chris Robinson 869b041f2f Reduce the default buffer size to 4096
Should help with latency issues some people have and not put too much extra
burden on the mixer, hopefully
2008-07-26 21:07:08 -07:00
Chris Robinson 8621fbb015 Improve getting and setting EFX filter parameters 2008-07-26 18:32:45 -07:00
Chris Robinson 597e01153e Use arrays instead of pointer-to-arrays for the low-pass filter 2008-07-26 17:13:50 -07:00
Chris Robinson d3e5fcd13e Fix some calculations for the reverb buffer 2008-07-26 01:57:04 -07:00
Chris Robinson 3e0f9cc716 Make the filter processing function inline 2008-07-26 00:58:54 -07:00
Chris Robinson c7e49c9f57 Implement yet another low-pass filter
This one using the Butterworth IIR filter design
2008-07-25 19:31:12 -07:00
Chris Robinson e2ed8ff2bf Use a temp pointer when realloc()ing
So the original data isn't lost on out-of-memory conditions
2008-07-24 13:44:26 -07:00
Chris Robinson 559c786d0c Specify padding per buffer, and make sure it's large enough for the filter step 2008-07-24 00:41:25 -07:00
Chris Robinson c3a7480961 Don't advertise extra samples for mixing 2008-07-23 23:27:38 -07:00
Chris Robinson a75e75aef5 Implement an alternative low-pass filter
This method samples from the buffer so that it gets a time-correct 5khz stream,
which is subtracted from the original sample and has the high-frequency gain
applied, then added back.
A better method may be to average all the samples from the current one to the
one freq/5000 away, instead of bilinear filtering the two nearest freq/5000
apart. Processing cost will need to determine its viability
2008-07-23 22:29:53 -07:00
Chris Robinson d45b1207d0 Make sure the correct libname is used for pkg-config 2008-07-23 11:58:36 -07:00
Chris Robinson 5a9e24dea1 Add a warning when building on Windows with the DSound backend disabled 2008-07-23 00:51:55 -07:00
Chris Robinson dc8132e965 Add a pkg-config file to install on the system 2008-07-22 18:42:53 -07:00
Chris Robinson 20bcdc1ef6 Add AL_LOKI_IMA_ADPCM_format and AL_EXT_vorbis tokens to alext.h 2008-07-22 14:45:31 -07:00
Chris Robinson 93c0f61050 Clarify implicit destruction warnings 2008-07-22 14:29:27 -07:00
Chris Robinson 3a8c543f8b Move ALC_ENUMERATE_ALL_EXT tokens to alext.h 2008-07-22 13:50:08 -07:00
Chris Robinson 9e96156451 Add AL_LOKI_WAVE_format tokens to alext.h 2008-07-22 13:45:26 -07:00
Chris Robinson 19aabd6d02 Add ALC_LOKI_audio_channel tokens to alext.h 2008-07-22 13:16:58 -07:00
Chris Robinson 87b5d7bc7b Store extension list with a pointer, not a per-context array 2008-07-22 12:39:10 -07:00
Chris Robinson 646714b585 Set the new linking policy for CMake 2.6 to avoid warnings 2008-07-22 11:26:56 -07:00
Chris Robinson eba60c30c5 Don't force initialization when shutting down
Thanks to Michael Simms
2008-07-17 18:45:21 -07:00
Chris Robinson e66bb09156 Move (de)initialization into ALc.c and remove unneeded file 2008-07-17 18:38:07 -07:00
Chris Robinson 0042b1f80d Implement doppler factor source property 2008-07-15 02:33:05 -07:00
Chris Robinson 6d416ee734 Add the reverb room rolloff to the source room rolloff, not override 2008-07-15 02:23:53 -07:00
Chris Robinson 97d3a45aff Don't check the number of objects being deleted with the number currently allocated
Since apps can validly delete buffer 0, and delete the same source/buffer multiple times in a single call
2008-07-11 09:12:11 -07:00
Chris Robinson 9e9ff44b17 Use volatile for member variables that are changed in a different thread 2008-07-10 20:36:28 -07:00
Chris Robinson f369be148f Reduce the mix buffer sizes by half
Nearly 3MB is a bit much. Could reduce it further, but this is good enough for now.
2008-07-08 19:37:14 -07:00
Chris Robinson 3a09e446b3 Leave SourceToListener untransformed for use with untransformed velocities
Distance is also left untransformed so cone calculations with SoundToListener
are correct
2008-07-03 03:13:43 -07:00
Chris Robinson 2d0b12e49e Store thread return value in the struct to avoid void*-to-uint casting 2008-06-17 19:46:37 -07:00
Chris Robinson 55e2f294ac Allow for overriding the default lib destination with LIB_INSTALL_DIR
So 64-bit builds can be optionally redirected to lib64
2008-06-06 18:39:18 -07:00
Chris Robinson 2a4b467f08 Make the project explicitly C
So it doesn't search for an unneeded C++ compiler
2008-06-06 18:33:13 -07:00
64 changed files with 18527 additions and 8165 deletions
+1 -1
View File
@@ -1 +1 @@
CMakeConf
build
+1728 -658
View File
File diff suppressed because it is too large Load Diff
+867 -1008
View File
File diff suppressed because it is too large Load Diff
+47 -27
View File
@@ -18,6 +18,14 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#ifdef _WIN32
#ifdef __MINGW64__
#define _WIN32_IE 0x501
#else
#define _WIN32_IE 0x400
#endif
#endif
#include "config.h"
#include <stdlib.h>
@@ -27,8 +35,7 @@
#include "alMain.h"
#ifdef _WIN32
#define _WIN32_IE 0x400
#ifdef _WIN32_IE
#include <shlobj.h>
#endif
@@ -208,7 +215,7 @@ void ReadALConfig(void)
#ifdef _WIN32
if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
{
int p = strlen(buffer);
size_t p = strlen(buffer);
snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini");
f = fopen(buffer, "rt");
if(f)
@@ -219,13 +226,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 +235,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);
@@ -250,6 +242,15 @@ void ReadALConfig(void)
}
}
#endif
if(getenv("ALSOFT_CONF"))
{
f = fopen(getenv("ALSOFT_CONF"), "r");
if(f)
{
LoadConfigFromFile(f);
fclose(f);
}
}
}
void FreeALConfig(void)
@@ -276,20 +277,24 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
{
size_t i, j;
if(keyName)
if(!keyName)
return def;
if(!blockName)
blockName = "general";
for(i = 0;i < cfgCount;i++)
{
if(!blockName)
blockName = "general";
if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
continue;
for(i = 0;i < cfgCount;i++)
for(j = 0;j < cfgBlocks[i].entryCount;j++)
{
if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
continue;
for(j = 0;j < cfgBlocks[i].entryCount;j++)
if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
{
if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
if(cfgBlocks[i].entries[j].value[0])
return cfgBlocks[i].entries[j].value;
return def;
}
}
}
@@ -297,6 +302,12 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
return def;
}
int ConfigValueExists(const char *blockName, const char *keyName)
{
const char *val = GetConfigValue(blockName, keyName, "");
return !!val[0];
}
int GetConfigValueInt(const char *blockName, const char *keyName, int def)
{
const char *val = GetConfigValue(blockName, keyName, "");
@@ -316,3 +327,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, int 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);
}
+196
View File
@@ -0,0 +1,196 @@
/**
* 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"
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;
ALfloat Gain[MAXCHANNELS];
FILTER iirFilter;
ALfloat history[2];
} ALechoState;
static ALvoid EchoDestroy(ALeffectState *effect)
{
ALechoState *state = (ALechoState*)effect;
if(state)
{
free(state->SampleBuffer);
state->SampleBuffer = NULL;
free(state);
}
}
static 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) + 1;
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
maxlen = NextPowerOf2(maxlen);
if(maxlen != state->BufferLength)
{
void *temp;
temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat));
if(!temp)
return AL_FALSE;
state->SampleBuffer = temp;
state->BufferLength = maxlen;
}
for(i = 0;i < state->BufferLength;i++)
state->SampleBuffer[i] = 0.0f;
for(i = 0;i < MAXCHANNELS;i++)
state->Gain[i] = 0.0f;
for(i = 0;i < Device->NumChan;i++)
{
Channel chan = Device->Speaker2Chan[i];
state->Gain[chan] = 1.0f;
}
return AL_TRUE;
}
static 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) + 1;
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;
}
static ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
{
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] += state->Gain[FRONT_LEFT] * samp[0];
SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp[1];
SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp[0];
SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp[1];
SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp[0];
SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp[1];
}
state->Offset = offset;
}
ALeffectState *EchoCreate(void)
{
ALechoState *state;
state = malloc(sizeof(*state));
if(!state)
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;
}
+205
View File
@@ -0,0 +1,205 @@
/**
* 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"
typedef struct ALmodulatorState {
// Must be first in all effects!
ALeffectState state;
enum {
SINUSOID,
SAWTOOTH,
SQUARE
} Waveform;
ALuint index;
ALuint step;
ALfloat Gain[MAXCHANNELS];
FILTER iirFilter;
ALfloat history[1];
} ALmodulatorState;
#define WAVEFORM_FRACBITS 16
#define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1)
static __inline ALfloat sin_func(ALuint index)
{
return sin(index / (double)(1<<WAVEFORM_FRACBITS) * M_PI * 2.0f);
}
static __inline ALfloat saw_func(ALuint index)
{
return index*2.0f/(1<<WAVEFORM_FRACBITS) - 1.0f;
}
static __inline ALfloat square_func(ALuint index)
{
return ((index>>(WAVEFORM_FRACBITS-1))&1) ? -1.0f : 1.0f;
}
static __inline ALfloat hpFilter1P(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;
return input - output;
}
static ALvoid ModulatorDestroy(ALeffectState *effect)
{
ALmodulatorState *state = (ALmodulatorState*)effect;
free(state);
}
static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
{
ALmodulatorState *state = (ALmodulatorState*)effect;
ALuint index;
for(index = 0;index < MAXCHANNELS;index++)
state->Gain[index] = 0.0f;
for(index = 0;index < Device->NumChan;index++)
{
Channel chan = Device->Speaker2Chan[index];
state->Gain[chan] = 1.0f;
}
return AL_TRUE;
}
static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
{
ALmodulatorState *state = (ALmodulatorState*)effect;
ALfloat cw, a = 0.0f;
if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
state->Waveform = SINUSOID;
else if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
state->Waveform = SAWTOOTH;
else if(Effect->Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
state->Waveform = SQUARE;
state->step = Effect->Modulator.Frequency*(1<<WAVEFORM_FRACBITS) /
Context->Device->Frequency;
if(!state->step)
state->step = 1;
cw = cos(2.0*M_PI * Effect->Modulator.HighPassCutoff / Context->Device->Frequency);
a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f);
state->iirFilter.coeff = a;
}
static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
{
ALmodulatorState *state = (ALmodulatorState*)effect;
const ALfloat gain = Slot->Gain;
const ALuint step = state->step;
ALuint index = state->index;
ALfloat samp;
ALuint i;
switch(state->Waveform)
{
case SINUSOID:
for(i = 0;i < SamplesToDo;i++)
{
#define FILTER_OUT(func) do { \
samp = SamplesIn[i]; \
\
index += step; \
index &= WAVEFORM_FRACMASK; \
samp *= func(index); \
\
samp = hpFilter1P(&state->iirFilter, 0, samp); \
\
/* Apply slot gain */ \
samp *= gain; \
\
SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \
SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \
SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \
SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \
SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \
SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \
SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \
SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \
} while(0)
FILTER_OUT(sin_func);
}
break;
case SAWTOOTH:
for(i = 0;i < SamplesToDo;i++)
{
FILTER_OUT(saw_func);
}
break;
case SQUARE:
for(i = 0;i < SamplesToDo;i++)
{
FILTER_OUT(square_func);
#undef FILTER_OUT
}
break;
}
state->index = index;
}
ALeffectState *ModulatorCreate(void)
{
ALmodulatorState *state;
state = malloc(sizeof(*state));
if(!state)
return NULL;
state->state.Destroy = ModulatorDestroy;
state->state.DeviceUpdate = ModulatorDeviceUpdate;
state->state.Update = ModulatorUpdate;
state->state.Process = ModulatorProcess;
state->index = 0.0f;
state->step = 1.0f;
state->iirFilter.coeff = 0.0f;
state->iirFilter.history[0] = 0.0f;
return &state->state;
}
+1348
View File
File diff suppressed because it is too large Load Diff
+21 -13
View File
@@ -46,7 +46,7 @@ RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length)
ring->frame_size = frame_size;
ring->length = length+1;
ring->write_pos = 1;
ring->mem = malloc((length+1)*frame_size);
ring->mem = malloc(ring->length * ring->frame_size);
if(!ring->mem)
{
free(ring);
@@ -81,33 +81,41 @@ 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);
if((ring->read_pos-ring->write_pos+ring->length)%ring->length < len)
ring->read_pos = (ring->write_pos+len) % ring->length;
remain = (ring->read_pos-ring->write_pos+ring->length) % ring->length;
if(remain < len) len = remain;
if(remain < len)
if(len > 0)
{
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, remain*ring->frame_size);
memcpy(ring->mem, data+(remain*ring->frame_size), (len-remain)*ring->frame_size);
}
else
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, len*ring->frame_size);
remain = ring->length - ring->write_pos;
if(remain < len)
{
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
remain*ring->frame_size);
memcpy(ring->mem, data+(remain*ring->frame_size),
(len-remain)*ring->frame_size);
}
else
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
len*ring->frame_size);
ring->write_pos += len;
ring->write_pos %= ring->length;
ring->write_pos += len;
ring->write_pos %= ring->length;
}
LeaveCriticalSection(&ring->cs);
}
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);
+12 -9
View File
@@ -47,13 +47,14 @@ static DWORD CALLBACK StarterFunc(void *ptr)
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
{
DWORD dummy;
ThreadInfo *inf = malloc(sizeof(ThreadInfo));
if(!inf) return 0;
inf->func = func;
inf->ptr = ptr;
inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, NULL);
inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, &dummy);
if(!inf->thread)
{
free(inf);
@@ -70,6 +71,7 @@ ALuint StopThread(ALvoid *thread)
WaitForSingleObject(inf->thread, INFINITE);
GetExitCodeThread(inf->thread, &ret);
CloseHandle(inf->thread);
free(inf);
@@ -83,22 +85,21 @@ ALuint StopThread(ALvoid *thread)
typedef struct {
ALuint (*func)(ALvoid*);
ALvoid *ptr;
ALuint ret;
pthread_t thread;
} ThreadInfo;
static void *StarterFunc(void *ptr)
{
ThreadInfo *inf = (ThreadInfo*)ptr;
ALint ret;
ret = inf->func(inf->ptr);
return (void*)ret;
inf->ret = inf->func(inf->ptr);
return NULL;
}
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
{
ThreadInfo *inf = malloc(sizeof(ThreadInfo));
if(!inf) return 0;
if(!inf) return NULL;
inf->func = func;
inf->ptr = ptr;
@@ -114,12 +115,14 @@ ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
ALuint StopThread(ALvoid *thread)
{
ThreadInfo *inf = thread;
void *ret;
ALuint ret;
pthread_join(inf->thread, NULL);
ret = inf->ret;
pthread_join(inf->thread, &ret);
free(inf);
return (ALuint)ret;
return ret;
}
#endif
+657 -517
View File
File diff suppressed because it is too large Load Diff
+201 -203
View File
@@ -1,203 +1,201 @@
/*-
* Copyright (c) 2005 Boris Mikhaylov
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <math.h>
#include "bs2b.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* Single pole IIR filter.
* O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
*/
/* Lowpass filter */
#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
/* Highboost filter */
#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
/* Set up all data. */
static void init(struct bs2b *bs2b)
{
double Fc_lo, Fc_hi;
double G_lo, G_hi;
double x;
if ((bs2b->srate > 192000) || (bs2b->srate < 2000))
bs2b->srate = BS2B_DEFAULT_SRATE;
switch(bs2b->level)
{
case BS2B_LOW_CLEVEL: /* Low crossfeed level */
Fc_lo = 360.0;
Fc_hi = 501.0;
G_lo = 0.398107170553497;
G_hi = 0.205671765275719;
break;
case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */
Fc_lo = 500.0;
Fc_hi = 711.0;
G_lo = 0.459726988530872;
G_hi = 0.228208484414988;
break;
case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */
Fc_lo = 700.0;
Fc_hi = 1021.0;
G_lo = 0.530884444230988;
G_hi = 0.250105790667544;
break;
case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */
Fc_lo = 360.0;
Fc_hi = 494.0;
G_lo = 0.316227766016838;
G_hi = 0.168236228897329;
break;
case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */
Fc_lo = 500.0;
Fc_hi = 689.0;
G_lo = 0.354813389233575;
G_hi = 0.187169483835901;
break;
default: /* High easy crossfeed level */
bs2b->level = BS2B_HIGH_ECLEVEL;
Fc_lo = 700.0;
Fc_hi = 975.0;
G_lo = 0.398107170553497;
G_hi = 0.205671765275719;
break;
} /* switch */
/* $fc = $Fc / $s;
* $d = 1 / 2 / pi / $fc;
* $x = exp(-1 / $d);
*/
x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate);
bs2b->b1_lo = x;
bs2b->a0_lo = G_lo * (1.0 - x);
x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate);
bs2b->b1_hi = x;
bs2b->a0_hi = 1.0 - G_hi * (1.0 - x);
bs2b->a1_hi = -x;
bs2b->gain = 1.0 / (1.0 - G_hi + G_lo);
bs2b_clear(bs2b);
} /* init */
/* Exported functions.
* See descriptions in "bs2b.h"
*/
void bs2b_set_level(struct bs2b *bs2b, int level)
{
if(level == bs2b->level)
return;
bs2b->level = level;
init(bs2b);
} /* bs2b_set_level */
int bs2b_get_level(struct bs2b *bs2b)
{
return bs2b->level;
} /* bs2b_get_level */
void bs2b_set_srate(struct bs2b *bs2b, int srate)
{
if (srate == bs2b->srate)
return;
bs2b->srate = srate;
init(bs2b);
} /* bs2b_set_srate */
int bs2b_get_srate(struct bs2b *bs2b)
{
return bs2b->srate;
} /* bs2b_get_srate */
void bs2b_clear(struct bs2b *bs2b)
{
int loopv = sizeof(bs2b->last_sample);
while (loopv)
{
((char *)&bs2b->last_sample)[--loopv] = 0;
}
} /* bs2b_clear */
int bs2b_is_clear(struct bs2b *bs2b)
{
int loopv = sizeof(bs2b->last_sample);
while (loopv)
{
if (((char *)&bs2b->last_sample)[--loopv] != 0)
return 0;
}
return 1;
} /* bs2b_is_clear */
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
{
/* Lowpass filter */
bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
/* Highboost filter */
bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
bs2b->last_sample.asis[0] = sample[0];
bs2b->last_sample.asis[1] = sample[1];
/* Crossfeed */
sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
/* Bass boost cause allpass attenuation */
sample[0] *= bs2b->gain;
sample[1] *= bs2b->gain;
/* Clipping of overloaded samples */
#if 0
if (sample[0] > 1.0)
sample[0] = 1.0;
if (sample[0] < -1.0)
sample[0] = -1.0;
if (sample[1] > 1.0)
sample[1] = 1.0;
if (sample[1] < -1.0)
sample[1] = -1.0;
#endif
} /* bs2b_cross_feed */
/*-
* Copyright (c) 2005 Boris Mikhaylov
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <math.h>
#include "bs2b.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/* Single pole IIR filter.
* O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
*/
/* Lowpass filter */
#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
/* Highboost filter */
#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
/* Set up all data. */
static void init(struct bs2b *bs2b)
{
double Fc_lo, Fc_hi;
double G_lo, G_hi;
double x;
if ((bs2b->srate > 192000) || (bs2b->srate < 2000))
bs2b->srate = BS2B_DEFAULT_SRATE;
switch(bs2b->level)
{
case BS2B_LOW_CLEVEL: /* Low crossfeed level */
Fc_lo = 360.0;
Fc_hi = 501.0;
G_lo = 0.398107170553497;
G_hi = 0.205671765275719;
break;
case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */
Fc_lo = 500.0;
Fc_hi = 711.0;
G_lo = 0.459726988530872;
G_hi = 0.228208484414988;
break;
case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */
Fc_lo = 700.0;
Fc_hi = 1021.0;
G_lo = 0.530884444230988;
G_hi = 0.250105790667544;
break;
case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */
Fc_lo = 360.0;
Fc_hi = 494.0;
G_lo = 0.316227766016838;
G_hi = 0.168236228897329;
break;
case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */
Fc_lo = 500.0;
Fc_hi = 689.0;
G_lo = 0.354813389233575;
G_hi = 0.187169483835901;
break;
default: /* High easy crossfeed level */
bs2b->level = BS2B_HIGH_ECLEVEL;
Fc_lo = 700.0;
Fc_hi = 975.0;
G_lo = 0.398107170553497;
G_hi = 0.205671765275719;
break;
} /* switch */
/* $fc = $Fc / $s;
* $d = 1 / 2 / pi / $fc;
* $x = exp(-1 / $d);
*/
x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate);
bs2b->b1_lo = x;
bs2b->a0_lo = G_lo * (1.0 - x);
x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate);
bs2b->b1_hi = x;
bs2b->a0_hi = 1.0 - G_hi * (1.0 - x);
bs2b->a1_hi = -x;
bs2b->gain = 1.0 / (1.0 - G_hi + G_lo);
} /* init */
/* Exported functions.
* See descriptions in "bs2b.h"
*/
void bs2b_set_level(struct bs2b *bs2b, int level)
{
if(level == bs2b->level)
return;
bs2b->level = level;
init(bs2b);
} /* bs2b_set_level */
int bs2b_get_level(struct bs2b *bs2b)
{
return bs2b->level;
} /* bs2b_get_level */
void bs2b_set_srate(struct bs2b *bs2b, int srate)
{
if (srate == bs2b->srate)
return;
bs2b->srate = srate;
init(bs2b);
} /* bs2b_set_srate */
int bs2b_get_srate(struct bs2b *bs2b)
{
return bs2b->srate;
} /* bs2b_get_srate */
void bs2b_clear(struct bs2b *bs2b)
{
int loopv = sizeof(bs2b->last_sample);
while (loopv)
{
((char *)&bs2b->last_sample)[--loopv] = 0;
}
} /* bs2b_clear */
int bs2b_is_clear(struct bs2b *bs2b)
{
int loopv = sizeof(bs2b->last_sample);
while (loopv)
{
if (((char *)&bs2b->last_sample)[--loopv] != 0)
return 0;
}
return 1;
} /* bs2b_is_clear */
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
{
/* Lowpass filter */
bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
/* Highboost filter */
bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
bs2b->last_sample.asis[0] = sample[0];
bs2b->last_sample.asis[1] = sample[1];
/* Crossfeed */
sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
/* Bass boost cause allpass attenuation */
sample[0] *= bs2b->gain;
sample[1] *= bs2b->gain;
/* Clipping of overloaded samples */
#if 0
if (sample[0] > 1.0)
sample[0] = 1.0;
if (sample[0] < -1.0)
sample[0] = -1.0;
if (sample[1] > 1.0)
sample[1] = 1.0;
if (sample[1] < -1.0)
sample[1] = -1.0;
#endif
} /* bs2b_cross_feed */
+314 -119
View File
@@ -27,20 +27,31 @@
#include <memory.h>
#include <dsound.h>
#include <cguid.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, just assume 4 fragments
#define DS_FRAGS 4
typedef struct {
// DirectSound Playback Device
@@ -48,7 +59,7 @@ typedef struct {
LPDIRECTSOUNDBUFFER DSpbuffer;
LPDIRECTSOUNDBUFFER DSsbuffer;
int killNow;
volatile int killNow;
ALvoid *thread;
} DSoundData;
@@ -57,70 +68,192 @@ typedef struct {
ALCchar *name;
GUID guid;
} DevMap;
static DevMap DeviceList[16];
static const ALCchar dsDevice[] = "DirectSound Default";
static DevMap *DeviceList;
static ALuint NumDevices;
void *DSoundLoad(void)
{
if(!ds_handle)
{
#ifdef _WIN32
ds_handle = LoadLibraryA("dsound.dll");
if(ds_handle == NULL)
{
AL_PRINT("Failed to load dsound.dll\n");
return NULL;
}
#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 NULL; \
} \
} while(0)
#else
ds_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
LOAD_FUNC(DirectSoundCreate);
LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
}
return ds_handle;
}
static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
{
char str[1024];
void *temp;
int count;
ALuint i;
(void)data;
(void)drvname;
if(NumDevices == 0)
{
temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1));
if(temp)
{
DeviceList = temp;
DeviceList[NumDevices].name = strdup(dsDevice);
DeviceList[NumDevices].guid = GUID_NULL;
NumDevices++;
}
}
if(!guid)
return TRUE;
count = 0;
do {
if(count == 0)
snprintf(str, sizeof(str), "%s via DirectSound", desc);
else
snprintf(str, sizeof(str), "%s #%d via DirectSound", desc, count+1);
count++;
for(i = 0;i < NumDevices;i++)
{
if(strcmp(str, DeviceList[i].name) == 0)
break;
}
} while(i != NumDevices);
temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1));
if(temp)
{
DeviceList = temp;
DeviceList[NumDevices].name = strdup(str);
DeviceList[NumDevices].guid = *guid;
NumDevices++;
}
return TRUE;
}
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;
BOOL Playing = FALSE;
DWORD FrameSize;
DWORD FragSize;
DWORD avail;
HRESULT err;
BufferSize = pDevice->UpdateSize * DS_FRAGS *
aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format);
SetRTPriority();
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 = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
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 == 0)
if(avail < FragSize)
{
if(!Playing)
{
err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
if(FAILED(err))
{
AL_PRINT("Failed to play buffer: 0x%lx\n", err);
aluHandleDisconnect(pDevice);
return 1;
}
Playing = TRUE;
}
Sleep(1);
continue;
}
avail -= avail%FragSize;
// Lock output buffer
WriteCnt1 = 0;
WriteCnt2 = 0;
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
// If the buffer is lost, restore it, play and lock
// If the buffer is lost, restore it and lock
if(err == DSERR_BUFFERLOST)
{
err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
if(SUCCEEDED(err))
err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
if(SUCCEEDED(err))
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
{
Playing = FALSE;
LastCursor = 0;
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
}
}
// Successfully locked the output buffer
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);
}
else
{
AL_PRINT("Buffer lock error: %#lx\n", err);
aluHandleDisconnect(pDevice);
return 1;
}
// Update old write cursor location
LastCursor += WriteCnt1+WriteCnt2;
LastCursor %= BufferSize;
LastCursor %= DSBCaps.dwBufferBytes;
}
return 0;
@@ -128,67 +261,121 @@ 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(deviceName)
if(!DSoundLoad())
return ALC_FALSE;
if(!deviceName)
deviceName = dsDevice;
else if(strcmp(deviceName, dsDevice) != 0)
{
int i;
for(i = 0;DeviceList[i].name;i++)
ALuint i;
if(!DeviceList)
{
hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL);
if(FAILED(hr))
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
}
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;
break;
}
}
if(!DeviceList[i].name)
if(i == NumDevices)
return ALC_FALSE;
}
else
device->szDeviceName = DeviceList[0].name;
memset(&OutputType, 0, sizeof(OutputType));
//Initialise requested device
pData = calloc(1, sizeof(DSoundData));
if(!pData)
{
SetALCError(ALC_OUT_OF_MEMORY);
alcSetError(device, ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
//DirectSound Init code
hr = DirectSoundCreate(guid, &pData->lpDS, NULL);
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);
else
if(pData->lpDS)
IDirectSound_Release(pData->lpDS);
free(pData);
AL_PRINT("Device init failed: 0x%08lx\n", hr);
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;
}
static ALCboolean DSoundResetPlayback(ALCdevice *device)
{
DSoundData *pData = (DSoundData*)device->ExtraData;
DSBUFFERDESC DSBDescription;
WAVEFORMATEXTENSIBLE OutputType;
DWORD speakers;
HRESULT hr;
memset(&OutputType, 0, sizeof(OutputType));
switch(device->FmtType)
{
case DevFmtByte:
device->FmtType = DevFmtUByte;
break;
case DevFmtUShort:
device->FmtType = DevFmtShort;
break;
case DevFmtUByte:
case DevFmtShort:
case DevFmtFloat:
break;
}
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format"))
{
switch(device->FmtChans)
{
if(device->Format == AL_FORMAT_MONO8 || device->Format == AL_FORMAT_MONO16)
case DevFmtMono:
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
else if(device->Format == AL_FORMAT_STEREO8 || device->Format == AL_FORMAT_STEREO16)
break;
case DevFmtStereo:
speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
else if(device->Format == AL_FORMAT_QUAD8 || device->Format == AL_FORMAT_QUAD16)
break;
case DevFmtQuad:
speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
else if(device->Format == AL_FORMAT_51CHN8 || device->Format == AL_FORMAT_51CHN16)
break;
case DevFmtX51:
speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
else if(device->Format == AL_FORMAT_71CHN8 || device->Format == AL_FORMAT_71CHN16)
break;
case DevFmtX61:
/* ??? */;
break;
case DevFmtX71:
speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
else
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
break;
}
}
if(SUCCEEDED(hr))
@@ -196,24 +383,18 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
speakers = DSSPEAKER_CONFIG(speakers);
if(speakers == DSSPEAKER_MONO)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_MONO8;
else
device->Format = AL_FORMAT_MONO16;
device->FmtChans = DevFmtMono;
OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
}
else if(speakers == DSSPEAKER_STEREO)
else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_STEREO8;
else
device->Format = AL_FORMAT_STEREO16;
device->FmtChans = DevFmtStereo;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT;
}
else if(speakers == DSSPEAKER_QUAD)
{
if(aluBytesFromFormat(device->Format) == 1)
device->Format = AL_FORMAT_QUAD8;
else
device->Format = AL_FORMAT_QUAD16;
device->FmtChans = DevFmtQuad;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_BACK_LEFT |
@@ -221,10 +402,7 @@ 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;
device->FmtChans = DevFmtX51;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
@@ -234,10 +412,7 @@ 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;
device->FmtChans = DevFmtX71;
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
SPEAKER_FRONT_RIGHT |
SPEAKER_FRONT_CENTER |
@@ -247,26 +422,25 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
SPEAKER_SIDE_LEFT |
SPEAKER_SIDE_RIGHT;
}
frameSize = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
OutputType.Format.nChannels = aluChannelsFromFormat(device->Format);
OutputType.Format.wBitsPerSample = aluBytesFromFormat(device->Format) * 8;
OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 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 /= DS_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
{
@@ -286,17 +460,15 @@ 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 * DS_FRAGS * frameSize;
DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates *
OutputType.Format.nBlockAlign;
DSBDescription.lpwfxFormat=&OutputType.Format;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
}
if(SUCCEEDED(hr))
hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
if(SUCCEEDED(hr))
{
device->ExtraData = pData;
SetDefaultWFXChannelOrder(device);
pData->thread = StartThread(DSoundProc, device);
if(!pData->thread)
hr = E_FAIL;
@@ -306,42 +478,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;
}
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;
pData->killNow = 0;
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;
}
@@ -377,6 +548,8 @@ static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
BackendFuncs DSoundFuncs = {
DSoundOpenPlayback,
DSoundClosePlayback,
DSoundResetPlayback,
DSoundStopPlayback,
DSoundOpenCapture,
DSoundCloseCapture,
DSoundStartCapture,
@@ -385,33 +558,55 @@ BackendFuncs DSoundFuncs = {
DSoundAvailableSamples
};
static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
{
size_t *iter = 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)++;
}
else
DeviceList[0].name = AppendDeviceList("DirectSound Software");
return TRUE;
}
void alcDSoundInit(BackendFuncs *FuncList)
{
size_t iter = 1;
HRESULT hr;
*FuncList = DSoundFuncs;
hr = DirectSoundEnumerate(DSoundEnumDevices, &iter);
if(FAILED(hr))
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
}
void alcDSoundDeinit(void)
{
ALuint i;
for(i = 0;i < NumDevices;++i)
free(DeviceList[i].name);
free(DeviceList);
DeviceList = NULL;
NumDevices = 0;
if(ds_handle)
{
#ifdef _WIN32
FreeLibrary(ds_handle);
#endif
ds_handle = NULL;
}
}
void alcDSoundProbe(int type)
{
if(!DSoundLoad()) return;
if(type == DEVICE_PROBE)
AppendDeviceList(dsDevice);
else if(type == ALL_DEVICE_PROBE)
{
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);
else
{
for(i = 0;i < NumDevices;i++)
AppendAllDeviceList(DeviceList[i].name);
}
}
}
+808
View File
@@ -0,0 +1,808 @@
/**
* 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 <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alSource.h"
#include "alBuffer.h"
#include "alListener.h"
#include "alAuxEffectSlot.h"
#include "alu.h"
#include "bs2b.h"
static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac)
{ return vals[0]; (void)step; (void)frac; }
static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac)
{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)); }
static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac)
{ return cubic(vals[-step], vals[0], vals[step], vals[step+step],
frac * (1.0/FRACTIONONE)); }
static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac)
{ return vals[0] * (1.0/32767.0); (void)step; (void)frac; }
static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac)
{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac)
{ return cubic(vals[-step], vals[0], vals[step], vals[step+step],
frac * (1.0/FRACTIONONE)) * (1.0/32767.0); }
static __inline ALdouble point8(const ALubyte *vals, ALint step, ALint frac)
{ return (vals[0]-128.0) * (1.0/127.0); (void)step; (void)frac; }
static __inline ALdouble lerp8(const ALubyte *vals, ALint step, ALint frac)
{ return (lerp(vals[0], vals[step],
frac * (1.0/FRACTIONONE))-128.0) * (1.0/127.0); }
static __inline ALdouble cubic8(const ALubyte *vals, ALint step, ALint frac)
{ return (cubic(vals[-step], vals[0], vals[step], vals[step+step],
frac * (1.0/FRACTIONONE))-128.0) * (1.0/127.0); }
#define DECL_TEMPLATE(T, sampler) \
static void Mix_##T##_1_##sampler(ALsource *Source, ALCdevice *Device, \
const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
ALfloat (*DryBuffer)[MAXCHANNELS]; \
ALfloat *ClickRemoval, *PendingClicks; \
ALuint pos, frac; \
ALfloat DrySend[MAXCHANNELS]; \
FILTER *DryFilter; \
ALuint BufferIdx; \
ALuint increment; \
ALuint out, c; \
ALfloat value; \
\
increment = Source->Params.Step; \
\
DryBuffer = Device->DryBuffer; \
ClickRemoval = Device->ClickRemoval; \
PendingClicks = Device->PendingClicks; \
DryFilter = &Source->Params.iirFilter; \
for(c = 0;c < MAXCHANNELS;c++) \
DrySend[c] = Source->Params.DryGains[0][c]; \
\
pos = 0; \
frac = *DataPosFrac; \
\
if(OutPos == 0) \
{ \
value = sampler(data+pos, 1, frac); \
\
value = lpFilter4PC(DryFilter, 0, value); \
for(c = 0;c < MAXCHANNELS;c++) \
ClickRemoval[c] -= value*DrySend[c]; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
/* First order interpolator */ \
value = sampler(data+pos, 1, frac); \
\
/* Direct path final mix buffer and panning */ \
value = lpFilter4P(DryFilter, 0, value); \
for(c = 0;c < MAXCHANNELS;c++) \
DryBuffer[OutPos][c] += value*DrySend[c]; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(OutPos == SamplesToDo) \
{ \
value = sampler(data+pos, 1, frac); \
\
value = lpFilter4PC(DryFilter, 0, value); \
for(c = 0;c < MAXCHANNELS;c++) \
PendingClicks[c] += value*DrySend[c]; \
} \
\
for(out = 0;out < Device->NumAuxSends;out++) \
{ \
ALfloat WetSend; \
ALfloat *WetBuffer; \
ALfloat *WetClickRemoval; \
ALfloat *WetPendingClicks; \
FILTER *WetFilter; \
\
if(!Source->Send[out].Slot || \
Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
continue; \
\
WetBuffer = Source->Send[out].Slot->WetBuffer; \
WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
pos = 0; \
frac = *DataPosFrac; \
OutPos -= BufferSize; \
\
if(OutPos == 0) \
{ \
value = sampler(data+pos, 1, frac); \
\
value = lpFilter2PC(WetFilter, 0, value); \
WetClickRemoval[0] -= value*WetSend; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
/* First order interpolator */ \
value = sampler(data+pos, 1, frac); \
\
/* Room path final mix buffer and panning */ \
value = lpFilter2P(WetFilter, 0, value); \
WetBuffer[OutPos] += value*WetSend; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(OutPos == SamplesToDo) \
{ \
value = sampler(data+pos, 1, frac); \
\
value = lpFilter2PC(WetFilter, 0, value); \
WetPendingClicks[0] += value*WetSend; \
} \
} \
*DataPosInt += pos; \
*DataPosFrac = frac; \
}
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
DECL_TEMPLATE(ALfloat, cubic32)
DECL_TEMPLATE(ALshort, point16)
DECL_TEMPLATE(ALshort, lerp16)
DECL_TEMPLATE(ALshort, cubic16)
DECL_TEMPLATE(ALubyte, point8)
DECL_TEMPLATE(ALubyte, lerp8)
DECL_TEMPLATE(ALubyte, cubic8)
#undef DECL_TEMPLATE
#define DECL_TEMPLATE(T, chnct, sampler) \
static void Mix_##T##_##chnct##_##sampler(ALsource *Source, ALCdevice *Device,\
const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
const ALuint Channels = chnct; \
const ALfloat scaler = 1.0f/chnct; \
ALfloat (*DryBuffer)[MAXCHANNELS]; \
ALfloat *ClickRemoval, *PendingClicks; \
ALuint pos, frac; \
ALfloat DrySend[chnct][MAXCHANNELS]; \
FILTER *DryFilter; \
ALuint BufferIdx; \
ALuint increment; \
ALuint i, out, c; \
ALfloat value; \
\
increment = Source->Params.Step; \
\
DryBuffer = Device->DryBuffer; \
ClickRemoval = Device->ClickRemoval; \
PendingClicks = Device->PendingClicks; \
DryFilter = &Source->Params.iirFilter; \
for(i = 0;i < Channels;i++) \
{ \
for(c = 0;c < MAXCHANNELS;c++) \
DrySend[i][c] = Source->Params.DryGains[i][c]; \
} \
\
pos = 0; \
frac = *DataPosFrac; \
\
if(OutPos == 0) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter2PC(DryFilter, i*2, value); \
for(c = 0;c < MAXCHANNELS;c++) \
ClickRemoval[c] -= value*DrySend[i][c]; \
} \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter2P(DryFilter, i*2, value); \
for(c = 0;c < MAXCHANNELS;c++) \
DryBuffer[OutPos][c] += value*DrySend[i][c]; \
} \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(OutPos == SamplesToDo) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter2PC(DryFilter, i*2, value); \
for(c = 0;c < MAXCHANNELS;c++) \
PendingClicks[c] += value*DrySend[i][c]; \
} \
} \
\
for(out = 0;out < Device->NumAuxSends;out++) \
{ \
ALfloat WetSend; \
ALfloat *WetBuffer; \
ALfloat *WetClickRemoval; \
ALfloat *WetPendingClicks; \
FILTER *WetFilter; \
\
if(!Source->Send[out].Slot || \
Source->Send[out].Slot->effect.type == AL_EFFECT_NULL) \
continue; \
\
WetBuffer = Source->Send[out].Slot->WetBuffer; \
WetClickRemoval = Source->Send[out].Slot->ClickRemoval; \
WetPendingClicks = Source->Send[out].Slot->PendingClicks; \
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
pos = 0; \
frac = *DataPosFrac; \
OutPos -= BufferSize; \
\
if(OutPos == 0) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter1PC(WetFilter, i, value); \
WetClickRemoval[0] -= value*WetSend * scaler; \
} \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter1P(WetFilter, i, value); \
WetBuffer[OutPos] += value*WetSend * scaler; \
} \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(OutPos == SamplesToDo) \
{ \
for(i = 0;i < Channels;i++) \
{ \
value = sampler(data + pos*Channels + i, Channels, frac); \
\
value = lpFilter1PC(WetFilter, i, value); \
WetPendingClicks[0] += value*WetSend * scaler; \
} \
} \
} \
*DataPosInt += pos; \
*DataPosFrac = frac; \
}
DECL_TEMPLATE(ALfloat, 2, point32)
DECL_TEMPLATE(ALfloat, 2, lerp32)
DECL_TEMPLATE(ALfloat, 2, cubic32)
DECL_TEMPLATE(ALshort, 2, point16)
DECL_TEMPLATE(ALshort, 2, lerp16)
DECL_TEMPLATE(ALshort, 2, cubic16)
DECL_TEMPLATE(ALubyte, 2, point8)
DECL_TEMPLATE(ALubyte, 2, lerp8)
DECL_TEMPLATE(ALubyte, 2, cubic8)
DECL_TEMPLATE(ALfloat, 4, point32)
DECL_TEMPLATE(ALfloat, 4, lerp32)
DECL_TEMPLATE(ALfloat, 4, cubic32)
DECL_TEMPLATE(ALshort, 4, point16)
DECL_TEMPLATE(ALshort, 4, lerp16)
DECL_TEMPLATE(ALshort, 4, cubic16)
DECL_TEMPLATE(ALubyte, 4, point8)
DECL_TEMPLATE(ALubyte, 4, lerp8)
DECL_TEMPLATE(ALubyte, 4, cubic8)
DECL_TEMPLATE(ALfloat, 6, point32)
DECL_TEMPLATE(ALfloat, 6, lerp32)
DECL_TEMPLATE(ALfloat, 6, cubic32)
DECL_TEMPLATE(ALshort, 6, point16)
DECL_TEMPLATE(ALshort, 6, lerp16)
DECL_TEMPLATE(ALshort, 6, cubic16)
DECL_TEMPLATE(ALubyte, 6, point8)
DECL_TEMPLATE(ALubyte, 6, lerp8)
DECL_TEMPLATE(ALubyte, 6, cubic8)
DECL_TEMPLATE(ALfloat, 7, point32)
DECL_TEMPLATE(ALfloat, 7, lerp32)
DECL_TEMPLATE(ALfloat, 7, cubic32)
DECL_TEMPLATE(ALshort, 7, point16)
DECL_TEMPLATE(ALshort, 7, lerp16)
DECL_TEMPLATE(ALshort, 7, cubic16)
DECL_TEMPLATE(ALubyte, 7, point8)
DECL_TEMPLATE(ALubyte, 7, lerp8)
DECL_TEMPLATE(ALubyte, 7, cubic8)
DECL_TEMPLATE(ALfloat, 8, point32)
DECL_TEMPLATE(ALfloat, 8, lerp32)
DECL_TEMPLATE(ALfloat, 8, cubic32)
DECL_TEMPLATE(ALshort, 8, point16)
DECL_TEMPLATE(ALshort, 8, lerp16)
DECL_TEMPLATE(ALshort, 8, cubic16)
DECL_TEMPLATE(ALubyte, 8, point8)
DECL_TEMPLATE(ALubyte, 8, lerp8)
DECL_TEMPLATE(ALubyte, 8, cubic8)
#undef DECL_TEMPLATE
#define DECL_TEMPLATE(T, sampler) \
static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
enum FmtChannels FmtChannels, \
const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
switch(FmtChannels) \
{ \
case FmtMono: \
Mix_##T##_1_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
case FmtStereo: \
case FmtRear: \
Mix_##T##_2_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
case FmtQuad: \
Mix_##T##_4_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
case FmtX51: \
Mix_##T##_6_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
case FmtX61: \
Mix_##T##_7_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
case FmtX71: \
Mix_##T##_8_##sampler(Source, Device, Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
} \
}
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
DECL_TEMPLATE(ALfloat, cubic32)
DECL_TEMPLATE(ALshort, point16)
DECL_TEMPLATE(ALshort, lerp16)
DECL_TEMPLATE(ALshort, cubic16)
DECL_TEMPLATE(ALubyte, point8)
DECL_TEMPLATE(ALubyte, lerp8)
DECL_TEMPLATE(ALubyte, cubic8)
#undef DECL_TEMPLATE
#define DECL_TEMPLATE(sampler) \
static void Mix_##sampler(ALsource *Source, ALCdevice *Device, \
enum FmtChannels FmtChannels, enum FmtType FmtType, \
const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
switch(FmtType) \
{ \
case FmtUByte: \
Mix_ALubyte_##sampler##8(Source, Device, FmtChannels, \
Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
\
case FmtShort: \
Mix_ALshort_##sampler##16(Source, Device, FmtChannels, \
Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
\
case FmtFloat: \
Mix_ALfloat_##sampler##32(Source, Device, FmtChannels, \
Data, DataPosInt, DataPosFrac, \
OutPos, SamplesToDo, BufferSize); \
break; \
} \
}
DECL_TEMPLATE(point)
DECL_TEMPLATE(lerp)
DECL_TEMPLATE(cubic)
#undef DECL_TEMPLATE
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
{
ALbufferlistitem *BufferListItem;
ALuint DataPosInt, DataPosFrac;
enum FmtChannels FmtChannels;
enum FmtType FmtType;
ALuint BuffersPlayed;
ALboolean Looping;
ALuint increment;
resampler_t Resampler;
ALenum State;
ALuint OutPos;
ALuint FrameSize;
ALint64 DataSize64;
ALuint i;
/* Get source info */
State = Source->state;
BuffersPlayed = Source->BuffersPlayed;
DataPosInt = Source->position;
DataPosFrac = Source->position_fraction;
Looping = Source->bLooping;
increment = Source->Params.Step;
Resampler = (increment == FRACTIONONE) ? POINT_RESAMPLER :
Source->Resampler;
/* Get buffer info */
FrameSize = 0;
FmtChannels = FmtMono;
FmtType = FmtUByte;
BufferListItem = Source->queue;
for(i = 0;i < Source->BuffersInQueue;i++)
{
const ALbuffer *ALBuffer;
if((ALBuffer=BufferListItem->buffer) != NULL)
{
FmtChannels = ALBuffer->FmtChannels;
FmtType = ALBuffer->FmtType;
FrameSize = FrameSizeFromFmt(FmtChannels, FmtType);
break;
}
BufferListItem = BufferListItem->next;
}
/* Get current buffer queue item */
BufferListItem = Source->queue;
for(i = 0;i < BuffersPlayed;i++)
BufferListItem = BufferListItem->next;
OutPos = 0;
do {
const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
const ALuint BufferPadding = ResamplerPadding[Resampler];
ALubyte StackData[STACK_DATA_SIZE];
ALubyte *SrcData = StackData;
ALuint SrcDataSize = 0;
ALuint BufferSize;
/* Figure out how many buffer bytes will be needed */
DataSize64 = SamplesToDo-OutPos+1;
DataSize64 *= increment;
DataSize64 += DataPosFrac+FRACTIONMASK;
DataSize64 >>= FRACTIONBITS;
DataSize64 += BufferPadding+BufferPrePadding;
DataSize64 *= FrameSize;
BufferSize = min(DataSize64, STACK_DATA_SIZE);
BufferSize -= BufferSize%FrameSize;
if(Source->lSourceType == AL_STATIC)
{
const ALbuffer *ALBuffer = Source->Buffer;
const ALubyte *Data = ALBuffer->data;
ALuint DataSize;
ALuint pos;
/* If current pos is beyond the loop range, do not loop */
if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
{
Looping = AL_FALSE;
if(DataPosInt >= BufferPrePadding)
pos = (DataPosInt-BufferPrePadding)*FrameSize;
else
{
DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
DataSize = min(BufferSize, DataSize);
memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
pos = 0;
}
/* Copy what's left to play in the source buffer, and clear the
* rest of the temp buffer */
DataSize = ALBuffer->size - pos;
DataSize = min(BufferSize, DataSize);
memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, BufferSize);
SrcDataSize += BufferSize;
BufferSize -= BufferSize;
}
else
{
ALuint LoopStart = ALBuffer->LoopStart;
ALuint LoopEnd = ALBuffer->LoopEnd;
if(DataPosInt >= LoopStart)
{
pos = DataPosInt-LoopStart;
while(pos < BufferPrePadding)
pos += LoopEnd-LoopStart;
pos -= BufferPrePadding;
pos += LoopStart;
pos *= FrameSize;
}
else if(DataPosInt >= BufferPrePadding)
pos = (DataPosInt-BufferPrePadding)*FrameSize;
else
{
DataSize = (BufferPrePadding-DataPosInt)*FrameSize;
DataSize = min(BufferSize, DataSize);
memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
pos = 0;
}
/* Copy what's left of this loop iteration, then copy repeats
* of the loop section */
DataSize = LoopEnd*FrameSize - pos;
DataSize = min(BufferSize, DataSize);
memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
DataSize = (LoopEnd-LoopStart) * FrameSize;
while(BufferSize > 0)
{
DataSize = min(BufferSize, DataSize);
memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
}
}
}
else
{
/* Crawl the buffer queue to fill in the temp buffer */
ALbufferlistitem *BufferListIter = BufferListItem;
ALuint pos;
if(DataPosInt >= BufferPrePadding)
pos = (DataPosInt-BufferPrePadding)*FrameSize;
else
{
pos = (BufferPrePadding-DataPosInt)*FrameSize;
while(pos > 0)
{
if(!BufferListIter->prev && !Looping)
{
ALuint DataSize = min(BufferSize, pos);
memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
pos = 0;
break;
}
if(BufferListIter->prev)
BufferListIter = BufferListIter->prev;
else
{
while(BufferListIter->next)
BufferListIter = BufferListIter->next;
}
if(BufferListIter->buffer)
{
if((ALuint)BufferListIter->buffer->size > pos)
{
pos = BufferListIter->buffer->size - pos;
break;
}
pos -= BufferListIter->buffer->size;
}
}
}
while(BufferListIter && BufferSize > 0)
{
const ALbuffer *ALBuffer;
if((ALBuffer=BufferListIter->buffer) != NULL)
{
const ALubyte *Data = ALBuffer->data;
ALuint DataSize = ALBuffer->size;
/* Skip the data already played */
if(DataSize <= pos)
pos -= DataSize;
else
{
Data += pos;
DataSize -= pos;
pos -= pos;
DataSize = min(BufferSize, DataSize);
memcpy(&SrcData[SrcDataSize], Data, DataSize);
SrcDataSize += DataSize;
BufferSize -= DataSize;
}
}
BufferListIter = BufferListIter->next;
if(!BufferListIter && Looping)
BufferListIter = Source->queue;
else if(!BufferListIter)
{
memset(&SrcData[SrcDataSize], (FmtType==FmtUByte)?0x80:0, BufferSize);
SrcDataSize += BufferSize;
BufferSize -= BufferSize;
}
}
}
/* Figure out how many samples we can mix. */
DataSize64 = SrcDataSize / FrameSize;
DataSize64 -= BufferPadding+BufferPrePadding;
DataSize64 <<= FRACTIONBITS;
DataSize64 -= increment;
DataSize64 -= DataPosFrac;
BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
BufferSize = min(BufferSize, (SamplesToDo-OutPos));
SrcData += BufferPrePadding*FrameSize;
switch(Resampler)
{
case POINT_RESAMPLER:
Mix_point(Source, Device, FmtChannels, FmtType,
SrcData, &DataPosInt, &DataPosFrac,
OutPos, SamplesToDo, BufferSize);
break;
case LINEAR_RESAMPLER:
Mix_lerp(Source, Device, FmtChannels, FmtType,
SrcData, &DataPosInt, &DataPosFrac,
OutPos, SamplesToDo, BufferSize);
break;
case CUBIC_RESAMPLER:
Mix_cubic(Source, Device, FmtChannels, FmtType,
SrcData, &DataPosInt, &DataPosFrac,
OutPos, SamplesToDo, BufferSize);
break;
case RESAMPLER_MIN:
case RESAMPLER_MAX:
break;
}
OutPos += BufferSize;
/* Handle looping sources */
while(1)
{
const ALbuffer *ALBuffer;
ALuint DataSize = 0;
ALuint LoopStart = 0;
ALuint LoopEnd = 0;
if((ALBuffer=BufferListItem->buffer) != NULL)
{
DataSize = ALBuffer->size / FrameSize;
LoopStart = ALBuffer->LoopStart;
LoopEnd = ALBuffer->LoopEnd;
if(LoopEnd > DataPosInt)
break;
}
if(Looping && Source->lSourceType == AL_STATIC)
{
BufferListItem = Source->queue;
DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
break;
}
if(DataSize > DataPosInt)
break;
if(BufferListItem->next)
{
BufferListItem = BufferListItem->next;
BuffersPlayed++;
}
else if(Looping)
{
BufferListItem = Source->queue;
BuffersPlayed = 0;
}
else
{
State = AL_STOPPED;
BufferListItem = Source->queue;
BuffersPlayed = Source->BuffersInQueue;
DataPosInt = 0;
DataPosFrac = 0;
break;
}
DataPosInt -= DataSize;
}
} while(State == AL_PLAYING && OutPos < SamplesToDo);
/* Update source info */
Source->state = State;
Source->BuffersPlayed = BuffersPlayed;
Source->position = DataPosInt;
Source->position_fraction = DataPosFrac;
Source->Buffer = BufferListItem->buffer;
}
+182
View File
@@ -0,0 +1,182 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 2010 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 <stdlib.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
typedef struct {
ALvoid *buffer;
ALuint size;
volatile int killNow;
ALvoid *thread;
} null_data;
static const ALCchar nullDevice[] = "No Output";
static ALuint NullProc(ALvoid *ptr)
{
ALCdevice *Device = (ALCdevice*)ptr;
null_data *data = (null_data*)Device->ExtraData;
ALuint now, start;
ALuint64 avail, done;
const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
Device->Frequency / 2;
done = 0;
start = timeGetTime();
while(!data->killNow && Device->Connected)
{
now = timeGetTime();
avail = (ALuint64)(now-start) * Device->Frequency / 1000;
if(avail < done)
{
/* Timer wrapped. Add the remainder of the cycle to the available
* count and reset the number of samples done */
avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done;
done = 0;
}
if(avail-done < Device->UpdateSize)
{
Sleep(restTime);
continue;
}
while(avail-done >= Device->UpdateSize)
{
aluMixData(Device, data->buffer, Device->UpdateSize);
done += Device->UpdateSize;
}
}
return 0;
}
static ALCboolean null_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
null_data *data;
if(!deviceName)
deviceName = nullDevice;
else if(strcmp(deviceName, nullDevice) != 0)
return ALC_FALSE;
data = (null_data*)calloc(1, sizeof(*data));
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_TRUE;
}
static void null_close_playback(ALCdevice *device)
{
null_data *data = (null_data*)device->ExtraData;
free(data);
device->ExtraData = NULL;
}
static ALCboolean null_reset_playback(ALCdevice *device)
{
null_data *data = (null_data*)device->ExtraData;
data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans,
device->FmtType);
data->buffer = malloc(data->size);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
data->thread = StartThread(NullProc, device);
if(data->thread == NULL)
{
free(data->buffer);
data->buffer = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
static void null_stop_playback(ALCdevice *device)
{
null_data *data = (null_data*)device->ExtraData;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
free(data->buffer);
data->buffer = NULL;
}
static ALCboolean null_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
(void)device;
(void)deviceName;
return ALC_FALSE;
}
BackendFuncs null_funcs = {
null_open_playback,
null_close_playback,
null_reset_playback,
null_stop_playback,
null_open_capture,
NULL,
NULL,
NULL,
NULL,
NULL
};
void alc_null_init(BackendFuncs *func_list)
{
*func_list = null_funcs;
}
void alc_null_deinit(void)
{
}
void alc_null_probe(int type)
{
if(type == DEVICE_PROBE)
AppendDeviceList(nullDevice);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(nullDevice);
}
+230 -163
View File
@@ -47,12 +47,11 @@
#define SOUND_MIXER_WRITE MIXER_WRITE
#endif
static char *oss_device;
static char *oss_device_capture;
static const ALCchar oss_device[] = "OSS Default";
typedef struct {
int fd;
int killNow;
volatile int killNow;
ALvoid *thread;
ALubyte *mix_data;
@@ -79,35 +78,38 @@ 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)
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
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);
break;
}
remaining += len;
wrote = write(data->fd, data->mix_data, remaining);
if(wrote < 0)
{
AL_PRINT("write failed: %s\n", strerror(errno));
remaining = 0;
Sleep(1);
continue;
}
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;
@@ -120,8 +122,9 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
int frameSize;
int amt;
frameSize = aluBytesFromFormat(pDevice->Format);
frameSize *= aluChannelsFromFormat(pDevice->Format);
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
while(!data->killNow)
{
@@ -129,6 +132,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 +149,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,99 +170,139 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
return ALC_FALSE;
}
switch(aluBytesFromFormat(device->Format))
{
case 1:
ossFormat = AFMT_U8;
break;
case 2:
ossFormat = AFMT_S16_NE;
break;
default:
ossFormat = -1;
AL_PRINT("Unknown format?! %x\n", device->Format);
}
periods = GetConfigValueInt("oss", "periods", 4);
if((int)periods <= 0)
periods = 4;
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = device->Frequency;
log2FragmentSize = log2i(device->UpdateSize * frameSize / periods);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
log2FragmentSize = 4;
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") &&
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
device->Frequency = ossSpeed;
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;
}
if(!((ossFormat == AFMT_U8 && aluBytesFromFormat(device->Format) == 1) ||
(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;
}
device->UpdateSize = info.fragsize / frameSize;
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
free(data->mix_data);
free(data);
return ALC_FALSE;
}
return ALC_TRUE;
}
static void oss_close_playback(ALCdevice *device)
{
oss_data *data = (oss_data*)device->ExtraData;
data->killNow = 1;
StopThread(data->thread);
close(data->fd);
free(data->mix_data);
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;
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
switch(device->FmtType)
{
case DevFmtByte:
ossFormat = AFMT_S8;
break;
case DevFmtUByte:
ossFormat = AFMT_U8;
break;
case DevFmtUShort:
case DevFmtFloat:
device->FmtType = DevFmtShort;
/* fall-through */
case DevFmtShort:
ossFormat = AFMT_S16_NE;
break;
}
periods = device->NumUpdates;
numChannels = ChannelsFromDevFmt(device->FmtChans);
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
ossSpeed = device->Frequency;
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 CHECKERR(func) if((func) < 0) { \
err = #func; \
goto err; \
}
/* 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);
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info));
if(0)
{
err:
AL_PRINT("%s failed: %s\n", err, strerror(errno));
return ALC_FALSE;
}
#undef CHECKERR
if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
{
AL_PRINT("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), numChannels);
return ALC_FALSE;
}
if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
(ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
(ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
{
AL_PRINT("Could not set %#x format type, got OSS format %#x\n", device->FmtType, ossFormat);
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);
SetDefaultChannelOrder(device);
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_stop_playback(ALCdevice *device)
{
oss_data *data = (oss_data*)device->ExtraData;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0)
AL_PRINT("Error resetting device: %s\n", strerror(errno));
free(data->mix_data);
data->mix_data = NULL;
}
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
int numFragmentsLogSize;
int log2FragmentSize;
@@ -285,18 +315,13 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
int ossFormat;
int ossSpeed;
char *err;
int i;
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;
else if(strcmp(deviceName, oss_device) != 0)
return ALC_FALSE;
data = (oss_data*)calloc(1, sizeof(oss_data));
data->killNow = 0;
@@ -309,62 +334,74 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
switch(aluBytesFromFormat(format))
switch(device->FmtType)
{
case 1:
case DevFmtByte:
ossFormat = AFMT_S8;
break;
case DevFmtUByte:
ossFormat = AFMT_U8;
break;
case 2:
case DevFmtShort:
ossFormat = AFMT_S16_NE;
break;
default:
ossFormat = -1;
AL_PRINT("Unknown format?! %x\n", device->Format);
case DevFmtUShort:
case DevFmtFloat:
free(data);
AL_PRINT("Format type %#x capture not supported on OSS\n", device->FmtType);
return ALC_FALSE;
}
periods = 4;
numChannels = aluChannelsFromFormat(device->Format);
frameSize = numChannels * aluBytesFromFormat(device->Format);
ossSpeed = frequency;
log2FragmentSize = log2i(SampleSize * frameSize / periods);
numChannels = ChannelsFromDevFmt(device->FmtChans);
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
ossSpeed = device->Frequency;
log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
frameSize / periods);
/* according to the OSS spec, 16 bytes are the minimum */
if (log2FragmentSize < 4)
log2FragmentSize = 4;
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") &&
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_GETISPACE, &info), "get space")))
#define CHECKERR(func) if((func) < 0) { \
err = #func; \
goto err; \
}
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed));
CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info));
if(0)
{
err:
AL_PRINT("%s failed: %s\n", err, strerror(errno));
close(data->fd);
free(data);
return ALC_FALSE;
}
#undef ok
#undef CHECKERR
if((int)aluChannelsFromFormat(device->Format) != numChannels)
if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
{
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), numChannels);
AL_PRINT("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), numChannels);
close(data->fd);
free(data);
return ALC_FALSE;
}
if(!((ossFormat == AFMT_U8 && aluBytesFromFormat(device->Format) == 1) ||
(ossFormat == AFMT_S16_NE && aluBytesFromFormat(device->Format) == 2)))
if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
(ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
(ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
{
AL_PRINT("Could not set %d-bit input, got format %#x\n", aluBytesFromFormat(device->Format)*8, ossFormat);
AL_PRINT("Could not set %#x format type, got OSS format %#x\n", device->FmtType, ossFormat);
close(data->fd);
free(data);
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");
@@ -386,6 +423,7 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
return ALC_TRUE;
}
@@ -422,7 +460,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(pDevice, ALC_INVALID_VALUE);
}
static ALCuint oss_available_samples(ALCdevice *pDevice)
@@ -435,6 +473,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,
@@ -446,9 +486,36 @@ 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)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
#endif
AppendDeviceList(oss_device);
}
else if(type == ALL_DEVICE_PROBE)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
#endif
AppendAllDeviceList(oss_device);
}
else if(type == CAPTURE_DEVICE_PROBE)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0)
#endif
AppendCaptureDeviceList(oss_device);
}
}
+361
View File
@@ -0,0 +1,361 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 1999-2010 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 <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS],
Channel Speaker2Chan[MAXCHANNELS], ALint chans)
{
char layout_str[256];
char *confkey, *next;
char *sep, *end;
Channel val;
int i;
if(!ConfigValueExists(NULL, name))
name = "layout";
strncpy(layout_str, GetConfigValue(NULL, name, ""), sizeof(layout_str));
layout_str[sizeof(layout_str)-1] = 0;
if(!layout_str[0])
return;
next = confkey = layout_str;
while(next && *next)
{
confkey = next;
next = strchr(confkey, ',');
if(next)
{
*next = 0;
do {
next++;
} while(isspace(*next) || *next == ',');
}
sep = strchr(confkey, '=');
if(!sep || confkey == sep)
continue;
end = sep - 1;
while(isspace(*end) && end != confkey)
end--;
*(++end) = 0;
if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
val = FRONT_LEFT;
else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
val = FRONT_RIGHT;
else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
val = FRONT_CENTER;
else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
val = BACK_LEFT;
else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
val = BACK_RIGHT;
else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
val = BACK_CENTER;
else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
val = SIDE_LEFT;
else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
val = SIDE_RIGHT;
else
{
AL_PRINT("Unknown speaker for %s: \"%s\"\n", name, confkey);
continue;
}
*(sep++) = 0;
while(isspace(*sep))
sep++;
for(i = 0;i < chans;i++)
{
if(Speaker2Chan[i] == val)
{
long angle = strtol(sep, NULL, 10);
if(angle >= -180 && angle <= 180)
SpeakerAngle[i] = angle * M_PI/180.0f;
else
AL_PRINT("Invalid angle for speaker \"%s\": %ld\n", confkey, angle);
break;
}
}
}
for(i = 0;i < chans;i++)
{
int min = i;
int i2;
for(i2 = i+1;i2 < chans;i2++)
{
if(SpeakerAngle[i2] < SpeakerAngle[min])
min = i2;
}
if(min != i)
{
ALfloat tmpf;
Channel tmpc;
tmpf = SpeakerAngle[i];
SpeakerAngle[i] = SpeakerAngle[min];
SpeakerAngle[min] = tmpf;
tmpc = Speaker2Chan[i];
Speaker2Chan[i] = Speaker2Chan[min];
Speaker2Chan[min] = tmpc;
}
}
}
static ALfloat aluLUTpos2Angle(ALint pos)
{
if(pos < QUADRANT_NUM)
return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos));
if(pos < 2 * QUADRANT_NUM)
return M_PI_2 + aluAtan((ALfloat)(pos - QUADRANT_NUM) / (ALfloat)(2 * QUADRANT_NUM - pos));
if(pos < 3 * QUADRANT_NUM)
return aluAtan((ALfloat)(pos - 2 * QUADRANT_NUM) / (ALfloat)(3 * QUADRANT_NUM - pos)) - M_PI;
return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - M_PI_2;
}
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;
}
ALvoid aluInitPanning(ALCdevice *Device)
{
ALfloat SpeakerAngle[MAXCHANNELS];
ALfloat (*Matrix)[MAXCHANNELS];
Channel *Speaker2Chan;
ALfloat Alpha, Theta;
ALfloat *PanningLUT;
ALint pos, offset;
ALuint s, s2;
for(s = 0;s < MAXCHANNELS;s++)
{
for(s2 = 0;s2 < MAXCHANNELS;s2++)
Device->ChannelMatrix[s][s2] = ((s==s2) ? 1.0f : 0.0f);
}
Speaker2Chan = Device->Speaker2Chan;
Matrix = Device->ChannelMatrix;
switch(Device->FmtChans)
{
case DevFmtMono:
Matrix[FRONT_LEFT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[FRONT_RIGHT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[SIDE_LEFT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[SIDE_RIGHT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[BACK_LEFT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[BACK_RIGHT][FRONT_CENTER] = aluSqrt(0.5);
Matrix[BACK_CENTER][FRONT_CENTER] = 1.0f;
Device->NumChan = 1;
Speaker2Chan[0] = FRONT_CENTER;
SpeakerAngle[0] = 0.0f * M_PI/180.0f;
break;
case DevFmtStereo:
Matrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5);
Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
Matrix[SIDE_LEFT][FRONT_LEFT] = 1.0f;
Matrix[SIDE_RIGHT][FRONT_RIGHT] = 1.0f;
Matrix[BACK_LEFT][FRONT_LEFT] = 1.0f;
Matrix[BACK_RIGHT][FRONT_RIGHT] = 1.0f;
Matrix[BACK_CENTER][FRONT_LEFT] = aluSqrt(0.5);
Matrix[BACK_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
Device->NumChan = 2;
Speaker2Chan[0] = FRONT_LEFT;
Speaker2Chan[1] = FRONT_RIGHT;
SpeakerAngle[0] = -90.0f * M_PI/180.0f;
SpeakerAngle[1] = 90.0f * M_PI/180.0f;
SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan);
break;
case DevFmtQuad:
Matrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5);
Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5);
Matrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5);
Matrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5);
Matrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5);
Matrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5);
Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
Device->NumChan = 4;
Speaker2Chan[0] = BACK_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_RIGHT;
Speaker2Chan[3] = BACK_RIGHT;
SpeakerAngle[0] = -135.0f * M_PI/180.0f;
SpeakerAngle[1] = -45.0f * M_PI/180.0f;
SpeakerAngle[2] = 45.0f * M_PI/180.0f;
SpeakerAngle[3] = 135.0f * M_PI/180.0f;
SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan);
break;
case DevFmtX51:
Matrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5);
Matrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5);
Matrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5);
Matrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5);
Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
Device->NumChan = 5;
Speaker2Chan[0] = BACK_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_CENTER;
Speaker2Chan[3] = FRONT_RIGHT;
Speaker2Chan[4] = BACK_RIGHT;
SpeakerAngle[0] = -110.0f * M_PI/180.0f;
SpeakerAngle[1] = -30.0f * M_PI/180.0f;
SpeakerAngle[2] = 0.0f * M_PI/180.0f;
SpeakerAngle[3] = 30.0f * M_PI/180.0f;
SpeakerAngle[4] = 110.0f * M_PI/180.0f;
SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
break;
case DevFmtX61:
Matrix[BACK_LEFT][BACK_CENTER] = aluSqrt(0.5);
Matrix[BACK_LEFT][SIDE_LEFT] = aluSqrt(0.5);
Matrix[BACK_RIGHT][BACK_CENTER] = aluSqrt(0.5);
Matrix[BACK_RIGHT][SIDE_RIGHT] = aluSqrt(0.5);
Device->NumChan = 6;
Speaker2Chan[0] = SIDE_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_CENTER;
Speaker2Chan[3] = FRONT_RIGHT;
Speaker2Chan[4] = SIDE_RIGHT;
Speaker2Chan[5] = BACK_CENTER;
SpeakerAngle[0] = -90.0f * M_PI/180.0f;
SpeakerAngle[1] = -30.0f * M_PI/180.0f;
SpeakerAngle[2] = 0.0f * M_PI/180.0f;
SpeakerAngle[3] = 30.0f * M_PI/180.0f;
SpeakerAngle[4] = 90.0f * M_PI/180.0f;
SpeakerAngle[5] = 180.0f * M_PI/180.0f;
SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
break;
case DevFmtX71:
Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5);
Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5);
Device->NumChan = 7;
Speaker2Chan[0] = BACK_LEFT;
Speaker2Chan[1] = SIDE_LEFT;
Speaker2Chan[2] = FRONT_LEFT;
Speaker2Chan[3] = FRONT_CENTER;
Speaker2Chan[4] = FRONT_RIGHT;
Speaker2Chan[5] = SIDE_RIGHT;
Speaker2Chan[6] = BACK_RIGHT;
SpeakerAngle[0] = -150.0f * M_PI/180.0f;
SpeakerAngle[1] = -90.0f * M_PI/180.0f;
SpeakerAngle[2] = -30.0f * M_PI/180.0f;
SpeakerAngle[3] = 0.0f * M_PI/180.0f;
SpeakerAngle[4] = 30.0f * M_PI/180.0f;
SpeakerAngle[5] = 90.0f * M_PI/180.0f;
SpeakerAngle[6] = 150.0f * M_PI/180.0f;
SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan);
break;
}
if(GetConfigValueBool(NULL, "scalemix", 0))
{
ALfloat maxout = 1.0f;
for(s = 0;s < MAXCHANNELS;s++)
{
ALfloat out = 0.0f;
for(s2 = 0;s2 < MAXCHANNELS;s2++)
out += Device->ChannelMatrix[s2][s];
maxout = __max(maxout, out);
}
maxout = 1.0f/maxout;
for(s = 0;s < MAXCHANNELS;s++)
{
for(s2 = 0;s2 < MAXCHANNELS;s2++)
Device->ChannelMatrix[s2][s] *= maxout;
}
}
PanningLUT = Device->PanningLUT;
for(pos = 0; pos < LUT_NUM; pos++)
{
/* clear all values */
offset = MAXCHANNELS * pos;
for(s = 0; s < MAXCHANNELS; s++)
PanningLUT[offset+s] = 0.0f;
if(Device->NumChan == 1)
{
PanningLUT[offset + Speaker2Chan[0]] = 1.0f;
continue;
}
/* source angle */
Theta = aluLUTpos2Angle(pos);
/* set panning values */
for(s = 0; s < Device->NumChan - 1; s++)
{
if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1])
{
/* source between speaker s and speaker s+1 */
Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
(SpeakerAngle[s+1]-SpeakerAngle[s]);
PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha);
PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha);
break;
}
}
if(s == Device->NumChan - 1)
{
/* source between last and first speaker */
if(Theta < SpeakerAngle[0])
Theta += 2.0f * M_PI;
Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) /
(2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]);
PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha);
PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha);
}
}
}
+442
View File
@@ -0,0 +1,442 @@
/**
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <portaudio.h>
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 const ALCchar pa_device[] = "PortAudio Default";
void *pa_load(void)
{
if(!pa_handle)
{
PaError err;
#ifdef _WIN32
pa_handle = LoadLibrary("portaudio.dll");
#define LOAD_FUNC(x) do { \
p##x = (typeof(p##x))GetProcAddress(pa_handle, #x); \
if(!(p##x)) { \
AL_PRINT("Could not load %s from portaudio.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return NULL; \
} \
} while(0)
#elif defined(HAVE_DLFCN_H)
const char *str;
#if defined(__APPLE__) && defined(__MACH__)
# define PALIB "libportaudio.2.dylib"
#else
# define PALIB "libportaudio.so.2"
#endif
pa_handle = dlopen(PALIB, RTLD_NOW);
dlerror();
#define LOAD_FUNC(f) do { \
p##f = (typeof(f)*)dlsym(pa_handle, #f); \
if((str=dlerror()) != NULL) \
{ \
dlclose(pa_handle); \
pa_handle = NULL; \
AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \
return NULL; \
} \
} while(0)
#else
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
if(!pa_handle)
return NULL;
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));
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined(HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
pa_handle = NULL;
return NULL;
}
}
return pa_handle;
}
typedef struct {
PaStream *stream;
ALuint update_size;
RingBuffer *ring;
} 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 int pa_capture_cb(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
const PaStreamCallbackFlags statusFlags, void *userData)
{
ALCdevice *device = (ALCdevice*)userData;
pa_data *data = (pa_data*)device->ExtraData;
(void)outputBuffer;
(void)timeInfo;
(void)statusFlags;
WriteRingBuffer(data->ring, inputBuffer, 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;
if(!pa_load())
return ALC_FALSE;
data = (pa_data*)calloc(1, sizeof(pa_data));
data->update_size = device->UpdateSize;
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(device->FmtType)
{
case DevFmtByte:
outParams.sampleFormat = paInt8;
break;
case DevFmtUByte:
outParams.sampleFormat = paUInt8;
break;
case DevFmtUShort:
device->FmtType = DevFmtShort;
/* fall-through */
case DevFmtShort:
outParams.sampleFormat = paInt16;
break;
case DevFmtFloat:
outParams.sampleFormat = paFloat32;
break;
}
outParams.channelCount = ChannelsFromDevFmt(device->FmtChans);
SetDefaultChannelOrder(device);
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);
return ALC_FALSE;
}
streamInfo = pPa_GetStreamInfo(data->stream);
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_CloseStream(data->stream);
if(err != paNoError)
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
}
static ALCboolean pa_reset_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
const PaStreamInfo *streamInfo;
PaError err;
streamInfo = pPa_GetStreamInfo(data->stream);
device->Frequency = streamInfo->sampleRate;
device->UpdateSize = data->update_size;
err = pPa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
return ALC_FALSE;
}
return ALC_TRUE;
}
static void pa_stop_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
}
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
PaStreamParameters inParams;
ALuint frame_size;
pa_data *data;
PaError err;
if(!deviceName)
deviceName = pa_device;
else if(strcmp(deviceName, pa_device) != 0)
return ALC_FALSE;
if(!pa_load())
return ALC_FALSE;
data = (pa_data*)calloc(1, sizeof(pa_data));
if(data == NULL)
{
alcSetError(device, ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
if(data->ring == NULL)
{
alcSetError(device, ALC_OUT_OF_MEMORY);
goto error;
}
inParams.device = GetConfigValueInt("port", "capture", -1);
if(inParams.device < 0)
inParams.device = pPa_GetDefaultOutputDevice();
inParams.suggestedLatency = 0.0f;
inParams.hostApiSpecificStreamInfo = NULL;
switch(device->FmtType)
{
case DevFmtByte:
inParams.sampleFormat = paInt8;
break;
case DevFmtUByte:
inParams.sampleFormat = paUInt8;
break;
case DevFmtShort:
inParams.sampleFormat = paInt16;
break;
case DevFmtFloat:
inParams.sampleFormat = paFloat32;
break;
case DevFmtUShort:
AL_PRINT("Unsigned short not supported\n");
goto error;
}
inParams.channelCount = ChannelsFromDevFmt(device->FmtChans);
err = pPa_OpenStream(&data->stream, &inParams, NULL, device->Frequency,
paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
if(err != paNoError)
{
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
goto error;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_TRUE;
error:
DestroyRingBuffer(data->ring);
free(data);
return ALC_FALSE;
}
static void pa_close_capture(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_CloseStream(data->stream);
if(err != paNoError)
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
}
static void pa_start_capture(ALCdevice *device)
{
pa_data *data = device->ExtraData;
PaError err;
err = pPa_StartStream(data->stream);
if(err != paNoError)
AL_PRINT("Error starting stream: %s\n", pPa_GetErrorText(err));
}
static void pa_stop_capture(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
}
static void pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
{
pa_data *data = device->ExtraData;
if(samples <= (ALCuint)RingBufferSize(data->ring))
ReadRingBuffer(data->ring, buffer, samples);
else
alcSetError(device, ALC_INVALID_VALUE);
}
static ALCuint pa_available_samples(ALCdevice *device)
{
pa_data *data = device->ExtraData;
return RingBufferSize(data->ring);
}
static const BackendFuncs pa_funcs = {
pa_open_playback,
pa_close_playback,
pa_reset_playback,
pa_stop_playback,
pa_open_capture,
pa_close_capture,
pa_start_capture,
pa_stop_capture,
pa_capture_samples,
pa_available_samples
};
void alc_pa_init(BackendFuncs *func_list)
{
*func_list = pa_funcs;
}
void alc_pa_deinit(void)
{
if(pa_handle)
{
pPa_Terminate();
#ifdef _WIN32
FreeLibrary(pa_handle);
#elif defined(HAVE_DLFCN_H)
dlclose(pa_handle);
#endif
pa_handle = NULL;
}
}
void alc_pa_probe(int type)
{
if(!pa_load()) return;
if(type == DEVICE_PROBE)
AppendDeviceList(pa_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(pa_device);
else if(type == CAPTURE_DEVICE_PROBE)
AppendCaptureDeviceList(pa_device);
}
+1358
View File
File diff suppressed because it is too large Load Diff
+304
View File
@@ -0,0 +1,304 @@
/**
* 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 <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include <sys/audioio.h>
static const ALCchar solaris_device[] = "Solaris Default";
typedef struct {
int fd;
volatile int killNow;
ALvoid *thread;
ALubyte *mix_data;
int data_size;
} solaris_data;
static ALuint SolarisProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
solaris_data *data = (solaris_data*)pDevice->ExtraData;
ALint frameSize;
int wrote;
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
while(!data->killNow && pDevice->Connected)
{
ALint len = data->data_size;
ALubyte *WritePtr = data->mix_data;
aluMixData(pDevice, WritePtr, len/frameSize);
while(len > 0 && !data->killNow)
{
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);
break;
}
Sleep(1);
continue;
}
len -= wrote;
WritePtr += wrote;
}
}
return 0;
}
static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
char driver[64];
solaris_data *data;
strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
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;
data->fd = open(driver, O_WRONLY);
if(data->fd == -1)
{
free(data);
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
return ALC_FALSE;
}
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;
if(device->FmtChans != DevFmtMono)
device->FmtChans = DevFmtStereo;
numChannels = ChannelsFromDevFmt(device->FmtChans);
info.play.channels = numChannels;
switch(device->FmtType)
{
case DevFmtByte:
info.play.precision = 8;
info.play.encoding = AUDIO_ENCODING_LINEAR;
break;
case DevFmtUByte:
info.play.precision = 8;
info.play.encoding = AUDIO_ENCODING_LINEAR8;
break;
case DevFmtUShort:
case DevFmtFloat:
device->FmtType = DevFmtShort;
/* fall-through */
case DevFmtShort:
info.play.precision = 16;
info.play.encoding = AUDIO_ENCODING_LINEAR;
break;
}
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
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));
return ALC_FALSE;
}
if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels)
{
AL_PRINT("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels);
return ALC_FALSE;
}
if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR &&
device->FmtType == DevFmtByte) ||
(info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 &&
device->FmtType == DevFmtUByte) ||
(info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR &&
device->FmtType == DevFmtShort)))
{
AL_PRINT("Could not set %#x sample type, got %d (%#x)\n",
device->FmtType, info.play.precision, info.play.encoding);
return ALC_FALSE;
}
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);
SetDefaultChannelOrder(device);
data->thread = StartThread(SolarisProc, device);
if(data->thread == NULL)
{
free(data->mix_data);
data->mix_data = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
static void solaris_stop_playback(ALCdevice *device)
{
solaris_data *data = (solaris_data*)device->ExtraData;
if(!data->thread)
return;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
if(ioctl(data->fd, AUDIO_DRAIN) < 0)
AL_PRINT("Error draining device: %s\n", strerror(errno));
free(data->mix_data);
data->mix_data = NULL;
}
static ALCboolean solaris_open_capture(ALCdevice *device, const ALCchar *deviceName)
{
(void)device;
(void)deviceName;
return ALC_FALSE;
}
static void solaris_close_capture(ALCdevice *device)
{
(void)device;
}
static void solaris_start_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void solaris_stop_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void solaris_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
(void)pDevice;
(void)pBuffer;
(void)lSamples;
}
static ALCuint solaris_available_samples(ALCdevice *pDevice)
{
(void)pDevice;
return 0;
}
BackendFuncs solaris_funcs = {
solaris_open_playback,
solaris_close_playback,
solaris_reset_playback,
solaris_stop_playback,
solaris_open_capture,
solaris_close_capture,
solaris_start_capture,
solaris_stop_capture,
solaris_capture_samples,
solaris_available_samples
};
void alc_solaris_init(BackendFuncs *func_list)
{
*func_list = solaris_funcs;
}
void alc_solaris_deinit(void)
{
}
void alc_solaris_probe(int type)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0)
return;
#endif
if(type == DEVICE_PROBE)
AppendDeviceList(solaris_device);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(solaris_device);
}
+214 -193
View File
@@ -35,12 +35,48 @@ typedef struct {
ALvoid *buffer;
ALuint size;
int killNow;
volatile int killNow;
ALvoid *thread;
} wave_data;
static ALCchar *waveDevice;
static const ALCchar waveDevice[] = "Wave File Writer";
static const ALubyte SUBTYPE_PCM[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
0x00, 0x38, 0x9b, 0x71
};
static const ALubyte SUBTYPE_FLOAT[] = {
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
0x00, 0x38, 0x9b, 0x71
};
static const ALuint channel_masks[] = {
0, /* invalid */
0x4, /* Mono */
0x1 | 0x2, /* Stereo */
0, /* 3 channel */
0x1 | 0x2 | 0x10 | 0x20, /* Quad */
0, /* 5 channel */
0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20, /* 5.1 */
0x1 | 0x2 | 0x4 | 0x8 | 0x100 | 0x200 | 0x400, /* 6.1 */
0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */
};
static void fwrite16le(ALushort val, FILE *f)
{
fputc(val&0xff, f);
fputc((val>>8)&0xff, f);
}
static void fwrite32le(ALuint val, FILE *f)
{
fputc(val&0xff, f);
fputc((val>>8)&0xff, f);
fputc((val>>16)&0xff, f);
fputc((val>>24)&0xff, f);
}
static ALuint WaveProc(ALvoid *ptr)
@@ -48,58 +84,76 @@ static ALuint WaveProc(ALvoid *ptr)
ALCdevice *pDevice = (ALCdevice*)ptr;
wave_data *data = (wave_data*)pDevice->ExtraData;
ALuint frameSize;
ALuint now, last;
size_t WriteCnt;
ALuint avail;
ALuint now, start;
ALuint64 avail, done;
size_t fs;
union {
short s;
char b[sizeof(short)];
} uSB;
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
pDevice->Frequency / 2;
uSB.s = 1;
frameSize = aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format);
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
last = timeGetTime();
while(!data->killNow)
done = 0;
start = timeGetTime();
while(!data->killNow && pDevice->Connected)
{
now = timeGetTime();
avail = (now-last) * pDevice->Frequency / 1000;
if(avail < pDevice->UpdateSize/4)
avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
if(avail < done)
{
Sleep(1);
/* Timer wrapped. Add the remainder of the cycle to the available
* count and reset the number of samples done */
avail += (ALuint64)0xFFFFFFFFu*pDevice->Frequency/1000 - done;
done = 0;
}
if(avail-done < pDevice->UpdateSize)
{
Sleep(restTime);
continue;
}
while(avail > 0)
while(avail-done >= 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);
done += pDevice->UpdateSize;
if(uSB.b[0] != 1 && aluBytesFromFormat(pDevice->Format) > 1)
if(uSB.b[0] != 1)
{
ALuint bytesize = BytesFromDevFmt(pDevice->FmtType);
ALubyte *bytes = data->buffer;
ALuint i;
for(i = 0;i < WriteCnt*frameSize;i++)
fputc(bytes[i^1], data->f);
if(bytesize == 1)
{
for(i = 0;i < data->size;i++)
fputc(bytes[i], data->f);
}
else if(bytesize == 2)
{
for(i = 0;i < data->size;i++)
fputc(bytes[i^1], data->f);
}
else if(bytesize == 4)
{
for(i = 0;i < data->size;i++)
fputc(bytes[i^3], data->f);
}
}
else
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;
}
last = now;
}
return 0;
@@ -108,23 +162,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));
@@ -136,199 +183,173 @@ static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
bits = aluBytesFromFormat(device->Format) * 8;
channels = aluChannelsFromFormat(device->Format);
switch(bits)
{
case 8:
case 16:
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;
}
fprintf(data->f, "RIFF");
fputc(0, data->f); // 'RIFF' header len; filled in at close
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
fprintf(data->f, "WAVE");
fprintf(data->f, "fmt ");
fputc(16, data->f); // 'fmt ' header len; 16 bytes for PCM
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
// 16-bit val, format type id (PCM: 1)
fputc(1, data->f);
fputc(0, data->f);
// 16-bit val, channel count
fputc(channels&0xff, data->f);
fputc((channels>>8)&0xff, data->f);
// 32-bit val, frequency
fputc(device->Frequency&0xff, data->f);
fputc((device->Frequency>>8)&0xff, data->f);
fputc((device->Frequency>>16)&0xff, data->f);
fputc((device->Frequency>>24)&0xff, data->f);
// 32-bit val, bytes per second
i = device->Frequency * channels * bits / 8;
fputc(i&0xff, data->f);
fputc((i>>8)&0xff, data->f);
fputc((i>>16)&0xff, data->f);
fputc((i>>24)&0xff, data->f);
// 16-bit val, frame size
i = channels * bits / 8;
fputc(i&0xff, data->f);
fputc((i>>8)&0xff, data->f);
// 16-bit val, bits per sample
fputc(bits&0xff, data->f);
fputc((bits>>8)&0xff, data->f);
fprintf(data->f, "data");
fputc(0, data->f); // 'data' header len; filled in at close
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
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);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
fclose(data->f);
free(data);
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = data;
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
fclose(data->f);
free(data->buffer);
free(data);
return ALC_FALSE;
}
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=0, bits=0;
size_t val;
fseek(data->f, 0, SEEK_SET);
clearerr(data->f);
switch(device->FmtType)
{
case DevFmtByte:
device->FmtType = DevFmtUByte;
break;
case DevFmtUShort:
device->FmtType = DevFmtShort;
break;
case DevFmtUByte:
case DevFmtShort:
case DevFmtFloat:
break;
}
bits = BytesFromDevFmt(device->FmtType) * 8;
channels = ChannelsFromDevFmt(device->FmtChans);
fprintf(data->f, "RIFF");
fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close
fprintf(data->f, "WAVE");
fprintf(data->f, "fmt ");
fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE
// 16-bit val, format type id (extensible: 0xFFFE)
fwrite16le(0xFFFE, data->f);
// 16-bit val, channel count
fwrite16le(channels, data->f);
// 32-bit val, frequency
fwrite32le(device->Frequency, data->f);
// 32-bit val, bytes per second
fwrite32le(device->Frequency * channels * bits / 8, data->f);
// 16-bit val, frame size
fwrite16le(channels * bits / 8, data->f);
// 16-bit val, bits per sample
fwrite16le(bits, data->f);
// 16-bit val, extra byte count
fwrite16le(22, data->f);
// 16-bit val, valid bits per sample
fwrite16le(bits, data->f);
// 32-bit val, channel mask
fwrite32le(channel_masks[channels], data->f);
// 16 byte GUID, sub-type format
val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f);
fprintf(data->f, "data");
fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close
if(ferror(data->f))
{
AL_PRINT("Error writing header: %s\n", strerror(errno));
return ALC_FALSE;
}
data->DataStart = ftell(data->f);
data->size = device->UpdateSize * channels * bits / 8;
data->buffer = malloc(data->size);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
free(data->buffer);
data->buffer = NULL;
return ALC_FALSE;
}
return ALC_TRUE;
}
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;
data->killNow = 0;
free(data->buffer);
data->buffer = NULL;
size = ftell(data->f);
if(size > 0)
{
dataLen = size - data->DataStart;
if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0)
{
fputc(dataLen&0xff, data->f); // 'data' header len
fputc((dataLen>>8)&0xff, data->f);
fputc((dataLen>>16)&0xff, data->f);
fputc((dataLen>>24)&0xff, data->f);
}
fwrite32le(dataLen, data->f); // 'data' header len
if(fseek(data->f, 4, SEEK_SET) == 0)
{
size -= 8;
fputc(size&0xff, data->f); // 'WAVE' header len
fputc((size>>8)&0xff, data->f);
fputc((size>>16)&0xff, data->f);
fputc((size>>24)&0xff, data->f);
}
fwrite32le(size-8, data->f); // 'WAVE' header len
}
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;
}
static void wave_close_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_start_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_stop_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
(void)pDevice;
(void)pBuffer;
(void)lSamples;
}
static ALCuint wave_available_samples(ALCdevice *pDevice)
{
(void)pDevice;
return 0;
}
BackendFuncs wave_funcs = {
wave_open_playback,
wave_close_playback,
wave_reset_playback,
wave_stop_playback,
wave_open_capture,
wave_close_capture,
wave_start_capture,
wave_stop_capture,
wave_capture_samples,
wave_available_samples
NULL,
NULL,
NULL,
NULL,
NULL
};
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(!ConfigValueExists("wave", "file"))
return;
if(type == DEVICE_PROBE)
AppendDeviceList(waveDevice);
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(waveDevice);
}
+588 -246
View File
@@ -34,23 +34,190 @@
typedef struct {
// MMSYSTEM Capture Device
ALboolean bWaveInShutdown;
HANDLE hWaveInHdrEvent;
HANDLE hWaveInThreadEvent;
HANDLE hWaveInThread;
DWORD ulWaveInThreadID;
ALint lWaveInBuffersCommitted;
HWAVEIN hWaveInHandle;
WAVEHDR WaveInBuffer[4];
ALCchar *pCapturedSampleData;
ALuint ulCapturedDataSize;
ALuint ulReadCapturedDataPos;
ALuint ulWriteCapturedDataPos;
// MMSYSTEM Device
volatile ALboolean bWaveShutdown;
HANDLE hWaveHdrEvent;
HANDLE hWaveThreadEvent;
HANDLE hWaveThread;
DWORD ulWaveThreadID;
LONG lWaveBuffersCommitted;
WAVEHDR WaveBuffer[4];
union {
HWAVEIN In;
HWAVEOUT Out;
} hWaveHandle;
ALsizei Frequency;
RingBuffer *pRing;
} WinMMData;
static ALCchar *CaptureDeviceList[16];
static const ALCchar woDefault[] = "WaveOut Default";
static ALCchar **PlaybackDeviceList;
static ALuint NumPlaybackDevices;
static ALCchar **CaptureDeviceList;
static ALuint NumCaptureDevices;
static void ProbePlaybackDevices(void)
{
ALuint i;
for(i = 0;i < NumPlaybackDevices;i++)
free(PlaybackDeviceList[i]);
NumPlaybackDevices = waveOutGetNumDevs();
PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices);
for(i = 0;i < NumPlaybackDevices;i++)
{
WAVEOUTCAPS WaveCaps;
PlaybackDeviceList[i] = NULL;
if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
{
char name[1024];
ALuint count, j;
count = 0;
do {
if(count == 0)
snprintf(name, sizeof(name), "%s via WaveOut", WaveCaps.szPname);
else
snprintf(name, sizeof(name), "%s #%d via WaveOut", WaveCaps.szPname, count+1);
count++;
for(j = 0;j < i;j++)
{
if(strcmp(name, PlaybackDeviceList[j]) == 0)
break;
}
} while(j != i);
PlaybackDeviceList[i] = strdup(name);
}
}
}
static void ProbeCaptureDevices(void)
{
ALuint i;
for(i = 0;i < NumCaptureDevices;i++)
free(CaptureDeviceList[i]);
NumCaptureDevices = waveInGetNumDevs();
CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
for(i = 0;i < NumCaptureDevices;i++)
{
WAVEINCAPS WaveInCaps;
CaptureDeviceList[i] = NULL;
if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
{
char name[1024];
ALuint count, j;
count = 0;
do {
if(count == 0)
snprintf(name, sizeof(name), "%s via WaveIn", WaveInCaps.szPname);
else
snprintf(name, sizeof(name), "%s #%d via WaveIn", WaveInCaps.szPname, count+1);
count++;
for(j = 0;j < i;j++)
{
if(strcmp(name, CaptureDeviceList[j]) == 0)
break;
}
} while(j != i);
CaptureDeviceList[i] = strdup(name);
}
}
}
/*
WaveOutProc
Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
returns to the application (for more data)
*/
static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
ALCdevice *pDevice = (ALCdevice*)dwInstance;
WinMMData *pData = pDevice->ExtraData;
(void)hDevice;
(void)dwParam2;
if(uMsg != WOM_DONE)
return;
// Decrement number of buffers in use
InterlockedDecrement(&pData->lWaveBuffersCommitted);
if(pData->bWaveShutdown == AL_FALSE)
{
// Notify Wave Processor Thread that a Wave Header has returned
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
}
else
{
if(pData->lWaveBuffersCommitted == 0)
{
// Signal Wave Buffers Returned event
if(pData->hWaveHdrEvent)
SetEvent(pData->hWaveHdrEvent);
// Post 'Quit' Message to WaveOut Processor Thread
PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
}
}
}
/*
PlaybackThreadProc
Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its
audio data.
*/
static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
{
ALCdevice *pDevice = (ALCdevice*)lpParameter;
WinMMData *pData = pDevice->ExtraData;
LPWAVEHDR pWaveHdr;
ALuint FrameSize;
MSG msg;
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message != WOM_DONE || pData->bWaveShutdown)
continue;
pWaveHdr = ((LPWAVEHDR)msg.lParam);
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
// Send buffer back to play more data
waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
}
// Signal Wave Thread completed event
if(pData->hWaveThreadEvent)
SetEvent(pData->hWaveThreadEvent);
ExitThread(0);
return 0;
}
/*
WaveInProc
@@ -60,33 +227,33 @@ static ALCchar *CaptureDeviceList[16];
*/
static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
ALCdevice *pDevice = (ALCdevice *)dwInstance;
ALCdevice *pDevice = (ALCdevice*)dwInstance;
WinMMData *pData = pDevice->ExtraData;
(void)hDevice;
(void)dwParam2;
if ((uMsg==WIM_DATA))
if(uMsg != WIM_DATA)
return;
// Decrement number of buffers in use
InterlockedDecrement(&pData->lWaveBuffersCommitted);
if(pData->bWaveShutdown == AL_FALSE)
{
// Decrement number of buffers in use
pData->lWaveInBuffersCommitted--;
if (pData->bWaveInShutdown == AL_FALSE)
// Notify Wave Processor Thread that a Wave Header has returned
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
}
else
{
if(pData->lWaveBuffersCommitted == 0)
{
// Notify Wave Processor Thread that a Wave Header has returned
PostThreadMessage(pData->ulWaveInThreadID,uMsg,0,dwParam1);
}
else
{
if (pData->lWaveInBuffersCommitted == 0)
{
// Signal Wave Buffers Returned event
if (pData->hWaveInHdrEvent)
SetEvent(pData->hWaveInHdrEvent);
// Signal Wave Buffers Returned event
if(pData->hWaveHdrEvent)
SetEvent(pData->hWaveHdrEvent);
// Post 'Quit' Message to WaveIn Processor Thread
PostThreadMessage(pData->ulWaveInThreadID,WM_QUIT,0,0);
}
// Post 'Quit' Message to WaveIn Processor Thread
PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0);
}
}
}
@@ -97,64 +264,34 @@ static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,D
Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
audio data.
*/
DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
{
ALCdevice *pDevice = (ALCdevice*)lpParameter;
WinMMData *pData = pDevice->ExtraData;
ALuint ulOffset, ulMaxSize, ulSection;
LPWAVEHDR pWaveHdr;
ALuint FrameSize;
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
while(GetMessage(&msg, NULL, 0, 0))
{
if ((msg.message==WIM_DATA)&&(!pData->bWaveInShutdown))
{
SuspendContext(NULL);
if(msg.message != WIM_DATA || pData->bWaveShutdown)
continue;
pWaveHdr = ((LPWAVEHDR)msg.lParam);
pWaveHdr = ((LPWAVEHDR)msg.lParam);
// Calculate offset in local buffer to write data to
ulOffset = pData->ulWriteCapturedDataPos % pData->ulCapturedDataSize;
WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData,
pWaveHdr->dwBytesRecorded/FrameSize);
if ((ulOffset + pWaveHdr->dwBytesRecorded) > pData->ulCapturedDataSize)
{
ulSection = pData->ulCapturedDataSize - ulOffset;
memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, ulSection);
memcpy(pData->pCapturedSampleData, pWaveHdr->lpData + ulSection, pWaveHdr->dwBytesRecorded - ulSection);
}
else
{
memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);
}
pData->ulWriteCapturedDataPos += pWaveHdr->dwBytesRecorded;
if (pData->ulWriteCapturedDataPos > (pData->ulReadCapturedDataPos + pData->ulCapturedDataSize))
{
// Application has not read enough audio data from the capture buffer so data has been
// overwritten. Reset ReadPosition.
pData->ulReadCapturedDataPos = pData->ulWriteCapturedDataPos - pData->ulCapturedDataSize;
}
// To prevent an over-flow prevent the offset values from getting too large
ulMaxSize = pData->ulCapturedDataSize << 4;
if ((pData->ulReadCapturedDataPos > ulMaxSize) && (pData->ulWriteCapturedDataPos > ulMaxSize))
{
pData->ulReadCapturedDataPos -= ulMaxSize;
pData->ulWriteCapturedDataPos -= ulMaxSize;
}
// Send buffer back to capture more data
waveInAddBuffer(pData->hWaveInHandle,pWaveHdr,sizeof(WAVEHDR));
pData->lWaveInBuffersCommitted++;
ProcessContext(NULL);
}
// Send buffer back to capture more data
waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
}
// Signal Wave Thread completed event
if (pData->hWaveInThreadEvent)
SetEvent(pData->hWaveInThreadEvent);
if(pData->hWaveThreadEvent)
SetEvent(pData->hWaveThreadEvent);
ExitThread(0);
@@ -162,136 +299,344 @@ DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
}
static ALCboolean WinMMOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
static ALCboolean WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
{
(void)device;
(void)deviceName;
return ALC_FALSE;
}
static void WinMMClosePlayback(ALCdevice *device)
{
(void)device;
}
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
{
WAVEFORMATEX wfexCaptureFormat;
WAVEFORMATEX wfexFormat;
WinMMData *pData = NULL;
ALint lDeviceID = 0;
ALint lBufferSize;
ALint i;
(void)format;
UINT lDeviceID = 0;
MMRESULT res;
ALuint i = 0;
// Find the Device ID matching the deviceName if valid
if (deviceName)
if(!deviceName || strcmp(deviceName, woDefault) == 0)
lDeviceID = WAVE_MAPPER;
else
{
for(i = 0;CaptureDeviceList[i];i++)
if(!PlaybackDeviceList)
ProbePlaybackDevices();
for(i = 0;i < NumPlaybackDevices;i++)
{
if (!strcmp(deviceName, CaptureDeviceList[i]))
if(PlaybackDeviceList[i] &&
strcmp(deviceName, PlaybackDeviceList[i]) == 0)
{
lDeviceID = i;
break;
}
}
if(!CaptureDeviceList[i])
if(i == NumPlaybackDevices)
return ALC_FALSE;
}
pDevice->szDeviceName = CaptureDeviceList[lDeviceID];
pData = calloc(1, sizeof(*pData));
if(!pData)
{
SetALCError(ALC_OUT_OF_MEMORY);
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
pDevice->ExtraData = pData;
if(pDevice->FmtChans != DevFmtMono)
pDevice->FmtChans = DevFmtStereo;
switch(pDevice->FmtType)
{
case DevFmtByte:
pDevice->FmtType = DevFmtUByte;
break;
case DevFmtUShort:
case DevFmtFloat:
pDevice->FmtType = DevFmtShort;
break;
case DevFmtUByte:
case DevFmtShort:
break;
}
memset(&wfexFormat, 0, sizeof(WAVEFORMATEX));
wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample *
wfexFormat.nChannels / 8;
wfexFormat.nSamplesPerSec = pDevice->Frequency;
wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec *
wfexFormat.nBlockAlign;
wfexFormat.cbSize = 0;
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
AL_PRINT("waveInOpen failed: %u\n", res);
goto failure;
}
pData->hWaveHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveOutAllHeadersReturned");
pData->hWaveThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveOutThreadDestroyed");
if(pData->hWaveHdrEvent == NULL || pData->hWaveThreadEvent == NULL)
{
AL_PRINT("CreateEvent failed: %lu\n", GetLastError());
goto failure;
}
pData->Frequency = pDevice->Frequency;
pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault :
PlaybackDeviceList[lDeviceID]);
return ALC_TRUE;
failure:
if(pData->hWaveThreadEvent)
CloseHandle(pData->hWaveThreadEvent);
if(pData->hWaveHdrEvent)
CloseHandle(pData->hWaveHdrEvent);
if(pData->hWaveHandle.Out)
waveOutClose(pData->hWaveHandle.Out);
free(pData);
pDevice->ExtraData = NULL;
return ALC_FALSE;
}
static void WinMMClosePlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
// Close the Wave device
CloseHandle(pData->hWaveThreadEvent);
pData->hWaveThreadEvent = 0;
CloseHandle(pData->hWaveHdrEvent);
pData->hWaveHdrEvent = 0;
waveInClose(pData->hWaveHandle.In);
pData->hWaveHandle.In = 0;
free(pData);
device->ExtraData = NULL;
}
static ALCboolean WinMMResetPlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
ALbyte *BufferData;
ALint lBufferSize;
ALuint i;
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID);
if(pData->hWaveThread == NULL)
return ALC_FALSE;
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
pData->Frequency / device->Frequency);
device->Frequency = pData->Frequency;
pData->lWaveBuffersCommitted = 0;
// Create 4 Buffers
lBufferSize = device->UpdateSize*device->NumUpdates / 4;
lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
BufferData = calloc(4, lBufferSize);
for(i = 0;i < 4;i++)
{
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
(pData->WaveBuffer[i-1].lpData +
pData->WaveBuffer[i-1].dwBufferLength));
waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
}
return ALC_TRUE;
}
static void WinMMStopPlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
int i;
if(pData->hWaveThread == NULL)
return;
// Set flag to stop processing headers
pData->bWaveShutdown = AL_TRUE;
// Wait for signal that all Wave Buffers have returned
WaitForSingleObjectEx(pData->hWaveHdrEvent, 5000, FALSE);
// Wait for signal that Wave Thread has been destroyed
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
CloseHandle(pData->hWaveThread);
pData->hWaveThread = 0;
pData->bWaveShutdown = AL_FALSE;
// Release the wave buffers
for(i = 0;i < 4;i++)
{
waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0)
free(pData->WaveBuffer[i].lpData);
pData->WaveBuffer[i].lpData = NULL;
}
}
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
{
WAVEFORMATEX wfexCaptureFormat;
DWORD ulCapturedDataSize;
WinMMData *pData = NULL;
UINT lDeviceID = 0;
ALbyte *BufferData;
ALint lBufferSize;
MMRESULT res;
ALuint i;
if(!CaptureDeviceList)
ProbeCaptureDevices();
// Find the Device ID matching the deviceName if valid
if(deviceName)
{
for(i = 0;i < NumCaptureDevices;i++)
{
if(CaptureDeviceList[i] &&
strcmp(deviceName, CaptureDeviceList[i]) == 0)
{
lDeviceID = i;
break;
}
}
}
else
{
for(i = 0;i < NumCaptureDevices;i++)
{
if(CaptureDeviceList[i])
{
lDeviceID = i;
break;
}
}
}
if(i == NumCaptureDevices)
return ALC_FALSE;
pData = calloc(1, sizeof(*pData));
if(!pData)
{
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
pDevice->ExtraData = pData;
if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) ||
(pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort))
{
alcSetError(pDevice, ALC_INVALID_ENUM);
goto failure;
}
memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
wfexCaptureFormat.nChannels = aluChannelsFromFormat(pDevice->Format);
wfexCaptureFormat.wBitsPerSample = aluBytesFromFormat(pDevice->Format) * 8;
wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
wfexCaptureFormat.nChannels / 8;
wfexCaptureFormat.nSamplesPerSec = frequency;
wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
wfexCaptureFormat.nBlockAlign;
wfexCaptureFormat.cbSize = 0;
if (waveInOpen(&pData->hWaveInHandle, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
goto failure;
pData->hWaveInHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInAllHeadersReturned");
if (pData->hWaveInHdrEvent == NULL)
goto failure;
pData->hWaveInThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInThreadDestroyed");
if (pData->hWaveInThreadEvent == NULL)
goto failure;
// Allocate circular memory buffer for the captured audio
pData->ulCapturedDataSize = SampleSize * wfexCaptureFormat.nBlockAlign;
// Make sure circular buffer is at least 100ms in size (and an exact multiple of
// the block alignment
if (pData->ulCapturedDataSize < (wfexCaptureFormat.nAvgBytesPerSec / 10))
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
pData->ulCapturedDataSize = wfexCaptureFormat.nAvgBytesPerSec / 10;
pData->ulCapturedDataSize -= (pData->ulCapturedDataSize % wfexCaptureFormat.nBlockAlign);
AL_PRINT("waveInOpen failed: %u\n", res);
goto failure;
}
pData->pCapturedSampleData = (ALCchar*)malloc(pData->ulCapturedDataSize);
pData->lWaveInBuffersCommitted=0;
pData->hWaveHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInAllHeadersReturned");
pData->hWaveThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInThreadDestroyed");
if(pData->hWaveHdrEvent == NULL || pData->hWaveThreadEvent == NULL)
{
AL_PRINT("CreateEvent failed: %lu\n", GetLastError());
goto failure;
}
pData->Frequency = pDevice->Frequency;
// Allocate circular memory buffer for the captured audio
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
// Make sure circular buffer is at least 100ms in size
if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10))
ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10;
pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize);
if(!pData->pRing)
goto failure;
pData->lWaveBuffersCommitted = 0;
// Create 4 Buffers of 50ms each
lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
for (i=0;i<4;i++)
{
memset(&pData->WaveInBuffer[i], 0, sizeof(WAVEHDR));
pData->WaveInBuffer[i].dwBufferLength = lBufferSize;
pData->WaveInBuffer[i].lpData = calloc(1,pData->WaveInBuffer[i].dwBufferLength);
pData->WaveInBuffer[i].dwFlags = 0;
pData->WaveInBuffer[i].dwLoops = 0;
waveInPrepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
waveInAddBuffer(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
pData->lWaveInBuffersCommitted++;
}
pData->ulReadCapturedDataPos = 0;
pData->ulWriteCapturedDataPos = 0;
pDevice->ExtraData = pData;
pData->hWaveInThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveInThreadID);
if (pData->hWaveInThread == NULL)
BufferData = calloc(4, lBufferSize);
if(!BufferData)
goto failure;
for(i = 0;i < 4;i++)
{
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
(pData->WaveBuffer[i-1].lpData +
pData->WaveBuffer[i-1].dwBufferLength));
pData->WaveBuffer[i].dwFlags = 0;
pData->WaveBuffer[i].dwLoops = 0;
waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
}
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
if (pData->hWaveThread == NULL)
goto failure;
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
return ALC_TRUE;
failure:
for (i=0;i<4;i++)
if(pData->hWaveThread)
CloseHandle(pData->hWaveThread);
for(i = 0;i < 4;i++)
{
if(pData->WaveInBuffer[i].lpData)
if(pData->WaveBuffer[i].lpData)
{
waveInUnprepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
free(pData->WaveInBuffer[i].lpData);
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0)
free(pData->WaveBuffer[i].lpData);
}
}
free(pData->pCapturedSampleData);
if(pData->hWaveInHandle)
waveInClose(pData->hWaveInHandle);
if(pData->hWaveInThread)
CloseHandle(pData->hWaveInThread);
if (pData->hWaveInHdrEvent)
CloseHandle(pData->hWaveInHdrEvent);
if (pData->hWaveInThreadEvent)
CloseHandle(pData->hWaveInThreadEvent);
if(pData->pRing)
DestroyRingBuffer(pData->pRing);
if(pData->hWaveThreadEvent)
CloseHandle(pData->hWaveThreadEvent);
if(pData->hWaveHdrEvent)
CloseHandle(pData->hWaveHdrEvent);
if(pData->hWaveHandle.In)
waveInClose(pData->hWaveHandle.In);
free(pData);
pDevice->ExtraData = NULL;
return ALC_FALSE;
}
@@ -301,44 +646,39 @@ static void WinMMCloseCapture(ALCdevice *pDevice)
int i;
// Call waveOutReset to shutdown wave device
pData->bWaveInShutdown = AL_TRUE;
waveInReset(pData->hWaveInHandle);
pData->bWaveShutdown = AL_TRUE;
waveInReset(pData->hWaveHandle.In);
// Wait for signal that all Wave Buffers have returned
WaitForSingleObjectEx(pData->hWaveInHdrEvent, 5000, FALSE);
WaitForSingleObjectEx(pData->hWaveHdrEvent, 5000, FALSE);
// Wait for signal that Wave Thread has been destroyed
WaitForSingleObjectEx(pData->hWaveInThreadEvent, 5000, FALSE);
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
CloseHandle(pData->hWaveThread);
pData->hWaveThread = 0;
// Release the wave buffers
for (i=0;i<4;i++)
for(i = 0;i < 4;i++)
{
waveInUnprepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
free(pData->WaveInBuffer[i].lpData);
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0)
free(pData->WaveBuffer[i].lpData);
pData->WaveBuffer[i].lpData = NULL;
}
// Free Audio Buffer data
free(pData->pCapturedSampleData);
pData->pCapturedSampleData = NULL;
DestroyRingBuffer(pData->pRing);
pData->pRing = NULL;
// Close the Wave device
waveInClose(pData->hWaveInHandle);
pData->hWaveInHandle = 0;
CloseHandle(pData->hWaveThreadEvent);
pData->hWaveThreadEvent = 0;
CloseHandle(pData->hWaveInThread);
pData->hWaveInThread = 0;
CloseHandle(pData->hWaveHdrEvent);
pData->hWaveHdrEvent = 0;
if (pData->hWaveInHdrEvent)
{
CloseHandle(pData->hWaveInHdrEvent);
pData->hWaveInHdrEvent = 0;
}
if (pData->hWaveInThreadEvent)
{
CloseHandle(pData->hWaveInThreadEvent);
pData->hWaveInThreadEvent = 0;
}
waveInClose(pData->hWaveHandle.In);
pData->hWaveHandle.In = 0;
free(pData);
pDevice->ExtraData = NULL;
@@ -347,72 +687,37 @@ static void WinMMCloseCapture(ALCdevice *pDevice)
static void WinMMStartCapture(ALCdevice *pDevice)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
waveInStart(pData->hWaveInHandle);
waveInStart(pData->hWaveHandle.In);
}
static void WinMMStopCapture(ALCdevice *pDevice)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
waveInStop(pData->hWaveInHandle);
}
static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
ALuint ulSamples = (unsigned long)lSamples;
ALuint ulBytes, ulBytesToCopy;
ALuint ulCapturedSamples;
ALuint ulReadOffset;
ALuint frameSize = aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format);
// Check that we have the requested numbers of Samples
ulCapturedSamples = (pData->ulWriteCapturedDataPos -
pData->ulReadCapturedDataPos) /
frameSize;
if(ulSamples > ulCapturedSamples)
{
SetALCError(ALC_INVALID_VALUE);
return;
}
ulBytes = ulSamples * frameSize;
// Get Read Offset
ulReadOffset = (pData->ulReadCapturedDataPos % pData->ulCapturedDataSize);
// Check for wrap-around condition
if ((ulReadOffset + ulBytes) > pData->ulCapturedDataSize)
{
// Copy data from last Read position to end of data
ulBytesToCopy = pData->ulCapturedDataSize - ulReadOffset;
memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytesToCopy);
// Copy rest of the data from the start of the captured data
memcpy(((char *)pBuffer) + ulBytesToCopy, pData->pCapturedSampleData, ulBytes - ulBytesToCopy);
}
else
{
// Copy data from the read position in the captured data
memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytes);
}
// Update Read Position
pData->ulReadCapturedDataPos += ulBytes;
waveInStop(pData->hWaveHandle.In);
}
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
ALCuint lCapturedBytes = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos);
return lCapturedBytes / (aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format));
return RingBufferSize(pData->pRing);
}
static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
if(WinMMAvailableSamples(pDevice) >= lSamples)
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
else
alcSetError(pDevice, ALC_INVALID_VALUE);
}
BackendFuncs WinMMFuncs = {
static BackendFuncs WinMMFuncs = {
WinMMOpenPlayback,
WinMMClosePlayback,
WinMMResetPlayback,
WinMMStopPlayback,
WinMMOpenCapture,
WinMMCloseCapture,
WinMMStartCapture,
@@ -423,20 +728,57 @@ 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 < NumPlaybackDevices;lLoop++)
free(PlaybackDeviceList[lLoop]);
free(PlaybackDeviceList);
PlaybackDeviceList = NULL;
NumPlaybackDevices = 0;
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
free(CaptureDeviceList[lLoop]);
free(CaptureDeviceList);
CaptureDeviceList = NULL;
NumCaptureDevices = 0;
}
void alcWinMMProbe(int type)
{
ALuint i;
if(type == DEVICE_PROBE)
{
WAVEINCAPS WaveInCaps;
if(waveInGetDevCaps(lLoop, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
ProbePlaybackDevices();
if(NumPlaybackDevices > 0)
AppendDeviceList(woDefault);
}
else if(type == ALL_DEVICE_PROBE)
{
ProbePlaybackDevices();
if(NumPlaybackDevices > 0)
AppendAllDeviceList(woDefault);
for(i = 0;i < NumPlaybackDevices;i++)
{
char name[128];
snprintf(name, sizeof(name), "WaveIn on %s", WaveInCaps.szPname);
CaptureDeviceList[lLoop] = AppendCaptureDeviceList(name);
if(PlaybackDeviceList[i])
AppendAllDeviceList(PlaybackDeviceList[i]);
}
}
else if(type == CAPTURE_DEVICE_PROBE)
{
ProbeCaptureDevices();
for(i = 0;i < NumCaptureDevices;i++)
{
if(CaptureDeviceList[i])
AppendCaptureDeviceList(CaptureDeviceList[i]);
}
}
}
+281 -74
View File
@@ -1,15 +1,25 @@
# CMake build file list for OpenAL
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
INCLUDE(CheckFunctionExists)
INCLUDE(CheckLibraryExists)
INCLUDE(CheckSharedLibraryExists)
INCLUDE(CheckIncludeFile)
INCLUDE(CheckIncludeFiles)
INCLUDE(CheckSymbolExists)
INCLUDE(CheckCCompilerFlag)
INCLUDE(CheckCSourceCompiles)
INCLUDE(CheckTypeSize)
PROJECT(OpenAL)
PROJECT(OpenAL C)
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
@@ -17,20 +27,36 @@ SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
OPTION(ALSA "Check for ALSA backend" ON)
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(PULSEAUDIO "Check for PulseAudio backend" ON)
OPTION(WAVE "Enable Wave Writer backend" ON)
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
OPTION(WERROR "Treat compile warnings as errors" OFF)
OPTION(EXAMPLES "Build example programs" ON)
OPTION(UTILS "Build and install utility programs" ON)
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
IF(WIN32)
SET(LIBNAME OpenAL32)
ADD_DEFINITIONS("-D_WIN32")
ELSE()
SET(LIBNAME openal)
ENDIF()
IF(NOT LIBTYPE)
SET(LIBTYPE SHARED)
ENDIF()
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "4")
SET(LIB_BUILD_VERSION "272")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
SET(LIB_MINOR_VERSION "13")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}")
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
@@ -47,6 +73,11 @@ IF(NOT CMAKE_BUILD_TYPE)
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE)
ENDIF()
IF(NOT CMAKE_DEBUG_POSTFIX)
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING
"Library postfix for debug builds. Normally left blank."
FORCE)
ENDIF()
IF(MSVC)
# ???
@@ -54,10 +85,35 @@ IF(MSVC)
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)
ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
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()
OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
IF(FORCE_STATIC_VCRT)
FOREACH(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
IF(${flag_var} MATCHES "/MD")
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
ENDIF()
ENDFOREACH(flag_var)
ENDIF()
ELSE()
ADD_DEFINITIONS(-Wall)
ADD_DEFINITIONS(-Winline -Wall)
CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
IF("${HAVE_W_EXTRA}")
IF(HAVE_W_EXTRA)
ADD_DEFINITIONS(-Wextra)
ENDIF()
@@ -65,43 +121,56 @@ ELSE()
ADD_DEFINITIONS(-Werror)
ENDIF()
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -funroll-loops -D_DEBUG" CACHE STRING
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING
"Flags used by the compiler during Release with Debug Info builds."
FORCE)
SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING
"Flags used by the compiler during release minsize builds."
FORCE)
SET(CMAKE_C_FLAGS_RELEASE "-O2 -funroll-loops -fomit-frame-pointer -DNDEBUG" CACHE STRING
SET(CMAKE_C_FLAGS_RELEASE "-O2 -fomit-frame-pointer -DNDEBUG" CACHE STRING
"Flags used by the compiler during release builds"
FORCE)
SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING
"Flags used by the compiler during debug builds."
FORCE)
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
# Set visibility options if available
IF(NOT WIN32)
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_SWITCH)
IF("${HAVE_VISIBILITY_SWITCH}")
CHECK_C_COMPILER_FLAG(-fvisibility=internal HAVE_VISIBILITY_SWITCH)
IF(HAVE_VISIBILITY_SWITCH)
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
int main() {return 0;}" HAVE_GCC_VISIBILITY)
IF("${HAVE_GCC_VISIBILITY}")
ADD_DEFINITIONS(-fvisibility=hidden -DHAVE_GCC_VISIBILITY)
IF(HAVE_GCC_VISIBILITY)
ADD_DEFINITIONS(-fvisibility=internal -DHAVE_GCC_VISIBILITY)
ENDIF()
ENDIF()
ENDIF()
ENDIF()
CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2)));
int main() {return 0;}" HAVE_GCC_FORMAT)
CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H)
CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H)
CHECK_LIBRARY_EXISTS(m powf "" HAVE_POWF)
CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF)
IF(HAVE_SQRTF OR HAVE_ACOSF)
CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF)
CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF)
IF(HAVE_FENV_H)
CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND)
ENDIF()
IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND)
SET(EXTRA_LIBS m ${EXTRA_LIBS})
ENDIF()
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP)
CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
IF(NOT HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
@@ -132,6 +201,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)
@@ -156,22 +246,34 @@ 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(pthread pthread_setschedparam "" HAVE_PTHREAD_SETSCHEDPARAM)
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
@@ -192,9 +294,19 @@ IF(NOT HAVE_STDINT_H)
ENDIF()
ENDIF()
IF(WIN32)
# Windows needs winmm for timeGetTime, even if the backend is disabled
CHECK_SHARED_LIBRARY_EXISTS(winmm timeGetTime 0 "" HAVE_LIBWINMM)
IF(HAVE_LIBWINMM)
SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
SET(PKG_CONFIG_LIBS ${PKG_CONFIG_LIBS} -lwinmm)
ENDIF()
ENDIF()
SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
OpenAL32/alBuffer.c
OpenAL32/alDatabuffer.c
OpenAL32/alEffect.c
OpenAL32/alError.c
OpenAL32/alExtension.c
@@ -203,28 +315,40 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
OpenAL32/alSource.c
OpenAL32/alState.c
OpenAL32/alThunk.c
OpenAL32/OpenAL32.c
)
SET(ALC_OBJS Alc/ALc.c
Alc/ALu.c
Alc/alcConfig.c
Alc/alcEcho.c
Alc/alcModulator.c
Alc/alcReverb.c
Alc/alcRing.c
Alc/alcThread.c
Alc/bs2b.c
Alc/wave.c
Alc/mixer.c
Alc/panning.c
Alc/null.c
)
SET(BACKENDS "")
SET(HAVE_ALSA 0)
SET(HAVE_OSS 0)
SET(HAVE_SOLARIS 0)
SET(HAVE_DSOUND 0)
SET(HAVE_WINMM 0)
SET(HAVE_PORTAUDIO 0)
SET(HAVE_PULSEAUDIO 0)
SET(HAVE_WAVE 0)
# Check ALSA backend
IF(ALSA)
CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H)
IF(HAVE_ALSA_ASOUNDLIB_H)
CHECK_LIBRARY_EXISTS(asound snd_pcm_open "" HAVE_LIBASOUND)
IF(HAVE_DLFCN_H OR HAVE_LIBASOUND)
CHECK_SHARED_LIBRARY_EXISTS(asound snd_pcm_open 4 "" HAVE_LIBASOUND)
IF(HAVE_LIBASOUND OR HAVE_DLFCN_H OR WIN32)
SET(HAVE_ALSA 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/alsa.c)
IF(HAVE_DLFCN_H)
IF(HAVE_DLFCN_H OR WIN32)
SET(BACKENDS "${BACKENDS} ALSA,")
ELSE()
SET(BACKENDS "${BACKENDS} ALSA \(linked\),")
@@ -244,63 +368,121 @@ IF(OSS)
ENDIF()
ENDIF()
# Check Solaris backend
IF(SOLARIS)
CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H)
IF(HAVE_SYS_AUDIOIO_H)
SET(HAVE_SOLARIS 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/solaris.c)
SET(BACKENDS "${BACKENDS} Solaris,")
ENDIF()
ENDIF()
# Check DSound/MMSystem backend
IF(HAVE_WINDOWS_H)
IF(DSOUND)
CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
IF(HAVE_DSOUND_H)
IF(DSOUND)
CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
IF(HAVE_DSOUND_H)
CHECK_SHARED_LIBRARY_EXISTS(dsound DirectSoundCreate 3 "" HAVE_LIBDSOUND)
IF(HAVE_LIBDSOUND OR HAVE_DLFCN_H OR WIN32)
SET(HAVE_DSOUND 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
SET(BACKENDS "${BACKENDS} DirectSound,")
SET(CMAKE_REQUIRED_LIBRARIES dsound)
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBDSOUND)
SET(CMAKE_REQUIRED_LIBRARIES "")
# CHECK_LIBRARY_EXISTS(dsound DirectSoundCreate "" HAVE_LIBDSOUND)
IF(HAVE_LIBDSOUND)
IF(HAVE_DLFCN_H OR WIN32)
SET(BACKENDS "${BACKENDS} DirectSound,")
ELSE()
SET(BACKENDS "${BACKENDS} DirectSound \(linked\),")
SET(EXTRA_LIBS dsound ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
IF(WINMM)
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
IF(HAVE_MMSYSTEM_H)
SET(HAVE_WINMM 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
SET(BACKENDS "${BACKENDS} WinMM,")
SET(CMAKE_REQUIRED_LIBRARIES winmm)
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBWINMM)
SET(CMAKE_REQUIRED_LIBRARIES "")
# CHECK_LIBRARY_EXISTS(winmm waveInOpen "" HAVE_LIBWINMM)
IF(HAVE_LIBWINMM)
SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
IF(HAVE_WINDOWS_H)
IF(WINMM)
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM)
SET(HAVE_WINMM 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
SET(BACKENDS "${BACKENDS} WinMM,")
ENDIF()
ENDIF()
ENDIF()
# Check PortAudio backend
IF(PORTAUDIO)
CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H)
IF(HAVE_PORTAUDIO_H)
CHECK_SHARED_LIBRARY_EXISTS(portaudio Pa_Initialize 0 "" HAVE_LIBPORTAUDIO)
IF(HAVE_LIBPORTAUDIO OR HAVE_DLFCN_H OR WIN32)
SET(HAVE_PORTAUDIO 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/portaudio.c)
IF(HAVE_DLFCN_H OR WIN32)
SET(BACKENDS "${BACKENDS} PortAudio,")
ELSE()
SET(BACKENDS "${BACKENDS} PortAudio \(linked\),")
SET(EXTRA_LIBS portaudio ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# Check PortAudio backend
IF(PULSEAUDIO)
CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H)
IF(HAVE_PULSE_PULSEAUDIO_H)
CHECK_SHARED_LIBRARY_EXISTS(pulse pa_context_new 2 "" HAVE_LIBPULSE)
IF(HAVE_LIBPULSE OR HAVE_DLFCN_H OR WIN32)
SET(HAVE_PULSEAUDIO 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/pulseaudio.c)
IF(HAVE_DLFCN_H OR WIN32)
SET(BACKENDS "${BACKENDS} PulseAudio,")
ELSE()
SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),")
SET(EXTRA_LIBS pulse ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# Optionally enable the Wave Writer backend
IF(WAVE)
SET(HAVE_WAVE 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/wave.c)
SET(BACKENDS "${BACKENDS} WaveFile,")
ENDIF()
# This is always available
SET(BACKENDS "${BACKENDS} WaveFile")
SET(BACKENDS "${BACKENDS} Null")
IF(LIBTYPE STREQUAL "STATIC")
ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC)
SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS})
ENDIF()
# Needed for openal.pc.in
SET(prefix ${CMAKE_INSTALL_PREFIX})
SET(exec_prefix "\${prefix}")
SET(libdir "\${exec_prefix}/lib${LIB_SUFFIX}")
SET(bindir "\${exec_prefix}/bin")
SET(includedir "\${prefix}/include")
SET(PACKAGE_VERSION "${LIB_VERSION}")
# End configuration
CONFIGURE_FILE(
"${OpenAL_SOURCE_DIR}/config.h.in"
"${OpenAL_BINARY_DIR}/config.h")
CONFIGURE_FILE(
"${OpenAL_SOURCE_DIR}/openal.pc.in"
"${OpenAL_BINARY_DIR}/openal.pc"
@ONLY)
ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
# Build a shared library
IF(WIN32)
SET(LIBNAME openal32)
ELSE()
SET(LIBNAME openal)
ENDIF()
ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
# Build a library
ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES DEFINE_SYMBOL AL_BUILD_LIBRARY
COMPILE_FLAGS -DAL_ALEXT_PROTOTYPES
VERSION ${LIB_VERSION}.0
SOVERSION ${LIB_MAJOR_VERSION})
IF(WIN32)
IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
ENDIF()
@@ -309,26 +491,51 @@ TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
# Add an install target here
INSTALL(TARGETS ${LIBNAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
)
INSTALL(FILES include/AL/al.h
include/AL/alc.h
include/AL/alext.h
include/AL/efx.h
include/AL/efx-creative.h
DESTINATION include/AL
)
INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
DESTINATION "lib${LIB_SUFFIX}/pkgconfig")
IF(EXAMPLES)
ADD_EXECUTABLE(openal-info examples/openal-info.c)
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
INSTALL(TARGETS openal-info
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS "Building OpenAL with support for the following backends:")
MESSAGE(STATUS " ${BACKENDS}")
MESSAGE(STATUS "")
IF(WIN32)
IF(NOT HAVE_DSOUND)
MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output")
MESSAGE(STATUS " This is probably NOT what you want!")
MESSAGE(STATUS "")
ENDIF()
ENDIF()
# Install alsoft.conf configuration file
IF(ALSOFT_CONFIG)
INSTALL(FILES alsoftrc.sample
DESTINATION /etc/openal
RENAME alsoft.conf
)
MESSAGE(STATUS "Installing sample alsoft.conf")
MESSAGE(STATUS "")
ENDIF()
IF(UTILS)
ADD_EXECUTABLE(openal-info utils/openal-info.c)
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
INSTALL(TARGETS openal-info
RUNTIME DESTINATION bin
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
)
MESSAGE(STATUS "Building utility programs")
MESSAGE(STATUS "")
ENDIF()
+29 -27
View File
@@ -1,18 +1,15 @@
#ifndef _AL_AUXEFFECTSLOT_H_
#define _AL_AUXEFFECTSLOT_H_
#include "alEffect.h"
#include "AL/al.h"
#include "alEffect.h"
#include "alFilter.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECTSLOT_GAIN 0x0002
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
#define AL_EFFECTSLOT_NULL 0x0000
typedef struct ALeffectState ALeffectState;
typedef struct ALeffectslot
{
@@ -21,14 +18,12 @@ typedef struct ALeffectslot
ALfloat Gain;
ALboolean AuxSendAuto;
ALfloat *ReverbBuffer;
// in frames!
ALuint ReverbLength;
ALuint ReverbPos;
ALuint ReverbReflectPos;
ALuint ReverbLatePos;
ALfloat ReverbDecayGain;
ALfloat LastDecaySample;
ALeffectState *EffectState;
ALfloat WetBuffer[BUFFERSIZE];
ALfloat ClickRemoval[1];
ALfloat PendingClicks[1];
ALuint refcount;
@@ -38,22 +33,29 @@ typedef struct ALeffectslot
struct ALeffectslot *next;
} ALeffectslot;
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
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)[MAXCHANNELS]);
};
ALeffectState *NoneCreate(void);
ALeffectState *EAXVerbCreate(void);
ALeffectState *VerbCreate(void);
ALeffectState *EchoCreate(void);
ALeffectState *ModulatorCreate(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
+77 -11
View File
@@ -7,23 +7,89 @@
extern "C" {
#endif
#define UNUSED 0
#define PENDING 1
#define PROCESSED 2
/* Input formats (some are currently theoretical) */
enum UserFmtType {
UserFmtByte, /* AL_BYTE */
UserFmtUByte, /* AL_UNSIGNED_BYTE */
UserFmtShort, /* AL_SHORT */
UserFmtUShort, /* AL_UNSIGNED_SHORT */
UserFmtInt, /* AL_INT */
UserFmtUInt, /* AL_UNSIGNED_INT */
UserFmtFloat, /* AL_FLOAT */
UserFmtDouble, /* AL_DOUBLE */
UserFmtMulaw, /* AL_MULAW */
UserFmtIMA4, /* AL_IMA4 */
};
enum UserFmtChannels {
UserFmtMono, /* AL_MONO */
UserFmtStereo, /* AL_STEREO */
UserFmtRear, /* AL_REAR */
UserFmtQuad, /* AL_QUAD */
UserFmtX51, /* AL_5POINT1 (WFX order) */
UserFmtX61, /* AL_6POINT1 (WFX order) */
UserFmtX71, /* AL_7POINT1 (WFX order) */
};
typedef struct ALbuffer_struct
ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
enum UserFmtType *type);
ALuint BytesFromUserFmt(enum UserFmtType type);
ALuint ChannelsFromUserFmt(enum UserFmtChannels chans);
static __inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans,
enum UserFmtType type)
{
ALenum format;
ALenum eOriginalFormat;
ALshort *data;
return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type);
}
/* Storable formats */
enum FmtType {
FmtUByte = UserFmtUByte,
FmtShort = UserFmtShort,
FmtFloat = UserFmtFloat,
};
enum FmtChannels {
FmtMono = UserFmtMono,
FmtStereo = UserFmtStereo,
FmtRear = UserFmtRear,
FmtQuad = UserFmtQuad,
FmtX51 = UserFmtX51,
FmtX61 = UserFmtX61,
FmtX71 = UserFmtX71,
};
ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type);
ALuint BytesFromFmt(enum FmtType type);
ALuint ChannelsFromFmt(enum FmtChannels chans);
static __inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
{
return ChannelsFromFmt(chans) * BytesFromFmt(type);
}
typedef struct ALbuffer
{
ALvoid *data;
ALsizei size;
ALsizei frequency;
ALenum state;
ALsizei Frequency;
enum FmtChannels FmtChannels;
enum FmtType FmtType;
enum UserFmtChannels OriginalChannels;
enum UserFmtType OriginalType;
ALsizei OriginalSize;
ALsizei OriginalAlign;
ALsizei LoopStart;
ALsizei LoopEnd;
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;
} ALbuffer;
ALvoid ReleaseALBuffers(ALvoid);
ALvoid ReleaseALBuffers(ALCdevice *device);
#ifdef __cplusplus
}
+33
View File
@@ -0,0 +1,33 @@
#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;
ALintptrEXT size;
ALenum state;
ALenum usage;
/* Index to self */
ALuint databuffer;
struct ALdatabuffer *next;
} ALdatabuffer;
ALvoid ReleaseALDatabuffers(ALCdevice *device);
#ifdef __cplusplus
}
#endif
#endif
+41 -47
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_
@@ -7,46 +9,25 @@
extern "C" {
#endif
#define AL_EFFECT_TYPE 0x8001
enum {
EAXREVERB = 0,
REVERB,
ECHO,
MODULATOR,
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
MAX_EFFECTS
};
extern ALboolean DisabledEffects[MAX_EFFECTS];
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
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;
@@ -58,29 +39,42 @@ 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;
struct {
ALfloat Frequency;
ALfloat HighPassCutoff;
ALint Waveform;
} Modulator;
// Index to itself
ALuint effect;
struct ALeffect_struct *next;
} ALeffect;
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALEffects(ALvoid);
ALvoid ReleaseALEffects(ALCdevice *device);
#ifdef __cplusplus
}
+2 -1
View File
@@ -2,12 +2,13 @@
#define _AL_ERROR_H_
#include "AL/al.h"
#include "AL/alc.h"
#ifdef __cplusplus
extern "C" {
#endif
ALvoid alSetError(ALenum errorCode);
ALvoid alSetError(ALCcontext *Context, ALenum errorCode);
#ifdef __cplusplus
}
-33
View File
@@ -1,33 +0,0 @@
#ifndef _AL_EXTENSION_H_
#define _AL_EXTENSION_H_
#include "AL/al.h"
#include "AL/alc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ALextension_struct
{
ALchar *extName;
ALvoid *address;
} ALextension;
typedef struct ALfunction_struct
{
ALchar *funcName;
ALvoid *address;
} ALfunction;
typedef struct ALenum_struct
{
ALchar *enumName;
ALenum value;
} ALenums;
#ifdef __cplusplus
}
#endif
#endif
+107 -24
View File
@@ -2,23 +2,121 @@
#define _AL_FILTER_H_
#include "AL/al.h"
#include "alu.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AL_FILTER_TYPE 0x8001
typedef struct {
ALfloat coeff;
#ifndef _MSC_VER
ALfloat history[0];
#else
ALfloat history[1];
#endif
} FILTER;
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
static __inline ALfloat lpFilter4P(FILTER *iir, ALuint offset, ALfloat input)
{
ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
#define AL_LOWPASS_GAIN 0x0001
#define AL_LOWPASS_GAINHF 0x0002
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;
}
static __inline ALfloat lpFilter1P(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;
return output;
}
static __inline ALfloat lpFilter4PC(const FILTER *iir, ALuint offset, ALfloat input)
{
const ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
output = output + (history[1]-output)*a;
output = output + (history[2]-output)*a;
output = output + (history[3]-output)*a;
return output;
}
static __inline ALfloat lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat input)
{
const ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
output = output + (history[1]-output)*a;
return output;
}
static __inline ALfloat lpFilter1PC(FILTER *iir, ALuint offset, ALfloat input)
{
const ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
return output;
}
/* Calculates the low-pass filter coefficient given the pre-scaled gain and
* cos(w) value. Note that g should be pre-scaled (sqr(gain) for one-pole,
* sqrt(gain) for four-pole, etc) */
static __inline ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
ALfloat a = 0.0f;
/* Be careful with gains < 0.01, as that causes the coefficient
* head towards 1, which will flatten the signal */
g = __max(g, 0.01f);
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
return a;
}
typedef struct ALfilter_struct
typedef struct ALfilter
{
// Filter type (AL_FILTER_NULL, ...)
ALenum type;
@@ -28,25 +126,10 @@ typedef struct ALfilter_struct
// Index to itself
ALuint filter;
struct ALfilter_struct *next;
} ALfilter;
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALFilters(ALvoid);
ALvoid ReleaseALFilters(ALCdevice *device);
#ifdef __cplusplus
}
-2
View File
@@ -7,8 +7,6 @@
extern "C" {
#endif
#define AL_METERS_PER_UNIT 0x20004
typedef struct ALlistener_struct
{
ALfloat Position[3];
+303 -50
View File
@@ -3,8 +3,93 @@
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "alu.h"
#ifdef HAVE_FENV_H
#include <fenv.h>
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#ifndef AL_EXT_sample_buffer_object
#define AL_EXT_sample_buffer_object 1
typedef ptrdiff_t ALintptrEXT;
typedef ptrdiff_t ALsizeiptrEXT;
#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,ALsizeiptrEXT size,ALenum usage);
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *);
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT 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, ALintptrEXT start, ALsizeiptrEXT length, ALenum access);
typedef ALvoid (AL_APIENTRY*PFNALUNMAPDATABUFFEREXTPROC)(ALuint uiBuffer);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers);
AL_API ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers);
AL_API ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint uiBuffer);
AL_API ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage);
AL_API ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data);
AL_API ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data);
AL_API ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues);
AL_API ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue);
AL_API ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues);
AL_API ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues);
AL_API ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue);
AL_API ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues);
AL_API ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer);
AL_API ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access);
AL_API ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer);
#endif
#endif
#if defined(HAVE_STDINT_H)
#include <stdint.h>
typedef int64_t ALint64;
typedef uint64_t ALuint64;
#elif defined(HAVE___INT64)
typedef __int64 ALint64;
typedef unsigned __int64 ALuint64;
#elif (SIZEOF_LONG == 8)
typedef long ALint64;
typedef unsigned long ALuint64;
#elif (SIZEOF_LONG_LONG == 8)
typedef long long ALint64;
typedef unsigned long long ALuint64;
#endif
#ifdef HAVE_GCC_FORMAT
#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y))))
#else
#define PRINTF_STYLE(x, y)
#endif
#ifdef _WIN32
@@ -13,8 +98,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
@@ -24,22 +116,28 @@
#include <time.h>
#include <errno.h>
#define IsBadWritePtr(a,b) (0)
#define IsBadWritePtr(a,b) ((a) == NULL && (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)
static __inline void EnterCriticalSection(CRITICAL_SECTION *cs)
{
int ret;
ret = pthread_mutex_lock(cs);
assert(ret == 0);
}
static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
static __inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
{
int ret;
ret = pthread_mutex_unlock(cs);
assert(ret == 0);
}
static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
static __inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
{
pthread_mutexattr_t attrib;
int ret;
@@ -59,7 +157,7 @@ static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
pthread_mutexattr_destroy(&attrib);
}
static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
static __inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
{
int ret;
ret = pthread_mutex_destroy(cs);
@@ -70,8 +168,26 @@ static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
* to the expected DWORD. Both are defined as unsigned 32-bit types, however.
* Additionally, Win32 is supposed to measure the time since Windows started,
* as opposed to the actual time. */
static inline ALuint timeGetTime(void)
static __inline ALuint timeGetTime(void)
{
#if _POSIX_TIMERS > 0
struct timespec ts;
int ret = -1;
#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
#if _POSIX_MONOTONIC_CLOCK == 0
static int hasmono = 0;
if(hasmono > 0 || (hasmono == 0 &&
(hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0))
#endif
ret = clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
if(ret != 0)
ret = clock_gettime(CLOCK_REALTIME, &ts);
assert(ret == 0);
return ts.tv_nsec/1000000 + ts.tv_sec*1000;
#else
struct timeval tv;
int ret;
@@ -79,9 +195,10 @@ static inline ALuint timeGetTime(void)
assert(ret == 0);
return tv.tv_usec/1000 + tv.tv_sec*1000;
#endif
}
static inline void Sleep(ALuint t)
static __inline void Sleep(ALuint t)
{
struct timespec tv, rem;
tv.tv_nsec = (t*1000000)%1000000000;
@@ -94,42 +211,49 @@ 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 CRITICAL_SECTION _alMutex;
extern char _alDebug[256];
#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)
#define SWMIXER_OUTPUT_RATE 44100
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
#define AIRABSORBGAINHF (0.994f)
#define AIRABSORBGAINDBHF (-0.05f)
#define LOWPASSFREQCUTOFF (5000)
#define DEFAULT_HEAD_DAMPEN (0.25f)
// Find the next power-of-2 for non-power-of-2 numbers.
static __inline ALuint NextPowerOf2(ALuint value)
{
ALuint powerOf2 = 1;
if(value)
{
value--;
while(value)
{
value >>= 1;
powerOf2 <<= 1;
}
}
return powerOf2;
}
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*);
@@ -137,28 +261,145 @@ 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_solaris_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);
void alc_null_init(BackendFuncs *func_list);
void alc_null_deinit(void);
void alc_null_probe(int type);
typedef struct UIntMap {
struct {
ALuint key;
ALvoid *value;
} *array;
ALsizei size;
ALsizei maxsize;
} UIntMap;
void InitUIntMap(UIntMap *map);
void ResetUIntMap(UIntMap *map);
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value);
void RemoveUIntMapKey(UIntMap *map, ALuint key);
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key);
/* Device formats */
enum DevFmtType {
DevFmtByte, /* AL_BYTE */
DevFmtUByte, /* AL_UNSIGNED_BYTE */
DevFmtShort, /* AL_SHORT */
DevFmtUShort, /* AL_UNSIGNED_SHORT */
DevFmtFloat, /* AL_FLOAT */
};
enum DevFmtChannels {
DevFmtMono, /* AL_MONO */
DevFmtStereo, /* AL_STEREO */
DevFmtQuad, /* AL_QUAD */
DevFmtX51, /* AL_5POINT1 */
DevFmtX61, /* AL_6POINT1 */
DevFmtX71, /* AL_7POINT1 */
};
ALuint BytesFromDevFmt(enum DevFmtType type);
ALuint ChannelsFromDevFmt(enum DevFmtChannels chans);
static __inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans,
enum DevFmtType type)
{
return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
}
struct ALCdevice_struct
{
ALCboolean Connected;
ALboolean IsCaptureDevice;
ALuint Frequency;
ALuint UpdateSize;
ALenum Format;
ALuint NumUpdates;
enum DevFmtChannels FmtChans;
enum DevFmtType FmtType;
ALCchar *szDeviceName;
ALCenum LastError;
// 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;
ALCuint NumMonoSources;
ALCuint NumStereoSources;
ALuint NumAuxSends;
// Map of Buffers for this device
UIntMap BufferMap;
// Map of Effects for this device
UIntMap EffectMap;
// Map of Filters for this device
UIntMap FilterMap;
// Map of Databuffers for this device
UIntMap DatabufferMap;
// Stereo-to-binaural filter
struct bs2b *Bs2b;
ALCint Bs2bLevel;
// Simulated dampening from head occlusion
ALfloat HeadDampen;
// Duplicate stereo sources on the side/rear channels
ALboolean DuplicateStereo;
// Dry path buffer mix
ALfloat DryBuffer[BUFFERSIZE][MAXCHANNELS];
ALuint DevChannels[MAXCHANNELS];
ALfloat ChannelMatrix[MAXCHANNELS][MAXCHANNELS];
Channel Speaker2Chan[MAXCHANNELS];
ALfloat PanningLUT[MAXCHANNELS * LUT_NUM];
ALuint NumChan;
ALfloat ClickRemoval[MAXCHANNELS];
ALfloat PendingClicks[MAXCHANNELS];
// Contexts created on this device
ALCcontext **Contexts;
ALuint NumContexts;
BackendFuncs *Funcs;
void *ExtraData; // For the backend's use
@@ -168,7 +409,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)))
@@ -179,41 +422,38 @@ struct ALCcontext_struct
{
ALlistener Listener;
struct ALsource *Source;
ALuint SourceCount;
UIntMap SourceMap;
UIntMap EffectSlotMap;
struct ALeffectslot *AuxiliaryEffectSlot;
ALuint AuxiliaryEffectSlotCount;
struct ALdatabuffer *SampleSource;
struct ALdatabuffer *SampleSink;
ALenum LastError;
ALboolean InUse;
ALuint Frequency;
ALboolean Suspended;
ALenum DistanceModel;
ALboolean SourceDistanceModel;
ALfloat DopplerFactor;
ALfloat DopplerVelocity;
ALfloat flSpeedOfSound;
ALint lNumMonoSources;
ALint lNumStereoSources;
struct ALsource **ActiveSources;
ALsizei ActiveSourceCount;
ALsizei MaxActiveSources;
ALCdevice *Device;
ALCchar ExtensionList[1024];
struct bs2b *bs2b;
const ALCchar *ExtensionList;
ALCcontext *next;
};
ALCvoid ReleaseALC(ALCvoid);
void AppendDeviceList(const ALCchar *name);
void AppendAllDeviceList(const ALCchar *name);
void AppendCaptureDeviceList(const ALCchar *name);
ALCchar *AppendDeviceList(char *name);
ALCchar *AppendAllDeviceList(char *name);
ALCchar *AppendCaptureDeviceList(char *name);
ALCvoid SetALCError(ALenum errorCode);
ALCvoid alcSetError(ALCdevice *device, ALenum errorCode);
ALCvoid SuspendContext(ALCcontext *context);
ALCvoid ProcessContext(ALCcontext *context);
@@ -221,6 +461,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);
@@ -230,9 +472,20 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
void ReadALConfig(void);
void FreeALConfig(void);
int ConfigValueExists(const char *blockName, const char *keyName);
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, int def);
void SetRTPriority(void);
void SetDefaultChannelOrder(ALCdevice *device);
void SetDefaultWFXChannelOrder(ALCdevice *device);
void al_print(const char *fname, unsigned int line, const char *fmt, ...)
PRINTF_STYLE(3,4);
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
#ifdef __cplusplus
}
+51 -35
View File
@@ -1,33 +1,36 @@
#ifndef _AL_SOURCE_H_
#define _AL_SOURCE_H_
#define AL_NUM_SOURCE_PARAMS 128
/* This cannot be changed without working on the code! */
#define MAX_SENDS 1
#define MAX_SENDS 4
#include "alFilter.h"
#include "alu.h"
#include "AL/al.h"
#define AL_DIRECT_FILTER 0x20005
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_AIR_ABSORPTION_FACTOR 0x20007
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
#define AL_CONE_OUTER_GAINHF 0x20009
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
POINT_RESAMPLER = 0,
LINEAR_RESAMPLER,
CUBIC_RESAMPLER,
RESAMPLER_MAX,
RESAMPLER_MIN = -1,
RESAMPLER_DEFAULT = LINEAR_RESAMPLER
} resampler_t;
extern resampler_t DefaultResampler;
extern const ALsizei ResamplerPadding[RESAMPLER_MAX];
extern const ALsizei ResamplerPrePadding[RESAMPLER_MAX];
typedef struct ALbufferlistitem
{
ALuint buffer;
ALuint bufferstate;
ALuint flag;
struct ALbuffer *buffer;
struct ALbufferlistitem *next;
struct ALbufferlistitem *prev;
} ALbufferlistitem;
typedef struct ALsource
@@ -47,21 +50,19 @@ typedef struct ALsource
ALfloat vOrientation[3];
ALboolean bHeadRelative;
ALboolean bLooping;
ALenum DistanceModel;
ALuint ulBufferID;
resampler_t Resampler;
ALboolean inuse;
ALboolean play;
ALenum state;
ALuint position;
ALuint position_fraction;
struct ALbufferlistitem *queue; // Linked list of buffers in queue
ALuint BuffersInQueue; // Number of buffers in queue
ALuint BuffersProcessed; // Number of buffers already processed (played)
ALuint TotalBufferDataSize; // Total amount of data contained in the buffers queued for this source
ALuint BuffersPlayed; // Number of buffers played on this loop
ALuint BufferPosition; // Read position in audio data of current buffer
struct ALbuffer *Buffer;
ALbufferlistitem *queue; // Linked list of buffers in queue
ALuint BuffersInQueue; // Number of buffers in queue
ALuint BuffersPlayed; // Number of buffers played on this loop
ALfilter DirectFilter;
@@ -70,22 +71,14 @@ typedef struct ALsource
ALfilter WetFilter;
} Send[MAX_SENDS];
ALfloat LastDrySample;
ALfloat LastWetSample;
ALboolean DryGainHFAuto;
ALboolean WetGainAuto;
ALboolean WetGainHFAuto;
ALfloat OuterGainHF;
ALfloat AirAbsorptionFactor;
ALfloat RoomRolloffFactor;
// Index to itself
ALuint source;
ALint lBytesPlayed;
ALfloat DopplerFactor;
ALint lOffset;
ALint lOffsetType;
@@ -93,8 +86,31 @@ typedef struct ALsource
// Source Type (Static, Streaming, or Undetermined)
ALint lSourceType;
struct ALsource *next;
// Current target parameters used for mixing
ALboolean NeedsUpdate;
struct {
ALint Step;
/* A mixing matrix. First subscript is the channel number of the input
* data (regardless of channel configuration) and the second is the
* channel target (eg. FRONT_LEFT) */
ALfloat DryGains[MAXCHANNELS][MAXCHANNELS];
FILTER iirFilter;
ALfloat history[MAXCHANNELS*2];
struct {
ALfloat WetGain;
FILTER iirFilter;
ALfloat history[MAXCHANNELS];
} Send[MAX_SENDS];
} Params;
ALvoid (*Update)(struct ALsource *self, const ALCcontext *context);
// Index to itself
ALuint source;
} ALsource;
#define ALsource_Update(s,a) ((s)->Update(s,a))
ALvoid ReleaseALSources(ALCcontext *Context);
+2 -2
View File
@@ -12,7 +12,7 @@ extern "C" {
void alThunkInit(void);
void alThunkExit(void);
ALuint alThunkAddEntry(ALvoid * ptr);
ALuint alThunkAddEntry(ALvoid *ptr);
void alThunkRemoveEntry(ALuint index);
ALvoid *alThunkLookupEntry(ALuint index);
@@ -29,7 +29,7 @@ ALvoid *alThunkLookupEntry(ALuint index);
#define ALTHUNK_INIT()
#define ALTHUNK_EXIT()
#define ALTHUNK_ADDENTRY(p) ((ALuint)p)
#define ALTHUNK_REMOVEENTRY(i)
#define ALTHUNK_REMOVEENTRY(i) ((ALvoid)i)
#define ALTHUNK_LOOKUPENTRY(i) ((ALvoid*)(i))
#endif // (SIZEOF_VOIDP > SIZEOF_INT)
+113 -4
View File
@@ -3,16 +3,125 @@
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include <limits.h>
#include <math.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_POWF
#define aluPow(x,y) ((ALfloat)powf((float)(x),(float)(y)))
#else
#define aluPow(x,y) ((ALfloat)pow((double)(x),(double)(y)))
#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
#define QUADRANT_NUM 128
#define LUT_NUM (4 * QUADRANT_NUM)
#ifdef __cplusplus
extern "C" {
#endif
extern ALboolean DuplicateStereo;
typedef enum {
FRONT_LEFT = 0,
FRONT_RIGHT,
FRONT_CENTER,
LFE,
BACK_LEFT,
BACK_RIGHT,
BACK_CENTER,
SIDE_LEFT,
SIDE_RIGHT,
__inline ALuint aluBytesFromFormat(ALenum format);
__inline ALuint aluChannelsFromFormat(ALenum format);
ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format);
MAXCHANNELS
} Channel;
#define BUFFERSIZE 4096
#define FRACTIONBITS (14)
#define FRACTIONONE (1<<FRACTIONBITS)
#define FRACTIONMASK (FRACTIONONE-1)
/* Size for temporary stack storage of buffer data. Larger values need more
* stack, while smaller values may need more iterations. The value needs to be
* a sensible size, however, as it constrains the max stepping value used for
* mixing.
* The mixer requires being able to do two samplings per mixing loop. A 16KB
* buffer can hold 512 sample frames for a 7.1 float buffer. With the cubic
* resampler (which requires 3 padding sample frames), this limits the maximum
* step to about 508. This means that buffer_freq*source_pitch cannot exceed
* device_freq*508 for an 8-channel 32-bit buffer. */
#ifndef STACK_DATA_SIZE
#define STACK_DATA_SIZE 16384
#endif
static __inline ALdouble lerp(ALdouble val1, ALdouble val2, ALdouble mu)
{
return val1 + (val2-val1)*mu;
}
static __inline ALdouble cubic(ALdouble val0, ALdouble val1, ALdouble val2, ALdouble val3, ALdouble mu)
{
ALdouble mu2 = mu*mu;
ALdouble a0 = -0.5*val0 + 1.5*val1 + -1.5*val2 + 0.5*val3;
ALdouble a1 = val0 + -2.5*val1 + 2.0*val2 + -0.5*val3;
ALdouble a2 = -0.5*val0 + 0.5*val2;
ALdouble a3 = val1;
return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
}
struct ALsource;
ALvoid aluInitPanning(ALCdevice *Device);
ALint aluCart2LUTpos(ALfloat re, ALfloat im);
ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo);
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
ALvoid aluHandleDisconnect(ALCdevice *device);
#ifdef __cplusplus
}
+109 -109
View File
@@ -1,109 +1,109 @@
/*-
* Copyright (c) 2005 Boris Mikhaylov
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef BS2B_H
#define BS2B_H
/* Number of crossfeed levels */
#define BS2B_CLEVELS 3
/* Normal crossfeed levels */
#define BS2B_HIGH_CLEVEL 3
#define BS2B_MIDDLE_CLEVEL 2
#define BS2B_LOW_CLEVEL 1
/* Easy crossfeed levels */
#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS
#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS
#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS
/* Default crossfeed levels */
#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL
/* Default sample rate (Hz) */
#define BS2B_DEFAULT_SRATE 44100
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct bs2b {
int level; /* Crossfeed level */
int srate; /* Sample rate (Hz) */
/* Lowpass IIR filter coefficients */
double a0_lo;
double b1_lo;
/* Highboost IIR filter coefficients */
double a0_hi;
double a1_hi;
double b1_hi;
/* Global gain against overloading */
double gain;
/* Buffer of last filtered sample.
* [0] - first channel, [1] - second channel
*/
struct t_last_sample {
double asis[2];
double lo[2];
double hi[2];
} last_sample;
};
/* Clear buffers and set new coefficients with new crossfeed level value.
* level - crossfeed level of *LEVEL values.
*/
void bs2b_set_level(struct bs2b *bs2b, int level);
/* Return current crossfeed level value */
int bs2b_get_level(struct bs2b *bs2b);
/* Clear buffers and set new coefficients with new sample rate value.
* srate - sample rate by Hz.
*/
void bs2b_set_srate(struct bs2b *bs2b, int srate);
/* Return current sample rate value */
int bs2b_get_srate(struct bs2b *bs2b);
/* Clear buffer */
void bs2b_clear(struct bs2b *bs2b);
/* Return 1 if buffer is clear */
int bs2b_is_clear(struct bs2b *bs2b);
/* Crossfeeds one stereo sample that are pointed by sample.
* [0] - first channel, [1] - second channel.
* Returns crossfided samle by sample pointer.
*/
/* sample poits to floats */
void bs2b_cross_feed(struct bs2b *bs2b, float *sample);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* BS2B_H */
/*-
* Copyright (c) 2005 Boris Mikhaylov
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef BS2B_H
#define BS2B_H
/* Number of crossfeed levels */
#define BS2B_CLEVELS 3
/* Normal crossfeed levels */
#define BS2B_HIGH_CLEVEL 3
#define BS2B_MIDDLE_CLEVEL 2
#define BS2B_LOW_CLEVEL 1
/* Easy crossfeed levels */
#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS
#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS
#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS
/* Default crossfeed levels */
#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL
/* Default sample rate (Hz) */
#define BS2B_DEFAULT_SRATE 44100
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct bs2b {
int level; /* Crossfeed level */
int srate; /* Sample rate (Hz) */
/* Lowpass IIR filter coefficients */
double a0_lo;
double b1_lo;
/* Highboost IIR filter coefficients */
double a0_hi;
double a1_hi;
double b1_hi;
/* Global gain against overloading */
double gain;
/* Buffer of last filtered sample.
* [0] - first channel, [1] - second channel
*/
struct t_last_sample {
double asis[2];
double lo[2];
double hi[2];
} last_sample;
};
/* Clear buffers and set new coefficients with new crossfeed level value.
* level - crossfeed level of *LEVEL values.
*/
void bs2b_set_level(struct bs2b *bs2b, int level);
/* Return current crossfeed level value */
int bs2b_get_level(struct bs2b *bs2b);
/* Clear buffers and set new coefficients with new sample rate value.
* srate - sample rate by Hz.
*/
void bs2b_set_srate(struct bs2b *bs2b, int srate);
/* Return current sample rate value */
int bs2b_get_srate(struct bs2b *bs2b);
/* Clear buffer */
void bs2b_clear(struct bs2b *bs2b);
/* Return 1 if buffer is clear */
int bs2b_is_clear(struct bs2b *bs2b);
/* Crossfeeds one stereo sample that are pointed by sample.
* [0] - first channel, [1] - second channel.
* Returns crossfided samle by sample pointer.
*/
/* sample poits to floats */
void bs2b_cross_feed(struct bs2b *bs2b, float *sample);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* BS2B_H */
-74
View File
@@ -1,74 +0,0 @@
/**
* 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 "alMain.h"
#include "alBuffer.h"
#include "alFilter.h"
#include "alEffect.h"
#include "alAuxEffectSlot.h"
#include "alThunk.h"
CRITICAL_SECTION _alMutex;
#ifdef _WIN32
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
(void)lpReserved;
// Perform actions based on the reason for calling.
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
case DLL_PROCESS_DETACH:
ReleaseALC();
ReleaseALBuffers();
ReleaseALEffects();
ReleaseALFilters();
FreeALConfig();
ALTHUNK_EXIT();
DeleteCriticalSection(&_alMutex);
break;
}
return TRUE;
}
#else
#ifdef HAVE_GCC_DESTRUCTOR
static void my_deinit() __attribute__((destructor));
static void my_deinit()
{
static ALenum once = AL_FALSE;
if(once) return;
once = AL_TRUE;
ReleaseALC();
ReleaseALBuffers();
ReleaseALEffects();
ReleaseALFilters();
FreeALConfig();
ALTHUNK_EXIT();
DeleteCriticalSection(&_alMutex);
}
#endif
#endif
+253 -267
View File
@@ -29,64 +29,72 @@
#include "alAuxEffectSlot.h"
#include "alThunk.h"
#include "alError.h"
#include "alSource.h"
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);
#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k)))
#define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k)))
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALsizei i;
ALCdevice *Device;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n > 0)
Device = Context->Device;
if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else if((ALuint)n > Device->AuxiliaryEffectSlotMax - Context->EffectSlotMap.size)
alSetError(Context, AL_INVALID_VALUE);
else
{
/* NOTE: We only support one slot currently */
if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
ALenum err;
ALsizei i, j;
i = 0;
while(i < n)
{
// Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
if(!slot || !(slot->EffectState=NoneCreate()))
{
ALeffectslot **list = &Context->AuxiliaryEffectSlot;
while(*list)
list = &(*list)->next;
i = 0;
while(i < n)
{
*list = calloc(1, sizeof(ALeffectslot));
if(!(*list))
{
// We must have run out or memory
alDeleteAuxiliaryEffectSlots(i, effectslots);
alSetError(AL_OUT_OF_MEMORY);
break;
}
(*list)->Gain = 1.0;
(*list)->AuxSendAuto = AL_TRUE;
(*list)->refcount = 0;
effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->effectslot = effectslots[i];
Context->AuxiliaryEffectSlotCount++;
i++;
list = &(*list)->next;
}
free(slot);
// We must have run out or memory
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteAuxiliaryEffectSlots(i, effectslots);
break;
}
slot->effectslot = (ALuint)ALTHUNK_ADDENTRY(slot);
err = InsertUIntMapEntry(&Context->EffectSlotMap,
slot->effectslot, slot);
if(err != AL_NO_ERROR)
{
ALTHUNK_REMOVEENTRY(slot->effectslot);
ALEffect_Destroy(slot->EffectState);
free(slot);
alSetError(Context, err);
alDeleteAuxiliaryEffectSlots(i, effectslots);
break;
}
effectslots[i++] = slot->effectslot;
slot->Gain = 1.0;
slot->AuxSendAuto = AL_TRUE;
for(j = 0;j < BUFFERSIZE;j++)
slot->WetBuffer[j] = 0.0f;
for(j = 0;j < 1;j++)
{
slot->ClickRemoval[j] = 0.0f;
slot->PendingClicks[j] = 0.0f;
}
slot->refcount = 0;
}
else
alSetError(AL_INVALID_OPERATION);
}
ProcessContext(Context);
@@ -95,71 +103,54 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALeffectslot *ALAuxiliaryEffectSlot;
ALeffectslot *EffectSlot;
ALboolean SlotsValid = AL_FALSE;
ALsizei i;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n >= 0)
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
{
SlotsValid = AL_TRUE;
// Check that all effectslots are valid
for (i = 0; i < n; i++)
for(i = 0;i < n;i++)
{
if (!alIsAuxiliaryEffectSlot(effectslots[i]))
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
{
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
SlotsValid = AL_FALSE;
break;
}
else
else if(EffectSlot->refcount > 0)
{
ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
if(ALAuxiliaryEffectSlot->refcount > 0)
{
alSetError(AL_INVALID_NAME);
break;
}
}
}
if (i == n)
{
// All effectslots are valid
for (i = 0; i < n; i++)
{
// Recheck that the effectslot is valid, because there could be duplicated names
if (alIsAuxiliaryEffectSlot(effectslots[i]))
{
ALeffectslot **list;
ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
// Remove Source from list of Sources
list = &Context->AuxiliaryEffectSlot;
while(*list && *list != ALAuxiliaryEffectSlot)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
free(ALAuxiliaryEffectSlot->ReverbBuffer);
memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
free(ALAuxiliaryEffectSlot);
Context->AuxiliaryEffectSlotCount--;
}
alSetError(Context, AL_INVALID_NAME);
SlotsValid = AL_FALSE;
break;
}
}
}
else
alSetError(AL_INVALID_VALUE);
if(SlotsValid)
{
// All effectslots are valid
for(i = 0;i < n;i++)
{
// Recheck that the effectslot is valid, because there could be duplicated names
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL)
continue;
ALEffect_Destroy(EffectSlot->EffectState);
RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot);
ALTHUNK_REMOVEENTRY(EffectSlot->effectslot);
memset(EffectSlot, 0, sizeof(ALeffectslot));
free(EffectSlot);
}
}
ProcessContext(Context);
}
@@ -167,67 +158,84 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effect
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
{
ALCcontext *Context;
ALeffectslot **list;
ALboolean result;
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)
list = &(*list)->next;
result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ?
AL_TRUE : AL_FALSE);
ProcessContext(Context);
return (*list ? AL_TRUE : AL_FALSE);
return result;
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
{
ALCdevice *Device;
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
ALeffectslot *EffectSlot;
Context = alcGetCurrentContext();
if(!Context)
Context = GetContextSuspended();
if(!Context) return;
Device = Context->Device;
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
if(alIsEffect(iValue))
case AL_EFFECTSLOT_EFFECT: {
ALeffect *effect = NULL;
if(iValue == 0 ||
(effect=LookupEffect(Device->EffectMap, iValue)) != NULL)
{
ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
InitializeEffect(Context, ALEffectSlot, effect);
InitializeEffect(Context, EffectSlot, effect);
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
alSetError(Context, AL_INVALID_VALUE);
} break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(iValue == AL_TRUE || iValue == AL_FALSE)
ALEffectSlot->AuxSendAuto = iValue;
{
EffectSlot->AuxSendAuto = iValue;
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
// Force updating the sources that use this slot, since it affects the
// sending parameters
if(updateSources)
{
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
ALsource *source = Context->SourceMap.array[pos].value;
ALuint i;
for(i = 0;i < Device->NumAuxSends;i++)
{
if(!source->Send[i].Slot ||
source->Send[i].Slot->effectslot != effectslot)
continue;
source->NeedsUpdate = AL_TRUE;
break;
}
}
}
ProcessContext(Context);
}
@@ -236,15 +244,10 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
{
switch(param)
{
@@ -254,12 +257,12 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -267,35 +270,29 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
Context = alcGetCurrentContext();
if(!Context)
Context = GetContextSuspended();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffectSlot->Gain = flValue;
EffectSlot->Gain = flValue;
else
alSetError(AL_INVALID_VALUE);
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -304,15 +301,10 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
{
switch(param)
{
@@ -321,12 +313,12 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -334,36 +326,30 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
Context = alcGetCurrentContext();
if(!Context)
Context = GetContextSuspended();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
*piValue = ALEffectSlot->effect.effect;
*piValue = EffectSlot->effect.effect;
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
*piValue = ALEffectSlot->AuxSendAuto;
*piValue = EffectSlot->AuxSendAuto;
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -372,15 +358,10 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
{
switch(param)
{
@@ -390,12 +371,12 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -403,32 +384,26 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
Context = alcGetCurrentContext();
if(!Context)
Context = GetContextSuspended();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
*pflValue = ALEffectSlot->Gain;
*pflValue = EffectSlot->Gain;
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -437,15 +412,10 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (alIsAuxiliaryEffectSlot(effectslot))
if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL)
{
switch(param)
{
@@ -454,88 +424,104 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
static ALvoid NoneDestroy(ALeffectState *State)
{ free(State); }
static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
{
ALfloat *ptr = NULL;
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)[MAXCHANNELS])
{
(void)State;
(void)Slot;
(void)SamplesToDo;
(void)SamplesIn;
(void)SamplesOut;
}
ALeffectState *NoneCreate(void)
{
ALeffectState *state;
if(!effect)
state = calloc(1, sizeof(*state));
if(!state)
return NULL;
state->Destroy = NoneDestroy;
state->DeviceUpdate = NoneDeviceUpdate;
state->Update = NoneUpdate;
state->Process = NoneProcess;
return state;
}
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
{
if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
{
memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
goto done;
}
if(effect->type == AL_EFFECT_REVERB)
{
ALuint size;
ALfloat reverbwait;
reverbwait = (1.0f-effect->Reverb.Density)*(0.1f-0.075f) + 0.075f;
size = (ALuint)((ALfloat)Context->Frequency *
(effect->Reverb.ReflectionsDelay +
effect->Reverb.LateReverbDelay +
reverbwait)) + 1;
ptr = calloc(size, sizeof(ALfloat));
if(!ptr)
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();
else if(effect->type == AL_EFFECT_RING_MODULATOR)
NewState = ModulatorCreate();
/* No new state? An error occured.. */
if(NewState == NULL ||
ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
{
alSetError(AL_OUT_OF_MEMORY);
if(NewState)
ALEffect_Destroy(NewState);
alSetError(Context, AL_OUT_OF_MEMORY);
return;
}
if(ALEffectSlot->ReverbBuffer)
memcpy(ptr, ALEffectSlot->ReverbBuffer, min(size, ALEffectSlot->ReverbLength)*sizeof(ALfloat));
ALEffectSlot->ReverbLength = size;
ALEffectSlot->ReverbPos %= size;
ALEffectSlot->ReverbReflectPos = (ALuint)(ALEffectSlot->ReverbLength -
((ALfloat)Context->Frequency *
effect->Reverb.ReflectionsDelay) +
ALEffectSlot->ReverbPos) %
ALEffectSlot->ReverbLength;
ALEffectSlot->ReverbLatePos = (ALuint)(ALEffectSlot->ReverbLength -
((ALfloat)Context->Frequency *
(effect->Reverb.LateReverbDelay +
effect->Reverb.ReflectionsDelay)) +
ALEffectSlot->ReverbPos) %
ALEffectSlot->ReverbLength;
ALEffectSlot->ReverbDecayGain = pow(1.0/32768.0, 1.0/(effect->Reverb.DecayTime/reverbwait));
if(EffectSlot->EffectState)
ALEffect_Destroy(EffectSlot->EffectState);
EffectSlot->EffectState = NewState;
}
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
done:
free(ALEffectSlot->ReverbBuffer);
ALEffectSlot->ReverbBuffer = ptr;
if(!effect)
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
else
memcpy(&EffectSlot->effect, effect, sizeof(*effect));
ALEffect_Update(EffectSlot->EffectState, Context, effect);
}
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
{
#ifdef _DEBUG
if(Context->AuxiliaryEffectSlotCount > 0)
AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
#endif
while(Context->AuxiliaryEffectSlot)
ALsizei pos;
for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
{
ALeffectslot *temp = Context->AuxiliaryEffectSlot;
Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
Context->EffectSlotMap.array[pos].value = NULL;
// Release effectslot structure
free(temp->ReverbBuffer);
ALTHUNK_REMOVEENTRY(temp->effectslot);
ALEffect_Destroy(temp->EffectState);
ALTHUNK_REMOVEENTRY(temp->effectslot);
memset(temp, 0, sizeof(ALeffectslot));
free(temp);
}
Context->AuxiliaryEffectSlotCount = 0;
}
+1600 -818
View File
File diff suppressed because it is too large Load Diff
+648
View File
@@ -0,0 +1,648 @@
/**
* 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"
#define LookupDatabuffer(m, k) ((ALdatabuffer*)LookupUIntMapKey(&(m), (k)))
/*
* alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
*
* Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
*/
AL_API ALvoid AL_APIENTRY 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 || IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else
{
ALCdevice *device = Context->Device;
ALenum err;
/* Create all the new Databuffers */
while(i < n)
{
ALdatabuffer *buffer = calloc(1, sizeof(ALdatabuffer));
if(!buffer)
{
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteDatabuffersEXT(i, puiBuffers);
break;
}
buffer->databuffer = ALTHUNK_ADDENTRY(buffer);
err = InsertUIntMapEntry(&device->DatabufferMap,
buffer->databuffer, buffer);
if(err != AL_NO_ERROR)
{
ALTHUNK_REMOVEENTRY(buffer->databuffer);
memset(buffer, 0, sizeof(ALdatabuffer));
free(buffer);
alSetError(Context, err);
alDeleteDatabuffersEXT(i, puiBuffers);
break;
}
puiBuffers[i++] = buffer->databuffer;
buffer->state = UNMAPPED;
}
}
ProcessContext(Context);
}
/*
* alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
*
* Deletes the n AL Databuffers pointed to by puiBuffers
*/
AL_API ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *buffers)
{
ALCcontext *Context;
ALCdevice *device;
ALdatabuffer *ALBuf;
ALboolean Failed;
ALsizei i;
Context = GetContextSuspended();
if(!Context) return;
/* Check we are actually Deleting some Databuffers */
Failed = AL_TRUE;
device = Context->Device;
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
{
Failed = AL_FALSE;
/* Check that all the databuffers are valid and can actually be
* deleted */
for(i = 0;i < n;i++)
{
if(!buffers[i])
continue;
/* Check for valid Buffer ID */
if((ALBuf=LookupDatabuffer(device->DatabufferMap, buffers[i])) == NULL)
{
/* Invalid Databuffer */
alSetError(Context, AL_INVALID_NAME);
Failed = AL_TRUE;
break;
}
else if(ALBuf->state != UNMAPPED)
{
/* Databuffer still in use, cannot be deleted */
alSetError(Context, AL_INVALID_OPERATION);
Failed = AL_TRUE;
break;
}
}
}
/* If all the Databuffers were valid (and unmapped), then we can delete them */
if(!Failed)
{
for(i = 0;i < n;i++)
{
if((ALBuf=LookupDatabuffer(device->DatabufferMap, buffers[i])) == NULL)
continue;
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
RemoveUIntMapKey(&device->DatabufferMap, ALBuf->databuffer);
ALTHUNK_REMOVEENTRY(ALBuf->databuffer);
memset(ALBuf, 0, sizeof(ALdatabuffer));
free(ALBuf);
}
}
ProcessContext(Context);
}
/*
* alIsDatabufferEXT(ALuint uiBuffer)
*
* Checks if ulBuffer is a valid Databuffer Name
*/
AL_API ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint buffer)
{
ALCcontext *Context;
ALboolean result;
ALCdevice *device;
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
device = Context->Device;
result = ((!buffer || LookupDatabuffer(device->DatabufferMap, buffer)) ?
AL_TRUE : AL_FALSE);
ProcessContext(Context);
return result;
}
/*
* alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
*
* Fill databuffer with data
*/
AL_API ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage)
{
ALCcontext *Context;
ALdatabuffer *ALBuf;
ALCdevice *Device;
ALvoid *temp;
Context = GetContextSuspended();
if(!Context) return;
Device = Context->Device;
if((ALBuf=LookupDatabuffer(Device->DatabufferMap, buffer)) != NULL)
{
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)
{
if(size >= 0)
{
/* (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(Context, AL_OUT_OF_MEMORY);
}
else
alSetError(Context, AL_INVALID_VALUE);
}
else
alSetError(Context, AL_INVALID_ENUM);
}
else
alSetError(Context, AL_INVALID_OPERATION);
}
else
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
{
if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
{
if(pBuffer->state == UNMAPPED)
memcpy(pBuffer->data+start, data, length);
else
alSetError(pContext, AL_INVALID_OPERATION);
}
else
alSetError(pContext, AL_INVALID_VALUE);
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
{
if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
{
if(pBuffer->state == UNMAPPED)
memcpy(data, pBuffer->data+start, length);
else
alSetError(pContext, AL_INVALID_OPERATION);
}
else
alSetError(pContext, AL_INVALID_VALUE);
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
{
ALCcontext *pContext;
ALCdevice *Device;
(void)flValue;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
{
ALCcontext *pContext;
ALCdevice *Device;
(void)flValues;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
{
ALCcontext *pContext;
ALCdevice *Device;
(void)lValue;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
{
ALCcontext *pContext;
ALCdevice *Device;
(void)plValues;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
{
ALCcontext *pContext;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
if(pflValue)
{
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
}
else
alSetError(pContext, AL_INVALID_VALUE);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
{
ALCcontext *pContext;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
if(pflValues)
{
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch(eParam)
{
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
}
else
alSetError(pContext, AL_INVALID_VALUE);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
if(plValue)
{
Device = pContext->Device;
if((pBuffer=LookupDatabuffer(Device->DatabufferMap, buffer)) != NULL)
{
switch(eParam)
{
case AL_SIZE:
*plValue = (ALint)pBuffer->size;
break;
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
}
else
alSetError(pContext, AL_INVALID_VALUE);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
{
ALCcontext *pContext;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
if(plValues)
{
Device = pContext->Device;
if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
{
switch (eParam)
{
case AL_SIZE:
alGetDatabufferiEXT(buffer, eParam, plValues);
break;
default:
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(pContext, AL_INVALID_NAME);
}
else
alSetError(pContext, AL_INVALID_VALUE);
ProcessContext(pContext);
}
AL_API ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer = NULL;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if(uiBuffer == 0 ||
(pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
{
if(target == AL_SAMPLE_SOURCE_EXT)
pContext->SampleSource = pBuffer;
else if(target == AL_SAMPLE_SINK_EXT)
pContext->SampleSink = pBuffer;
else
alSetError(pContext, AL_INVALID_VALUE);
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
AL_API ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALvoid *ret = NULL;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return NULL;
Device = pContext->Device;
if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
{
if(start >= 0 && 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(pContext, AL_INVALID_OPERATION);
}
else
alSetError(pContext, AL_INVALID_ENUM);
}
else
alSetError(pContext, AL_INVALID_VALUE);
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
return ret;
}
AL_API ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
{
ALCcontext *pContext;
ALdatabuffer *pBuffer;
ALCdevice *Device;
pContext = GetContextSuspended();
if(!pContext) return;
Device = pContext->Device;
if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
{
if(pBuffer->state == MAPPED)
pBuffer->state = UNMAPPED;
else
alSetError(pContext, AL_INVALID_OPERATION);
}
else
alSetError(pContext, AL_INVALID_NAME);
ProcessContext(pContext);
}
/*
* ReleaseALDatabuffers()
*
* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
*/
ALvoid ReleaseALDatabuffers(ALCdevice *device)
{
ALsizei i;
for(i = 0;i < device->DatabufferMap.size;i++)
{
ALdatabuffer *temp = device->DatabufferMap.array[i].value;
device->DatabufferMap.array[i].value = NULL;
// Release buffer data
free(temp->data);
// Release Buffer structure
ALTHUNK_REMOVEENTRY(temp->databuffer);
memset(temp, 0, sizeof(ALdatabuffer));
free(temp);
}
}
+932 -186
View File
File diff suppressed because it is too large Load Diff
+12 -24
View File
@@ -24,36 +24,24 @@
#include "AL/alc.h"
#include "alError.h"
ALAPI ALenum ALAPIENTRY alGetError(ALvoid)
AL_API ALenum AL_APIENTRY 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)
ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
{
ALCcontext *Context;
Context=alcGetCurrentContext();
SuspendContext(Context);
if (Context && Context->LastError == AL_NO_ERROR)
Context->LastError = errorCode;
ProcessContext(Context);
if(Context->LastError == AL_NO_ERROR)
Context->LastError = errorCode;
}
+211 -267
View File
@@ -23,322 +23,271 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "alExtension.h"
#include "alError.h"
#include "alMain.h"
#include "alFilter.h"
#include "alEffect.h"
#include "alAuxEffectSlot.h"
#include "alDatabuffer.h"
#include "alSource.h"
#include "alBuffer.h"
#include "AL/al.h"
#include "AL/alc.h"
static ALfunction function[]= {
{ "alEnable", (ALvoid *) alEnable },
{ "alDisable", (ALvoid *) alDisable },
{ "alIsEnabled", (ALvoid *) alIsEnabled },
{ "alGetString", (ALvoid *) alGetString },
{ "alGetBooleanv", (ALvoid *) alGetBooleanv },
{ "alGetIntegerv", (ALvoid *) alGetIntegerv },
{ "alGetFloatv", (ALvoid *) alGetFloatv },
{ "alGetDoublev", (ALvoid *) alGetDoublev },
{ "alGetBoolean", (ALvoid *) alGetBoolean },
{ "alGetInteger", (ALvoid *) alGetInteger },
{ "alGetFloat", (ALvoid *) alGetFloat },
{ "alGetDouble", (ALvoid *) alGetDouble },
{ "alGetError", (ALvoid *) alGetError },
{ "alIsExtensionPresent", (ALvoid *) alIsExtensionPresent },
{ "alGetProcAddress", (ALvoid *) alGetProcAddress },
{ "alGetEnumValue", (ALvoid *) alGetEnumValue },
{ "alListenerf", (ALvoid *) alListenerf },
{ "alListener3f", (ALvoid *) alListener3f },
{ "alListenerfv", (ALvoid *) alListenerfv },
{ "alListeneri", (ALvoid *) alListeneri },
{ "alListener3i", (ALvoid *) alListener3i },
{ "alListeneriv", (ALvoid *) alListeneriv },
{ "alGetListenerf", (ALvoid *) alGetListenerf },
{ "alGetListener3f", (ALvoid *) alGetListener3f },
{ "alGetListenerfv", (ALvoid *) alGetListenerfv },
{ "alGetListeneri", (ALvoid *) alGetListeneri },
{ "alGetListener3i", (ALvoid *) alGetListener3i },
{ "alGetListeneriv", (ALvoid *) alGetListeneriv },
{ "alGenSources", (ALvoid *) alGenSources },
{ "alDeleteSources", (ALvoid *) alDeleteSources },
{ "alIsSource", (ALvoid *) alIsSource },
{ "alSourcef", (ALvoid *) alSourcef },
{ "alSource3f", (ALvoid *) alSource3f },
{ "alSourcefv", (ALvoid *) alSourcefv },
{ "alSourcei", (ALvoid *) alSourcei },
{ "alSource3i", (ALvoid *) alSource3i },
{ "alSourceiv", (ALvoid *) alSourceiv },
{ "alGetSourcef", (ALvoid *) alGetSourcef },
{ "alGetSource3f", (ALvoid *) alGetSource3f },
{ "alGetSourcefv", (ALvoid *) alGetSourcefv },
{ "alGetSourcei", (ALvoid *) alGetSourcei },
{ "alGetSource3i", (ALvoid *) alGetSource3i },
{ "alGetSourceiv", (ALvoid *) alGetSourceiv },
{ "alSourcePlayv", (ALvoid *) alSourcePlayv },
{ "alSourceStopv", (ALvoid *) alSourceStopv },
{ "alSourceRewindv", (ALvoid *) alSourceRewindv },
{ "alSourcePausev", (ALvoid *) alSourcePausev },
{ "alSourcePlay", (ALvoid *) alSourcePlay },
{ "alSourceStop", (ALvoid *) alSourceStop },
{ "alSourceRewind", (ALvoid *) alSourceRewind },
{ "alSourcePause", (ALvoid *) alSourcePause },
{ "alSourceQueueBuffers", (ALvoid *) alSourceQueueBuffers },
{ "alSourceUnqueueBuffers", (ALvoid *) alSourceUnqueueBuffers },
{ "alGenBuffers", (ALvoid *) alGenBuffers },
{ "alDeleteBuffers", (ALvoid *) alDeleteBuffers },
{ "alIsBuffer", (ALvoid *) alIsBuffer },
{ "alBufferData", (ALvoid *) alBufferData },
{ "alBufferf", (ALvoid *) alBufferf },
{ "alBuffer3f", (ALvoid *) alBuffer3f },
{ "alBufferfv", (ALvoid *) alBufferfv },
{ "alBufferi", (ALvoid *) alBufferi },
{ "alBuffer3i", (ALvoid *) alBuffer3i },
{ "alBufferiv", (ALvoid *) alBufferiv },
{ "alGetBufferf", (ALvoid *) alGetBufferf },
{ "alGetBuffer3f", (ALvoid *) alGetBuffer3f },
{ "alGetBufferfv", (ALvoid *) alGetBufferfv },
{ "alGetBufferi", (ALvoid *) alGetBufferi },
{ "alGetBuffer3i", (ALvoid *) alGetBuffer3i },
{ "alGetBufferiv", (ALvoid *) alGetBufferiv },
{ "alDopplerFactor", (ALvoid *) alDopplerFactor },
{ "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
{ "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
{ "alDistanceModel", (ALvoid *) alDistanceModel },
typedef struct ALenums {
const ALchar *enumName;
ALenum value;
} ALenums;
{ "alGenFilters", (ALvoid *) alGenFilters },
{ "alDeleteFilters", (ALvoid *) alDeleteFilters },
{ "alIsFilter", (ALvoid *) alIsFilter },
{ "alFilteri", (ALvoid *) alFilteri },
{ "alFilteriv", (ALvoid *) alFilteriv },
{ "alFilterf", (ALvoid *) alFilterf },
{ "alFilterfv", (ALvoid *) alFilterfv },
{ "alGetFilteri", (ALvoid *) alGetFilteri },
{ "alGetFilteriv", (ALvoid *) alGetFilteriv },
{ "alGetFilterf", (ALvoid *) alGetFilterf },
{ "alGetFilterfv", (ALvoid *) alGetFilterfv },
{ "alGenEffects", (ALvoid *) alGenEffects },
{ "alDeleteEffects", (ALvoid *) alDeleteEffects },
{ "alIsEffect", (ALvoid *) alIsEffect },
{ "alEffecti", (ALvoid *) alEffecti },
{ "alEffectiv", (ALvoid *) alEffectiv },
{ "alEffectf", (ALvoid *) alEffectf },
{ "alEffectfv", (ALvoid *) alEffectfv },
{ "alGetEffecti", (ALvoid *) alGetEffecti },
{ "alGetEffectiv", (ALvoid *) alGetEffectiv },
{ "alGetEffectf", (ALvoid *) alGetEffectf },
{ "alGetEffectfv", (ALvoid *) alGetEffectfv },
{ "alGenAuxiliaryEffectSlots", (ALvoid *) alGenAuxiliaryEffectSlots },
{ "alDeleteAuxiliaryEffectSlots",(ALvoid *) alDeleteAuxiliaryEffectSlots},
{ "alIsAuxiliaryEffectSlot", (ALvoid *) alIsAuxiliaryEffectSlot },
{ "alAuxiliaryEffectSloti", (ALvoid *) alAuxiliaryEffectSloti },
{ "alAuxiliaryEffectSlotiv", (ALvoid *) alAuxiliaryEffectSlotiv },
{ "alAuxiliaryEffectSlotf", (ALvoid *) alAuxiliaryEffectSlotf },
{ "alAuxiliaryEffectSlotfv", (ALvoid *) alAuxiliaryEffectSlotfv },
{ "alGetAuxiliaryEffectSloti", (ALvoid *) alGetAuxiliaryEffectSloti },
{ "alGetAuxiliaryEffectSlotiv", (ALvoid *) alGetAuxiliaryEffectSlotiv},
{ "alGetAuxiliaryEffectSlotf", (ALvoid *) alGetAuxiliaryEffectSlotf },
{ "alGetAuxiliaryEffectSlotfv", (ALvoid *) alGetAuxiliaryEffectSlotfv},
{ NULL, (ALvoid *) NULL } };
static ALenums enumeration[]={
static const ALenums enumeration[] = {
// Types
{ (ALchar *)"AL_INVALID", AL_INVALID },
{ (ALchar *)"AL_NONE", AL_NONE },
{ (ALchar *)"AL_FALSE", AL_FALSE },
{ (ALchar *)"AL_TRUE", AL_TRUE },
{ "AL_INVALID", AL_INVALID },
{ "AL_NONE", AL_NONE },
{ "AL_FALSE", AL_FALSE },
{ "AL_TRUE", AL_TRUE },
// Source and Listener Properties
{ (ALchar *)"AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE },
{ (ALchar *)"AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE },
{ (ALchar *)"AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE },
{ (ALchar *)"AL_PITCH", AL_PITCH },
{ (ALchar *)"AL_POSITION", AL_POSITION },
{ (ALchar *)"AL_DIRECTION", AL_DIRECTION },
{ (ALchar *)"AL_VELOCITY", AL_VELOCITY },
{ (ALchar *)"AL_LOOPING", AL_LOOPING },
{ (ALchar *)"AL_BUFFER", AL_BUFFER },
{ (ALchar *)"AL_GAIN", AL_GAIN },
{ (ALchar *)"AL_MIN_GAIN", AL_MIN_GAIN },
{ (ALchar *)"AL_MAX_GAIN", AL_MAX_GAIN },
{ (ALchar *)"AL_ORIENTATION", AL_ORIENTATION },
{ (ALchar *)"AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE },
{ (ALchar *)"AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR },
{ (ALchar *)"AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN },
{ (ALchar *)"AL_MAX_DISTANCE", AL_MAX_DISTANCE },
{ (ALchar *)"AL_SEC_OFFSET", AL_SEC_OFFSET },
{ (ALchar *)"AL_SAMPLE_OFFSET", AL_SAMPLE_OFFSET },
{ (ALchar *)"AL_BYTE_OFFSET", AL_BYTE_OFFSET },
{ (ALchar *)"AL_SOURCE_TYPE", AL_SOURCE_TYPE },
{ (ALchar *)"AL_STATIC", AL_STATIC },
{ (ALchar *)"AL_STREAMING", AL_STREAMING },
{ (ALchar *)"AL_UNDETERMINED", AL_UNDETERMINED },
{ (ALchar *)"AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
{ "AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE },
{ "AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE },
{ "AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE },
{ "AL_PITCH", AL_PITCH },
{ "AL_POSITION", AL_POSITION },
{ "AL_DIRECTION", AL_DIRECTION },
{ "AL_VELOCITY", AL_VELOCITY },
{ "AL_LOOPING", AL_LOOPING },
{ "AL_BUFFER", AL_BUFFER },
{ "AL_GAIN", AL_GAIN },
{ "AL_MIN_GAIN", AL_MIN_GAIN },
{ "AL_MAX_GAIN", AL_MAX_GAIN },
{ "AL_ORIENTATION", AL_ORIENTATION },
{ "AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE },
{ "AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR },
{ "AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN },
{ "AL_MAX_DISTANCE", AL_MAX_DISTANCE },
{ "AL_SEC_OFFSET", AL_SEC_OFFSET },
{ "AL_SAMPLE_OFFSET", AL_SAMPLE_OFFSET },
{ "AL_SAMPLE_RW_OFFSETS_SOFT", AL_SAMPLE_RW_OFFSETS_SOFT },
{ "AL_BYTE_OFFSET", AL_BYTE_OFFSET },
{ "AL_BYTE_RW_OFFSETS_SOFT", AL_BYTE_RW_OFFSETS_SOFT },
{ "AL_SOURCE_TYPE", AL_SOURCE_TYPE },
{ "AL_STATIC", AL_STATIC },
{ "AL_STREAMING", AL_STREAMING },
{ "AL_UNDETERMINED", AL_UNDETERMINED },
{ "AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
// Source EFX Properties
{ (ALchar *)"AL_DIRECT_FILTER", AL_DIRECT_FILTER },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER", AL_AUXILIARY_SEND_FILTER },
{ (ALchar *)"AL_AIR_ABSORPTION_FACTOR", AL_AIR_ABSORPTION_FACTOR },
{ (ALchar *)"AL_ROOM_ROLLOFF_FACTOR", AL_ROOM_ROLLOFF_FACTOR },
{ (ALchar *)"AL_CONE_OUTER_GAINHF", AL_CONE_OUTER_GAINHF },
{ (ALchar *)"AL_DIRECT_FILTER_GAINHF_AUTO", AL_DIRECT_FILTER_GAINHF_AUTO },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAIN_AUTO", AL_AUXILIARY_SEND_FILTER_GAIN_AUTO },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO", AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO},
{ "AL_DIRECT_FILTER", AL_DIRECT_FILTER },
{ "AL_AUXILIARY_SEND_FILTER", AL_AUXILIARY_SEND_FILTER },
{ "AL_AIR_ABSORPTION_FACTOR", AL_AIR_ABSORPTION_FACTOR },
{ "AL_ROOM_ROLLOFF_FACTOR", AL_ROOM_ROLLOFF_FACTOR },
{ "AL_CONE_OUTER_GAINHF", AL_CONE_OUTER_GAINHF },
{ "AL_DIRECT_FILTER_GAINHF_AUTO", AL_DIRECT_FILTER_GAINHF_AUTO },
{ "AL_AUXILIARY_SEND_FILTER_GAIN_AUTO", AL_AUXILIARY_SEND_FILTER_GAIN_AUTO },
{ "AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO", AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO},
// Source State information
{ (ALchar *)"AL_SOURCE_STATE", AL_SOURCE_STATE },
{ (ALchar *)"AL_INITIAL", AL_INITIAL },
{ (ALchar *)"AL_PLAYING", AL_PLAYING },
{ (ALchar *)"AL_PAUSED", AL_PAUSED },
{ (ALchar *)"AL_STOPPED", AL_STOPPED },
{ "AL_SOURCE_STATE", AL_SOURCE_STATE },
{ "AL_INITIAL", AL_INITIAL },
{ "AL_PLAYING", AL_PLAYING },
{ "AL_PAUSED", AL_PAUSED },
{ "AL_STOPPED", AL_STOPPED },
// Queue information
{ (ALchar *)"AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
{ (ALchar *)"AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
{ "AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
{ "AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
// Buffer Formats
{ (ALchar *)"AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
{ (ALchar *)"AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
{ (ALchar *)"AL_FORMAT_MONO_FLOAT32", AL_FORMAT_MONO_FLOAT32 },
{ (ALchar *)"AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
{ (ALchar *)"AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
{ (ALchar *)"AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 },
{ (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
{ (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
{ (ALchar *)"AL_FORMAT_QUAD8_LOKI", AL_FORMAT_QUAD8_LOKI },
{ (ALchar *)"AL_FORMAT_QUAD16_LOKI", AL_FORMAT_QUAD16_LOKI },
{ (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
{ (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
{ (ALchar *)"AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 },
{ (ALchar *)"AL_FORMAT_51CHN8", AL_FORMAT_51CHN8 },
{ (ALchar *)"AL_FORMAT_51CHN16", AL_FORMAT_51CHN16 },
{ (ALchar *)"AL_FORMAT_51CHN32", AL_FORMAT_51CHN32 },
{ (ALchar *)"AL_FORMAT_61CHN8", AL_FORMAT_61CHN8 },
{ (ALchar *)"AL_FORMAT_61CHN16", AL_FORMAT_61CHN16 },
{ (ALchar *)"AL_FORMAT_61CHN32", AL_FORMAT_61CHN32 },
{ (ALchar *)"AL_FORMAT_71CHN8", AL_FORMAT_71CHN8 },
{ (ALchar *)"AL_FORMAT_71CHN16", AL_FORMAT_71CHN16 },
{ (ALchar *)"AL_FORMAT_71CHN32", AL_FORMAT_71CHN32 },
{ (ALchar *)"AL_FORMAT_REAR8", AL_FORMAT_REAR8 },
{ (ALchar *)"AL_FORMAT_REAR16", AL_FORMAT_REAR16 },
{ (ALchar *)"AL_FORMAT_REAR32", AL_FORMAT_REAR32 },
{ "AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
{ "AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
{ "AL_FORMAT_MONO_FLOAT32", AL_FORMAT_MONO_FLOAT32 },
{ "AL_FORMAT_MONO_DOUBLE_EXT", AL_FORMAT_MONO_DOUBLE_EXT },
{ "AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
{ "AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
{ "AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 },
{ "AL_FORMAT_STEREO_DOUBLE_EXT", AL_FORMAT_STEREO_DOUBLE_EXT },
{ "AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
{ "AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
{ "AL_FORMAT_QUAD8_LOKI", AL_FORMAT_QUAD8_LOKI },
{ "AL_FORMAT_QUAD16_LOKI", AL_FORMAT_QUAD16_LOKI },
{ "AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
{ "AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
{ "AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 },
{ "AL_FORMAT_51CHN8", AL_FORMAT_51CHN8 },
{ "AL_FORMAT_51CHN16", AL_FORMAT_51CHN16 },
{ "AL_FORMAT_51CHN32", AL_FORMAT_51CHN32 },
{ "AL_FORMAT_61CHN8", AL_FORMAT_61CHN8 },
{ "AL_FORMAT_61CHN16", AL_FORMAT_61CHN16 },
{ "AL_FORMAT_61CHN32", AL_FORMAT_61CHN32 },
{ "AL_FORMAT_71CHN8", AL_FORMAT_71CHN8 },
{ "AL_FORMAT_71CHN16", AL_FORMAT_71CHN16 },
{ "AL_FORMAT_71CHN32", AL_FORMAT_71CHN32 },
{ "AL_FORMAT_REAR8", AL_FORMAT_REAR8 },
{ "AL_FORMAT_REAR16", AL_FORMAT_REAR16 },
{ "AL_FORMAT_REAR32", AL_FORMAT_REAR32 },
{ "AL_FORMAT_MONO_MULAW", AL_FORMAT_MONO_MULAW },
{ "AL_FORMAT_MONO_MULAW_EXT", AL_FORMAT_MONO_MULAW },
{ "AL_FORMAT_STEREO_MULAW", AL_FORMAT_STEREO_MULAW },
{ "AL_FORMAT_STEREO_MULAW_EXT", AL_FORMAT_STEREO_MULAW },
{ "AL_FORMAT_QUAD_MULAW", AL_FORMAT_QUAD_MULAW },
{ "AL_FORMAT_51CHN_MULAW", AL_FORMAT_51CHN_MULAW },
{ "AL_FORMAT_61CHN_MULAW", AL_FORMAT_61CHN_MULAW },
{ "AL_FORMAT_71CHN_MULAW", AL_FORMAT_71CHN_MULAW },
{ "AL_FORMAT_REAR_MULAW", AL_FORMAT_REAR_MULAW },
// Buffer attributes
{ (ALchar *)"AL_FREQUENCY", AL_FREQUENCY },
{ (ALchar *)"AL_BITS", AL_BITS },
{ (ALchar *)"AL_CHANNELS", AL_CHANNELS },
{ (ALchar *)"AL_SIZE", AL_SIZE },
{ "AL_FREQUENCY", AL_FREQUENCY },
{ "AL_BITS", AL_BITS },
{ "AL_CHANNELS", AL_CHANNELS },
{ "AL_SIZE", AL_SIZE },
// Buffer States (not supported yet)
{ (ALchar *)"AL_UNUSED", AL_UNUSED },
{ (ALchar *)"AL_PENDING", AL_PENDING },
{ (ALchar *)"AL_PROCESSED", AL_PROCESSED },
{ "AL_UNUSED", AL_UNUSED },
{ "AL_PENDING", AL_PENDING },
{ "AL_PROCESSED", AL_PROCESSED },
// AL Error Messages
{ (ALchar *)"AL_NO_ERROR", AL_NO_ERROR },
{ (ALchar *)"AL_INVALID_NAME", AL_INVALID_NAME },
{ (ALchar *)"AL_INVALID_ENUM", AL_INVALID_ENUM },
{ (ALchar *)"AL_INVALID_VALUE", AL_INVALID_VALUE },
{ (ALchar *)"AL_INVALID_OPERATION", AL_INVALID_OPERATION },
{ (ALchar *)"AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY },
{ "AL_NO_ERROR", AL_NO_ERROR },
{ "AL_INVALID_NAME", AL_INVALID_NAME },
{ "AL_INVALID_ENUM", AL_INVALID_ENUM },
{ "AL_INVALID_VALUE", AL_INVALID_VALUE },
{ "AL_INVALID_OPERATION", AL_INVALID_OPERATION },
{ "AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY },
// Context strings
{ (ALchar *)"AL_VENDOR", AL_VENDOR },
{ (ALchar *)"AL_VERSION", AL_VERSION },
{ (ALchar *)"AL_RENDERER", AL_RENDERER },
{ (ALchar *)"AL_EXTENSIONS", AL_EXTENSIONS },
{ "AL_VENDOR", AL_VENDOR },
{ "AL_VERSION", AL_VERSION },
{ "AL_RENDERER", AL_RENDERER },
{ "AL_EXTENSIONS", AL_EXTENSIONS },
// Global states
{ (ALchar *)"AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR },
{ (ALchar *)"AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY },
{ (ALchar *)"AL_DISTANCE_MODEL", AL_DISTANCE_MODEL },
{ (ALchar *)"AL_SPEED_OF_SOUND", AL_SPEED_OF_SOUND },
{ "AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR },
{ "AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY },
{ "AL_DISTANCE_MODEL", AL_DISTANCE_MODEL },
{ "AL_SPEED_OF_SOUND", AL_SPEED_OF_SOUND },
{ "AL_SOURCE_DISTANCE_MODEL", AL_SOURCE_DISTANCE_MODEL },
// Distance Models
{ (ALchar *)"AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE },
{ (ALchar *)"AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED },
{ (ALchar *)"AL_LINEAR_DISTANCE", AL_LINEAR_DISTANCE },
{ (ALchar *)"AL_LINEAR_DISTANCE_CLAMPED", AL_LINEAR_DISTANCE_CLAMPED },
{ (ALchar *)"AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
{ (ALchar *)"AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
{ "AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE },
{ "AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED },
{ "AL_LINEAR_DISTANCE", AL_LINEAR_DISTANCE },
{ "AL_LINEAR_DISTANCE_CLAMPED", AL_LINEAR_DISTANCE_CLAMPED },
{ "AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
{ "AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
// Filter types
{ (ALchar *)"AL_FILTER_TYPE", AL_FILTER_TYPE },
{ (ALchar *)"AL_FILTER_NULL", AL_FILTER_NULL },
{ (ALchar *)"AL_FILTER_LOWPASS", AL_FILTER_LOWPASS },
{ (ALchar *)"AL_FILTER_HIGHPASS", AL_FILTER_HIGHPASS },
{ (ALchar *)"AL_FILTER_BANDPASS", AL_FILTER_BANDPASS },
{ "AL_FILTER_TYPE", AL_FILTER_TYPE },
{ "AL_FILTER_NULL", AL_FILTER_NULL },
{ "AL_FILTER_LOWPASS", AL_FILTER_LOWPASS },
#if 0
{ "AL_FILTER_HIGHPASS", AL_FILTER_HIGHPASS },
{ "AL_FILTER_BANDPASS", AL_FILTER_BANDPASS },
#endif
// Filter params
{ (ALchar *)"AL_LOWPASS_GAIN", AL_LOWPASS_GAIN },
{ (ALchar *)"AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF },
{ "AL_LOWPASS_GAIN", AL_LOWPASS_GAIN },
{ "AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF },
// Effect types
{ (ALchar *)"AL_EFFECT_TYPE", AL_EFFECT_TYPE },
{ (ALchar *)"AL_EFFECT_NULL", AL_EFFECT_NULL },
{ (ALchar *)"AL_EFFECT_REVERB", AL_EFFECT_REVERB },
{ (ALchar *)"AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
{ (ALchar *)"AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
{ (ALchar *)"AL_EFFECT_ECHO", AL_EFFECT_ECHO },
{ (ALchar *)"AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
{ (ALchar *)"AL_EFFECT_FREQUENCY_SHIFTER", AL_EFFECT_FREQUENCY_SHIFTER },
{ (ALchar *)"AL_EFFECT_VOCAL_MORPHER", AL_EFFECT_VOCAL_MORPHER },
{ (ALchar *)"AL_EFFECT_PITCH_SHIFTER", AL_EFFECT_PITCH_SHIFTER },
{ (ALchar *)"AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
{ (ALchar *)"AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH },
{ (ALchar *)"AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
{ (ALchar *)"AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
{ "AL_EFFECT_TYPE", AL_EFFECT_TYPE },
{ "AL_EFFECT_NULL", AL_EFFECT_NULL },
{ "AL_EFFECT_REVERB", AL_EFFECT_REVERB },
{ "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB },
#if 0
{ "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
{ "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
#endif
{ "AL_EFFECT_ECHO", AL_EFFECT_ECHO },
#if 0
{ "AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
{ "AL_EFFECT_FREQUENCY_SHIFTER", AL_EFFECT_FREQUENCY_SHIFTER },
{ "AL_EFFECT_VOCAL_MORPHER", AL_EFFECT_VOCAL_MORPHER },
{ "AL_EFFECT_PITCH_SHIFTER", AL_EFFECT_PITCH_SHIFTER },
#endif
{ "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
#if 0
{ "AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH },
{ "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
{ "AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
#endif
// Reverb params
{ (ALchar *)"AL_REVERB_DENSITY", AL_REVERB_DENSITY },
{ (ALchar *)"AL_REVERB_DIFFUSION", AL_REVERB_DIFFUSION },
{ (ALchar *)"AL_REVERB_GAIN", AL_REVERB_GAIN },
{ (ALchar *)"AL_REVERB_GAINHF", AL_REVERB_GAINHF },
{ (ALchar *)"AL_REVERB_DECAY_TIME", AL_REVERB_DECAY_TIME },
{ (ALchar *)"AL_REVERB_DECAY_HFRATIO", AL_REVERB_DECAY_HFRATIO },
{ (ALchar *)"AL_REVERB_REFLECTIONS_GAIN", AL_REVERB_REFLECTIONS_GAIN },
{ (ALchar *)"AL_REVERB_REFLECTIONS_DELAY", AL_REVERB_REFLECTIONS_DELAY },
{ (ALchar *)"AL_REVERB_LATE_REVERB_GAIN", AL_REVERB_LATE_REVERB_GAIN },
{ (ALchar *)"AL_REVERB_LATE_REVERB_DELAY", AL_REVERB_LATE_REVERB_DELAY },
{ (ALchar *)"AL_REVERB_AIR_ABSORPTION_GAINHF", AL_REVERB_AIR_ABSORPTION_GAINHF },
{ (ALchar *)"AL_REVERB_ROOM_ROLLOFF_FACTOR", AL_REVERB_ROOM_ROLLOFF_FACTOR },
{ (ALchar *)"AL_REVERB_DECAY_HFLIMIT", AL_REVERB_DECAY_HFLIMIT },
{ "AL_REVERB_DENSITY", AL_REVERB_DENSITY },
{ "AL_REVERB_DIFFUSION", AL_REVERB_DIFFUSION },
{ "AL_REVERB_GAIN", AL_REVERB_GAIN },
{ "AL_REVERB_GAINHF", AL_REVERB_GAINHF },
{ "AL_REVERB_DECAY_TIME", AL_REVERB_DECAY_TIME },
{ "AL_REVERB_DECAY_HFRATIO", AL_REVERB_DECAY_HFRATIO },
{ "AL_REVERB_REFLECTIONS_GAIN", AL_REVERB_REFLECTIONS_GAIN },
{ "AL_REVERB_REFLECTIONS_DELAY", AL_REVERB_REFLECTIONS_DELAY },
{ "AL_REVERB_LATE_REVERB_GAIN", AL_REVERB_LATE_REVERB_GAIN },
{ "AL_REVERB_LATE_REVERB_DELAY", AL_REVERB_LATE_REVERB_DELAY },
{ "AL_REVERB_AIR_ABSORPTION_GAINHF", AL_REVERB_AIR_ABSORPTION_GAINHF },
{ "AL_REVERB_ROOM_ROLLOFF_FACTOR", AL_REVERB_ROOM_ROLLOFF_FACTOR },
{ "AL_REVERB_DECAY_HFLIMIT", AL_REVERB_DECAY_HFLIMIT },
// EAX Reverb params
{ "AL_EAXREVERB_DENSITY", AL_EAXREVERB_DENSITY },
{ "AL_EAXREVERB_DIFFUSION", AL_EAXREVERB_DIFFUSION },
{ "AL_EAXREVERB_GAIN", AL_EAXREVERB_GAIN },
{ "AL_EAXREVERB_GAINHF", AL_EAXREVERB_GAINHF },
{ "AL_EAXREVERB_GAINLF", AL_EAXREVERB_GAINLF },
{ "AL_EAXREVERB_DECAY_TIME", AL_EAXREVERB_DECAY_TIME },
{ "AL_EAXREVERB_DECAY_HFRATIO", AL_EAXREVERB_DECAY_HFRATIO },
{ "AL_EAXREVERB_DECAY_LFRATIO", AL_EAXREVERB_DECAY_LFRATIO },
{ "AL_EAXREVERB_REFLECTIONS_GAIN", AL_EAXREVERB_REFLECTIONS_GAIN },
{ "AL_EAXREVERB_REFLECTIONS_DELAY", AL_EAXREVERB_REFLECTIONS_DELAY },
{ "AL_EAXREVERB_REFLECTIONS_PAN", AL_EAXREVERB_REFLECTIONS_PAN },
{ "AL_EAXREVERB_LATE_REVERB_GAIN", AL_EAXREVERB_LATE_REVERB_GAIN },
{ "AL_EAXREVERB_LATE_REVERB_DELAY", AL_EAXREVERB_LATE_REVERB_DELAY },
{ "AL_EAXREVERB_LATE_REVERB_PAN", AL_EAXREVERB_LATE_REVERB_PAN },
{ "AL_EAXREVERB_ECHO_TIME", AL_EAXREVERB_ECHO_TIME },
{ "AL_EAXREVERB_ECHO_DEPTH", AL_EAXREVERB_ECHO_DEPTH },
{ "AL_EAXREVERB_MODULATION_TIME", AL_EAXREVERB_MODULATION_TIME },
{ "AL_EAXREVERB_MODULATION_DEPTH", AL_EAXREVERB_MODULATION_DEPTH },
{ "AL_EAXREVERB_AIR_ABSORPTION_GAINHF", AL_EAXREVERB_AIR_ABSORPTION_GAINHF },
{ "AL_EAXREVERB_HFREFERENCE", AL_EAXREVERB_HFREFERENCE },
{ "AL_EAXREVERB_LFREFERENCE", AL_EAXREVERB_LFREFERENCE },
{ "AL_EAXREVERB_ROOM_ROLLOFF_FACTOR", AL_EAXREVERB_ROOM_ROLLOFF_FACTOR },
{ "AL_EAXREVERB_DECAY_HFLIMIT", AL_EAXREVERB_DECAY_HFLIMIT },
// Echo params
{ "AL_ECHO_DELAY", AL_ECHO_DELAY },
{ "AL_ECHO_LRDELAY", AL_ECHO_LRDELAY },
{ "AL_ECHO_DAMPING", AL_ECHO_DAMPING },
{ "AL_ECHO_FEEDBACK", AL_ECHO_FEEDBACK },
{ "AL_ECHO_SPREAD", AL_ECHO_SPREAD },
// Ring Modulator params
{ "AL_RING_MODULATOR_FREQUENCY", AL_RING_MODULATOR_FREQUENCY },
{ "AL_RING_MODULATOR_HIGHPASS_CUTOFF", AL_RING_MODULATOR_HIGHPASS_CUTOFF },
{ "AL_RING_MODULATOR_WAVEFORM", AL_RING_MODULATOR_WAVEFORM },
// Default
{ (ALchar *)NULL, (ALenum)0 }
{ NULL, (ALenum)0 }
};
ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
{
ALboolean bIsSupported = AL_FALSE;
ALCcontext *pContext;
const char *ptr;
size_t len;
if (!extName)
pContext = GetContextSuspended();
if(!pContext) return AL_FALSE;
if(!extName)
{
alSetError(AL_INVALID_VALUE);
alSetError(pContext, AL_INVALID_VALUE);
ProcessContext(pContext);
return AL_FALSE;
}
pContext = alcGetCurrentContext();
if(!pContext)
{
alSetError(AL_INVALID_OPERATION);
return AL_FALSE;
}
SuspendContext(pContext);
len = strlen(extName);
ptr = pContext->ExtensionList;
while(ptr && *ptr)
@@ -363,19 +312,14 @@ ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
}
ALAPI ALvoid * ALAPIENTRY alGetProcAddress(const ALchar *funcName)
AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName)
{
ALsizei i = 0;
while(function[i].funcName &&
strcmp((char*)function[i].funcName, (char*)funcName) != 0)
i++;
return function[i].address;
if(!funcName)
return NULL;
return alcGetProcAddress(NULL, funcName);
}
/* NOTE: This function must be able to run without a context! */
ALAPI ALenum ALAPIENTRY alGetEnumValue(const ALchar *enumName)
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName)
{
ALsizei i = 0;
+170 -163
View File
@@ -29,50 +29,51 @@
#include "alThunk.h"
#include "alError.h"
static ALfilter *g_FilterList;
static ALuint g_FilterCount;
static void InitFilterParams(ALfilter *filter, ALenum type);
#define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k)))
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
ALCcontext *Context;
ALsizei i;
ALsizei i=0;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n > 0)
if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else
{
// Check that enough memory has been allocted in the 'filters' array for n Filters
if (!IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
ALCdevice *device = Context->Device;
ALenum err;
while(i < n)
{
ALfilter **list = &g_FilterList;
while(*list)
list = &(*list)->next;
i = 0;
while(i < n)
ALfilter *filter = calloc(1, sizeof(ALfilter));
if(!filter)
{
*list = calloc(1, sizeof(ALfilter));
if(!(*list))
{
// We must have run out or memory
alDeleteFilters(i, filters);
alSetError(AL_OUT_OF_MEMORY);
break;
}
filters[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->filter = filters[i];
InitFilterParams(*list, AL_FILTER_NULL);
g_FilterCount++;
i++;
list = &(*list)->next;
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteFilters(i, filters);
break;
}
filter->filter = ALTHUNK_ADDENTRY(filter);
err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter);
if(err != AL_NO_ERROR)
{
ALTHUNK_REMOVEENTRY(filter->filter);
memset(filter, 0, sizeof(ALfilter));
free(filter);
alSetError(Context, err);
alDeleteFilters(i, filters);
break;
}
filters[i++] = filter->filter;
InitFilterParams(filter, AL_FILTER_NULL);
}
}
@@ -82,55 +83,52 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
{
ALCcontext *Context;
ALCdevice *device;
ALfilter *ALFilter;
ALboolean Failed;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (n >= 0)
Failed = AL_TRUE;
device = Context->Device;
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
{
Failed = AL_FALSE;
// Check that all filters are valid
for (i = 0; i < n; i++)
for(i = 0;i < n;i++)
{
if (!alIsFilter(filters[i]))
if(!filters[i])
continue;
if(LookupFilter(device->FilterMap, filters[i]) == NULL)
{
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
Failed = AL_TRUE;
break;
}
}
}
if (i == n)
if(!Failed)
{
// All filters are valid
for(i = 0;i < n;i++)
{
// All filters are valid
for (i = 0; i < n; i++)
{
// Recheck that the filter is valid, because there could be duplicated names
if (filters[i] && alIsFilter(filters[i]))
{
ALfilter **list;
// Recheck that the filter is valid, because there could be duplicated names
if((ALFilter=LookupFilter(device->FilterMap, filters[i])) == NULL)
continue;
ALFilter = ((ALfilter*)ALTHUNK_LOOKUPENTRY(filters[i]));
RemoveUIntMapKey(&device->FilterMap, ALFilter->filter);
ALTHUNK_REMOVEENTRY(ALFilter->filter);
// Remove Source from list of Sources
list = &g_FilterList;
while(*list && *list != ALFilter)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALFilter->filter);
memset(ALFilter, 0, sizeof(ALfilter));
free(ALFilter);
g_FilterCount--;
}
}
memset(ALFilter, 0, sizeof(ALfilter));
free(ALFilter);
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
@@ -138,31 +136,31 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
{
ALCcontext *Context;
ALfilter **list;
ALboolean result;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return AL_FALSE;
list = &g_FilterList;
while(*list && (*list)->filter != filter)
list = &(*list)->next;
result = ((!filter || LookupFilter(Context->Device->FilterMap, filter)) ?
AL_TRUE : AL_FALSE);
ProcessContext(Context);
return ((*list || !filter) ? AL_TRUE : AL_FALSE);
return result;
}
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
{
case AL_FILTER_TYPE:
@@ -170,16 +168,16 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
iValue == AL_FILTER_LOWPASS)
InitFilterParams(ALFilter, iValue);
else
alSetError(AL_INVALID_VALUE);
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -187,11 +185,13 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
ALCdevice *Device;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if(LookupFilter(Device->FilterMap, filter) != NULL)
{
switch(param)
{
@@ -200,12 +200,12 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValue
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -213,43 +213,47 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValue
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
switch(ALFilter->type)
{
case AL_LOWPASS_GAIN:
if(ALFilter->type == AL_FILTER_LOWPASS)
case AL_FILTER_LOWPASS:
switch(param)
{
case AL_LOWPASS_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
ALFilter->Gain = flValue;
}
else
alSetError(AL_INVALID_ENUM);
break;
else
alSetError(Context, AL_INVALID_VALUE);
break;
case AL_LOWPASS_GAINHF:
if(ALFilter->type == AL_FILTER_LOWPASS)
{
case AL_LOWPASS_GAINHF:
if(flValue >= 0.0f && flValue <= 1.0f)
ALFilter->GainHF = flValue;
else
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
else
alSetError(AL_INVALID_ENUM);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -257,26 +261,23 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
ALCdevice *Device;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if(LookupFilter(Device->FilterMap, filter) != NULL)
{
switch(param)
{
case AL_LOWPASS_GAIN:
case AL_LOWPASS_GAINHF:
alFilterf(filter, param, pflValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
alFilterf(filter, param, pflValues[0]);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -284,23 +285,28 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflVa
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
(void)piValue;
Context = GetContextSuspended();
if(!Context) return;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
Device = Context->Device;
if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
{
switch(param)
{
case AL_FILTER_TYPE:
*piValue = ALFilter->type;
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -308,23 +314,27 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piVal
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
ALCdevice *Device;
(void)piValues;
Context = GetContextSuspended();
if(!Context) return;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
Device = Context->Device;
if(LookupFilter(Device->FilterMap, filter) != NULL)
{
switch(param)
{
case AL_FILTER_TYPE:
alGetFilteri(filter, param, piValues);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -332,37 +342,41 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piVa
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL)
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
switch(ALFilter->type)
{
case AL_LOWPASS_GAIN:
if(ALFilter->type == AL_FILTER_LOWPASS)
case AL_FILTER_LOWPASS:
switch(param)
{
case AL_LOWPASS_GAIN:
*pflValue = ALFilter->Gain;
else
alSetError(AL_INVALID_ENUM);
break;
break;
case AL_LOWPASS_GAINHF:
if(ALFilter->type == AL_FILTER_LOWPASS)
case AL_LOWPASS_GAINHF:
*pflValue = ALFilter->GainHF;
else
alSetError(AL_INVALID_ENUM);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
@@ -370,48 +384,41 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pfl
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
ALCdevice *Device;
Context = alcGetCurrentContext();
SuspendContext(Context);
Context = GetContextSuspended();
if(!Context) return;
if (filter && alIsFilter(filter))
Device = Context->Device;
if(LookupFilter(Device->FilterMap, filter) != NULL)
{
switch(param)
{
case AL_LOWPASS_GAIN:
case AL_LOWPASS_GAINHF:
alGetFilterf(filter, param, pflValues);
break;
default:
alSetError(AL_INVALID_ENUM);
alGetFilterf(filter, param, pflValues);
break;
}
}
else
alSetError(AL_INVALID_NAME);
alSetError(Context, AL_INVALID_NAME);
ProcessContext(Context);
}
ALvoid ReleaseALFilters(ALvoid)
ALvoid ReleaseALFilters(ALCdevice *device)
{
#ifdef _DEBUG
if(g_FilterCount > 0)
AL_PRINT("exit() %d Filter(s) NOT deleted\n", g_FilterCount);
#endif
while(g_FilterList)
ALsizei i;
for(i = 0;i < device->FilterMap.size;i++)
{
ALfilter *temp = g_FilterList;
g_FilterList = g_FilterList->next;
ALfilter *temp = device->FilterMap.array[i].value;
device->FilterMap.array[i].value = NULL;
// Release filter structure
ALTHUNK_REMOVEENTRY(temp->filter);
memset(temp, 0, sizeof(ALfilter));
free(temp);
}
g_FilterCount = 0;
}
+153 -206
View File
@@ -24,120 +24,123 @@
#include "AL/alc.h"
#include "alError.h"
#include "alListener.h"
#include "alSource.h"
ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
AL_API ALvoid AL_APIENTRY alListenerf(ALenum eParam, ALfloat flValue)
{
ALCcontext *pContext;
ALboolean updateAll = AL_FALSE;
pContext = alcGetCurrentContext();
if (pContext)
pContext = GetContextSuspended();
if(!pContext) return;
switch(eParam)
{
SuspendContext(pContext);
switch (eParam)
{
case AL_GAIN:
if (flValue >= 0.0f)
if(flValue >= 0.0f)
{
pContext->Listener.Gain = flValue;
updateAll = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
alSetError(pContext, AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if (flValue > 0.0f)
if(flValue > 0.0f)
{
pContext->Listener.MetersPerUnit = flValue;
updateAll = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
alSetError(pContext, AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
// Force updating the sources for these parameters, since even head-
// relative sources are affected
if(updateAll)
{
ALsizei pos;
for(pos = 0;pos < pContext->SourceMap.size;pos++)
{
ALsource *source = pContext->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
AL_API ALvoid AL_APIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
{
ALCcontext *pContext;
ALboolean updateWorld = AL_FALSE;
pContext = alcGetCurrentContext();
if (pContext)
pContext = GetContextSuspended();
if(!pContext) return;
switch(eParam)
{
SuspendContext(pContext);
switch(eParam)
{
case AL_POSITION:
pContext->Listener.Position[0] = flValue1;
pContext->Listener.Position[1] = flValue2;
pContext->Listener.Position[2] = flValue3;
updateWorld = AL_TRUE;
break;
case AL_VELOCITY:
pContext->Listener.Velocity[0] = flValue1;
pContext->Listener.Velocity[1] = flValue2;
pContext->Listener.Velocity[2] = flValue3;
updateWorld = AL_TRUE;
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
if(updateWorld)
{
ALsizei pos;
for(pos = 0;pos < pContext->SourceMap.size;pos++)
{
ALsource *source = pContext->SourceMap.array[pos].value;
if(!source->bHeadRelative)
source->NeedsUpdate = AL_TRUE;
}
}
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
{
ALCcontext *pContext;
ALboolean updateWorld = AL_FALSE;
pContext = alcGetCurrentContext();
if (pContext)
pContext = GetContextSuspended();
if(!pContext) return;
if(pflValues)
{
SuspendContext(pContext);
if (pflValues)
switch(eParam)
{
switch (eParam)
{
case AL_GAIN:
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)
pContext->Listener.MetersPerUnit = pflValues[0];
else
alSetError(AL_INVALID_VALUE);
alListenerf(eParam, pflValues[0]);
break;
case AL_POSITION:
pContext->Listener.Position[0] = pflValues[0];
pContext->Listener.Position[1] = pflValues[1];
pContext->Listener.Position[2] = pflValues[2];
break;
case AL_VELOCITY:
pContext->Listener.Velocity[0] = pflValues[0];
pContext->Listener.Velocity[1] = pflValues[1];
pContext->Listener.Velocity[2] = pflValues[2];
alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]);
break;
case AL_ORIENTATION:
@@ -148,96 +151,87 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
pContext->Listener.Up[0] = pflValues[3];
pContext->Listener.Up[1] = pflValues[4];
pContext->Listener.Up[2] = pflValues[5];
updateWorld = AL_TRUE;
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
if(updateWorld)
{
ALsizei pos;
for(pos = 0;pos < pContext->SourceMap.size;pos++)
{
ALsource *source = pContext->SourceMap.array[pos].value;
if(!source->bHeadRelative)
source->NeedsUpdate = AL_TRUE;
}
}
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alListeneri(ALenum eParam, ALint lValue)
AL_API ALvoid AL_APIENTRY alListeneri(ALenum eParam, ALint lValue)
{
ALCcontext *pContext;
(void)lValue;
pContext = alcGetCurrentContext();
if (pContext)
pContext = GetContextSuspended();
if(!pContext) return;
switch(eParam)
{
SuspendContext(pContext);
switch (eParam)
{
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
ALAPI void ALAPIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
AL_API void AL_APIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
{
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);
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
return;
ProcessContext(pContext);
}
ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
AL_API void AL_APIENTRY 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];
@@ -257,35 +251,28 @@ ALAPI void ALAPIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
AL_API ALvoid AL_APIENTRY 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;
@@ -295,35 +282,28 @@ ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
{
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];
@@ -337,35 +317,28 @@ ALAPI ALvoid ALAPIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALflo
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY 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;
@@ -397,65 +370,51 @@ ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
AL_API ALvoid AL_APIENTRY 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);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
AL_API void AL_APIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
{
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];
@@ -469,35 +428,28 @@ ALAPI void ALAPIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plV
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
AL_API void AL_APIENTRY 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];
@@ -521,17 +473,12 @@ ALAPI void ALAPIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
break;
default:
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
}
else
alSetError(AL_INVALID_OPERATION);
alSetError(pContext, AL_INVALID_VALUE);
return;
ProcessContext(pContext);
}
+1220 -1458
View File
File diff suppressed because it is too large Load Diff
+365 -383
View File
@@ -23,11 +23,14 @@
#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";
static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
static const ALchar alRenderer[] = "OpenAL Soft";
// Error Messages
@@ -38,481 +41,443 @@ static const ALchar alErrInvalidValue[] = "Invalid Value";
static const ALchar alErrInvalidOp[] = "Invalid Operation";
static const ALchar alErrOutOfMemory[] = "Out of Memory";
ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
switch(capability)
{
SuspendContext(Context);
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_TRUE;
updateSources = AL_TRUE;
break;
switch (capability)
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
if(updateSources)
{
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
default:
alSetError(AL_INVALID_ENUM);
break;
ALsource *source = Context->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
}
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
switch(capability)
{
SuspendContext(Context);
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_FALSE;
updateSources = AL_TRUE;
break;
switch (capability)
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
if(updateSources)
{
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
default:
alSetError(AL_INVALID_ENUM);
break;
ALsource *source = Context->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
}
ProcessContext(Context);
}
ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
AL_API ALboolean AL_APIENTRY 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);
case AL_SOURCE_DISTANCE_MODEL:
value = Context->SourceDistanceModel;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
ALAPI ALboolean ALAPIENTRY alGetBoolean(ALenum pname)
AL_API ALboolean AL_APIENTRY 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(Context, AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
ALAPI ALdouble ALAPIENTRY alGetDouble(ALenum pname)
AL_API ALdouble AL_APIENTRY 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(Context, AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
ALAPI ALfloat ALAPIENTRY alGetFloat(ALenum pname)
AL_API ALfloat AL_APIENTRY 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(Context, AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
ALAPI ALint ALAPIENTRY alGetInteger(ALenum pname)
AL_API ALint AL_APIENTRY 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(Context, AL_INVALID_ENUM);
break;
}
ProcessContext(Context);
return value;
}
ALAPI ALvoid ALAPIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
AL_API ALvoid AL_APIENTRY 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(Context, 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(Context, AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetDoublev(ALenum pname,ALdouble *data)
AL_API ALvoid AL_APIENTRY 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(Context, 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(Context, AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetFloatv(ALenum pname,ALfloat *data)
AL_API ALvoid AL_APIENTRY 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(Context, 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(Context, AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alGetIntegerv(ALenum pname,ALint *data)
AL_API ALvoid AL_APIENTRY 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(Context, 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(Context, AL_INVALID_VALUE);
}
return;
ProcessContext(Context);
}
ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
AL_API const ALchar* AL_APIENTRY 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)
{
@@ -558,7 +523,7 @@ ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
default:
value=NULL;
alSetError(AL_INVALID_ENUM);
alSetError(pContext, AL_INVALID_ENUM);
break;
}
@@ -567,113 +532,130 @@ ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
return value;
}
ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(value >= 0.0f)
{
SuspendContext(Context);
if (value>=0.0f)
Context->DopplerFactor = value;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
Context->DopplerFactor = value;
updateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
// Force updating the sources for these parameters, since even head-
// relative sources are affected
if(updateSources)
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
ALsource *source = Context->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context=alcGetCurrentContext();
if (Context)
Context = GetContextSuspended();
if(!Context) return;
if(value > 0.0f)
{
SuspendContext(Context);
if (value>0.0f)
Context->DopplerVelocity=value;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
Context->DopplerVelocity=value;
updateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
if(updateSources)
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
ALsource *source = Context->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
return;
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
{
ALCcontext *pContext;
ALboolean updateSources = AL_FALSE;
pContext = alcGetCurrentContext();
if (pContext)
pContext = GetContextSuspended();
if(!pContext) return;
if(flSpeedOfSound > 0.0f)
{
SuspendContext(pContext);
if (flSpeedOfSound > 0.0f)
pContext->flSpeedOfSound = flSpeedOfSound;
else
alSetError(AL_INVALID_VALUE);
ProcessContext(pContext);
pContext->flSpeedOfSound = flSpeedOfSound;
updateSources = AL_TRUE;
}
else
alSetError(pContext, AL_INVALID_VALUE);
if(updateSources)
{
alSetError(AL_INVALID_OPERATION);
ALsizei pos;
for(pos = 0;pos < pContext->SourceMap.size;pos++)
{
ALsource *source = pContext->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
}
return;
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
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;
updateSources = !Context->SourceDistanceModel;
break;
switch (value)
default:
alSetError(Context, AL_INVALID_VALUE);
break;
}
if(updateSources)
{
ALsizei pos;
for(pos = 0;pos < Context->SourceMap.size;pos++)
{
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;
break;
default:
alSetError(AL_INVALID_VALUE);
break;
ALsource *source = Context->SourceMap.array[pos].value;
source->NeedsUpdate = AL_TRUE;
}
ProcessContext(Context);
}
else
{
// Invalid Context
alSetError(AL_INVALID_OPERATION);
}
return;
ProcessContext(Context);
}
+1
View File
@@ -70,6 +70,7 @@ ALuint alThunkAddEntry(ALvoid *ptr)
if(!NewList)
{
LeaveCriticalSection(&g_ThunkLock);
AL_PRINT("Realloc failed to increase to %u enties!\n", g_ThunkArraySize*2);
return 0;
}
memset(&NewList[g_ThunkArraySize], 0, g_ThunkArraySize*sizeof(ThunkEntry));
+53
View File
@@ -0,0 +1,53 @@
Source Install
==============
To install OpenAL Soft, use your favorite shell to go into the build/
directory, and run:
cmake ..
Assuming configuration went well, you can then build it, typically using GNU
Make (KDevelop, MSVC, and others are possible depending on your system setup
and CMake configuration).
Please Note: Double check that the appropriate backends were detected. Often,
complaints of no sound, crashing, and missing devices can be solved by making
sure the correct backends are being used. CMake's output will identify which
backends were enabled.
For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
were detected (if your target system uses them). For Windows, make sure
DirectSound was detected.
Utilities
=========
The source package comes with an informational utility, openal-info, and is
built by default. It prints out information provided by the ALC and AL sub-
systems, including discovered devices, version information, and extensions.
Configuration
=============
OpenAL Soft can be configured on a per-user and per-system basis. This allows
users and sysadmins to control information provided to applications, as well
as application-agnostic behavior of the library. See alsoftrc.sample for
available settings.
Acknowledgements
================
Special thanks go to:
Creative Labs for the original source code this is based off of.
Christopher Fitzgerald for the current reverb effect implementation, and
helping with the low-pass filter.
Christian Borss for the 3D panning code the current implementation is heavilly
based on.
Ben Davis for the idea behind the current click-removal code.
+23
View File
@@ -0,0 +1,23 @@
# 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 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
# file.
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)
# which compilers to use for C and C++
SET(CMAKE_C_COMPILER mingw32-gcc)
SET(CMAKE_CXX_COMPILER mingw32-g++)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/mingw32/mingw)
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+225 -68
View File
@@ -5,91 +5,248 @@
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
# specific override settings in ~/.alsoftrc.
# For Windows, these settings should go into %AppData%\alsoft.ini
# The environment variable ALSOFT_CONF can be used to specify another config
# override
# 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
## head_dampen:
# Sets the amount of dampening on sounds emanating from behind the listener.
# This is used to simulate the natural occlusion of the head, which is
# typically missing with mono and stereo output, and as such, only works on
# mono and stereo output modes. Valid values range from 0 to 1 (inclusive),
# and higher values provide a stronger effect.
#head_dampen = 0.25
refresh = 8192 # Sets the buffer size, in frames. Default is 8192. Note that
# the actual granularity may or may not be less than this.
## frequency:
# Sets the output frequency.
#frequency = 44100
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
## resampler:
# Selects the resampler used when mixing sources. Valid values are:
# 0 - None (nearest sample, no interpolation)
# 1 - Linear (extrapolates samples using a linear slope between samples)
# 2 - Cubic (extrapolates samples using a Catmull-Rom spline)
# Specifying other values will result in using the default (linear).
#resampler = 1
stereodup = # Sets whether to duplicate stereo sounds on the rear 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
## rt-prio:
# Sets real-time priority for the mixing thread. Not all drivers may use this
# (eg. PortAudio) as they already control the priority of the mixing thread.
# 0 and negative values will disable it. Note that this may constitute a
# security risk since a real-time priority thread can indefinitely block
# normal-priority threads if it fails to wait. As such, the default is
# disabled.
#rt-prio = 0
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,dsound,winmm,wave
## period_size:
# Sets the update period size, in frames. This is the number of frames needed
# for each mixing update.
#period_size = 1024
[alsa] # ALSA backend stuff
device = default # Sets the device name for the default playback device.
# Default is default
## 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
periods = 0 # Sets the number of update buffers for playback. A value of 0
# means auto-select. Default is 0
## 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
capture = default # Sets the device name for the default capture device.
# Default is default
## stereodup:
# Sets whether to duplicate stereo sounds on the rear and side speakers for 4+
# channel output. This provides a "fuller" playback quality for 4+ channel
# output modes, although each individual speaker will have a slight reduction
# in volume to compensate for the extra output speakers. 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. This only has an effect
# when a suitable output format is used (ie. those that contain side and/or
# rear speakers).
#stereodup = true
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.
## scalemix:
# Sets whether to scale the remixed output. When the final mix is written to
# the device, the multi-channel data is remixed so pure-virtual channels (eg.
# front-center on stereo output) are remixed and added to available channels
# (eg. front-left and front-right). Scaling helps ensure that no single source
# will put out more than 100% on a given physical channel. This can cause a
# noticeable reduction in overall volume, however, so it is off by default.
#scalemix = false
[oss] # OSS backend stuff
device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
## drivers:
# Sets the backend driver list order, comma-seperated. Unknown backends and
# duplicated names are ignored. Unlisted backends won't be considered for use
# unless the list is ended with a comma (eg. 'oss,' will list OSS first
# followed by all other available backends, while 'oss' will list OSS only).
# Backends prepended with - won't be available for use (eg. '-oss,' will allow
# all available backends except OSS). An empty list means the default.
#drivers = pulse,alsa,oss,solaris,dsound,winmm,port,null,wave
periods = 4 # Sets the number of update buffers. Default is 4
## 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,modulator
#excludefx =
capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp
## 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
[dsound] # DirectSound backend stuff
# Nothing yet...
## sends:
# Sets the number of auxiliary sends per source. When not specified (default),
# it allows the app to request how many it wants. The maximum value currently
# possible is 4.
#sends =
[winmm] # Windows Multimedia backend stuff
# Nothing yet...
## layout:
# Sets the virtual speaker layout. Values are specified in degrees, where 0 is
# straight in front, negative goes left, and positive goes right. Unspecified
# speakers will remain at their default positions (which are dependant on the
# output format). Available speakers are back-left(bl), side-left(sl), front-
# left(fl), front-center(fc), front-right(fr), side-right(sr), back-right(br),
# and back-center(bc).
#layout =
[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
## layout_*:
# Channel-specific layouts may be specified to override the layout option. The
# same speakers as the layout option are available, and the default settings
# are shown below.
#layout_STEREO = fl=-90, fr=90
#layout_QUAD = fl=-45, fr=45, bl=-135, br=135
#layout_51CHN = fl=-30, fr=30, fc=0, bl=-110, br=110
#layout_61CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180
#layout_71CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150
##
## ALSA backend stuff
##
[alsa]
## device:
# Sets the device name for the default playback device.
#device = default
## capture:
# Sets the device name for the default capture device.
#capture = default
## 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
##
## OSS backend stuff
##
[oss]
## device:
# Sets the device name for OSS output.
#device = /dev/dsp
## capture:
# Sets the device name for OSS capture.
#capture = /dev/dsp
##
## Solaris backend stuff
##
[solaris]
## device:
# Sets the device name for Solaris output.
#device = /dev/audio
##
## DirectSound backend stuff
##
[dsound]
##
## 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
## capture:
# Sets the device index for capture. Negative values will use the default as
# given by PortAudio itself.
#capture = -1
##
## PulseAudio backend stuff
##
[pulse]
## spawn-server:
# Attempts to spawn a PulseAudio server when requesting to open a PulseAudio
# device. Note that some apps may open and probe all enumerated devices on
# startup, causing a server to spawn even if a PulseAudio device is not
# actually selected. Setting autospawn to false in Pulse's client.conf will
# still prevent autospawning even if this is set to true.
#spawn-server = false
##
## 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
+59
View File
@@ -0,0 +1,59 @@
# - Check if the C source code provided in the SOURCE argument compiles.
# CHECK_C_SOURCE_COMPILES(SOURCE VAR)
#
# FLAG - compiler flag to check
# VAR - variable to store whether the source code compiled
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
MACRO(CHECK_C_COMPILER_FLAG FLAG VAR)
IF("${VAR}" MATCHES "^${VAR}$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"${FLAG} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ELSE(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES)
ENDIF(CMAKE_REQUIRED_LIBRARIES)
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES)
ENDIF(CMAKE_REQUIRED_INCLUDES)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
"int main() {return 0;}\n")
MESSAGE(STATUS "Checking if C compiler supports ${FLAG}")
TRY_COMPILE(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_C_COMPILER_FLAG_ADD_LIBRARIES}"
"${CHECK_C_COMPILER_FLAG_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VAR})
SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Success")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
ELSE(${VAR})
MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Failed")
SET(${VAR} "" CACHE INTERNAL "Test ${VAR}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
ENDIF(${VAR})
ENDIF("${VAR}" MATCHES "^${VAR}$")
ENDMACRO(CHECK_C_COMPILER_FLAG)
+38
View File
@@ -0,0 +1,38 @@
#ifdef CHECK_SHARED_FUNCTION_EXISTS
#include <stdlib.h>
#ifndef CALLSTACK
#define CALLSTACK
#endif
#ifdef _WIN32
#ifdef ARGSTACK
char __stdcall CHECK_SHARED_FUNCTION_EXISTS(ARGSTACK);
#else
char __stdcall CHECK_SHARED_FUNCTION_EXISTS(void);
#endif
#else
char CHECK_SHARED_FUNCTION_EXISTS();
#endif
#ifdef __CLASSIC_C__
int main(){
int ac;
char*av[];
#else
int main(int ac, char*av[]){
#endif
CHECK_SHARED_FUNCTION_EXISTS(CALLSTACK);
if(ac > 1000)
{
return *av[0];
}
return 0;
}
#else /* CHECK_SHARED_FUNCTION_EXISTS */
# error "CHECK_SHARED_FUNCTION_EXISTS has to specify the function"
#endif /* CHECK_SHARED_FUNCTION_EXISTS */
+70
View File
@@ -0,0 +1,70 @@
# - Check if the function exists.
# CHECK_LIBRARY_EXISTS (LIBRARY FUNCTION LOCATION VARIABLE)
#
# LIBRARY - the name of the library you are looking for
# FUNCTION - the name of the function
# ARGCOUNT - number of arguments for stdcall functions
# LOCATION - location where the library should be found
# VARIABLE - variable to store the result
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
MACRO(CHECK_SHARED_LIBRARY_EXISTS LIBRARY FUNCTION ARGCOUNT LOCATION VARIABLE)
IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
SET(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION
"-DCHECK_SHARED_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}")
IF(WIN32)
IF(${ARGCOUNT} GREATER 0)
SET(ARGSTACK "void*")
SET(CALLSTACK "NULL")
SET(CURARG 1)
WHILE(${ARGCOUNT} GREATER ${CURARG})
SET(ARGSTACK "${ARGSTACK},void*")
SET(CALLSTACK "${CALLSTACK},NULL")
MATH(EXPR CURARG "${CURARG} + 1")
ENDWHILE(${ARGCOUNT} GREATER ${CURARG})
SET(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION
"-D_WIN32 -DARGSTACK=\"${ARGSTACK}\" -DCALLSTACK=\"${CALLSTACK}\" ${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION}")
ELSE(${ARGCOUNT} GREATER 0)
SET(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION
"-D_WIN32 ${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION}")
ENDIF(${ARGCOUNT} GREATER 0)
ENDIF(WIN32)
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY}")
SET(CHECK_LIBRARY_EXISTS_LIBRARIES ${LIBRARY})
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_LIBRARY_EXISTS_LIBRARIES
${CHECK_LIBRARY_EXISTS_LIBRARIES} ${CMAKE_REQUIRED_LIBRARIES})
ENDIF(CMAKE_REQUIRED_LIBRARIES)
TRY_COMPILE(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/cmake/CheckSharedFunctionExists.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION}
-DLINK_DIRECTORIES:STRING=${LOCATION}
"-DLINK_LIBRARIES:STRING=${CHECK_LIBRARY_EXISTS_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VARIABLE})
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - found")
SET(${VARIABLE} 1 CACHE INTERNAL "Have library ${LIBRARY}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if the function ${FUNCTION} exists in the ${LIBRARY} "
"passed with the following output:\n"
"${OUTPUT}\n\n")
ELSE(${VARIABLE})
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - not found")
SET(${VARIABLE} "" CACHE INTERNAL "Have library ${LIBRARY}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the function ${FUNCTION} exists in the ${LIBRARY} "
"failed with the following output:\n"
"${OUTPUT}\n\n")
ENDIF(${VARIABLE})
ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
ENDMACRO(CHECK_SHARED_LIBRARY_EXISTS)
+45
View File
@@ -1,27 +1,54 @@
#ifndef CONFIG_H
#define CONFIG_H
/* Define to the library version */
#define ALSOFT_VERSION "${LIB_VERSION}"
/* Define if we have the ALSA backend */
#cmakedefine HAVE_ALSA
/* Define if we have the OSS backend */
#cmakedefine HAVE_OSS
/* Define if we have the Solaris backend */
#cmakedefine HAVE_SOLARIS
/* Define if we have the DSound backend */
#cmakedefine HAVE_DSOUND
/* Define if we have the Windows Multimedia backend */
#cmakedefine HAVE_WINMM
/* Define if we have the PortAudio backend */
#cmakedefine HAVE_PORTAUDIO
/* Define if we have the PulseAudio backend */
#cmakedefine HAVE_PULSEAUDIO
/* Define if we have the Wave Writer backend */
#cmakedefine HAVE_WAVE
/* Define if we have dlfcn.h */
#cmakedefine HAVE_DLFCN_H
/* Define if we have the stat function */
#cmakedefine HAVE_STAT
/* Define if we have the powf function */
#cmakedefine HAVE_POWF
/* Define if we have the sqrtf function */
#cmakedefine HAVE_SQRTF
/* Define if we have the acosf function */
#cmakedefine HAVE_ACOSF
/* Define if we have the atanf function */
#cmakedefine HAVE_ATANF
/* Define if we have the fabsf function */
#cmakedefine HAVE_FABSF
/* Define if we have the strtof function */
#cmakedefine HAVE_STRTOF
@@ -46,7 +73,25 @@
/* Define if we have GCC's destructor attribute */
#cmakedefine HAVE_GCC_DESTRUCTOR
/* Define if we have GCC's format attribute */
#cmakedefine HAVE_GCC_FORMAT
/* Define if we have pthread_np.h */
#cmakedefine HAVE_PTHREAD_NP_H
/* Define if we have float.h */
#cmakedefine HAVE_FLOAT_H
/* Define if we have fenv.h */
#cmakedefine HAVE_FENV_H
/* Define if we have fesetround() */
#cmakedefine HAVE_FESETROUND
/* Define if we have _controlfp() */
#cmakedefine HAVE__CONTROLFP
/* Define if we have pthread_setschedparam() */
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
#endif
-171
View File
@@ -1,171 +0,0 @@
/*
* openal-info: Display information about ALC and AL.
*
* Idea based on glxinfo for OpenGL.
* Initial OpenAL version by Erik Hofman <erik@ehofman.com>.
* Further hacked by Sven Panne <sven.panne@aedion.de>.
* More work (clean up) by Chris Robinson <chris.kcat@gmail.com>.
*
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
static const int indentation = 4;
static const int maxmimumWidth = 79;
static void printChar(int c, int *width)
{
putchar(c);
*width = ((c == '\n') ? 0 : ((*width) + 1));
}
static void indent(int *width)
{
int i;
for(i = 0; i < indentation; i++)
printChar(' ', width);
}
static void printExtensions(const char *header, char separator, const char *extensions)
{
int width = 0, start = 0, end = 0;
printf("%s:\n", header);
if(extensions == NULL || extensions[0] == '\0')
return;
indent(&width);
while (1)
{
if(extensions[end] == separator || extensions[end] == '\0')
{
if(width + end - start + 2 > maxmimumWidth)
{
printChar('\n', &width);
indent(&width);
}
while(start < end)
{
printChar(extensions[start], &width);
start++;
}
if(extensions[end] == '\0')
break;
start++;
end++;
if(extensions[end] == '\0')
break;
printChar(',', &width);
printChar(' ', &width);
}
end++;
}
printChar('\n', &width);
}
static void die(const char *kind, const char *description)
{
fprintf(stderr, "%s error %s occured\n", kind, description);
exit(EXIT_FAILURE);
}
static void checkForErrors(void)
{
{
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
ALCenum error = alcGetError(device);
if(error != ALC_NO_ERROR)
die("ALC", (const char*)alcGetString(device, error));
}
{
ALenum error = alGetError();
if(error != AL_NO_ERROR)
die("AL", (const char*)alGetString(error));
}
}
static void printDevices(ALCenum which, const char *kind)
{
const char *s = alcGetString(NULL, which);
checkForErrors();
printf("Available %sdevices:\n", kind);
while(*s != '\0')
{
printf(" %s\n", s);
while(*s++ != '\0')
;
}
}
static void printALCInfo (void)
{
ALCint major, minor;
ALCdevice *device;
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
{
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
printDevices(ALC_ALL_DEVICES_SPECIFIER, "playback ");
else
printDevices(ALC_DEVICE_SPECIFIER, "playback ");
printDevices(ALC_CAPTURE_DEVICE_SPECIFIER, "capture ");
}
else
printf("No device enumeration available\n");
device = alcGetContextsDevice(alcGetCurrentContext());
checkForErrors();
printf("Default device: %s\n",
alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER));
printf("Default capture device: %s\n",
alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
checkForErrors();
printf("ALC version: %d.%d\n", (int)major, (int)minor);
printExtensions("ALC extensions", ' ',
alcGetString(device, ALC_EXTENSIONS));
checkForErrors();
}
static void printALInfo(void)
{
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
printExtensions("OpenAL extensions", ' ', alGetString(AL_EXTENSIONS));
checkForErrors();
}
int main()
{
ALCdevice *device = alcOpenDevice(NULL);
ALCcontext *context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
checkForErrors();
printALCInfo();
printALInfo();
checkForErrors();
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
alcCloseDevice(device);
return EXIT_SUCCESS;
}
+7 -7
View File
@@ -5,16 +5,17 @@
extern "C" {
#endif
#if defined(_WIN32) && !defined(_XBOX)
/* _OPENAL32LIB is deprecated */
#if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB)
#if defined(AL_LIBTYPE_STATIC)
#define AL_API
#elif defined(_WIN32) && !defined(_XBOX)
#if defined(AL_BUILD_LIBRARY)
#define AL_API __declspec(dllexport)
#else
#define AL_API __declspec(dllimport)
#endif
#else
#if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
#define AL_API __attribute__((visibility("default")))
#define AL_API __attribute__((visibility("protected")))
#else
#define AL_API extern
#endif
@@ -53,7 +54,7 @@ typedef char ALboolean;
typedef char ALchar;
/** signed 8-bit 2's complement integer */
typedef char ALbyte;
typedef signed char ALbyte;
/** unsigned 8-bit integer */
typedef unsigned char ALubyte;
@@ -117,8 +118,7 @@ typedef void ALvoid;
#define AL_CONE_OUTER_ANGLE 0x1002
/**
* Specify the pitch to be applied, either at source,
* or on mixer results, at listener.
* Specify the pitch to be applied at source.
* Range: [0.5-2.0]
* Default: 1.0
*/
+6 -10
View File
@@ -5,16 +5,17 @@
extern "C" {
#endif
#if defined(_WIN32) && !defined(_XBOX)
/* _OPENAL32LIB is deprecated */
#if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB)
#if defined(AL_LIBTYPE_STATIC)
#define ALC_API
#elif defined(_WIN32) && !defined(_XBOX)
#if defined(AL_BUILD_LIBRARY)
#define ALC_API __declspec(dllexport)
#else
#define ALC_API __declspec(dllimport)
#endif
#else
#if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
#define ALC_API __attribute__((visibility("default")))
#define ALC_API __attribute__((visibility("protected")))
#else
#define ALC_API extern
#endif
@@ -52,7 +53,7 @@ typedef char ALCboolean;
typedef char ALCchar;
/** signed 8-bit 2's complement integer */
typedef char ALCbyte;
typedef signed char ALCbyte;
/** unsigned 8-bit integer */
typedef unsigned char ALCubyte;
@@ -166,11 +167,6 @@ typedef void ALCvoid;
#define ALC_ATTRIBUTES_SIZE 0x1002
#define ALC_ALL_ATTRIBUTES 0x1003
/**
* ALC_ENUMERATE_ALL_EXT enums
*/
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
/**
* Capture extension
+100 -4
View File
@@ -21,20 +21,57 @@
#ifndef AL_ALEXT_H
#define AL_ALEXT_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef AL_LOKI_IMA_ADPCM_format
#define AL_LOKI_IMA_ADPCM_format 1
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
#endif
#ifndef AL_LOKI_WAVE_format
#define AL_LOKI_WAVE_format 1
#define AL_FORMAT_WAVE_EXT 0x10002
#endif
#ifndef AL_EXT_vorbis
#define AL_EXT_vorbis 1
#define AL_FORMAT_VORBIS_EXT 0x10003
#endif
#ifndef AL_LOKI_quadriphonic
#define AL_LOKI_quadriphonic 1
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
#endif
#ifndef AL_EXT_float32
#define AL_EXT_float32 1
#define AL_FORMAT_MONO_FLOAT32 0x10010
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_LOKI_quadriphonic
#define AL_LOKI_quadriphonic 1
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
#ifndef AL_EXT_double
#define AL_EXT_double 1
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
#endif
#ifndef ALC_LOKI_audio_channel
#define ALC_LOKI_audio_channel 1
#define ALC_CHAN_MAIN_LOKI 0x500001
#define ALC_CHAN_PCM_LOKI 0x500002
#define ALC_CHAN_CD_LOKI 0x500003
#endif
#ifndef ALC_ENUMERATE_ALL_EXT
#define ALC_ENUMERATE_ALL_EXT 1
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
#ifndef AL_EXT_MCFORMATS
@@ -56,12 +93,71 @@ extern "C" {
#define AL_FORMAT_71CHN32 0x1212
#endif
#ifndef AL_EXT_MULAW_MCFORMATS
#define AL_EXT_MULAW_MCFORMATS 1
#define AL_FORMAT_MONO_MULAW 0x10014
#define AL_FORMAT_STEREO_MULAW 0x10015
#define AL_FORMAT_QUAD_MULAW 0x10021
#define AL_FORMAT_REAR_MULAW 0x10022
#define AL_FORMAT_51CHN_MULAW 0x10023
#define AL_FORMAT_61CHN_MULAW 0x10024
#define AL_FORMAT_71CHN_MULAW 0x10025
#endif
#ifndef AL_EXT_IMA4
#define AL_EXT_IMA4 1
#define AL_FORMAT_MONO_IMA4 0x1300
#define AL_FORMAT_STEREO_IMA4 0x1301
#endif
#ifndef AL_EXT_STATIC_BUFFER
#define AL_EXT_STATIC_BUFFER 1
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq);
#endif
#endif
#ifndef ALC_EXT_EFX
#define ALC_EXT_EFX 1
#include "efx.h"
#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 (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context);
typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
#ifdef AL_ALEXT_PROTOTYPES
ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context);
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
#endif
#endif
#ifndef AL_EXT_source_distance_model
#define AL_EXT_source_distance_model 1
#define AL_SOURCE_DISTANCE_MODEL 0x200
#endif
#ifndef AL_SOFT_buffer_sub_data
#define AL_SOFT_buffer_sub_data 1
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
#endif
#endif
#ifndef AL_SOFT_loop_points
#define AL_SOFT_loop_points 1
#define AL_LOOP_POINTS_SOFT 0x2015
#endif
#ifdef __cplusplus
}
#endif
+3
View File
@@ -0,0 +1,3 @@
/* The tokens that would be defined here are already defined in efx.h. This
* empty file is here to provide compatibility with Windows-based projects
* that would include it. */
+758
View File
@@ -0,0 +1,758 @@
#ifndef AL_EFX_H
#define AL_EFX_H
#ifdef __cplusplus
extern "C" {
#endif
#define ALC_EXT_EFX_NAME "ALC_EXT_EFX"
#define ALC_EFX_MAJOR_VERSION 0x20001
#define ALC_EFX_MINOR_VERSION 0x20002
#define ALC_MAX_AUXILIARY_SENDS 0x20003
/* Listener properties. */
#define AL_METERS_PER_UNIT 0x20004
/* Source properties. */
#define AL_DIRECT_FILTER 0x20005
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_AIR_ABSORPTION_FACTOR 0x20007
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
#define AL_CONE_OUTER_GAINHF 0x20009
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
/* Effect properties. */
/* Reverb effect parameters */
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
/* EAX Reverb effect parameters */
#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
/* Chorus effect parameters */
#define AL_CHORUS_WAVEFORM 0x0001
#define AL_CHORUS_PHASE 0x0002
#define AL_CHORUS_RATE 0x0003
#define AL_CHORUS_DEPTH 0x0004
#define AL_CHORUS_FEEDBACK 0x0005
#define AL_CHORUS_DELAY 0x0006
/* Distortion effect parameters */
#define AL_DISTORTION_EDGE 0x0001
#define AL_DISTORTION_GAIN 0x0002
#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003
#define AL_DISTORTION_EQCENTER 0x0004
#define AL_DISTORTION_EQBANDWIDTH 0x0005
/* Echo effect parameters */
#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
/* Flanger effect parameters */
#define AL_FLANGER_WAVEFORM 0x0001
#define AL_FLANGER_PHASE 0x0002
#define AL_FLANGER_RATE 0x0003
#define AL_FLANGER_DEPTH 0x0004
#define AL_FLANGER_FEEDBACK 0x0005
#define AL_FLANGER_DELAY 0x0006
/* Frequency shifter effect parameters */
#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001
#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002
#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003
/* Vocal morpher effect parameters */
#define AL_VOCAL_MORPHER_PHONEMEA 0x0001
#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002
#define AL_VOCAL_MORPHER_PHONEMEB 0x0003
#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004
#define AL_VOCAL_MORPHER_WAVEFORM 0x0005
#define AL_VOCAL_MORPHER_RATE 0x0006
/* Pitchshifter effect parameters */
#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001
#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002
/* Ringmodulator effect parameters */
#define AL_RING_MODULATOR_FREQUENCY 0x0001
#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002
#define AL_RING_MODULATOR_WAVEFORM 0x0003
/* Autowah effect parameters */
#define AL_AUTOWAH_ATTACK_TIME 0x0001
#define AL_AUTOWAH_RELEASE_TIME 0x0002
#define AL_AUTOWAH_RESONANCE 0x0003
#define AL_AUTOWAH_PEAK_GAIN 0x0004
/* Compressor effect parameters */
#define AL_COMPRESSOR_ONOFF 0x0001
/* Equalizer effect parameters */
#define AL_EQUALIZER_LOW_GAIN 0x0001
#define AL_EQUALIZER_LOW_CUTOFF 0x0002
#define AL_EQUALIZER_MID1_GAIN 0x0003
#define AL_EQUALIZER_MID1_CENTER 0x0004
#define AL_EQUALIZER_MID1_WIDTH 0x0005
#define AL_EQUALIZER_MID2_GAIN 0x0006
#define AL_EQUALIZER_MID2_CENTER 0x0007
#define AL_EQUALIZER_MID2_WIDTH 0x0008
#define AL_EQUALIZER_HIGH_GAIN 0x0009
#define AL_EQUALIZER_HIGH_CUTOFF 0x000A
/* Effect type */
#define AL_EFFECT_FIRST_PARAMETER 0x0000
#define AL_EFFECT_LAST_PARAMETER 0x8000
#define AL_EFFECT_TYPE 0x8001
/* Effect types, used with the AL_EFFECT_TYPE property */
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
#define AL_EFFECT_EAXREVERB 0x8000
/* Auxiliary Effect Slot properties. */
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECTSLOT_GAIN 0x0002
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
/* NULL Auxiliary Slot ID to disable a source send. */
#define AL_EFFECTSLOT_NULL 0x0000
/* Filter properties. */
/* Lowpass filter parameters */
#define AL_LOWPASS_GAIN 0x0001
#define AL_LOWPASS_GAINHF 0x0002
/* Highpass filter parameters */
#define AL_HIGHPASS_GAIN 0x0001
#define AL_HIGHPASS_GAINLF 0x0002
/* Bandpass filter parameters */
#define AL_BANDPASS_GAIN 0x0001
#define AL_BANDPASS_GAINLF 0x0002
#define AL_BANDPASS_GAINHF 0x0003
/* Filter type */
#define AL_FILTER_FIRST_PARAMETER 0x0000
#define AL_FILTER_LAST_PARAMETER 0x8000
#define AL_FILTER_TYPE 0x8001
/* Filter types, used with the AL_FILTER_TYPE property */
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
/* Effect object function types. */
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
/* Filter object function types. */
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
/* Auxiliary Effect Slot object function types. */
typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
#ifdef AL_ALEXT_PROTOTYPES
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
#endif
/* Filter ranges and defaults. */
/* Lowpass filter */
#define LOWPASS_MIN_GAIN (0.0f)
#define LOWPASS_MAX_GAIN (1.0f)
#define LOWPASS_DEFAULT_GAIN (1.0f)
#define LOWPASS_MIN_GAINHF (0.0f)
#define LOWPASS_MAX_GAINHF (1.0f)
#define LOWPASS_DEFAULT_GAINHF (1.0f)
/* Highpass filter */
#define HIGHPASS_MIN_GAIN (0.0f)
#define HIGHPASS_MAX_GAIN (1.0f)
#define HIGHPASS_DEFAULT_GAIN (1.0f)
#define HIGHPASS_MIN_GAINLF (0.0f)
#define HIGHPASS_MAX_GAINLF (1.0f)
#define HIGHPASS_DEFAULT_GAINLF (1.0f)
/* Bandpass filter */
#define BANDPASS_MIN_GAIN (0.0f)
#define BANDPASS_MAX_GAIN (1.0f)
#define BANDPASS_DEFAULT_GAIN (1.0f)
#define BANDPASS_MIN_GAINHF (0.0f)
#define BANDPASS_MAX_GAINHF (1.0f)
#define BANDPASS_DEFAULT_GAINHF (1.0f)
#define BANDPASS_MIN_GAINLF (0.0f)
#define BANDPASS_MAX_GAINLF (1.0f)
#define BANDPASS_DEFAULT_GAINLF (1.0f)
/* Effect parameter ranges and defaults. */
/* Standard reverb effect */
#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
/* EAX reverb effect */
#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
/* Chorus effect */
#define AL_CHORUS_WAVEFORM_SINUSOID (0)
#define AL_CHORUS_WAVEFORM_TRIANGLE (1)
#define AL_CHORUS_MIN_WAVEFORM (0)
#define AL_CHORUS_MAX_WAVEFORM (1)
#define AL_CHORUS_DEFAULT_WAVEFORM (1)
#define AL_CHORUS_MIN_PHASE (-180)
#define AL_CHORUS_MAX_PHASE (180)
#define AL_CHORUS_DEFAULT_PHASE (90)
#define AL_CHORUS_MIN_RATE (0.0f)
#define AL_CHORUS_MAX_RATE (10.0f)
#define AL_CHORUS_DEFAULT_RATE (1.1f)
#define AL_CHORUS_MIN_DEPTH (0.0f)
#define AL_CHORUS_MAX_DEPTH (1.0f)
#define AL_CHORUS_DEFAULT_DEPTH (0.1f)
#define AL_CHORUS_MIN_FEEDBACK (-1.0f)
#define AL_CHORUS_MAX_FEEDBACK (1.0f)
#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f)
#define AL_CHORUS_MIN_DELAY (0.0f)
#define AL_CHORUS_MAX_DELAY (0.016f)
#define AL_CHORUS_DEFAULT_DELAY (0.016f)
/* Distortion effect */
#define AL_DISTORTION_MIN_EDGE (0.0f)
#define AL_DISTORTION_MAX_EDGE (1.0f)
#define AL_DISTORTION_DEFAULT_EDGE (0.2f)
#define AL_DISTORTION_MIN_GAIN (0.01f)
#define AL_DISTORTION_MAX_GAIN (1.0f)
#define AL_DISTORTION_DEFAULT_GAIN (0.05f)
#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f)
#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f)
#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f)
#define AL_DISTORTION_MIN_EQCENTER (80.0f)
#define AL_DISTORTION_MAX_EQCENTER (24000.0f)
#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f)
#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f)
#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f)
#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f)
/* Echo effect */
#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)
/* Flanger effect */
#define AL_FLANGER_WAVEFORM_SINUSOID (0)
#define AL_FLANGER_WAVEFORM_TRIANGLE (1)
#define AL_FLANGER_MIN_WAVEFORM (0)
#define AL_FLANGER_MAX_WAVEFORM (1)
#define AL_FLANGER_DEFAULT_WAVEFORM (1)
#define AL_FLANGER_MIN_PHASE (-180)
#define AL_FLANGER_MAX_PHASE (180)
#define AL_FLANGER_DEFAULT_PHASE (0)
#define AL_FLANGER_MIN_RATE (0.0f)
#define AL_FLANGER_MAX_RATE (10.0f)
#define AL_FLANGER_DEFAULT_RATE (0.27f)
#define AL_FLANGER_MIN_DEPTH (0.0f)
#define AL_FLANGER_MAX_DEPTH (1.0f)
#define AL_FLANGER_DEFAULT_DEPTH (1.0f)
#define AL_FLANGER_MIN_FEEDBACK (-1.0f)
#define AL_FLANGER_MAX_FEEDBACK (1.0f)
#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f)
#define AL_FLANGER_MIN_DELAY (0.0f)
#define AL_FLANGER_MAX_DELAY (0.004f)
#define AL_FLANGER_DEFAULT_DELAY (0.002f)
/* Frequency shifter effect */
#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f)
#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f)
#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f)
#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2)
#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0)
#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1)
#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2)
#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0)
#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2)
#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0)
/* Vocal morpher effect */
#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0)
#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0)
#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24)
#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0)
#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0)
#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10)
#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24)
#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24)
#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0)
#define AL_VOCAL_MORPHER_PHONEME_A (0)
#define AL_VOCAL_MORPHER_PHONEME_E (1)
#define AL_VOCAL_MORPHER_PHONEME_I (2)
#define AL_VOCAL_MORPHER_PHONEME_O (3)
#define AL_VOCAL_MORPHER_PHONEME_U (4)
#define AL_VOCAL_MORPHER_PHONEME_AA (5)
#define AL_VOCAL_MORPHER_PHONEME_AE (6)
#define AL_VOCAL_MORPHER_PHONEME_AH (7)
#define AL_VOCAL_MORPHER_PHONEME_AO (8)
#define AL_VOCAL_MORPHER_PHONEME_EH (9)
#define AL_VOCAL_MORPHER_PHONEME_ER (10)
#define AL_VOCAL_MORPHER_PHONEME_IH (11)
#define AL_VOCAL_MORPHER_PHONEME_IY (12)
#define AL_VOCAL_MORPHER_PHONEME_UH (13)
#define AL_VOCAL_MORPHER_PHONEME_UW (14)
#define AL_VOCAL_MORPHER_PHONEME_B (15)
#define AL_VOCAL_MORPHER_PHONEME_D (16)
#define AL_VOCAL_MORPHER_PHONEME_F (17)
#define AL_VOCAL_MORPHER_PHONEME_G (18)
#define AL_VOCAL_MORPHER_PHONEME_J (19)
#define AL_VOCAL_MORPHER_PHONEME_K (20)
#define AL_VOCAL_MORPHER_PHONEME_L (21)
#define AL_VOCAL_MORPHER_PHONEME_M (22)
#define AL_VOCAL_MORPHER_PHONEME_N (23)
#define AL_VOCAL_MORPHER_PHONEME_P (24)
#define AL_VOCAL_MORPHER_PHONEME_R (25)
#define AL_VOCAL_MORPHER_PHONEME_S (26)
#define AL_VOCAL_MORPHER_PHONEME_T (27)
#define AL_VOCAL_MORPHER_PHONEME_V (28)
#define AL_VOCAL_MORPHER_PHONEME_Z (29)
#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0)
#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1)
#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2)
#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0)
#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2)
#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0)
#define AL_VOCAL_MORPHER_MIN_RATE (0.0f)
#define AL_VOCAL_MORPHER_MAX_RATE (10.0f)
#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f)
/* Pitch shifter effect */
#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12)
#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12)
#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12)
#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50)
#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50)
#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0)
/* Ring modulator effect */
#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f)
#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f)
#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f)
#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f)
#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f)
#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f)
#define AL_RING_MODULATOR_SINUSOID (0)
#define AL_RING_MODULATOR_SAWTOOTH (1)
#define AL_RING_MODULATOR_SQUARE (2)
#define AL_RING_MODULATOR_MIN_WAVEFORM (0)
#define AL_RING_MODULATOR_MAX_WAVEFORM (2)
#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0)
/* Autowah effect */
#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f)
#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f)
#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f)
#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f)
#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f)
#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f)
#define AL_AUTOWAH_MIN_RESONANCE (2.0f)
#define AL_AUTOWAH_MAX_RESONANCE (1000.0f)
#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f)
#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f)
#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f)
#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f)
/* Compressor effect */
#define AL_COMPRESSOR_MIN_ONOFF (0)
#define AL_COMPRESSOR_MAX_ONOFF (1)
#define AL_COMPRESSOR_DEFAULT_ONOFF (1)
/* Equalizer effect */
#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f)
#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f)
#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f)
#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f)
#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f)
#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f)
#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f)
#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f)
#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f)
#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f)
#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f)
#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f)
#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f)
#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f)
#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f)
#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f)
#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f)
#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f)
#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f)
#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f)
#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f)
#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f)
#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f)
#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f)
#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f)
#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f)
#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f)
/* Source parameter value ranges and defaults. */
#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f)
#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f)
#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f)
#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
#define AL_MIN_CONE_OUTER_GAINHF (0.0f)
#define AL_MAX_CONE_OUTER_GAINHF (1.0f)
#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f)
#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE
#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE
#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE
#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE
#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE
#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE
/* Listener parameter value ranges and defaults. */
#define AL_MIN_METERS_PER_UNIT FLT_MIN
#define AL_MAX_METERS_PER_UNIT FLT_MAX
#define AL_DEFAULT_METERS_PER_UNIT (1.0f)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* AL_EFX_H */
-483
View File
@@ -1,483 +0,0 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+11
View File
@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenAL
Description: OpenAL is a cross-platform 3D audio API
Requires: @PKG_CONFIG_REQUIRES@
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@
Cflags: -I${includedir} @PKG_CONFIG_CFLAGS@
+332
View File
@@ -0,0 +1,332 @@
/*
* OpenAL Info Utility
*
* Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
#ifndef ALC_ENUMERATE_ALL_EXT
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
#endif
#ifndef ALC_EXT_EFX
#define ALC_EFX_MAJOR_VERSION 0x20001
#define ALC_EFX_MINOR_VERSION 0x20002
#define ALC_MAX_AUXILIARY_SENDS 0x20003
#define AL_FILTER_TYPE 0x8001
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
#define AL_EFFECT_TYPE 0x8001
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_EAXREVERB 0x8000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
#endif
static LPALGENFILTERS palGenFilters;
static LPALDELETEFILTERS palDeleteFilters;
static LPALFILTERI palFilteri;
static LPALGENEFFECTS palGenEffects;
static LPALDELETEEFFECTS palDeleteEffects;
static LPALEFFECTI palEffecti;
#define MAX_WIDTH 80
static void printList(const char *list, char separator)
{
size_t col = MAX_WIDTH, len;
const char *indent = " ";
const char *next;
if(!list || *list == '\0')
{
fprintf(stdout, "\n%s!!! none !!!\n", indent);
return;
}
do {
next = strchr(list, separator);
if(next)
{
len = next-list;
do {
next++;
} while(*next == separator);
}
else
len = strlen(list);
if(len + col + 2 >= MAX_WIDTH)
{
fprintf(stdout, "\n%s", indent);
col = strlen(indent);
}
else
{
fputc(' ', stdout);
col++;
}
len = fwrite(list, 1, len, stdout);
col += len;
if(!next || *next == '\0')
break;
fputc(',', stdout);
col++;
list = next;
} while(1);
fputc('\n', stdout);
}
static void printDeviceList(const char *list)
{
if(!list || *list == '\0')
printf(" !!! none !!!\n");
else do {
printf(" %s\n", list);
list += strlen(list) + 1;
} while(*list != '\0');
}
static ALenum checkALErrors(int linenum)
{
ALenum err = alGetError();
if(err != AL_NO_ERROR)
printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum);
return err;
}
#define checkALErrors() checkALErrors(__LINE__)
static ALCenum checkALCErrors(ALCdevice *device, int linenum)
{
ALCenum err = alcGetError(device);
if(err != ALC_NO_ERROR)
printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum);
return err;
}
#define checkALCErrors(x) checkALCErrors((x),__LINE__)
static void printALCInfo(ALCdevice *device)
{
ALCint major, minor;
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
if(checkALCErrors(device) == ALC_NO_ERROR)
printf("ALC version: %d.%d\n", major, minor);
if(device)
{
printf("ALC extensions:");
printList(alcGetString(device, ALC_EXTENSIONS), ' ');
checkALCErrors(device);
}
}
static void printALInfo(void)
{
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
printf("OpenAL extensions:");
printList(alGetString(AL_EXTENSIONS), ' ');
checkALErrors();
}
static void printEFXInfo(ALCdevice *device)
{
ALCint major, minor, sends;
ALuint obj;
int i;
const ALenum filters[] = {
AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS,
AL_FILTER_NULL
};
char filterNames[] = "Low-pass,High-pass,Band-pass,";
const ALenum effects[] = {
AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS,
AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER,
AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER,
AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH,
AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL
};
char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
"Frequency Shifter,Vocal Morpher,Pitch Shifter,"
"Ring Modulator,Autowah,Compressor,Equalizer,";
char *current;
if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE)
{
printf("EFX not available\n");
return;
}
alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor);
if(checkALCErrors(device) == ALC_NO_ERROR)
printf("EFX version: %d.%d\n", major, minor);
alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends);
if(checkALCErrors(device) == ALC_NO_ERROR)
printf("Max auxiliary sends: %d\n", sends);
palGenFilters = alGetProcAddress("alGenFilters");
palDeleteFilters = alGetProcAddress("alDeleteFilters");
palFilteri = alGetProcAddress("alFilteri");
palGenEffects = alGetProcAddress("alGenEffects");
palDeleteEffects = alGetProcAddress("alDeleteEffects");
palEffecti = alGetProcAddress("alEffecti");
if(checkALErrors() != AL_NO_ERROR ||
!palGenFilters || !palDeleteFilters || !palFilteri ||
!palGenEffects || !palDeleteEffects || !palEffecti)
{
printf("!!! Missing EFX functions !!!\n");
return;
}
palGenFilters(1, &obj);
if(checkALErrors() == AL_NO_ERROR)
{
current = filterNames;
for(i = 0;filters[i] != AL_FILTER_NULL;i++)
{
char *next = strchr(current, ',');
palFilteri(obj, AL_FILTER_TYPE, filters[i]);
if(alGetError() == AL_NO_ERROR)
current = next+1;
else
memmove(current, next+1, strlen(next));
}
palDeleteFilters(1, &obj);
checkALErrors();
printf("Supported filters:");
printList(filterNames, ',');
}
palGenEffects(1, &obj);
if(checkALErrors() == AL_NO_ERROR)
{
current = effectNames;
for(i = 0;effects[i] != AL_EFFECT_NULL;i++)
{
char *next = strchr(current, ',');
palEffecti(obj, AL_EFFECT_TYPE, effects[i]);
if(alGetError() == AL_NO_ERROR)
current = next+1;
else
memmove(current, next+1, strlen(next));
}
palDeleteEffects(1, &obj);
checkALErrors();
printf("Supported effects:");
printList(effectNames, ',');
}
}
int main(int argc, char *argv[])
{
ALCdevice *device;
ALCcontext *context;
if(argc > 1 && (strcmp(argv[1], "--help") == 0 ||
strcmp(argv[1], "-h") == 0))
{
printf("Usage: %s [playback device]\n", argv[0]);
return 0;
}
printf("Available playback devices:\n");
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER));
else
printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
printf("Available capture devices:\n");
printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER));
printf("Default playback device: %s\n",
alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
printf("Default capture device: %s\n",
alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
printALCInfo(NULL);
device = alcOpenDevice((argc>1) ? argv[1] : NULL);
if(!device)
{
printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device"));
return 1;
}
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
printALCInfo(device);
context = alcCreateContext(device, NULL);
if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
{
if(context)
alcDestroyContext(context);
alcCloseDevice(device);
printf("\n!!! Failed to set a context !!!\n\n");
return 1;
}
printALInfo();
printEFXInfo(device);
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
alcCloseDevice(device);
return 0;
}