Compare commits

...

331 Commits

Author SHA1 Message Date
Chris Robinson 9b6a226da5 Release 1.15.1 2012-12-11 12:35:55 -08:00
Chris Robinson eb5073a8a7 Properly convert uint values when getting them as int64 2012-12-07 18:43:13 -08:00
Chris Robinson beb84bdc21 SetSourceiv should never get AL_SAMPLE_OFFSET_LATENCY_SOFT 2012-12-06 09:03:48 -08:00
Chris Robinson a20f1fa779 Use a helper to count the number of float/double values for a property 2012-12-05 20:51:25 -08:00
Chris Robinson 7445ffe1a6 Use a helper to count the number of int(64) values for a property 2012-12-05 19:58:01 -08:00
Chris Robinson c225c59b0a Remove 'v' from the source enum names 2012-12-05 18:27:05 -08:00
Chris Robinson 37a6705556 Add a comment to note the extension for sfvDistanceModel 2012-12-05 13:48:33 -08:00
Chris Robinson ed5738bfa4 Use an enum to handle int source properties 2012-12-05 09:55:05 -08:00
Chris Robinson 5e14a83030 Use an enum to handle float source properties 2012-12-05 09:22:38 -08:00
Chris Robinson 3b9b176f14 Print an error if trying to handle a missed source property 2012-12-05 08:29:38 -08:00
Chris Robinson 838f0fd71b Fix retrieving source gain 2012-12-05 08:27:02 -08:00
Chris Robinson fd83e006ec Release 1.15 2012-12-04 13:49:16 -08:00
Chris Robinson e51574c764 Trace the list of supported backends 2012-12-04 13:46:51 -08:00
Chris Robinson 893a1bedbc Use +/-90 degrees for stereo sources with non-HRTF stereo output. 2012-12-04 05:30:06 -08:00
Chris Robinson 4621a7b426 Add support for float32 output to CoreAudio 2012-12-03 11:50:02 -08:00
Chris Robinson 4808313e70 Use the correct multiplier for int32 output with CoreAudio 2012-12-03 10:44:02 -08:00
Chris Robinson 1fb9311d82 Lock the device before calling aluHandleDisconnect
PulseAudio causes an assert if being relocked inside a callback on the worker
thread, where aluHandleDisconnect is called. We can assume it's already locked
there, so just make sure the device is locked before being calling it.
2012-12-02 11:30:23 -08:00
Chris Robinson dd34daed42 Trace the opened device name in alcCaptureOpenDevice 2012-12-02 06:37:34 -08:00
Chris Robinson 830428fb06 Use WARN when implicitly deleting resources with the context 2012-12-02 01:17:26 -08:00
Chris Robinson 0ca7ab2cf8 Explicitly check for malloc.h 2012-11-25 19:20:35 -08:00
Chris Robinson a0c39989f5 malloc.h isn't standard, and is only needed for _aligned_malloc 2012-11-25 02:33:20 -08:00
Chris Robinson 209d09ae13 Avoid locking PulseAudio's mainloop when starting and stopping capture
The mainloop is already locked by the caller, and double-locking interferes
with the subsequent wait.
2012-11-19 16:50:03 -08:00
Chris Robinson 0c030f7d9c Fix a comment describing the sinc function 2012-11-18 19:02:50 -08:00
Chris Robinson 2d800e99e2 Fix off-by-one error in the makehrtf dither and add a resample option
Also fixes some size_t type warnings
2012-11-18 09:29:58 -08:00
Chris Robinson 0518ecca14 Avoid storing the SSE state if it's not supported 2012-11-13 15:20:36 -08:00
Chris Robinson 43b9027611 Return the integer from fastf2i with MSVC 2012-11-13 15:12:46 -08:00
Chris Robinson 40ea4f4b46 Use int instead of long for the IMA4 tables 2012-11-10 03:40:36 -08:00
Chris Robinson 4f624cb734 Load Int and UInt samples as float with alBufferData
This shouldn't really ever happen, as there's no 32-bit (u)int formats
alBufferData can take.
2012-11-10 03:36:37 -08:00
Chris Robinson b03013d6a7 Specify that the config file being installed is a sample 2012-11-06 03:52:41 -08:00
Chris Robinson 9e79d144de Install the config sample by default 2012-11-05 04:20:15 -08:00
Chris Robinson 40b3f60cde Install the config example into share/openal instead of /etc/openal
/etc/openal/alsoft.conf is still used for configuration, only the sample's
install placement is changed.
2012-11-05 04:14:05 -08:00
Chris Robinson 2b27d243ca Use stdout to print alstream information 2012-11-04 22:37:10 -08:00
Chris Robinson 2f07c46e20 Include standard headers before conditional ones 2012-11-04 22:36:34 -08:00
Chris Robinson 3da1b540fd Use the stored buffer metrics for the mmdevapi buffer size 2012-11-04 22:35:35 -08:00
Chris Robinson 92dde81296 Add rudimentary latency tracking for mmdevapi
This won't be as granular as it could be, since it only updates when the wakeup
event trips (which may or may not happen more often than OpenAL's mix updates).
A more correct method would be to query GetCurrentPadding directly, but that
would require sending a message to the processing thread and waiting for a
reply, since we can't guarantee COM on the calling thread.
2012-11-04 08:35:39 -08:00
Chris Robinson e2368eb960 Use an array to specify the offset for each channel of the device buffer
This effectively inverts the DevChannels array
2012-11-04 04:41:11 -08:00
Chris Robinson 3e71a7cb94 Rename some struct fields for DirectSound 2012-11-04 01:18:39 -08:00
Chris Robinson b92ad830ef Avoid recreating the DSound primary buffer 2012-11-04 00:37:31 -07:00
Chris Robinson fc7adccd6f Fix retrieving the source's write offset 2012-11-01 23:41:18 -07:00
Chris Robinson 97bf718d0e Pass the offset latency properties to the set handler 2012-11-01 18:35:20 -07:00
Chris Robinson eb6360e1f8 Set the proper error when trying to set AL_SAMPLE_OFFSET_LATENCY_SOFT or AL_SEC_OFFSET_LATENCY_SOFT 2012-11-01 00:16:44 -07:00
Chris Robinson 41b1ba146a Add an example to get and show the source latency 2012-10-31 23:53:10 -07:00
Chris Robinson 6450d0cbca Avoid prefixing function pointers in the streaming example 2012-10-31 22:38:27 -07:00
Chris Robinson 4e281350a0 Print the name of the device when opening it in the example apps 2012-10-31 17:16:56 -07:00
Chris Robinson e868dad61c Make a decimal value a float type 2012-10-31 06:58:16 -07:00
Chris Robinson 4a3d36a176 Finalize AL_SOFT_source_latency 2012-10-31 05:09:42 -07:00
Chris Robinson f3dddb6e63 Add an example program showing how to apply reverb to a source 2012-10-31 04:04:49 -07:00
Chris Robinson 3c3e3b123b Add a couple comments to the code 2012-10-26 20:11:59 -07:00
Chris Robinson f02a9935c6 Avoid branching when clamping and converting float samples to integer 2012-10-26 15:31:14 -07:00
Chris Robinson 3711735ed9 Add the AL subdir to the list of include flags in the pkg-config file
This allows apps to include "al.h", "alc.h", etc, like with Creative's SDK and
CMake's FindOpenAL module, or as "AL/al.h" and "AL/alc.h" like before.
2012-10-26 00:02:39 -07:00
Chris Robinson 2c802cc10a Reorder and comment some function in alhelpers.c 2012-10-25 23:53:46 -07:00
Chris Robinson e2e502970c Move some math functions to where they're used 2012-10-25 17:24:22 -07:00
Chris Robinson 404d601666 Add a couple missing RESTRICTs 2012-10-25 17:02:21 -07:00
Chris Robinson 252fc40f78 Fix some types 2012-10-25 15:37:52 -07:00
Chris Robinson fb21a73b4e Add the RESTRICT keyword to a function pointer definition's parameters 2012-10-25 14:52:09 -07:00
Chris Robinson 138a4c6d92 Add explicit casts for MSVC 2012-10-25 14:46:27 -07:00
Chris Robinson c802bfccef Remove the float math wrapper functions 2012-10-25 14:16:35 -07:00
Chris Robinson fae4959db3 Add retrieval of missing source properties 2012-10-21 11:36:27 -07:00
Chris Robinson 8a67e5cfa2 Use an asterisk to denote a requested format option in the trace 2012-10-16 07:46:04 -07:00
Chris Robinson 617def3ef0 Require an alignment declaration for SSE support 2012-10-15 02:23:08 -07:00
Chris Robinson 4f5aafe59f Put the HRTF DirectParams into an anonymous struct 2012-10-15 01:37:37 -07:00
Chris Robinson a14383d6cc Constify the direct and send parameters given to the mixer 2012-10-15 01:31:58 -07:00
Chris Robinson fe1903fb56 Use a separate step to deinterlace reverb samples 2012-10-14 11:55:03 -07:00
Chris Robinson f0d27e5f91 Remove the unused Device parameter 2012-10-14 11:29:28 -07:00
Chris Robinson a852669dce Store the output buffers in the DirectParams struct 2012-10-14 11:21:52 -07:00
Chris Robinson 3240894cd5 Remove the now-unused Source parameter from the DryMix methods 2012-10-14 11:04:36 -07:00
Chris Robinson 0b679167c9 Store some more HRTF info in the DirectParams struct 2012-10-14 10:57:11 -07:00
Chris Robinson 5ac0a93fba Mark some parameters as const and/or RESTRICT 2012-10-14 10:27:15 -07:00
Chris Robinson f7655d44a2 Move alhelpers and alffmpeg code to a common sub-directory 2012-10-14 01:55:39 -07:00
Chris Robinson 38e6bfb702 Use a helper method to convert i64 values to the proper types 2012-10-14 01:41:49 -07:00
Chris Robinson 20ede6de59 Check i64 property ranges before passing them to the int handlers
Note that some properties (e.g. AL_BUFFER, AL_DIRECT_FILTER) actually take
unsigned int values, and so are checked against the unsigned range even though
they eventually get casted to an int. The int handler casts them back as
needed.
2012-10-14 00:55:46 -07:00
Chris Robinson 5c70e6b9ab Don't add the dry gain to the mixing matrix 2012-10-13 11:10:58 -07:00
Chris Robinson 9bd3b88a58 Silence an implicit int-to-float conversion warning on MSVC 2012-10-13 11:00:43 -07:00
Chris Robinson e60281c927 Don't use a loop to determine the next power of 2 2012-10-13 08:58:48 -07:00
Chris Robinson 01136ecd51 List the in-progress AL_SOFT_source_latency extension 2012-10-13 00:59:46 -07:00
Chris Robinson 1212523470 Implement the double and int64 source setters
Note that currently the int64 setters do not range check before being passed to
the int setters, erroneously chopping off the upper bits.
2012-10-13 00:56:39 -07:00
Chris Robinson 73105b2d4b Fix copying the listener Up vector 2012-10-12 23:35:00 -07:00
Chris Robinson 06ab9cf70e Use the enum to set the default distance model 2012-10-12 23:28:51 -07:00
Chris Robinson a3d4868ef4 Initialize the listener velocity parameter 2012-10-12 08:01:02 -07:00
Chris Robinson 815b03855b Apply the listener matrix to the listener velocity once 2012-10-12 07:56:37 -07:00
Chris Robinson 6750bbb1d7 Avoid needlessly copying the listener matrix 2012-10-12 07:45:20 -07:00
Chris Robinson 43c8c4fa29 Apply the listener position to the transformation matrix 2012-10-12 07:38:29 -07:00
Chris Robinson 25b8a95987 Check the distance against epsilon to determine if it matches 2012-10-12 07:10:51 -07:00
Chris Robinson 99fcd6f816 Properly scale wide-stereo sources 2012-10-10 04:08:35 -07:00
Chris Robinson 513c6db0d5 Avoid mixing to a send slot if the gain is too low 2012-10-10 03:52:45 -07:00
Chris Robinson 1b7f01b7cc The max step is no longer dependent on the channel count 2012-10-10 03:40:01 -07:00
Chris Robinson a4f21aaa64 Set Hrtf.Moving after setting the source params instead of after mixing 2012-10-09 06:54:21 -07:00
Chris Robinson 39bc2ba65c Build the listener matrix separately 2012-10-09 06:19:36 -07:00
Chris Robinson d598f82722 Don't include alListener.h from alMain.h 2012-10-09 04:48:12 -07:00
Chris Robinson c22408cb2a Store a pointer to the listener in the context 2012-10-09 04:44:27 -07:00
Chris Robinson 8c3419ed48 Define RESTRICT in config.h instead of alMain.h 2012-10-09 01:46:02 -07:00
Chris Robinson a98361ebbe Don't assume x86 or x64 to use IsProcessorFeaturePresent 2012-10-08 00:43:51 -07:00
Chris Robinson 999f0783c5 Fix a type conversion warning 2012-10-08 00:32:35 -07:00
Chris Robinson 2a6dd2f243 Fix a type mismatch 2012-10-07 08:19:09 -07:00
Chris Robinson f3349221c6 Add missing include 2012-10-07 08:18:53 -07:00
Chris Robinson 65c7c468cc Use IsProcessorFeaturePresent to detect SSE on Windows 2012-10-07 08:18:22 -07:00
Chris Robinson ebdf636759 Revert "Use __cpuid from intrin.h in Windows when available"
This reverts commit 6b870714a9.
2012-10-07 08:08:11 -07:00
Chris Robinson 6b870714a9 Use __cpuid from intrin.h in Windows when available 2012-10-07 05:36:25 -07:00
Chris Robinson 708f3ccc3d Add trace, warn, and error markers to logged output 2012-10-07 04:31:31 -07:00
Chris Robinson 84f4afa5f2 Lock the device using the pulseaudio main loop 2012-10-07 02:25:59 -07:00
Chris Robinson 991e21a712 Avoid unnecessarily locking the list lock 2012-10-07 00:13:23 -07:00
Chris Robinson 1a9cf7ab80 Shorten format trace messages 2012-10-06 23:32:36 -07:00
Chris Robinson 9501f1cb9e Define WIN32_LEAN_AND_MEAN when including windows.h in alMain.h 2012-10-06 21:36:15 -07:00
Chris Robinson d52cb3708b Include windows.h before cpuid.h to avoid __cpuid clashes 2012-10-06 21:30:03 -07:00
Chris Robinson fa8d374613 Rename a couple functions
Since they don't use the stack anymore.
2012-10-05 06:44:55 -07:00
Chris Robinson 0d26b0dcc2 Put temporary storage in the device instead of on the stack 2012-10-05 06:42:26 -07:00
Chris Robinson a6287fd407 Add a special resampler for matching sample rates 2012-10-05 06:03:19 -07:00
Chris Robinson 16bdf79d4c Round up the device's default slot alignment 2012-10-05 00:32:41 -07:00
Chris Robinson 0b47844606 Fix potential buffer overflow with temp sample space 2012-10-05 00:27:29 -07:00
Chris Robinson 468759e6ab Scale and round NumUpdates when PulseAudio changes the sample rate 2012-10-04 23:36:59 -07:00
Chris Robinson f138774d78 Avoid void* arithmetic 2012-10-04 06:16:16 -07:00
Chris Robinson 068da3fe83 Make sure the output buffer pointer is updated in case multiple iterations are needed 2012-10-03 02:35:43 -07:00
Chris Robinson 29b11db13f Update the example to use avcodec_decode_audio4 2012-10-03 02:01:52 -07:00
Chris Robinson dca6254b35 Update some ffmpeg functions 2012-10-03 00:29:08 -07:00
Chris Robinson cccec40e87 Fix some signed/unsigned comparisons 2012-10-02 18:55:39 -07:00
Chris Robinson b5d9d8e005 Reset maxlength if PulseAudio updates the playback rate 2012-10-02 17:01:35 -07:00
Chris Robinson 825c5b5282 Use lrintf to fast convert floats to ints when possible 2012-09-28 04:20:55 -07:00
Chris Robinson 25ca179389 Decrease the default BUFFERSIZE to 2048 2012-09-28 03:30:57 -07:00
Chris Robinson 8bd0592e3f Combine early reflections and late reverb in VerbPass 2012-09-27 17:30:35 -07:00
Chris Robinson 06a0d1b86e Use an unsigned type for the sample position fraction 2012-09-27 13:52:45 -07:00
Chris Robinson 41b2c2f3bb Remove an unneeded parameter from the resampler 2012-09-27 02:46:15 -07:00
Chris Robinson 68faef5b84 Ensure the device's default effect slot is properly aligned 2012-09-26 18:21:03 -07:00
Chris Robinson abf1309fb6 Update a comment 2012-09-26 18:04:22 -07:00
Chris Robinson d3891af36e Ensure effect slots are aligned 2012-09-26 18:00:38 -07:00
Chris Robinson ed82194260 Deinterlace audio when loading it into the stack.
It may be better to deinterlace it on load into the buffer, though I don't
imagine this will affect much. It could be nice for consistency's sake, though
it would also complicate things if we ever want to support direct access to
buffer data.
2012-09-26 17:16:25 -07:00
Chris Robinson 012e61b105 Round when calculating NumUpdates from PulseAudio's minreq 2012-09-25 11:32:49 -07:00
Chris Robinson d19d7321d9 Remove an unnecessary include 2012-09-24 20:39:12 -07:00
Chris Robinson d4e82d441e Combine multiple loops into one 2012-09-24 19:07:07 -07:00
Chris Robinson 2ceea21f76 Avoid mixing silence to output
"Silence" being less than -100dB.
2012-09-24 15:33:44 -07:00
Chris Robinson 12327da4fe Remove SSE resamplers. They aren't gaining us much this way. 2012-09-24 14:47:06 -07:00
Chris Robinson 52d403b0d1 Make sure PulseAudio sets an update size that's a multiple of 4 samples with SSE 2012-09-20 15:01:49 -07:00
Chris Robinson ccd35bffe7 Help ensure the update size is a multiple of 4 with SSE 2012-09-20 14:54:28 -07:00
Chris Robinson d1c93525ed Fix matrix multiply used by the SSE cubic resampler
Also remove the 4-sample loop. It's not terribly effective.
2012-09-18 18:09:43 -07:00
Chris Robinson f0732426f2 Precision control bits don't exist with SSE 2012-09-18 15:08:36 -07:00
Chris Robinson eedbd1e81c Improve a couple error traces with the HRTF loader 2012-09-18 12:15:43 -07:00
Chris Robinson 6005e7f27f fpu_control.h is no longer used 2012-09-18 11:28:47 -07:00
Chris Robinson e779e64c95 Win64 doesn't allow _controlfp or __control87_2 to set the precision control bits 2012-09-18 11:20:48 -07:00
Chris Robinson 3baaf99a6e Fix a typo in a comment 2012-09-17 07:48:57 -07:00
Chris Robinson 4a86983a6f Avoid correcting for more non-existing clicks 2012-09-16 09:04:37 -07:00
Chris Robinson c19d9d3452 Don't try to correct for non-existing clicks. 2012-09-16 08:42:36 -07:00
Chris Robinson 79b6d89b3f Explicitly give the wet buffer 1 channel 2012-09-16 08:27:50 -07:00
Chris Robinson 535e8fd0f7 Check the proper value for setting WetPendingClicks 2012-09-16 08:15:03 -07:00
Chris Robinson a240abb6c8 Avoid building redundant mixers 2012-09-16 08:14:26 -07:00
Chris Robinson dd9d30e248 Implement an SSE MixSend method 2012-09-16 06:19:39 -07:00
Chris Robinson 95535ce99e Properly restore the SSE control word with __control87_2 2012-09-16 06:01:48 -07:00
Chris Robinson df2e82da78 Properly handle the SSE control word 2012-09-16 05:35:38 -07:00
Chris Robinson a1daec66e2 Use __control87_2 when available 2012-09-16 01:44:45 -07:00
Chris Robinson 657ee85136 Use a struct to store the FPU mode 2012-09-16 01:35:16 -07:00
Chris Robinson 965306b296 Add missing source property retrievals 2012-09-14 09:02:36 -07:00
Chris Robinson 28086f6cb7 Implement an SSE cubic resampler 2012-09-14 07:01:58 -07:00
Chris Robinson 45bb010b28 Shorten a warning 2012-09-14 05:05:20 -07:00
Chris Robinson 90e0c74721 Implement an SSE linear resampler 2012-09-14 04:48:53 -07:00
Chris Robinson a20341ac2a Ensure the ResampledBuffer is aligned 2012-09-14 04:16:49 -07:00
Chris Robinson 7635afcb52 Use a source param for the resampler and move them to the mixer source 2012-09-14 04:13:18 -07:00
Chris Robinson 74aee374a6 Remove an unused header 2012-09-14 03:10:12 -07:00
Chris Robinson 4f70766b95 Move a couple macros to more appropriate headers 2012-09-14 02:52:37 -07:00
Chris Robinson 9f58edd7a8 Fix up some more header includes 2012-09-14 02:42:36 -07:00
Chris Robinson 0f3a575a09 Don't include alu.h in alMain.h 2012-09-14 02:14:29 -07:00
Chris Robinson ec74fb9ba2 Enable flush-to-zero mode when possible 2012-09-14 01:10:19 -07:00
Chris Robinson ff809f2271 Move a couple methods to where they're used 2012-09-12 07:57:50 -07:00
Chris Robinson 41f52fdd6a Restore support for the previous mhr format 2012-09-12 07:25:05 -07:00
Chris Robinson aa827790bd Add a note about the hrtf_tables filename markers 2012-09-12 05:34:42 -07:00
Chris Robinson 38e7bd5359 Properly scale the HRTF delays when writing them 2012-09-12 05:11:53 -07:00
Chris Robinson 613ce3f976 Update fnamelist after handling % markers 2012-09-12 04:55:03 -07:00
Chris Robinson ce8a0a9fd5 Use PATH_MAX for the fname length 2012-09-12 03:45:26 -07:00
Chris Robinson f59e4ba7c2 Improve parsing hrtf_tables filenames 2012-09-12 03:41:41 -07:00
Chris Robinson df469bfdea Fix HRTF data format description 2012-09-11 19:55:45 -07:00
Chris Robinson f4642953d4 Warn about SSE performance with non-multiple-of-4 update sizes 2012-09-11 11:17:41 -07:00
Chris Robinson 88b0c30152 Use the correct size for defaultCoeffs 2012-09-11 10:43:53 -07:00
Chris Robinson 01183ad93b Minor cleanups for variable declarations 2012-09-11 09:40:08 -07:00
Chris Robinson 3f97af4c8c Don't use count-specific functions to write to the output buffer 2012-09-11 06:41:24 -07:00
Chris Robinson 4c5cb2189b Use a non-interleaved DryBuffer 2012-09-11 06:32:42 -07:00
Chris Robinson 98ff6f990a Do the filtering separately from the mixing 2012-09-11 05:56:19 -07:00
Chris Robinson aaa81e00b7 Use HUGE_VAL instead of dividing by 0 for infinity, where possible 2012-09-11 04:45:43 -07:00
Chris Robinson 1c44a96768 Silence a couple MSVC warnings 2012-09-11 03:29:00 -07:00
Chris Robinson 34fef456c8 Add example HRTF definition files for makehrtf 2012-09-11 03:19:03 -07:00
Chris Robinson 7e81918f7b Update HRTF code
This update allows for much more flexibility in the HRTF data. It also allows
for HRTF table file names to include "%r" to represent the device's playback
rate (e.g. if you set hrtf-%r.mhr, then it will try to use hrtf-44100.mhr or
hrtf-48000.mhr depending if the device's output rate is 44100 or 48000,
respectively).

The makehrtf utility has also been updated to support more options and input
file formats, as well as the new mhr format.
2012-09-11 02:11:51 -07:00
Chris Robinson 1b840a3db8 Again try to get _WIN32_IE to behave right with MinGW 2012-09-11 01:39:05 -07:00
Chris Robinson 4e440fff62 Remove a hack for MinGW 2012-09-10 00:19:13 -07:00
Chris Robinson 81208acd6e Add missing returns 2012-09-09 21:27:54 -07:00
Chris Robinson af3b5c23c8 Try to ensure mixing samples in multiples of 4 2012-09-09 04:27:47 -07:00
Chris Robinson 9f208417df Use the right method to clear a __m128 to 0 2012-09-09 04:09:31 -07:00
Chris Robinson f1ce139997 Use SSE to do 4 samples at once (non-HRTF direct mix), instead of to apply a matrix row
MaxCHannels no longer needs to be a multiple of 4 now, either.
2012-09-09 04:02:54 -07:00
Chris Robinson f56dddfa73 Implement MixDirect_SSE separately from the C and Neon versions 2012-09-09 00:53:54 -07:00
Chris Robinson 2bf1979d4a Move the target effect slot to the SendParams struct 2012-09-08 22:32:30 -07:00
Chris Robinson 89cab3cd39 Remove STACK_DATA_SIZE in favor of BUFFERSIZE 2012-09-08 22:09:34 -07:00
Chris Robinson 6723d27e06 Remove some unused code 2012-09-08 21:53:04 -07:00
Chris Robinson 1c03025090 Separate the resampling and mixing steps 2012-09-08 21:34:36 -07:00
Chris Robinson 7a37a63b8e Workaround MinGW __declspec(align(x)) bug 2012-09-08 19:24:07 -07:00
Chris Robinson 2b5fdad2c8 Free the global ALSA config after opening capture devices too 2012-09-02 14:26:46 -07:00
Lauri Kasanen a6f9ede849 alsa: Free the global config cache to remove a lot of reported leaks
Signed-off-by: Lauri Kasanen <curaga@operamail.com>
2012-09-02 14:16:23 -07:00
Chris Robinson 78dac1bf4a Set the error if setting a new integer source offset fails 2012-09-01 19:31:43 -07:00
Chris Robinson 795909c39e Minor cleanups for mixer_inc 2012-08-29 02:43:19 -07:00
Chris Robinson 3c042a054d Add an SSE-enhanced path for applying the mixer matrix 2012-08-29 01:56:04 -07:00
Chris Robinson 332d66c183 Make sure device buffers are 16-byte aligned 2012-08-29 01:40:42 -07:00
Chris Robinson de006947ac Increase MaxChannels to be a multiple of 4 2012-08-29 01:11:55 -07:00
Chris Robinson 8a128e5d25 Set an error closer to where it occurs for setting source properties 2012-08-29 00:25:01 -07:00
Chris Robinson 34cbacf424 Add helpers to set source properties 2012-08-28 22:16:55 -07:00
Chris Robinson f2fa5e7c88 Print the error when reporting snd_pcm_delay failure 2012-08-27 22:52:37 -07:00
Chris Robinson 3b735cc34a Use _aligned_free for pointers returned by _aligned_malloc 2012-08-24 17:45:16 -07:00
Chris Robinson 238caa1492 Constify some parameters 2012-08-21 16:01:11 -07:00
Chris Robinson e5ebe345ad Add the option to retrieve the source offset and latency in seconds 2012-08-20 15:57:27 -07:00
Chris Robinson 965608356f Fix getting the RW offsets with alGetSourcei64vSOFT 2012-08-20 15:33:28 -07:00
Chris Robinson bc1ce7b3ac Add methods to get source properties as doubles 2012-08-20 15:26:35 -07:00
Chris Robinson 6a3619c40f Fix a parameter name 2012-08-20 14:50:43 -07:00
Chris Robinson 50fa9a44be Properly export alGetSource3i64SOFT 2012-08-20 14:48:08 -07:00
Chris Robinson 4937a48bd9 Use helper functions to read source properties
And make sure the 64-bit int getters to get 32-bit int values
2012-08-20 14:16:58 -07:00
Chris Robinson 987a81c4de Use the correct 64-bit int type for the extension functions 2012-08-20 12:22:00 -07:00
Chris Robinson f5e0500df4 Add a macro to help make a 64-bit value 2012-08-19 22:31:55 -07:00
Chris Robinson 37924887e8 Use a default method to provide a dummy latency 2012-08-19 12:31:59 -07:00
Chris Robinson 0db7c4131b Hold the device lock with PulseAudio between mixing and writing 2012-08-18 17:20:20 -07:00
Chris Robinson a56a974149 Hold the device lock with ALSA between mixing and writing 2012-08-18 17:18:53 -07:00
Chris Robinson af7f3768fa Use non-blocking access for ALSA playback 2012-08-18 17:01:56 -07:00
Chris Robinson 0865db564f Move the device lock into the backend function table
For backend-specific implementations: this should hold the audio mixer loop for
playback devices, and provide recursive mutex behavior.
2012-08-18 15:58:04 -07:00
Chris Robinson 2b020040b4 Keep the backend device open until the last reference is released
This should generally happen with the next ALCdevice_DecRef call unless the
device is in the middle of being used in another thread, in which case it's
probably best to not remove the resources.
2012-08-18 14:49:42 -07:00
Chris Robinson 3ae5fcbd7e Add the start of AL_SOFT_source_latency
This extension will provide a way for apps to get accurate latency and playback
position information
2012-08-18 11:06:39 -07:00
Chris Robinson ac4fc4026c Add a device method to retrieve the active latency
This is effectively the time until the next update will be heard by the user,
or the closest approximation thereof, in nanoseconds.
2012-08-17 13:38:52 -07:00
Chris Robinson 9737f68315 Place the alignment attribute before the variable declaration 2012-08-16 10:42:48 -07:00
Chris Robinson 2a8c26e390 Remove extra parenthesis used in the aligned attribute declaration 2012-08-16 10:33:37 -07:00
Chris Robinson 3c395a82db Fix aligned allocator fallback 2012-08-16 10:30:13 -07:00
Chris Robinson 15c6b9b165 MSVC wants __declspec(align), not __declspec(aligned) 2012-08-16 10:23:25 -07:00
Chris Robinson 147fd9de4e Avoid dynamic handling of libsndio
This makes it safer and easier to handle as OpenBSD updates it
2012-08-16 10:12:50 -07:00
Chris Robinson 0bca771a88 Apply HRTF mixer coefficients with stepping using SSE 2012-08-15 08:19:04 -07:00
Chris Robinson f4ff63e271 Check the max CPUID functions before calling them 2012-08-15 06:28:45 -07:00
Chris Robinson bbcf4e8c1d Make sure sources are 16-byte aligned
They contain fields that require 16-byte alignment for SSE (and Neon?)
acceleration.
2012-08-15 05:54:13 -07:00
Chris Robinson 2859357939 Add wrapper methods to ensure aligned allocations 2012-08-15 05:50:40 -07:00
Chris Robinson 2cbb565d09 Ensure some HRTF-related parameters are aligned 2012-08-15 04:10:41 -07:00
Chris Robinson 4d157d2849 Make sure the working coefficients are aligned for the SSE mixer 2012-08-15 03:43:36 -07:00
Chris Robinson 64cd763e19 Remove unused filter functions 2012-08-15 01:48:47 -07:00
Chris Robinson c3f387da70 Check for and use the -msse switch when dealing with SSE intrinsics 2012-08-15 01:46:42 -07:00
Chris Robinson 6ebeb3b4f7 Check the correct macro for ARM Neon support 2012-08-15 01:32:17 -07:00
Chris Robinson 2e18baa3c8 Don't bother handling MMX since we don't use it 2012-08-15 01:29:19 -07:00
Chris Robinson c9e87a19a9 Add cmake options to disable or require support for CPU extensions 2012-08-15 01:24:50 -07:00
Chris Robinson 3b87e29e63 Move mixers into separate source files 2012-08-15 01:01:55 -07:00
Chris Robinson e9a20cb985 Add an SSE-enhanced HRTF mixer using intrinsics
Not as good as it could be, but it's something
2012-08-14 03:53:07 -07:00
Chris Robinson cfc5205569 Fix a typo 2012-08-13 22:31:58 -07:00
Chris Robinson 17dfaa3aae Add a config option to disable use of CPU extensions 2012-08-13 10:37:49 -07:00
Chris Robinson 0a3eba08d8 Allow building multiple types of mixers, selecting based on CPU caps 2012-08-13 09:18:46 -07:00
Chris Robinson add53e28c2 Check for some CPU extensions 2012-08-13 09:07:01 -07:00
Chris Robinson f42f655ea9 Don't unlock the pulseaudio mainloop when mixing
Lock contention could cause a lengthy delay between mixing and writing the
audio. There shouldn't be any risk of dead-locking as the device lock should
never be held when the mainloop gets locked.
2012-08-12 03:52:38 -07:00
Chris Robinson 8304fc1bef Handle the scalar values a bit better 2012-08-11 06:20:24 -07:00
Chris Robinson ea84fee952 Use a more efficient method to blend HRTF delays and coefficients 2012-08-11 02:16:34 -07:00
Chris Robinson d6fd52a0e5 Add an option for wide stereo sources
Replaces the old stereodup option
2012-08-09 05:38:07 -07:00
Chris Robinson 0dde7dd88a Use a more efficient method to offset the speaker angles when computing gains 2012-08-09 02:31:19 -07:00
Chris Robinson 1323e11701 Interpolate between HRTF delay samples using the delay fraction 2012-07-20 15:08:11 -07:00
Chris Robinson 7ac9944bb3 Increase the directional change sensitivity for the HRTF delta 2012-07-20 14:38:49 -07:00
Chris Robinson e32e2fd6b8 Fix an inadvertent change in the HRTF coefficient stepping value array size 2012-07-19 11:49:43 -07:00
Chris Robinson 6bd535bed0 Use wrappers for float-typed math functions 2012-06-29 02:12:36 -07:00
Chris Robinson 524c88c402 Test the squared length of a vector before normalizing 2012-06-28 20:54:10 -07:00
Chris Robinson 1c096b101d Minor typo fixes 2012-06-28 19:57:23 -07:00
Chris Robinson 583dc8dbca Don't use all caps for enum value names 2012-06-28 18:49:49 -07:00
Chris Robinson befa4e7528 Don't try to set FE_TOWARDZERO when it's not available 2012-06-28 18:27:45 -07:00
Chris Robinson bc6751237c Clamp the Y position before trying to get the elevation 2012-06-28 17:26:00 -07:00
Chris Robinson 6f3be31b60 Add some includes 2012-06-20 03:01:19 -07:00
Chris Robinson 8001d86751 Add missing include 2012-06-19 22:15:19 -07:00
Chris Robinson acca3e5a21 Use a proper method to wait for a PulseAudio operation 2012-06-19 10:37:09 -07:00
Chris Robinson d17f835e74 Remove an unused include 2012-06-19 04:02:55 -07:00
Chris Robinson ef1f8aa9a0 Don't needlessly verify a device 2012-06-19 00:25:45 -07:00
Chris Robinson a5ac6eb524 Remove an outdated comment about _REENTRANT 2012-06-18 02:04:10 -07:00
Chris Robinson ac84d95c6e Silence some GCC warnings 2012-06-17 22:17:03 -07:00
Chris Robinson 785f52aa29 Only try float32 with DSound when specifically requested
Some hardware drivers seem to have a bug where a buffer descriptor with a
32-bit float sample type ends up creating a non-float32 buffer.
2012-06-17 04:13:01 -07:00
Chris Robinson 051195a991 Avoid failing if ALSA can't set a buffer or period time near to our request
These functions should not fail, but there seem to be bugs that cause them to
sometimes. We're flexible enough to handle almost anything it throws back at us
though, so anything is better than nothing here.
2012-06-16 23:02:59 -07:00
Chris Robinson 90ca6675c2 Allow PulseAudio to spawn a server by default
Since only one backend is used at a time now, the issues with device ownership
aren't really prevelant anymore. An application that tries to open all
enumerated devices won't run into the problem of spawning a server and end up
preventing other backend devices from working.
2012-06-16 22:37:45 -07:00
Chris Robinson 0db9730a50 Add an option to allow PulseAudio to move streams
This could be made the default, if there's a safe way to update the AL device
specifier.
2012-06-16 22:32:19 -07:00
Chris Robinson ad2643d8af Clarify some comments, fix some definition ordering, and add some includes 2012-06-15 23:46:09 -07:00
Chris Robinson 46840ee787 Add DEVPKEY_Device_FriendlyName declaration for mingw-w64 compatibility 2012-06-14 18:10:10 -07:00
Chris Robinson 1e0282a238 Add some more entries to .gitignore 2012-05-09 16:30:22 -07:00
Chris Robinson 259e4f5b38 Rename AllDevice -> AllDevices 2012-05-09 16:28:16 -07:00
Chris Robinson e44229c74e Clamp the ALSA period time between min and max if setting near fails 2012-05-08 01:23:53 -07:00
Chris Robinson 92827cc467 Clamp the ALSA buffer time between min and max if setting near fails
It seems there's some bugs with snd_pcm_hw_params_set_buffer_time_near that
cause it to return "invalid argument" despite a valid nearby buffer time being
available. Clamping the buffer time seems to mitigate the issue a bit.
2012-05-07 11:42:59 -07:00
Chris Robinson dd3d5bc2d4 Look for libsndio.so.2 instead of libsndio.so 2012-05-05 16:19:51 -07:00
Chris Robinson b4c7b3309a Only use _FPU_GETCW and _FPU_SETCW for x86 targets 2012-05-03 12:15:51 -07:00
Chris Robinson 010a66487d Use 2 chained one-pole filters for the wet path 2012-04-30 09:33:00 -07:00
Chris Robinson aed35fd811 Use ComputeAngleGains for multi-channel sources and remove the unused lookup table stuff 2012-04-29 05:04:46 -07:00
Chris Robinson 8d9838012d Remove the stereodup option
There's better ways to do it now with "wide" sound sources.
2012-04-29 04:44:53 -07:00
Chris Robinson 57d36ec582 Fix a couple comment typos, and a minor cleanup 2012-04-29 03:39:08 -07:00
Chris Robinson febc2a50cb Use ComputeAngleGains for 3D sounds 2012-04-28 13:06:16 -07:00
Chris Robinson 74e128bd0f Fix ComputeAngleGains
The old code would improperly handle speakers just inside or outside the
coverage area if it had to be inverted. It also didn't properly handle when
only one speaker was outside of the covered area.
2012-04-28 12:12:02 -07:00
Chris Robinson c34d78f417 Use ComputeAngleGains for the echo and dedicated effects 2012-04-28 08:24:09 -07:00
Chris Robinson 611bd0b2d3 Add a method to calculate gains given a sound point and its half-width, and use it for reverb
The half-width ranges from 0 to pi, and essentially specifies the coverage area
around the listener. At 0, it's an infinitely small point sound and behaves
like a usual panning sound. At pi/2 it covers half the area, and at pi it
covers the whole area.
2012-04-28 08:21:53 -07:00
Chris Robinson 267d38cf20 Flip the parameters to aluCart2LUTpos, so it behaves a bit more like atan2 2012-04-28 03:58:58 -07:00
Chris Robinson 26456f13e1 Pass the direct/send params to the mixer instead of accessing through the source 2012-04-28 03:31:13 -07:00
Chris Robinson 2484c44db0 Apply the listener gain with the filter 2012-04-28 03:13:37 -07:00
Chris Robinson a8a13fcbd8 Move the HrtfParams into the DirectParams 2012-04-28 02:23:53 -07:00
Chris Robinson 0a193c5645 Move the direct and send params into separate different types 2012-04-28 01:32:52 -07:00
Chris Robinson 2450ee1723 Use separate methods for the dry and wet mixing loops 2012-04-27 23:46:51 -07:00
Chris Robinson 67f1cdfcbe Store the speaker angles in the device 2012-04-27 07:38:17 -07:00
Chris Robinson 549d542a31 Reorganize some ALsource fields 2012-04-27 01:36:13 -07:00
Chris Robinson 2cdb58fb85 The mixer always uses floats 2012-04-26 07:50:17 -07:00
Chris Robinson 68ab232364 Use a separate loop to actually update DataPosFrac and DataPosInt 2012-04-26 06:44:37 -07:00
Chris Robinson 871d61f3f9 Add and fixup some ALsource comments 2012-04-26 03:26:22 -07:00
Chris Robinson b08bd3746e Add AL_EXT_SOURCE_RADIUS to alext.h 2012-04-26 02:05:49 -07:00
Chris Robinson 39ab0b0aa3 Add AL_EXT_STEREO_ANGLES to alext.h 2012-04-26 01:19:25 -07:00
Chris Robinson 5c70cacc13 Fixup some comments in ALu.c 2012-04-26 00:59:17 -07:00
Chris Robinson 8c2cd057b2 Fix a minor typo 2012-04-25 19:37:12 -07:00
Chris Robinson fdc4133ac9 Partially convert alEffect.c and alFilter.c to the new error handling 2012-04-25 00:24:02 -07:00
Chris Robinson 3833c021c0 Move a comment 2012-04-25 00:03:01 -07:00
Chris Robinson cafbd9461e Fix up alEffect.c and alFilter.c a bit 2012-04-24 23:06:10 -07:00
Chris Robinson 6995ac1ed2 Change alAuxEffectSlot.c to the new error handling 2012-04-24 22:57:23 -07:00
Chris Robinson 58e3dc3d52 Add a SIGTRAP for when alGetError is called without a context 2012-04-24 21:41:01 -07:00
Chris Robinson 3e49e79140 Couple small error handling fixups 2012-04-24 03:52:21 -07:00
Chris Robinson dec8e81211 Change alState.c to the new error handling 2012-04-24 03:09:28 -07:00
Chris Robinson 4188a5f3f3 Fix compiling al.h with C++ 2012-04-24 02:51:23 -07:00
Chris Robinson 31d124582b Switch alBuffer.c to the new error handling scheme, and get rid of more hungarian notation 2012-04-24 00:17:05 -07:00
Chris Robinson 248e079301 Switch alListener.c to the new error handling scheme, and get rid of more hungarian notation 2012-04-23 21:35:05 -07:00
Chris Robinson 5ce850570f Add try/catch-like macros to handle errors, and convert alSource.c to use them 2012-04-23 19:46:05 -07:00
Chris Robinson 648464a2da Check the right playback device file with OSS 2012-04-22 05:06:44 -07:00
Chris Robinson 29f77003c0 Some alSource.c cleanups 2012-04-21 05:56:03 -07:00
Chris Robinson dfa38ed7a5 Reformat alc/h and al.h, and redo the comments 2012-04-21 04:34:08 -07:00
Chris Robinson 66c918c84b Remove export pragmas from headers
Available information suggests it's only useful for Mac OS9 and earlier (not
OSX).
2012-04-20 22:53:47 -07:00
Chris Robinson 77f55da6c7 Use a macro to declare the function and enum list members 2012-04-20 22:38:03 -07:00
Chris Robinson d6af7cdcb2 Rename another variable to avoid hungarian notation 2012-04-20 22:37:36 -07:00
Chris Robinson 0ad8047820 Combine ALCenum and ALenum lists 2012-04-20 01:24:58 -07:00
Chris Robinson 2115f578e9 Reorganize ALC functions and fixup some comments 2012-04-20 01:18:38 -07:00
Chris Robinson 511b4790d0 Remove hungarian notation from dsound and mmdevapi 2012-04-19 23:42:02 -07:00
Chris Robinson d6491e21f9 Remove some more hungarian notation 2012-04-19 23:28:34 -07:00
Chris Robinson cff0f938e5 Remove hungarian notation from the winmm backend 2012-04-19 23:22:11 -07:00
Chris Robinson 5418519637 Remove some more hungarian notation 2012-04-19 23:00:58 -07:00
Chris Robinson b023dbe7b8 Remove hungarian notation from the device and context structs 2012-04-19 22:50:11 -07:00
Chris Robinson 8092cd9205 Remove hungarian notation from some function parameters 2012-04-19 22:40:40 -07:00
Chris Robinson 60da5bd338 Remove an unused field 2012-04-19 22:32:04 -07:00
Chris Robinson c9e64596a4 Use a consistent name for the self-id field 2012-04-19 22:28:01 -07:00
Chris Robinson 08bd5e8b37 Fix comment and rename the buffer's self-id 2012-04-19 22:14:02 -07:00
Chris Robinson 125b743e5c Remove hungarian notation from sources 2012-04-19 21:46:29 -07:00
Chris Robinson 9a3eb397f4 Print the device name in printALCInfo 2012-04-16 23:27:13 -07:00
Chris Robinson 84c1f2bfd0 Avoid shadowing a couple variables 2012-04-16 23:09:36 -07:00
Chris Robinson d7ba49ea62 Clear the position fraction when setting a new source offset 2012-04-16 22:13:39 -07:00
Chris Robinson e47557630e Use a double to store the source offset and don't use milliseconds for seconds 2012-04-16 22:11:03 -07:00
Chris Robinson f6a1e53f19 Read ALSOFT_TRAP_*ERROR when reading the config 2012-04-16 20:13:50 -07:00
Chris Robinson a0a015f19f Set a 1MB stack size for created threads 2012-04-16 19:15:48 -07:00
Chris Robinson e3bea63f94 Check for a recent libavutil for the example, too 2012-04-07 12:35:59 -07:00
74 changed files with 16450 additions and 9219 deletions
+4
View File
@@ -1 +1,5 @@
build
winbuild
include/sndio.h
include/sys
openal-soft.kdev4
+1106 -757
View File
File diff suppressed because it is too large Load Diff
+450 -380
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -19,7 +19,7 @@
*/
#ifdef _WIN32
#ifdef __MINGW64__
#ifdef __MINGW32__
#define _WIN32_IE 0x501
#else
#define _WIN32_IE 0x400
+9 -20
View File
@@ -33,7 +33,7 @@ typedef struct ALdedicatedState {
// Must be first in all effects!
ALeffectState state;
ALfloat gains[MAXCHANNELS];
ALfloat gains[MaxChannels];
} ALdedicatedState;
@@ -53,40 +53,29 @@ static ALboolean DedicatedDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
static ALvoid DedicatedUpdate(ALeffectState *effect, ALCdevice *device, const ALeffectslot *Slot)
{
ALdedicatedState *state = (ALdedicatedState*)effect;
const ALfloat *ChannelGain;
ALfloat Gain;
ALint pos;
ALsizei s;
Gain = Slot->Gain * Slot->effect.Dedicated.Gain;
for(s = 0;s < MAXCHANNELS;s++)
for(s = 0;s < MaxChannels;s++)
state->gains[s] = 0.0f;
if(Slot->effect.type == AL_EFFECT_DEDICATED_DIALOGUE)
{
pos = aluCart2LUTpos(1.0f, 0.0f);
ChannelGain = device->PanningLUT[pos];
for(s = 0;s < MAXCHANNELS;s++)
state->gains[s] = ChannelGain[s] * Gain;
}
ComputeAngleGains(device, atan2f(0.0f, 1.0f), 0.0f, Gain, state->gains);
else if(Slot->effect.type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
state->gains[LFE] = Gain;
}
static ALvoid DedicatedProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid DedicatedProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALdedicatedState *state = (ALdedicatedState*)effect;
const ALfloat *gains = state->gains;
ALuint i, s;
ALuint i, c;
for(i = 0;i < SamplesToDo;i++)
for(c = 0;c < MaxChannels;c++)
{
ALfloat sample;
sample = SamplesIn[i];
for(s = 0;s < MAXCHANNELS;s++)
SamplesOut[i][s] = sample * gains[s];
for(i = 0;i < SamplesToDo;i++)
SamplesOut[c][i] = SamplesIn[i] * gains[c];
}
}
@@ -104,7 +93,7 @@ ALeffectState *DedicatedCreate(void)
state->state.Update = DedicatedUpdate;
state->state.Process = DedicatedProcess;
for(s = 0;s < MAXCHANNELS;s++)
for(s = 0;s < MaxChannels;s++)
state->gains[s] = 0.0f;
return &state->state;
+13 -29
View File
@@ -44,7 +44,7 @@ typedef struct ALechoState {
} Tap[2];
ALuint Offset;
/* The panning gains for the two taps */
ALfloat Gain[2][MAXCHANNELS];
ALfloat Gain[2][MaxChannels];
ALfloat FeedGain;
@@ -94,10 +94,9 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffec
{
ALechoState *state = (ALechoState*)effect;
ALuint frequency = Device->Frequency;
ALfloat dirGain, ambientGain;
const ALfloat *ChannelGain;
ALfloat lrpan, cw, g, gain;
ALuint i, pos;
ALfloat dirGain;
ALuint i;
state->Tap[0].delay = fastf2u(Slot->effect.Echo.Delay * frequency) + 1;
state->Tap[1].delay = fastf2u(Slot->effect.Echo.LRDelay * frequency);
@@ -107,42 +106,27 @@ static ALvoid EchoUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffec
state->FeedGain = Slot->effect.Echo.Feedback;
cw = aluCos(F_PI*2.0f * LOWPASSFREQREF / frequency);
cw = cosf(F_PI*2.0f * LOWPASSFREQREF / frequency);
g = 1.0f - Slot->effect.Echo.Damping;
state->iirFilter.coeff = lpCoeffCalc(g, cw);
gain = Slot->Gain;
for(i = 0;i < MAXCHANNELS;i++)
for(i = 0;i < MaxChannels;i++)
{
state->Gain[0][i] = 0.0f;
state->Gain[1][i] = 0.0f;
}
ambientGain = aluSqrt(1.0f/Device->NumChan);
dirGain = aluFabs(lrpan);
dirGain = fabsf(lrpan);
/* First tap panning */
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?-1.0f:1.0f));
ChannelGain = Device->PanningLUT[pos];
for(i = 0;i < Device->NumChan;i++)
{
enum Channel chan = Device->Speaker2Chan[i];
state->Gain[0][chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * gain;
}
ComputeAngleGains(Device, atan2f(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]);
/* Second tap panning */
pos = aluCart2LUTpos(0.0f, ((lrpan>0.0f)?1.0f:-1.0f));
ChannelGain = Device->PanningLUT[pos];
for(i = 0;i < Device->NumChan;i++)
{
enum Channel chan = Device->Speaker2Chan[i];
state->Gain[1][chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * gain;
}
ComputeAngleGains(Device, atan2f(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]);
}
static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALechoState *state = (ALechoState*)effect;
const ALuint mask = state->BufferLength-1;
@@ -156,13 +140,13 @@ static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALflo
{
/* First tap */
smp = state->SampleBuffer[(offset-tap1) & mask];
for(k = 0;k < MAXCHANNELS;k++)
SamplesOut[i][k] += smp * state->Gain[0][k];
for(k = 0;k < MaxChannels;k++)
SamplesOut[k][i] += smp * state->Gain[0][k];
/* Second tap */
smp = state->SampleBuffer[(offset-tap2) & mask];
for(k = 0;k < MAXCHANNELS;k++)
SamplesOut[i][k] += smp * state->Gain[1][k];
for(k = 0;k < MaxChannels;k++)
SamplesOut[k][i] += smp * state->Gain[1][k];
// Apply damping and feedback gain to the second tap, and mix in the
// new sample
+12 -11
View File
@@ -43,7 +43,7 @@ typedef struct ALmodulatorState {
ALuint index;
ALuint step;
ALfloat Gain[MAXCHANNELS];
ALfloat Gain[MaxChannels];
FILTER iirFilter;
ALfloat history[1];
@@ -55,7 +55,7 @@ typedef struct ALmodulatorState {
static __inline ALfloat Sin(ALuint index)
{
return aluSin(index * (F_PI*2.0f / WAVEFORM_FRACONE));
return sinf(index * (F_PI*2.0f / WAVEFORM_FRACONE));
}
static __inline ALfloat Saw(ALuint index)
@@ -84,7 +84,8 @@ static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
#define DECL_TEMPLATE(func) \
static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \
const ALfloat *RESTRICT SamplesIn, \
ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE]) \
{ \
const ALuint step = state->step; \
ALuint index = state->index; \
@@ -101,8 +102,8 @@ static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
\
samp = hpFilter1P(&state->iirFilter, 0, samp); \
\
for(k = 0;k < MAXCHANNELS;k++) \
SamplesOut[i][k] += state->Gain[k] * samp; \
for(k = 0;k < MaxChannels;k++) \
SamplesOut[k][i] += state->Gain[k] * samp; \
} \
state->index = index; \
}
@@ -144,14 +145,14 @@ static ALvoid ModulatorUpdate(ALeffectState *effect, ALCdevice *Device, const AL
Device->Frequency);
if(state->step == 0) state->step = 1;
cw = aluCos(F_PI*2.0f * Slot->effect.Modulator.HighPassCutoff /
Device->Frequency);
a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f);
cw = cosf(F_PI*2.0f * Slot->effect.Modulator.HighPassCutoff /
Device->Frequency);
a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f);
state->iirFilter.coeff = a;
gain = aluSqrt(1.0f/Device->NumChan);
gain = sqrtf(1.0f/Device->NumChan);
gain *= Slot->Gain;
for(index = 0;index < MAXCHANNELS;index++)
for(index = 0;index < MaxChannels;index++)
state->Gain[index] = 0.0f;
for(index = 0;index < Device->NumChan;index++)
{
@@ -160,7 +161,7 @@ static ALvoid ModulatorUpdate(ALeffectState *effect, ALCdevice *Device, const AL
}
}
static ALvoid ModulatorProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid ModulatorProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALmodulatorState *state = (ALmodulatorState*)effect;
+85 -89
View File
@@ -24,13 +24,12 @@
#include <stdlib.h>
#include <math.h>
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alu.h"
#include "alAuxEffectSlot.h"
#include "alEffect.h"
#include "alFilter.h"
#include "alError.h"
#include "alu.h"
typedef struct DelayLine
{
@@ -85,7 +84,7 @@ typedef struct ALverbState {
// The gain for each output channel based on 3D panning (only for the
// EAX path).
ALfloat PanGain[MAXCHANNELS];
ALfloat PanGain[MaxChannels];
} Early;
// Decorrelator delay line.
@@ -124,7 +123,7 @@ typedef struct ALverbState {
// The gain for each output channel based on 3D panning (only for the
// EAX path).
ALfloat PanGain[MAXCHANNELS];
ALfloat PanGain[MaxChannels];
} Late;
struct {
@@ -157,6 +156,10 @@ typedef struct ALverbState {
// The gain for each output channel (non-EAX path only; aliased from
// Late.PanGain)
ALfloat *Gain;
/* Temporary storage used when processing, before deinterlacing. */
ALfloat ReverbSamples[BUFFERSIZE][4];
ALfloat EarlySamples[BUFFERSIZE][4];
} ALverbState;
/* This is a user config option for modifying the overall output of the reverb
@@ -261,7 +264,7 @@ static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in)
// Calculate the sinus rythm (dependent on modulation time and the
// sampling rate). The center of the sinus is moved to reduce the delay
// of the effect when the time or depth are low.
sinus = 1.0f - aluCos(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
sinus = 1.0f - cosf(F_PI*2.0f * State->Mod.Index / State->Mod.Range);
// The depth determines the range over which to read the input samples
// from, so it must be filtered to reduce the distortion caused by even
@@ -298,7 +301,7 @@ static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index)
// Given an input sample, this function produces four-channel output for the
// early reflections.
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out)
static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
{
ALfloat d[4], v, f[4];
@@ -369,7 +372,7 @@ static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALflo
// Given four decorrelated input samples, this function produces four-channel
// output for the late reverb.
static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
static __inline ALvoid LateReverb(ALverbState *State, const ALfloat *RESTRICT in, ALfloat *RESTRICT out)
{
ALfloat d[4], f[4];
@@ -440,7 +443,7 @@ static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out)
// Given an input sample, this function mixes echo into the four-channel late
// reverb.
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late)
static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *RESTRICT late)
{
ALfloat out, feed;
@@ -474,9 +477,9 @@ static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late)
// Perform the non-EAX reverb pass on a given input sample, resulting in
// four-channel output.
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT out)
{
ALfloat feed, taps[4];
ALfloat feed, late[4], taps[4];
// Low-pass filter the incoming sample.
in = lpFilter2P(&State->LpFilter, 0, in);
@@ -486,7 +489,7 @@ static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early,
// Calculate the early reflection from the first delay tap.
in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
EarlyReflection(State, in, early);
EarlyReflection(State, in, out);
// Feed the decorrelator from the energy-attenuated output of the second
// delay tap.
@@ -501,13 +504,19 @@ static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early,
taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
LateReverb(State, taps, late);
// Mix early reflections and late reverb.
out[0] += late[0];
out[1] += late[1];
out[2] += late[2];
out[3] += late[3];
// Step all delays forward one sample.
State->Offset++;
}
// Perform the EAX reverb pass on a given input sample, resulting in four-
// channel output.
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late)
static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *RESTRICT early, ALfloat *RESTRICT late)
{
ALfloat feed, taps[4];
@@ -546,53 +555,62 @@ static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *earl
// This processes the reverb state, given the input samples and an output
// buffer.
static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid VerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALverbState *State = (ALverbState*)effect;
ALfloat (*RESTRICT out)[4] = State->ReverbSamples;
ALuint index, c;
ALfloat early[4], late[4], out[4];
const ALfloat *panGain = State->Gain;
/* Process reverb for these samples. */
for(index = 0;index < SamplesToDo;index++)
VerbPass(State, SamplesIn[index], out[index]);
for(c = 0;c < MaxChannels;c++)
{
// Process reverb for this sample.
VerbPass(State, SamplesIn[index], early, late);
// Mix early reflections and late reverb.
out[0] = (early[0] + late[0]);
out[1] = (early[1] + late[1]);
out[2] = (early[2] + late[2]);
out[3] = (early[3] + late[3]);
// Output the results.
for(c = 0;c < MAXCHANNELS;c++)
SamplesOut[index][c] += panGain[c] * out[c&3];
ALfloat gain = State->Gain[c];
if(gain > 0.00001f)
{
for(index = 0;index < SamplesToDo;index++)
SamplesOut[c][index] += gain * out[index][c&3];
}
}
}
// This processes the EAX reverb state, given the input samples and an output
// buffer.
static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid EAXVerbProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
ALverbState *State = (ALverbState*)effect;
ALfloat (*RESTRICT early)[4] = State->EarlySamples;
ALfloat (*RESTRICT late)[4] = State->ReverbSamples;
ALuint index, c;
ALfloat early[4], late[4];
/* Process reverb for these samples. */
for(index = 0;index < SamplesToDo;index++)
{
// Process reverb for this sample.
EAXVerbPass(State, SamplesIn[index], early, late);
EAXVerbPass(State, SamplesIn[index], early[index], late[index]);
for(c = 0;c < MAXCHANNELS;c++)
SamplesOut[index][c] += State->Early.PanGain[c]*early[c&3] +
State->Late.PanGain[c]*late[c&3];
for(c = 0;c < MaxChannels;c++)
{
ALfloat earlyGain = State->Early.PanGain[c];
ALfloat lateGain = State->Late.PanGain[c];
if(earlyGain > 0.00001f)
{
for(index = 0;index < SamplesToDo;index++)
SamplesOut[c][index] += earlyGain*early[index][c&3];
}
if(lateGain > 0.00001f)
{
for(index = 0;index < SamplesToDo;index++)
SamplesOut[c][index] += lateGain*late[index][c&3];
}
}
}
// Given the allocated sample buffer, this function updates each delay line
// offset.
static __inline ALvoid RealizeLineOffset(ALfloat * sampleBuffer, DelayLine *Delay)
static __inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
{
Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
}
@@ -720,8 +738,8 @@ static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
// is calculated given the current sample rate. This ensures that the
// resulting filter response over time is consistent across all sample
// rates.
State->Mod.Coeff = aluPow(MODULATION_FILTER_COEFF,
MODULATION_FILTER_CONST / frequency);
State->Mod.Coeff = powf(MODULATION_FILTER_COEFF,
MODULATION_FILTER_CONST / frequency);
// The early reflection and late all-pass filter line lengths are static,
// so their offsets only need to be calculated once.
@@ -744,21 +762,21 @@ static ALboolean ReverbDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
// until the decay reaches -60 dB.
static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
{
return aluPow(0.001f/*-60 dB*/, length/decayTime);
return powf(0.001f/*-60 dB*/, length/decayTime);
}
// Calculate a decay length from a coefficient and the time until the decay
// reaches -60 dB.
static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
{
return aluLog10(coeff) * decayTime / aluLog10(0.001f)/*-60 dB*/;
return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
}
// Calculate the high frequency parameter for the I3DL2 coefficient
// calculation.
static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
{
return aluCos(F_PI*2.0f * hfRef / frequency);
return cosf(F_PI*2.0f * hfRef / frequency);
}
// Calculate an attenuation to be applied to the input of any echo models to
@@ -778,7 +796,7 @@ static __inline ALfloat CalcDensityGain(ALfloat a)
* calculated by inverting the square root of this approximation,
* yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
*/
return aluSqrt(1.0f - (a * a));
return sqrtf(1.0f - (a * a));
}
// Calculate the mixing matrix coefficients given a diffusion factor.
@@ -787,13 +805,13 @@ static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *
ALfloat n, t;
// The matrix is of order 4, so n is sqrt (4 - 1).
n = aluSqrt(3.0f);
t = diffusion * aluAtan(n);
n = sqrtf(3.0f);
t = diffusion * atanf(n);
// Calculate the first mixing matrix coefficient.
*x = aluCos(t);
*x = cosf(t);
// Calculate the second mixing matrix coefficient.
*y = aluSin(t) / n;
*y = sinf(t) / n;
}
// Calculate the limited HF ratio for use with the late reverb low-pass
@@ -913,7 +931,7 @@ static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState
*/
for(index = 0;index < 3;index++)
{
length = (DECO_FRACTION * aluPow(DECO_MULTIPLIER, (ALfloat)index)) *
length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)index)) *
LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
State->DecoTap[index] = fastf2u(length * frequency);
}
@@ -947,7 +965,7 @@ static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix
decayTime));
// Calculate the all-pass feed-back and feed-forward coefficient.
State->Late.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f);
State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
for(index = 0;index < 4;index++)
{
@@ -991,7 +1009,7 @@ static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoT
State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
// Calculate the echo all-pass feed coefficient.
State->Echo.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f);
State->Echo.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
// Calculate the echo all-pass attenuation coefficient.
State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
@@ -1016,24 +1034,21 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
ReflectionsPan[2] };
ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
LateReverbPan[2] };
const ALfloat *ChannelGain;
ALfloat ambientGain;
ALfloat dirGain;
ALfloat length;
ALuint index;
ALint pos;
Gain *= ReverbBoost;
// Attenuate non-directional reverb according to the number of channels
ambientGain = aluSqrt(2.0f/Device->NumChan);
/* Attenuate reverb according to its coverage (dirGain=0 will give
* Gain*ambientGain, and dirGain=1 will give Gain). */
ambientGain = minf(sqrtf(2.0f/Device->NumChan), 1.0f);
// Calculate the 3D-panning gains for the early reflections and late
// reverb.
length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
if(length > 1.0f)
{
length = 1.0f / aluSqrt(length);
length = 1.0f / sqrtf(length);
earlyPan[0] *= length;
earlyPan[1] *= length;
earlyPan[2] *= length;
@@ -1041,42 +1056,23 @@ static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *Reflection
length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
if(length > 1.0f)
{
length = 1.0f / aluSqrt(length);
length = 1.0f / sqrtf(length);
latePan[0] *= length;
latePan[1] *= length;
latePan[2] *= length;
}
/* This code applies directional reverb just like the mixer applies
* directional sources. It diffuses the sound toward all speakers as the
* magnitude of the panning vector drops, which is only a rough
* approximation of the expansion of sound across the speakers from the
* panning direction.
*/
pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]);
ChannelGain = Device->PanningLUT[pos];
dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2]));
dirGain = sqrtf(earlyPan[0]*earlyPan[0] + earlyPan[2]*earlyPan[2]);
for(index = 0;index < MaxChannels;index++)
State->Early.PanGain[index] = 0.0f;
ComputeAngleGains(Device, atan2f(earlyPan[0], earlyPan[2]), (1.0f-dirGain)*F_PI,
lerp(ambientGain, 1.0f, dirGain) * Gain, State->Early.PanGain);
for(index = 0;index < MAXCHANNELS;index++)
State->Early.PanGain[index] = 0.0f;
for(index = 0;index < Device->NumChan;index++)
{
enum Channel chan = Device->Speaker2Chan[index];
State->Early.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
}
pos = aluCart2LUTpos(latePan[2], latePan[0]);
ChannelGain = Device->PanningLUT[pos];
dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2]));
for(index = 0;index < MAXCHANNELS;index++)
dirGain = sqrtf(latePan[0]*latePan[0] + latePan[2]*latePan[2]);
for(index = 0;index < MaxChannels;index++)
State->Late.PanGain[index] = 0.0f;
for(index = 0;index < Device->NumChan;index++)
{
enum Channel chan = Device->Speaker2Chan[index];
State->Late.PanGain[chan] = lerp(ambientGain, ChannelGain[chan], dirGain) * Gain;
}
ComputeAngleGains(Device, atan2f(latePan[0], latePan[2]), (1.0f-dirGain)*F_PI,
lerp(ambientGain, 1.0f, dirGain) * Gain, State->Late.PanGain);
}
// This updates the EAX reverb state. This is called any time the EAX reverb
@@ -1163,8 +1159,8 @@ static ALvoid ReverbUpdate(ALeffectState *effect, ALCdevice *Device, const ALeff
ALuint index;
/* Update channel gains */
gain *= aluSqrt(2.0f/Device->NumChan) * ReverbBoost;
for(index = 0;index < MAXCHANNELS;index++)
gain *= sqrtf(2.0f/Device->NumChan) * ReverbBoost;
for(index = 0;index < MaxChannels;index++)
State->Gain[index] = 0.0f;
for(index = 0;index < Device->NumChan;index++)
{
@@ -1258,7 +1254,7 @@ ALeffectState *ReverbCreate(void)
State->Late.LpSample[index] = 0.0f;
}
for(index = 0;index < MAXCHANNELS;index++)
for(index = 0;index < MaxChannels;index++)
{
State->Early.PanGain[index] = 0.0f;
State->Late.PanGain[index] = 0.0f;
+20 -4
View File
@@ -25,6 +25,7 @@
#include "alMain.h"
#include "alThunk.h"
#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
#ifdef _WIN32
@@ -54,7 +55,7 @@ ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
inf->func = func;
inf->ptr = ptr;
inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, &dummy);
inf->thread = CreateThread(NULL, THREAD_STACK_SIZE, StarterFunc, inf, 0, &dummy);
if(!inf->thread)
{
free(inf);
@@ -98,16 +99,31 @@ static void *StarterFunc(void *ptr)
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
{
pthread_attr_t attr;
ThreadInfo *inf = malloc(sizeof(ThreadInfo));
if(!inf) return NULL;
inf->func = func;
inf->ptr = ptr;
if(pthread_create(&inf->thread, NULL, StarterFunc, inf) != 0)
if(pthread_attr_init(&attr) != 0)
{
free(inf);
return NULL;
}
if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0)
{
pthread_attr_destroy(&attr);
free(inf);
return NULL;
}
inf->func = func;
inf->ptr = ptr;
if(pthread_create(&inf->thread, &attr, StarterFunc, inf) != 0)
{
pthread_attr_destroy(&attr);
free(inf);
return NULL;
}
pthread_attr_destroy(&attr);
return inf;
}
+120 -47
View File
@@ -25,6 +25,7 @@
#include <memory.h>
#include "alMain.h"
#include "alu.h"
#include <alsa/asoundlib.h>
@@ -57,6 +58,10 @@ MAKE_FUNC(snd_pcm_hw_params_set_period_time_near);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
MAKE_FUNC(snd_pcm_hw_params_set_period_size_near);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
MAKE_FUNC(snd_pcm_hw_params_get_buffer_time_min);
MAKE_FUNC(snd_pcm_hw_params_get_buffer_time_max);
MAKE_FUNC(snd_pcm_hw_params_get_period_time_min);
MAKE_FUNC(snd_pcm_hw_params_get_period_time_max);
MAKE_FUNC(snd_pcm_hw_params_get_buffer_size);
MAKE_FUNC(snd_pcm_hw_params_get_period_size);
MAKE_FUNC(snd_pcm_hw_params_get_access);
@@ -75,6 +80,7 @@ MAKE_FUNC(snd_pcm_start);
MAKE_FUNC(snd_pcm_resume);
MAKE_FUNC(snd_pcm_reset);
MAKE_FUNC(snd_pcm_wait);
MAKE_FUNC(snd_pcm_delay);
MAKE_FUNC(snd_pcm_state);
MAKE_FUNC(snd_pcm_avail_update);
MAKE_FUNC(snd_pcm_areas_silence);
@@ -101,6 +107,7 @@ MAKE_FUNC(snd_ctl_card_info);
MAKE_FUNC(snd_ctl_card_info_get_name);
MAKE_FUNC(snd_ctl_card_info_get_id);
MAKE_FUNC(snd_card_next);
MAKE_FUNC(snd_config_update_free_global);
#undef MAKE_FUNC
#define snd_strerror psnd_strerror
@@ -125,6 +132,10 @@ MAKE_FUNC(snd_card_next);
#define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near
#define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near
#define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min
#define snd_pcm_hw_params_get_buffer_time_min psnd_pcm_hw_params_get_buffer_time_min
#define snd_pcm_hw_params_get_buffer_time_max psnd_pcm_hw_params_get_buffer_time_max
#define snd_pcm_hw_params_get_period_time_min psnd_pcm_hw_params_get_period_time_min
#define snd_pcm_hw_params_get_period_time_max psnd_pcm_hw_params_get_period_time_max
#define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size
#define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size
#define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access
@@ -143,6 +154,7 @@ MAKE_FUNC(snd_card_next);
#define snd_pcm_resume psnd_pcm_resume
#define snd_pcm_reset psnd_pcm_reset
#define snd_pcm_wait psnd_pcm_wait
#define snd_pcm_delay psnd_pcm_delay
#define snd_pcm_state psnd_pcm_state
#define snd_pcm_avail_update psnd_pcm_avail_update
#define snd_pcm_areas_silence psnd_pcm_areas_silence
@@ -169,6 +181,7 @@ MAKE_FUNC(snd_card_next);
#define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name
#define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id
#define snd_card_next psnd_card_next
#define snd_config_update_free_global psnd_config_update_free_global
#endif
@@ -211,6 +224,10 @@ static ALCboolean alsa_load(void)
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
LOAD_FUNC(snd_pcm_hw_params_set_period_size_near);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_time_min);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_time_max);
LOAD_FUNC(snd_pcm_hw_params_get_period_time_min);
LOAD_FUNC(snd_pcm_hw_params_get_period_time_max);
LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
LOAD_FUNC(snd_pcm_hw_params_get_access);
@@ -229,6 +246,7 @@ static ALCboolean alsa_load(void)
LOAD_FUNC(snd_pcm_resume);
LOAD_FUNC(snd_pcm_reset);
LOAD_FUNC(snd_pcm_wait);
LOAD_FUNC(snd_pcm_delay);
LOAD_FUNC(snd_pcm_state);
LOAD_FUNC(snd_pcm_avail_update);
LOAD_FUNC(snd_pcm_areas_silence);
@@ -255,6 +273,7 @@ static ALCboolean alsa_load(void)
LOAD_FUNC(snd_ctl_card_info_get_name);
LOAD_FUNC(snd_ctl_card_info_get_id);
LOAD_FUNC(snd_card_next);
LOAD_FUNC(snd_config_update_free_global);
#undef LOAD_FUNC
}
#endif
@@ -434,8 +453,8 @@ static int verify_state(snd_pcm_t *handle)
static ALuint ALSAProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
alsa_data *data = (alsa_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
alsa_data *data = (alsa_data*)Device->ExtraData;
const snd_pcm_channel_area_t *areas = NULL;
snd_pcm_uframes_t update_size, num_updates;
snd_pcm_sframes_t avail, commitres;
@@ -445,15 +464,17 @@ static ALuint ALSAProc(ALvoid *ptr)
SetRTPriority();
update_size = pDevice->UpdateSize;
num_updates = pDevice->NumUpdates;
update_size = Device->UpdateSize;
num_updates = Device->NumUpdates;
while(!data->killNow)
{
int state = verify_state(data->pcmHandle);
if(state < 0)
{
ERR("Invalid state detected: %s\n", snd_strerror(state));
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
@@ -490,6 +511,7 @@ static ALuint ALSAProc(ALvoid *ptr)
avail -= avail%update_size;
// it is possible that contiguous areas are smaller, thus we use a loop
ALCdevice_Lock(Device);
while(avail > 0)
{
frames = avail;
@@ -502,7 +524,7 @@ static ALuint ALSAProc(ALvoid *ptr)
}
WritePtr = (char*)areas->addr + (offset * areas->step / 8);
aluMixData(pDevice, WritePtr, frames);
aluMixData(Device, WritePtr, frames);
commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames);
if(commitres < 0 || (commitres-frames) != 0)
@@ -514,6 +536,7 @@ static ALuint ALSAProc(ALvoid *ptr)
avail -= frames;
}
ALCdevice_Unlock(Device);
}
return 0;
@@ -521,26 +544,63 @@ static ALuint ALSAProc(ALvoid *ptr)
static ALuint ALSANoMMapProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
alsa_data *data = (alsa_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
alsa_data *data = (alsa_data*)Device->ExtraData;
snd_pcm_uframes_t update_size, num_updates;
snd_pcm_sframes_t avail;
char *WritePtr;
int err;
SetRTPriority();
update_size = Device->UpdateSize;
num_updates = Device->NumUpdates;
while(!data->killNow)
{
int state = verify_state(data->pcmHandle);
if(state < 0)
{
ERR("Invalid state detected: %s\n", snd_strerror(state));
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
avail = snd_pcm_avail_update(data->pcmHandle);
if(avail < 0)
{
ERR("available update failed: %s\n", snd_strerror(avail));
continue;
}
if((snd_pcm_uframes_t)avail > update_size*num_updates)
{
WARN("available samples exceeds the buffer size\n");
snd_pcm_reset(data->pcmHandle);
continue;
}
if((snd_pcm_uframes_t)avail < update_size)
{
if(state != SND_PCM_STATE_RUNNING)
{
err = snd_pcm_start(data->pcmHandle);
if(err < 0)
{
ERR("start failed: %s\n", snd_strerror(err));
continue;
}
}
if(snd_pcm_wait(data->pcmHandle, 1000) == 0)
ERR("Wait timeout... buffer size too low?\n");
continue;
}
ALCdevice_Lock(Device);
WritePtr = data->buffer;
avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1);
aluMixData(pDevice, WritePtr, avail);
avail = snd_pcm_bytes_to_frames(data->pcmHandle, data->size);
aluMixData(Device, WritePtr, avail);
while(avail > 0)
{
@@ -571,6 +631,7 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
break;
}
}
ALCdevice_Unlock(Device);
}
return 0;
@@ -609,11 +670,6 @@ static ALCenum alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
data = (alsa_data*)calloc(1, sizeof(alsa_data));
err = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(err >= 0)
{
err = snd_pcm_nonblock(data->pcmHandle, 0);
if(err < 0) snd_pcm_close(data->pcmHandle);
}
if(err < 0)
{
free(data);
@@ -621,7 +677,10 @@ static ALCenum alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
return ALC_OUT_OF_MEMORY;
}
device->szDeviceName = strdup(deviceName);
/* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
snd_config_update_free_global();
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -688,11 +747,7 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
/* set interleaved access */
if(!allowmmap || snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0)
{
if(periods > 2)
{
periods--;
bufferLen = periodLen * periods;
}
/* No mmap */
CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED));
}
/* test and set format (implicitly sets sample bits) */
@@ -750,9 +805,11 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
ERR("Failed to disable ALSA resampler\n");
CHECK(snd_pcm_hw_params_set_rate_near(data->pcmHandle, hp, &rate, NULL));
/* set buffer time (implicitly constrains period/buffer parameters) */
CHECK(snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, hp, &bufferLen, NULL));
if(snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, hp, &bufferLen, NULL) < 0)
ERR("snd_pcm_hw_params_set_buffer_time_near failed: %s\n", snd_strerror(err));
/* set period time (implicitly sets buffer size/bytes/time and period size/bytes) */
CHECK(snd_pcm_hw_params_set_period_time_near(data->pcmHandle, hp, &periodLen, NULL));
if(snd_pcm_hw_params_set_period_time_near(data->pcmHandle, hp, &periodLen, NULL) < 0)
ERR("snd_pcm_hw_params_set_period_time_near failed: %s\n", snd_strerror(err));
/* install and prepare hardware configuration */
CHECK(snd_pcm_hw_params(data->pcmHandle, hp));
/* retrieve configuration info */
@@ -772,12 +829,7 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
snd_pcm_sw_params_free(sp);
sp = NULL;
/* Increase periods by one, since the temp buffer counts as an extra
* period */
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
device->NumUpdates = periods+1;
else
device->NumUpdates = periods;
device->NumUpdates = periods;
device->UpdateSize = periodSizeInFrames;
device->Frequency = rate;
@@ -862,7 +914,7 @@ static void alsa_stop_playback(ALCdevice *device)
}
static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
static ALCenum alsa_open_capture(ALCdevice *Device, const ALCchar *deviceName)
{
const char *driver = NULL;
snd_pcm_hw_params_t *hp;
@@ -908,8 +960,11 @@ static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
return ALC_INVALID_VALUE;
}
/* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
snd_config_update_free_global();
format = -1;
switch(pDevice->FmtType)
switch(Device->FmtType)
{
case DevFmtByte:
format = SND_PCM_FORMAT_S8;
@@ -935,9 +990,9 @@ static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
}
funcerr = NULL;
bufferSizeInFrames = maxu(pDevice->UpdateSize*pDevice->NumUpdates,
100*pDevice->Frequency/1000);
periodSizeInFrames = minu(bufferSizeInFrames, 25*pDevice->Frequency/1000);
bufferSizeInFrames = maxu(Device->UpdateSize*Device->NumUpdates,
100*Device->Frequency/1000);
periodSizeInFrames = minu(bufferSizeInFrames, 25*Device->Frequency/1000);
snd_pcm_hw_params_malloc(&hp);
#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
@@ -947,9 +1002,9 @@ static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
/* set format (implicitly sets sample bits) */
CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format));
/* set channels (implicitly sets frame bits) */
CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(pDevice->FmtChans)));
CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(Device->FmtChans)));
/* set rate (implicitly constrains period/buffer parameters) */
CHECK(snd_pcm_hw_params_set_rate(data->pcmHandle, hp, pDevice->Frequency, 0));
CHECK(snd_pcm_hw_params_set_rate(data->pcmHandle, hp, Device->Frequency, 0));
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
if(snd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, hp, &bufferSizeInFrames) < 0)
{
@@ -969,8 +1024,8 @@ static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
if(needring)
{
data->ring = CreateRingBuffer(FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType),
pDevice->UpdateSize*pDevice->NumUpdates);
data->ring = CreateRingBuffer(FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType),
Device->UpdateSize*Device->NumUpdates);
if(!data->ring)
{
ERR("ring buffer create failed\n");
@@ -986,9 +1041,9 @@ static ALCenum alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
}
}
pDevice->szDeviceName = strdup(deviceName);
Device->DeviceName = strdup(deviceName);
pDevice->ExtraData = data;
Device->ExtraData = data;
return ALC_NO_ERROR;
error:
@@ -1001,20 +1056,20 @@ error2:
snd_pcm_close(data->pcmHandle);
free(data);
pDevice->ExtraData = NULL;
Device->ExtraData = NULL;
return ALC_INVALID_VALUE;
}
static void alsa_close_capture(ALCdevice *pDevice)
static void alsa_close_capture(ALCdevice *Device)
{
alsa_data *data = (alsa_data*)pDevice->ExtraData;
alsa_data *data = (alsa_data*)Device->ExtraData;
snd_pcm_close(data->pcmHandle);
DestroyRingBuffer(data->ring);
free(data->buffer);
free(data);
pDevice->ExtraData = NULL;
Device->ExtraData = NULL;
}
static void alsa_start_capture(ALCdevice *Device)
@@ -1210,6 +1265,21 @@ static void alsa_stop_capture(ALCdevice *Device)
}
static ALint64 alsa_get_latency(ALCdevice *device)
{
alsa_data *data = (alsa_data*)device->ExtraData;
snd_pcm_sframes_t delay = 0;
int err;
if((err=snd_pcm_delay(data->pcmHandle, &delay)) < 0)
{
ERR("Failed to get pcm delay: %s\n", snd_strerror(err));
return 0;
}
return maxi64((ALint64)delay*1000000000/device->Frequency, 0);
}
static const BackendFuncs alsa_funcs = {
alsa_open_playback,
alsa_close_playback,
@@ -1221,7 +1291,10 @@ static const BackendFuncs alsa_funcs = {
alsa_start_capture,
alsa_stop_capture,
alsa_capture_samples,
alsa_available_samples
alsa_available_samples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
alsa_get_latency
};
ALCboolean alc_alsa_init(BackendFuncs *func_list)
@@ -1278,7 +1351,7 @@ void alc_alsa_probe(enum DevProbe type)
allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames);
for(i = 0;i < numDevNames;++i)
AppendAllDeviceList(allDevNameMap[i].name);
AppendAllDevicesList(allDevNameMap[i].name);
break;
case CAPTURE_DEVICE_PROBE:
+20 -15
View File
@@ -25,8 +25,7 @@
#include <string.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <CoreServices/CoreServices.h>
#include <unistd.h>
@@ -181,7 +180,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -277,38 +276,41 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
/* use channel count and sample rate from the default output unit's current
* parameters, but reset everything else */
streamFormat.mFramesPerPacket = 1;
streamFormat.mFormatFlags = 0;
switch(device->FmtType)
{
case DevFmtUByte:
device->FmtType = DevFmtByte;
/* fall-through */
case DevFmtByte:
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
streamFormat.mBitsPerChannel = 8;
streamFormat.mBytesPerPacket = streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame;
break;
case DevFmtUShort:
case DevFmtFloat:
device->FmtType = DevFmtShort;
/* fall-through */
case DevFmtShort:
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
streamFormat.mBitsPerChannel = 16;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
break;
case DevFmtUInt:
device->FmtType = DevFmtInt;
/* fall-through */
case DevFmtInt:
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
streamFormat.mBitsPerChannel = 32;
break;
case DevFmtFloat:
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
streamFormat.mBitsPerChannel = 32;
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
break;
}
streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame *
streamFormat.mBitsPerChannel / 8;
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
kAudioFormatFlagsNativeEndian |
kLinearPCMFormatFlagIsPacked;
streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian |
kLinearPCMFormatFlagIsPacked;
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
if(err != noErr)
@@ -674,7 +676,10 @@ static const BackendFuncs ca_funcs = {
ca_start_capture,
ca_stop_capture,
ca_capture_samples,
ca_available_samples
ca_available_samples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_ca_init(BackendFuncs *func_list)
@@ -692,7 +697,7 @@ void alc_ca_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(ca_device);
AppendAllDevicesList(ca_device);
break;
case CAPTURE_DEVICE_PROBE:
AppendCaptureDeviceList(ca_device);
+173 -162
View File
@@ -33,8 +33,7 @@
#endif
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#ifndef DSSPEAKER_5POINT1
#define DSSPEAKER_5POINT1 6
@@ -61,11 +60,11 @@ static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA pDSEnum
typedef struct {
// DirectSound Playback Device
IDirectSound *lpDS;
IDirectSoundBuffer *DSpbuffer;
IDirectSoundBuffer *DSsbuffer;
IDirectSoundNotify *DSnotify;
HANDLE hNotifyEvent;
IDirectSound *DS;
IDirectSoundBuffer *PrimaryBuffer;
IDirectSoundBuffer *Buffer;
IDirectSoundNotify *Notifies;
HANDLE NotifyEvent;
volatile int killNow;
ALvoid *thread;
@@ -73,11 +72,11 @@ typedef struct {
typedef struct {
// DirectSound Capture Device
IDirectSoundCapture *lpDSC;
IDirectSoundCapture *DSC;
IDirectSoundCaptureBuffer *DSCbuffer;
DWORD dwBufferBytes;
DWORD dwCursor;
RingBuffer *pRing;
DWORD BufferBytes;
DWORD Cursor;
RingBuffer *Ring;
} DSoundCaptureData;
@@ -224,8 +223,8 @@ static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR d
static ALuint DSoundPlaybackProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
DSoundPlaybackData *pData = (DSoundPlaybackData*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData;
DSBCAPS DSBCaps;
DWORD LastCursor = 0;
DWORD PlayCursor;
@@ -241,39 +240,43 @@ static ALuint DSoundPlaybackProc(ALvoid *ptr)
memset(&DSBCaps, 0, sizeof(DSBCaps));
DSBCaps.dwSize = sizeof(DSBCaps);
err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps);
if(FAILED(err))
{
ERR("Failed to get buffer caps: 0x%lx\n", err);
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
return 1;
}
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
FragSize = pDevice->UpdateSize * FrameSize;
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
FragSize = Device->UpdateSize * FrameSize;
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
while(!pData->killNow)
IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL);
while(!data->killNow)
{
// Get current play cursor
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL);
avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
if(avail < FragSize)
{
if(!Playing)
{
err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING);
if(FAILED(err))
{
ERR("Failed to play buffer: 0x%lx\n", err);
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
return 1;
}
Playing = TRUE;
}
avail = WaitForSingleObjectEx(pData->hNotifyEvent, 2000, FALSE);
avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
if(avail != WAIT_OBJECT_0)
ERR("WaitForSingleObjectEx error: 0x%lx\n", avail);
continue;
@@ -283,18 +286,18 @@ static ALuint DSoundPlaybackProc(ALvoid *ptr)
// Lock output buffer
WriteCnt1 = 0;
WriteCnt2 = 0;
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
// If the buffer is lost, restore it and lock
if(err == DSERR_BUFFERLOST)
{
WARN("Buffer lost, restoring...\n");
err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
err = IDirectSoundBuffer_Restore(data->Buffer);
if(SUCCEEDED(err))
{
Playing = FALSE;
LastCursor = 0;
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
}
}
@@ -302,16 +305,18 @@ static ALuint DSoundPlaybackProc(ALvoid *ptr)
if(SUCCEEDED(err))
{
// If we have an active context, mix data directly into output buffer otherwise fill with silence
aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize);
aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize);
aluMixData(Device, WritePtr1, WriteCnt1/FrameSize);
aluMixData(Device, WritePtr2, WriteCnt2/FrameSize);
// Unlock output buffer only when successfully locked
IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
}
else
{
ERR("Buffer lock error: %#lx\n", err);
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
return 1;
}
@@ -325,7 +330,7 @@ static ALuint DSoundPlaybackProc(ALvoid *ptr)
static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
{
DSoundPlaybackData *pData = NULL;
DSoundPlaybackData *data = NULL;
LPGUID guid = NULL;
HRESULT hr;
@@ -358,59 +363,59 @@ static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
}
//Initialise requested device
pData = calloc(1, sizeof(DSoundPlaybackData));
if(!pData)
data = calloc(1, sizeof(DSoundPlaybackData));
if(!data)
return ALC_OUT_OF_MEMORY;
hr = DS_OK;
pData->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(pData->hNotifyEvent == NULL)
data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(data->NotifyEvent == NULL)
hr = E_FAIL;
//DirectSound Init code
if(SUCCEEDED(hr))
hr = DirectSoundCreate(guid, &pData->lpDS, NULL);
hr = DirectSoundCreate(guid, &data->DS, NULL);
if(SUCCEEDED(hr))
hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
hr = IDirectSound_SetCooperativeLevel(data->DS, GetForegroundWindow(), DSSCL_PRIORITY);
if(FAILED(hr))
{
if(pData->lpDS)
IDirectSound_Release(pData->lpDS);
if(pData->hNotifyEvent)
CloseHandle(pData->hNotifyEvent);
free(pData);
if(data->DS)
IDirectSound_Release(data->DS);
if(data->NotifyEvent)
CloseHandle(data->NotifyEvent);
free(data);
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->ExtraData = pData;
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
static void DSoundClosePlayback(ALCdevice *device)
{
DSoundPlaybackData *pData = device->ExtraData;
DSoundPlaybackData *data = device->ExtraData;
if(pData->DSnotify)
IDirectSoundNotify_Release(pData->DSnotify);
pData->DSnotify = NULL;
if(pData->DSsbuffer)
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if(pData->DSpbuffer != NULL)
IDirectSoundBuffer_Release(pData->DSpbuffer);
pData->DSpbuffer = NULL;
if(data->Notifies)
IDirectSoundNotify_Release(data->Notifies);
data->Notifies = NULL;
if(data->Buffer)
IDirectSoundBuffer_Release(data->Buffer);
data->Buffer = NULL;
if(data->PrimaryBuffer != NULL)
IDirectSoundBuffer_Release(data->PrimaryBuffer);
data->PrimaryBuffer = NULL;
IDirectSound_Release(pData->lpDS);
CloseHandle(pData->hNotifyEvent);
free(pData);
IDirectSound_Release(data->DS);
CloseHandle(data->NotifyEvent);
free(data);
device->ExtraData = NULL;
}
static ALCboolean DSoundResetPlayback(ALCdevice *device)
{
DSoundPlaybackData *pData = (DSoundPlaybackData*)device->ExtraData;
DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData;
DSBUFFERDESC DSBDescription;
WAVEFORMATEXTENSIBLE OutputType;
DWORD speakers;
@@ -418,21 +423,25 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
memset(&OutputType, 0, sizeof(OutputType));
if(pData->DSnotify)
IDirectSoundNotify_Release(pData->DSnotify);
pData->DSnotify = NULL;
if(pData->DSsbuffer)
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if(pData->DSpbuffer != NULL)
IDirectSoundBuffer_Release(pData->DSpbuffer);
pData->DSpbuffer = NULL;
if(data->Notifies)
IDirectSoundNotify_Release(data->Notifies);
data->Notifies = NULL;
if(data->Buffer)
IDirectSoundBuffer_Release(data->Buffer);
data->Buffer = NULL;
if(data->PrimaryBuffer != NULL)
IDirectSoundBuffer_Release(data->PrimaryBuffer);
data->PrimaryBuffer = NULL;
switch(device->FmtType)
{
case DevFmtByte:
device->FmtType = DevFmtUByte;
break;
case DevFmtFloat:
if((device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
break;
/* fall-through */
case DevFmtUShort:
device->FmtType = DevFmtShort;
break;
@@ -442,11 +451,10 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
case DevFmtUByte:
case DevFmtShort:
case DevFmtInt:
case DevFmtFloat:
break;
}
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers);
if(SUCCEEDED(hr))
{
if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
@@ -539,21 +547,21 @@ retry_open:
else
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
if(pData->DSpbuffer)
IDirectSoundBuffer_Release(pData->DSpbuffer);
pData->DSpbuffer = NULL;
if(data->PrimaryBuffer)
IDirectSoundBuffer_Release(data->PrimaryBuffer);
data->PrimaryBuffer = NULL;
}
else
{
if(SUCCEEDED(hr))
if(SUCCEEDED(hr) && !data->PrimaryBuffer)
{
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL);
hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL);
}
if(SUCCEEDED(hr))
hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format);
hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format);
}
if(SUCCEEDED(hr))
@@ -571,7 +579,7 @@ retry_open:
DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates *
OutputType.Format.nBlockAlign;
DSBDescription.lpwfxFormat=&OutputType.Format;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL);
if(FAILED(hr) && device->FmtType == DevFmtFloat)
{
device->FmtType = DevFmtShort;
@@ -581,7 +589,7 @@ retry_open:
if(SUCCEEDED(hr))
{
hr = IDirectSoundBuffer_QueryInterface(pData->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&pData->DSnotify);
hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies);
if(SUCCEEDED(hr))
{
DSBPOSITIONNOTIFY notifies[MAX_UPDATES];
@@ -591,28 +599,28 @@ retry_open:
{
notifies[i].dwOffset = i * device->UpdateSize *
OutputType.Format.nBlockAlign;
notifies[i].hEventNotify = pData->hNotifyEvent;
notifies[i].hEventNotify = data->NotifyEvent;
}
if(IDirectSoundNotify_SetNotificationPositions(pData->DSnotify, device->NumUpdates, notifies) != DS_OK)
if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK)
hr = E_FAIL;
}
}
if(FAILED(hr))
{
if(pData->DSnotify != NULL)
IDirectSoundNotify_Release(pData->DSnotify);
pData->DSnotify = NULL;
if(pData->DSsbuffer != NULL)
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if(pData->DSpbuffer != NULL)
IDirectSoundBuffer_Release(pData->DSpbuffer);
pData->DSpbuffer = NULL;
if(data->Notifies != NULL)
IDirectSoundNotify_Release(data->Notifies);
data->Notifies = NULL;
if(data->Buffer != NULL)
IDirectSoundBuffer_Release(data->Buffer);
data->Buffer = NULL;
if(data->PrimaryBuffer != NULL)
IDirectSoundBuffer_Release(data->PrimaryBuffer);
data->PrimaryBuffer = NULL;
return ALC_FALSE;
}
ResetEvent(pData->hNotifyEvent);
ResetEvent(data->NotifyEvent);
SetDefaultWFXChannelOrder(device);
return ALC_TRUE;
@@ -620,10 +628,10 @@ retry_open:
static ALCboolean DSoundStartPlayback(ALCdevice *device)
{
DSoundPlaybackData *pData = (DSoundPlaybackData*)device->ExtraData;
DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData;
pData->thread = StartThread(DSoundPlaybackProc, device);
if(pData->thread == NULL)
data->thread = StartThread(DSoundPlaybackProc, device);
if(data->thread == NULL)
return ALC_FALSE;
return ALC_TRUE;
@@ -631,23 +639,23 @@ static ALCboolean DSoundStartPlayback(ALCdevice *device)
static void DSoundStopPlayback(ALCdevice *device)
{
DSoundPlaybackData *pData = device->ExtraData;
DSoundPlaybackData *data = device->ExtraData;
if(!pData->thread)
if(!data->thread)
return;
pData->killNow = 1;
StopThread(pData->thread);
pData->thread = NULL;
data->killNow = 1;
StopThread(data->thread);
data->thread = NULL;
pData->killNow = 0;
IDirectSoundBuffer_Stop(pData->DSsbuffer);
data->killNow = 0;
IDirectSoundBuffer_Stop(data->Buffer);
}
static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
{
DSoundCaptureData *pData = NULL;
DSoundCaptureData *data = NULL;
WAVEFORMATEXTENSIBLE InputType;
DSCBUFFERDESC DSCBDescription;
LPGUID guid = NULL;
@@ -702,15 +710,15 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
}
//Initialise requested device
pData = calloc(1, sizeof(DSoundCaptureData));
if(!pData)
data = calloc(1, sizeof(DSoundCaptureData));
if(!data)
return ALC_OUT_OF_MEMORY;
hr = DS_OK;
//DirectSoundCapture Init code
if(SUCCEEDED(hr))
hr = DirectSoundCaptureCreate(guid, &pData->lpDSC, NULL);
hr = DirectSoundCaptureCreate(guid, &data->DSC, NULL);
if(SUCCEEDED(hr))
{
memset(&InputType, 0, sizeof(InputType));
@@ -795,12 +803,12 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
DSCBDescription.lpwfxFormat = &InputType.Format;
hr = IDirectSoundCapture_CreateCaptureBuffer(pData->lpDSC, &DSCBDescription, &pData->DSCbuffer, NULL);
hr = IDirectSoundCapture_CreateCaptureBuffer(data->DSC, &DSCBDescription, &data->DSCbuffer, NULL);
}
if(SUCCEEDED(hr))
{
pData->pRing = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
if(pData->pRing == NULL)
data->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
if(data->Ring == NULL)
hr = DSERR_OUTOFMEMORY;
}
@@ -808,55 +816,55 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
{
ERR("Device init failed: 0x%08lx\n", hr);
DestroyRingBuffer(pData->pRing);
pData->pRing = NULL;
if(pData->DSCbuffer != NULL)
IDirectSoundCaptureBuffer_Release(pData->DSCbuffer);
pData->DSCbuffer = NULL;
if(pData->lpDSC)
IDirectSoundCapture_Release(pData->lpDSC);
pData->lpDSC = NULL;
DestroyRingBuffer(data->Ring);
data->Ring = NULL;
if(data->DSCbuffer != NULL)
IDirectSoundCaptureBuffer_Release(data->DSCbuffer);
data->DSCbuffer = NULL;
if(data->DSC)
IDirectSoundCapture_Release(data->DSC);
data->DSC = NULL;
free(pData);
free(data);
return ALC_INVALID_VALUE;
}
pData->dwBufferBytes = DSCBDescription.dwBufferBytes;
data->BufferBytes = DSCBDescription.dwBufferBytes;
SetDefaultWFXChannelOrder(device);
device->szDeviceName = strdup(deviceName);
device->ExtraData = pData;
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
static void DSoundCloseCapture(ALCdevice *device)
{
DSoundCaptureData *pData = device->ExtraData;
DSoundCaptureData *data = device->ExtraData;
DestroyRingBuffer(pData->pRing);
pData->pRing = NULL;
DestroyRingBuffer(data->Ring);
data->Ring = NULL;
if(pData->DSCbuffer != NULL)
if(data->DSCbuffer != NULL)
{
IDirectSoundCaptureBuffer_Stop(pData->DSCbuffer);
IDirectSoundCaptureBuffer_Release(pData->DSCbuffer);
pData->DSCbuffer = NULL;
IDirectSoundCaptureBuffer_Stop(data->DSCbuffer);
IDirectSoundCaptureBuffer_Release(data->DSCbuffer);
data->DSCbuffer = NULL;
}
IDirectSoundCapture_Release(pData->lpDSC);
pData->lpDSC = NULL;
IDirectSoundCapture_Release(data->DSC);
data->DSC = NULL;
free(pData);
free(data);
device->ExtraData = NULL;
}
static void DSoundStartCapture(ALCdevice *device)
{
DSoundCaptureData *pData = device->ExtraData;
DSoundCaptureData *data = device->ExtraData;
HRESULT hr;
hr = IDirectSoundCaptureBuffer_Start(pData->DSCbuffer, DSCBSTART_LOOPING);
hr = IDirectSoundCaptureBuffer_Start(data->DSCbuffer, DSCBSTART_LOOPING);
if(FAILED(hr))
{
ERR("start failed: 0x%08lx\n", hr);
@@ -866,10 +874,10 @@ static void DSoundStartCapture(ALCdevice *device)
static void DSoundStopCapture(ALCdevice *device)
{
DSoundCaptureData *pData = device->ExtraData;
DSoundCaptureData *data = device->ExtraData;
HRESULT hr;
hr = IDirectSoundCaptureBuffer_Stop(pData->DSCbuffer);
hr = IDirectSoundCaptureBuffer_Stop(data->DSCbuffer);
if(FAILED(hr))
{
ERR("stop failed: 0x%08lx\n", hr);
@@ -877,61 +885,61 @@ static void DSoundStopCapture(ALCdevice *device)
}
}
static ALCenum DSoundCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
static ALCenum DSoundCaptureSamples(ALCdevice *Device, ALCvoid *pBuffer, ALCuint lSamples)
{
DSoundCaptureData *pData = pDevice->ExtraData;
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
DSoundCaptureData *data = Device->ExtraData;
ReadRingBuffer(data->Ring, pBuffer, lSamples);
return ALC_NO_ERROR;
}
static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
static ALCuint DSoundAvailableSamples(ALCdevice *Device)
{
DSoundCaptureData *pData = pDevice->ExtraData;
DWORD dwRead, dwCursor, dwBufferBytes, dwNumBytes;
void *pvAudio1, *pvAudio2;
DWORD dwAudioBytes1, dwAudioBytes2;
DSoundCaptureData *data = Device->ExtraData;
DWORD ReadCursor, LastCursor, BufferBytes, NumBytes;
VOID *ReadPtr1, *ReadPtr2;
DWORD ReadCnt1, ReadCnt2;
DWORD FrameSize;
HRESULT hr;
if(!pDevice->Connected)
if(!Device->Connected)
goto done;
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
dwBufferBytes = pData->dwBufferBytes;
dwCursor = pData->dwCursor;
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
BufferBytes = data->BufferBytes;
LastCursor = data->Cursor;
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(pData->DSCbuffer, NULL, &dwRead);
hr = IDirectSoundCaptureBuffer_GetCurrentPosition(data->DSCbuffer, NULL, &ReadCursor);
if(SUCCEEDED(hr))
{
dwNumBytes = (dwBufferBytes + dwRead - dwCursor) % dwBufferBytes;
if(dwNumBytes == 0)
NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes;
if(NumBytes == 0)
goto done;
hr = IDirectSoundCaptureBuffer_Lock(pData->DSCbuffer,
dwCursor, dwNumBytes,
&pvAudio1, &dwAudioBytes1,
&pvAudio2, &dwAudioBytes2, 0);
hr = IDirectSoundCaptureBuffer_Lock(data->DSCbuffer, LastCursor, NumBytes,
&ReadPtr1, &ReadCnt1,
&ReadPtr2, &ReadCnt2, 0);
}
if(SUCCEEDED(hr))
{
WriteRingBuffer(pData->pRing, pvAudio1, dwAudioBytes1/FrameSize);
if(pvAudio2 != NULL)
WriteRingBuffer(pData->pRing, pvAudio2, dwAudioBytes2/FrameSize);
hr = IDirectSoundCaptureBuffer_Unlock(pData->DSCbuffer,
pvAudio1, dwAudioBytes1,
pvAudio2, dwAudioBytes2);
pData->dwCursor = (dwCursor + dwAudioBytes1 + dwAudioBytes2) % dwBufferBytes;
WriteRingBuffer(data->Ring, ReadPtr1, ReadCnt1/FrameSize);
if(ReadPtr2 != NULL)
WriteRingBuffer(data->Ring, ReadPtr2, ReadCnt2/FrameSize);
hr = IDirectSoundCaptureBuffer_Unlock(data->DSCbuffer,
ReadPtr1, ReadCnt1,
ReadPtr2, ReadCnt2);
data->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
}
if(FAILED(hr))
{
ERR("update failed: 0x%08lx\n", hr);
aluHandleDisconnect(pDevice);
aluHandleDisconnect(Device);
}
done:
return RingBufferSize(pData->pRing);
return RingBufferSize(data->Ring);
}
static const BackendFuncs DSoundFuncs = {
DSoundOpenPlayback,
DSoundClosePlayback,
@@ -943,7 +951,10 @@ static const BackendFuncs DSoundFuncs = {
DSoundStartCapture,
DSoundStopCapture,
DSoundCaptureSamples,
DSoundAvailableSamples
DSoundAvailableSamples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
@@ -996,7 +1007,7 @@ void alcDSoundProbe(enum DevProbe type)
else
{
for(i = 0;i < NumPlaybackDevices;i++)
AppendAllDeviceList(PlaybackDeviceList[i].name);
AppendAllDevicesList(PlaybackDeviceList[i].name);
}
break;
+8 -4
View File
@@ -21,14 +21,14 @@
#include "config.h"
#include <stdlib.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
static ALCenum loopback_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
return ALC_NO_ERROR;
}
@@ -54,6 +54,7 @@ static void loopback_stop_playback(ALCdevice *device)
(void)device;
}
static const BackendFuncs loopback_funcs = {
loopback_open_playback,
loopback_close_playback,
@@ -65,7 +66,10 @@ static const BackendFuncs loopback_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_loopback_init(BackendFuncs *func_list)
+43 -25
View File
@@ -28,6 +28,7 @@
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <cguid.h>
#include <devpropdef.h>
#include <mmreg.h>
#include <propsys.h>
#include <propkey.h>
@@ -38,13 +39,14 @@
#endif
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
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);
DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
#define MONO SPEAKER_FRONT_CENTER
#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
@@ -60,10 +62,12 @@ typedef struct {
IMMDevice *mmdev;
IAudioClient *client;
IAudioRenderClient *render;
HANDLE hNotifyEvent;
HANDLE NotifyEvent;
HANDLE MsgEvent;
volatile UINT32 Padding;
volatile int killNow;
ALvoid *thread;
} MMDevApiData;
@@ -225,37 +229,34 @@ static ALuint MMDevApiProc(ALvoid *ptr)
if(FAILED(hr))
{
ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
ALCdevice_Lock(device);
aluHandleDisconnect(device);
return 0;
}
hr = IAudioClient_GetBufferSize(data->client, &buffer_len);
if(FAILED(hr))
{
ERR("Failed to get audio buffer size: 0x%08lx\n", hr);
aluHandleDisconnect(device);
CoUninitialize();
ALCdevice_Unlock(device);
return 0;
}
SetRTPriority();
update_size = device->UpdateSize;
buffer_len = update_size * device->NumUpdates;
while(!data->killNow)
{
hr = IAudioClient_GetCurrentPadding(data->client, &written);
if(FAILED(hr))
{
ERR("Failed to get padding: 0x%08lx\n", hr);
ALCdevice_Lock(device);
aluHandleDisconnect(device);
ALCdevice_Unlock(device);
break;
}
data->Padding = written;
len = buffer_len - written;
if(len < update_size)
{
DWORD res;
res = WaitForSingleObjectEx(data->hNotifyEvent, 2000, FALSE);
res = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
if(res != WAIT_OBJECT_0)
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
continue;
@@ -265,16 +266,22 @@ static ALuint MMDevApiProc(ALvoid *ptr)
hr = IAudioRenderClient_GetBuffer(data->render, len, &buffer);
if(SUCCEEDED(hr))
{
ALCdevice_Lock(device);
aluMixData(device, buffer, len);
data->Padding = written + len;
ALCdevice_Unlock(device);
hr = IAudioRenderClient_ReleaseBuffer(data->render, len, 0);
}
if(FAILED(hr))
{
ERR("Failed to buffer data: 0x%08lx\n", hr);
ALCdevice_Lock(device);
aluHandleDisconnect(device);
ALCdevice_Unlock(device);
break;
}
}
data->Padding = 0;
CoUninitialize();
return 0;
@@ -622,7 +629,7 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
if(SUCCEEDED(hr))
{
data->client = ptr;
device->szDeviceName = get_device_name(data->mmdev);
device->DeviceName = get_device_name(data->mmdev);
}
if(FAILED(hr))
@@ -651,8 +658,8 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
device = (ALCdevice*)msg.lParam;
data = device->ExtraData;
ResetEvent(data->hNotifyEvent);
hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent);
ResetEvent(data->NotifyEvent);
hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent);
if(FAILED(hr))
ERR("Failed to set event handle: 0x%08lx\n", hr);
else
@@ -820,9 +827,9 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
device->ExtraData = data;
hr = S_OK;
data->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
data->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(data->hNotifyEvent == NULL || data->MsgEvent == NULL)
if(data->NotifyEvent == NULL || data->MsgEvent == NULL)
hr = E_FAIL;
if(SUCCEEDED(hr))
@@ -862,9 +869,9 @@ static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName
if(FAILED(hr))
{
if(data->hNotifyEvent != NULL)
CloseHandle(data->hNotifyEvent);
data->hNotifyEvent = NULL;
if(data->NotifyEvent != NULL)
CloseHandle(data->NotifyEvent);
data->NotifyEvent = NULL;
if(data->MsgEvent != NULL)
CloseHandle(data->MsgEvent);
data->MsgEvent = NULL;
@@ -890,8 +897,8 @@ static void MMDevApiClosePlayback(ALCdevice *device)
CloseHandle(data->MsgEvent);
data->MsgEvent = NULL;
CloseHandle(data->hNotifyEvent);
data->hNotifyEvent = NULL;
CloseHandle(data->NotifyEvent);
data->NotifyEvent = NULL;
free(data->devid);
data->devid = NULL;
@@ -934,6 +941,14 @@ static void MMDevApiStopPlayback(ALCdevice *device)
}
static ALint64 MMDevApiGetLatency(ALCdevice *device)
{
MMDevApiData *data = device->ExtraData;
return (ALint64)data->Padding * 1000000000 / device->Frequency;
}
static const BackendFuncs MMDevApiFuncs = {
MMDevApiOpenPlayback,
MMDevApiClosePlayback,
@@ -945,7 +960,10 @@ static const BackendFuncs MMDevApiFuncs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
MMDevApiGetLatency
};
@@ -1007,7 +1025,7 @@ void alcMMDevApiProbe(enum DevProbe type)
for(i = 0;i < NumPlaybackDevices;i++)
{
if(PlaybackDeviceList[i].name)
AppendAllDeviceList(PlaybackDeviceList[i].name);
AppendAllDevicesList(PlaybackDeviceList[i].name);
}
}
break;
+11 -5
View File
@@ -21,9 +21,12 @@
#include "config.h"
#include <stdlib.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
typedef struct {
@@ -84,7 +87,7 @@ static ALCenum null_open_playback(ALCdevice *device, const ALCchar *deviceName)
data = (null_data*)calloc(1, sizeof(*data));
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -140,7 +143,10 @@ static const BackendFuncs null_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_null_init(BackendFuncs *func_list)
@@ -158,7 +164,7 @@ void alc_null_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(nullDevice);
AppendAllDevicesList(nullDevice);
break;
case CAPTURE_DEVICE_PROBE:
break;
+8 -5
View File
@@ -22,9 +22,9 @@
#include "config.h"
#include <stdlib.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <SLES/OpenSLES.h>
@@ -231,7 +231,7 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName
return ALC_INVALID_VALUE;
}
Device->szDeviceName = strdup(deviceName);
Device->DeviceName = strdup(deviceName);
Device->ExtraData = data;
return ALC_NO_ERROR;
@@ -412,7 +412,10 @@ static const BackendFuncs opensl_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
@@ -431,7 +434,7 @@ void alc_opensl_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(opensl_device);
AppendAllDevicesList(opensl_device);
break;
case CAPTURE_DEVICE_PROBE:
break;
+32 -25
View File
@@ -30,9 +30,9 @@
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <sys/soundcard.h>
@@ -79,21 +79,21 @@ static int log2i(ALCuint x)
static ALuint OSSProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
oss_data *data = (oss_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
oss_data *data = (oss_data*)Device->ExtraData;
ALint frameSize;
ssize_t wrote;
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
while(!data->killNow && pDevice->Connected)
while(!data->killNow && Device->Connected)
{
ALint len = data->data_size;
ALubyte *WritePtr = data->mix_data;
aluMixData(pDevice, WritePtr, len/frameSize);
aluMixData(Device, WritePtr, len/frameSize);
while(len > 0 && !data->killNow)
{
wrote = write(data->fd, WritePtr, len);
@@ -102,7 +102,9 @@ static ALuint OSSProc(ALvoid *ptr)
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
{
ERR("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
@@ -120,14 +122,14 @@ static ALuint OSSProc(ALvoid *ptr)
static ALuint OSSCaptureProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
oss_data *data = (oss_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
oss_data *data = (oss_data*)Device->ExtraData;
int frameSize;
int amt;
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
while(!data->killNow)
{
@@ -135,7 +137,9 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
if(amt < 0)
{
ERR("read failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
if(amt == 0)
@@ -170,7 +174,7 @@ static ALCenum oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -431,7 +435,7 @@ static ALCenum oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
return ALC_OUT_OF_MEMORY;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
return ALC_NO_ERROR;
}
@@ -450,28 +454,28 @@ static void oss_close_capture(ALCdevice *device)
device->ExtraData = NULL;
}
static void oss_start_capture(ALCdevice *pDevice)
static void oss_start_capture(ALCdevice *Device)
{
oss_data *data = (oss_data*)pDevice->ExtraData;
oss_data *data = (oss_data*)Device->ExtraData;
data->doCapture = 1;
}
static void oss_stop_capture(ALCdevice *pDevice)
static void oss_stop_capture(ALCdevice *Device)
{
oss_data *data = (oss_data*)pDevice->ExtraData;
oss_data *data = (oss_data*)Device->ExtraData;
data->doCapture = 0;
}
static ALCenum oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
static ALCenum oss_capture_samples(ALCdevice *Device, ALCvoid *pBuffer, ALCuint lSamples)
{
oss_data *data = (oss_data*)pDevice->ExtraData;
oss_data *data = (oss_data*)Device->ExtraData;
ReadRingBuffer(data->ring, pBuffer, lSamples);
return ALC_NO_ERROR;
}
static ALCuint oss_available_samples(ALCdevice *pDevice)
static ALCuint oss_available_samples(ALCdevice *Device)
{
oss_data *data = (oss_data*)pDevice->ExtraData;
oss_data *data = (oss_data*)Device->ExtraData;
return RingBufferSize(data->ring);
}
@@ -487,7 +491,10 @@ static const BackendFuncs oss_funcs = {
oss_start_capture,
oss_stop_capture,
oss_capture_samples,
oss_available_samples
oss_available_samples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_oss_init(BackendFuncs *func_list)
@@ -511,9 +518,9 @@ void alc_oss_probe(enum DevProbe type)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(oss_device, &buf) == 0)
if(stat(oss_driver, &buf) == 0)
#endif
AppendAllDeviceList(oss_device);
AppendAllDevicesList(oss_device);
}
break;
+9 -6
View File
@@ -23,9 +23,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <portaudio.h>
@@ -219,7 +219,7 @@ retry_open:
}
device->ExtraData = data;
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
return ALC_NO_ERROR;
}
@@ -361,7 +361,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
goto error;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
@@ -430,7 +430,10 @@ static const BackendFuncs pa_funcs = {
pa_start_capture,
pa_stop_capture,
pa_capture_samples,
pa_available_samples
pa_available_samples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_pa_init(BackendFuncs *func_list)
@@ -460,7 +463,7 @@ void alc_pa_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(pa_device);
AppendAllDevicesList(pa_device);
break;
case CAPTURE_DEVICE_PROBE:
AppendCaptureDeviceList(pa_device);
+106 -46
View File
@@ -21,7 +21,10 @@
#include "config.h"
#include <string.h>
#include "alMain.h"
#include "alu.h"
#include <pulse/pulseaudio.h>
@@ -65,6 +68,7 @@ MAKE_FUNC(pa_stream_is_corked);
MAKE_FUNC(pa_stream_cork);
MAKE_FUNC(pa_stream_is_suspended);
MAKE_FUNC(pa_stream_get_device_name);
MAKE_FUNC(pa_stream_get_latency);
MAKE_FUNC(pa_path_get_filename);
MAKE_FUNC(pa_get_binary_name);
MAKE_FUNC(pa_threaded_mainloop_free);
@@ -137,6 +141,7 @@ MAKE_FUNC(pa_stream_begin_write);
#define pa_stream_cork ppa_stream_cork
#define pa_stream_is_suspended ppa_stream_is_suspended
#define pa_stream_get_device_name ppa_stream_get_device_name
#define pa_stream_get_latency ppa_stream_get_latency
#define pa_path_get_filename ppa_path_get_filename
#define pa_get_binary_name ppa_get_binary_name
#define pa_threaded_mainloop_free ppa_threaded_mainloop_free
@@ -272,6 +277,7 @@ static ALCboolean pulse_load(void)
LOAD_FUNC(pa_stream_cork);
LOAD_FUNC(pa_stream_is_suspended);
LOAD_FUNC(pa_stream_get_device_name);
LOAD_FUNC(pa_stream_get_latency);
LOAD_FUNC(pa_path_get_filename);
LOAD_FUNC(pa_get_binary_name);
LOAD_FUNC(pa_threaded_mainloop_free);
@@ -525,8 +531,8 @@ static void sink_name_callback(pa_context *context, const pa_sink_info *info, in
return;
}
free(device->szDeviceName);
device->szDeviceName = strdup(info->description);
free(device->DeviceName);
device->DeviceName = strdup(info->description);
}
static void source_name_callback(pa_context *context, const pa_source_info *info, int eol, void *pdata)
@@ -541,8 +547,21 @@ static void source_name_callback(pa_context *context, const pa_source_info *info
return;
}
free(device->szDeviceName);
device->szDeviceName = strdup(info->description);
free(device->DeviceName);
device->DeviceName = strdup(info->description);
}
static void stream_moved_callback(pa_stream *stream, void *pdata)
{
ALCdevice *device = pdata;
pulse_data *data = device->ExtraData;
(void)stream;
free(data->device_name);
data->device_name = strdup(pa_stream_get_device_name(data->stream));
TRACE("Stream moved to %s\n", data->device_name);
}
@@ -674,14 +693,15 @@ static pa_stream *connect_record_stream(const char *device_name,
}
#define WAIT_FOR_OPERATION(x, l) do { \
pa_threaded_mainloop *_l = (l); \
pa_operation *_o = (x); \
if(!_o) break; \
while(pa_operation_get_state(_o) == PA_OPERATION_RUNNING) \
pa_threaded_mainloop_wait(_l); \
pa_operation_unref(_o); \
} while(0)
static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop)
{
if(op)
{
while(pa_operation_get_state(op) == PA_OPERATION_RUNNING)
pa_threaded_mainloop_wait(loop);
pa_operation_unref(op);
}
}
static void probe_devices(ALboolean capture)
@@ -722,7 +742,7 @@ static void probe_devices(ALboolean capture)
if(stream)
{
o = pa_context_get_sink_info_by_name(context, pa_stream_get_device_name(stream), sink_device_callback, loop);
WAIT_FOR_OPERATION(o, loop);
wait_for_operation(o, loop);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
@@ -749,7 +769,7 @@ static void probe_devices(ALboolean capture)
if(stream)
{
o = pa_context_get_source_info_by_name(context, pa_stream_get_device_name(stream), source_device_callback, loop);
WAIT_FOR_OPERATION(o, loop);
wait_for_operation(o, loop);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
@@ -758,7 +778,7 @@ static void probe_devices(ALboolean capture)
o = pa_context_get_source_info_list(context, source_device_callback, loop);
}
WAIT_FOR_OPERATION(o, loop);
wait_for_operation(o, loop);
pa_context_disconnect(context);
pa_context_unref(context);
@@ -822,11 +842,9 @@ static ALuint PulseProc(ALvoid *param)
buf = pa_xmalloc(newlen);
free_func = pa_xfree;
}
pa_threaded_mainloop_unlock(data->loop);
aluMixData(Device, buf, newlen/frame_size);
pa_threaded_mainloop_lock(data->loop);
pa_stream_write(data->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
len -= newlen;
}
@@ -887,6 +905,7 @@ static void pulse_close(ALCdevice *device)
if(data->stream)
{
pa_stream_set_moved_callback(data->stream, NULL, NULL);
#if PA_CHECK_VERSION(0,9,15)
if(pa_stream_set_buffer_attr_callback)
pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
@@ -944,7 +963,9 @@ static ALCenum pulse_open_playback(ALCdevice *device, const ALCchar *device_name
pa_threaded_mainloop_lock(data->loop);
flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;
PA_STREAM_FIX_CHANNELS;
if(!GetConfigValueBool("pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
spec.format = PA_SAMPLE_S16NE;
spec.rate = 44100;
@@ -962,7 +983,9 @@ static ALCenum pulse_open_playback(ALCdevice *device, const ALCchar *device_name
data->device_name = strdup(pa_stream_get_device_name(data->stream));
o = pa_context_get_sink_info_by_name(data->context, data->device_name,
sink_name_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
wait_for_operation(o, data->loop);
pa_stream_set_moved_callback(data->stream, stream_moved_callback, device);
pa_threaded_mainloop_unlock(data->loop);
@@ -979,11 +1002,13 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
pulse_data *data = device->ExtraData;
pa_stream_flags_t flags = 0;
pa_channel_map chanmap;
ALuint len;
pa_threaded_mainloop_lock(data->loop);
if(data->stream)
{
pa_stream_set_moved_callback(data->stream, NULL, NULL);
#if PA_CHECK_VERSION(0,9,15)
if(pa_stream_set_buffer_attr_callback)
pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
@@ -997,7 +1022,7 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
{
pa_operation *o;
o = pa_context_get_sink_info_by_name(data->context, data->device_name, sink_info_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
wait_for_operation(o, data->loop);
}
if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
flags |= PA_STREAM_FIX_RATE;
@@ -1005,7 +1030,8 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
flags |= PA_STREAM_ADJUST_LATENCY;
flags |= PA_STREAM_START_CORKED;
flags |= PA_STREAM_DONT_MOVE;
if(!GetConfigValueBool("pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
switch(device->FmtType)
{
@@ -1072,28 +1098,33 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
/* Server updated our playback rate, so modify the buffer attribs
* accordingly. */
data->attr.minreq = (ALuint64)device->UpdateSize * data->spec.rate /
device->Frequency * pa_frame_size(&data->spec);
data->attr.tlength = data->attr.minreq * maxu(device->NumUpdates, 2);
data->attr.prebuf = 0;
device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates / device->Frequency *
data->spec.rate + 0.5);
data->attr.minreq = device->UpdateSize * pa_frame_size(&data->spec);
data->attr.tlength = data->attr.minreq * clampu(device->NumUpdates, 2, 16);
data->attr.maxlength = -1;
data->attr.prebuf = 0;
o = pa_stream_set_buffer_attr(data->stream, &data->attr,
stream_success_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
wait_for_operation(o, data->loop);
device->Frequency = data->spec.rate;
}
pa_stream_set_moved_callback(data->stream, stream_moved_callback, device);
#if PA_CHECK_VERSION(0,9,15)
if(pa_stream_set_buffer_attr_callback)
pa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device);
#endif
stream_buffer_attr_callback(data->stream, device);
device->NumUpdates = device->UpdateSize*device->NumUpdates /
(data->attr.minreq/pa_frame_size(&data->spec));
device->NumUpdates = maxu(device->NumUpdates, 2);
device->UpdateSize = data->attr.minreq / pa_frame_size(&data->spec);
len = data->attr.minreq / pa_frame_size(&data->spec);
if((CPUCapFlags&CPU_CAP_SSE))
len = (len+3)&~3;
device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5);
device->NumUpdates = clampu(device->NumUpdates, 2, 16);
device->UpdateSize = len;
pa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
@@ -1129,7 +1160,7 @@ static void pulse_stop_playback(ALCdevice *device)
pa_threaded_mainloop_lock(data->loop);
o = pa_stream_cork(data->stream, 1, stream_success_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
wait_for_operation(o, data->loop);
pa_threaded_mainloop_unlock(data->loop);
}
@@ -1218,8 +1249,10 @@ static ALCenum pulse_open_capture(ALCdevice *device, const ALCchar *device_name)
data->attr.fragsize = minu(samples, 50*device->Frequency/1000) *
pa_frame_size(&data->spec);
flags |= PA_STREAM_DONT_MOVE;
flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY;
if(!GetConfigValueBool("pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
data->stream = connect_record_stream(pulse_name, data->loop, data->context,
flags, &data->attr, &data->spec,
&chanmap);
@@ -1233,7 +1266,9 @@ static ALCenum pulse_open_capture(ALCdevice *device, const ALCchar *device_name)
data->device_name = strdup(pa_stream_get_device_name(data->stream));
o = pa_context_get_source_info_by_name(data->context, data->device_name,
source_name_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
wait_for_operation(o, data->loop);
pa_stream_set_moved_callback(data->stream, stream_moved_callback, device);
pa_threaded_mainloop_unlock(data->loop);
return ALC_NO_ERROR;
@@ -1253,10 +1288,8 @@ static void pulse_start_capture(ALCdevice *device)
pulse_data *data = device->ExtraData;
pa_operation *o;
pa_threaded_mainloop_lock(data->loop);
o = pa_stream_cork(data->stream, 0, stream_success_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
pa_threaded_mainloop_unlock(data->loop);
wait_for_operation(o, data->loop);
}
static void pulse_stop_capture(ALCdevice *device)
@@ -1264,10 +1297,8 @@ static void pulse_stop_capture(ALCdevice *device)
pulse_data *data = device->ExtraData;
pa_operation *o;
pa_threaded_mainloop_lock(data->loop);
o = pa_stream_cork(data->stream, 1, stream_success_callback, device);
WAIT_FOR_OPERATION(o, data->loop);
pa_threaded_mainloop_unlock(data->loop);
wait_for_operation(o, data->loop);
}
static ALCenum pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
@@ -1275,7 +1306,6 @@ static ALCenum pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint
pulse_data *data = device->ExtraData;
ALCuint todo = samples * pa_frame_size(&data->spec);
pa_threaded_mainloop_lock(data->loop);
/* Capture is done in fragment-sized chunks, so we loop until we get all
* that's available */
data->last_readable -= todo;
@@ -1320,7 +1350,6 @@ static ALCenum pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint
}
if(todo > 0)
memset(buffer, ((device->FmtType==DevFmtUByte) ? 0x80 : 0), todo);
pa_threaded_mainloop_unlock(data->loop);
return ALC_NO_ERROR;
}
@@ -1330,7 +1359,6 @@ static ALCuint pulse_available_samples(ALCdevice *device)
pulse_data *data = device->ExtraData;
size_t readable = data->cap_remain;
pa_threaded_mainloop_lock(data->loop);
if(device->Connected)
{
ssize_t got = pa_stream_readable_size(data->stream);
@@ -1342,7 +1370,6 @@ static ALCuint pulse_available_samples(ALCdevice *device)
else if((size_t)got > data->cap_len)
readable += got - data->cap_len;
}
pa_threaded_mainloop_unlock(data->loop);
if(data->last_readable < readable)
data->last_readable = readable;
@@ -1350,6 +1377,36 @@ static ALCuint pulse_available_samples(ALCdevice *device)
}
static void pulse_lock(ALCdevice *device)
{
pulse_data *data = device->ExtraData;
pa_threaded_mainloop_lock(data->loop);
}
static void pulse_unlock(ALCdevice *device)
{
pulse_data *data = device->ExtraData;
pa_threaded_mainloop_unlock(data->loop);
}
static ALint64 pulse_get_latency(ALCdevice *device)
{
pulse_data *data = device->ExtraData;
pa_usec_t latency = 0;
int neg;
if(pa_stream_get_latency(data->stream, &latency, &neg) == 0)
{
if(neg)
latency = 0;
return (ALint64)minu64(latency, MAKEU64(0x7fffffff,0xffffffff)/1000) * 1000;
}
ERR("Failed to get stream latency!\n");
return 0;
}
static const BackendFuncs pulse_funcs = {
pulse_open_playback,
pulse_close_playback,
@@ -1361,7 +1418,10 @@ static const BackendFuncs pulse_funcs = {
pulse_start_capture,
pulse_stop_capture,
pulse_capture_samples,
pulse_available_samples
pulse_available_samples,
pulse_lock,
pulse_unlock,
pulse_get_latency
};
ALCboolean alc_pulse_init(BackendFuncs *func_list)
@@ -1373,7 +1433,7 @@ ALCboolean alc_pulse_init(BackendFuncs *func_list)
pa_threaded_mainloop *loop;
pulse_ctx_flags = 0;
if(!GetConfigValueBool("pulse", "spawn-server", 0))
if(!GetConfigValueBool("pulse", "spawn-server", 1))
pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
if((loop=pa_threaded_mainloop_new()) &&
@@ -1457,7 +1517,7 @@ void alc_pulse_probe(enum DevProbe type)
probe_devices(AL_FALSE);
for(i = 0;i < numDevNames;i++)
AppendAllDeviceList(allDevNameMap[i].name);
AppendAllDevicesList(allDevNameMap[i].name);
break;
case CAPTURE_DEVICE_PROBE:
+10 -86
View File
@@ -23,9 +23,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <sndio.h>
@@ -33,84 +33,8 @@
static const ALCchar sndio_device[] = "SndIO Default";
#ifdef HAVE_DYNLOAD
static void *sndio_handle;
#define MAKE_FUNC(x) static typeof(x) * p##x
MAKE_FUNC(sio_initpar);
MAKE_FUNC(sio_open);
MAKE_FUNC(sio_close);
MAKE_FUNC(sio_setpar);
MAKE_FUNC(sio_getpar);
MAKE_FUNC(sio_getcap);
MAKE_FUNC(sio_onmove);
MAKE_FUNC(sio_write);
MAKE_FUNC(sio_read);
MAKE_FUNC(sio_start);
MAKE_FUNC(sio_stop);
MAKE_FUNC(sio_nfds);
MAKE_FUNC(sio_pollfd);
MAKE_FUNC(sio_revents);
MAKE_FUNC(sio_eof);
MAKE_FUNC(sio_setvol);
MAKE_FUNC(sio_onvol);
#define sio_initpar psio_initpar
#define sio_open psio_open
#define sio_close psio_close
#define sio_setpar psio_setpar
#define sio_getpar psio_getpar
#define sio_getcap psio_getcap
#define sio_onmove psio_onmove
#define sio_write psio_write
#define sio_read psio_read
#define sio_start psio_start
#define sio_stop psio_stop
#define sio_nfds psio_nfds
#define sio_pollfd psio_pollfd
#define sio_revents psio_revents
#define sio_eof psio_eof
#define sio_setvol psio_setvol
#define sio_onvol psio_onvol
#endif
static ALCboolean sndio_load(void)
{
#ifdef HAVE_DYNLOAD
if(!sndio_handle)
{
sndio_handle = LoadLib("libsndio.so");
if(!sndio_handle)
return ALC_FALSE;
#define LOAD_FUNC(f) do { \
p##f = GetSymbol(sndio_handle, #f); \
if(p##f == NULL) { \
CloseLib(sndio_handle); \
sndio_handle = NULL; \
return ALC_FALSE; \
} \
} while(0)
LOAD_FUNC(sio_initpar);
LOAD_FUNC(sio_open);
LOAD_FUNC(sio_close);
LOAD_FUNC(sio_setpar);
LOAD_FUNC(sio_getpar);
LOAD_FUNC(sio_getcap);
LOAD_FUNC(sio_onmove);
LOAD_FUNC(sio_write);
LOAD_FUNC(sio_read);
LOAD_FUNC(sio_start);
LOAD_FUNC(sio_stop);
LOAD_FUNC(sio_nfds);
LOAD_FUNC(sio_pollfd);
LOAD_FUNC(sio_revents);
LOAD_FUNC(sio_eof);
LOAD_FUNC(sio_setvol);
LOAD_FUNC(sio_onvol);
#undef LOAD_FUNC
}
#endif
return ALC_TRUE;
}
@@ -149,7 +73,9 @@ static ALuint sndio_proc(ALvoid *ptr)
if(wrote == 0)
{
ERR("sio_write failed\n");
ALCdevice_Lock(device);
aluHandleDisconnect(device);
ALCdevice_Unlock(device);
break;
}
@@ -183,7 +109,7 @@ static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
@@ -339,7 +265,10 @@ static const BackendFuncs sndio_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_sndio_init(BackendFuncs *func_list)
@@ -352,11 +281,6 @@ ALCboolean alc_sndio_init(BackendFuncs *func_list)
void alc_sndio_deinit(void)
{
#ifdef HAVE_DYNLOAD
if(sndio_handle)
CloseLib(sndio_handle);
sndio_handle = NULL;
#endif
}
void alc_sndio_probe(enum DevProbe type)
@@ -364,7 +288,7 @@ void alc_sndio_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(sndio_device);
AppendAllDevicesList(sndio_device);
break;
case CAPTURE_DEVICE_PROBE:
break;
+16 -11
View File
@@ -30,9 +30,9 @@
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#include <sys/audioio.h>
@@ -53,21 +53,21 @@ typedef struct {
static ALuint SolarisProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
solaris_data *data = (solaris_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
solaris_data *data = (solaris_data*)Device->ExtraData;
ALint frameSize;
int wrote;
SetRTPriority();
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
while(!data->killNow && pDevice->Connected)
while(!data->killNow && Device->Connected)
{
ALint len = data->data_size;
ALubyte *WritePtr = data->mix_data;
aluMixData(pDevice, WritePtr, len/frameSize);
aluMixData(Device, WritePtr, len/frameSize);
while(len > 0 && !data->killNow)
{
wrote = write(data->fd, WritePtr, len);
@@ -76,7 +76,9 @@ static ALuint SolarisProc(ALvoid *ptr)
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
{
ERR("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
@@ -113,7 +115,7 @@ static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceNam
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -247,7 +249,10 @@ static const BackendFuncs solaris_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_solaris_init(BackendFuncs *func_list)
@@ -272,7 +277,7 @@ void alc_solaris_probe(enum DevProbe type)
struct stat buf;
if(stat(solaris_driver, &buf) == 0)
#endif
AppendAllDeviceList(solaris_device);
AppendAllDevicesList(solaris_device);
}
break;
+32 -20
View File
@@ -23,9 +23,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
typedef struct {
@@ -81,45 +84,45 @@ static void fwrite32le(ALuint val, FILE *f)
static ALuint WaveProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
wave_data *data = (wave_data*)pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)ptr;
wave_data *data = (wave_data*)Device->ExtraData;
ALuint frameSize;
ALuint now, start;
ALuint64 avail, done;
size_t fs;
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
pDevice->Frequency / 2;
const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
Device->Frequency / 2;
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
done = 0;
start = timeGetTime();
while(!data->killNow && pDevice->Connected)
while(!data->killNow && Device->Connected)
{
now = timeGetTime();
avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
avail = (ALuint64)(now-start) * Device->Frequency / 1000;
if(avail < done)
{
/* Timer wrapped (50 days???). Add the remainder of the cycle to
* the available count and reset the number of samples done */
avail += ((ALuint64)1<<32)*pDevice->Frequency/1000 - done;
avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
done = 0;
}
if(avail-done < pDevice->UpdateSize)
if(avail-done < Device->UpdateSize)
{
Sleep(restTime);
continue;
}
while(avail-done >= pDevice->UpdateSize)
while(avail-done >= Device->UpdateSize)
{
aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
done += pDevice->UpdateSize;
aluMixData(Device, data->buffer, Device->UpdateSize);
done += Device->UpdateSize;
if(!IS_LITTLE_ENDIAN)
{
ALuint bytesize = BytesFromDevFmt(pDevice->FmtType);
ALuint bytesize = BytesFromDevFmt(Device->FmtType);
ALubyte *bytes = data->buffer;
ALuint i;
@@ -140,12 +143,17 @@ static ALuint WaveProc(ALvoid *ptr)
}
}
else
fs = fwrite(data->buffer, frameSize, pDevice->UpdateSize,
{
fs = fwrite(data->buffer, frameSize, Device->UpdateSize,
data->f);
fs = fs;
}
if(ferror(data->f))
{
ERR("Error writing to file\n");
aluHandleDisconnect(pDevice);
ALCdevice_Lock(Device);
aluHandleDisconnect(Device);
ALCdevice_Unlock(Device);
break;
}
}
@@ -178,7 +186,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
return ALC_INVALID_VALUE;
}
device->szDeviceName = strdup(deviceName);
device->DeviceName = strdup(deviceName);
device->ExtraData = data;
return ALC_NO_ERROR;
}
@@ -249,6 +257,7 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
fwrite32le(channel_masks[channels], data->f);
// 16 byte GUID, sub-type format
val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f);
val = val;
fprintf(data->f, "data");
fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close
@@ -329,7 +338,10 @@ static const BackendFuncs wave_funcs = {
NULL,
NULL,
NULL,
NULL
NULL,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alc_wave_init(BackendFuncs *func_list)
@@ -350,7 +362,7 @@ void alc_wave_probe(enum DevProbe type)
switch(type)
{
case ALL_DEVICE_PROBE:
AppendAllDeviceList(waveDevice);
AppendAllDevicesList(waveDevice);
break;
case CAPTURE_DEVICE_PROBE:
break;
+228 -231
View File
@@ -28,8 +28,7 @@
#include <mmsystem.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alu.h"
#ifndef WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
@@ -38,21 +37,21 @@
typedef struct {
// MMSYSTEM Device
volatile ALboolean bWaveShutdown;
HANDLE hWaveThreadEvent;
HANDLE hWaveThread;
DWORD ulWaveThreadID;
volatile LONG lWaveBuffersCommitted;
volatile ALboolean killNow;
HANDLE WaveThreadEvent;
HANDLE WaveThread;
DWORD WaveThreadID;
volatile LONG WaveBuffersCommitted;
WAVEHDR WaveBuffer[4];
union {
HWAVEIN In;
HWAVEOUT Out;
} hWaveHandle;
} WaveHandle;
WAVEFORMATEX wfexFormat;
WAVEFORMATEX Format;
RingBuffer *pRing;
RingBuffer *Ring;
} WinMMData;
@@ -147,19 +146,19 @@ static void ProbeCaptureDevices(void)
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)
static void CALLBACK WaveOutProc(HWAVEOUT device, UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR param2)
{
ALCdevice *pDevice = (ALCdevice*)dwInstance;
WinMMData *pData = pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)instance;
WinMMData *data = Device->ExtraData;
(void)hDevice;
(void)dwParam2;
(void)device;
(void)param2;
if(uMsg != WOM_DONE)
if(msg != WOM_DONE)
return;
InterlockedDecrement(&pData->lWaveBuffersCommitted);
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
InterlockedDecrement(&data->WaveBuffersCommitted);
PostThreadMessage(data->WaveThreadID, msg, 0, param1);
}
/*
@@ -168,15 +167,15 @@ static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance
Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its
audio data.
*/
static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
static DWORD WINAPI PlaybackThreadProc(LPVOID param)
{
ALCdevice *pDevice = (ALCdevice*)lpParameter;
WinMMData *pData = pDevice->ExtraData;
LPWAVEHDR pWaveHdr;
ALCdevice *Device = (ALCdevice*)param;
WinMMData *data = Device->ExtraData;
LPWAVEHDR WaveHdr;
ALuint FrameSize;
MSG msg;
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
SetRTPriority();
@@ -185,28 +184,26 @@ static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
if(msg.message != WOM_DONE)
continue;
if(pData->bWaveShutdown)
if(data->killNow)
{
if(pData->lWaveBuffersCommitted == 0)
if(data->WaveBuffersCommitted == 0)
break;
continue;
}
pWaveHdr = ((LPWAVEHDR)msg.lParam);
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
WaveHdr = ((LPWAVEHDR)msg.lParam);
aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength/FrameSize);
// Send buffer back to play more data
waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR));
InterlockedIncrement(&data->WaveBuffersCommitted);
}
// Signal Wave Thread completed event
if(pData->hWaveThreadEvent)
SetEvent(pData->hWaveThreadEvent);
if(data->WaveThreadEvent)
SetEvent(data->WaveThreadEvent);
ExitThread(0);
return 0;
}
@@ -216,19 +213,19 @@ static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
returns to the application (with more data)
*/
static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
static void CALLBACK WaveInProc(HWAVEIN device, UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR param2)
{
ALCdevice *pDevice = (ALCdevice*)dwInstance;
WinMMData *pData = pDevice->ExtraData;
ALCdevice *Device = (ALCdevice*)instance;
WinMMData *data = Device->ExtraData;
(void)hDevice;
(void)dwParam2;
(void)device;
(void)param2;
if(uMsg != WIM_DATA)
if(msg != WIM_DATA)
return;
InterlockedDecrement(&pData->lWaveBuffersCommitted);
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
InterlockedDecrement(&data->WaveBuffersCommitted);
PostThreadMessage(data->WaveThreadID, msg, 0, param1);
}
/*
@@ -237,15 +234,15 @@ 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.
*/
static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
static DWORD WINAPI CaptureThreadProc(LPVOID param)
{
ALCdevice *pDevice = (ALCdevice*)lpParameter;
WinMMData *pData = pDevice->ExtraData;
LPWAVEHDR pWaveHdr;
ALCdevice *Device = (ALCdevice*)param;
WinMMData *data = Device->ExtraData;
LPWAVEHDR WaveHdr;
ALuint FrameSize;
MSG msg;
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
while(GetMessage(&msg, NULL, 0, 0))
{
@@ -253,33 +250,30 @@ static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
continue;
/* Don't wait for other buffers to finish before quitting. We're
* closing so we don't need them. */
if(pData->bWaveShutdown)
if(data->killNow)
break;
pWaveHdr = ((LPWAVEHDR)msg.lParam);
WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData,
pWaveHdr->dwBytesRecorded/FrameSize);
WaveHdr = ((LPWAVEHDR)msg.lParam);
WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, WaveHdr->dwBytesRecorded/FrameSize);
// Send buffer back to capture more data
waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR));
InterlockedIncrement(&pData->lWaveBuffersCommitted);
waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR));
InterlockedIncrement(&data->WaveBuffersCommitted);
}
// Signal Wave Thread completed event
if(pData->hWaveThreadEvent)
SetEvent(pData->hWaveThreadEvent);
if(data->WaveThreadEvent)
SetEvent(data->WaveThreadEvent);
ExitThread(0);
return 0;
}
static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName)
{
WinMMData *pData = NULL;
UINT lDeviceID = 0;
WinMMData *data = NULL;
UINT DeviceID = 0;
MMRESULT res;
ALuint i = 0;
@@ -292,86 +286,86 @@ static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
if(PlaybackDeviceList[i] &&
(!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0))
{
lDeviceID = i;
DeviceID = i;
break;
}
}
if(i == NumPlaybackDevices)
return ALC_INVALID_VALUE;
pData = calloc(1, sizeof(*pData));
if(!pData)
data = calloc(1, sizeof(*data));
if(!data)
return ALC_OUT_OF_MEMORY;
pDevice->ExtraData = pData;
Device->ExtraData = data;
retry_open:
memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
if(pDevice->FmtType == DevFmtFloat)
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
if(Device->FmtType == DevFmtFloat)
{
pData->wfexFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
pData->wfexFormat.wBitsPerSample = 32;
data->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
data->Format.wBitsPerSample = 32;
}
else
{
pData->wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
if(pDevice->FmtType == DevFmtUByte || pDevice->FmtType == DevFmtByte)
pData->wfexFormat.wBitsPerSample = 8;
data->Format.wFormatTag = WAVE_FORMAT_PCM;
if(Device->FmtType == DevFmtUByte || Device->FmtType == DevFmtByte)
data->Format.wBitsPerSample = 8;
else
pData->wfexFormat.wBitsPerSample = 16;
data->Format.wBitsPerSample = 16;
}
pData->wfexFormat.nChannels = ((pDevice->FmtChans == DevFmtMono) ? 1 : 2);
pData->wfexFormat.nBlockAlign = pData->wfexFormat.wBitsPerSample *
pData->wfexFormat.nChannels / 8;
pData->wfexFormat.nSamplesPerSec = pDevice->Frequency;
pData->wfexFormat.nAvgBytesPerSec = pData->wfexFormat.nSamplesPerSec *
pData->wfexFormat.nBlockAlign;
pData->wfexFormat.cbSize = 0;
data->Format.nChannels = ((Device->FmtChans == DevFmtMono) ? 1 : 2);
data->Format.nBlockAlign = data->Format.wBitsPerSample *
data->Format.nChannels / 8;
data->Format.nSamplesPerSec = Device->Frequency;
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
data->Format.nBlockAlign;
data->Format.cbSize = 0;
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
if((res=waveOutOpen(&data->WaveHandle.Out, DeviceID, &data->Format, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
if(pDevice->FmtType == DevFmtFloat)
if(Device->FmtType == DevFmtFloat)
{
pDevice->FmtType = DevFmtShort;
Device->FmtType = DevFmtShort;
goto retry_open;
}
ERR("waveOutOpen failed: %u\n", res);
goto failure;
}
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(pData->hWaveThreadEvent == NULL)
data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(data->WaveThreadEvent == NULL)
{
ERR("CreateEvent failed: %lu\n", GetLastError());
goto failure;
}
pDevice->szDeviceName = strdup(PlaybackDeviceList[lDeviceID]);
Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]);
return ALC_NO_ERROR;
failure:
if(pData->hWaveThreadEvent)
CloseHandle(pData->hWaveThreadEvent);
if(data->WaveThreadEvent)
CloseHandle(data->WaveThreadEvent);
if(pData->hWaveHandle.Out)
waveOutClose(pData->hWaveHandle.Out);
if(data->WaveHandle.Out)
waveOutClose(data->WaveHandle.Out);
free(pData);
pDevice->ExtraData = NULL;
free(data);
Device->ExtraData = NULL;
return ALC_INVALID_VALUE;
}
static void WinMMClosePlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
WinMMData *data = (WinMMData*)device->ExtraData;
// Close the Wave device
CloseHandle(pData->hWaveThreadEvent);
pData->hWaveThreadEvent = 0;
CloseHandle(data->WaveThreadEvent);
data->WaveThreadEvent = 0;
waveOutClose(pData->hWaveHandle.Out);
pData->hWaveHandle.Out = 0;
waveOutClose(data->WaveHandle.Out);
data->WaveHandle.Out = 0;
free(pData);
free(data);
device->ExtraData = NULL;
}
@@ -380,47 +374,47 @@ static ALCboolean WinMMResetPlayback(ALCdevice *device)
WinMMData *data = (WinMMData*)device->ExtraData;
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
data->wfexFormat.nSamplesPerSec /
data->Format.nSamplesPerSec /
device->Frequency);
device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
device->NumUpdates = 4;
device->Frequency = data->wfexFormat.nSamplesPerSec;
device->Frequency = data->Format.nSamplesPerSec;
if(data->wfexFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
if(data->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
{
if(data->wfexFormat.wBitsPerSample == 32)
if(data->Format.wBitsPerSample == 32)
device->FmtType = DevFmtFloat;
else
{
ERR("Unhandled IEEE float sample depth: %d\n", data->wfexFormat.wBitsPerSample);
ERR("Unhandled IEEE float sample depth: %d\n", data->Format.wBitsPerSample);
return ALC_FALSE;
}
}
else if(data->wfexFormat.wFormatTag == WAVE_FORMAT_PCM)
else if(data->Format.wFormatTag == WAVE_FORMAT_PCM)
{
if(data->wfexFormat.wBitsPerSample == 16)
if(data->Format.wBitsPerSample == 16)
device->FmtType = DevFmtShort;
else if(data->wfexFormat.wBitsPerSample == 8)
else if(data->Format.wBitsPerSample == 8)
device->FmtType = DevFmtUByte;
else
{
ERR("Unhandled PCM sample depth: %d\n", data->wfexFormat.wBitsPerSample);
ERR("Unhandled PCM sample depth: %d\n", data->Format.wBitsPerSample);
return ALC_FALSE;
}
}
else
{
ERR("Unhandled format tag: 0x%04x\n", data->wfexFormat.wFormatTag);
ERR("Unhandled format tag: 0x%04x\n", data->Format.wFormatTag);
return ALC_FALSE;
}
if(data->wfexFormat.nChannels == 2)
if(data->Format.nChannels == 2)
device->FmtChans = DevFmtStereo;
else if(data->wfexFormat.nChannels == 1)
else if(data->Format.nChannels == 1)
device->FmtChans = DevFmtMono;
else
{
ERR("Unhandled channel count: %d\n", data->wfexFormat.nChannels);
ERR("Unhandled channel count: %d\n", data->Format.nChannels);
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
@@ -430,32 +424,32 @@ static ALCboolean WinMMResetPlayback(ALCdevice *device)
static ALCboolean WinMMStartPlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
WinMMData *data = (WinMMData*)device->ExtraData;
ALbyte *BufferData;
ALint lBufferSize;
ALint BufferSize;
ALuint i;
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID);
if(pData->hWaveThread == NULL)
data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &data->WaveThreadID);
if(data->WaveThread == NULL)
return ALC_FALSE;
pData->lWaveBuffersCommitted = 0;
data->WaveBuffersCommitted = 0;
// Create 4 Buffers
lBufferSize = device->UpdateSize*device->NumUpdates / 4;
lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
BufferSize = device->UpdateSize*device->NumUpdates / 4;
BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
BufferData = calloc(4, lBufferSize);
BufferData = calloc(4, BufferSize);
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);
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
data->WaveBuffer[i].dwBufferLength = BufferSize;
data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
(data->WaveBuffer[i-1].lpData +
data->WaveBuffer[i-1].dwBufferLength));
waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
InterlockedIncrement(&data->WaveBuffersCommitted);
}
return ALC_TRUE;
@@ -463,42 +457,42 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device)
static void WinMMStopPlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
WinMMData *data = (WinMMData*)device->ExtraData;
void *buffer = NULL;
int i;
if(pData->hWaveThread == NULL)
if(data->WaveThread == NULL)
return;
// Set flag to stop processing headers
pData->bWaveShutdown = AL_TRUE;
data->killNow = AL_TRUE;
// Wait for signal that Wave Thread has been destroyed
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
CloseHandle(pData->hWaveThread);
pData->hWaveThread = 0;
CloseHandle(data->WaveThread);
data->WaveThread = 0;
pData->bWaveShutdown = AL_FALSE;
data->killNow = AL_FALSE;
// Release the wave buffers
for(i = 0;i < 4;i++)
{
waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = pData->WaveBuffer[i].lpData;
pData->WaveBuffer[i].lpData = NULL;
waveOutUnprepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = data->WaveBuffer[i].lpData;
data->WaveBuffer[i].lpData = NULL;
}
free(buffer);
}
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
{
ALbyte *BufferData = NULL;
DWORD ulCapturedDataSize;
WinMMData *pData = NULL;
UINT lDeviceID = 0;
ALint lBufferSize;
DWORD CapturedDataSize;
WinMMData *data = NULL;
UINT DeviceID = 0;
ALint BufferSize;
MMRESULT res;
ALuint i;
@@ -511,14 +505,14 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
if(CaptureDeviceList[i] &&
(!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
{
lDeviceID = i;
DeviceID = i;
break;
}
}
if(i == NumCaptureDevices)
return ALC_INVALID_VALUE;
switch(pDevice->FmtChans)
switch(Device->FmtChans)
{
case DevFmtMono:
case DevFmtStereo:
@@ -532,7 +526,7 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
return ALC_INVALID_ENUM;
}
switch(pDevice->FmtType)
switch(Device->FmtType)
{
case DevFmtUByte:
case DevFmtShort:
@@ -546,167 +540,167 @@ static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
return ALC_INVALID_ENUM;
}
pData = calloc(1, sizeof(*pData));
if(!pData)
data = calloc(1, sizeof(*data));
if(!data)
return ALC_OUT_OF_MEMORY;
pDevice->ExtraData = pData;
Device->ExtraData = data;
memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
pData->wfexFormat.wFormatTag = ((pDevice->FmtType == DevFmtFloat) ?
WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
pData->wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
pData->wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
pData->wfexFormat.nBlockAlign = pData->wfexFormat.wBitsPerSample *
pData->wfexFormat.nChannels / 8;
pData->wfexFormat.nSamplesPerSec = pDevice->Frequency;
pData->wfexFormat.nAvgBytesPerSec = pData->wfexFormat.nSamplesPerSec *
pData->wfexFormat.nBlockAlign;
pData->wfexFormat.cbSize = 0;
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
data->Format.wFormatTag = ((Device->FmtType == DevFmtFloat) ?
WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
data->Format.nChannels = ChannelsFromDevFmt(Device->FmtChans);
data->Format.wBitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
data->Format.nBlockAlign = data->Format.wBitsPerSample *
data->Format.nChannels / 8;
data->Format.nSamplesPerSec = Device->Frequency;
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
data->Format.nBlockAlign;
data->Format.cbSize = 0;
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
if((res=waveInOpen(&data->WaveHandle.In, DeviceID, &data->Format, (DWORD_PTR)&WaveInProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
ERR("waveInOpen failed: %u\n", res);
goto failure;
}
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(pData->hWaveThreadEvent == NULL)
data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if(data->WaveThreadEvent == NULL)
{
ERR("CreateEvent failed: %lu\n", GetLastError());
goto failure;
}
// Allocate circular memory buffer for the captured audio
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
CapturedDataSize = Device->UpdateSize*Device->NumUpdates;
// Make sure circular buffer is at least 100ms in size
if(ulCapturedDataSize < (pData->wfexFormat.nSamplesPerSec / 10))
ulCapturedDataSize = pData->wfexFormat.nSamplesPerSec / 10;
if(CapturedDataSize < (data->Format.nSamplesPerSec / 10))
CapturedDataSize = data->Format.nSamplesPerSec / 10;
pData->pRing = CreateRingBuffer(pData->wfexFormat.nBlockAlign, ulCapturedDataSize);
if(!pData->pRing)
data->Ring = CreateRingBuffer(data->Format.nBlockAlign, CapturedDataSize);
if(!data->Ring)
goto failure;
pData->lWaveBuffersCommitted = 0;
data->WaveBuffersCommitted = 0;
// Create 4 Buffers of 50ms each
lBufferSize = pData->wfexFormat.nAvgBytesPerSec / 20;
lBufferSize -= (lBufferSize % pData->wfexFormat.nBlockAlign);
BufferSize = data->Format.nAvgBytesPerSec / 20;
BufferSize -= (BufferSize % data->Format.nBlockAlign);
BufferData = calloc(4, lBufferSize);
BufferData = calloc(4, BufferSize);
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);
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
data->WaveBuffer[i].dwBufferLength = BufferSize;
data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
(data->WaveBuffer[i-1].lpData +
data->WaveBuffer[i-1].dwBufferLength));
data->WaveBuffer[i].dwFlags = 0;
data->WaveBuffer[i].dwLoops = 0;
waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
InterlockedIncrement(&data->WaveBuffersCommitted);
}
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
if (pData->hWaveThread == NULL)
data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)Device, 0, &data->WaveThreadID);
if (data->WaveThread == NULL)
goto failure;
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
Device->DeviceName = strdup(CaptureDeviceList[DeviceID]);
return ALC_NO_ERROR;
failure:
if(pData->hWaveThread)
CloseHandle(pData->hWaveThread);
if(data->WaveThread)
CloseHandle(data->WaveThread);
if(BufferData)
{
for(i = 0;i < 4;i++)
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
free(BufferData);
}
if(pData->pRing)
DestroyRingBuffer(pData->pRing);
if(data->Ring)
DestroyRingBuffer(data->Ring);
if(pData->hWaveThreadEvent)
CloseHandle(pData->hWaveThreadEvent);
if(data->WaveThreadEvent)
CloseHandle(data->WaveThreadEvent);
if(pData->hWaveHandle.In)
waveInClose(pData->hWaveHandle.In);
if(data->WaveHandle.In)
waveInClose(data->WaveHandle.In);
free(pData);
pDevice->ExtraData = NULL;
free(data);
Device->ExtraData = NULL;
return ALC_INVALID_VALUE;
}
static void WinMMCloseCapture(ALCdevice *pDevice)
static void WinMMCloseCapture(ALCdevice *Device)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
WinMMData *data = (WinMMData*)Device->ExtraData;
void *buffer = NULL;
int i;
/* Tell the processing thread to quit and wait for it to do so. */
pData->bWaveShutdown = AL_TRUE;
PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
data->killNow = AL_TRUE;
PostThreadMessage(data->WaveThreadID, WM_QUIT, 0, 0);
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
/* Make sure capture is stopped and all pending buffers are flushed. */
waveInReset(pData->hWaveHandle.In);
waveInReset(data->WaveHandle.In);
CloseHandle(pData->hWaveThread);
pData->hWaveThread = 0;
CloseHandle(data->WaveThread);
data->WaveThread = 0;
// Release the wave buffers
for(i = 0;i < 4;i++)
{
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = pData->WaveBuffer[i].lpData;
pData->WaveBuffer[i].lpData = NULL;
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = data->WaveBuffer[i].lpData;
data->WaveBuffer[i].lpData = NULL;
}
free(buffer);
DestroyRingBuffer(pData->pRing);
pData->pRing = NULL;
DestroyRingBuffer(data->Ring);
data->Ring = NULL;
// Close the Wave device
CloseHandle(pData->hWaveThreadEvent);
pData->hWaveThreadEvent = 0;
CloseHandle(data->WaveThreadEvent);
data->WaveThreadEvent = 0;
waveInClose(pData->hWaveHandle.In);
pData->hWaveHandle.In = 0;
waveInClose(data->WaveHandle.In);
data->WaveHandle.In = 0;
free(pData);
pDevice->ExtraData = NULL;
free(data);
Device->ExtraData = NULL;
}
static void WinMMStartCapture(ALCdevice *pDevice)
static void WinMMStartCapture(ALCdevice *Device)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
waveInStart(pData->hWaveHandle.In);
WinMMData *data = (WinMMData*)Device->ExtraData;
waveInStart(data->WaveHandle.In);
}
static void WinMMStopCapture(ALCdevice *pDevice)
static void WinMMStopCapture(ALCdevice *Device)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
waveInStop(pData->hWaveHandle.In);
WinMMData *data = (WinMMData*)Device->ExtraData;
waveInStop(data->WaveHandle.In);
}
static ALCenum WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
static ALCenum WinMMCaptureSamples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
WinMMData *data = (WinMMData*)Device->ExtraData;
ReadRingBuffer(data->Ring, Buffer, Samples);
return ALC_NO_ERROR;
}
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
static ALCuint WinMMAvailableSamples(ALCdevice *Device)
{
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
return RingBufferSize(pData->pRing);
WinMMData *data = (WinMMData*)Device->ExtraData;
return RingBufferSize(data->Ring);
}
@@ -721,7 +715,10 @@ static const BackendFuncs WinMMFuncs = {
WinMMStartCapture,
WinMMStopCapture,
WinMMCaptureSamples,
WinMMAvailableSamples
WinMMAvailableSamples,
ALCdevice_LockDefault,
ALCdevice_UnlockDefault,
ALCdevice_GetLatencyDefault
};
ALCboolean alcWinMMInit(BackendFuncs *FuncList)
@@ -732,18 +729,18 @@ ALCboolean alcWinMMInit(BackendFuncs *FuncList)
void alcWinMMDeinit()
{
ALuint lLoop;
ALuint i;
for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++)
free(PlaybackDeviceList[lLoop]);
for(i = 0;i < NumPlaybackDevices;i++)
free(PlaybackDeviceList[i]);
free(PlaybackDeviceList);
PlaybackDeviceList = NULL;
NumPlaybackDevices = 0;
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
free(CaptureDeviceList[lLoop]);
for(i = 0;i < NumCaptureDevices;i++)
free(CaptureDeviceList[i]);
free(CaptureDeviceList);
CaptureDeviceList = NULL;
@@ -761,7 +758,7 @@ void alcWinMMProbe(enum DevProbe type)
for(i = 0;i < NumPlaybackDevices;i++)
{
if(PlaybackDeviceList[i])
AppendAllDeviceList(PlaybackDeviceList[i]);
AppendAllDevicesList(PlaybackDeviceList[i]);
}
break;
+215 -7
View File
@@ -21,8 +21,11 @@
#include "config.h"
#include <stdlib.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#include <time.h>
#include <errno.h>
#include <stdarg.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
@@ -46,14 +49,213 @@ DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xa
#ifdef HAVE_MMDEVAPI
#include <devpropdef.h>
DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
#endif
#endif
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#ifdef HAVE_CPUID_H
#include <cpuid.h>
#endif
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#include "alMain.h"
ALuint CPUCapFlags = 0;
void FillCPUCaps(ALuint capfilter)
{
ALuint caps = 0;
/* FIXME: We really should get this for all available CPUs in case different
* CPUs have different caps (is that possible on one machine?). */
#if defined(HAVE_CPUID_H) && (defined(__i386__) || defined(__x86_64__) || \
defined(_M_IX86) || defined(_M_X64))
union {
unsigned int regs[4];
char str[sizeof(unsigned int[4])];
} cpuinf[3];
if(!__get_cpuid(0, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
ERR("Failed to get CPUID\n");
else
{
unsigned int maxfunc = cpuinf[0].regs[0];
unsigned int maxextfunc = 0;
if(__get_cpuid(0x80000000, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
maxextfunc = cpuinf[0].regs[0];
TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc);
TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8);
if(maxextfunc >= 0x80000004 &&
__get_cpuid(0x80000002, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]) &&
__get_cpuid(0x80000003, &cpuinf[1].regs[0], &cpuinf[1].regs[1], &cpuinf[1].regs[2], &cpuinf[1].regs[3]) &&
__get_cpuid(0x80000004, &cpuinf[2].regs[0], &cpuinf[2].regs[1], &cpuinf[2].regs[2], &cpuinf[2].regs[3]))
TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str);
if(maxfunc >= 1 &&
__get_cpuid(1, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
{
#ifdef bit_SSE
if((cpuinf[0].regs[3]&bit_SSE))
caps |= CPU_CAP_SSE;
#endif
}
}
#elif defined(HAVE_WINDOWS_H)
HMODULE k32 = GetModuleHandleA("kernel32.dll");
BOOL (WINAPI*IsProcessorFeaturePresent)(DWORD ProcessorFeature);
IsProcessorFeaturePresent = (BOOL(WINAPI*)(DWORD))GetProcAddress(k32, "IsProcessorFeaturePresent");
if(!IsProcessorFeaturePresent)
ERR("IsProcessorFeaturePresent not available; CPU caps not detected\n");
else
{
if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
caps |= CPU_CAP_SSE;
}
#endif
#ifdef HAVE_NEON
/* Assume Neon support if compiled with it */
caps |= CPU_CAP_NEON;
#endif
TRACE("Got caps:%s%s%s\n", ((caps&CPU_CAP_SSE)?((capfilter&CPU_CAP_SSE)?" SSE":" (SSE)"):""),
((caps&CPU_CAP_NEON)?((capfilter&CPU_CAP_NEON)?" Neon":" (Neon)"):""),
((!caps)?" -none-":""));
CPUCapFlags = caps & capfilter;
}
void *al_malloc(size_t alignment, size_t size)
{
#if defined(HAVE_ALIGNED_ALLOC)
size = (size+(alignment-1))&~(alignment-1);
return aligned_alloc(alignment, size);
#elif defined(HAVE_POSIX_MEMALIGN)
void *ret;
if(posix_memalign(&ret, alignment, size) == 0)
return ret;
return NULL;
#elif defined(HAVE__ALIGNED_MALLOC)
return _aligned_malloc(size, alignment);
#else
char *ret = malloc(size+alignment);
if(ret != NULL)
{
*(ret++) = 0x00;
while(((ALintptrEXT)ret&(alignment-1)) != 0)
*(ret++) = 0x55;
}
return ret;
#endif
}
void *al_calloc(size_t alignment, size_t size)
{
void *ret = al_malloc(alignment, size);
if(ret) memset(ret, 0, size);
return ret;
}
void al_free(void *ptr)
{
#if defined(HAVE_ALIGNED_ALLOC) || defined(HAVE_POSIX_MEMALIGN)
free(ptr);
#elif defined(HAVE__ALIGNED_MALLOC)
_aligned_free(ptr);
#else
if(ptr != NULL)
{
char *finder = ptr;
do {
--finder;
} while(*finder == 0x55);
free(finder);
}
#endif
}
#if (defined(HAVE___CONTROL87_2) || defined(HAVE__CONTROLFP)) && (defined(__x86_64__) || defined(_M_X64))
/* Win64 doesn't allow us to set the precision control. */
#undef _MCW_PC
#define _MCW_PC 0
#endif
void SetMixerFPUMode(FPUCtl *ctl)
{
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
unsigned short fpuState;
__asm__ __volatile__("fnstcw %0" : "=m" (*&fpuState));
ctl->state = fpuState;
fpuState &= ~0x300; /* clear precision to single */
fpuState |= 0xC00; /* set round-to-zero */
__asm__ __volatile__("fldcw %0" : : "m" (*&fpuState));
#ifdef HAVE_SSE
if((CPUCapFlags&CPU_CAP_SSE))
{
int sseState;
__asm__ __volatile__("stmxcsr %0" : "=m" (*&sseState));
ctl->sse_state = sseState;
sseState |= 0x0C00; /* set round-to-zero */
sseState |= 0x8000; /* set flush-to-zero */
__asm__ __volatile__("ldmxcsr %0" : : "m" (*&sseState));
}
#endif
#elif defined(HAVE___CONTROL87_2)
int mode;
__control87_2(0, 0, &ctl->state, NULL);
__control87_2(_RC_CHOP|_PC_24, _MCW_RC|_MCW_PC, &mode, NULL);
#ifdef HAVE_SSE
if((CPUCapFlags&CPU_CAP_SSE))
{
__control87_2(0, 0, NULL, &ctl->sse_state);
__control87_2(_RC_CHOP|_DN_FLUSH, _MCW_RC|_MCW_DN, NULL, &mode);
}
#endif
#elif defined(HAVE__CONTROLFP)
ctl->state = _controlfp(0, 0);
(void)_controlfp(_RC_CHOP|_PC_24, _MCW_RC|_MCW_PC);
#elif defined(HAVE_FESETROUND)
ctl->state = fegetround();
#ifdef FE_TOWARDZERO
fesetround(FE_TOWARDZERO);
#endif
#endif
}
void RestoreFPUMode(const FPUCtl *ctl)
{
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
unsigned short fpuState = ctl->state;
__asm__ __volatile__("fldcw %0" : : "m" (*&fpuState));
#ifdef HAVE_SSE
if((CPUCapFlags&CPU_CAP_SSE))
__asm__ __volatile__("ldmxcsr %0" : : "m" (*&ctl->sse_state));
#endif
#elif defined(HAVE___CONTROL87_2)
int mode;
__control87_2(ctl->state, _MCW_RC|_MCW_PC, &mode, NULL);
#ifdef HAVE_SSE
if((CPUCapFlags&CPU_CAP_SSE))
__control87_2(ctl->sse_state, _MCW_RC|_MCW_DN, NULL, &mode);
#endif
#elif defined(HAVE__CONTROLFP)
_controlfp(ctl->state, _MCW_RC|_MCW_PC);
#elif defined(HAVE_FESETROUND)
fesetround(ctl->state);
#endif
}
#ifdef _WIN32
void pthread_once(pthread_once_t *once, void (*callback)(void))
{
@@ -123,6 +325,12 @@ WCHAR *strdupW(const WCHAR *str)
#else
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
#include <sched.h>
void InitializeCriticalSection(CRITICAL_SECTION *cs)
{
pthread_mutexattr_t attrib;
@@ -239,13 +447,13 @@ void *GetSymbol(void *handle, const char *name)
#endif
void al_print(const char *func, const char *fmt, ...)
void al_print(const char *type, const char *func, const char *fmt, ...)
{
char str[256];
int i;
i = snprintf(str, sizeof(str), "AL lib: %s: ", func);
if(i < (int)sizeof(str) && i > 0)
i = snprintf(str, sizeof(str), "AL lib: %s %s: ", type, func);
if(i > 0 && (unsigned int)i < sizeof(str))
{
va_list ap;
va_start(ap, fmt);
+621 -274
View File
File diff suppressed because it is too large Load Diff
+846 -837
View File
File diff suppressed because it is too large Load Diff
+238 -639
View File
@@ -37,437 +37,6 @@
#include "bs2b.h"
static __inline ALfloat point32(const ALfloat *vals, ALint step, ALint frac)
{ return vals[0]; (void)step; (void)frac; }
static __inline ALfloat lerp32(const ALfloat *vals, ALint step, ALint frac)
{ return lerp(vals[0], vals[step], frac * (1.0f/FRACTIONONE)); }
static __inline ALfloat cubic32(const ALfloat *vals, ALint step, ALint frac)
{ return cubic(vals[-step], vals[0], vals[step], vals[step+step],
frac * (1.0f/FRACTIONONE)); }
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
#if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H)
#include <arm_neon.h>
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALuint c;
float32x4_t leftright4;
{
float32x2_t leftright2 = vdup_n_f32(0.0);
leftright2 = vset_lane_f32(left, leftright2, 0);
leftright2 = vset_lane_f32(right, leftright2, 1);
leftright4 = vcombine_f32(leftright2, leftright2);
}
for(c = 0;c < HRIR_LENGTH;c += 2)
{
const ALuint o0 = (Offset+c)&HRIR_MASK;
const ALuint o1 = (o0+1)&HRIR_MASK;
float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
vld1_f32((float32_t*)&Values[o1][0]));
float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
vals = vmlaq_f32(vals, coefs, leftright4);
vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
}
}
#else
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALuint c;
for(c = 0;c < HRIR_LENGTH;c++)
{
const ALuint off = (Offset+c)&HRIR_MASK;
Values[off][0] += Coeffs[c][0] * left;
Values[off][1] += Coeffs[c][1] * right;
}
}
#endif
#define DECL_TEMPLATE(T, sampler) \
static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
const ALuint NumChannels = Source->NumChannels; \
const T *RESTRICT data = srcdata; \
const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \
ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \
ALuint pos, frac; \
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; \
\
pos = 0; \
frac = *DataPosFrac; \
\
for(i = 0;i < NumChannels;i++) \
{ \
ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \
ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \
ALfloat *RESTRICT History = Source->HrtfHistory[i]; \
ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \
ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \
ALuint Offset = Source->HrtfOffset + OutPos; \
ALfloat Coeffs[HRIR_LENGTH][2]; \
ALuint Delay[2]; \
ALfloat left, right; \
\
pos = 0; \
frac = *DataPosFrac; \
\
for(c = 0;c < HRIR_LENGTH;c++) \
{ \
Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \
Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \
} \
\
Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \
Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \
\
if(LIKELY(OutPos == 0)) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2PC(DryFilter, i, value); \
\
History[Offset&SRC_HISTORY_MASK] = value; \
left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
\
ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \
Coeffs[0][0] * left; \
ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \
Coeffs[0][1] * right; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2P(DryFilter, i, value); \
\
History[Offset&SRC_HISTORY_MASK] = value; \
left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \
right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \
\
Delay[0] += DelayStep[0]; \
Delay[1] += DelayStep[1]; \
\
Values[Offset&HRIR_MASK][0] = 0.0f; \
Values[Offset&HRIR_MASK][1] = 0.0f; \
Offset++; \
\
for(c = 0;c < HRIR_LENGTH;c++) \
{ \
const ALuint off = (Offset+c)&HRIR_MASK; \
Values[off][0] += Coeffs[c][0] * left; \
Values[off][1] += Coeffs[c][1] * right; \
Coeffs[c][0] += CoeffStep[c][0]; \
Coeffs[c][1] += CoeffStep[c][1]; \
} \
\
DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
Counter--; \
} \
\
Delay[0] >>= 16; \
Delay[1] >>= 16; \
for(;BufferIdx < BufferSize;BufferIdx++) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2P(DryFilter, i, value); \
\
History[Offset&SRC_HISTORY_MASK] = value; \
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
\
Values[Offset&HRIR_MASK][0] = 0.0f; \
Values[Offset&HRIR_MASK][1] = 0.0f; \
Offset++; \
\
ApplyCoeffs(Offset, Values, Coeffs, left, right); \
DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \
DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(LIKELY(OutPos == SamplesToDo)) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
value = lpFilter2PC(DryFilter, i, value); \
\
History[Offset&SRC_HISTORY_MASK] = value; \
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \
\
PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \
Coeffs[0][0] * left; \
PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \
Coeffs[0][1] * right; \
} \
OutPos -= BufferSize; \
} \
\
for(out = 0;out < Device->NumAuxSends;out++) \
{ \
ALeffectslot *Slot = Source->Params.Send[out].Slot; \
ALfloat WetSend; \
ALfloat *RESTRICT WetBuffer; \
ALfloat *RESTRICT WetClickRemoval; \
ALfloat *RESTRICT WetPendingClicks; \
FILTER *WetFilter; \
\
if(Slot == NULL) \
continue; \
\
WetBuffer = Slot->WetBuffer; \
WetClickRemoval = Slot->ClickRemoval; \
WetPendingClicks = Slot->PendingClicks; \
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
for(i = 0;i < NumChannels;i++) \
{ \
pos = 0; \
frac = *DataPosFrac; \
\
if(LIKELY(OutPos == 0)) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
value = lpFilter1PC(WetFilter, i, value); \
\
WetClickRemoval[0] -= value * WetSend; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
value = lpFilter1P(WetFilter, i, value); \
\
WetBuffer[OutPos] += value * WetSend; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(LIKELY(OutPos == SamplesToDo)) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
value = lpFilter1PC(WetFilter, i, value); \
\
WetPendingClicks[0] += value * WetSend; \
} \
OutPos -= BufferSize; \
} \
} \
*DataPosInt += pos; \
*DataPosFrac = frac; \
}
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
DECL_TEMPLATE(ALfloat, cubic32)
#undef DECL_TEMPLATE
#define DECL_TEMPLATE(T, sampler) \
static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \
{ \
const ALuint NumChannels = Source->NumChannels; \
const T *RESTRICT data = srcdata; \
ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \
ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \
ALfloat DrySend[MAXCHANNELS]; \
FILTER *DryFilter; \
ALuint pos, frac; \
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; \
\
pos = 0; \
frac = *DataPosFrac; \
\
for(i = 0;i < NumChannels;i++) \
{ \
for(c = 0;c < MAXCHANNELS;c++) \
DrySend[c] = Source->Params.DryGains[i][c]; \
\
pos = 0; \
frac = *DataPosFrac; \
\
if(OutPos == 0) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
\
value = lpFilter2PC(DryFilter, i, value); \
for(c = 0;c < MAXCHANNELS;c++) \
ClickRemoval[c] -= value*DrySend[c]; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels, frac); \
\
value = lpFilter2P(DryFilter, i, 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*NumChannels + i, NumChannels, frac); \
\
value = lpFilter2PC(DryFilter, i, value); \
for(c = 0;c < MAXCHANNELS;c++) \
PendingClicks[c] += value*DrySend[c]; \
} \
OutPos -= BufferSize; \
} \
\
for(out = 0;out < Device->NumAuxSends;out++) \
{ \
ALeffectslot *Slot = Source->Params.Send[out].Slot; \
ALfloat WetSend; \
ALfloat *WetBuffer; \
ALfloat *WetClickRemoval; \
ALfloat *WetPendingClicks; \
FILTER *WetFilter; \
\
if(Slot == NULL) \
continue; \
\
WetBuffer = Slot->WetBuffer; \
WetClickRemoval = Slot->ClickRemoval; \
WetPendingClicks = Slot->PendingClicks; \
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
for(i = 0;i < NumChannels;i++) \
{ \
pos = 0; \
frac = *DataPosFrac; \
\
if(OutPos == 0) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
\
value = lpFilter1PC(WetFilter, i, value); \
WetClickRemoval[0] -= value * WetSend; \
} \
for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
\
value = lpFilter1P(WetFilter, i, value); \
WetBuffer[OutPos] += value * WetSend; \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
OutPos++; \
} \
if(OutPos == SamplesToDo) \
{ \
value = sampler(data + pos*NumChannels + i, NumChannels,frac);\
\
value = lpFilter1PC(WetFilter, i, value); \
WetPendingClicks[0] += value * WetSend; \
} \
OutPos -= BufferSize; \
} \
} \
*DataPosInt += pos; \
*DataPosFrac = frac; \
}
DECL_TEMPLATE(ALfloat, point32)
DECL_TEMPLATE(ALfloat, lerp32)
DECL_TEMPLATE(ALfloat, cubic32)
#undef DECL_TEMPLATE
MixerFunc SelectMixer(enum Resampler Resampler)
{
switch(Resampler)
{
case PointResampler:
return Mix_ALfloat_point32;
case LinearResampler:
return Mix_ALfloat_lerp32;
case CubicResampler:
return Mix_ALfloat_cubic32;
case ResamplerMax:
break;
}
return NULL;
}
MixerFunc SelectHrtfMixer(enum Resampler Resampler)
{
switch(Resampler)
{
case PointResampler:
return Mix_Hrtf_ALfloat_point32;
case LinearResampler:
return Mix_Hrtf_ALfloat_lerp32;
case CubicResampler:
return Mix_Hrtf_ALfloat_cubic32;
case ResamplerMax:
break;
}
return NULL;
}
static __inline ALfloat Sample_ALbyte(ALbyte val)
{ return val * (1.0f/127.0f); }
@@ -478,11 +47,11 @@ static __inline ALfloat Sample_ALfloat(ALfloat val)
{ return val; }
#define DECL_TEMPLATE(T) \
static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
{ \
ALuint i; \
for(i = 0;i < samples;i++) \
dst[i] = Sample_##T(src[i]); \
dst[i] = Sample_##T(src[i*srcstep]); \
}
DECL_TEMPLATE(ALbyte)
@@ -491,23 +60,23 @@ DECL_TEMPLATE(ALfloat)
#undef DECL_TEMPLATE
static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
{
switch(srctype)
{
case FmtByte:
Load_ALbyte(dst, src, samples);
Load_ALbyte(dst, src, srcstep, samples);
break;
case FmtShort:
Load_ALshort(dst, src, samples);
Load_ALshort(dst, src, srcstep, samples);
break;
case FmtFloat:
Load_ALfloat(dst, src, samples);
Load_ALfloat(dst, src, srcstep, samples);
break;
}
}
static void SilenceStack(ALfloat *dst, ALuint samples)
static void SilenceData(ALfloat *dst, ALuint samples)
{
ALuint i;
for(i = 0;i < samples;i++)
@@ -515,6 +84,16 @@ static void SilenceStack(ALfloat *dst, ALuint samples)
}
static void Filter2P(FILTER *filter, ALuint chan, ALfloat *RESTRICT dst,
const ALfloat *RESTRICT src, ALuint numsamples)
{
ALuint i;
for(i = 0;i < numsamples;i++)
dst[i] = lpFilter2P(filter, chan, src[i]);
dst[i] = lpFilter2PC(filter, chan, src[i]);
}
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
{
ALbufferlistitem *BufferListItem;
@@ -526,34 +105,31 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
ALenum State;
ALuint OutPos;
ALuint NumChannels;
ALuint FrameSize;
ALuint SampleSize;
ALint64 DataSize64;
ALuint i;
ALuint chan, j;
/* Get source info */
State = Source->state;
BuffersPlayed = Source->BuffersPlayed;
DataPosInt = Source->position;
DataPosFrac = Source->position_fraction;
Looping = Source->bLooping;
Looping = Source->Looping;
increment = Source->Params.Step;
Resampler = Source->Resampler;
Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
NumChannels = Source->NumChannels;
FrameSize = NumChannels * Source->SampleSize;
SampleSize = Source->SampleSize;
/* Get current buffer queue item */
BufferListItem = Source->queue;
for(i = 0;i < BuffersPlayed;i++)
for(j = 0;j < BuffersPlayed;j++)
BufferListItem = BufferListItem->next;
OutPos = 0;
do {
const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
const ALuint BufferPadding = ResamplerPadding[Resampler];
ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
ALfloat *SrcData = StackData;
ALuint SrcDataSize = 0;
ALuint BufferSize;
ALuint SrcBufferSize, DstBufferSize;
/* Figure out how many buffer bytes will be needed */
DataSize64 = SamplesToDo-OutPos+1;
@@ -561,197 +137,223 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
DataSize64 += DataPosFrac+FRACTIONMASK;
DataSize64 >>= FRACTIONBITS;
DataSize64 += BufferPadding+BufferPrePadding;
DataSize64 *= NumChannels;
BufferSize = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
BufferSize /= NumChannels;
SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
if(Source->lSourceType == AL_STATIC)
{
const ALbuffer *ALBuffer = Source->queue->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;
else
{
DataSize = BufferPrePadding - DataPosInt;
DataSize = minu(BufferSize, DataSize);
SilenceStack(&SrcData[SrcDataSize*NumChannels],
DataSize*NumChannels);
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->SampleLen - pos;
DataSize = minu(BufferSize, DataSize);
LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
ALBuffer->FmtType, DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
SilenceStack(&SrcData[SrcDataSize*NumChannels],
BufferSize*NumChannels);
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;
}
else if(DataPosInt >= BufferPrePadding)
pos = DataPosInt - BufferPrePadding;
else
{
DataSize = BufferPrePadding - DataPosInt;
DataSize = minu(BufferSize, DataSize);
SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
pos = 0;
}
/* Copy what's left of this loop iteration, then copy repeats
* of the loop section */
DataSize = LoopEnd - pos;
DataSize = minu(BufferSize, DataSize);
LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[pos*FrameSize],
ALBuffer->FmtType, DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
DataSize = LoopEnd-LoopStart;
while(BufferSize > 0)
{
DataSize = minu(BufferSize, DataSize);
LoadStack(&SrcData[SrcDataSize*NumChannels], &Data[LoopStart*FrameSize],
ALBuffer->FmtType, DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
}
}
}
else
{
/* Crawl the buffer queue to fill in the temp buffer */
ALbufferlistitem *tmpiter = BufferListItem;
ALuint pos;
if(DataPosInt >= BufferPrePadding)
pos = DataPosInt - BufferPrePadding;
else
{
pos = BufferPrePadding - DataPosInt;
while(pos > 0)
{
if(!tmpiter->prev && !Looping)
{
ALuint DataSize = minu(BufferSize, pos);
SilenceStack(&SrcData[SrcDataSize*NumChannels], DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
pos = 0;
break;
}
if(tmpiter->prev)
tmpiter = tmpiter->prev;
else
{
while(tmpiter->next)
tmpiter = tmpiter->next;
}
if(tmpiter->buffer)
{
if((ALuint)tmpiter->buffer->SampleLen > pos)
{
pos = tmpiter->buffer->SampleLen - pos;
break;
}
pos -= tmpiter->buffer->SampleLen;
}
}
}
while(tmpiter && BufferSize > 0)
{
const ALbuffer *ALBuffer;
if((ALBuffer=tmpiter->buffer) != NULL)
{
const ALubyte *Data = ALBuffer->data;
ALuint DataSize = ALBuffer->SampleLen;
/* Skip the data already played */
if(DataSize <= pos)
pos -= DataSize;
else
{
Data += pos*FrameSize;
DataSize -= pos;
pos -= pos;
DataSize = minu(BufferSize, DataSize);
LoadStack(&SrcData[SrcDataSize*NumChannels], Data,
ALBuffer->FmtType, DataSize*NumChannels);
SrcDataSize += DataSize;
BufferSize -= DataSize;
}
}
tmpiter = tmpiter->next;
if(!tmpiter && Looping)
tmpiter = Source->queue;
else if(!tmpiter)
{
SilenceStack(&SrcData[SrcDataSize*NumChannels], BufferSize*NumChannels);
SrcDataSize += BufferSize;
BufferSize -= BufferSize;
}
}
}
/* Figure out how many samples we can mix. */
DataSize64 = SrcDataSize;
/* Figure out how many samples we can actually mix from this. */
DataSize64 = SrcBufferSize;
DataSize64 -= BufferPadding+BufferPrePadding;
DataSize64 <<= FRACTIONBITS;
DataSize64 -= increment;
DataSize64 -= DataPosFrac;
BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
DstBufferSize = minu(DstBufferSize, (SamplesToDo-OutPos));
SrcData += BufferPrePadding*NumChannels;
Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
OutPos, SamplesToDo, BufferSize);
OutPos += BufferSize;
/* Some mixers like having a multiple of 4, so try to give that unless
* this is the last update. */
if(OutPos+DstBufferSize < SamplesToDo)
DstBufferSize &= ~3;
for(chan = 0;chan < NumChannels;chan++)
{
ALfloat *SrcData = Device->SampleData1;
ALfloat *ResampledData = Device->SampleData2;
ALuint SrcDataSize = 0;
if(Source->SourceType == AL_STATIC)
{
const ALbuffer *ALBuffer = Source->queue->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;
else
{
DataSize = BufferPrePadding - DataPosInt;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
SilenceData(&SrcData[SrcDataSize], DataSize);
SrcDataSize += DataSize;
pos = 0;
}
/* Copy what's left to play in the source buffer, and clear the
* rest of the temp buffer */
DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
SrcDataSize += SrcBufferSize - SrcDataSize;
}
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;
}
else if(DataPosInt >= BufferPrePadding)
pos = DataPosInt - BufferPrePadding;
else
{
DataSize = BufferPrePadding - DataPosInt;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
SilenceData(&SrcData[SrcDataSize], DataSize);
SrcDataSize += DataSize;
pos = 0;
}
/* Copy what's left of this loop iteration, then copy repeats
* of the loop section */
DataSize = LoopEnd - pos;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
DataSize = LoopEnd-LoopStart;
while(SrcBufferSize > SrcDataSize)
{
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
}
}
}
else
{
/* Crawl the buffer queue to fill in the temp buffer */
ALbufferlistitem *tmpiter = BufferListItem;
ALuint pos;
if(DataPosInt >= BufferPrePadding)
pos = DataPosInt - BufferPrePadding;
else
{
pos = BufferPrePadding - DataPosInt;
while(pos > 0)
{
if(!tmpiter->prev && !Looping)
{
ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
SilenceData(&SrcData[SrcDataSize], DataSize);
SrcDataSize += DataSize;
pos = 0;
break;
}
if(tmpiter->prev)
tmpiter = tmpiter->prev;
else
{
while(tmpiter->next)
tmpiter = tmpiter->next;
}
if(tmpiter->buffer)
{
if((ALuint)tmpiter->buffer->SampleLen > pos)
{
pos = tmpiter->buffer->SampleLen - pos;
break;
}
pos -= tmpiter->buffer->SampleLen;
}
}
}
while(tmpiter && SrcBufferSize > SrcDataSize)
{
const ALbuffer *ALBuffer;
if((ALBuffer=tmpiter->buffer) != NULL)
{
const ALubyte *Data = ALBuffer->data;
ALuint DataSize = ALBuffer->SampleLen;
/* Skip the data already played */
if(DataSize <= pos)
pos -= DataSize;
else
{
Data += (pos*NumChannels + chan)*SampleSize;
DataSize -= pos;
pos -= pos;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
LoadData(&SrcData[SrcDataSize], Data, NumChannels,
ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
}
}
tmpiter = tmpiter->next;
if(!tmpiter && Looping)
tmpiter = Source->queue;
else if(!tmpiter)
{
SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
SrcDataSize += SrcBufferSize - SrcDataSize;
}
}
}
/* Now resample, then filter and mix to the appropriate outputs. */
Source->Params.Resample(&SrcData[BufferPrePadding], DataPosFrac,
increment, ResampledData, DstBufferSize);
{
DirectParams *directparms = &Source->Params.Direct;
Filter2P(&directparms->iirFilter, chan, SrcData, ResampledData,
DstBufferSize);
Source->Params.DryMix(directparms, SrcData, chan, OutPos,
SamplesToDo, DstBufferSize);
}
for(j = 0;j < Device->NumAuxSends;j++)
{
SendParams *sendparms = &Source->Params.Send[j];
if(!sendparms->Slot)
continue;
Filter2P(&sendparms->iirFilter, chan, SrcData, ResampledData,
DstBufferSize);
Source->Params.WetMix(sendparms, SrcData, OutPos,
SamplesToDo, DstBufferSize);
}
}
/* Update positions */
for(j = 0;j < DstBufferSize;j++)
{
DataPosFrac += increment;
DataPosInt += DataPosFrac>>FRACTIONBITS;
DataPosFrac &= FRACTIONMASK;
}
OutPos += DstBufferSize;
/* Handle looping sources */
while(1)
@@ -770,7 +372,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
break;
}
if(Looping && Source->lSourceType == AL_STATIC)
if(Looping && Source->SourceType == AL_STATIC)
{
DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
break;
@@ -808,15 +410,12 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
Source->BuffersPlayed = BuffersPlayed;
Source->position = DataPosInt;
Source->position_fraction = DataPosFrac;
Source->HrtfOffset += OutPos;
Source->Hrtf.Offset += OutPos;
if(State == AL_PLAYING)
{
Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
Source->HrtfMoving = AL_TRUE;
}
Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
else
{
Source->HrtfCounter = 0;
Source->HrtfMoving = AL_FALSE;
Source->Hrtf.Counter = 0;
Source->Hrtf.Moving = AL_FALSE;
}
}
+131
View File
@@ -0,0 +1,131 @@
#include "config.h"
#include <assert.h>
#include "alMain.h"
#include "alu.h"
#include "alSource.h"
#include "alAuxEffectSlot.h"
static __inline ALfloat point32(const ALfloat *vals, ALuint frac)
{ return vals[0]; (void)frac; }
static __inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
static __inline ALfloat cubic32(const ALfloat *vals, ALuint frac)
{ return cubic(vals[-1], vals[0], vals[1], vals[2], frac * (1.0f/FRACTIONONE)); }
void Resample_copy32_C(const ALfloat *data, ALuint frac,
ALuint increment, ALfloat *RESTRICT OutBuffer, ALuint BufferSize)
{
(void)frac;
assert(increment==FRACTIONONE);
memcpy(OutBuffer, data, (BufferSize+1)*sizeof(ALfloat));
}
#define DECL_TEMPLATE(Sampler) \
void Resample_##Sampler##_C(const ALfloat *data, ALuint frac, \
ALuint increment, ALfloat *RESTRICT OutBuffer, ALuint BufferSize) \
{ \
ALuint pos = 0; \
ALuint i; \
\
for(i = 0;i < BufferSize+1;i++) \
{ \
OutBuffer[i] = Sampler(data + pos, frac); \
\
frac += increment; \
pos += frac>>FRACTIONBITS; \
frac &= FRACTIONMASK; \
} \
}
DECL_TEMPLATE(point32)
DECL_TEMPLATE(lerp32)
DECL_TEMPLATE(cubic32)
#undef DECL_TEMPLATE
static __inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
const ALfloat (*RESTRICT CoeffStep)[2],
ALfloat left, ALfloat right)
{
ALuint c;
for(c = 0;c < IrSize;c++)
{
const ALuint off = (Offset+c)&HRIR_MASK;
Values[off][0] += Coeffs[c][0] * left;
Values[off][1] += Coeffs[c][1] * right;
Coeffs[c][0] += CoeffStep[c][0];
Coeffs[c][1] += CoeffStep[c][1];
}
}
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALuint c;
for(c = 0;c < IrSize;c++)
{
const ALuint off = (Offset+c)&HRIR_MASK;
Values[off][0] += Coeffs[c][0] * left;
Values[off][1] += Coeffs[c][1] * right;
}
}
#define SUFFIX C
#include "mixer_inc.c"
#undef SUFFIX
void MixDirect_C(const DirectParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALfloat (*RESTRICT DryBuffer)[BUFFERSIZE] = params->OutBuffer;
ALfloat *RESTRICT ClickRemoval = params->ClickRemoval;
ALfloat *RESTRICT PendingClicks = params->PendingClicks;
ALfloat DrySend;
ALuint pos;
ALuint c;
for(c = 0;c < MaxChannels;c++)
{
DrySend = params->Gains[srcchan][c];
if(DrySend < 0.00001f)
continue;
if(OutPos == 0)
ClickRemoval[c] -= data[0]*DrySend;
for(pos = 0;pos < BufferSize;pos++)
DryBuffer[c][OutPos+pos] += data[pos]*DrySend;
if(OutPos+pos == SamplesToDo)
PendingClicks[c] += data[pos]*DrySend;
}
}
void MixSend_C(const SendParams *params, const ALfloat *RESTRICT data,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALeffectslot *Slot = params->Slot;
ALfloat (*RESTRICT WetBuffer)[BUFFERSIZE] = Slot->WetBuffer;
ALfloat *RESTRICT WetClickRemoval = Slot->ClickRemoval;
ALfloat *RESTRICT WetPendingClicks = Slot->PendingClicks;
ALfloat WetSend = params->Gain;
ALuint pos;
if(WetSend < 0.00001f)
return;
if(OutPos == 0)
WetClickRemoval[0] -= data[0] * WetSend;
for(pos = 0;pos < BufferSize;pos++)
WetBuffer[0][OutPos+pos] += data[pos] * WetSend;
if(OutPos+pos == SamplesToDo)
WetPendingClicks[0] += data[pos] * WetSend;
}
+31
View File
@@ -0,0 +1,31 @@
#ifndef MIXER_DEFS_H
#define MIXER_DEFS_H
#include "AL/alc.h"
#include "AL/al.h"
#include "alMain.h"
struct DirectParams;
struct SendParams;
/* C resamplers */
void Resample_copy32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen);
void Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen);
void Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen);
void Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *RESTRICT dst, ALuint dstlen);
/* C mixers */
void MixDirect_Hrtf_C(const struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixDirect_C(const struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_C(const struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint);
/* SSE mixers */
void MixDirect_Hrtf_SSE(const struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixDirect_SSE(const struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
void MixSend_SSE(const struct SendParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint);
/* Neon mixers */
void MixDirect_Hrtf_Neon(const struct DirectParams*,const ALfloat*RESTRICT,ALuint,ALuint,ALuint,ALuint);
#endif /* MIXER_DEFS_H */
+141
View File
@@ -0,0 +1,141 @@
#include "config.h"
#include "alMain.h"
#include "alSource.h"
#include "mixer_defs.h"
#ifdef __GNUC__
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
#define REAL_MERGE2(a,b) a##b
#define MERGE2(a,b) REAL_MERGE2(a,b)
#define MixDirect_Hrtf MERGE2(MixDirect_Hrtf_,SUFFIX)
static __inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint irSize,
ALfloat (*RESTRICT Coeffs)[2],
const ALfloat (*RESTRICT CoeffStep)[2],
ALfloat left, ALfloat right);
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint irSize,
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right);
void MixDirect_Hrtf(const DirectParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALfloat (*RESTRICT DryBuffer)[BUFFERSIZE] = params->OutBuffer;
ALfloat *RESTRICT ClickRemoval = params->ClickRemoval;
ALfloat *RESTRICT PendingClicks = params->PendingClicks;
const ALuint IrSize = params->Hrtf.Params.IrSize;
const ALint *RESTRICT DelayStep = params->Hrtf.Params.DelayStep;
const ALfloat (*RESTRICT CoeffStep)[2] = params->Hrtf.Params.CoeffStep;
const ALfloat (*RESTRICT TargetCoeffs)[2] = params->Hrtf.Params.Coeffs[srcchan];
const ALuint *RESTRICT TargetDelay = params->Hrtf.Params.Delay[srcchan];
ALfloat *RESTRICT History = params->Hrtf.State->History[srcchan];
ALfloat (*RESTRICT Values)[2] = params->Hrtf.State->Values[srcchan];
ALint Counter = maxu(params->Hrtf.State->Counter, OutPos) - OutPos;
ALuint Offset = params->Hrtf.State->Offset + OutPos;
ALIGN(16) ALfloat Coeffs[HRIR_LENGTH][2];
ALuint Delay[2];
ALfloat left, right;
ALuint pos;
ALuint c;
pos = 0;
for(c = 0;c < IrSize;c++)
{
Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter);
Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter);
}
Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter);
Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter);
if(LIKELY(OutPos == 0))
{
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
ClickRemoval[FrontLeft] -= Values[(Offset+1)&HRIR_MASK][0] +
Coeffs[0][0] * left;
ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] +
Coeffs[0][1] * right;
}
for(pos = 0;pos < BufferSize && Counter > 0;pos++)
{
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
(Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
Delay[0] += DelayStep[0];
Delay[1] += DelayStep[1];
Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
Offset++;
ApplyCoeffsStep(Offset, Values, IrSize, Coeffs, CoeffStep, left, right);
DryBuffer[FrontLeft][OutPos] += Values[Offset&HRIR_MASK][0];
DryBuffer[FrontRight][OutPos] += Values[Offset&HRIR_MASK][1];
OutPos++;
Counter--;
}
Delay[0] >>= HRTFDELAY_BITS;
Delay[1] >>= HRTFDELAY_BITS;
for(;pos < BufferSize;pos++)
{
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
Offset++;
ApplyCoeffs(Offset, Values, IrSize, Coeffs, left, right);
DryBuffer[FrontLeft][OutPos] += Values[Offset&HRIR_MASK][0];
DryBuffer[FrontRight][OutPos] += Values[Offset&HRIR_MASK][1];
OutPos++;
}
if(LIKELY(OutPos == SamplesToDo))
{
History[Offset&SRC_HISTORY_MASK] = data[pos];
left = History[(Offset-Delay[0])&SRC_HISTORY_MASK];
right = History[(Offset-Delay[1])&SRC_HISTORY_MASK];
PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] +
Coeffs[0][0] * left;
PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] +
Coeffs[0][1] * right;
}
}
#undef MixDirect_Hrtf
#undef MERGE2
#undef REAL_MERGE2
#undef UNLIKELY
#undef LIKELY
+61
View File
@@ -0,0 +1,61 @@
#include "config.h"
#ifdef HAVE_ARM_NEON_H
#include <arm_neon.h>
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alu.h"
static __inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
const ALfloat (*RESTRICT CoeffStep)[2],
ALfloat left, ALfloat right)
{
ALuint c;
for(c = 0;c < IrSize;c++)
{
const ALuint off = (Offset+c)&HRIR_MASK;
Values[off][0] += Coeffs[c][0] * left;
Values[off][1] += Coeffs[c][1] * right;
Coeffs[c][0] += CoeffStep[c][0];
Coeffs[c][1] += CoeffStep[c][1];
}
}
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALuint c;
float32x4_t leftright4;
{
float32x2_t leftright2 = vdup_n_f32(0.0);
leftright2 = vset_lane_f32(left, leftright2, 0);
leftright2 = vset_lane_f32(right, leftright2, 1);
leftright4 = vcombine_f32(leftright2, leftright2);
}
for(c = 0;c < IrSize;c += 2)
{
const ALuint o0 = (Offset+c)&HRIR_MASK;
const ALuint o1 = (o0+1)&HRIR_MASK;
float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
vld1_f32((float32_t*)&Values[o1][0]));
float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
vals = vmlaq_f32(vals, coefs, leftright4);
vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
}
}
#define SUFFIX Neon
#include "mixer_inc.c"
#undef SUFFIX
+204
View File
@@ -0,0 +1,204 @@
#include "config.h"
#ifdef HAVE_XMMINTRIN_H
#include <xmmintrin.h>
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alu.h"
#include "alSource.h"
#include "alAuxEffectSlot.h"
#include "mixer_defs.h"
static __inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
const ALfloat (*RESTRICT CoeffStep)[2],
ALfloat left, ALfloat right)
{
const __m128 lrlr = { left, right, left, right };
__m128 coeffs, deltas, imp0, imp1;
__m128 vals = _mm_setzero_ps();
ALuint i;
if((Offset&1))
{
const ALuint o0 = Offset&HRIR_MASK;
const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK;
coeffs = _mm_load_ps(&Coeffs[0][0]);
deltas = _mm_load_ps(&CoeffStep[0][0]);
vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]);
imp0 = _mm_mul_ps(lrlr, coeffs);
coeffs = _mm_add_ps(coeffs, deltas);
vals = _mm_add_ps(imp0, vals);
_mm_store_ps(&Coeffs[0][0], coeffs);
_mm_storel_pi((__m64*)&Values[o0][0], vals);
for(i = 1;i < IrSize-1;i += 2)
{
const ALuint o2 = (Offset+i)&HRIR_MASK;
coeffs = _mm_load_ps(&Coeffs[i+1][0]);
deltas = _mm_load_ps(&CoeffStep[i+1][0]);
vals = _mm_load_ps(&Values[o2][0]);
imp1 = _mm_mul_ps(lrlr, coeffs);
coeffs = _mm_add_ps(coeffs, deltas);
imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
vals = _mm_add_ps(imp0, vals);
_mm_store_ps(&Coeffs[i+1][0], coeffs);
_mm_store_ps(&Values[o2][0], vals);
imp0 = imp1;
}
vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]);
imp0 = _mm_movehl_ps(imp0, imp0);
vals = _mm_add_ps(imp0, vals);
_mm_storel_pi((__m64*)&Values[o1][0], vals);
}
else
{
for(i = 0;i < IrSize;i += 2)
{
const ALuint o = (Offset + i)&HRIR_MASK;
coeffs = _mm_load_ps(&Coeffs[i][0]);
deltas = _mm_load_ps(&CoeffStep[i][0]);
vals = _mm_load_ps(&Values[o][0]);
imp0 = _mm_mul_ps(lrlr, coeffs);
coeffs = _mm_add_ps(coeffs, deltas);
vals = _mm_add_ps(imp0, vals);
_mm_store_ps(&Coeffs[i][0], coeffs);
_mm_store_ps(&Values[o][0], vals);
}
}
}
static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2],
const ALuint IrSize,
ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
const __m128 lrlr = { left, right, left, right };
__m128 vals = _mm_setzero_ps();
__m128 coeffs;
ALuint i;
if((Offset&1))
{
const ALuint o0 = Offset&HRIR_MASK;
const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK;
__m128 imp0, imp1;
coeffs = _mm_load_ps(&Coeffs[0][0]);
vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]);
imp0 = _mm_mul_ps(lrlr, coeffs);
vals = _mm_add_ps(imp0, vals);
_mm_storel_pi((__m64*)&Values[o0][0], vals);
for(i = 1;i < IrSize-1;i += 2)
{
const ALuint o2 = (Offset+i)&HRIR_MASK;
coeffs = _mm_load_ps(&Coeffs[i+1][0]);
vals = _mm_load_ps(&Values[o2][0]);
imp1 = _mm_mul_ps(lrlr, coeffs);
imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
vals = _mm_add_ps(imp0, vals);
_mm_store_ps(&Values[o2][0], vals);
imp0 = imp1;
}
vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]);
imp0 = _mm_movehl_ps(imp0, imp0);
vals = _mm_add_ps(imp0, vals);
_mm_storel_pi((__m64*)&Values[o1][0], vals);
}
else
{
for(i = 0;i < IrSize;i += 2)
{
const ALuint o = (Offset + i)&HRIR_MASK;
coeffs = _mm_load_ps(&Coeffs[i][0]);
vals = _mm_load_ps(&Values[o][0]);
vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs));
_mm_store_ps(&Values[o][0], vals);
}
}
}
#define SUFFIX SSE
#include "mixer_inc.c"
#undef SUFFIX
void MixDirect_SSE(const DirectParams *params, const ALfloat *RESTRICT data, ALuint srcchan,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALfloat (*RESTRICT DryBuffer)[BUFFERSIZE] = params->OutBuffer;
ALfloat *RESTRICT ClickRemoval = params->ClickRemoval;
ALfloat *RESTRICT PendingClicks = params->PendingClicks;
ALfloat DrySend;
ALuint pos;
ALuint c;
for(c = 0;c < MaxChannels;c++)
{
__m128 gain;
DrySend = params->Gains[srcchan][c];
if(DrySend < 0.00001f)
continue;
if(OutPos == 0)
ClickRemoval[c] -= data[0]*DrySend;
gain = _mm_set1_ps(DrySend);
for(pos = 0;pos < BufferSize-3;pos += 4)
{
const __m128 val4 = _mm_load_ps(&data[pos]);
__m128 dry4 = _mm_load_ps(&DryBuffer[c][OutPos+pos]);
dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain));
_mm_store_ps(&DryBuffer[c][OutPos+pos], dry4);
}
for(;pos < BufferSize;pos++)
DryBuffer[c][OutPos+pos] += data[pos]*DrySend;
if(OutPos+pos == SamplesToDo)
PendingClicks[c] += data[pos]*DrySend;
}
}
void MixSend_SSE(const SendParams *params, const ALfloat *RESTRICT data,
ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
{
ALeffectslot *Slot = params->Slot;
ALfloat (*RESTRICT WetBuffer)[BUFFERSIZE] = Slot->WetBuffer;
ALfloat *RESTRICT WetClickRemoval = Slot->ClickRemoval;
ALfloat *RESTRICT WetPendingClicks = Slot->PendingClicks;
const ALfloat WetGain = params->Gain;
__m128 gain;
ALuint pos;
if(WetGain < 0.00001f)
return;
if(OutPos == 0)
WetClickRemoval[0] -= data[0] * WetGain;
gain = _mm_set1_ps(WetGain);
for(pos = 0;pos < BufferSize-3;pos+=4)
{
const __m128 val4 = _mm_load_ps(&data[pos]);
__m128 wet4 = _mm_load_ps(&WetBuffer[0][OutPos+pos]);
wet4 = _mm_add_ps(wet4, _mm_mul_ps(val4, gain));
_mm_store_ps(&WetBuffer[0][OutPos+pos], wet4);
}
for(;pos < BufferSize;pos++)
WetBuffer[0][OutPos+pos] += data[pos] * WetGain;
if(OutPos+pos == SamplesToDo)
WetPendingClicks[0] += data[pos] * WetGain;
}
+239 -107
View File
@@ -31,8 +31,8 @@
#include "AL/alc.h"
#include "alu.h"
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS],
enum Channel Speaker2Chan[MAXCHANNELS], ALint chans)
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MaxChannels],
enum Channel Speaker2Chan[MaxChannels], ALint chans)
{
char *confkey, *next;
char *layout_str;
@@ -71,21 +71,21 @@ static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHAN
*(++end) = 0;
if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
val = FRONT_LEFT;
val = FrontLeft;
else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
val = FRONT_RIGHT;
val = FrontRight;
else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
val = FRONT_CENTER;
val = FrontCenter;
else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
val = BACK_LEFT;
val = BackLeft;
else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
val = BACK_RIGHT;
val = BackRight;
else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
val = BACK_CENTER;
val = BackCenter;
else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
val = SIDE_LEFT;
val = SideLeft;
else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
val = SIDE_RIGHT;
val = SideRight;
else
{
ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
@@ -139,54 +139,228 @@ static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHAN
}
}
static ALfloat aluLUTpos2Angle(ALint pos)
/**
* ComputeAngleGains
*
* Sets channel gains based on a given source's angle and its half-width. The
* angle and hwidth parameters are in radians.
*/
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains)
{
if(pos < QUADRANT_NUM)
return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos));
if(pos < 2 * QUADRANT_NUM)
return F_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)) - F_PI;
return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - F_PI_2;
ALfloat tmpgains[MaxChannels] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
enum Channel Speaker2Chan[MaxChannels];
ALfloat SpeakerAngle[MaxChannels];
ALfloat langle, rangle;
ALfloat a;
ALuint i;
for(i = 0;i < device->NumChan;i++)
Speaker2Chan[i] = device->Speaker2Chan[i];
for(i = 0;i < device->NumChan;i++)
SpeakerAngle[i] = device->SpeakerAngle[i];
/* Some easy special-cases first... */
if(device->NumChan == 1 || hwidth >= F_PI)
{
/* Full coverage for all speakers. */
for(i = 0;i < device->NumChan;i++)
{
enum Channel chan = Speaker2Chan[i];
gains[chan] = ingain;
}
return;
}
if(hwidth <= 0.0f)
{
/* Infinitely small sound point. */
for(i = 0;i < device->NumChan-1;i++)
{
if(angle >= SpeakerAngle[i] && angle < SpeakerAngle[i+1])
{
/* Sound is between speakers i and i+1 */
a = (angle-SpeakerAngle[i]) /
(SpeakerAngle[i+1]-SpeakerAngle[i]);
gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
gains[Speaker2Chan[i+1]] = sqrtf( a) * ingain;
return;
}
}
/* Sound is between last and first speakers */
if(angle < SpeakerAngle[0])
angle += F_PI*2.0f;
a = (angle-SpeakerAngle[i]) /
(F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
gains[Speaker2Chan[0]] = sqrtf( a) * ingain;
return;
}
if(fabsf(angle)+hwidth > F_PI)
{
/* The coverage area would go outside of -pi...+pi. Instead, rotate the
* speaker angles so it would be as if angle=0, and keep them wrapped
* within -pi...+pi. */
if(angle > 0.0f)
{
ALuint done = 0;
ALuint i = 0;
while(i < device->NumChan && device->SpeakerAngle[i]-angle < -F_PI)
i++;
for(done = 0;i < device->NumChan;done++)
{
SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
Speaker2Chan[done] = device->Speaker2Chan[i];
i++;
}
for(i = 0;done < device->NumChan;i++)
{
SpeakerAngle[done] = device->SpeakerAngle[i]-angle + F_PI*2.0f;
Speaker2Chan[done] = device->Speaker2Chan[i];
done++;
}
}
else
{
/* NOTE: '< device->NumChan' on the iterators is correct here since
* we need to handle index 0. Because the iterators are unsigned,
* they'll underflow and wrap to become 0xFFFFFFFF, which will
* break as expected. */
ALuint done = device->NumChan-1;
ALuint i = device->NumChan-1;
while(i < device->NumChan && device->SpeakerAngle[i]-angle > F_PI)
i--;
for(done = device->NumChan-1;i < device->NumChan;done--)
{
SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
Speaker2Chan[done] = device->Speaker2Chan[i];
i--;
}
for(i = device->NumChan-1;done < device->NumChan;i--)
{
SpeakerAngle[done] = device->SpeakerAngle[i]-angle - F_PI*2.0f;
Speaker2Chan[done] = device->Speaker2Chan[i];
done--;
}
}
angle = 0.0f;
}
langle = angle - hwidth;
rangle = angle + hwidth;
/* First speaker */
i = 0;
do {
ALuint last = device->NumChan-1;
enum Channel chan = Speaker2Chan[i];
if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
{
tmpgains[chan] = 1.0f;
continue;
}
if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
{
a = (langle-SpeakerAngle[i]) /
(SpeakerAngle[i+1]-SpeakerAngle[i]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
}
if(SpeakerAngle[i] > rangle)
{
a = (F_PI*2.0f + rangle-SpeakerAngle[last]) /
(F_PI*2.0f + SpeakerAngle[i]-SpeakerAngle[last]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
}
else if(SpeakerAngle[last] < rangle)
{
a = (rangle-SpeakerAngle[last]) /
(F_PI*2.0f + SpeakerAngle[i]-SpeakerAngle[last]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
}
} while(0);
for(i = 1;i < device->NumChan-1;i++)
{
enum Channel chan = Speaker2Chan[i];
if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
{
tmpgains[chan] = 1.0f;
continue;
}
if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
{
a = (langle-SpeakerAngle[i]) /
(SpeakerAngle[i+1]-SpeakerAngle[i]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
}
if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
{
a = (rangle-SpeakerAngle[i-1]) /
(SpeakerAngle[i]-SpeakerAngle[i-1]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
}
}
/* Last speaker */
i = device->NumChan-1;
do {
enum Channel chan = Speaker2Chan[i];
if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
{
tmpgains[Speaker2Chan[i]] = 1.0f;
continue;
}
if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
{
a = (rangle-SpeakerAngle[i-1]) /
(SpeakerAngle[i]-SpeakerAngle[i-1]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
}
if(SpeakerAngle[i] < langle)
{
a = (langle-SpeakerAngle[i]) /
(F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
}
else if(SpeakerAngle[0] > langle)
{
a = (F_PI*2.0f + langle-SpeakerAngle[i]) /
(F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[i]);
tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
}
} while(0);
for(i = 0;i < device->NumChan;i++)
{
enum Channel chan = device->Speaker2Chan[i];
gains[chan] = sqrtf(tmpgains[chan]) * ingain;
}
}
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.0f)
pos = 2 * QUADRANT_NUM - pos;
if(im < 0.0f)
pos = LUT_NUM - pos;
return pos%LUT_NUM;
}
ALvoid aluInitPanning(ALCdevice *Device)
{
ALfloat SpeakerAngle[MAXCHANNELS];
const char *layoutname = NULL;
enum Channel *Speaker2Chan;
ALfloat Alpha, Theta;
ALint pos;
ALuint s;
ALfloat *SpeakerAngle;
Speaker2Chan = Device->Speaker2Chan;
SpeakerAngle = Device->SpeakerAngle;
switch(Device->FmtChans)
{
case DevFmtMono:
Device->NumChan = 1;
Speaker2Chan[0] = FRONT_CENTER;
Speaker2Chan[0] = FrontCenter;
SpeakerAngle[0] = F_PI/180.0f * 0.0f;
layoutname = NULL;
break;
case DevFmtStereo:
Device->NumChan = 2;
Speaker2Chan[0] = FRONT_LEFT;
Speaker2Chan[1] = FRONT_RIGHT;
Speaker2Chan[0] = FrontLeft;
Speaker2Chan[1] = FrontRight;
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
SpeakerAngle[1] = F_PI/180.0f * 90.0f;
layoutname = "layout_stereo";
@@ -194,10 +368,10 @@ ALvoid aluInitPanning(ALCdevice *Device)
case DevFmtQuad:
Device->NumChan = 4;
Speaker2Chan[0] = BACK_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_RIGHT;
Speaker2Chan[3] = BACK_RIGHT;
Speaker2Chan[0] = BackLeft;
Speaker2Chan[1] = FrontLeft;
Speaker2Chan[2] = FrontRight;
Speaker2Chan[3] = BackRight;
SpeakerAngle[0] = F_PI/180.0f * -135.0f;
SpeakerAngle[1] = F_PI/180.0f * -45.0f;
SpeakerAngle[2] = F_PI/180.0f * 45.0f;
@@ -207,11 +381,11 @@ ALvoid aluInitPanning(ALCdevice *Device)
case DevFmtX51:
Device->NumChan = 5;
Speaker2Chan[0] = BACK_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_CENTER;
Speaker2Chan[3] = FRONT_RIGHT;
Speaker2Chan[4] = BACK_RIGHT;
Speaker2Chan[0] = BackLeft;
Speaker2Chan[1] = FrontLeft;
Speaker2Chan[2] = FrontCenter;
Speaker2Chan[3] = FrontRight;
Speaker2Chan[4] = BackRight;
SpeakerAngle[0] = F_PI/180.0f * -110.0f;
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
@@ -222,11 +396,11 @@ ALvoid aluInitPanning(ALCdevice *Device)
case DevFmtX51Side:
Device->NumChan = 5;
Speaker2Chan[0] = SIDE_LEFT;
Speaker2Chan[1] = FRONT_LEFT;
Speaker2Chan[2] = FRONT_CENTER;
Speaker2Chan[3] = FRONT_RIGHT;
Speaker2Chan[4] = SIDE_RIGHT;
Speaker2Chan[0] = SideLeft;
Speaker2Chan[1] = FrontLeft;
Speaker2Chan[2] = FrontCenter;
Speaker2Chan[3] = FrontRight;
Speaker2Chan[4] = SideRight;
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
@@ -237,12 +411,12 @@ ALvoid aluInitPanning(ALCdevice *Device)
case DevFmtX61:
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;
Speaker2Chan[0] = SideLeft;
Speaker2Chan[1] = FrontLeft;
Speaker2Chan[2] = FrontCenter;
Speaker2Chan[3] = FrontRight;
Speaker2Chan[4] = SideRight;
Speaker2Chan[5] = BackCenter;
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
@@ -254,13 +428,13 @@ ALvoid aluInitPanning(ALCdevice *Device)
case DevFmtX71:
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;
Speaker2Chan[0] = BackLeft;
Speaker2Chan[1] = SideLeft;
Speaker2Chan[2] = FrontLeft;
Speaker2Chan[3] = FrontCenter;
Speaker2Chan[4] = FrontRight;
Speaker2Chan[5] = SideRight;
Speaker2Chan[6] = BackRight;
SpeakerAngle[0] = F_PI/180.0f * -150.0f;
SpeakerAngle[1] = F_PI/180.0f * -90.0f;
SpeakerAngle[2] = F_PI/180.0f * -30.0f;
@@ -273,46 +447,4 @@ ALvoid aluInitPanning(ALCdevice *Device)
}
if(layoutname && Device->Type != Loopback)
SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan);
for(pos = 0; pos < LUT_NUM; pos++)
{
ALfloat *PanningLUT = Device->PanningLUT[pos];
/* clear all values */
for(s = 0; s < MAXCHANNELS; s++)
PanningLUT[s] = 0.0f;
if(Device->NumChan == 1)
{
PanningLUT[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 = (Theta-SpeakerAngle[s]) /
(SpeakerAngle[s+1]-SpeakerAngle[s]);
PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
PanningLUT[Speaker2Chan[s+1]] = aluSqrt( Alpha);
break;
}
}
if(s == Device->NumChan - 1)
{
/* source between last and first speaker */
if(Theta < SpeakerAngle[0])
Theta += F_PI*2.0f;
Alpha = (Theta-SpeakerAngle[s]) /
(F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[s]);
PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha);
PanningLUT[Speaker2Chan[0]] = aluSqrt( Alpha);
}
}
}
+114 -37
View File
@@ -26,6 +26,13 @@ PROJECT(OpenAL C)
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
OPTION(SSE "Check for SSE CPU extensions" ON)
OPTION(NEON "Check for ARM Neon CPU extensions" ON)
OPTION(REQUIRE_SSE "Require SSE CPU extensions" OFF)
OPTION(REQUIRE_NEON "Require ARM Neon CPU extensions" OFF)
OPTION(ALSA "Check for ALSA backend" ON)
OPTION(OSS "Check for OSS backend" ON)
OPTION(SOLARIS "Check for Solaris backend" ON)
@@ -59,7 +66,7 @@ OPTION(UTILS "Build and install utility programs" ON)
OPTION(EXAMPLES "Build and install example programs" ON)
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
OPTION(ALSOFT_CONFIG "Install alsoft.conf sample configuration file" ON)
IF(WIN32)
@@ -74,10 +81,13 @@ IF(NOT LIBTYPE)
ENDIF()
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "14")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}")
SET(LIB_MINOR_VERSION "15")
SET(LIB_REVISION "1")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
SET(EXPORT_DECL "")
SET(ALIGN_DECL "")
SET(RESTRICT_DECL "")
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
@@ -86,8 +96,15 @@ CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
CHECK_C_SOURCE_COMPILES("int *restrict foo;
int main() {return 0;}" HAVE_RESTRICT)
CHECK_C_SOURCE_COMPILES("int *__restrict foo;
int main() {return 0;}" HAVE___RESTRICT)
IF(HAVE_RESTRICT)
SET(RESTRICT_DECL "restrict")
ELSE()
CHECK_C_SOURCE_COMPILES("int *__restrict foo;
int main() {return 0;}" HAVE___RESTRICT)
IF(HAVE___RESTRICT)
SET(RESTRICT_DECL "__restrict")
ENDIF()
ENDIF()
# Add definitions, compiler switches, etc.
@@ -166,6 +183,7 @@ ENDIF()
# Set visibility/export options if available
IF(WIN32)
SET(EXPORT_DECL "__declspec(dllexport)")
SET(ALIGN_DECL "__declspec(align(x))")
OPTION(WINE "Enable use of Wine headers when compiling" OFF)
IF(WINE)
@@ -211,21 +229,33 @@ ELSE()
ENDIF()
ENDIF()
CHECK_C_SOURCE_COMPILES("int foo __attribute__((aligned(16)));
int main() {return 0;}" HAVE_ATTRIBUTE_ALIGNED)
IF(HAVE_ATTRIBUTE_ALIGNED)
SET(ALIGN_DECL "__attribute__((aligned(x)))")
ENDIF()
SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}")
ENDIF()
SET(SSE_SWITCH "")
CHECK_C_COMPILER_FLAG(-msse HAVE_MSSE_SWITCH)
IF(HAVE_MSSE_SWITCH)
SET(SSE_SWITCH "-msse")
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(malloc.h HAVE_MALLOC_H)
CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H)
CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H)
CHECK_INCLUDE_FILE(fpu_control.h HAVE_FPU_CONTROL_H)
CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H)
CHECK_INCLUDE_FILE(ieeefp.h HAVE_IEEEFP_H)
CHECK_INCLUDE_FILE(guiddef.h HAVE_GUIDDEF_H)
IF(NOT HAVE_GUIDDEF_H)
CHECK_INCLUDE_FILE(initguid.h HAVE_INITGUID_H)
ENDIF()
CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H)
# Some systems need libm for some of the following math functions to work
CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIBM)
@@ -235,25 +265,20 @@ IF(HAVE_LIBM)
ENDIF()
CHECK_SYMBOL_EXISTS(powf math.h HAVE_POWF)
CHECK_SYMBOL_EXISTS(sqrtf math.h HAVE_SQRTF)
CHECK_SYMBOL_EXISTS(cosf math.h HAVE_COSF)
CHECK_SYMBOL_EXISTS(sinf math.h HAVE_SINF)
CHECK_SYMBOL_EXISTS(acosf math.h HAVE_ACOSF)
CHECK_SYMBOL_EXISTS(asinf math.h HAVE_ASINF)
CHECK_SYMBOL_EXISTS(atanf math.h HAVE_ATANF)
CHECK_SYMBOL_EXISTS(atan2f math.h HAVE_ATAN2F)
CHECK_SYMBOL_EXISTS(fabsf math.h HAVE_FABSF)
CHECK_SYMBOL_EXISTS(log10f math.h HAVE_LOG10F)
CHECK_SYMBOL_EXISTS(floorf math.h HAVE_FLOORF)
CHECK_SYMBOL_EXISTS(aligned_alloc stdlib.h HAVE_ALIGNED_ALLOC)
CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN)
CHECK_SYMBOL_EXISTS(_aligned_malloc malloc.h HAVE__ALIGNED_MALLOC)
CHECK_SYMBOL_EXISTS(lrintf math.h HAVE_LRINTF)
IF(HAVE_FENV_H)
CHECK_SYMBOL_EXISTS(fesetround fenv.h HAVE_FESETROUND)
ENDIF()
IF(HAVE_FLOAT_H)
CHECK_SYMBOL_EXISTS(_controlfp float.h HAVE__CONTROLFP)
CHECK_SYMBOL_EXISTS(__control87_2 float.h HAVE___CONTROL87_2)
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)
@@ -358,8 +383,7 @@ IF(NOT HAVE_WINDOWS_H)
# 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
# _GNU_SOURCE is needed on some systems for extra attributes
ADD_DEFINITIONS(-D_GNU_SOURCE=1)
CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD)
IF(HAVE_LIBPTHREAD)
@@ -422,9 +446,49 @@ SET(ALC_OBJS Alc/ALc.c
Alc/alcThread.c
Alc/bs2b.c
Alc/helpers.c
Alc/panning.c
Alc/hrtf.c
Alc/mixer.c
Alc/panning.c
Alc/mixer_c.c
)
SET(CPU_EXTS "Default")
SET(HAVE_SSE 0)
SET(HAVE_NEON 0)
# Check for SSE support
IF(SSE AND ALIGN_DECL)
CHECK_INCLUDE_FILE(xmmintrin.h HAVE_XMMINTRIN_H "${SSE_SWITCH}")
IF(HAVE_XMMINTRIN_H)
SET(HAVE_SSE 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_sse.c)
IF(SSE_SWITCH)
SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse.c PROPERTIES
COMPILE_FLAGS "${SSE_SWITCH}")
ENDIF()
SET(CPU_EXTS "${CPU_EXTS}, SSE")
ENDIF()
ENDIF()
IF(REQUIRE_SSE AND NOT HAVE_SSE)
MESSAGE(FATAL_ERROR "Failed to enabled required SSE CPU extensions")
ENDIF()
# Check for ARM Neon support
IF(NEON)
CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H)
IF(HAVE_ARM_NEON_H)
SET(HAVE_NEON 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_neon.c)
SET(CPU_EXTS "${CPU_EXTS}, Neon")
ENDIF()
ENDIF()
IF(REQUIRE_NEON AND NOT HAVE_NEON)
MESSAGE(FATAL_ERROR "Failed to enabled required ARM Neon CPU extensions")
ENDIF()
SET(ALC_OBJS ${ALC_OBJS}
# Default backends, always available
Alc/backends/loopback.c
Alc/backends/null.c
@@ -496,15 +560,11 @@ IF(SNDIO)
CHECK_INCLUDE_FILE(sndio.h HAVE_SNDIO_H)
IF(HAVE_SNDIO_H)
CHECK_SHARED_FUNCTION_EXISTS(sio_open "sndio.h" sndio "" HAVE_LIBSNDIO)
IF(HAVE_LIBSNDIO OR HAVE_DLFCN_H OR WIN32)
IF(HAVE_LIBSNDIO)
SET(HAVE_SNDIO 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sndio.c)
IF(HAVE_DLFCN_H OR WIN32)
SET(BACKENDS "${BACKENDS} SndIO,")
ELSE()
SET(BACKENDS "${BACKENDS} SndIO \(linked\),")
SET(EXTRA_LIBS sndio ${EXTRA_LIBS})
ENDIF()
SET(BACKENDS "${BACKENDS} SndIO \(linked\),")
SET(EXTRA_LIBS sndio ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
@@ -663,7 +723,7 @@ SET(BACKENDS "${BACKENDS} Null")
IF(EXAMPLES)
# Might be able to use earlier versions, but these definitely work
PKG_CHECK_MODULES(FFMPEG libavcodec>=52.123.0 libavformat>=52.111.0)
PKG_CHECK_MODULES(FFMPEG libavcodec>=53.61.100 libavformat>=53.32.100 libavutil>=51.35.100)
ENDIF()
IF(LIBTYPE STREQUAL "STATIC")
@@ -692,7 +752,7 @@ CONFIGURE_FILE(
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
VERSION ${LIB_VERSION}
SOVERSION ${LIB_MAJOR_VERSION})
IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
@@ -722,6 +782,9 @@ MESSAGE(STATUS "")
MESSAGE(STATUS "Building OpenAL with support for the following backends:")
MESSAGE(STATUS " ${BACKENDS}")
MESSAGE(STATUS "")
MESSAGE(STATUS "Building with support for CPU extensions:")
MESSAGE(STATUS " ${CPU_EXTS}")
MESSAGE(STATUS "")
IF(WIN32)
IF(NOT HAVE_DSOUND)
@@ -734,10 +797,9 @@ ENDIF()
# Install alsoft.conf configuration file
IF(ALSOFT_CONFIG)
INSTALL(FILES alsoftrc.sample
DESTINATION /etc/openal
RENAME alsoft.conf
DESTINATION share/openal
)
MESSAGE(STATUS "Installing sample alsoft.conf")
MESSAGE(STATUS "Installing sample configuration")
MESSAGE(STATUS "")
ENDIF()
@@ -761,10 +823,25 @@ ENDIF()
IF(EXAMPLES)
IF(FFMPEG_FOUND)
ADD_EXECUTABLE(alstream examples/alhelpers.c examples/alffmpeg.c examples/alstream.c)
ADD_EXECUTABLE(alstream examples/common/alhelpers.c
examples/common/alffmpeg.c
examples/alstream.c)
TARGET_LINK_LIBRARIES(alstream ${FFMPEG_LIBRARIES} ${LIBNAME})
SET_TARGET_PROPERTIES(alstream PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
INSTALL(TARGETS alstream
ADD_EXECUTABLE(alreverb examples/common/alhelpers.c
examples/common/alffmpeg.c
examples/alreverb.c)
TARGET_LINK_LIBRARIES(alreverb ${FFMPEG_LIBRARIES} ${LIBNAME})
SET_TARGET_PROPERTIES(alreverb PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
ADD_EXECUTABLE(allatency examples/common/alhelpers.c
examples/common/alffmpeg.c
examples/allatency.c)
TARGET_LINK_LIBRARIES(allatency ${FFMPEG_LIBRARIES} ${LIBNAME})
SET_TARGET_PROPERTIES(allatency PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
INSTALL(TARGETS alstream alreverb allatency
RUNTIME DESTINATION bin
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+11 -15
View File
@@ -1,15 +1,20 @@
#ifndef _AL_AUXEFFECTSLOT_H_
#define _AL_AUXEFFECTSLOT_H_
#include "AL/al.h"
#include "alMain.h"
#include "alEffect.h"
#include "alFilter.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ALeffectState ALeffectState;
typedef struct ALeffectState {
ALvoid (*Destroy)(struct ALeffectState *State);
ALboolean (*DeviceUpdate)(struct ALeffectState *State, ALCdevice *Device);
ALvoid (*Update)(struct ALeffectState *State, ALCdevice *Device, const struct ALeffectslot *Slot);
ALvoid (*Process)(struct ALeffectState *State, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE]);
} ALeffectState;
typedef struct ALeffectslot
{
@@ -21,30 +26,21 @@ typedef struct ALeffectslot
volatile ALenum NeedsUpdate;
ALeffectState *EffectState;
ALfloat WetBuffer[BUFFERSIZE];
ALIGN(16) ALfloat WetBuffer[1][BUFFERSIZE];
ALfloat ClickRemoval[1];
ALfloat PendingClicks[1];
RefCount ref;
// Index to itself
ALuint effectslot;
struct ALeffectslot *next;
/* Self ID */
ALuint id;
} ALeffectslot;
ALenum InitEffectSlot(ALeffectslot *slot);
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
struct ALeffectState {
ALvoid (*Destroy)(ALeffectState *State);
ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device);
ALvoid (*Update)(ALeffectState *State, ALCdevice *Device, const ALeffectslot *Slot);
ALvoid (*Process)(ALeffectState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]);
};
ALeffectState *NoneCreate(void);
ALeffectState *ReverbCreate(void);
ALeffectState *EchoCreate(void);
+5 -4
View File
@@ -1,7 +1,7 @@
#ifndef _AL_BUFFER_H_
#define _AL_BUFFER_H_
#include "AL/al.h"
#include "alMain.h"
#ifdef __cplusplus
extern "C" {
@@ -84,12 +84,13 @@ typedef struct ALbuffer
ALsizei LoopStart;
ALsizei LoopEnd;
RefCount ref; // Number of sources using this buffer (deletion can only occur when this is 0)
/* Number of times buffer was attached to a source (deletion can only occur when 0) */
RefCount ref;
RWLock lock;
// Index to itself
ALuint buffer;
/* Self ID */
ALuint id;
} ALbuffer;
ALvoid ReleaseALBuffers(ALCdevice *device);
+3 -3
View File
@@ -1,7 +1,7 @@
#ifndef _AL_EFFECT_H_
#define _AL_EFFECT_H_
#include "AL/al.h"
#include "alMain.h"
#ifdef __cplusplus
extern "C" {
@@ -85,8 +85,8 @@ typedef struct ALeffect
void (*GetParamf)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val);
void (*GetParamfv)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals);
// Index to itself
ALuint effect;
/* Self ID */
ALuint id;
} ALeffect;
#define ALeffect_SetParami(x, c, p, v) ((x)->SetParami((x),(c),(p),(v)))
+1 -2
View File
@@ -1,8 +1,7 @@
#ifndef _AL_ERROR_H_
#define _AL_ERROR_H_
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#ifdef __cplusplus
extern "C" {
+5 -25
View File
@@ -1,13 +1,14 @@
#ifndef _AL_FILTER_H_
#define _AL_FILTER_H_
#include "AL/al.h"
#include "alu.h"
#include "alMain.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LOWPASSFREQREF (5000)
typedef struct {
ALfloat coeff;
#ifndef _MSC_VER
@@ -30,17 +31,6 @@ static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
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 lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat input)
{
@@ -53,16 +43,6 @@ static __inline ALfloat lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat in
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,
@@ -87,8 +67,8 @@ typedef struct ALfilter {
void (*GetParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val);
void (*GetParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals);
// Index to itself
ALuint filter;
/* Self ID */
ALuint id;
} ALfilter;
#define ALfilter_SetParami(x, c, p, v) ((x)->SetParami((x),(c),(p),(v)))
+7 -4
View File
@@ -1,21 +1,24 @@
#ifndef _AL_LISTENER_H_
#define _AL_LISTENER_H_
#include "AL/al.h"
#include "alMain.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ALlistener_struct
{
typedef struct ALlistener {
volatile ALfloat Position[3];
volatile ALfloat Velocity[3];
volatile ALfloat Forward[3];
volatile ALfloat Up[3];
volatile ALfloat Matrix[4][4];
volatile ALfloat Gain;
volatile ALfloat MetersPerUnit;
struct {
ALfloat Matrix[4][4];
ALfloat Velocity[3];
} Params;
} ALlistener;
#ifdef __cplusplus
+191 -74
View File
@@ -4,15 +4,13 @@
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <math.h>
#ifdef HAVE_FENV_H
#include <fenv.h>
#endif
#ifdef HAVE_FPU_CONTROL_H
#include <fpu_control.h>
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
@@ -47,20 +45,14 @@ typedef unsigned long long ALuint64;
typedef ptrdiff_t ALintptrEXT;
typedef ptrdiff_t ALsizeiptrEXT;
#define MAKEU64(x,y) (((ALuint64)(x)<<32)|(ALuint64)(y))
#ifdef HAVE_GCC_FORMAT
#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y))))
#else
#define PRINTF_STYLE(x, y)
#endif
#if defined(HAVE_RESTRICT)
#define RESTRICT restrict
#elif defined(HAVE___RESTRICT)
#define RESTRICT __restrict
#else
#define RESTRICT
#endif
static const union {
ALuint u;
@@ -72,6 +64,7 @@ static const union {
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef DWORD pthread_key_t;
@@ -99,9 +92,6 @@ static __inline int sched_yield(void)
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
#include <sys/time.h>
#include <time.h>
#include <errno.h>
@@ -341,60 +331,47 @@ static __inline void LockUIntMapWrite(UIntMap *map)
static __inline void UnlockUIntMapWrite(UIntMap *map)
{ WriteUnlock(&map->lock); }
#include "alListener.h"
#include "alu.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEFAULT_OUTPUT_RATE (44100)
#define MIN_OUTPUT_RATE (8000)
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
#define LOWPASSFREQREF (5000)
struct Hrtf;
#define DEFAULT_OUTPUT_RATE (44100)
#define MIN_OUTPUT_RATE (8000)
// Find the next power-of-2 for non-power-of-2 numbers.
static __inline ALuint NextPowerOf2(ALuint value)
{
ALuint powerOf2 = 1;
if(value)
if(value > 0)
{
value--;
while(value)
{
value >>= 1;
powerOf2 <<= 1;
}
value |= value>>1;
value |= value>>2;
value |= value>>4;
value |= value>>8;
value |= value>>16;
}
return powerOf2;
return value+1;
}
/* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
* mode. */
static __inline ALint fastf2i(ALfloat f)
{
#ifdef HAVE_LRINTF
return lrintf(f);
#elif defined(_MSC_VER) && defined(_M_IX86)
ALint i;
#if defined(_MSC_VER) && defined(_M_IX86)
__asm fld f
__asm fistp i
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
__asm__ __volatile__("flds %1\n\t"
"fistpl %0\n\t"
: "=m" (i)
: "m" (f));
#else
i = (ALint)f;
#endif
return i;
#else
return (ALint)f;
#endif
}
/* Fast float-to-uint conversion. Assumes the FPU is already in round-to-zero
@@ -421,6 +398,11 @@ typedef struct {
void (*StopCapture)(ALCdevice*);
ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
ALCuint (*AvailableSamples)(ALCdevice*);
void (*Lock)(ALCdevice*);
void (*Unlock)(ALCdevice*);
ALint64 (*GetLatency)(ALCdevice*);
} BackendFuncs;
struct BackendInfo {
@@ -475,6 +457,41 @@ void alc_loopback_deinit(void);
void alc_loopback_probe(enum DevProbe type);
enum DistanceModel {
InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
InverseDistance = AL_INVERSE_DISTANCE,
LinearDistance = AL_LINEAR_DISTANCE,
ExponentDistance = AL_EXPONENT_DISTANCE,
DisableDistance = AL_NONE,
DefaultDistanceModel = InverseDistanceClamped
};
enum Resampler {
PointResampler,
LinearResampler,
CubicResampler,
ResamplerMax,
};
enum Channel {
FrontLeft = 0,
FrontRight,
FrontCenter,
LFE,
BackLeft,
BackRight,
BackCenter,
SideLeft,
SideRight,
MaxChannels,
};
/* Device formats */
enum DevFmtType {
DevFmtByte = ALC_BYTE_SOFT,
@@ -524,6 +541,22 @@ enum DeviceType {
Loopback
};
/* Size for temporary storage of buffer data, in ALfloats. Larger values need
* more memory, 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, as well as the maximum number of samples per mixing iteration.
*
* The mixer requires being able to do two samplings per mixing loop. With the
* cubic resampler (which requires 3 padding samples), this limits a 2048
* buffer size to about 2044. This means that buffer_freq*source_pitch cannot
* exceed device_freq*2044 for a 32-bit buffer.
*/
#ifndef BUFFERSIZE
#define BUFFERSIZE 2048
#endif
struct ALCdevice_struct
{
volatile RefCount ref;
@@ -539,7 +572,7 @@ struct ALCdevice_struct
enum DevFmtChannels FmtChans;
enum DevFmtType FmtType;
ALCchar *szDeviceName;
ALCchar *DeviceName;
volatile ALCenum LastError;
@@ -571,17 +604,21 @@ struct ALCdevice_struct
// Device flags
ALuint Flags;
// Dry path buffer mix
ALfloat DryBuffer[BUFFERSIZE][MAXCHANNELS];
ALuint ChannelOffsets[MaxChannels];
enum Channel DevChannels[MAXCHANNELS];
enum Channel Speaker2Chan[MAXCHANNELS];
ALfloat PanningLUT[LUT_NUM][MAXCHANNELS];
enum Channel Speaker2Chan[MaxChannels];
ALfloat SpeakerAngle[MaxChannels];
ALuint NumChan;
ALfloat ClickRemoval[MAXCHANNELS];
ALfloat PendingClicks[MAXCHANNELS];
/* Temp storage used for mixing. +1 for the predictive sample. */
ALIGN(16) ALfloat SampleData1[BUFFERSIZE+1];
ALIGN(16) ALfloat SampleData2[BUFFERSIZE+1];
// Dry path buffer mix
ALIGN(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE];
ALIGN(16) ALfloat ClickRemoval[MaxChannels];
ALIGN(16) ALfloat PendingClicks[MaxChannels];
/* Default effect slot */
struct ALeffectslot *DefaultSlot;
@@ -606,9 +643,10 @@ struct ALCdevice_struct
#define ALCdevice_StopCapture(a) ((a)->Funcs->StopCapture((a)))
#define ALCdevice_CaptureSamples(a,b,c) ((a)->Funcs->CaptureSamples((a), (b), (c)))
#define ALCdevice_AvailableSamples(a) ((a)->Funcs->AvailableSamples((a)))
#define ALCdevice_Lock(a) ((a)->Funcs->Lock((a)))
#define ALCdevice_Unlock(a) ((a)->Funcs->Unlock((a)))
#define ALCdevice_GetLatency(a) ((a)->Funcs->GetLatency((a)))
// Duplicate stereo sources on the side/rear channels
#define DEVICE_DUPLICATE_STEREO (1<<0)
// Frequency was requested by the app or config file
#define DEVICE_FREQUENCY_REQUEST (1<<1)
// Channel configuration was requested by the config file
@@ -616,9 +654,16 @@ struct ALCdevice_struct
// Sample type was requested by the config file
#define DEVICE_SAMPLE_TYPE_REQUEST (1<<3)
// Stereo sources cover 120-degree angles around +/-90
#define DEVICE_WIDE_STEREO (1<<16)
// Specifies if the device is currently running
#define DEVICE_RUNNING (1<<31)
/* Invalid channel offset */
#define INVALID_OFFSET (~0u)
#define LookupBuffer(m, k) ((struct ALbuffer*)LookupUIntMapKey(&(m)->BufferMap, (k)))
#define LookupEffect(m, k) ((struct ALeffect*)LookupUIntMapKey(&(m)->EffectMap, (k)))
#define LookupFilter(m, k) ((struct ALfilter*)LookupUIntMapKey(&(m)->FilterMap, (k)))
@@ -631,7 +676,7 @@ struct ALCcontext_struct
{
volatile RefCount ref;
ALlistener Listener;
struct ALlistener *Listener;
UIntMap SourceMap;
UIntMap EffectSlotMap;
@@ -645,7 +690,7 @@ struct ALCcontext_struct
volatile ALfloat DopplerFactor;
volatile ALfloat DopplerVelocity;
volatile ALfloat flSpeedOfSound;
volatile ALfloat SpeedOfSound;
volatile ALenum DeferUpdates;
struct ALsource **ActiveSources;
@@ -667,25 +712,38 @@ struct ALCcontext_struct
#define RemoveSource(m, k) ((struct ALsource*)RemoveUIntMapKey(&(m)->SourceMap, (k)))
#define RemoveEffectSlot(m, k) ((struct ALeffectslot*)RemoveUIntMapKey(&(m)->EffectSlotMap, (k)))
ALCcontext *GetContextRef(void);
void ALCcontext_IncRef(ALCcontext *context);
void ALCcontext_DecRef(ALCcontext *context);
void AppendAllDeviceList(const ALCchar *name);
void AppendAllDevicesList(const ALCchar *name);
void AppendCaptureDeviceList(const ALCchar *name);
static __inline void LockDevice(ALCdevice *device)
{ EnterCriticalSection(&device->Mutex); }
static __inline void UnlockDevice(ALCdevice *device)
{ LeaveCriticalSection(&device->Mutex); }
void ALCdevice_LockDefault(ALCdevice *device);
void ALCdevice_UnlockDefault(ALCdevice *device);
ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device);
static __inline void LockContext(ALCcontext *context)
{ LockDevice(context->Device); }
{ ALCdevice_Lock(context->Device); }
static __inline void UnlockContext(ALCcontext *context)
{ UnlockDevice(context->Device); }
{ ALCdevice_Unlock(context->Device); }
void *al_malloc(size_t alignment, size_t size);
void *al_calloc(size_t alignment, size_t size);
void al_free(void *ptr);
typedef struct {
int state;
#ifdef HAVE_SSE
int sse_state;
#endif
} FPUCtl;
void SetMixerFPUMode(FPUCtl *ctl);
void RestoreFPUMode(const FPUCtl *ctl);
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
ALuint StopThread(ALvoid *thread);
@@ -714,18 +772,21 @@ void SetDefaultWFXChannelOrder(ALCdevice *device);
const ALCchar *DevFmtTypeString(enum DevFmtType type);
const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
#define HRIR_BITS (5)
#define HRIR_BITS (7)
#define HRIR_LENGTH (1<<HRIR_BITS)
#define HRIR_MASK (HRIR_LENGTH-1)
void InitHrtf(void);
void FreeHrtf(void);
#define HRTFDELAY_BITS (20)
#define HRTFDELAY_FRACONE (1<<HRTFDELAY_BITS)
#define HRTFDELAY_MASK (HRTFDELAY_FRACONE-1)
const struct Hrtf *GetHrtf(ALCdevice *device);
void FreeHrtfs(void);
ALuint GetHrtfIrSize (const struct Hrtf *Hrtf);
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]);
void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays);
ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep);
void al_print(const char *func, const char *fmt, ...) PRINTF_STYLE(2,3);
#define AL_PRINT(...) al_print(__FUNCTION__, __VA_ARGS__)
void al_print(const char *type, const char *func, const char *fmt, ...) PRINTF_STYLE(3,4);
#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
extern FILE *LogFile;
enum LogLevel {
@@ -739,27 +800,83 @@ extern enum LogLevel LogLevel;
#define TRACEREF(...) do { \
if(LogLevel >= LogRef) \
AL_PRINT(__VA_ARGS__); \
AL_PRINT("(--)", __VA_ARGS__); \
} while(0)
#define TRACE(...) do { \
if(LogLevel >= LogTrace) \
AL_PRINT(__VA_ARGS__); \
AL_PRINT("(II)", __VA_ARGS__); \
} while(0)
#define WARN(...) do { \
if(LogLevel >= LogWarning) \
AL_PRINT(__VA_ARGS__); \
AL_PRINT("(WW)", __VA_ARGS__); \
} while(0)
#define ERR(...) do { \
if(LogLevel >= LogError) \
AL_PRINT(__VA_ARGS__); \
AL_PRINT("(EE)", __VA_ARGS__); \
} while(0)
extern ALint RTPrioLevel;
extern ALuint CPUCapFlags;
enum {
CPU_CAP_SSE = 1<<0,
CPU_CAP_NEON = 1<<1,
};
void FillCPUCaps(ALuint capfilter);
/**
* Starts a try block. Must not be nested within another try block within the
* same function.
*/
#define al_try do { \
int _al_err=0; \
_al_try_label: \
if(_al_err == 0)
/**
* After a try or another catch block, runs the next block if the given value
* was thrown.
*/
#define al_catch(val) else if(_al_err == (val))
/**
* After a try or catch block, runs the next block for any value thrown and not
* caught.
*/
#define al_catchany() else
/** Marks the end of the final catch (or the try) block. */
#define al_endtry } while(0)
/**
* The given integer value is "thrown" so as to be caught by a catch block.
* Must be called in a try block within the same function. The value must not
* be 0.
*/
#define al_throw(e) do { \
_al_err = (e); \
assert(_al_err != 0); \
goto _al_try_label; \
} while(0)
/** Sets an AL error on the given context, before throwing the error code. */
#define al_throwerr(ctx, err) do { \
alSetError((ctx), (err)); \
al_throw((err)); \
} while(0)
/**
* Throws an AL_INVALID_VALUE error with the given ctx if the given condition
* is false.
*/
#define CHECK_VALUE(ctx, cond) do { \
if(!(cond)) \
al_throwerr((ctx), AL_INVALID_VALUE); \
} while(0)
#ifdef __cplusplus
}
#endif
+119 -71
View File
@@ -3,9 +3,9 @@
#define MAX_SENDS 4
#include "alFilter.h"
#include "alMain.h"
#include "alu.h"
#include "AL/al.h"
#include "alFilter.h"
#ifdef __cplusplus
extern "C" {
@@ -28,45 +28,77 @@ typedef struct ALbufferlistitem
struct ALbufferlistitem *prev;
} ALbufferlistitem;
typedef struct ALsource
{
volatile ALfloat flPitch;
volatile ALfloat flGain;
volatile ALfloat flOuterGain;
volatile ALfloat flMinGain;
volatile ALfloat flMaxGain;
volatile ALfloat flInnerAngle;
volatile ALfloat flOuterAngle;
volatile ALfloat flRefDistance;
volatile ALfloat flMaxDistance;
volatile ALfloat flRollOffFactor;
volatile ALfloat vPosition[3];
volatile ALfloat vVelocity[3];
volatile ALfloat vOrientation[3];
volatile ALboolean bHeadRelative;
volatile ALboolean bLooping;
volatile enum DistanceModel DistanceModel;
volatile ALboolean DirectChannels;
typedef struct HrtfState {
ALboolean Moving;
ALuint Counter;
ALIGN(16) ALfloat History[MaxChannels][SRC_HISTORY_LENGTH];
ALIGN(16) ALfloat Values[MaxChannels][HRIR_LENGTH][2];
ALuint Offset;
} HrtfState;
enum Resampler Resampler;
typedef struct HrtfParams {
ALfloat Gain;
ALfloat Dir[3];
ALIGN(16) ALfloat Coeffs[MaxChannels][HRIR_LENGTH][2];
ALIGN(16) ALfloat CoeffStep[HRIR_LENGTH][2];
ALuint Delay[MaxChannels][2];
ALint DelayStep[2];
ALuint IrSize;
} HrtfParams;
volatile ALenum state;
ALenum new_state;
ALuint position;
ALuint position_fraction;
ALbufferlistitem *queue; // Linked list of buffers in queue
ALuint BuffersInQueue; // Number of buffers in queue
ALuint BuffersPlayed; // Number of buffers played on this loop
ALfloat DirectGain;
ALfloat DirectGainHF;
typedef struct DirectParams {
ALfloat (*OutBuffer)[BUFFERSIZE];
ALfloat *ClickRemoval;
ALfloat *PendingClicks;
struct {
struct ALeffectslot *Slot;
ALfloat WetGain;
ALfloat WetGainHF;
} Send[MAX_SENDS];
HrtfParams Params;
HrtfState *State;
} Hrtf;
/* 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. FrontLeft). Not used with HRTF. */
ALfloat Gains[MaxChannels][MaxChannels];
/* A low-pass filter, using 2 chained one-pole filters. */
FILTER iirFilter;
ALfloat history[MaxChannels*2];
} DirectParams;
typedef struct SendParams {
struct ALeffectslot *Slot;
/* Gain control, which applies to all input channels to a single (mono)
* output buffer. */
ALfloat Gain;
/* A low-pass filter, using 2 chained one-pole filters. */
FILTER iirFilter;
ALfloat history[MaxChannels*2];
} SendParams;
typedef struct ALsource
{
/** Source properties. */
volatile ALfloat Pitch;
volatile ALfloat Gain;
volatile ALfloat OuterGain;
volatile ALfloat MinGain;
volatile ALfloat MaxGain;
volatile ALfloat InnerAngle;
volatile ALfloat OuterAngle;
volatile ALfloat RefDistance;
volatile ALfloat MaxDistance;
volatile ALfloat RollOffFactor;
volatile ALfloat Position[3];
volatile ALfloat Velocity[3];
volatile ALfloat Orientation[3];
volatile ALboolean HeadRelative;
volatile ALboolean Looping;
volatile enum DistanceModel DistanceModel;
volatile ALboolean DirectChannels;
volatile ALboolean DryGainHFAuto;
volatile ALboolean WetGainAuto;
@@ -77,56 +109,72 @@ typedef struct ALsource
volatile ALfloat RoomRolloffFactor;
volatile ALfloat DopplerFactor;
ALint lOffset;
ALint lOffsetType;
enum Resampler Resampler;
// Source Type (Static, Streaming, or Undetermined)
volatile ALint lSourceType;
/**
* Last user-specified offset, and the offset type (bytes, samples, or
* seconds).
*/
ALdouble Offset;
ALenum OffsetType;
/** Source type (static, streaming, or undetermined) */
volatile ALint SourceType;
/** Source state (initial, playing, paused, or stopped) */
volatile ALenum state;
ALenum new_state;
/**
* Source offset in samples, relative to the currently playing buffer, NOT
* the whole queue, and the fractional (fixed-point) offset to the next
* sample.
*/
ALuint position;
ALuint position_fraction;
/** Source Buffer Queue info. */
ALbufferlistitem *queue;
ALuint BuffersInQueue;
ALuint BuffersPlayed;
/** Current buffer sample info. */
ALuint NumChannels;
ALuint SampleSize;
/* HRTF info */
ALboolean HrtfMoving;
ALuint HrtfCounter;
ALfloat HrtfHistory[MAXCHANNELS][SRC_HISTORY_LENGTH];
ALfloat HrtfValues[MAXCHANNELS][HRIR_LENGTH][2];
ALuint HrtfOffset;
/** Direct filter and auxiliary send info. */
ALfloat DirectGain;
ALfloat DirectGainHF;
/* Current target parameters used for mixing */
struct {
MixerFunc DoMix;
struct ALeffectslot *Slot;
ALfloat Gain;
ALfloat GainHF;
} Send[MAX_SENDS];
/** HRTF info. */
HrtfState Hrtf;
/** Current target parameters used for mixing. */
struct {
ResamplerFunc Resample;
DryMixerFunc DryMix;
WetMixerFunc WetMix;
ALint Step;
ALfloat HrtfGain;
ALfloat HrtfDir[3];
ALfloat HrtfCoeffs[MAXCHANNELS][HRIR_LENGTH][2];
ALuint HrtfDelay[MAXCHANNELS][2];
ALfloat HrtfCoeffStep[HRIR_LENGTH][2];
ALint HrtfDelayStep[2];
DirectParams Direct;
/* 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 {
struct ALeffectslot *Slot;
ALfloat WetGain;
FILTER iirFilter;
ALfloat history[MAXCHANNELS];
} Send[MAX_SENDS];
SendParams Send[MAX_SENDS];
} Params;
/** Source needs to update its mixing parameters. */
volatile ALenum NeedsUpdate;
/** Method to update mixing parameters. */
ALvoid (*Update)(struct ALsource *self, const ALCcontext *context);
// Index to itself
ALuint source;
/** Self ID */
ALuint id;
} ALsource;
#define ALsource_Update(s,a) ((s)->Update(s,a))
-14
View File
@@ -1,14 +0,0 @@
#ifndef _AL_STATE_H_
#define _AL_STATE_H_
#include "AL/al.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif
+27 -213
View File
@@ -1,40 +1,12 @@
#ifndef _ALU_H_
#define _ALU_H_
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "alMain.h"
#include <limits.h>
#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
/* HACK: Seems cross-compiling with MinGW includes the wrong float.h, which
* doesn't define Windows' _controlfp and related macros */
#if defined(__MINGW32__) && !defined(_RC_CHOP)
/* Control word masks for unMask */
#define _MCW_EM 0x0008001F /* Error masks */
#define _MCW_IC 0x00040000 /* Infinity */
#define _MCW_RC 0x00000300 /* Rounding */
#define _MCW_PC 0x00030000 /* Precision */
/* Control word values for unNew (use with related unMask above) */
#define _EM_INVALID 0x00000010
#define _EM_DENORMAL 0x00080000
#define _EM_ZERODIVIDE 0x00000008
#define _EM_OVERFLOW 0x00000004
#define _EM_UNDERFLOW 0x00000002
#define _EM_INEXACT 0x00000001
#define _IC_AFFINE 0x00040000
#define _IC_PROJECTIVE 0x00000000
#define _RC_CHOP 0x00000300
#define _RC_UP 0x00000200
#define _RC_DOWN 0x00000100
#define _RC_NEAR 0x00000000
#define _PC_24 0x00020000
#define _PC_53 0x00010000
#define _PC_64 0x00000000
_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _controlfp (unsigned int unNew, unsigned int unMask);
#endif
#endif
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
@@ -44,74 +16,10 @@ _CRTIMP unsigned int __cdecl __MINGW_NOTHROW _controlfp (unsigned int unNew, uns
#define F_PI (3.14159265358979323846f) /* pi */
#define F_PI_2 (1.57079632679489661923f) /* pi/2 */
#ifdef HAVE_POWF
#define aluPow(x,y) (powf((x),(y)))
#else
#define aluPow(x,y) ((ALfloat)pow((double)(x),(double)(y)))
#ifndef FLT_EPSILON
#define FLT_EPSILON (1.19209290e-07f)
#endif
#ifdef HAVE_SQRTF
#define aluSqrt(x) (sqrtf((x)))
#else
#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
#endif
#ifdef HAVE_COSF
#define aluCos(x) (cosf((x)))
#else
#define aluCos(x) ((ALfloat)cos((double)(x)))
#endif
#ifdef HAVE_SINF
#define aluSin(x) (sinf((x)))
#else
#define aluSin(x) ((ALfloat)sin((double)(x)))
#endif
#ifdef HAVE_ACOSF
#define aluAcos(x) (acosf((x)))
#else
#define aluAcos(x) ((ALfloat)acos((double)(x)))
#endif
#ifdef HAVE_ASINF
#define aluAsin(x) (asinf((x)))
#else
#define aluAsin(x) ((ALfloat)asin((double)(x)))
#endif
#ifdef HAVE_ATANF
#define aluAtan(x) (atanf((x)))
#else
#define aluAtan(x) ((ALfloat)atan((double)(x)))
#endif
#ifdef HAVE_ATAN2F
#define aluAtan2(x,y) (atan2f((x),(y)))
#else
#define aluAtan2(x,y) ((ALfloat)atan2((double)(x),(double)(y)))
#endif
#ifdef HAVE_FABSF
#define aluFabs(x) (fabsf((x)))
#else
#define aluFabs(x) ((ALfloat)fabs((double)(x)))
#endif
#ifdef HAVE_LOG10F
#define aluLog10(x) (log10f((x)))
#else
#define aluLog10(x) ((ALfloat)log10((double)(x)))
#endif
#ifdef HAVE_FLOORF
#define aluFloor(x) (floorf((x)))
#else
#define aluFloor(x) ((ALfloat)floor((double)(x)))
#endif
#define QUADRANT_NUM 128
#define LUT_NUM (4 * QUADRANT_NUM)
#ifdef __cplusplus
extern "C" {
@@ -119,66 +27,29 @@ extern "C" {
struct ALsource;
struct ALbuffer;
struct DirectParams;
struct SendParams;
typedef ALvoid (*MixerFunc)(struct ALsource *self, ALCdevice *Device,
const ALvoid *RESTRICT data,
ALuint *DataPosInt, ALuint *DataPosFrac,
ALuint OutPos, ALuint SamplesToDo,
ALuint BufferSize);
typedef void (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
ALfloat *RESTRICT dst, ALuint dstlen);
enum Resampler {
PointResampler,
LinearResampler,
CubicResampler,
typedef ALvoid (*DryMixerFunc)(const struct DirectParams *params,
const ALfloat *RESTRICT data, ALuint srcchan,
ALuint OutPos, ALuint SamplesToDo,
ALuint BufferSize);
typedef ALvoid (*WetMixerFunc)(const struct SendParams *params,
const ALfloat *RESTRICT data,
ALuint OutPos, ALuint SamplesToDo,
ALuint BufferSize);
ResamplerMax,
};
enum Channel {
FRONT_LEFT = 0,
FRONT_RIGHT,
FRONT_CENTER,
LFE,
BACK_LEFT,
BACK_RIGHT,
BACK_CENTER,
SIDE_LEFT,
SIDE_RIGHT,
MAXCHANNELS
};
enum DistanceModel {
InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED,
LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED,
ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
InverseDistance = AL_INVERSE_DISTANCE,
LinearDistance = AL_LINEAR_DISTANCE,
ExponentDistance = AL_EXPONENT_DISTANCE,
DisableDistance = AL_NONE,
DefaultDistanceModel = InverseDistanceClamped
};
#define BUFFERSIZE 4096
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
#define FRACTIONBITS (14)
#define FRACTIONONE (1<<FRACTIONBITS)
#define FRACTIONMASK (FRACTIONONE-1)
/* Size for temporary stack storage of buffer data. Must be a multiple of the
* size of ALfloat, ie, 4. 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 ALfloat minf(ALfloat a, ALfloat b)
{ return ((a > b) ? b : a); }
@@ -208,6 +79,13 @@ static __inline ALint64 maxi64(ALint64 a, ALint64 b)
static __inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
{ return mini64(max, maxi64(min, val)); }
static __inline ALuint64 minu64(ALuint64 a, ALuint64 b)
{ return ((a > b) ? b : a); }
static __inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
{ return ((a > b) ? a : b); }
static __inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
{ return minu64(max, maxu64(min, val)); }
static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
{
@@ -225,81 +103,17 @@ static __inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat
}
static __inline int SetMixerFPUMode(void)
{
#if defined(_FPU_GETCW) && defined(_FPU_SETCW)
fpu_control_t fpuState, newState;
_FPU_GETCW(fpuState);
newState = fpuState&~(_FPU_EXTENDED|_FPU_DOUBLE|_FPU_SINGLE |
_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO);
newState |= _FPU_SINGLE | _FPU_RC_ZERO;
_FPU_SETCW(newState);
#else
int fpuState;
#if defined(HAVE__CONTROLFP)
fpuState = _controlfp(0, 0);
(void)_controlfp(_RC_CHOP|_PC_24, _MCW_RC|_MCW_PC);
#elif defined(HAVE_FESETROUND)
fpuState = fegetround();
fesetround(FE_TOWARDZERO);
#endif
#endif
return fpuState;
}
static __inline void RestoreFPUMode(int state)
{
#if defined(_FPU_GETCW) && defined(_FPU_SETCW)
fpu_control_t fpuState = state;
_FPU_SETCW(fpuState);
#elif defined(HAVE__CONTROLFP)
_controlfp(state, _MCW_RC|_MCW_PC);
#elif defined(HAVE_FESETROUND)
fesetround(state);
#endif
}
static __inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
{
outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
}
static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
{
return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
inVector1[2]*inVector2[2];
}
static __inline void aluNormalize(ALfloat *inVector)
{
ALfloat length, inverse_length;
length = aluSqrt(aluDotproduct(inVector, inVector));
if(length > 0.0f)
{
inverse_length = 1.0f/length;
inVector[0] *= inverse_length;
inVector[1] *= inverse_length;
inVector[2] *= inverse_length;
}
}
ALvoid aluInitPanning(ALCdevice *Device);
ALint aluCart2LUTpos(ALfloat re, ALfloat im);
ALvoid ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat *gains);
ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
MixerFunc SelectMixer(enum Resampler Resampler);
MixerFunc SelectHrtfMixer(enum Resampler Resampler);
ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo);
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
/* Caller must lock the device. */
ALvoid aluHandleDisconnect(ALCdevice *device);
extern ALfloat ConeScale;
+161 -182
View File
@@ -32,67 +32,58 @@
#include "alSource.h"
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count);
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
static ALenum AddEffectSlotArray(ALCcontext *Context, ALsizei count, const ALuint *slots);
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot);
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALsizei cur = 0;
Context = GetContextRef();
if(!Context) return;
if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
ALenum err;
ALsizei i;
err = ResizeEffectSlotArray(Context, n);
if(err != AL_NO_ERROR)
CHECK_VALUE(Context, n >= 0);
for(cur = 0;cur < n;cur++)
{
alSetError(Context, err);
n = 0;
}
for(i = 0;i < n;i++)
{
ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
if(!slot || InitEffectSlot(slot) != AL_NO_ERROR)
ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
err = AL_OUT_OF_MEMORY;
if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
{
free(slot);
// We must have run out or memory
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteAuxiliaryEffectSlots(i, effectslots);
al_free(slot);
al_throwerr(Context, err);
break;
}
LockContext(Context);
err = ResizeEffectSlotArray(Context, 1);
err = NewThunkEntry(&slot->id);
if(err == AL_NO_ERROR)
Context->ActiveEffectSlots[Context->ActiveEffectSlotCount++] = slot;
UnlockContext(Context);
if(err == AL_NO_ERROR)
err = NewThunkEntry(&slot->effectslot);
if(err == AL_NO_ERROR)
err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot);
err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->id, slot);
if(err != AL_NO_ERROR)
{
RemoveEffectSlotArray(Context, slot);
FreeThunkEntry(slot->effectslot);
FreeThunkEntry(slot->id);
ALeffectState_Destroy(slot->EffectState);
free(slot);
al_free(slot);
alSetError(Context, err);
alDeleteAuxiliaryEffectSlots(i, effectslots);
break;
al_throwerr(Context, err);
}
effectslots[i] = slot->effectslot;
effectslots[cur] = slot->id;
}
err = AddEffectSlotArray(Context, n, effectslots);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
}
al_catchany()
{
if(cur > 0)
alDeleteAuxiliaryEffectSlots(cur, effectslots);
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -100,48 +91,38 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
ALeffectslot *slot;
ALsizei i;
Context = GetContextRef();
if(!Context) return;
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
// Check that all effectslots are valid
CHECK_VALUE(Context, n >= 0);
for(i = 0;i < n;i++)
{
if((EffectSlot=LookupEffectSlot(Context, effectslots[i])) == NULL)
{
alSetError(Context, AL_INVALID_NAME);
n = 0;
break;
}
else if(EffectSlot->ref != 0)
{
alSetError(Context, AL_INVALID_OPERATION);
n = 0;
break;
}
if((slot=LookupEffectSlot(Context, effectslots[i])) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
if(slot->ref != 0)
al_throwerr(Context, AL_INVALID_OPERATION);
}
// All effectslots are valid
for(i = 0;i < n;i++)
{
// Recheck that the effectslot is valid, because there could be duplicated names
if((EffectSlot=RemoveEffectSlot(Context, effectslots[i])) == NULL)
if((slot=RemoveEffectSlot(Context, effectslots[i])) == NULL)
continue;
FreeThunkEntry(EffectSlot->effectslot);
FreeThunkEntry(slot->id);
RemoveEffectSlotArray(Context, EffectSlot);
ALeffectState_Destroy(EffectSlot->EffectState);
RemoveEffectSlotArray(Context, slot);
ALeffectState_Destroy(slot->EffectState);
memset(EffectSlot, 0, sizeof(ALeffectslot));
free(EffectSlot);
memset(slot, 0, sizeof(*slot));
al_free(slot);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -161,59 +142,49 @@ AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
return result;
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
{
ALCdevice *Device;
ALCcontext *Context;
ALeffectslot *EffectSlot;
ALeffectslot *Slot;
ALeffect *effect = NULL;
ALenum err;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
al_try
{
ALCdevice *device = Context->Device;
if((Slot=LookupEffectSlot(Context, effectslot)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
case AL_EFFECTSLOT_EFFECT: {
ALeffect *effect = NULL;
case AL_EFFECTSLOT_EFFECT:
CHECK_VALUE(Context, value == 0 || (effect=LookupEffect(device, value)) != NULL);
if(iValue == 0 ||
(effect=LookupEffect(Device, iValue)) != NULL)
{
ALenum err;
err = InitializeEffect(Device, EffectSlot, effect);
if(err != AL_NO_ERROR)
alSetError(Context, err);
else
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
} break;
err = InitializeEffect(device, Slot, effect);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
Context->UpdateSources = AL_TRUE;
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(iValue == AL_TRUE || iValue == AL_FALSE)
{
EffectSlot->AuxSendAuto = iValue;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
CHECK_VALUE(Context, value == AL_TRUE || value == AL_FALSE);
Slot->AuxSendAuto = value;
Context->UpdateSources = AL_TRUE;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues)
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
{
ALCcontext *Context;
@@ -221,122 +192,119 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
{
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
alAuxiliaryEffectSloti(effectslot, param, values[0]);
return;
}
Context = GetContextRef();
if(!Context) return;
if(LookupEffectSlot(Context, effectslot) != NULL)
al_try
{
if(LookupEffectSlot(Context, effectslot) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
ALeffectslot *Slot;
Context = GetContextRef();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
al_try
{
if((Slot=LookupEffectSlot(Context, effectslot)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
{
EffectSlot->Gain = flValue;
EffectSlot->NeedsUpdate = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
CHECK_VALUE(Context, value >= 0.0f && value <= 1.0f);
Slot->Gain = value;
Slot->NeedsUpdate = AL_TRUE;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
{
ALCcontext *Context;
switch(param)
{
case AL_EFFECTSLOT_GAIN:
alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
alAuxiliaryEffectSlotf(effectslot, param, values[0]);
return;
}
Context = GetContextRef();
if(!Context) return;
if(LookupEffectSlot(Context, effectslot) != NULL)
al_try
{
if(LookupEffectSlot(Context, effectslot) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
ALeffectslot *Slot;
Context = GetContextRef();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
al_try
{
if((Slot=LookupEffectSlot(Context, effectslot)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
*piValue = EffectSlot->effect.effect;
*value = Slot->effect.id;
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
*piValue = EffectSlot->AuxSendAuto;
*value = Slot->AuxSendAuto;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
{
ALCcontext *Context;
@@ -344,80 +312,80 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
{
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
alGetAuxiliaryEffectSloti(effectslot, param, piValues);
alGetAuxiliaryEffectSloti(effectslot, param, values);
return;
}
Context = GetContextRef();
if(!Context) return;
if(LookupEffectSlot(Context, effectslot) != NULL)
al_try
{
if(LookupEffectSlot(Context, effectslot) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
{
ALCcontext *Context;
ALeffectslot *EffectSlot;
ALeffectslot *Slot;
Context = GetContextRef();
if(!Context) return;
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
al_try
{
if((Slot=LookupEffectSlot(Context, effectslot)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
*pflValue = EffectSlot->Gain;
*value = Slot->Gain;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
{
ALCcontext *Context;
switch(param)
{
case AL_EFFECTSLOT_GAIN:
alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
alGetAuxiliaryEffectSlotf(effectslot, param, values);
return;
}
Context = GetContextRef();
if(!Context) return;
if(LookupEffectSlot(Context, effectslot) != NULL)
al_try
{
if(LookupEffectSlot(Context, effectslot) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
switch(param)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_NAME);
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -437,7 +405,7 @@ static ALvoid NoneUpdate(ALeffectState *State, ALCdevice *Device, const ALeffect
(void)Device;
(void)Slot;
}
static ALvoid NoneProcess(ALeffectState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
static ALvoid NoneProcess(ALeffectState *State, ALuint SamplesToDo, const ALfloat *RESTRICT SamplesIn, ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE])
{
(void)State;
(void)SamplesToDo;
@@ -481,23 +449,35 @@ static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot)
UnlockContext(Context);
}
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count)
static ALenum AddEffectSlotArray(ALCcontext *Context, ALsizei count, const ALuint *slots)
{
ALsizei newcount;
void *temp;
ALsizei i;
if(count <= Context->MaxActiveEffectSlots-Context->ActiveEffectSlotCount)
return AL_NO_ERROR;
LockContext(Context);
if(count > Context->MaxActiveEffectSlots-Context->ActiveEffectSlotCount)
{
ALsizei newcount;
void *temp = NULL;
newcount = Context->MaxActiveEffectSlots ?
(Context->MaxActiveEffectSlots<<1) : 1;
if(newcount <= Context->MaxActiveEffectSlots ||
!(temp=realloc(Context->ActiveEffectSlots, newcount *
sizeof(*Context->ActiveEffectSlots))))
return AL_OUT_OF_MEMORY;
Context->ActiveEffectSlots = temp;
Context->MaxActiveEffectSlots = newcount;
newcount = Context->MaxActiveEffectSlots ? (Context->MaxActiveEffectSlots<<1) : 1;
if(newcount > Context->MaxActiveEffectSlots)
temp = realloc(Context->ActiveEffectSlots,
newcount * sizeof(*Context->ActiveEffectSlots));
if(!temp)
{
UnlockContext(Context);
return AL_OUT_OF_MEMORY;
}
Context->ActiveEffectSlots = temp;
Context->MaxActiveEffectSlots = newcount;
}
for(i = 0;i < count;i++)
{
ALeffectslot *slot = LookupEffectSlot(Context, slots[i]);
assert(slot != NULL);
Context->ActiveEffectSlots[Context->ActiveEffectSlotCount++] = slot;
}
UnlockContext(Context);
return AL_NO_ERROR;
}
@@ -507,7 +487,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
ALeffectState *State = NULL;
ALenum err = AL_NO_ERROR;
LockDevice(Device);
ALCdevice_Lock(Device);
if(newtype == AL_EFFECT_NULL && EffectSlot->effect.type != AL_EFFECT_NULL)
{
State = NoneCreate();
@@ -542,19 +522,19 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
if(err != AL_NO_ERROR)
{
UnlockDevice(Device);
ALCdevice_Unlock(Device);
return err;
}
if(State)
{
int oldMode;
oldMode = SetMixerFPUMode();
FPUCtl oldMode;
SetMixerFPUMode(&oldMode);
if(ALeffectState_DeviceUpdate(State, Device) == AL_FALSE)
{
RestoreFPUMode(oldMode);
UnlockDevice(Device);
RestoreFPUMode(&oldMode);
ALCdevice_Unlock(Device);
ALeffectState_Destroy(State);
return AL_OUT_OF_MEMORY;
}
@@ -569,9 +549,9 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
* be called. */
EffectSlot->NeedsUpdate = AL_FALSE;
ALeffectState_Update(EffectSlot->EffectState, Device, EffectSlot);
UnlockDevice(Device);
ALCdevice_Unlock(Device);
RestoreFPUMode(oldMode);
RestoreFPUMode(&oldMode);
ALeffectState_Destroy(State);
State = NULL;
@@ -582,7 +562,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
else
memcpy(&EffectSlot->effect, effect, sizeof(*effect));
UnlockDevice(Device);
ALCdevice_Unlock(Device);
EffectSlot->NeedsUpdate = AL_TRUE;
}
@@ -592,7 +572,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
ALenum InitEffectSlot(ALeffectslot *slot)
{
ALint i;
ALint i, c;
if(!(slot->EffectState=NoneCreate()))
return AL_OUT_OF_MEMORY;
@@ -600,12 +580,12 @@ ALenum InitEffectSlot(ALeffectslot *slot)
slot->Gain = 1.0;
slot->AuxSendAuto = AL_TRUE;
slot->NeedsUpdate = AL_FALSE;
for(i = 0;i < BUFFERSIZE;i++)
slot->WetBuffer[i] = 0.0f;
for(i = 0;i < 1;i++)
for(c = 0;c < 1;c++)
{
slot->ClickRemoval[i] = 0.0f;
slot->PendingClicks[i] = 0.0f;
for(i = 0;i < BUFFERSIZE;i++)
slot->WetBuffer[c][i] = 0.0f;
slot->ClickRemoval[c] = 0.0f;
slot->PendingClicks[c] = 0.0f;
}
slot->ref = 0;
@@ -620,11 +600,10 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
Context->EffectSlotMap.array[pos].value = NULL;
// Release effectslot structure
ALeffectState_Destroy(temp->EffectState);
FreeThunkEntry(temp->effectslot);
FreeThunkEntry(temp->id);
memset(temp, 0, sizeof(ALeffectslot));
free(temp);
al_free(temp);
}
}
+425 -468
View File
File diff suppressed because it is too large Load Diff
+105 -100
View File
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "AL/al.h"
#include "AL/alc.h"
@@ -40,46 +41,48 @@ static void InitEffectParams(ALeffect *effect, ALenum type);
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
{
ALCcontext *Context;
ALsizei i;
ALsizei cur = 0;
Context = GetContextRef();
if(!Context) return;
if(n < 0 || IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
ALCdevice *device = Context->Device;
ALenum err;
for(i = 0;i < n;i++)
CHECK_VALUE(Context, n >= 0);
for(cur = 0;cur < n;cur++)
{
ALeffect *effect = calloc(1, sizeof(ALeffect));
if(!effect || InitEffect(effect) != AL_NO_ERROR)
err = AL_OUT_OF_MEMORY;
if(!effect || (err=InitEffect(effect)) != AL_NO_ERROR)
{
free(effect);
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteEffects(i, effects);
break;
al_throwerr(Context, err);
}
err = NewThunkEntry(&effect->effect);
err = NewThunkEntry(&effect->id);
if(err == AL_NO_ERROR)
err = InsertUIntMapEntry(&device->EffectMap, effect->effect, effect);
err = InsertUIntMapEntry(&device->EffectMap, effect->id, effect);
if(err != AL_NO_ERROR)
{
FreeThunkEntry(effect->effect);
FreeThunkEntry(effect->id);
memset(effect, 0, sizeof(ALeffect));
free(effect);
alSetError(Context, err);
alDeleteEffects(i, effects);
break;
al_throwerr(Context, err);
}
effects[i] = effect->effect;
effects[cur] = effect->id;
}
}
al_catchany()
{
if(cur > 0)
alDeleteEffects(cur, effects);
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -87,43 +90,33 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
{
ALCcontext *Context;
ALCdevice *device;
ALeffect *ALEffect;
ALeffect *Effect;
ALsizei i;
Context = GetContextRef();
if(!Context) return;
device = Context->Device;
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
// Check that all effects are valid
ALCdevice *device = Context->Device;
CHECK_VALUE(Context, n >= 0);
for(i = 0;i < n;i++)
{
if(!effects[i])
continue;
if(LookupEffect(device, effects[i]) == NULL)
{
alSetError(Context, AL_INVALID_NAME);
n = 0;
break;
}
if(effects[i] && LookupEffect(device, effects[i]) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
}
for(i = 0;i < n;i++)
{
// Recheck that the effect is valid, because there could be duplicated names
if((ALEffect=RemoveEffect(device, effects[i])) == NULL)
if((Effect=RemoveEffect(device, effects[i])) == NULL)
continue;
FreeThunkEntry(ALEffect->effect);
FreeThunkEntry(Effect->id);
memset(ALEffect, 0, sizeof(ALeffect));
free(ALEffect);
memset(Effect, 0, sizeof(*Effect));
free(Effect);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -144,7 +137,7 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
return result;
}
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -154,58 +147,65 @@ AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
if(param == AL_EFFECT_TYPE)
{
ALboolean isOk = (iValue == AL_EFFECT_NULL);
ALboolean isOk = (value == AL_EFFECT_NULL);
ALint i;
for(i = 0;!isOk && EffectList[i].val;i++)
{
if(iValue == EffectList[i].val &&
if(value == EffectList[i].val &&
!DisabledEffects[EffectList[i].type])
isOk = AL_TRUE;
}
if(isOk)
InitEffectParams(ALEffect, iValue);
InitEffectParams(ALEffect, value);
else
alSetError(Context, AL_INVALID_VALUE);
}
else
{
/* Call the appropriate handler */
ALeffect_SetParami(ALEffect, Context, param, iValue);
ALeffect_SetParami(ALEffect, Context, param, value);
}
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues)
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALeffect *ALEffect;
switch(param)
{
case AL_EFFECT_TYPE:
alEffecti(effect, param, values[0]);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_SetParamiv(ALEffect, Context, param, piValues);
ALeffect_SetParamiv(ALEffect, Context, param, values);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -215,18 +215,18 @@ AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_SetParamf(ALEffect, Context, param, flValue);
ALeffect_SetParamf(ALEffect, Context, param, value);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -236,18 +236,18 @@ AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_SetParamfv(ALEffect, Context, param, pflValues);
ALeffect_SetParamfv(ALEffect, Context, param, values);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -257,25 +257,51 @@ AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piVal
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
if(param == AL_EFFECT_TYPE)
{
*piValue = ALEffect->type;
}
*value = ALEffect->type;
else
{
/* Call the appropriate handler */
ALeffect_GetParamiv(ALEffect, Context, param, piValue);
ALeffect_GetParami(ALEffect, Context, param, value);
}
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALeffect *ALEffect;
switch(param)
{
case AL_EFFECT_TYPE:
alGetEffecti(effect, param, values);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_GetParamiv(ALEffect, Context, param, values);
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -285,18 +311,18 @@ AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piVa
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_GetParamiv(ALEffect, Context, param, piValues);
ALeffect_GetParamf(ALEffect, Context, param, value);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -306,34 +332,13 @@ AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pfl
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
if((ALEffect=LookupEffect(Device, effect)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALeffect_GetParamf(ALEffect, Context, param, pflValue);
ALeffect_GetParamfv(ALEffect, Context, param, values);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
ALCdevice *Device;
ALeffect *ALEffect;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALEffect=LookupEffect(Device, effect)) != NULL)
{
/* Call the appropriate handler */
ALeffect_GetParamfv(ALEffect, Context, param, pflValues);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
@@ -1188,7 +1193,7 @@ ALvoid ReleaseALEffects(ALCdevice *device)
device->EffectMap.array[i].value = NULL;
// Release effect structure
FreeThunkEntry(temp->effect);
FreeThunkEntry(temp->id);
memset(temp, 0, sizeof(ALeffect));
free(temp);
}
+27 -15
View File
@@ -28,21 +28,6 @@
ALboolean TrapALError = AL_FALSE;
AL_API ALenum AL_APIENTRY alGetError(void)
{
ALCcontext *Context;
ALenum errorCode;
Context = GetContextRef();
if(!Context) return AL_INVALID_OPERATION;
errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR);
ALCcontext_DecRef(Context);
return errorCode;
}
ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
{
if(TrapALError)
@@ -57,3 +42,30 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
}
CompExchangeInt(&Context->LastError, AL_NO_ERROR, errorCode);
}
AL_API ALenum AL_APIENTRY alGetError(void)
{
ALCcontext *Context;
ALenum errorCode;
Context = GetContextRef();
if(!Context)
{
if(TrapALError)
{
#ifdef _WIN32
if(IsDebuggerPresent())
DebugBreak();
#elif defined(SIGTRAP)
raise(SIGTRAP);
#endif
}
return AL_INVALID_OPERATION;
}
errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR);
ALCcontext_DecRef(Context);
return errorCode;
}
+10 -312
View File
@@ -34,297 +34,6 @@
#include "AL/al.h"
#include "AL/alc.h"
typedef struct ALenums {
const ALchar *enumName;
ALenum value;
} ALenums;
static const ALenums enumeration[] = {
// Types
{ "AL_INVALID", AL_INVALID },
{ "AL_NONE", AL_NONE },
{ "AL_FALSE", AL_FALSE },
{ "AL_TRUE", AL_TRUE },
// Source and Listener Properties
{ "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 },
{ "AL_DIRECT_CHANNELS_SOFT", AL_DIRECT_CHANNELS_SOFT },
// Source EFX Properties
{ "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
{ "AL_SOURCE_STATE", AL_SOURCE_STATE },
{ "AL_INITIAL", AL_INITIAL },
{ "AL_PLAYING", AL_PLAYING },
{ "AL_PAUSED", AL_PAUSED },
{ "AL_STOPPED", AL_STOPPED },
// Queue information
{ "AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED },
{ "AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED },
// Buffer Formats
{ "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_EXT },
{ "AL_FORMAT_STEREO_MULAW", AL_FORMAT_STEREO_MULAW },
{ "AL_FORMAT_STEREO_MULAW_EXT", AL_FORMAT_STEREO_MULAW_EXT },
{ "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 },
{ "AL_FORMAT_MONO_ALAW_EXT", AL_FORMAT_MONO_ALAW_EXT },
{ "AL_FORMAT_STEREO_ALAW_EXT", AL_FORMAT_STEREO_ALAW_EXT },
// Internal Buffer Formats
{ "AL_MONO8_SOFT", AL_MONO8_SOFT },
{ "AL_MONO16_SOFT", AL_MONO16_SOFT },
{ "AL_MONO32F_SOFT", AL_MONO32F_SOFT },
{ "AL_STEREO8_SOFT", AL_STEREO8_SOFT },
{ "AL_STEREO16_SOFT", AL_STEREO16_SOFT },
{ "AL_STEREO32F_SOFT", AL_STEREO32F_SOFT },
{ "AL_QUAD8_SOFT", AL_QUAD8_SOFT },
{ "AL_QUAD16_SOFT", AL_QUAD16_SOFT },
{ "AL_QUAD32F_SOFT", AL_QUAD32F_SOFT },
{ "AL_REAR8_SOFT", AL_REAR8_SOFT },
{ "AL_REAR16_SOFT", AL_REAR16_SOFT },
{ "AL_REAR32F_SOFT", AL_REAR32F_SOFT },
{ "AL_5POINT1_8_SOFT", AL_5POINT1_8_SOFT },
{ "AL_5POINT1_16_SOFT", AL_5POINT1_16_SOFT },
{ "AL_5POINT1_32F_SOFT", AL_5POINT1_32F_SOFT },
{ "AL_6POINT1_8_SOFT", AL_6POINT1_8_SOFT },
{ "AL_6POINT1_16_SOFT", AL_6POINT1_16_SOFT },
{ "AL_6POINT1_32F_SOFT", AL_6POINT1_32F_SOFT },
{ "AL_7POINT1_8_SOFT", AL_7POINT1_8_SOFT },
{ "AL_7POINT1_16_SOFT", AL_7POINT1_16_SOFT },
{ "AL_7POINT1_32F_SOFT", AL_7POINT1_32F_SOFT },
// Buffer Channel Configurations
{ "AL_MONO_SOFT", AL_MONO_SOFT },
{ "AL_STEREO_SOFT", AL_STEREO_SOFT },
{ "AL_QUAD_SOFT", AL_QUAD_SOFT },
{ "AL_REAR_SOFT", AL_REAR_SOFT },
{ "AL_5POINT1_SOFT", AL_5POINT1_SOFT },
{ "AL_6POINT1_SOFT", AL_6POINT1_SOFT },
{ "AL_7POINT1_SOFT", AL_7POINT1_SOFT },
// Buffer Sample Types
{ "AL_BYTE_SOFT", AL_BYTE_SOFT },
{ "AL_UNSIGNED_BYTE_SOFT", AL_UNSIGNED_BYTE_SOFT },
{ "AL_SHORT_SOFT", AL_SHORT_SOFT },
{ "AL_UNSIGNED_SHORT_SOFT", AL_UNSIGNED_SHORT_SOFT },
{ "AL_INT_SOFT", AL_INT_SOFT },
{ "AL_UNSIGNED_INT_SOFT", AL_UNSIGNED_INT_SOFT },
{ "AL_FLOAT_SOFT", AL_FLOAT_SOFT },
{ "AL_DOUBLE_SOFT", AL_DOUBLE_SOFT },
{ "AL_BYTE3_SOFT", AL_BYTE3_SOFT },
{ "AL_UNSIGNED_BYTE3_SOFT", AL_UNSIGNED_BYTE3_SOFT },
// Buffer attributes
{ "AL_FREQUENCY", AL_FREQUENCY },
{ "AL_BITS", AL_BITS },
{ "AL_CHANNELS", AL_CHANNELS },
{ "AL_SIZE", AL_SIZE },
{ "AL_INTERNAL_FORMAT_SOFT", AL_INTERNAL_FORMAT_SOFT },
{ "AL_BYTE_LENGTH_SOFT", AL_BYTE_LENGTH_SOFT },
{ "AL_SAMPLE_LENGTH_SOFT", AL_SAMPLE_LENGTH_SOFT },
{ "AL_SEC_LENGTH_SOFT", AL_SEC_LENGTH_SOFT },
// Buffer States (not supported yet)
{ "AL_UNUSED", AL_UNUSED },
{ "AL_PENDING", AL_PENDING },
{ "AL_PROCESSED", AL_PROCESSED },
// AL Error Messages
{ "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
{ "AL_VENDOR", AL_VENDOR },
{ "AL_VERSION", AL_VERSION },
{ "AL_RENDERER", AL_RENDERER },
{ "AL_EXTENSIONS", AL_EXTENSIONS },
// Global states
{ "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 },
{ "AL_DEFERRED_UPDATES_SOFT", AL_DEFERRED_UPDATES_SOFT },
// Distance Models
{ "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
{ "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
{ "AL_LOWPASS_GAIN", AL_LOWPASS_GAIN },
{ "AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF },
// Effect types
{ "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
{ "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT",AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT},
{ "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE },
// Reverb params
{ "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 },
// Dedicated Dialogue/LFE params
{ "AL_DEDICATED_GAIN", AL_DEDICATED_GAIN },
// Default
{ NULL, (ALenum)0 }
};
const struct EffectList EffectList[] = {
{ "eaxreverb", EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB },
@@ -339,7 +48,7 @@ const struct EffectList EffectList[] = {
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
{
ALboolean bIsSupported = AL_FALSE;
ALboolean ret = AL_FALSE;
ALCcontext *Context;
const char *ptr;
size_t len;
@@ -347,10 +56,10 @@ AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
Context = GetContextRef();
if(!Context) return AL_FALSE;
if(!extName)
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
CHECK_VALUE(Context, extName);
len = strlen(extName);
ptr = Context->ExtensionList;
while(ptr && *ptr)
@@ -358,7 +67,7 @@ AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
if(strncasecmp(ptr, extName, len) == 0 &&
(ptr[len] == '\0' || isspace(ptr[len])))
{
bIsSupported = AL_TRUE;
ret = AL_TRUE;
break;
}
if((ptr=strchr(ptr, ' ')) != NULL)
@@ -369,9 +78,10 @@ AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
}
}
}
al_endtry;
ALCcontext_DecRef(Context);
return bIsSupported;
return ret;
}
@@ -384,19 +94,7 @@ AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName)
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName)
{
ALsizei i;
for(i = 0;EffectList[i].ename;i++)
{
if(DisabledEffects[EffectList[i].type] &&
strcmp(EffectList[i].ename, enumName) == 0)
return (ALenum)0;
}
i = 0;
while(enumeration[i].enumName &&
strcmp(enumeration[i].enumName, enumName) != 0)
i++;
return enumeration[i].value;
if(!enumName)
return (ALenum)0;
return alcGetEnumValue(NULL, enumName);
}
+152 -170
View File
@@ -22,9 +22,8 @@
#include <stdlib.h>
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alu.h"
#include "alFilter.h"
#include "alThunk.h"
#include "alError.h"
@@ -36,46 +35,45 @@ static void InitFilterParams(ALfilter *filter, ALenum type);
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
ALCcontext *Context;
ALsizei i;
ALsizei cur = 0;
Context = GetContextRef();
if(!Context) return;
if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
ALCdevice *device = Context->Device;
ALenum err;
for(i = 0;i < n;i++)
CHECK_VALUE(Context, n >= 0);
for(cur = 0;cur < n;cur++)
{
ALfilter *filter = calloc(1, sizeof(ALfilter));
if(!filter)
{
alSetError(Context, AL_OUT_OF_MEMORY);
alDeleteFilters(i, filters);
break;
}
al_throwerr(Context, AL_OUT_OF_MEMORY);
InitFilterParams(filter, AL_FILTER_NULL);
err = NewThunkEntry(&filter->filter);
err = NewThunkEntry(&filter->id);
if(err == AL_NO_ERROR)
err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter);
err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
if(err != AL_NO_ERROR)
{
FreeThunkEntry(filter->filter);
FreeThunkEntry(filter->id);
memset(filter, 0, sizeof(ALfilter));
free(filter);
alSetError(Context, err);
alDeleteFilters(i, filters);
break;
al_throwerr(Context, err);
}
filters[i] = filter->filter;
filters[cur] = filter->id;
}
}
al_catchany()
{
if(cur > 0)
alDeleteFilters(cur, filters);
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -83,43 +81,33 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
{
ALCcontext *Context;
ALCdevice *device;
ALfilter *ALFilter;
ALfilter *Filter;
ALsizei i;
Context = GetContextRef();
if(!Context) return;
device = Context->Device;
if(n < 0)
alSetError(Context, AL_INVALID_VALUE);
else
al_try
{
// Check that all filters are valid
ALCdevice *device = Context->Device;
CHECK_VALUE(Context, n >= 0);
for(i = 0;i < n;i++)
{
if(!filters[i])
continue;
if(LookupFilter(device, filters[i]) == NULL)
{
alSetError(Context, AL_INVALID_NAME);
n = 0;
break;
}
if(filters[i] && LookupFilter(device, filters[i]) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
}
for(i = 0;i < n;i++)
{
// Recheck that the filter is valid, because there could be duplicated names
if((ALFilter=RemoveFilter(device, filters[i])) == NULL)
if((Filter=RemoveFilter(device, filters[i])) == NULL)
continue;
FreeThunkEntry(ALFilter->filter);
FreeThunkEntry(Filter->id);
memset(ALFilter, 0, sizeof(ALfilter));
free(ALFilter);
memset(Filter, 0, sizeof(*Filter));
free(Filter);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -140,7 +128,7 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
return result;
}
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -150,130 +138,28 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
switch(param)
if(param == AL_FILTER_TYPE)
{
case AL_FILTER_TYPE:
if(iValue == AL_FILTER_NULL || iValue == AL_FILTER_LOWPASS)
InitFilterParams(ALFilter, iValue);
if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
InitFilterParams(ALFilter, value);
else
alSetError(Context, AL_INVALID_VALUE);
break;
default:
/* Call the appropriate handler */
ALfilter_SetParami(ALFilter, Context, param, iValue);
break;
}
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
switch(param)
{
case AL_FILTER_TYPE:
alFilteri(filter, param, piValues[0]);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
{
/* Call the appropriate handler */
ALfilter_SetParamiv(ALFilter, Context, param, piValues);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
{
/* Call the appropriate handler */
ALfilter_SetParamf(ALFilter, Context, param, flValue);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
{
/* Call the appropriate handler */
ALfilter_SetParamfv(ALFilter, Context, param, pflValues);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
{
switch(param)
else
{
case AL_FILTER_TYPE:
*piValue = ALFilter->type;
break;
default:
/* Call the appropriate handler */
ALfilter_GetParami(ALFilter, Context, param, piValue);
break;
ALfilter_SetParami(ALFilter, Context, param, value);
}
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -282,7 +168,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piVa
switch(param)
{
case AL_FILTER_TYPE:
alGetFilteri(filter, param, piValues);
alFilteri(filter, param, values[0]);
return;
}
@@ -290,18 +176,18 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piVa
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamiv(ALFilter, Context, param, piValues);
ALfilter_SetParamiv(ALFilter, Context, param, values);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -311,18 +197,18 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pfl
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamf(ALFilter, Context, param, pflValue);
ALfilter_SetParamf(ALFilter, Context, param, value);
}
else
alSetError(Context, AL_INVALID_NAME);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
@@ -332,13 +218,109 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pf
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) != NULL)
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamfv(ALFilter, Context, param, pflValues);
ALfilter_SetParamfv(ALFilter, Context, param, values);
}
else
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
if(param == AL_FILTER_TYPE)
*value = ALFilter->type;
else
{
/* Call the appropriate handler */
ALfilter_GetParami(ALFilter, Context, param, value);
}
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
switch(param)
{
case AL_FILTER_TYPE:
alGetFilteri(filter, param, values);
return;
}
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamiv(ALFilter, Context, param, values);
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamf(ALFilter, Context, param, value);
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values)
{
ALCcontext *Context;
ALCdevice *Device;
ALfilter *ALFilter;
Context = GetContextRef();
if(!Context) return;
Device = Context->Device;
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME);
else
{
/* Call the appropriate handler */
ALfilter_GetParamfv(ALFilter, Context, param, values);
}
ALCcontext_DecRef(Context);
}
@@ -348,12 +330,12 @@ ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
ALfloat a = 0.0f;
/* Be careful with gains < 0.001, as that causes the coefficient head
* towards 1, which will flatten the signal */
if(g < 0.9999f) /* 1-epsilon */
{
/* Be careful with gains < 0.001, as that causes the coefficient head
* towards 1, which will flatten the signal */
g = maxf(g, 0.001f);
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
a = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
}
@@ -448,7 +430,7 @@ ALvoid ReleaseALFilters(ALCdevice *device)
device->FilterMap.array[i].value = NULL;
// Release filter structure
FreeThunkEntry(temp->filter);
FreeThunkEntry(temp->id);
memset(temp, 0, sizeof(ALfilter));
free(temp);
}
+295 -336
View File
@@ -26,488 +26,447 @@
#include "alListener.h"
#include "alSource.h"
AL_API ALvoid AL_APIENTRY alListenerf(ALenum eParam, ALfloat flValue)
AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
switch(eParam)
al_try
{
case AL_GAIN:
if(flValue >= 0.0f && isfinite(flValue))
{
Context->Listener.Gain = flValue;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if(flValue > 0.0f && isfinite(flValue))
{
Context->Listener.MetersPerUnit = flValue;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
switch(eParam)
{
case AL_POSITION:
if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
{
LockContext(Context);
Context->Listener.Position[0] = flValue1;
Context->Listener.Position[1] = flValue2;
Context->Listener.Position[2] = flValue3;
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
}
else
alSetError(Context, AL_INVALID_VALUE);
break;
case AL_VELOCITY:
if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3))
{
LockContext(Context);
Context->Listener.Velocity[0] = flValue1;
Context->Listener.Velocity[1] = flValue2;
Context->Listener.Velocity[2] = flValue3;
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
}
else
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
{
ALCcontext *Context;
if(pflValues)
{
switch(eParam)
switch(param)
{
case AL_GAIN:
case AL_METERS_PER_UNIT:
alListenerf(eParam, pflValues[0]);
return;
CHECK_VALUE(Context, value >= 0.0f && isfinite(value));
case AL_POSITION:
case AL_VELOCITY:
alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]);
return;
}
}
Context = GetContextRef();
if(!Context) return;
if(pflValues)
{
switch(eParam)
{
case AL_ORIENTATION:
if(isfinite(pflValues[0]) && isfinite(pflValues[1]) &&
isfinite(pflValues[2]) && isfinite(pflValues[3]) &&
isfinite(pflValues[4]) && isfinite(pflValues[5]))
{
ALfloat U[3], V[3], N[3];
/* AT then UP */
N[0] = pflValues[0];
N[1] = pflValues[1];
N[2] = pflValues[2];
aluNormalize(N);
V[0] = pflValues[3];
V[1] = pflValues[4];
V[2] = pflValues[5];
aluNormalize(V);
/* Build and normalize right-vector */
aluCrossproduct(N, V, U);
aluNormalize(U);
LockContext(Context);
Context->Listener.Forward[0] = pflValues[0];
Context->Listener.Forward[1] = pflValues[1];
Context->Listener.Forward[2] = pflValues[2];
Context->Listener.Up[0] = pflValues[3];
Context->Listener.Up[1] = pflValues[4];
Context->Listener.Up[2] = pflValues[5];
Context->Listener.Matrix[0][0] = U[0];
Context->Listener.Matrix[0][1] = V[0];
Context->Listener.Matrix[0][2] = -N[0];
Context->Listener.Matrix[0][3] = 0.0f;
Context->Listener.Matrix[1][0] = U[1];
Context->Listener.Matrix[1][1] = V[1];
Context->Listener.Matrix[1][2] = -N[1];
Context->Listener.Matrix[1][3] = 0.0f;
Context->Listener.Matrix[2][0] = U[2];
Context->Listener.Matrix[2][1] = V[2];
Context->Listener.Matrix[2][2] = -N[2];
Context->Listener.Matrix[2][3] = 0.0f;
Context->Listener.Matrix[3][0] = 0.0f;
Context->Listener.Matrix[3][1] = 0.0f;
Context->Listener.Matrix[3][2] = 0.0f;
Context->Listener.Matrix[3][3] = 1.0f;
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
}
else
alSetError(Context, AL_INVALID_VALUE);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(Context, AL_INVALID_VALUE);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alListeneri(ALenum eParam, ALint lValue)
{
ALCcontext *Context;
(void)lValue;
Context = GetContextRef();
if(!Context) return;
switch(eParam)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
{
ALCcontext *Context;
switch(eParam)
{
case AL_POSITION:
case AL_VELOCITY:
alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
return;
}
Context = GetContextRef();
if(!Context) return;
switch(eParam)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
{
ALCcontext *Context;
ALfloat flValues[6];
if(plValues)
{
switch(eParam)
{
case AL_POSITION:
case AL_VELOCITY:
alListener3f(eParam, (ALfloat)plValues[0], (ALfloat)plValues[1], (ALfloat)plValues[2]);
return;
case AL_ORIENTATION:
flValues[0] = (ALfloat)plValues[0];
flValues[1] = (ALfloat)plValues[1];
flValues[2] = (ALfloat)plValues[2];
flValues[3] = (ALfloat)plValues[3];
flValues[4] = (ALfloat)plValues[4];
flValues[5] = (ALfloat)plValues[5];
alListenerfv(eParam, flValues);
return;
}
}
Context = GetContextRef();
if(!Context) return;
if(plValues)
{
switch(eParam)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
}
}
else
alSetError(Context, AL_INVALID_VALUE);
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
if(pflValue)
{
switch(eParam)
{
case AL_GAIN:
*pflValue = Context->Listener.Gain;
Context->Listener->Gain = value;
Context->UpdateSources = AL_TRUE;
break;
case AL_METERS_PER_UNIT:
*pflValue = Context->Listener.MetersPerUnit;
CHECK_VALUE(Context, value >= 0.0f && isfinite(value));
Context->Listener->MetersPerUnit = value;
Context->UpdateSources = AL_TRUE;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
if(pflValue1 && pflValue2 && pflValue3)
al_try
{
switch(eParam)
switch(param)
{
case AL_POSITION:
CHECK_VALUE(Context, isfinite(value1) && isfinite(value2) && isfinite(value3));
LockContext(Context);
Context->Listener->Position[0] = value1;
Context->Listener->Position[1] = value2;
Context->Listener->Position[2] = value3;
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
break;
case AL_VELOCITY:
CHECK_VALUE(Context, isfinite(value1) && isfinite(value2) && isfinite(value3));
LockContext(Context);
Context->Listener->Velocity[0] = value1;
Context->Listener->Velocity[1] = value2;
Context->Listener->Velocity[2] = value3;
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
{
ALCcontext *Context;
if(values)
{
switch(param)
{
case AL_GAIN:
case AL_METERS_PER_UNIT:
alListenerf(param, values[0]);
return;
case AL_POSITION:
case AL_VELOCITY:
alListener3f(param, values[0], values[1], values[2]);
return;
}
}
Context = GetContextRef();
if(!Context) return;
al_try
{
CHECK_VALUE(Context, values);
switch(param)
{
case AL_ORIENTATION:
CHECK_VALUE(Context, isfinite(values[0]) && isfinite(values[1]) &&
isfinite(values[2]) && isfinite(values[3]) &&
isfinite(values[4]) && isfinite(values[5]));
LockContext(Context);
/* AT then UP */
Context->Listener->Forward[0] = values[0];
Context->Listener->Forward[1] = values[1];
Context->Listener->Forward[2] = values[2];
Context->Listener->Up[0] = values[3];
Context->Listener->Up[1] = values[4];
Context->Listener->Up[2] = values[5];
Context->UpdateSources = AL_TRUE;
UnlockContext(Context);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint value)
{
ALCcontext *Context;
(void)value;
Context = GetContextRef();
if(!Context) return;
al_try
{
switch(param)
{
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3)
{
ALCcontext *Context;
switch(param)
{
case AL_POSITION:
case AL_VELOCITY:
alListener3f(param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
return;
}
Context = GetContextRef();
if(!Context) return;
al_try
{
switch(param)
{
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
{
ALCcontext *Context;
if(values)
{
ALfloat fvals[6];
switch(param)
{
case AL_POSITION:
case AL_VELOCITY:
alListener3f(param, (ALfloat)values[0], (ALfloat)values[1], (ALfloat)values[2]);
return;
case AL_ORIENTATION:
fvals[0] = (ALfloat)values[0];
fvals[1] = (ALfloat)values[1];
fvals[2] = (ALfloat)values[2];
fvals[3] = (ALfloat)values[3];
fvals[4] = (ALfloat)values[4];
fvals[5] = (ALfloat)values[5];
alListenerfv(param, fvals);
return;
}
}
Context = GetContextRef();
if(!Context) return;
al_try
{
CHECK_VALUE(Context, values);
switch(param)
{
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
al_try
{
CHECK_VALUE(Context, value);
switch(param)
{
case AL_GAIN:
*value = Context->Listener->Gain;
break;
case AL_METERS_PER_UNIT:
*value = Context->Listener->MetersPerUnit;
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
al_try
{
CHECK_VALUE(Context, value1 && value2 && value3);
switch(param)
{
case AL_POSITION:
LockContext(Context);
*pflValue1 = Context->Listener.Position[0];
*pflValue2 = Context->Listener.Position[1];
*pflValue3 = Context->Listener.Position[2];
*value1 = Context->Listener->Position[0];
*value2 = Context->Listener->Position[1];
*value3 = Context->Listener->Position[2];
UnlockContext(Context);
break;
case AL_VELOCITY:
LockContext(Context);
*pflValue1 = Context->Listener.Velocity[0];
*pflValue2 = Context->Listener.Velocity[1];
*pflValue3 = Context->Listener.Velocity[2];
*value1 = Context->Listener->Velocity[0];
*value2 = Context->Listener->Velocity[1];
*value3 = Context->Listener->Velocity[2];
UnlockContext(Context);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
{
ALCcontext *Context;
switch(eParam)
switch(param)
{
case AL_GAIN:
case AL_METERS_PER_UNIT:
alGetListenerf(eParam, pflValues);
alGetListenerf(param, values);
return;
case AL_POSITION:
case AL_VELOCITY:
alGetListener3f(eParam, pflValues+0, pflValues+1, pflValues+2);
alGetListener3f(param, values+0, values+1, values+2);
return;
}
Context = GetContextRef();
if(!Context) return;
if(pflValues)
al_try
{
switch(eParam)
CHECK_VALUE(Context, values);
switch(param)
{
case AL_ORIENTATION:
LockContext(Context);
// AT then UP
pflValues[0] = Context->Listener.Forward[0];
pflValues[1] = Context->Listener.Forward[1];
pflValues[2] = Context->Listener.Forward[2];
pflValues[3] = Context->Listener.Up[0];
pflValues[4] = Context->Listener.Up[1];
pflValues[5] = Context->Listener.Up[2];
values[0] = Context->Listener->Forward[0];
values[1] = Context->Listener->Forward[1];
values[2] = Context->Listener->Forward[2];
values[3] = Context->Listener->Up[0];
values[4] = Context->Listener->Up[1];
values[5] = Context->Listener->Up[2];
UnlockContext(Context);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
if(plValue)
al_try
{
switch(eParam)
CHECK_VALUE(Context, value);
switch(param)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
if(plValue1 && plValue2 && plValue3)
al_try
{
switch (eParam)
CHECK_VALUE(Context, value1 && value2 && value3);
switch (param)
{
case AL_POSITION:
LockContext(Context);
*plValue1 = (ALint)Context->Listener.Position[0];
*plValue2 = (ALint)Context->Listener.Position[1];
*plValue3 = (ALint)Context->Listener.Position[2];
*value1 = (ALint)Context->Listener->Position[0];
*value2 = (ALint)Context->Listener->Position[1];
*value3 = (ALint)Context->Listener->Position[2];
UnlockContext(Context);
break;
case AL_VELOCITY:
LockContext(Context);
*plValue1 = (ALint)Context->Listener.Velocity[0];
*plValue2 = (ALint)Context->Listener.Velocity[1];
*plValue3 = (ALint)Context->Listener.Velocity[2];
*value1 = (ALint)Context->Listener->Velocity[0];
*value2 = (ALint)Context->Listener->Velocity[1];
*value3 = (ALint)Context->Listener->Velocity[2];
UnlockContext(Context);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API void AL_APIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
{
ALCcontext *Context;
switch(eParam)
switch(param)
{
case AL_POSITION:
case AL_VELOCITY:
alGetListener3i(eParam, plValues+0, plValues+1, plValues+2);
alGetListener3i(param, values+0, values+1, values+2);
return;
}
Context = GetContextRef();
if(!Context) return;
if(plValues)
al_try
{
switch(eParam)
CHECK_VALUE(Context, values);
switch(param)
{
case AL_ORIENTATION:
LockContext(Context);
// AT then UP
plValues[0] = (ALint)Context->Listener.Forward[0];
plValues[1] = (ALint)Context->Listener.Forward[1];
plValues[2] = (ALint)Context->Listener.Forward[2];
plValues[3] = (ALint)Context->Listener.Up[0];
plValues[4] = (ALint)Context->Listener.Up[1];
plValues[5] = (ALint)Context->Listener.Up[2];
values[0] = (ALint)Context->Listener->Forward[0];
values[1] = (ALint)Context->Listener->Forward[1];
values[2] = (ALint)Context->Listener->Forward[2];
values[3] = (ALint)Context->Listener->Up[0];
values[4] = (ALint)Context->Listener->Up[1];
values[5] = (ALint)Context->Listener->Up[2];
UnlockContext(Context);
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
+2073 -1555
View File
File diff suppressed because it is too large Load Diff
+225 -213
View File
@@ -27,7 +27,7 @@
#include "alError.h"
#include "alSource.h"
#include "alAuxEffectSlot.h"
#include "alState.h"
static const ALchar alVendor[] = "OpenAL Community";
static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
@@ -48,17 +48,20 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
Context = GetContextRef();
if(!Context) return;
switch(capability)
al_try
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_TRUE;
Context->UpdateSources = AL_TRUE;
break;
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_TRUE;
Context->UpdateSources = AL_TRUE;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -70,17 +73,20 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
Context = GetContextRef();
if(!Context) return;
switch(capability)
al_try
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_FALSE;
Context->UpdateSources = AL_TRUE;
break;
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_FALSE;
Context->UpdateSources = AL_TRUE;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -93,16 +99,19 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
Context = GetContextRef();
if(!Context) return AL_FALSE;
switch(capability)
al_try
{
case AL_SOURCE_DISTANCE_MODEL:
value = Context->SourceDistanceModel;
break;
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
value = Context->SourceDistanceModel;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
@@ -117,36 +126,39 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
Context = GetContextRef();
if(!Context) return AL_FALSE;
switch(pname)
al_try
{
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->SpeedOfSound != 0.0f)
value = AL_TRUE;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = Context->DeferUpdates;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = Context->DeferUpdates;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
@@ -161,32 +173,35 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
Context = GetContextRef();
if(!Context) return 0.0;
switch(pname)
al_try
{
case AL_DOPPLER_FACTOR:
value = (double)Context->DopplerFactor;
break;
switch(pname)
{
case AL_DOPPLER_FACTOR:
value = (ALdouble)Context->DopplerFactor;
break;
case AL_DOPPLER_VELOCITY:
value = (double)Context->DopplerVelocity;
break;
case AL_DOPPLER_VELOCITY:
value = (ALdouble)Context->DopplerVelocity;
break;
case AL_DISTANCE_MODEL:
value = (double)Context->DistanceModel;
break;
case AL_DISTANCE_MODEL:
value = (ALdouble)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
value = (double)Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
value = (ALdouble)Context->SpeedOfSound;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALdouble)Context->DeferUpdates;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALdouble)Context->DeferUpdates;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
@@ -201,32 +216,35 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
Context = GetContextRef();
if(!Context) return 0.0f;
switch(pname)
al_try
{
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 = (ALfloat)Context->DistanceModel;
break;
case AL_SPEED_OF_SOUND:
value = Context->flSpeedOfSound;
break;
case AL_SPEED_OF_SOUND:
value = Context->SpeedOfSound;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALfloat)Context->DeferUpdates;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALfloat)Context->DeferUpdates;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
@@ -241,43 +259,46 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
Context = GetContextRef();
if(!Context) return 0;
switch(pname)
al_try
{
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->SpeedOfSound;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALint)Context->DeferUpdates;
break;
case AL_DEFERRED_UPDATES_SOFT:
value = (ALint)Context->DeferUpdates;
break;
default:
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_endtry;
ALCcontext_DecRef(Context);
return value;
}
AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
{
ALCcontext *Context;
if(data)
if(values)
{
switch(pname)
{
@@ -286,7 +307,7 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
*data = alGetBoolean(pname);
values[0] = alGetBoolean(pname);
return;
}
}
@@ -294,29 +315,25 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
Context = GetContextRef();
if(!Context) return;
if(data)
al_try
{
CHECK_VALUE(Context, values);
switch(pname)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
{
// data is a NULL pointer
alSetError(Context, AL_INVALID_VALUE);
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
{
ALCcontext *Context;
if(data)
if(values)
{
switch(pname)
{
@@ -325,7 +342,7 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
*data = alGetDouble(pname);
values[0] = alGetDouble(pname);
return;
}
}
@@ -333,29 +350,25 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
Context = GetContextRef();
if(!Context) return;
if(data)
al_try
{
CHECK_VALUE(Context, values);
switch(pname)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
{
// data is a NULL pointer
alSetError(Context, AL_INVALID_VALUE);
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
{
ALCcontext *Context;
if(data)
if(values)
{
switch(pname)
{
@@ -364,7 +377,7 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
*data = alGetFloat(pname);
values[0] = alGetFloat(pname);
return;
}
}
@@ -372,29 +385,25 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
Context = GetContextRef();
if(!Context) return;
if(data)
al_try
{
CHECK_VALUE(Context, values);
switch(pname)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
{
// data is a NULL pointer
alSetError(Context, AL_INVALID_VALUE);
}
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
{
ALCcontext *Context;
if(data)
if(values)
{
switch(pname)
{
@@ -403,7 +412,7 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
*data = alGetInteger(pname);
values[0] = alGetInteger(pname);
return;
}
}
@@ -411,20 +420,16 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
Context = GetContextRef();
if(!Context) return;
if(data)
al_try
{
CHECK_VALUE(Context, values);
switch(pname)
{
default:
alSetError(Context, AL_INVALID_ENUM);
break;
al_throwerr(Context, AL_INVALID_ENUM);
}
}
else
{
// data is a NULL pointer
alSetError(Context, AL_INVALID_VALUE);
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -437,53 +442,59 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
Context = GetContextRef();
if(!Context) return NULL;
switch(pname)
al_try
{
case AL_VENDOR:
value=alVendor;
break;
switch(pname)
{
case AL_VENDOR:
value = alVendor;
break;
case AL_VERSION:
value=alVersion;
break;
case AL_VERSION:
value = alVersion;
break;
case AL_RENDERER:
value=alRenderer;
break;
case AL_RENDERER:
value = alRenderer;
break;
case AL_EXTENSIONS:
value=Context->ExtensionList;
break;
case AL_EXTENSIONS:
value = Context->ExtensionList;
break;
case AL_NO_ERROR:
value=alNoError;
break;
case AL_NO_ERROR:
value = alNoError;
break;
case AL_INVALID_NAME:
value=alErrInvalidName;
break;
case AL_INVALID_NAME:
value = alErrInvalidName;
break;
case AL_INVALID_ENUM:
value=alErrInvalidEnum;
break;
case AL_INVALID_ENUM:
value = alErrInvalidEnum;
break;
case AL_INVALID_VALUE:
value=alErrInvalidValue;
break;
case AL_INVALID_VALUE:
value = alErrInvalidValue;
break;
case AL_INVALID_OPERATION:
value=alErrInvalidOp;
break;
case AL_INVALID_OPERATION:
value = alErrInvalidOp;
break;
case AL_OUT_OF_MEMORY:
value=alErrOutOfMemory;
break;
case AL_OUT_OF_MEMORY:
value = alErrOutOfMemory;
break;
default:
value=NULL;
alSetError(Context, AL_INVALID_ENUM);
break;
default:
al_throwerr(Context, AL_INVALID_ENUM);
}
}
al_catchany()
{
value = NULL;
}
al_endtry;
ALCcontext_DecRef(Context);
@@ -497,13 +508,14 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
Context = GetContextRef();
if(!Context) return;
if(value >= 0.0f && isfinite(value))
al_try
{
CHECK_VALUE(Context, value >= 0.0f && isfinite(value));
Context->DopplerFactor = value;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -515,31 +527,33 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
Context = GetContextRef();
if(!Context) return;
if(value > 0.0f && isfinite(value))
al_try
{
Context->DopplerVelocity=value;
CHECK_VALUE(Context, value >= 0.0f && isfinite(value));
Context->DopplerVelocity = value;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
{
ALCcontext *Context;
Context = GetContextRef();
if(!Context) return;
if(flSpeedOfSound > 0.0f && isfinite(flSpeedOfSound))
al_try
{
Context->flSpeedOfSound = flSpeedOfSound;
CHECK_VALUE(Context, value > 0.0f && isfinite(value));
Context->SpeedOfSound = value;
Context->UpdateSources = AL_TRUE;
}
else
alSetError(Context, AL_INVALID_VALUE);
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -551,23 +565,21 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
Context = GetContextRef();
if(!Context) return;
switch(value)
al_try
{
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;
Context->UpdateSources = AL_TRUE;
break;
CHECK_VALUE(Context, value == AL_NONE ||
value == AL_INVERSE_DISTANCE ||
value == AL_INVERSE_DISTANCE_CLAMPED ||
value == AL_LINEAR_DISTANCE ||
value == AL_LINEAR_DISTANCE_CLAMPED ||
value == AL_EXPONENT_DISTANCE ||
value == AL_EXPONENT_DISTANCE_CLAMPED);
default:
alSetError(Context, AL_INVALID_VALUE);
break;
Context->DistanceModel = value;
if(!Context->SourceDistanceModel)
Context->UpdateSources = AL_TRUE;
}
al_endtry;
ALCcontext_DecRef(Context);
}
@@ -585,9 +597,9 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
ALboolean UpdateSources;
ALsource **src, **src_end;
ALeffectslot **slot, **slot_end;
int fpuState;
FPUCtl oldMode;
fpuState = SetMixerFPUMode();
SetMixerFPUMode(&oldMode);
LockContext(Context);
Context->DeferUpdates = AL_TRUE;
@@ -622,7 +634,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
}
UnlockContext(Context);
RestoreFPUMode(fpuState);
RestoreFPUMode(&oldMode);
}
ALCcontext_DecRef(Context);
@@ -647,7 +659,7 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
ALenum new_state;
if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
Source->lOffset != -1)
Source->Offset >= 0.0)
ApplyOffset(Source);
new_state = ExchangeInt(&Source->new_state, AL_NONE);
+1 -1
View File
@@ -66,7 +66,7 @@ ALenum NewThunkEntry(ALuint *index)
if(!NewList)
{
WriteUnlock(&ThunkLock);
ERR("Realloc failed to increase to %u enties!\n", ThunkArraySize*2);
ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2);
return AL_OUT_OF_MEMORY;
}
memset(&NewList[ThunkArraySize], 0, ThunkArraySize*sizeof(*ThunkArray));
+32 -17
View File
@@ -11,6 +11,13 @@
# possible). Note: options that are left unset may default to app- or system-
# specified values. These are the current available settings:
## disable-cpu-exts:
# Disables use of the listed CPU extensions. Certain methods may utilize CPU
# extensions when detected, and this option is useful for preventing those
# extensions from being used. The available extensions are: sse, neon.
# Specifying 'all' disables use of all extensions.
#disable-cpu-exts =
## channels:
# Sets the output channel configuration. If left unspecified, one will try to
# be detected from the system, and defaulting to stereo. The available values
@@ -39,7 +46,13 @@
## hrtf_tables
# Specifies a comma-separated list of files containing HRTF data sets. The
# listed data sets can be used in place of or in addiiton to the the built-in
# set. The format of the files are described in hrtf.txt.
# set. The format of the files are described in hrtf.txt. The filenames may
# contain these markers, which will be replaced as needed:
# %r - Device sampling rate
# %% - Percent sign (%)
# So if this is set to "kemar-%r-diffuse.mhr", it will try to open
# "kemar-44100-diffuse.mhr" if the device is using 44100hz output, or
# "kemar-48000-diffuse.mhr" if the device is using 48000hz output, etc.
#hrtf_tables =
## cf_level:
@@ -55,6 +68,14 @@
# stereo modes.
#cf_level = 0
## wide-stereo:
# Specifies that stereo sources are given a width of about 120 degrees on each
# channel, centering on -90 (left) and +90 (right), as opposed to being points
# placed at -30 (left) and +30 (right). This can be useful for surround-sound
# to give stereo sources a more encompassing sound. Note that the sound's
# overall volume will be slightly reduced to account for the extra output.
#wide-stereo = false
## frequency:
# Sets the output frequency.
#frequency = 44100
@@ -93,16 +114,6 @@
# systems with apps that try to play more sounds than the CPU can handle.
#sources = 256
## stereodup:
# Sets whether to duplicate stereo sounds behind the listener. This provides a
# "fuller" playback quality for surround sound 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 in
# front. This only has an effect when a suitable output format is used (ie.
# those that contain side and/or rear speakers).
#stereodup = true
## drivers:
# Sets the backend driver list order, comma-seperated. Unknown backends and
# duplicated names are ignored. Unlisted backends won't be considered for use
@@ -210,7 +221,7 @@
# option. The option may specify the card id (eg, device-prefix-NVidia), or
# the card id and device index (eg, device-prefix-NVidia-0). The card id is
# case-sensitive.
#defice-prefix- =
#device-prefix- =
## capture:
# Sets the device name for the default capture device.
@@ -295,11 +306,15 @@
## 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
# device. Setting autospawn to false in PulseAudio's client.conf will still
# prevent autospawning even if this is set to true.
#spawn-server = true
## allow-moves:
# Allows PulseAudio to move active streams to different devices. Note that the
# device specifier seen by applications will not be updated when this occurs,
# and neither will the AL device configuration (sample rate, format, etc).
#allow-moves = false
##
## Wave File Writer stuff
+48 -48
View File
@@ -5,6 +5,30 @@
/* Define to the library version */
#define ALSOFT_VERSION "${LIB_VERSION}"
/* Define any available alignment declaration */
#define ALIGN(x) ${ALIGN_DECL}
#ifdef __MINGW32__
#define align(x) aligned(x)
#endif
/* Define to the appropriate 'restrict' keyword */
#define RESTRICT ${RESTRICT_DECL}
/* Define if we have the C11 aligned_alloc function */
#cmakedefine HAVE_ALIGNED_ALLOC
/* Define if we have the posix_memalign function */
#cmakedefine HAVE_POSIX_MEMALIGN
/* Define if we have the _aligned_malloc function */
#cmakedefine HAVE__ALIGNED_MALLOC
/* Define if we have SSE CPU extensions */
#cmakedefine HAVE_SSE
/* Define if we have ARM Neon CPU extensions */
#cmakedefine HAVE_NEON
/* Define if we have the ALSA backend */
#cmakedefine HAVE_ALSA
@@ -41,51 +65,15 @@
/* 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 cosf function */
#cmakedefine HAVE_COSF
/* Define if we have the sinf function */
#cmakedefine HAVE_SINF
/* Define if we have the acosf function */
#cmakedefine HAVE_ACOSF
/* Define if we have the asinf function */
#cmakedefine HAVE_ASINF
/* Define if we have the atanf function */
#cmakedefine HAVE_ATANF
/* Define if we have the atan2f function */
#cmakedefine HAVE_ATAN2F
/* Define if we have the fabsf function */
#cmakedefine HAVE_FABSF
/* Define if we have the log10f function */
#cmakedefine HAVE_LOG10F
/* Define if we have the floorf function */
#cmakedefine HAVE_FLOORF
/* Define if we have the lrintf function */
#cmakedefine HAVE_LRINTF
/* Define if we have the strtof function */
#cmakedefine HAVE_STRTOF
/* Define if we have stdint.h */
#cmakedefine HAVE_STDINT_H
/* Define if we have the __int64 type */
#cmakedefine HAVE___INT64
@@ -101,16 +89,34 @@
/* Define if we have GCC's format attribute */
#cmakedefine HAVE_GCC_FORMAT
/* Define if we have stdint.h */
#cmakedefine HAVE_STDINT_H
/* Define if we have windows.h */
#cmakedefine HAVE_WINDOWS_H
/* Define if we have dlfcn.h */
#cmakedefine HAVE_DLFCN_H
/* Define if we have pthread_np.h */
#cmakedefine HAVE_PTHREAD_NP_H
/* Define if we have xmmintrin.h */
#cmakedefine HAVE_XMMINTRIN_H
/* Define if we have arm_neon.h */
#cmakedefine HAVE_ARM_NEON_H
/* Define if we have malloc.h */
#cmakedefine HAVE_MALLOC_H
/* Define if we have cpuid.h */
#cmakedefine HAVE_CPUID_H
/* Define if we have guiddef.h */
#cmakedefine HAVE_GUIDDEF_H
/* Define if we have guiddef.h */
/* Define if we have initguid.h */
#cmakedefine HAVE_INITGUID_H
/* Define if we have ieeefp.h */
@@ -119,9 +125,6 @@
/* Define if we have float.h */
#cmakedefine HAVE_FLOAT_H
/* Define if we have fpu_control.h */
#cmakedefine HAVE_FPU_CONTROL_H
/* Define if we have fenv.h */
#cmakedefine HAVE_FENV_H
@@ -131,11 +134,8 @@
/* Define if we have _controlfp() */
#cmakedefine HAVE__CONTROLFP
/* Define if we have __control87_2() */
#cmakedefine HAVE___CONTROL87_2
/* Define if we have pthread_setschedparam() */
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
/* Define if we have the restrict keyword */
#cmakedefine HAVE_RESTRICT
/* Define if we have the __restrict keyword */
#cmakedefine HAVE___RESTRICT
+213
View File
@@ -0,0 +1,213 @@
/*
* OpenAL Source Latency Example
*
* Copyright (c) 2012 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.
*/
/* This file contains an example for checking the latency of a sound. */
#include <stdio.h>
#include <assert.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "common/alhelpers.h"
#include "common/alffmpeg.h"
LPALBUFFERSAMPLESSOFT alBufferSamplesSOFT = wrap_BufferSamples;
LPALISBUFFERFORMATSUPPORTEDSOFT alIsBufferFormatSupportedSOFT;
LPALSOURCEDSOFT alSourcedSOFT;
LPALSOURCE3DSOFT alSource3dSOFT;
LPALSOURCEDVSOFT alSourcedvSOFT;
LPALGETSOURCEDSOFT alGetSourcedSOFT;
LPALGETSOURCE3DSOFT alGetSource3dSOFT;
LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
LPALSOURCEI64SOFT alSourcei64SOFT;
LPALSOURCE3I64SOFT alSource3i64SOFT;
LPALSOURCEI64VSOFT alSourcei64vSOFT;
LPALGETSOURCEI64SOFT alGetSourcei64SOFT;
LPALGETSOURCE3I64SOFT alGetSource3i64SOFT;
LPALGETSOURCEI64VSOFT alGetSourcei64vSOFT;
/* LoadBuffer loads the named audio file into an OpenAL buffer object, and
* returns the new buffer ID. */
static ALuint LoadSound(const char *filename)
{
ALenum err, format, type, channels;
ALuint rate, buffer;
size_t datalen;
void *data;
FilePtr audiofile;
StreamPtr sound;
/* Open the file and get the first stream from it */
audiofile = openAVFile(filename);
sound = getAVAudioStream(audiofile, 0);
if(!sound)
{
fprintf(stderr, "Could not open audio in %s\n", filename);
closeAVFile(audiofile);
return 0;
}
/* Get the sound format, and figure out the OpenAL format */
if(getAVAudioInfo(sound, &rate, &channels, &type) != 0)
{
fprintf(stderr, "Error getting audio info for %s\n", filename);
closeAVFile(audiofile);
return 0;
}
format = GetFormat(channels, type, alIsBufferFormatSupportedSOFT);
if(format == AL_NONE)
{
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
ChannelsName(channels), TypeName(type), filename);
closeAVFile(audiofile);
return 0;
}
/* Decode the whole audio stream to a buffer. */
data = decodeAVAudioStream(sound, &datalen);
if(!data)
{
fprintf(stderr, "Failed to read audio from %s\n", filename);
closeAVFile(audiofile);
return 0;
}
/* Buffer the audio data into a new buffer object, then free the data and
* close the file. */
buffer = 0;
alGenBuffers(1, &buffer);
alBufferSamplesSOFT(buffer, rate, format, BytesToFrames(datalen, channels, type),
channels, type, data);
free(data);
closeAVFile(audiofile);
/* Check if an error occured, and clean up if so. */
err = alGetError();
if(err != AL_NO_ERROR)
{
fprintf(stderr, "OpenAL Error: %s\n", alGetString(err));
if(alIsBuffer(buffer))
alDeleteBuffers(1, &buffer);
return 0;
}
return buffer;
}
int main(int argc, char **argv)
{
ALuint source, buffer;
ALdouble offsets[2];
ALenum state;
/* Print out usage if no file was specified */
if(argc < 2)
{
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
/* Initialize OpenAL with the default device, and check for EFX support. */
if(InitAL() != 0)
return 1;
if(!alIsExtensionPresent("AL_SOFT_source_latency"))
{
fprintf(stderr, "Error: AL_SOFT_source_latency not supported\n");
CloseAL();
return 1;
}
/* Define a macro to help load the function pointers. */
#define LOAD_PROC(x) ((x) = alGetProcAddress(#x))
LOAD_PROC(alSourcedSOFT);
LOAD_PROC(alSource3dSOFT);
LOAD_PROC(alSourcedvSOFT);
LOAD_PROC(alGetSourcedSOFT);
LOAD_PROC(alGetSource3dSOFT);
LOAD_PROC(alGetSourcedvSOFT);
LOAD_PROC(alSourcei64SOFT);
LOAD_PROC(alSource3i64SOFT);
LOAD_PROC(alSourcei64vSOFT);
LOAD_PROC(alGetSourcei64SOFT);
LOAD_PROC(alGetSource3i64SOFT);
LOAD_PROC(alGetSourcei64vSOFT);
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
{
LOAD_PROC(alBufferSamplesSOFT);
LOAD_PROC(alIsBufferFormatSupportedSOFT);
}
#undef LOAD_PROC
/* Load the sound into a buffer. */
buffer = LoadSound(argv[1]);
if(!buffer)
{
CloseAL();
return 1;
}
/* Create the source to play the sound with. */
source = 0;
alGenSources(1, &source);
alSourcei(source, AL_BUFFER, buffer);
assert(alGetError()==AL_NO_ERROR && "Failed to setup sound source");
/* Play the sound until it finishes. */
alSourcePlay(source);
do {
Sleep(10);
alGetSourcei(source, AL_SOURCE_STATE, &state);
/* Get the source offset and latency. AL_SEC_OFFSET_LATENCY_SOFT will
* place the offset (in seconds) in offsets[0], and the time until that
* offset will be heard (in seconds) in offsets[1]. */
alGetSourcedvSOFT(source, AL_SEC_OFFSET_LATENCY_SOFT, offsets);
printf("\rOffset: %f - Latency:%3u ms ", offsets[0], (ALuint)(offsets[1]*1000));
fflush(stdout);
} while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);
printf("\n");
/* All done. Delete resources, and close OpenAL. */
alDeleteSources(1, &source);
alDeleteBuffers(1, &buffer);
CloseAL();
return 0;
}
+337
View File
@@ -0,0 +1,337 @@
/*
* OpenAL Reverb Example
*
* Copyright (c) 2012 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.
*/
/* This file contains an example for applying reverb to a sound. */
#include <stdio.h>
#include <assert.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "AL/efx-presets.h"
#include "common/alhelpers.h"
#include "common/alffmpeg.h"
LPALBUFFERSAMPLESSOFT alBufferSamplesSOFT = wrap_BufferSamples;
LPALISBUFFERFORMATSUPPORTEDSOFT alIsBufferFormatSupportedSOFT;
/* Effect object functions */
LPALGENEFFECTS alGenEffects;
LPALDELETEEFFECTS alDeleteEffects;
LPALISEFFECT alIsEffect;
LPALEFFECTI alEffecti;
LPALEFFECTIV alEffectiv;
LPALEFFECTF alEffectf;
LPALEFFECTFV alEffectfv;
LPALGETEFFECTI alGetEffecti;
LPALGETEFFECTIV alGetEffectiv;
LPALGETEFFECTF alGetEffectf;
LPALGETEFFECTFV alGetEffectfv;
/* Auxiliary Effect Slot object functions */
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
/* LoadEffect loads the given reverb properties into a new OpenAL effect
* object, and returns the new effect ID. */
static ALuint LoadEffect(const EFXEAXREVERBPROPERTIES *reverb)
{
ALuint effect = 0;
ALenum err;
/* Create the effect object and check if we can do EAX reverb. */
alGenEffects(1, &effect);
if(alGetEnumValue("AL_EFFECT_EAXREVERB") != 0)
{
printf("Using EAX Reverb\n");
/* EAX Reverb is available. Set the EAX effect type then load the
* reverb properties. */
alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
alEffectf(effect, AL_EAXREVERB_DENSITY, reverb->flDensity);
alEffectf(effect, AL_EAXREVERB_DIFFUSION, reverb->flDiffusion);
alEffectf(effect, AL_EAXREVERB_GAIN, reverb->flGain);
alEffectf(effect, AL_EAXREVERB_GAINHF, reverb->flGainHF);
alEffectf(effect, AL_EAXREVERB_GAINLF, reverb->flGainLF);
alEffectf(effect, AL_EAXREVERB_DECAY_TIME, reverb->flDecayTime);
alEffectf(effect, AL_EAXREVERB_DECAY_HFRATIO, reverb->flDecayHFRatio);
alEffectf(effect, AL_EAXREVERB_DECAY_LFRATIO, reverb->flDecayLFRatio);
alEffectf(effect, AL_EAXREVERB_REFLECTIONS_GAIN, reverb->flReflectionsGain);
alEffectf(effect, AL_EAXREVERB_REFLECTIONS_DELAY, reverb->flReflectionsDelay);
alEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN, reverb->flReflectionsPan);
alEffectf(effect, AL_EAXREVERB_LATE_REVERB_GAIN, reverb->flLateReverbGain);
alEffectf(effect, AL_EAXREVERB_LATE_REVERB_DELAY, reverb->flLateReverbDelay);
alEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN, reverb->flLateReverbPan);
alEffectf(effect, AL_EAXREVERB_ECHO_TIME, reverb->flEchoTime);
alEffectf(effect, AL_EAXREVERB_ECHO_DEPTH, reverb->flEchoDepth);
alEffectf(effect, AL_EAXREVERB_MODULATION_TIME, reverb->flModulationTime);
alEffectf(effect, AL_EAXREVERB_MODULATION_DEPTH, reverb->flModulationDepth);
alEffectf(effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, reverb->flAirAbsorptionGainHF);
alEffectf(effect, AL_EAXREVERB_HFREFERENCE, reverb->flHFReference);
alEffectf(effect, AL_EAXREVERB_LFREFERENCE, reverb->flLFReference);
alEffectf(effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, reverb->flRoomRolloffFactor);
alEffecti(effect, AL_EAXREVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit);
}
else
{
printf("Using Standard Reverb\n");
/* No EAX Reverb. Set the standard reverb effect type then load the
* available reverb properties. */
alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
alEffectf(effect, AL_REVERB_DENSITY, reverb->flDensity);
alEffectf(effect, AL_REVERB_DIFFUSION, reverb->flDiffusion);
alEffectf(effect, AL_REVERB_GAIN, reverb->flGain);
alEffectf(effect, AL_REVERB_GAINHF, reverb->flGainHF);
alEffectf(effect, AL_REVERB_DECAY_TIME, reverb->flDecayTime);
alEffectf(effect, AL_REVERB_DECAY_HFRATIO, reverb->flDecayHFRatio);
alEffectf(effect, AL_REVERB_REFLECTIONS_GAIN, reverb->flReflectionsGain);
alEffectf(effect, AL_REVERB_REFLECTIONS_DELAY, reverb->flReflectionsDelay);
alEffectf(effect, AL_REVERB_LATE_REVERB_GAIN, reverb->flLateReverbGain);
alEffectf(effect, AL_REVERB_LATE_REVERB_DELAY, reverb->flLateReverbDelay);
alEffectf(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, reverb->flAirAbsorptionGainHF);
alEffectf(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, reverb->flRoomRolloffFactor);
alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit);
}
/* Check if an error occured, and clean up if so. */
err = alGetError();
if(err != AL_NO_ERROR)
{
fprintf(stderr, "OpenAL error: %s\n", alGetString(err));
if(alIsEffect(effect))
alDeleteEffects(1, &effect);
return 0;
}
return effect;
}
/* LoadBuffer loads the named audio file into an OpenAL buffer object, and
* returns the new buffer ID. */
static ALuint LoadSound(const char *filename)
{
ALenum err, format, type, channels;
ALuint rate, buffer;
size_t datalen;
void *data;
FilePtr audiofile;
StreamPtr sound;
/* Open the file and get the first stream from it */
audiofile = openAVFile(filename);
sound = getAVAudioStream(audiofile, 0);
if(!sound)
{
fprintf(stderr, "Could not open audio in %s\n", filename);
closeAVFile(audiofile);
return 0;
}
/* Get the sound format, and figure out the OpenAL format */
if(getAVAudioInfo(sound, &rate, &channels, &type) != 0)
{
fprintf(stderr, "Error getting audio info for %s\n", filename);
closeAVFile(audiofile);
return 0;
}
format = GetFormat(channels, type, alIsBufferFormatSupportedSOFT);
if(format == AL_NONE)
{
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
ChannelsName(channels), TypeName(type), filename);
closeAVFile(audiofile);
return 0;
}
/* Decode the whole audio stream to a buffer. */
data = decodeAVAudioStream(sound, &datalen);
if(!data)
{
fprintf(stderr, "Failed to read audio from %s\n", filename);
closeAVFile(audiofile);
return 0;
}
/* Buffer the audio data into a new buffer object, then free the data and
* close the file. */
buffer = 0;
alGenBuffers(1, &buffer);
alBufferSamplesSOFT(buffer, rate, format, BytesToFrames(datalen, channels, type),
channels, type, data);
free(data);
closeAVFile(audiofile);
/* Check if an error occured, and clean up if so. */
err = alGetError();
if(err != AL_NO_ERROR)
{
fprintf(stderr, "OpenAL Error: %s\n", alGetString(err));
if(alIsBuffer(buffer))
alDeleteBuffers(1, &buffer);
return 0;
}
return buffer;
}
int main(int argc, char **argv)
{
EFXEAXREVERBPROPERTIES reverb = EFX_REVERB_PRESET_GENERIC;
ALuint source, buffer, effect, slot;
ALenum state;
/* Print out usage if no file was specified */
if(argc < 2)
{
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
}
/* Initialize OpenAL with the default device, and check for EFX support. */
if(InitAL() != 0)
return 1;
if(!alcIsExtensionPresent(alcGetContextsDevice(alcGetCurrentContext()), "ALC_EXT_EFX"))
{
fprintf(stderr, "Error: EFX not supported\n");
CloseAL();
return 1;
}
/* Define a macro to help load the function pointers. */
#define LOAD_PROC(x) ((x) = alGetProcAddress(#x))
LOAD_PROC(alGenEffects);
LOAD_PROC(alDeleteEffects);
LOAD_PROC(alIsEffect);
LOAD_PROC(alEffecti);
LOAD_PROC(alEffectiv);
LOAD_PROC(alEffectf);
LOAD_PROC(alEffectfv);
LOAD_PROC(alGetEffecti);
LOAD_PROC(alGetEffectiv);
LOAD_PROC(alGetEffectf);
LOAD_PROC(alGetEffectfv);
LOAD_PROC(alGenAuxiliaryEffectSlots);
LOAD_PROC(alDeleteAuxiliaryEffectSlots);
LOAD_PROC(alIsAuxiliaryEffectSlot);
LOAD_PROC(alAuxiliaryEffectSloti);
LOAD_PROC(alAuxiliaryEffectSlotiv);
LOAD_PROC(alAuxiliaryEffectSlotf);
LOAD_PROC(alAuxiliaryEffectSlotfv);
LOAD_PROC(alGetAuxiliaryEffectSloti);
LOAD_PROC(alGetAuxiliaryEffectSlotiv);
LOAD_PROC(alGetAuxiliaryEffectSlotf);
LOAD_PROC(alGetAuxiliaryEffectSlotfv);
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
{
LOAD_PROC(alBufferSamplesSOFT);
LOAD_PROC(alIsBufferFormatSupportedSOFT);
}
#undef LOAD_PROC
/* Load the sound into a buffer. */
buffer = LoadSound(argv[1]);
if(!buffer)
{
CloseAL();
return 1;
}
/* Load the reverb into an effect. */
effect = LoadEffect(&reverb);
if(!effect)
{
alDeleteBuffers(1, &buffer);
CloseAL();
return 1;
}
/* Create the effect slot object. This is what "plays" an effect on sources
* that connect to it. */
slot = 0;
alGenAuxiliaryEffectSlots(1, &slot);
/* Tell the effect slot to use the loaded effect object. Note that the this
* effectively copies the effect properties. You can modify or delete the
* effect object afterward without affecting the effect slot.
*/
alAuxiliaryEffectSloti(slot, AL_EFFECTSLOT_EFFECT, effect);
assert(alGetError()==AL_NO_ERROR && "Failed to set effect slot");
/* Create the source to play the sound with. */
source = 0;
alGenSources(1, &source);
alSourcei(source, AL_BUFFER, buffer);
/* Connect the source to the effect slot. This tells the source to use the
* effect slot 'slot', on send #0 with the AL_FILTER_NULL filter object.
*/
alSource3i(source, AL_AUXILIARY_SEND_FILTER, slot, 0, AL_FILTER_NULL);
assert(alGetError()==AL_NO_ERROR && "Failed to setup sound source");
/* Play the sound until it finishes. */
alSourcePlay(source);
do {
Sleep(10);
alGetSourcei(source, AL_SOURCE_STATE, &state);
} while(alGetError() == AL_NO_ERROR && state == AL_PLAYING);
/* All done. Delete resources, and close OpenAL. */
alDeleteSources(1, &source);
alDeleteAuxiliaryEffectSlots(1, &slot);
alDeleteEffects(1, &effect);
alDeleteBuffers(1, &buffer);
CloseAL();
return 0;
}
+18 -17
View File
@@ -34,12 +34,12 @@
#include "AL/alc.h"
#include "AL/alext.h"
#include "alhelpers.h"
#include "alffmpeg.h"
#include "common/alhelpers.h"
#include "common/alffmpeg.h"
LPALBUFFERSAMPLESSOFT palBufferSamplesSOFT = wrap_BufferSamples;
LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT = NULL;
LPALBUFFERSAMPLESSOFT alBufferSamplesSOFT = wrap_BufferSamples;
LPALISBUFFERFORMATSUPPORTEDSOFT alIsBufferFormatSupportedSOFT = NULL;
/* Define the number of buffers and buffer size (in samples) to use. 4 buffers
@@ -144,7 +144,7 @@ static int OpenPlayerFile(StreamPlayer *player, const char *filename)
goto error;
}
player->format = GetFormat(player->channels, player->type, palIsBufferFormatSupportedSOFT);
player->format = GetFormat(player->channels, player->type, alIsBufferFormatSupportedSOFT);
if(player->format == 0)
{
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
@@ -203,9 +203,9 @@ static int StartPlayer(StreamPlayer *player)
got = readAVAudioData(player->stream, player->data, player->datasize);
if(got == 0) break;
palBufferSamplesSOFT(player->buffers[i], player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
alBufferSamplesSOFT(player->buffers[i], player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
}
if(alGetError() != AL_NO_ERROR)
{
@@ -252,9 +252,9 @@ static int UpdatePlayer(StreamPlayer *player)
got = readAVAudioData(player->stream, player->data, player->datasize);
if(got > 0)
{
palBufferSamplesSOFT(bufid, player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
alBufferSamplesSOFT(bufid, player->rate, player->format,
BytesToFrames(got, player->channels, player->type),
player->channels, player->type, player->data);
alSourceQueueBuffers(player->source, 1, &bufid);
}
if(alGetError() != AL_NO_ERROR)
@@ -304,8 +304,8 @@ int main(int argc, char **argv)
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
{
printf("AL_SOFT_buffer_samples supported!\n");
palBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
palIsBufferFormatSupportedSOFT = alGetProcAddress("alIsBufferFormatSupportedSOFT");
alBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
alIsBufferFormatSupportedSOFT = alGetProcAddress("alIsBufferFormatSupportedSOFT");
}
else
printf("AL_SOFT_buffer_samples not supported\n");
@@ -318,9 +318,10 @@ int main(int argc, char **argv)
if(!OpenPlayerFile(player, argv[i]))
continue;
fprintf(stderr, "Playing %s (%s, %s, %dhz)\n", argv[i],
TypeName(player->type), ChannelsName(player->channels),
player->rate);
printf("Playing %s (%s, %s, %dhz)\n", argv[i],
TypeName(player->type), ChannelsName(player->channels),
player->rate);
fflush(stdout);
if(!StartPlayer(player))
{
@@ -334,7 +335,7 @@ int main(int argc, char **argv)
/* All done with this file. Close it and go to the next */
ClosePlayerFile(player);
}
fprintf(stderr, "Done.\n");
printf("Done.\n");
/* All files done. Delete the player, and close OpenAL */
DeletePlayer(player);
@@ -98,20 +98,20 @@ static int64_t MemData_seek(void *opaque, int64_t offset, int whence)
switch(whence)
{
case SEEK_SET:
if(offset < 0 || offset > membuf->length)
if(offset < 0 || (uint64_t)offset > membuf->length)
return -1;
membuf->pos = offset;
break;
case SEEK_CUR:
if((offset >= 0 && offset > membuf->length-membuf->pos) ||
(offset < 0 && offset < -membuf->pos))
if((offset >= 0 && (uint64_t)offset > membuf->length-membuf->pos) ||
(offset < 0 && (uint64_t)(-offset) > membuf->pos))
return -1;
membuf->pos += offset;
break;
case SEEK_END:
if(offset > 0 || offset < -membuf->length)
if(offset > 0 || (uint64_t)(-offset) > membuf->length)
return -1;
membuf->pos = membuf->length + offset;
break;
@@ -138,8 +138,10 @@ struct MyStream {
struct PacketList *Packets;
char *DecodedData;
size_t DecodedDataSize;
AVFrame *Frame;
const uint8_t *FrameData;
size_t FrameDataSize;
FilePtr parent;
};
@@ -173,7 +175,7 @@ FilePtr openAVFile(const char *fname)
* all formats will have it in stream headers */
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
return file;
av_close_input_file(file->FmtCtx);
avformat_close_input(&file->FmtCtx);
}
free(file);
@@ -205,8 +207,7 @@ FilePtr openAVData(const char *name, char *buffer, size_t buffer_len)
{
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
return file;
av_close_input_file(file->FmtCtx);
file->FmtCtx = NULL;
avformat_close_input(&file->FmtCtx);
}
if(file->FmtCtx)
avformat_free_context(file->FmtCtx);
@@ -240,8 +241,7 @@ FilePtr openAVCustom(const char *name, void *user_data,
{
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
return file;
av_close_input_file(file->FmtCtx);
file->FmtCtx = NULL;
avformat_close_input(&file->FmtCtx);
}
if(file->FmtCtx)
avformat_free_context(file->FmtCtx);
@@ -253,6 +253,21 @@ FilePtr openAVCustom(const char *name, void *user_data,
}
void clearAVAudioData(StreamPtr stream)
{
while(stream->Packets)
{
struct PacketList *self;
self = stream->Packets;
stream->Packets = self->next;
av_free_packet(&self->pkt);
av_free(self);
}
}
void closeAVFile(FilePtr file)
{
size_t i;
@@ -275,12 +290,12 @@ void closeAVFile(FilePtr file)
}
avcodec_close(stream->CodecCtx);
av_free(stream->DecodedData);
av_free(stream->Frame);
free(stream);
}
free(file->Streams);
av_close_input_file(file->FmtCtx);
avformat_close_input(&file->FmtCtx);
free(file);
}
@@ -335,7 +350,7 @@ StreamPtr getAVAudioStream(FilePtr file, int streamnum)
/* Try to find the codec for the given codec ID, and open it */
codec = avcodec_find_decoder(stream->CodecCtx->codec_id);
if(!codec || avcodec_open(stream->CodecCtx, codec) < 0)
if(!codec || avcodec_open2(stream->CodecCtx, codec, NULL) < 0)
{
free(stream);
return NULL;
@@ -343,13 +358,15 @@ StreamPtr getAVAudioStream(FilePtr file, int streamnum)
/* Allocate space for the decoded data to be stored in before it
* gets passed to the app */
stream->DecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
if(!stream->DecodedData)
stream->Frame = avcodec_alloc_frame();
if(!stream->Frame)
{
avcodec_close(stream->CodecCtx);
free(stream);
return NULL;
}
stream->FrameData = NULL;
stream->FrameDataSize = 0;
/* Append the new stream object to the stream list. The original
* pointer will remain valid if realloc fails, so we need to use
@@ -359,7 +376,7 @@ StreamPtr getAVAudioStream(FilePtr file, int streamnum)
if(!temp)
{
avcodec_close(stream->CodecCtx);
av_free(stream->DecodedData);
av_free(stream->Frame);
free(stream);
return NULL;
}
@@ -483,9 +500,9 @@ next_packet:
return 0;
}
void *getAVAudioData(StreamPtr stream, size_t *length)
uint8_t *getAVAudioData(StreamPtr stream, size_t *length)
{
int size;
int got_frame;
int len;
if(length) *length = 0;
@@ -493,25 +510,18 @@ void *getAVAudioData(StreamPtr stream, size_t *length)
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
return NULL;
stream->DecodedDataSize = 0;
next_packet:
if(!stream->Packets && !getNextPacket(stream->parent, stream->StreamIdx))
return NULL;
/* Decode some data, and check for errors */
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
while((len=avcodec_decode_audio3(stream->CodecCtx,
(int16_t*)stream->DecodedData, &size,
&stream->Packets->pkt)) == 0)
avcodec_get_frame_defaults(stream->Frame);
while((len=avcodec_decode_audio4(stream->CodecCtx, stream->Frame,
&got_frame, &stream->Packets->pkt)) < 0)
{
struct PacketList *self;
if(size > 0)
break;
/* Packet went unread and no data was given? Drop it and try the next,
* I guess... */
/* Error? Drop it and try the next, I guess... */
self = stream->Packets;
stream->Packets = self->next;
@@ -520,13 +530,8 @@ next_packet:
if(!stream->Packets)
goto next_packet;
size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
}
if(len < 0)
return NULL;
if(len < stream->Packets->pkt.size)
{
/* Move the unread data to the front and clear the end bits */
@@ -548,14 +553,15 @@ next_packet:
av_free(self);
}
if(size == 0)
if(!got_frame || stream->Frame->nb_samples == 0)
goto next_packet;
/* Set the output buffer size */
stream->DecodedDataSize = size;
if(length) *length = stream->DecodedDataSize;
*length = av_samples_get_buffer_size(NULL, stream->CodecCtx->channels,
stream->Frame->nb_samples,
stream->CodecCtx->sample_fmt, 1);
return stream->DecodedData;
return stream->Frame->data[0];
}
size_t readAVAudioData(StreamPtr stream, void *data, size_t length)
@@ -568,34 +574,33 @@ size_t readAVAudioData(StreamPtr stream, void *data, size_t length)
while(dec < length)
{
/* If there's no decoded data, find some */
if(stream->DecodedDataSize == 0)
if(stream->FrameDataSize == 0)
{
if(getAVAudioData(stream, NULL) == NULL)
stream->FrameData = getAVAudioData(stream, &stream->FrameDataSize);
if(!stream->FrameData)
break;
}
if(stream->DecodedDataSize > 0)
if(stream->FrameDataSize > 0)
{
/* Get the amount of bytes remaining to be written, and clamp to
* the amount of decoded data we have */
size_t rem = length-dec;
if(rem > stream->DecodedDataSize)
rem = stream->DecodedDataSize;
if(rem > stream->FrameDataSize)
rem = stream->FrameDataSize;
/* Copy the data to the app's buffer and increment */
if(data != NULL)
{
memcpy(data, stream->DecodedData, rem);
memcpy(data, stream->FrameData, rem);
data = (char*)data + rem;
}
dec += rem;
/* If there's any decoded data left, move it to the front of the
* buffer for next time */
if(rem < stream->DecodedDataSize)
memmove(stream->DecodedData, &stream->DecodedData[rem],
stream->DecodedDataSize - rem);
stream->DecodedDataSize -= rem;
stream->FrameData += rem;
stream->FrameDataSize -= rem;
}
}
@@ -44,7 +44,7 @@ int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *typ
* from a previously-decoded packet is dropped. The size (in bytes) of the
* returned data buffer is stored in 'length', and the returned pointer is only
* valid until the next call to getAVAudioData or readAVAudioData. */
void *getAVAudioData(StreamPtr stream, size_t *length);
uint8_t *getAVAudioData(StreamPtr stream, size_t *length);
/* The "meat" function. Decodes audio and writes, at most, length bytes into
* the provided data buffer. Will only return less for end-of-stream or error
@@ -37,72 +37,59 @@
#include "alhelpers.h"
const char *ChannelsName(ALenum chans)
/* InitAL opens the default device and sets up a context using default
* attributes, making the program ready to call OpenAL functions. */
int InitAL(void)
{
switch(chans)
ALCdevice *device;
ALCcontext *ctx;
/* Open and initialize a device with default settings */
device = alcOpenDevice(NULL);
if(!device)
{
case AL_MONO_SOFT: return "Mono";
case AL_STEREO_SOFT: return "Stereo";
case AL_REAR_SOFT: return "Rear";
case AL_QUAD_SOFT: return "Quadraphonic";
case AL_5POINT1_SOFT: return "5.1 Surround";
case AL_6POINT1_SOFT: return "6.1 Surround";
case AL_7POINT1_SOFT: return "7.1 Surround";
fprintf(stderr, "Could not open a device!\n");
return 1;
}
return "Unknown Channels";
ctx = alcCreateContext(device, NULL);
if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
{
if(ctx != NULL)
alcDestroyContext(ctx);
alcCloseDevice(device);
fprintf(stderr, "Could not set a context!\n");
return 1;
}
printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
return 0;
}
const char *TypeName(ALenum type)
/* CloseAL closes the device belonging to the current context, and destroys the
* context. */
void CloseAL(void)
{
switch(type)
{
case AL_BYTE_SOFT: return "S8";
case AL_UNSIGNED_BYTE_SOFT: return "U8";
case AL_SHORT_SOFT: return "S16";
case AL_UNSIGNED_SHORT_SOFT: return "U16";
case AL_INT_SOFT: return "S32";
case AL_UNSIGNED_INT_SOFT: return "U32";
case AL_FLOAT_SOFT: return "Float32";
case AL_DOUBLE_SOFT: return "Float64";
}
return "Unknown Type";
}
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
{
switch(channels)
{
case AL_MONO_SOFT: size *= 1; break;
case AL_STEREO_SOFT: size *= 2; break;
case AL_REAR_SOFT: size *= 2; break;
case AL_QUAD_SOFT: size *= 4; break;
case AL_5POINT1_SOFT: size *= 6; break;
case AL_6POINT1_SOFT: size *= 7; break;
case AL_7POINT1_SOFT: size *= 8; break;
}
switch(type)
{
case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
case AL_INT_SOFT: size *= sizeof(ALint); break;
case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
}
return size;
}
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
{
return size / FramesToBytes(1, channels, type);
ALCdevice *device;
ALCcontext *ctx;
ctx = alcGetCurrentContext();
if(ctx == NULL)
return;
device = alcGetContextsDevice(ctx);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(device);
}
/* GetFormat retrieves a compatible buffer format given the channel config and
* sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
* provided, it will be called to find the closest-matching format from
* AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
* found. */
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
{
ALenum format = AL_NONE;
@@ -274,46 +261,67 @@ void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
}
int InitAL(void)
const char *ChannelsName(ALenum chans)
{
ALCdevice *device;
ALCcontext *ctx;
/* Open and initialize a device with default settings */
device = alcOpenDevice(NULL);
if(!device)
switch(chans)
{
fprintf(stderr, "Could not open a device!\n");
return 1;
case AL_MONO_SOFT: return "Mono";
case AL_STEREO_SOFT: return "Stereo";
case AL_REAR_SOFT: return "Rear";
case AL_QUAD_SOFT: return "Quadraphonic";
case AL_5POINT1_SOFT: return "5.1 Surround";
case AL_6POINT1_SOFT: return "6.1 Surround";
case AL_7POINT1_SOFT: return "7.1 Surround";
}
ctx = alcCreateContext(device, NULL);
if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
{
if(ctx != NULL)
alcDestroyContext(ctx);
alcCloseDevice(device);
fprintf(stderr, "Could not set a context!\n");
return 1;
}
return 0;
return "Unknown Channels";
}
void CloseAL(void)
const char *TypeName(ALenum type)
{
ALCdevice *device;
ALCcontext *ctx;
/* Close the device belonging to the current context, and destroy the
* context. */
ctx = alcGetCurrentContext();
if(ctx == NULL)
return;
device = alcGetContextsDevice(ctx);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(device);
switch(type)
{
case AL_BYTE_SOFT: return "S8";
case AL_UNSIGNED_BYTE_SOFT: return "U8";
case AL_SHORT_SOFT: return "S16";
case AL_UNSIGNED_SHORT_SOFT: return "U16";
case AL_INT_SOFT: return "S32";
case AL_UNSIGNED_INT_SOFT: return "U32";
case AL_FLOAT_SOFT: return "Float32";
case AL_DOUBLE_SOFT: return "Float64";
}
return "Unknown Type";
}
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
{
switch(channels)
{
case AL_MONO_SOFT: size *= 1; break;
case AL_STEREO_SOFT: size *= 2; break;
case AL_REAR_SOFT: size *= 2; break;
case AL_QUAD_SOFT: size *= 4; break;
case AL_5POINT1_SOFT: size *= 6; break;
case AL_6POINT1_SOFT: size *= 7; break;
case AL_7POINT1_SOFT: size *= 8; break;
}
switch(type)
{
case AL_BYTE_SOFT: size *= sizeof(ALbyte); break;
case AL_UNSIGNED_BYTE_SOFT: size *= sizeof(ALubyte); break;
case AL_SHORT_SOFT: size *= sizeof(ALshort); break;
case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
case AL_INT_SOFT: size *= sizeof(ALint); break;
case AL_UNSIGNED_INT_SOFT: size *= sizeof(ALuint); break;
case AL_FLOAT_SOFT: size *= sizeof(ALfloat); break;
case AL_DOUBLE_SOFT: size *= sizeof(ALdouble); break;
}
return size;
}
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
{
return size / FramesToBytes(1, channels, type);
}
+29 -48
View File
@@ -12,9 +12,9 @@ placement of sounds, making it seem as though they are coming from all around,
including above and below the listener, instead of just to the front, back, and
sides.
The built-in data set is based on the KEMAR HRTF diffuse data provided by MIT,
which can be found at <http://sound.media.mit.edu/resources/KEMAR.html>. It's
only available when using 44100hz playback.
The built-in data set is based on the KEMAR HRTF data provided by MIT, which
can be found at <http://sound.media.mit.edu/resources/KEMAR.html>. It's only
available when using 44100hz playback.
External HRTF Data Sets
@@ -26,68 +26,49 @@ own data sets, which could be better suited for their heads, or to work with
stereo speakers instead of headphones, or to support more playback sample
rates, for example.
The file format for the data sets is specified below. It uses little-endian
byte order. Certain data fields are restricted to specific values (these
restriction may be lifted in future versions of the lib).
The file format is specified below. It uses little-endian byte order.
==
ALchar magic[8] = "MinPHR00";
ALchar magic[8] = "MinPHR01";
ALuint sampleRate;
ALushort hrirCount; /* Required value: 828 */
ALushort hrirSize; /* Required value: 32 */
ALubyte evCount; /* Required value: 19 */
ALubyte hrirSize; /* Can be 8 to 128 in steps of 8. */
ALubyte evCount; /* Can be 5 to 128. */
ALushort evOffset[evCount]; /* Required values:
{ 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755,
791, 815, 827 } */
ALubyte azCount[evCount]; /* Each can be 1 to 128. */
/* NOTE: hrirCount is the sum of all azCounts */
ALshort coefficients[hrirCount][hrirSize];
ALubyte delays[hrirCount]; /* Element values must not exceed 127 */
ALubyte delays[hrirCount]; /* Each can be 0 to 63. */
==
The data is described as thus:
The file first starts with the 8-byte marker, "MinPHR00", to identify it as an
The file first starts with the 8-byte marker, "MinPHR01", to identify it as an
HRTF data set. This is followed by an unsigned 32-bit integer, specifying the
sample rate the data set is designed for (OpenAL Soft will not use it if the
output device's playback rate doesn't match).
Afterward, an unsigned 16-bit integer specifies the total number of HRIR sets
(each HRIR set is a collection of impulse responses forming the coefficients
for a convolution filter). The next unsigned 16-bit integer specifies how many
samples are in each HRIR set (the number of coefficients in the filter). The
following unsigned 8-bit integer specifies the number of elevations used by the
data set. The elevations start at the bottom, and increment upwards.
Afterward, an unsigned 8-bit integer specifies how many sample points (or
finite impulse response filter coefficients) make up each HRIR.
Following this is an array of unsigned 16-bit integers, one for each elevation
which specifies the index offset to the start of the HRIR sets for each given
elevation (the number of HRIR sets at each elevation is infered by the offset
to the next elevation, or by the total count for the last elevation).
The following unsigned 8-bit integer specifies the number of elevations used
by the data set. The elevations start at the bottom (-90 degrees), and
increment upwards. Following this is an array of unsigned 8-bit integers, one
for each elevation which specifies the number of azimuths (and thus HRIRs) that
make up each elevation. Azimuths start clockwise from the front, constructing
a full circle for the left ear only. The right ear uses the same HRIRs but in
reverse (ie, left = angle, right = 360-angle).
The actual coefficients follow. Each coefficient is a signed 16-bit sample,
with each HRIR set being a consecutive number of samples. For each elevation,
the HRIR sets first start with a neutral "in-front" set (that is, one that is
applied equally to the left and right outputs). After this, the sets follow a
clockwise pattern, constructing a full circle for the left ear only. The right
ear uses the same sets but in reverse (ie, left = angle, right = 360-angle).
After the coefficients is an array of unsigned 8-bit delay values, one for each
HRIR set. This is the delay, in samples, after recieving an input sample before
before it's added in to the convolution filter that the corresponding HRIR set
operates on and gets heard.
Note that the HRTF data is expected to be minimum-phase reconstructed. The
time delays are handled by OpenAL Soft according to the specified delay[]
values, and afterward the samples are fed into the convolution filter using the
corresponding coefficients. This allows for less processing by using a shorter
convolution filter, as it skips the first coefficients that do little more than
cause a timed delay, as well as the tailing coefficients that are used to
equalize the length of all the sets and contribute nothing.
For reference, the built-in data set uses a 32-sample convolution filter while
with each HRIR being a consecutive number of sample points. The HRIRs must be
minimum-phase. This allows the use of a smaller filter length, reducing
computation. For reference, the built-in data set uses a 32-point filter while
even the smallest data set provided by MIT used a 128-sample filter (a 4x
reduction by applying minimum-phase reconstruction). Theoretically, one could
further reduce the minimum-phase version down to a 16-sample convolution filter
with little quality loss.
further reduce the minimum-phase version down to a 16-point filter with only a
small reduction in quality.
After the coefficients is an array of unsigned 8-bit delay values, one for
each HRIR. This is the propagation delay (in samples) a signal must wait before
being convolved with the corresponding minimum-phase HRIR filter.
+510 -572
View File
File diff suppressed because it is too large Load Diff
+101 -144
View File
@@ -21,25 +21,20 @@ extern "C" {
#define ALC_APIENTRY
#endif
#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
#pragma export on
#endif
/*
* The ALCAPI, ALCAPIENTRY, and ALC_INVALID macros are deprecated, but are
* included for applications porting code from AL 1.0
*/
#define ALCAPI ALC_API
#define ALCAPIENTRY ALC_APIENTRY
#define ALC_INVALID 0
/** Deprecated macro. */
#define ALCAPI ALC_API
#define ALCAPIENTRY ALC_APIENTRY
#define ALC_INVALID 0
/** Supported ALC version? */
#define ALC_VERSION_0_1 1
#define ALC_VERSION_0_1 1
/** Opaque device handle */
typedef struct ALCdevice_struct ALCdevice;
/** Opaque context handle */
typedef struct ALCcontext_struct ALCcontext;
/** 8-bit boolean */
typedef char ALCboolean;
@@ -82,196 +77,158 @@ typedef void ALCvoid;
/* Enumerant values begin at column 50. No tabs. */
/* Boolean False. */
/** Boolean False. */
#define ALC_FALSE 0
/* Boolean True. */
/** Boolean True. */
#define ALC_TRUE 1
/**
* followed by <int> Hz
*/
/** Context attribute: <int> Hz. */
#define ALC_FREQUENCY 0x1007
/**
* followed by <int> Hz
*/
/** Context attribute: <int> Hz. */
#define ALC_REFRESH 0x1008
/**
* followed by AL_TRUE, AL_FALSE
*/
/** Context attribute: AL_TRUE or AL_FALSE. */
#define ALC_SYNC 0x1009
/**
* followed by <int> Num of requested Mono (3D) Sources
*/
/** Context attribute: <int> requested Mono (3D) Sources. */
#define ALC_MONO_SOURCES 0x1010
/**
* followed by <int> Num of requested Stereo Sources
*/
/** Context attribute: <int> requested Stereo Sources. */
#define ALC_STEREO_SOURCES 0x1011
/**
* errors
*/
/**
* No error
*/
/** No error. */
#define ALC_NO_ERROR 0
/**
* No device
*/
/** Invalid device handle. */
#define ALC_INVALID_DEVICE 0xA001
/**
* invalid context ID
*/
/** Invalid context handle. */
#define ALC_INVALID_CONTEXT 0xA002
/**
* bad enum
*/
/** Invalid enum parameter passed to an ALC call. */
#define ALC_INVALID_ENUM 0xA003
/**
* bad value
*/
/** Invalid value parameter passed to an ALC call. */
#define ALC_INVALID_VALUE 0xA004
/**
* Out of memory.
*/
/** Out of memory. */
#define ALC_OUT_OF_MEMORY 0xA005
/**
* The Specifier string for default device
*/
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
#define ALC_DEVICE_SPECIFIER 0x1005
#define ALC_EXTENSIONS 0x1006
/** Runtime ALC version. */
#define ALC_MAJOR_VERSION 0x1000
#define ALC_MINOR_VERSION 0x1001
/** Context attribute list properties. */
#define ALC_ATTRIBUTES_SIZE 0x1002
#define ALC_ALL_ATTRIBUTES 0x1003
/** String for the default device specifier. */
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
/**
* Capture extension
* String for the given device's specifier.
*
* If device handle is NULL, it is instead a null-char separated list of
* strings of known device specifiers (list ends with an empty string).
*/
#define ALC_DEVICE_SPECIFIER 0x1005
/** String for space-separated list of ALC extensions. */
#define ALC_EXTENSIONS 0x1006
/** Capture extension */
#define ALC_EXT_CAPTURE 1
/**
* String for the given capture device's specifier.
*
* If device handle is NULL, it is instead a null-char separated list of
* strings of known capture device specifiers (list ends with an empty string).
*/
#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
/** String for the default capture device specifier. */
#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
/** Number of sample frames available for capture. */
#define ALC_CAPTURE_SAMPLES 0x312
/**
* ALC_ENUMERATE_ALL_EXT enums
*/
/** Enumerate All extension */
#define ALC_ENUMERATE_ALL_EXT 1
/** String for the default extended device specifier. */
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
/**
* String for the given extended device's specifier.
*
* If device handle is NULL, it is instead a null-char separated list of
* strings of known extended device specifiers (list ends with an empty string).
*/
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
/*
* Context Management
*/
ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist );
/** Context management. */
ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist);
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context);
ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context);
ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context);
ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context);
ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void);
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context);
ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context );
ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context );
ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context );
ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context );
ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( void );
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context );
/** Device management. */
ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename);
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device);
/*
* Device Management
*/
ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename );
ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device );
/*
/**
* Error support.
* Obtain the most recent Context error
*
* Obtain the most recent Device error.
*/
ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device );
ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device);
/*
/**
* Extension support.
*
* Query for the presence of an extension, and obtain any appropriate
* function pointers and enum values.
*/
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname );
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname);
ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname);
ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname );
/** Query function. */
ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param);
ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname );
/** Capture function. */
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device);
ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device);
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device);
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
/*
* Query functions
*/
ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param );
ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data );
/*
* Capture functions
*/
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device );
ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device );
ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device );
ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
/*
* Pointer-to-function types, useful for dynamically getting ALC entry points.
*/
typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist);
typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context );
typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)( ALCcontext *context );
typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)( ALCcontext *context );
typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context );
typedef ALCcontext * (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)( void );
typedef ALCdevice * (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)( ALCcontext *context );
typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename );
typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device );
typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)( ALCdevice *device );
typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname );
typedef void * (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname );
typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname );
typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param );
typedef void (ALC_APIENTRY *LPALCGETINTEGERV)( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest );
typedef ALCdevice * (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize );
typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)( ALCdevice *device );
typedef void (ALC_APIENTRY *LPALCCAPTURESTART)( ALCdevice *device );
typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)( ALCdevice *device );
typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples );
#if defined(TARGET_OS_MAC) && TARGET_OS_MAC
#pragma export off
#endif
/** Pointer-to-function type, useful for dynamically getting ALC entry points. */
typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist);
typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context);
typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context);
typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context);
typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context);
typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void);
typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context);
typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename);
typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device);
typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device);
typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname);
typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname);
typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname);
typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param);
typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device);
typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device);
typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device);
typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
#if defined(__cplusplus)
}
+59
View File
@@ -22,6 +22,21 @@
#define AL_ALEXT_H
#include <stddef.h>
/* Define int64_t and uint64_t types */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#include <inttypes.h>
#elif defined(_WIN32) && defined(__GNUC__)
#include <stdint.h>
#elif defined(_WIN32)
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
/* Fallback if nothing above works */
#include <inttypes.h>
#endif
#include "alc.h"
#include "al.h"
#ifdef __cplusplus
extern "C" {
@@ -289,6 +304,50 @@ ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffe
#endif
#endif
#ifndef AL_EXT_STEREO_ANGLES
#define AL_EXT_STEREO_ANGLES 1
#define AL_STEREO_ANGLES 0x1030
#endif
#ifndef AL_EXT_SOURCE_RADIUS
#define AL_EXT_SOURCE_RADIUS 1
#define AL_SOURCE_RADIUS 0x1031
#endif
#ifndef AL_SOFT_source_latency
#define AL_SOFT_source_latency 1
#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200
#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201
typedef int64_t ALint64SOFT;
typedef uint64_t ALuint64SOFT;
typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble);
typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*);
typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*);
typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT);
typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT);
typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*);
typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*);
#ifdef AL_ALEXT_PROTOTYPES
AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value);
AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3);
AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values);
AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value);
AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3);
AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values);
AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value);
AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3);
AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values);
AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value);
AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3);
AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values);
#endif
#endif
#ifdef __cplusplus
}
#endif
+3
View File
@@ -2,6 +2,9 @@
#define AL_EFX_H
#include "alc.h"
#include "al.h"
#ifdef __cplusplus
extern "C" {
#endif
+1 -1
View File
@@ -8,4 +8,4 @@ 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@
Cflags: -I${includedir} -I${includedir}/AL @PKG_CONFIG_CFLAGS@
+2010
View File
File diff suppressed because it is too large Load Diff
+421
View File
@@ -0,0 +1,421 @@
# This is a makehrtf HRIR definition file. It is used to define the layout
# and source data to be processed into an OpenAL Soft compatible HRTF.
#
# This definition is used to transform an average of the left and right ear
# HRIRs from any raw dataset from the IRCAM/AKG Listen HRTF database.
#
# The datasets are available free of charge from:
#
# http://recherche.ircam.fr/equipes/salles/listen/index.html
#
# Contact for the Listen HRTF Database:
#
# Olivier Warusfel <olivier.warusfel@ircam.fr>,
# Room Acoustics Team, IRCAM
# 1, place Igor Stravinsky
# 75004 PARIS, France
rate = 44100
# The raw sets have up to 8192 samples, but 2048 seems large enough.
points = 2048
# The IRCAM sets are not as dense as the MIT set.
azimuths = 1, 6, 12, 24, 24, 24, 24, 24, 24, 24, 12, 6, 1
# No head radius was provided. Just use the average radius of 9 cm.
radius = 0.09
# The distance between the source and the listener (in meters).
distance = 1.95
# The IRCAM source azimuth is counter-clockwise, so it needs to be flipped.
# Left and right ear HRIRs (from the respective WAVE channels) are averaged.
# Repalce all occurrences of IRC_#### for the desired subject (1005 was used
# in this demonstration).
[ 3, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav"
[ 3, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P315.wav"
[ 3, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P315.wav"
[ 3, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P315.wav"
[ 3, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P315.wav"
[ 3, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P315.wav"
[ 3, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P315.wav"
[ 3, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P315.wav"
[ 3, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P315.wav"
[ 3, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P315.wav"
[ 3, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P315.wav"
[ 3, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P315.wav"
[ 3, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P315.wav"
[ 3, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P315.wav"
[ 3, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P315.wav"
[ 3, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P315.wav"
[ 3, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P315.wav"
[ 3, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P315.wav"
[ 3, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P315.wav"
[ 3, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P315.wav"
[ 3, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P315.wav"
[ 3, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P315.wav"
[ 3, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P315.wav"
[ 3, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P315.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav"
[ 4, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P330.wav"
[ 4, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P330.wav"
[ 4, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P330.wav"
[ 4, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P330.wav"
[ 4, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P330.wav"
[ 4, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P330.wav"
[ 4, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P330.wav"
[ 4, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P330.wav"
[ 4, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P330.wav"
[ 4, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P330.wav"
[ 4, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P330.wav"
[ 4, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P330.wav"
[ 4, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P330.wav"
[ 4, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P330.wav"
[ 4, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P330.wav"
[ 4, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P330.wav"
[ 4, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P330.wav"
[ 4, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P330.wav"
[ 4, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P330.wav"
[ 4, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P330.wav"
[ 4, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P330.wav"
[ 4, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P330.wav"
[ 4, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P330.wav"
[ 4, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P330.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P330.wav"
[ 5, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P345.wav"
[ 5, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P345.wav"
[ 5, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P345.wav"
[ 5, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P345.wav"
[ 5, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P345.wav"
[ 5, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P345.wav"
[ 5, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P345.wav"
[ 5, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P345.wav"
[ 5, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P345.wav"
[ 5, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P345.wav"
[ 5, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P345.wav"
[ 5, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P345.wav"
[ 5, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P345.wav"
[ 5, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P345.wav"
[ 5, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P345.wav"
[ 5, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P345.wav"
[ 5, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P345.wav"
[ 5, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P345.wav"
[ 5, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P345.wav"
[ 5, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P345.wav"
[ 5, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P345.wav"
[ 5, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P345.wav"
[ 5, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P345.wav"
[ 5, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P345.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P345.wav"
[ 6, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P000.wav"
[ 6, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P000.wav"
[ 6, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P000.wav"
[ 6, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P000.wav"
[ 6, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P000.wav"
[ 6, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P000.wav"
[ 6, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P000.wav"
[ 6, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P000.wav"
[ 6, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P000.wav"
[ 6, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P000.wav"
[ 6, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P000.wav"
[ 6, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P000.wav"
[ 6, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P000.wav"
[ 6, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P000.wav"
[ 6, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P000.wav"
[ 6, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P000.wav"
[ 6, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P000.wav"
[ 6, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P000.wav"
[ 6, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P000.wav"
[ 6, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P000.wav"
[ 6, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P000.wav"
[ 6, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P000.wav"
[ 6, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P000.wav"
[ 6, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P000.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P000.wav"
[ 7, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P015.wav"
[ 7, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P015.wav"
[ 7, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P015.wav"
[ 7, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P015.wav"
[ 7, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P015.wav"
[ 7, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P015.wav"
[ 7, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P015.wav"
[ 7, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P015.wav"
[ 7, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P015.wav"
[ 7, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P015.wav"
[ 7, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P015.wav"
[ 7, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P015.wav"
[ 7, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P015.wav"
[ 7, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P015.wav"
[ 7, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P015.wav"
[ 7, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P015.wav"
[ 7, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P015.wav"
[ 7, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P015.wav"
[ 7, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P015.wav"
[ 7, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P015.wav"
[ 7, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P015.wav"
[ 7, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P015.wav"
[ 7, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P015.wav"
[ 7, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P015.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P015.wav"
[ 8, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P030.wav"
[ 8, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P030.wav"
[ 8, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P030.wav"
[ 8, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P030.wav"
[ 8, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P030.wav"
[ 8, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P030.wav"
[ 8, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P030.wav"
[ 8, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P030.wav"
[ 8, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P030.wav"
[ 8, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P030.wav"
[ 8, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P030.wav"
[ 8, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P030.wav"
[ 8, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P030.wav"
[ 8, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P030.wav"
[ 8, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P030.wav"
[ 8, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P030.wav"
[ 8, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P030.wav"
[ 8, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P030.wav"
[ 8, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P030.wav"
[ 8, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P030.wav"
[ 8, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P030.wav"
[ 8, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P030.wav"
[ 8, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P030.wav"
[ 8, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P030.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P030.wav"
[ 9, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P045.wav"
[ 9, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P045.wav"
[ 9, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P045.wav"
[ 9, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P045.wav"
[ 9, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P045.wav"
[ 9, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P045.wav"
[ 9, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P045.wav"
[ 9, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P045.wav"
[ 9, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P045.wav"
[ 9, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P045.wav"
[ 9, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P045.wav"
[ 9, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P045.wav"
[ 9, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P045.wav"
[ 9, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P045.wav"
[ 9, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P045.wav"
[ 9, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P045.wav"
[ 9, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P045.wav"
[ 9, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P045.wav"
[ 9, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P045.wav"
[ 9, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P045.wav"
[ 9, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P045.wav"
[ 9, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P045.wav"
[ 9, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P045.wav"
[ 9, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P045.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P045.wav"
[ 10, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P060.wav"
[ 10, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P060.wav"
[ 10, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P060.wav"
[ 10, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P060.wav"
[ 10, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P060.wav"
[ 10, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P060.wav"
[ 10, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P060.wav"
[ 10, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P060.wav"
[ 10, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P060.wav"
[ 10, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P060.wav"
[ 10, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P060.wav"
[ 10, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P060.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P060.wav"
[ 11, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P075.wav"
[ 11, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P075.wav"
[ 11, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P075.wav"
[ 11, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P075.wav"
[ 11, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P075.wav"
[ 11, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P075.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P075.wav"
[ 12, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P090.wav"
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P090.wav"
+819
View File
@@ -0,0 +1,819 @@
# This is a makehrtf HRIR definition file. It is used to define the layout
# and source data to be processed into an OpenAL Soft compatible HRTF.
#
# This definition is used to transform the left ear HRIRs from the full set
# of KEMAR HRIRs provided by Bill Gardner <billg@media.mit.edu> and Keith
# Martin <kdm@media.mit.edu> of MIT Media Laboratory.
#
# The data (full.tar.Z or full.zip) is available from:
#
# http://sound.media.mit.edu/resources/KEMAR.html
#
# It is copyright 1994 by MIT Media Laboratory, and provided free of charge
# with no restrictions on use so long as the authors (above) are cited.
#
# This definition is used to generate the internal HRTF table used by OpenAL
# Soft.
# The following are the dataset metrics. They must always be specified at
# start of a definition file, but their order is not important.
# Sampling rate of the HRIR data (in hertz).
rate = 44100
# The number of points to use from the HRIR data. This should be a
# sufficiently large value (to encompass the entire impulse response). It
# cannot be smaller than the truncation size (default is 32) specified on the
# command line.
points = 512
# A list of the number of azimuths measured for each elevation. There must
# be at least 5 elevations covering the 180 degrees for the dataset to be
# viable.
azimuths = 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1
# The approximate radius (measured ear-to-ear) of the listener's head (in
# meters). This does not have to match the dataset, since makehrtf uses a
# spherical model to reconstruct the propagation delay.
radius = 0.09
# The distance between the source and the listener (in meters). This does
# have to match the dataset, but it's effect is minimal at the moment due to
# the coupled nature of OpenAL Soft's HRTF model.
distance = 1.4
# Following the metrics is the list of source HRIRs for each elevation and
# azimuth pair. They don't have to be specified in order, but the final
# composition must not be sparse. They can however begin above a number of
# elevations (as typical for HRIR measurements).
#
# The elevation and azimuth indices are used to determine the resulting polar
# coordinates following OpenAL Soft's convention (-90 degree elevation
# increasing counter-clockwise from the bottom; 0 degree azimuth increasing
# clockwise from the front).
#
# More than one HRIR can be used per source, in which case the average
# magnitude response of all references for that source is used.
#
# Source specification is of the form (~BNF):
#
# source = '[' ev_index ',' az_index ']' '=' source_ref [ '+' source_ref ]*
#
# ev_index = unsigned_integer
# az_index = unsigned_integer
# source_ref = ref_spec ':' filename
#
# ref_spec = ( wave_fmt '(' wave_parms ')' [ '@' start_sample ] ) |
# ( bin_fmt '(' bini_parms ')' [ '@' start_bytes ] ) |
# ( bin_fmt '(' binf_parms ')' [ '@' start_bytes ] ) |
# ( ascii_fmt '(' asci_parms ')' [ '@' start_elements ] ) |
# ( ascii_fmt '(' ascf_parms ')' [ '@' start_elements ] )
# filename = double_quoted_string
#
# wave_fmt = 'wave'
# wave_parms = channel
# bin_fmt = 'bin_le' | 'bin_be'
# bini_parms = 'int' ',' byte_size [ ',' bin_sig_bits ] [ ';' skip_bytes ]
# binf_parms = 'fp' ',' byte_size [ ';' skip_bytes ]
# ascii_fmt = 'ascii'
# asci_parms = 'int' ',' sig_bits [ ';' skip_elements ]
# ascf_parms = 'fp' [ ';' skip_elements ]
# start_sample = unsigned_integer
# start_bytes = unsigned_integer
# start_elements = unsigned_integer
#
# channel = unsigned_integer
# byte_size = unsigned_integer
# bin_sig_bits = signed_integer
# skip_bytes = unsigned_integer
# sig_bits = unsigned_integer
# skip_elements = unsigned_integer
#
# For bin_sig_bits, positive values mean the significant bits start at the
# MSB (padding toward the LSB) while negative values mean they start at the
# LSB.
[ 5, 0 ] = wave (0) : "./MITfull/elev-40/L-40e000a.wav"
[ 5, 1 ] = wave (0) : "./MITfull/elev-40/L-40e006a.wav"
[ 5, 2 ] = wave (0) : "./MITfull/elev-40/L-40e013a.wav"
[ 5, 3 ] = wave (0) : "./MITfull/elev-40/L-40e019a.wav"
[ 5, 4 ] = wave (0) : "./MITfull/elev-40/L-40e026a.wav"
[ 5, 5 ] = wave (0) : "./MITfull/elev-40/L-40e032a.wav"
[ 5, 6 ] = wave (0) : "./MITfull/elev-40/L-40e039a.wav"
[ 5, 7 ] = wave (0) : "./MITfull/elev-40/L-40e045a.wav"
[ 5, 8 ] = wave (0) : "./MITfull/elev-40/L-40e051a.wav"
[ 5, 9 ] = wave (0) : "./MITfull/elev-40/L-40e058a.wav"
[ 5, 10 ] = wave (0) : "./MITfull/elev-40/L-40e064a.wav"
[ 5, 11 ] = wave (0) : "./MITfull/elev-40/L-40e071a.wav"
[ 5, 12 ] = wave (0) : "./MITfull/elev-40/L-40e077a.wav"
[ 5, 13 ] = wave (0) : "./MITfull/elev-40/L-40e084a.wav"
[ 5, 14 ] = wave (0) : "./MITfull/elev-40/L-40e090a.wav"
[ 5, 15 ] = wave (0) : "./MITfull/elev-40/L-40e096a.wav"
[ 5, 16 ] = wave (0) : "./MITfull/elev-40/L-40e103a.wav"
[ 5, 17 ] = wave (0) : "./MITfull/elev-40/L-40e109a.wav"
[ 5, 18 ] = wave (0) : "./MITfull/elev-40/L-40e116a.wav"
[ 5, 19 ] = wave (0) : "./MITfull/elev-40/L-40e122a.wav"
[ 5, 20 ] = wave (0) : "./MITfull/elev-40/L-40e129a.wav"
[ 5, 21 ] = wave (0) : "./MITfull/elev-40/L-40e135a.wav"
[ 5, 22 ] = wave (0) : "./MITfull/elev-40/L-40e141a.wav"
[ 5, 23 ] = wave (0) : "./MITfull/elev-40/L-40e148a.wav"
[ 5, 24 ] = wave (0) : "./MITfull/elev-40/L-40e154a.wav"
[ 5, 25 ] = wave (0) : "./MITfull/elev-40/L-40e161a.wav"
[ 5, 26 ] = wave (0) : "./MITfull/elev-40/L-40e167a.wav"
[ 5, 27 ] = wave (0) : "./MITfull/elev-40/L-40e174a.wav"
[ 5, 28 ] = wave (0) : "./MITfull/elev-40/L-40e180a.wav"
[ 5, 29 ] = wave (0) : "./MITfull/elev-40/L-40e186a.wav"
[ 5, 30 ] = wave (0) : "./MITfull/elev-40/L-40e193a.wav"
[ 5, 31 ] = wave (0) : "./MITfull/elev-40/L-40e199a.wav"
[ 5, 32 ] = wave (0) : "./MITfull/elev-40/L-40e206a.wav"
[ 5, 33 ] = wave (0) : "./MITfull/elev-40/L-40e212a.wav"
[ 5, 34 ] = wave (0) : "./MITfull/elev-40/L-40e219a.wav"
[ 5, 35 ] = wave (0) : "./MITfull/elev-40/L-40e225a.wav"
[ 5, 36 ] = wave (0) : "./MITfull/elev-40/L-40e231a.wav"
[ 5, 37 ] = wave (0) : "./MITfull/elev-40/L-40e238a.wav"
[ 5, 38 ] = wave (0) : "./MITfull/elev-40/L-40e244a.wav"
[ 5, 39 ] = wave (0) : "./MITfull/elev-40/L-40e251a.wav"
[ 5, 40 ] = wave (0) : "./MITfull/elev-40/L-40e257a.wav"
[ 5, 41 ] = wave (0) : "./MITfull/elev-40/L-40e264a.wav"
[ 5, 42 ] = wave (0) : "./MITfull/elev-40/L-40e270a.wav"
[ 5, 43 ] = wave (0) : "./MITfull/elev-40/L-40e276a.wav"
[ 5, 44 ] = wave (0) : "./MITfull/elev-40/L-40e283a.wav"
[ 5, 45 ] = wave (0) : "./MITfull/elev-40/L-40e289a.wav"
[ 5, 46 ] = wave (0) : "./MITfull/elev-40/L-40e296a.wav"
[ 5, 47 ] = wave (0) : "./MITfull/elev-40/L-40e302a.wav"
[ 5, 48 ] = wave (0) : "./MITfull/elev-40/L-40e309a.wav"
[ 5, 49 ] = wave (0) : "./MITfull/elev-40/L-40e315a.wav"
[ 5, 50 ] = wave (0) : "./MITfull/elev-40/L-40e321a.wav"
[ 5, 51 ] = wave (0) : "./MITfull/elev-40/L-40e328a.wav"
[ 5, 52 ] = wave (0) : "./MITfull/elev-40/L-40e334a.wav"
[ 5, 53 ] = wave (0) : "./MITfull/elev-40/L-40e341a.wav"
[ 5, 54 ] = wave (0) : "./MITfull/elev-40/L-40e347a.wav"
[ 5, 55 ] = wave (0) : "./MITfull/elev-40/L-40e354a.wav"
[ 6, 0 ] = wave (0) : "./MITfull/elev-30/L-30e000a.wav"
[ 6, 1 ] = wave (0) : "./MITfull/elev-30/L-30e006a.wav"
[ 6, 2 ] = wave (0) : "./MITfull/elev-30/L-30e012a.wav"
[ 6, 3 ] = wave (0) : "./MITfull/elev-30/L-30e018a.wav"
[ 6, 4 ] = wave (0) : "./MITfull/elev-30/L-30e024a.wav"
[ 6, 5 ] = wave (0) : "./MITfull/elev-30/L-30e030a.wav"
[ 6, 6 ] = wave (0) : "./MITfull/elev-30/L-30e036a.wav"
[ 6, 7 ] = wave (0) : "./MITfull/elev-30/L-30e042a.wav"
[ 6, 8 ] = wave (0) : "./MITfull/elev-30/L-30e048a.wav"
[ 6, 9 ] = wave (0) : "./MITfull/elev-30/L-30e054a.wav"
[ 6, 10 ] = wave (0) : "./MITfull/elev-30/L-30e060a.wav"
[ 6, 11 ] = wave (0) : "./MITfull/elev-30/L-30e066a.wav"
[ 6, 12 ] = wave (0) : "./MITfull/elev-30/L-30e072a.wav"
[ 6, 13 ] = wave (0) : "./MITfull/elev-30/L-30e078a.wav"
[ 6, 14 ] = wave (0) : "./MITfull/elev-30/L-30e084a.wav"
[ 6, 15 ] = wave (0) : "./MITfull/elev-30/L-30e090a.wav"
[ 6, 16 ] = wave (0) : "./MITfull/elev-30/L-30e096a.wav"
[ 6, 17 ] = wave (0) : "./MITfull/elev-30/L-30e102a.wav"
[ 6, 18 ] = wave (0) : "./MITfull/elev-30/L-30e108a.wav"
[ 6, 19 ] = wave (0) : "./MITfull/elev-30/L-30e114a.wav"
[ 6, 20 ] = wave (0) : "./MITfull/elev-30/L-30e120a.wav"
[ 6, 21 ] = wave (0) : "./MITfull/elev-30/L-30e126a.wav"
[ 6, 22 ] = wave (0) : "./MITfull/elev-30/L-30e132a.wav"
[ 6, 23 ] = wave (0) : "./MITfull/elev-30/L-30e138a.wav"
[ 6, 24 ] = wave (0) : "./MITfull/elev-30/L-30e144a.wav"
[ 6, 25 ] = wave (0) : "./MITfull/elev-30/L-30e150a.wav"
[ 6, 26 ] = wave (0) : "./MITfull/elev-30/L-30e156a.wav"
[ 6, 27 ] = wave (0) : "./MITfull/elev-30/L-30e162a.wav"
[ 6, 28 ] = wave (0) : "./MITfull/elev-30/L-30e168a.wav"
[ 6, 29 ] = wave (0) : "./MITfull/elev-30/L-30e174a.wav"
[ 6, 30 ] = wave (0) : "./MITfull/elev-30/L-30e180a.wav"
[ 6, 31 ] = wave (0) : "./MITfull/elev-30/L-30e186a.wav"
[ 6, 32 ] = wave (0) : "./MITfull/elev-30/L-30e192a.wav"
[ 6, 33 ] = wave (0) : "./MITfull/elev-30/L-30e198a.wav"
[ 6, 34 ] = wave (0) : "./MITfull/elev-30/L-30e204a.wav"
[ 6, 35 ] = wave (0) : "./MITfull/elev-30/L-30e210a.wav"
[ 6, 36 ] = wave (0) : "./MITfull/elev-30/L-30e216a.wav"
[ 6, 37 ] = wave (0) : "./MITfull/elev-30/L-30e222a.wav"
[ 6, 38 ] = wave (0) : "./MITfull/elev-30/L-30e228a.wav"
[ 6, 39 ] = wave (0) : "./MITfull/elev-30/L-30e234a.wav"
[ 6, 40 ] = wave (0) : "./MITfull/elev-30/L-30e240a.wav"
[ 6, 41 ] = wave (0) : "./MITfull/elev-30/L-30e246a.wav"
[ 6, 42 ] = wave (0) : "./MITfull/elev-30/L-30e252a.wav"
[ 6, 43 ] = wave (0) : "./MITfull/elev-30/L-30e258a.wav"
[ 6, 44 ] = wave (0) : "./MITfull/elev-30/L-30e264a.wav"
[ 6, 45 ] = wave (0) : "./MITfull/elev-30/L-30e270a.wav"
[ 6, 46 ] = wave (0) : "./MITfull/elev-30/L-30e276a.wav"
[ 6, 47 ] = wave (0) : "./MITfull/elev-30/L-30e282a.wav"
[ 6, 48 ] = wave (0) : "./MITfull/elev-30/L-30e288a.wav"
[ 6, 49 ] = wave (0) : "./MITfull/elev-30/L-30e294a.wav"
[ 6, 50 ] = wave (0) : "./MITfull/elev-30/L-30e300a.wav"
[ 6, 51 ] = wave (0) : "./MITfull/elev-30/L-30e306a.wav"
[ 6, 52 ] = wave (0) : "./MITfull/elev-30/L-30e312a.wav"
[ 6, 53 ] = wave (0) : "./MITfull/elev-30/L-30e318a.wav"
[ 6, 54 ] = wave (0) : "./MITfull/elev-30/L-30e324a.wav"
[ 6, 55 ] = wave (0) : "./MITfull/elev-30/L-30e330a.wav"
[ 6, 56 ] = wave (0) : "./MITfull/elev-30/L-30e336a.wav"
[ 6, 57 ] = wave (0) : "./MITfull/elev-30/L-30e342a.wav"
[ 6, 58 ] = wave (0) : "./MITfull/elev-30/L-30e348a.wav"
[ 6, 59 ] = wave (0) : "./MITfull/elev-30/L-30e354a.wav"
[ 7, 0 ] = wave (0) : "./MITfull/elev-20/L-20e000a.wav"
[ 7, 1 ] = wave (0) : "./MITfull/elev-20/L-20e005a.wav"
[ 7, 2 ] = wave (0) : "./MITfull/elev-20/L-20e010a.wav"
[ 7, 3 ] = wave (0) : "./MITfull/elev-20/L-20e015a.wav"
[ 7, 4 ] = wave (0) : "./MITfull/elev-20/L-20e020a.wav"
[ 7, 5 ] = wave (0) : "./MITfull/elev-20/L-20e025a.wav"
[ 7, 6 ] = wave (0) : "./MITfull/elev-20/L-20e030a.wav"
[ 7, 7 ] = wave (0) : "./MITfull/elev-20/L-20e035a.wav"
[ 7, 8 ] = wave (0) : "./MITfull/elev-20/L-20e040a.wav"
[ 7, 9 ] = wave (0) : "./MITfull/elev-20/L-20e045a.wav"
[ 7, 10 ] = wave (0) : "./MITfull/elev-20/L-20e050a.wav"
[ 7, 11 ] = wave (0) : "./MITfull/elev-20/L-20e055a.wav"
[ 7, 12 ] = wave (0) : "./MITfull/elev-20/L-20e060a.wav"
[ 7, 13 ] = wave (0) : "./MITfull/elev-20/L-20e065a.wav"
[ 7, 14 ] = wave (0) : "./MITfull/elev-20/L-20e070a.wav"
[ 7, 15 ] = wave (0) : "./MITfull/elev-20/L-20e075a.wav"
[ 7, 16 ] = wave (0) : "./MITfull/elev-20/L-20e080a.wav"
[ 7, 17 ] = wave (0) : "./MITfull/elev-20/L-20e085a.wav"
[ 7, 18 ] = wave (0) : "./MITfull/elev-20/L-20e090a.wav"
[ 7, 19 ] = wave (0) : "./MITfull/elev-20/L-20e095a.wav"
[ 7, 20 ] = wave (0) : "./MITfull/elev-20/L-20e100a.wav"
[ 7, 21 ] = wave (0) : "./MITfull/elev-20/L-20e105a.wav"
[ 7, 22 ] = wave (0) : "./MITfull/elev-20/L-20e110a.wav"
[ 7, 23 ] = wave (0) : "./MITfull/elev-20/L-20e115a.wav"
[ 7, 24 ] = wave (0) : "./MITfull/elev-20/L-20e120a.wav"
[ 7, 25 ] = wave (0) : "./MITfull/elev-20/L-20e125a.wav"
[ 7, 26 ] = wave (0) : "./MITfull/elev-20/L-20e130a.wav"
[ 7, 27 ] = wave (0) : "./MITfull/elev-20/L-20e135a.wav"
[ 7, 28 ] = wave (0) : "./MITfull/elev-20/L-20e140a.wav"
[ 7, 29 ] = wave (0) : "./MITfull/elev-20/L-20e145a.wav"
[ 7, 30 ] = wave (0) : "./MITfull/elev-20/L-20e150a.wav"
[ 7, 31 ] = wave (0) : "./MITfull/elev-20/L-20e155a.wav"
[ 7, 32 ] = wave (0) : "./MITfull/elev-20/L-20e160a.wav"
[ 7, 33 ] = wave (0) : "./MITfull/elev-20/L-20e165a.wav"
[ 7, 34 ] = wave (0) : "./MITfull/elev-20/L-20e170a.wav"
[ 7, 35 ] = wave (0) : "./MITfull/elev-20/L-20e175a.wav"
[ 7, 36 ] = wave (0) : "./MITfull/elev-20/L-20e180a.wav"
[ 7, 37 ] = wave (0) : "./MITfull/elev-20/L-20e185a.wav"
[ 7, 38 ] = wave (0) : "./MITfull/elev-20/L-20e190a.wav"
[ 7, 39 ] = wave (0) : "./MITfull/elev-20/L-20e195a.wav"
[ 7, 40 ] = wave (0) : "./MITfull/elev-20/L-20e200a.wav"
[ 7, 41 ] = wave (0) : "./MITfull/elev-20/L-20e205a.wav"
[ 7, 42 ] = wave (0) : "./MITfull/elev-20/L-20e210a.wav"
[ 7, 43 ] = wave (0) : "./MITfull/elev-20/L-20e215a.wav"
[ 7, 44 ] = wave (0) : "./MITfull/elev-20/L-20e220a.wav"
[ 7, 45 ] = wave (0) : "./MITfull/elev-20/L-20e225a.wav"
[ 7, 46 ] = wave (0) : "./MITfull/elev-20/L-20e230a.wav"
[ 7, 47 ] = wave (0) : "./MITfull/elev-20/L-20e235a.wav"
[ 7, 48 ] = wave (0) : "./MITfull/elev-20/L-20e240a.wav"
[ 7, 49 ] = wave (0) : "./MITfull/elev-20/L-20e245a.wav"
[ 7, 50 ] = wave (0) : "./MITfull/elev-20/L-20e250a.wav"
[ 7, 51 ] = wave (0) : "./MITfull/elev-20/L-20e255a.wav"
[ 7, 52 ] = wave (0) : "./MITfull/elev-20/L-20e260a.wav"
[ 7, 53 ] = wave (0) : "./MITfull/elev-20/L-20e265a.wav"
[ 7, 54 ] = wave (0) : "./MITfull/elev-20/L-20e270a.wav"
[ 7, 55 ] = wave (0) : "./MITfull/elev-20/L-20e275a.wav"
[ 7, 56 ] = wave (0) : "./MITfull/elev-20/L-20e280a.wav"
[ 7, 57 ] = wave (0) : "./MITfull/elev-20/L-20e285a.wav"
[ 7, 58 ] = wave (0) : "./MITfull/elev-20/L-20e290a.wav"
[ 7, 59 ] = wave (0) : "./MITfull/elev-20/L-20e295a.wav"
[ 7, 60 ] = wave (0) : "./MITfull/elev-20/L-20e300a.wav"
[ 7, 61 ] = wave (0) : "./MITfull/elev-20/L-20e305a.wav"
[ 7, 62 ] = wave (0) : "./MITfull/elev-20/L-20e310a.wav"
[ 7, 63 ] = wave (0) : "./MITfull/elev-20/L-20e315a.wav"
[ 7, 64 ] = wave (0) : "./MITfull/elev-20/L-20e320a.wav"
[ 7, 65 ] = wave (0) : "./MITfull/elev-20/L-20e325a.wav"
[ 7, 66 ] = wave (0) : "./MITfull/elev-20/L-20e330a.wav"
[ 7, 67 ] = wave (0) : "./MITfull/elev-20/L-20e335a.wav"
[ 7, 68 ] = wave (0) : "./MITfull/elev-20/L-20e340a.wav"
[ 7, 69 ] = wave (0) : "./MITfull/elev-20/L-20e345a.wav"
[ 7, 70 ] = wave (0) : "./MITfull/elev-20/L-20e350a.wav"
[ 7, 71 ] = wave (0) : "./MITfull/elev-20/L-20e355a.wav"
[ 8, 0 ] = wave (0) : "./MITfull/elev-10/L-10e000a.wav"
[ 8, 1 ] = wave (0) : "./MITfull/elev-10/L-10e005a.wav"
[ 8, 2 ] = wave (0) : "./MITfull/elev-10/L-10e010a.wav"
[ 8, 3 ] = wave (0) : "./MITfull/elev-10/L-10e015a.wav"
[ 8, 4 ] = wave (0) : "./MITfull/elev-10/L-10e020a.wav"
[ 8, 5 ] = wave (0) : "./MITfull/elev-10/L-10e025a.wav"
[ 8, 6 ] = wave (0) : "./MITfull/elev-10/L-10e030a.wav"
[ 8, 7 ] = wave (0) : "./MITfull/elev-10/L-10e035a.wav"
[ 8, 8 ] = wave (0) : "./MITfull/elev-10/L-10e040a.wav"
[ 8, 9 ] = wave (0) : "./MITfull/elev-10/L-10e045a.wav"
[ 8, 10 ] = wave (0) : "./MITfull/elev-10/L-10e050a.wav"
[ 8, 11 ] = wave (0) : "./MITfull/elev-10/L-10e055a.wav"
[ 8, 12 ] = wave (0) : "./MITfull/elev-10/L-10e060a.wav"
[ 8, 13 ] = wave (0) : "./MITfull/elev-10/L-10e065a.wav"
[ 8, 14 ] = wave (0) : "./MITfull/elev-10/L-10e070a.wav"
[ 8, 15 ] = wave (0) : "./MITfull/elev-10/L-10e075a.wav"
[ 8, 16 ] = wave (0) : "./MITfull/elev-10/L-10e080a.wav"
[ 8, 17 ] = wave (0) : "./MITfull/elev-10/L-10e085a.wav"
[ 8, 18 ] = wave (0) : "./MITfull/elev-10/L-10e090a.wav"
[ 8, 19 ] = wave (0) : "./MITfull/elev-10/L-10e095a.wav"
[ 8, 20 ] = wave (0) : "./MITfull/elev-10/L-10e100a.wav"
[ 8, 21 ] = wave (0) : "./MITfull/elev-10/L-10e105a.wav"
[ 8, 22 ] = wave (0) : "./MITfull/elev-10/L-10e110a.wav"
[ 8, 23 ] = wave (0) : "./MITfull/elev-10/L-10e115a.wav"
[ 8, 24 ] = wave (0) : "./MITfull/elev-10/L-10e120a.wav"
[ 8, 25 ] = wave (0) : "./MITfull/elev-10/L-10e125a.wav"
[ 8, 26 ] = wave (0) : "./MITfull/elev-10/L-10e130a.wav"
[ 8, 27 ] = wave (0) : "./MITfull/elev-10/L-10e135a.wav"
[ 8, 28 ] = wave (0) : "./MITfull/elev-10/L-10e140a.wav"
[ 8, 29 ] = wave (0) : "./MITfull/elev-10/L-10e145a.wav"
[ 8, 30 ] = wave (0) : "./MITfull/elev-10/L-10e150a.wav"
[ 8, 31 ] = wave (0) : "./MITfull/elev-10/L-10e155a.wav"
[ 8, 32 ] = wave (0) : "./MITfull/elev-10/L-10e160a.wav"
[ 8, 33 ] = wave (0) : "./MITfull/elev-10/L-10e165a.wav"
[ 8, 34 ] = wave (0) : "./MITfull/elev-10/L-10e170a.wav"
[ 8, 35 ] = wave (0) : "./MITfull/elev-10/L-10e175a.wav"
[ 8, 36 ] = wave (0) : "./MITfull/elev-10/L-10e180a.wav"
[ 8, 37 ] = wave (0) : "./MITfull/elev-10/L-10e185a.wav"
[ 8, 38 ] = wave (0) : "./MITfull/elev-10/L-10e190a.wav"
[ 8, 39 ] = wave (0) : "./MITfull/elev-10/L-10e195a.wav"
[ 8, 40 ] = wave (0) : "./MITfull/elev-10/L-10e200a.wav"
[ 8, 41 ] = wave (0) : "./MITfull/elev-10/L-10e205a.wav"
[ 8, 42 ] = wave (0) : "./MITfull/elev-10/L-10e210a.wav"
[ 8, 43 ] = wave (0) : "./MITfull/elev-10/L-10e215a.wav"
[ 8, 44 ] = wave (0) : "./MITfull/elev-10/L-10e220a.wav"
[ 8, 45 ] = wave (0) : "./MITfull/elev-10/L-10e225a.wav"
[ 8, 46 ] = wave (0) : "./MITfull/elev-10/L-10e230a.wav"
[ 8, 47 ] = wave (0) : "./MITfull/elev-10/L-10e235a.wav"
[ 8, 48 ] = wave (0) : "./MITfull/elev-10/L-10e240a.wav"
[ 8, 49 ] = wave (0) : "./MITfull/elev-10/L-10e245a.wav"
[ 8, 50 ] = wave (0) : "./MITfull/elev-10/L-10e250a.wav"
[ 8, 51 ] = wave (0) : "./MITfull/elev-10/L-10e255a.wav"
[ 8, 52 ] = wave (0) : "./MITfull/elev-10/L-10e260a.wav"
[ 8, 53 ] = wave (0) : "./MITfull/elev-10/L-10e265a.wav"
[ 8, 54 ] = wave (0) : "./MITfull/elev-10/L-10e270a.wav"
[ 8, 55 ] = wave (0) : "./MITfull/elev-10/L-10e275a.wav"
[ 8, 56 ] = wave (0) : "./MITfull/elev-10/L-10e280a.wav"
[ 8, 57 ] = wave (0) : "./MITfull/elev-10/L-10e285a.wav"
[ 8, 58 ] = wave (0) : "./MITfull/elev-10/L-10e290a.wav"
[ 8, 59 ] = wave (0) : "./MITfull/elev-10/L-10e295a.wav"
[ 8, 60 ] = wave (0) : "./MITfull/elev-10/L-10e300a.wav"
[ 8, 61 ] = wave (0) : "./MITfull/elev-10/L-10e305a.wav"
[ 8, 62 ] = wave (0) : "./MITfull/elev-10/L-10e310a.wav"
[ 8, 63 ] = wave (0) : "./MITfull/elev-10/L-10e315a.wav"
[ 8, 64 ] = wave (0) : "./MITfull/elev-10/L-10e320a.wav"
[ 8, 65 ] = wave (0) : "./MITfull/elev-10/L-10e325a.wav"
[ 8, 66 ] = wave (0) : "./MITfull/elev-10/L-10e330a.wav"
[ 8, 67 ] = wave (0) : "./MITfull/elev-10/L-10e335a.wav"
[ 8, 68 ] = wave (0) : "./MITfull/elev-10/L-10e340a.wav"
[ 8, 69 ] = wave (0) : "./MITfull/elev-10/L-10e345a.wav"
[ 8, 70 ] = wave (0) : "./MITfull/elev-10/L-10e350a.wav"
[ 8, 71 ] = wave (0) : "./MITfull/elev-10/L-10e355a.wav"
[ 9, 0 ] = wave (0) : "./MITfull/elev0/L0e000a.wav"
[ 9, 1 ] = wave (0) : "./MITfull/elev0/L0e005a.wav"
[ 9, 2 ] = wave (0) : "./MITfull/elev0/L0e010a.wav"
[ 9, 3 ] = wave (0) : "./MITfull/elev0/L0e015a.wav"
[ 9, 4 ] = wave (0) : "./MITfull/elev0/L0e020a.wav"
[ 9, 5 ] = wave (0) : "./MITfull/elev0/L0e025a.wav"
[ 9, 6 ] = wave (0) : "./MITfull/elev0/L0e030a.wav"
[ 9, 7 ] = wave (0) : "./MITfull/elev0/L0e035a.wav"
[ 9, 8 ] = wave (0) : "./MITfull/elev0/L0e040a.wav"
[ 9, 9 ] = wave (0) : "./MITfull/elev0/L0e045a.wav"
[ 9, 10 ] = wave (0) : "./MITfull/elev0/L0e050a.wav"
[ 9, 11 ] = wave (0) : "./MITfull/elev0/L0e055a.wav"
[ 9, 12 ] = wave (0) : "./MITfull/elev0/L0e060a.wav"
[ 9, 13 ] = wave (0) : "./MITfull/elev0/L0e065a.wav"
[ 9, 14 ] = wave (0) : "./MITfull/elev0/L0e070a.wav"
[ 9, 15 ] = wave (0) : "./MITfull/elev0/L0e075a.wav"
[ 9, 16 ] = wave (0) : "./MITfull/elev0/L0e080a.wav"
[ 9, 17 ] = wave (0) : "./MITfull/elev0/L0e085a.wav"
[ 9, 18 ] = wave (0) : "./MITfull/elev0/L0e090a.wav"
[ 9, 19 ] = wave (0) : "./MITfull/elev0/L0e095a.wav"
[ 9, 20 ] = wave (0) : "./MITfull/elev0/L0e100a.wav"
[ 9, 21 ] = wave (0) : "./MITfull/elev0/L0e105a.wav"
[ 9, 22 ] = wave (0) : "./MITfull/elev0/L0e110a.wav"
[ 9, 23 ] = wave (0) : "./MITfull/elev0/L0e115a.wav"
[ 9, 24 ] = wave (0) : "./MITfull/elev0/L0e120a.wav"
[ 9, 25 ] = wave (0) : "./MITfull/elev0/L0e125a.wav"
[ 9, 26 ] = wave (0) : "./MITfull/elev0/L0e130a.wav"
[ 9, 27 ] = wave (0) : "./MITfull/elev0/L0e135a.wav"
[ 9, 28 ] = wave (0) : "./MITfull/elev0/L0e140a.wav"
[ 9, 29 ] = wave (0) : "./MITfull/elev0/L0e145a.wav"
[ 9, 30 ] = wave (0) : "./MITfull/elev0/L0e150a.wav"
[ 9, 31 ] = wave (0) : "./MITfull/elev0/L0e155a.wav"
[ 9, 32 ] = wave (0) : "./MITfull/elev0/L0e160a.wav"
[ 9, 33 ] = wave (0) : "./MITfull/elev0/L0e165a.wav"
[ 9, 34 ] = wave (0) : "./MITfull/elev0/L0e170a.wav"
[ 9, 35 ] = wave (0) : "./MITfull/elev0/L0e175a.wav"
[ 9, 36 ] = wave (0) : "./MITfull/elev0/L0e180a.wav"
[ 9, 37 ] = wave (0) : "./MITfull/elev0/L0e185a.wav"
[ 9, 38 ] = wave (0) : "./MITfull/elev0/L0e190a.wav"
[ 9, 39 ] = wave (0) : "./MITfull/elev0/L0e195a.wav"
[ 9, 40 ] = wave (0) : "./MITfull/elev0/L0e200a.wav"
[ 9, 41 ] = wave (0) : "./MITfull/elev0/L0e205a.wav"
[ 9, 42 ] = wave (0) : "./MITfull/elev0/L0e210a.wav"
[ 9, 43 ] = wave (0) : "./MITfull/elev0/L0e215a.wav"
[ 9, 44 ] = wave (0) : "./MITfull/elev0/L0e220a.wav"
[ 9, 45 ] = wave (0) : "./MITfull/elev0/L0e225a.wav"
[ 9, 46 ] = wave (0) : "./MITfull/elev0/L0e230a.wav"
[ 9, 47 ] = wave (0) : "./MITfull/elev0/L0e235a.wav"
[ 9, 48 ] = wave (0) : "./MITfull/elev0/L0e240a.wav"
[ 9, 49 ] = wave (0) : "./MITfull/elev0/L0e245a.wav"
[ 9, 50 ] = wave (0) : "./MITfull/elev0/L0e250a.wav"
[ 9, 51 ] = wave (0) : "./MITfull/elev0/L0e255a.wav"
[ 9, 52 ] = wave (0) : "./MITfull/elev0/L0e260a.wav"
[ 9, 53 ] = wave (0) : "./MITfull/elev0/L0e265a.wav"
[ 9, 54 ] = wave (0) : "./MITfull/elev0/L0e270a.wav"
[ 9, 55 ] = wave (0) : "./MITfull/elev0/L0e275a.wav"
[ 9, 56 ] = wave (0) : "./MITfull/elev0/L0e280a.wav"
[ 9, 57 ] = wave (0) : "./MITfull/elev0/L0e285a.wav"
[ 9, 58 ] = wave (0) : "./MITfull/elev0/L0e290a.wav"
[ 9, 59 ] = wave (0) : "./MITfull/elev0/L0e295a.wav"
[ 9, 60 ] = wave (0) : "./MITfull/elev0/L0e300a.wav"
[ 9, 61 ] = wave (0) : "./MITfull/elev0/L0e305a.wav"
[ 9, 62 ] = wave (0) : "./MITfull/elev0/L0e310a.wav"
[ 9, 63 ] = wave (0) : "./MITfull/elev0/L0e315a.wav"
[ 9, 64 ] = wave (0) : "./MITfull/elev0/L0e320a.wav"
[ 9, 65 ] = wave (0) : "./MITfull/elev0/L0e325a.wav"
[ 9, 66 ] = wave (0) : "./MITfull/elev0/L0e330a.wav"
[ 9, 67 ] = wave (0) : "./MITfull/elev0/L0e335a.wav"
[ 9, 68 ] = wave (0) : "./MITfull/elev0/L0e340a.wav"
[ 9, 69 ] = wave (0) : "./MITfull/elev0/L0e345a.wav"
[ 9, 70 ] = wave (0) : "./MITfull/elev0/L0e350a.wav"
[ 9, 71 ] = wave (0) : "./MITfull/elev0/L0e355a.wav"
[ 10, 0 ] = wave (0) : "./MITfull/elev10/L10e000a.wav"
[ 10, 1 ] = wave (0) : "./MITfull/elev10/L10e005a.wav"
[ 10, 2 ] = wave (0) : "./MITfull/elev10/L10e010a.wav"
[ 10, 3 ] = wave (0) : "./MITfull/elev10/L10e015a.wav"
[ 10, 4 ] = wave (0) : "./MITfull/elev10/L10e020a.wav"
[ 10, 5 ] = wave (0) : "./MITfull/elev10/L10e025a.wav"
[ 10, 6 ] = wave (0) : "./MITfull/elev10/L10e030a.wav"
[ 10, 7 ] = wave (0) : "./MITfull/elev10/L10e035a.wav"
[ 10, 8 ] = wave (0) : "./MITfull/elev10/L10e040a.wav"
[ 10, 9 ] = wave (0) : "./MITfull/elev10/L10e045a.wav"
[ 10, 10 ] = wave (0) : "./MITfull/elev10/L10e050a.wav"
[ 10, 11 ] = wave (0) : "./MITfull/elev10/L10e055a.wav"
[ 10, 12 ] = wave (0) : "./MITfull/elev10/L10e060a.wav"
[ 10, 13 ] = wave (0) : "./MITfull/elev10/L10e065a.wav"
[ 10, 14 ] = wave (0) : "./MITfull/elev10/L10e070a.wav"
[ 10, 15 ] = wave (0) : "./MITfull/elev10/L10e075a.wav"
[ 10, 16 ] = wave (0) : "./MITfull/elev10/L10e080a.wav"
[ 10, 17 ] = wave (0) : "./MITfull/elev10/L10e085a.wav"
[ 10, 18 ] = wave (0) : "./MITfull/elev10/L10e090a.wav"
[ 10, 19 ] = wave (0) : "./MITfull/elev10/L10e095a.wav"
[ 10, 20 ] = wave (0) : "./MITfull/elev10/L10e100a.wav"
[ 10, 21 ] = wave (0) : "./MITfull/elev10/L10e105a.wav"
[ 10, 22 ] = wave (0) : "./MITfull/elev10/L10e110a.wav"
[ 10, 23 ] = wave (0) : "./MITfull/elev10/L10e115a.wav"
[ 10, 24 ] = wave (0) : "./MITfull/elev10/L10e120a.wav"
[ 10, 25 ] = wave (0) : "./MITfull/elev10/L10e125a.wav"
[ 10, 26 ] = wave (0) : "./MITfull/elev10/L10e130a.wav"
[ 10, 27 ] = wave (0) : "./MITfull/elev10/L10e135a.wav"
[ 10, 28 ] = wave (0) : "./MITfull/elev10/L10e140a.wav"
[ 10, 29 ] = wave (0) : "./MITfull/elev10/L10e145a.wav"
[ 10, 30 ] = wave (0) : "./MITfull/elev10/L10e150a.wav"
[ 10, 31 ] = wave (0) : "./MITfull/elev10/L10e155a.wav"
[ 10, 32 ] = wave (0) : "./MITfull/elev10/L10e160a.wav"
[ 10, 33 ] = wave (0) : "./MITfull/elev10/L10e165a.wav"
[ 10, 34 ] = wave (0) : "./MITfull/elev10/L10e170a.wav"
[ 10, 35 ] = wave (0) : "./MITfull/elev10/L10e175a.wav"
[ 10, 36 ] = wave (0) : "./MITfull/elev10/L10e180a.wav"
[ 10, 37 ] = wave (0) : "./MITfull/elev10/L10e185a.wav"
[ 10, 38 ] = wave (0) : "./MITfull/elev10/L10e190a.wav"
[ 10, 39 ] = wave (0) : "./MITfull/elev10/L10e195a.wav"
[ 10, 40 ] = wave (0) : "./MITfull/elev10/L10e200a.wav"
[ 10, 41 ] = wave (0) : "./MITfull/elev10/L10e205a.wav"
[ 10, 42 ] = wave (0) : "./MITfull/elev10/L10e210a.wav"
[ 10, 43 ] = wave (0) : "./MITfull/elev10/L10e215a.wav"
[ 10, 44 ] = wave (0) : "./MITfull/elev10/L10e220a.wav"
[ 10, 45 ] = wave (0) : "./MITfull/elev10/L10e225a.wav"
[ 10, 46 ] = wave (0) : "./MITfull/elev10/L10e230a.wav"
[ 10, 47 ] = wave (0) : "./MITfull/elev10/L10e235a.wav"
[ 10, 48 ] = wave (0) : "./MITfull/elev10/L10e240a.wav"
[ 10, 49 ] = wave (0) : "./MITfull/elev10/L10e245a.wav"
[ 10, 50 ] = wave (0) : "./MITfull/elev10/L10e250a.wav"
[ 10, 51 ] = wave (0) : "./MITfull/elev10/L10e255a.wav"
[ 10, 52 ] = wave (0) : "./MITfull/elev10/L10e260a.wav"
[ 10, 53 ] = wave (0) : "./MITfull/elev10/L10e265a.wav"
[ 10, 54 ] = wave (0) : "./MITfull/elev10/L10e270a.wav"
[ 10, 55 ] = wave (0) : "./MITfull/elev10/L10e275a.wav"
[ 10, 56 ] = wave (0) : "./MITfull/elev10/L10e280a.wav"
[ 10, 57 ] = wave (0) : "./MITfull/elev10/L10e285a.wav"
[ 10, 58 ] = wave (0) : "./MITfull/elev10/L10e290a.wav"
[ 10, 59 ] = wave (0) : "./MITfull/elev10/L10e295a.wav"
[ 10, 60 ] = wave (0) : "./MITfull/elev10/L10e300a.wav"
[ 10, 61 ] = wave (0) : "./MITfull/elev10/L10e305a.wav"
[ 10, 62 ] = wave (0) : "./MITfull/elev10/L10e310a.wav"
[ 10, 63 ] = wave (0) : "./MITfull/elev10/L10e315a.wav"
[ 10, 64 ] = wave (0) : "./MITfull/elev10/L10e320a.wav"
[ 10, 65 ] = wave (0) : "./MITfull/elev10/L10e325a.wav"
[ 10, 66 ] = wave (0) : "./MITfull/elev10/L10e330a.wav"
[ 10, 67 ] = wave (0) : "./MITfull/elev10/L10e335a.wav"
[ 10, 68 ] = wave (0) : "./MITfull/elev10/L10e340a.wav"
[ 10, 69 ] = wave (0) : "./MITfull/elev10/L10e345a.wav"
[ 10, 70 ] = wave (0) : "./MITfull/elev10/L10e350a.wav"
[ 10, 71 ] = wave (0) : "./MITfull/elev10/L10e355a.wav"
[ 11, 0 ] = wave (0) : "./MITfull/elev20/L20e000a.wav"
[ 11, 1 ] = wave (0) : "./MITfull/elev20/L20e005a.wav"
[ 11, 2 ] = wave (0) : "./MITfull/elev20/L20e010a.wav"
[ 11, 3 ] = wave (0) : "./MITfull/elev20/L20e015a.wav"
[ 11, 4 ] = wave (0) : "./MITfull/elev20/L20e020a.wav"
[ 11, 5 ] = wave (0) : "./MITfull/elev20/L20e025a.wav"
[ 11, 6 ] = wave (0) : "./MITfull/elev20/L20e030a.wav"
[ 11, 7 ] = wave (0) : "./MITfull/elev20/L20e035a.wav"
[ 11, 8 ] = wave (0) : "./MITfull/elev20/L20e040a.wav"
[ 11, 9 ] = wave (0) : "./MITfull/elev20/L20e045a.wav"
[ 11, 10 ] = wave (0) : "./MITfull/elev20/L20e050a.wav"
[ 11, 11 ] = wave (0) : "./MITfull/elev20/L20e055a.wav"
[ 11, 12 ] = wave (0) : "./MITfull/elev20/L20e060a.wav"
[ 11, 13 ] = wave (0) : "./MITfull/elev20/L20e065a.wav"
[ 11, 14 ] = wave (0) : "./MITfull/elev20/L20e070a.wav"
[ 11, 15 ] = wave (0) : "./MITfull/elev20/L20e075a.wav"
[ 11, 16 ] = wave (0) : "./MITfull/elev20/L20e080a.wav"
[ 11, 17 ] = wave (0) : "./MITfull/elev20/L20e085a.wav"
[ 11, 18 ] = wave (0) : "./MITfull/elev20/L20e090a.wav"
[ 11, 19 ] = wave (0) : "./MITfull/elev20/L20e095a.wav"
[ 11, 20 ] = wave (0) : "./MITfull/elev20/L20e100a.wav"
[ 11, 21 ] = wave (0) : "./MITfull/elev20/L20e105a.wav"
[ 11, 22 ] = wave (0) : "./MITfull/elev20/L20e110a.wav"
[ 11, 23 ] = wave (0) : "./MITfull/elev20/L20e115a.wav"
[ 11, 24 ] = wave (0) : "./MITfull/elev20/L20e120a.wav"
[ 11, 25 ] = wave (0) : "./MITfull/elev20/L20e125a.wav"
[ 11, 26 ] = wave (0) : "./MITfull/elev20/L20e130a.wav"
[ 11, 27 ] = wave (0) : "./MITfull/elev20/L20e135a.wav"
[ 11, 28 ] = wave (0) : "./MITfull/elev20/L20e140a.wav"
[ 11, 29 ] = wave (0) : "./MITfull/elev20/L20e145a.wav"
[ 11, 30 ] = wave (0) : "./MITfull/elev20/L20e150a.wav"
[ 11, 31 ] = wave (0) : "./MITfull/elev20/L20e155a.wav"
[ 11, 32 ] = wave (0) : "./MITfull/elev20/L20e160a.wav"
[ 11, 33 ] = wave (0) : "./MITfull/elev20/L20e165a.wav"
[ 11, 34 ] = wave (0) : "./MITfull/elev20/L20e170a.wav"
[ 11, 35 ] = wave (0) : "./MITfull/elev20/L20e175a.wav"
[ 11, 36 ] = wave (0) : "./MITfull/elev20/L20e180a.wav"
[ 11, 37 ] = wave (0) : "./MITfull/elev20/L20e185a.wav"
[ 11, 38 ] = wave (0) : "./MITfull/elev20/L20e190a.wav"
[ 11, 39 ] = wave (0) : "./MITfull/elev20/L20e195a.wav"
[ 11, 40 ] = wave (0) : "./MITfull/elev20/L20e200a.wav"
[ 11, 41 ] = wave (0) : "./MITfull/elev20/L20e205a.wav"
[ 11, 42 ] = wave (0) : "./MITfull/elev20/L20e210a.wav"
[ 11, 43 ] = wave (0) : "./MITfull/elev20/L20e215a.wav"
[ 11, 44 ] = wave (0) : "./MITfull/elev20/L20e220a.wav"
[ 11, 45 ] = wave (0) : "./MITfull/elev20/L20e225a.wav"
[ 11, 46 ] = wave (0) : "./MITfull/elev20/L20e230a.wav"
[ 11, 47 ] = wave (0) : "./MITfull/elev20/L20e235a.wav"
[ 11, 48 ] = wave (0) : "./MITfull/elev20/L20e240a.wav"
[ 11, 49 ] = wave (0) : "./MITfull/elev20/L20e245a.wav"
[ 11, 50 ] = wave (0) : "./MITfull/elev20/L20e250a.wav"
[ 11, 51 ] = wave (0) : "./MITfull/elev20/L20e255a.wav"
[ 11, 52 ] = wave (0) : "./MITfull/elev20/L20e260a.wav"
[ 11, 53 ] = wave (0) : "./MITfull/elev20/L20e265a.wav"
[ 11, 54 ] = wave (0) : "./MITfull/elev20/L20e270a.wav"
[ 11, 55 ] = wave (0) : "./MITfull/elev20/L20e275a.wav"
[ 11, 56 ] = wave (0) : "./MITfull/elev20/L20e280a.wav"
[ 11, 57 ] = wave (0) : "./MITfull/elev20/L20e285a.wav"
[ 11, 58 ] = wave (0) : "./MITfull/elev20/L20e290a.wav"
[ 11, 59 ] = wave (0) : "./MITfull/elev20/L20e295a.wav"
[ 11, 60 ] = wave (0) : "./MITfull/elev20/L20e300a.wav"
[ 11, 61 ] = wave (0) : "./MITfull/elev20/L20e305a.wav"
[ 11, 62 ] = wave (0) : "./MITfull/elev20/L20e310a.wav"
[ 11, 63 ] = wave (0) : "./MITfull/elev20/L20e315a.wav"
[ 11, 64 ] = wave (0) : "./MITfull/elev20/L20e320a.wav"
[ 11, 65 ] = wave (0) : "./MITfull/elev20/L20e325a.wav"
[ 11, 66 ] = wave (0) : "./MITfull/elev20/L20e330a.wav"
[ 11, 67 ] = wave (0) : "./MITfull/elev20/L20e335a.wav"
[ 11, 68 ] = wave (0) : "./MITfull/elev20/L20e340a.wav"
[ 11, 69 ] = wave (0) : "./MITfull/elev20/L20e345a.wav"
[ 11, 70 ] = wave (0) : "./MITfull/elev20/L20e350a.wav"
[ 11, 71 ] = wave (0) : "./MITfull/elev20/L20e355a.wav"
[ 12, 0 ] = wave (0) : "./MITfull/elev30/L30e000a.wav"
[ 12, 1 ] = wave (0) : "./MITfull/elev30/L30e006a.wav"
[ 12, 2 ] = wave (0) : "./MITfull/elev30/L30e012a.wav"
[ 12, 3 ] = wave (0) : "./MITfull/elev30/L30e018a.wav"
[ 12, 4 ] = wave (0) : "./MITfull/elev30/L30e024a.wav"
[ 12, 5 ] = wave (0) : "./MITfull/elev30/L30e030a.wav"
[ 12, 6 ] = wave (0) : "./MITfull/elev30/L30e036a.wav"
[ 12, 7 ] = wave (0) : "./MITfull/elev30/L30e042a.wav"
[ 12, 8 ] = wave (0) : "./MITfull/elev30/L30e048a.wav"
[ 12, 9 ] = wave (0) : "./MITfull/elev30/L30e054a.wav"
[ 12, 10 ] = wave (0) : "./MITfull/elev30/L30e060a.wav"
[ 12, 11 ] = wave (0) : "./MITfull/elev30/L30e066a.wav"
[ 12, 12 ] = wave (0) : "./MITfull/elev30/L30e072a.wav"
[ 12, 13 ] = wave (0) : "./MITfull/elev30/L30e078a.wav"
[ 12, 14 ] = wave (0) : "./MITfull/elev30/L30e084a.wav"
[ 12, 15 ] = wave (0) : "./MITfull/elev30/L30e090a.wav"
[ 12, 16 ] = wave (0) : "./MITfull/elev30/L30e096a.wav"
[ 12, 17 ] = wave (0) : "./MITfull/elev30/L30e102a.wav"
[ 12, 18 ] = wave (0) : "./MITfull/elev30/L30e108a.wav"
[ 12, 19 ] = wave (0) : "./MITfull/elev30/L30e114a.wav"
[ 12, 20 ] = wave (0) : "./MITfull/elev30/L30e120a.wav"
[ 12, 21 ] = wave (0) : "./MITfull/elev30/L30e126a.wav"
[ 12, 22 ] = wave (0) : "./MITfull/elev30/L30e132a.wav"
[ 12, 23 ] = wave (0) : "./MITfull/elev30/L30e138a.wav"
[ 12, 24 ] = wave (0) : "./MITfull/elev30/L30e144a.wav"
[ 12, 25 ] = wave (0) : "./MITfull/elev30/L30e150a.wav"
[ 12, 26 ] = wave (0) : "./MITfull/elev30/L30e156a.wav"
[ 12, 27 ] = wave (0) : "./MITfull/elev30/L30e162a.wav"
[ 12, 28 ] = wave (0) : "./MITfull/elev30/L30e168a.wav"
[ 12, 29 ] = wave (0) : "./MITfull/elev30/L30e174a.wav"
[ 12, 30 ] = wave (0) : "./MITfull/elev30/L30e180a.wav"
[ 12, 31 ] = wave (0) : "./MITfull/elev30/L30e186a.wav"
[ 12, 32 ] = wave (0) : "./MITfull/elev30/L30e192a.wav"
[ 12, 33 ] = wave (0) : "./MITfull/elev30/L30e198a.wav"
[ 12, 34 ] = wave (0) : "./MITfull/elev30/L30e204a.wav"
[ 12, 35 ] = wave (0) : "./MITfull/elev30/L30e210a.wav"
[ 12, 36 ] = wave (0) : "./MITfull/elev30/L30e216a.wav"
[ 12, 37 ] = wave (0) : "./MITfull/elev30/L30e222a.wav"
[ 12, 38 ] = wave (0) : "./MITfull/elev30/L30e228a.wav"
[ 12, 39 ] = wave (0) : "./MITfull/elev30/L30e234a.wav"
[ 12, 40 ] = wave (0) : "./MITfull/elev30/L30e240a.wav"
[ 12, 41 ] = wave (0) : "./MITfull/elev30/L30e246a.wav"
[ 12, 42 ] = wave (0) : "./MITfull/elev30/L30e252a.wav"
[ 12, 43 ] = wave (0) : "./MITfull/elev30/L30e258a.wav"
[ 12, 44 ] = wave (0) : "./MITfull/elev30/L30e264a.wav"
[ 12, 45 ] = wave (0) : "./MITfull/elev30/L30e270a.wav"
[ 12, 46 ] = wave (0) : "./MITfull/elev30/L30e276a.wav"
[ 12, 47 ] = wave (0) : "./MITfull/elev30/L30e282a.wav"
[ 12, 48 ] = wave (0) : "./MITfull/elev30/L30e288a.wav"
[ 12, 49 ] = wave (0) : "./MITfull/elev30/L30e294a.wav"
[ 12, 50 ] = wave (0) : "./MITfull/elev30/L30e300a.wav"
[ 12, 51 ] = wave (0) : "./MITfull/elev30/L30e306a.wav"
[ 12, 52 ] = wave (0) : "./MITfull/elev30/L30e312a.wav"
[ 12, 53 ] = wave (0) : "./MITfull/elev30/L30e318a.wav"
[ 12, 54 ] = wave (0) : "./MITfull/elev30/L30e324a.wav"
[ 12, 55 ] = wave (0) : "./MITfull/elev30/L30e330a.wav"
[ 12, 56 ] = wave (0) : "./MITfull/elev30/L30e336a.wav"
[ 12, 57 ] = wave (0) : "./MITfull/elev30/L30e342a.wav"
[ 12, 58 ] = wave (0) : "./MITfull/elev30/L30e348a.wav"
[ 12, 59 ] = wave (0) : "./MITfull/elev30/L30e354a.wav"
[ 13, 0 ] = wave (0) : "./MITfull/elev40/L40e000a.wav"
[ 13, 1 ] = wave (0) : "./MITfull/elev40/L40e006a.wav"
[ 13, 2 ] = wave (0) : "./MITfull/elev40/L40e013a.wav"
[ 13, 3 ] = wave (0) : "./MITfull/elev40/L40e019a.wav"
[ 13, 4 ] = wave (0) : "./MITfull/elev40/L40e026a.wav"
[ 13, 5 ] = wave (0) : "./MITfull/elev40/L40e032a.wav"
[ 13, 6 ] = wave (0) : "./MITfull/elev40/L40e039a.wav"
[ 13, 7 ] = wave (0) : "./MITfull/elev40/L40e045a.wav"
[ 13, 8 ] = wave (0) : "./MITfull/elev40/L40e051a.wav"
[ 13, 9 ] = wave (0) : "./MITfull/elev40/L40e058a.wav"
[ 13, 10 ] = wave (0) : "./MITfull/elev40/L40e064a.wav"
[ 13, 11 ] = wave (0) : "./MITfull/elev40/L40e071a.wav"
[ 13, 12 ] = wave (0) : "./MITfull/elev40/L40e077a.wav"
[ 13, 13 ] = wave (0) : "./MITfull/elev40/L40e084a.wav"
[ 13, 14 ] = wave (0) : "./MITfull/elev40/L40e090a.wav"
[ 13, 15 ] = wave (0) : "./MITfull/elev40/L40e096a.wav"
[ 13, 16 ] = wave (0) : "./MITfull/elev40/L40e103a.wav"
[ 13, 17 ] = wave (0) : "./MITfull/elev40/L40e109a.wav"
[ 13, 18 ] = wave (0) : "./MITfull/elev40/L40e116a.wav"
[ 13, 19 ] = wave (0) : "./MITfull/elev40/L40e122a.wav"
[ 13, 20 ] = wave (0) : "./MITfull/elev40/L40e129a.wav"
[ 13, 21 ] = wave (0) : "./MITfull/elev40/L40e135a.wav"
[ 13, 22 ] = wave (0) : "./MITfull/elev40/L40e141a.wav"
[ 13, 23 ] = wave (0) : "./MITfull/elev40/L40e148a.wav"
[ 13, 24 ] = wave (0) : "./MITfull/elev40/L40e154a.wav"
[ 13, 25 ] = wave (0) : "./MITfull/elev40/L40e161a.wav"
[ 13, 26 ] = wave (0) : "./MITfull/elev40/L40e167a.wav"
[ 13, 27 ] = wave (0) : "./MITfull/elev40/L40e174a.wav"
[ 13, 28 ] = wave (0) : "./MITfull/elev40/L40e180a.wav"
[ 13, 29 ] = wave (0) : "./MITfull/elev40/L40e186a.wav"
[ 13, 30 ] = wave (0) : "./MITfull/elev40/L40e193a.wav"
[ 13, 31 ] = wave (0) : "./MITfull/elev40/L40e199a.wav"
[ 13, 32 ] = wave (0) : "./MITfull/elev40/L40e206a.wav"
[ 13, 33 ] = wave (0) : "./MITfull/elev40/L40e212a.wav"
[ 13, 34 ] = wave (0) : "./MITfull/elev40/L40e219a.wav"
[ 13, 35 ] = wave (0) : "./MITfull/elev40/L40e225a.wav"
[ 13, 36 ] = wave (0) : "./MITfull/elev40/L40e231a.wav"
[ 13, 37 ] = wave (0) : "./MITfull/elev40/L40e238a.wav"
[ 13, 38 ] = wave (0) : "./MITfull/elev40/L40e244a.wav"
[ 13, 39 ] = wave (0) : "./MITfull/elev40/L40e251a.wav"
[ 13, 40 ] = wave (0) : "./MITfull/elev40/L40e257a.wav"
[ 13, 41 ] = wave (0) : "./MITfull/elev40/L40e264a.wav"
[ 13, 42 ] = wave (0) : "./MITfull/elev40/L40e270a.wav"
[ 13, 43 ] = wave (0) : "./MITfull/elev40/L40e276a.wav"
[ 13, 44 ] = wave (0) : "./MITfull/elev40/L40e283a.wav"
[ 13, 45 ] = wave (0) : "./MITfull/elev40/L40e289a.wav"
[ 13, 46 ] = wave (0) : "./MITfull/elev40/L40e296a.wav"
[ 13, 47 ] = wave (0) : "./MITfull/elev40/L40e302a.wav"
[ 13, 48 ] = wave (0) : "./MITfull/elev40/L40e309a.wav"
[ 13, 49 ] = wave (0) : "./MITfull/elev40/L40e315a.wav"
[ 13, 50 ] = wave (0) : "./MITfull/elev40/L40e321a.wav"
[ 13, 51 ] = wave (0) : "./MITfull/elev40/L40e328a.wav"
[ 13, 52 ] = wave (0) : "./MITfull/elev40/L40e334a.wav"
[ 13, 53 ] = wave (0) : "./MITfull/elev40/L40e341a.wav"
[ 13, 54 ] = wave (0) : "./MITfull/elev40/L40e347a.wav"
[ 13, 55 ] = wave (0) : "./MITfull/elev40/L40e354a.wav"
[ 14, 0 ] = wave (0) : "./MITfull/elev50/L50e000a.wav"
[ 14, 1 ] = wave (0) : "./MITfull/elev50/L50e008a.wav"
[ 14, 2 ] = wave (0) : "./MITfull/elev50/L50e016a.wav"
[ 14, 3 ] = wave (0) : "./MITfull/elev50/L50e024a.wav"
[ 14, 4 ] = wave (0) : "./MITfull/elev50/L50e032a.wav"
[ 14, 5 ] = wave (0) : "./MITfull/elev50/L50e040a.wav"
[ 14, 6 ] = wave (0) : "./MITfull/elev50/L50e048a.wav"
[ 14, 7 ] = wave (0) : "./MITfull/elev50/L50e056a.wav"
[ 14, 8 ] = wave (0) : "./MITfull/elev50/L50e064a.wav"
[ 14, 9 ] = wave (0) : "./MITfull/elev50/L50e072a.wav"
[ 14, 10 ] = wave (0) : "./MITfull/elev50/L50e080a.wav"
[ 14, 11 ] = wave (0) : "./MITfull/elev50/L50e088a.wav"
[ 14, 12 ] = wave (0) : "./MITfull/elev50/L50e096a.wav"
[ 14, 13 ] = wave (0) : "./MITfull/elev50/L50e104a.wav"
[ 14, 14 ] = wave (0) : "./MITfull/elev50/L50e112a.wav"
[ 14, 15 ] = wave (0) : "./MITfull/elev50/L50e120a.wav"
[ 14, 16 ] = wave (0) : "./MITfull/elev50/L50e128a.wav"
[ 14, 17 ] = wave (0) : "./MITfull/elev50/L50e136a.wav"
[ 14, 18 ] = wave (0) : "./MITfull/elev50/L50e144a.wav"
[ 14, 19 ] = wave (0) : "./MITfull/elev50/L50e152a.wav"
[ 14, 20 ] = wave (0) : "./MITfull/elev50/L50e160a.wav"
[ 14, 21 ] = wave (0) : "./MITfull/elev50/L50e168a.wav"
[ 14, 22 ] = wave (0) : "./MITfull/elev50/L50e176a.wav"
[ 14, 23 ] = wave (0) : "./MITfull/elev50/L50e184a.wav"
[ 14, 24 ] = wave (0) : "./MITfull/elev50/L50e192a.wav"
[ 14, 25 ] = wave (0) : "./MITfull/elev50/L50e200a.wav"
[ 14, 26 ] = wave (0) : "./MITfull/elev50/L50e208a.wav"
[ 14, 27 ] = wave (0) : "./MITfull/elev50/L50e216a.wav"
[ 14, 28 ] = wave (0) : "./MITfull/elev50/L50e224a.wav"
[ 14, 29 ] = wave (0) : "./MITfull/elev50/L50e232a.wav"
[ 14, 30 ] = wave (0) : "./MITfull/elev50/L50e240a.wav"
[ 14, 31 ] = wave (0) : "./MITfull/elev50/L50e248a.wav"
[ 14, 32 ] = wave (0) : "./MITfull/elev50/L50e256a.wav"
[ 14, 33 ] = wave (0) : "./MITfull/elev50/L50e264a.wav"
[ 14, 34 ] = wave (0) : "./MITfull/elev50/L50e272a.wav"
[ 14, 35 ] = wave (0) : "./MITfull/elev50/L50e280a.wav"
[ 14, 36 ] = wave (0) : "./MITfull/elev50/L50e288a.wav"
[ 14, 37 ] = wave (0) : "./MITfull/elev50/L50e296a.wav"
[ 14, 38 ] = wave (0) : "./MITfull/elev50/L50e304a.wav"
[ 14, 39 ] = wave (0) : "./MITfull/elev50/L50e312a.wav"
[ 14, 40 ] = wave (0) : "./MITfull/elev50/L50e320a.wav"
[ 14, 41 ] = wave (0) : "./MITfull/elev50/L50e328a.wav"
[ 14, 42 ] = wave (0) : "./MITfull/elev50/L50e336a.wav"
[ 14, 43 ] = wave (0) : "./MITfull/elev50/L50e344a.wav"
[ 14, 44 ] = wave (0) : "./MITfull/elev50/L50e352a.wav"
[ 15, 0 ] = wave (0) : "./MITfull/elev60/L60e000a.wav"
[ 15, 1 ] = wave (0) : "./MITfull/elev60/L60e010a.wav"
[ 15, 2 ] = wave (0) : "./MITfull/elev60/L60e020a.wav"
[ 15, 3 ] = wave (0) : "./MITfull/elev60/L60e030a.wav"
[ 15, 4 ] = wave (0) : "./MITfull/elev60/L60e040a.wav"
[ 15, 5 ] = wave (0) : "./MITfull/elev60/L60e050a.wav"
[ 15, 6 ] = wave (0) : "./MITfull/elev60/L60e060a.wav"
[ 15, 7 ] = wave (0) : "./MITfull/elev60/L60e070a.wav"
[ 15, 8 ] = wave (0) : "./MITfull/elev60/L60e080a.wav"
[ 15, 9 ] = wave (0) : "./MITfull/elev60/L60e090a.wav"
[ 15, 10 ] = wave (0) : "./MITfull/elev60/L60e100a.wav"
[ 15, 11 ] = wave (0) : "./MITfull/elev60/L60e110a.wav"
[ 15, 12 ] = wave (0) : "./MITfull/elev60/L60e120a.wav"
[ 15, 13 ] = wave (0) : "./MITfull/elev60/L60e130a.wav"
[ 15, 14 ] = wave (0) : "./MITfull/elev60/L60e140a.wav"
[ 15, 15 ] = wave (0) : "./MITfull/elev60/L60e150a.wav"
[ 15, 16 ] = wave (0) : "./MITfull/elev60/L60e160a.wav"
[ 15, 17 ] = wave (0) : "./MITfull/elev60/L60e170a.wav"
[ 15, 18 ] = wave (0) : "./MITfull/elev60/L60e180a.wav"
[ 15, 19 ] = wave (0) : "./MITfull/elev60/L60e190a.wav"
[ 15, 20 ] = wave (0) : "./MITfull/elev60/L60e200a.wav"
[ 15, 21 ] = wave (0) : "./MITfull/elev60/L60e210a.wav"
[ 15, 22 ] = wave (0) : "./MITfull/elev60/L60e220a.wav"
[ 15, 23 ] = wave (0) : "./MITfull/elev60/L60e230a.wav"
[ 15, 24 ] = wave (0) : "./MITfull/elev60/L60e240a.wav"
[ 15, 25 ] = wave (0) : "./MITfull/elev60/L60e250a.wav"
[ 15, 26 ] = wave (0) : "./MITfull/elev60/L60e260a.wav"
[ 15, 27 ] = wave (0) : "./MITfull/elev60/L60e270a.wav"
[ 15, 28 ] = wave (0) : "./MITfull/elev60/L60e280a.wav"
[ 15, 29 ] = wave (0) : "./MITfull/elev60/L60e290a.wav"
[ 15, 30 ] = wave (0) : "./MITfull/elev60/L60e300a.wav"
[ 15, 31 ] = wave (0) : "./MITfull/elev60/L60e310a.wav"
[ 15, 32 ] = wave (0) : "./MITfull/elev60/L60e320a.wav"
[ 15, 33 ] = wave (0) : "./MITfull/elev60/L60e330a.wav"
[ 15, 34 ] = wave (0) : "./MITfull/elev60/L60e340a.wav"
[ 15, 35 ] = wave (0) : "./MITfull/elev60/L60e350a.wav"
[ 16, 0 ] = wave (0) : "./MITfull/elev70/L70e000a.wav"
[ 16, 1 ] = wave (0) : "./MITfull/elev70/L70e015a.wav"
[ 16, 2 ] = wave (0) : "./MITfull/elev70/L70e030a.wav"
[ 16, 3 ] = wave (0) : "./MITfull/elev70/L70e045a.wav"
[ 16, 4 ] = wave (0) : "./MITfull/elev70/L70e060a.wav"
[ 16, 5 ] = wave (0) : "./MITfull/elev70/L70e075a.wav"
[ 16, 6 ] = wave (0) : "./MITfull/elev70/L70e090a.wav"
[ 16, 7 ] = wave (0) : "./MITfull/elev70/L70e105a.wav"
[ 16, 8 ] = wave (0) : "./MITfull/elev70/L70e120a.wav"
[ 16, 9 ] = wave (0) : "./MITfull/elev70/L70e135a.wav"
[ 16, 10 ] = wave (0) : "./MITfull/elev70/L70e150a.wav"
[ 16, 11 ] = wave (0) : "./MITfull/elev70/L70e165a.wav"
[ 16, 12 ] = wave (0) : "./MITfull/elev70/L70e180a.wav"
[ 16, 13 ] = wave (0) : "./MITfull/elev70/L70e195a.wav"
[ 16, 14 ] = wave (0) : "./MITfull/elev70/L70e210a.wav"
[ 16, 15 ] = wave (0) : "./MITfull/elev70/L70e225a.wav"
[ 16, 16 ] = wave (0) : "./MITfull/elev70/L70e240a.wav"
[ 16, 17 ] = wave (0) : "./MITfull/elev70/L70e255a.wav"
[ 16, 18 ] = wave (0) : "./MITfull/elev70/L70e270a.wav"
[ 16, 19 ] = wave (0) : "./MITfull/elev70/L70e285a.wav"
[ 16, 20 ] = wave (0) : "./MITfull/elev70/L70e300a.wav"
[ 16, 21 ] = wave (0) : "./MITfull/elev70/L70e315a.wav"
[ 16, 22 ] = wave (0) : "./MITfull/elev70/L70e330a.wav"
[ 16, 23 ] = wave (0) : "./MITfull/elev70/L70e345a.wav"
[ 17, 0 ] = wave (0) : "./MITfull/elev80/L80e000a.wav"
[ 17, 1 ] = wave (0) : "./MITfull/elev80/L80e030a.wav"
[ 17, 2 ] = wave (0) : "./MITfull/elev80/L80e060a.wav"
[ 17, 3 ] = wave (0) : "./MITfull/elev80/L80e090a.wav"
[ 17, 4 ] = wave (0) : "./MITfull/elev80/L80e120a.wav"
[ 17, 5 ] = wave (0) : "./MITfull/elev80/L80e150a.wav"
[ 17, 6 ] = wave (0) : "./MITfull/elev80/L80e180a.wav"
[ 17, 7 ] = wave (0) : "./MITfull/elev80/L80e210a.wav"
[ 17, 8 ] = wave (0) : "./MITfull/elev80/L80e240a.wav"
[ 17, 9 ] = wave (0) : "./MITfull/elev80/L80e270a.wav"
[ 17, 10 ] = wave (0) : "./MITfull/elev80/L80e300a.wav"
[ 17, 11 ] = wave (0) : "./MITfull/elev80/L80e330a.wav"
[ 18, 0 ] = wave (0) : "./MITfull/elev90/L90e000a.wav"
+2483 -567
View File
File diff suppressed because it is too large Load Diff
+10 -5
View File
@@ -125,6 +125,16 @@ static void printALCInfo(ALCdevice *device)
{
ALCint major, minor;
if(device)
{
const ALCchar *devname = NULL;
printf("\n");
if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
devname = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER);
if(checkALCErrors(device) != ALC_NO_ERROR || !devname)
devname = alcGetString(device, ALC_DEVICE_SPECIFIER);
printf("** Info for device \"%s\" **\n", devname);
}
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
if(checkALCErrors(device) == ALC_NO_ERROR)
@@ -276,11 +286,6 @@ int main(int argc, char *argv[])
printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device"));
return 1;
}
if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_ALL_DEVICES_SPECIFIER));
else
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
printALCInfo(device);
context = alcCreateContext(device, NULL);