Compare commits
1232 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b154025ab | |||
| b9b2bdb37a | |||
| 7b35c77062 | |||
| c23cfdcfa1 | |||
| 929e9bfac1 | |||
| b51afb74da | |||
| 5a43cd3b64 | |||
| 5d08563975 | |||
| adb83ad3c0 | |||
| 2d0e028993 | |||
| 703d72f20e | |||
| b7d67d8bcc | |||
| 7e5b13aabd | |||
| 7fbcb4b9e6 | |||
| 767a5b3c73 | |||
| a08080bd82 | |||
| 415bf58a06 | |||
| 3b517bfa59 | |||
| e356527a88 | |||
| 07e34cc3cf | |||
| f7f1dd1346 | |||
| 92ccacdc77 | |||
| b5ed2a5351 | |||
| 55c5e4fe92 | |||
| 3b165809cc | |||
| 5c59e6e704 | |||
| ef2f237276 | |||
| 0af14c7a11 | |||
| 8ef777ebbe | |||
| 305d790a19 | |||
| 1f3c1091d3 | |||
| 663b43f4f1 | |||
| 3e0cf0f239 | |||
| 560f34e3df | |||
| 335232207d | |||
| 93e71f0554 | |||
| 0efbf7bc9e | |||
| 3daaa078fb | |||
| 647448a32b | |||
| f7a8e3db35 | |||
| 7747c320a8 | |||
| ebc69bc870 | |||
| 10e2b7ecbf | |||
| 842a698f2b | |||
| f5f519aa80 | |||
| 7db29a2332 | |||
| 6e70ae9958 | |||
| e190fc9416 | |||
| 1a4a0abd1a | |||
| dddacc25a5 | |||
| 2ba2da467c | |||
| f2b64fd111 | |||
| 6623f69476 | |||
| db36574667 | |||
| 3131104595 | |||
| f64bdc4bd4 | |||
| fe6e532c87 | |||
| 5cdeeb47f3 | |||
| bc1bb7f90f | |||
| 0f0141b9dd | |||
| 302c08a14b | |||
| b643f13a6e | |||
| 487d05a73e | |||
| 91ed077eba | |||
| 49433c2074 | |||
| a93ff6ef3c | |||
| 44e10c4f69 | |||
| 7a832c4522 | |||
| 7d0faba424 | |||
| 01d942628b | |||
| 2a9012c94d | |||
| b571926a6d | |||
| f784aa704d | |||
| 153affac12 | |||
| e5d365a3d9 | |||
| 6ffaabeb75 | |||
| 06debb153d | |||
| 51e6786f31 | |||
| 50ef19720d | |||
| db4d62d17c | |||
| 8d24bd720f | |||
| 55556f0e6c | |||
| 7d9cabebff | |||
| 9602c46809 | |||
| 85daab0d5e | |||
| 105faa1935 | |||
| b299b90964 | |||
| 346f1ac293 | |||
| 6e113eea89 | |||
| 54f906b347 | |||
| 4b252bc494 | |||
| b192165fb4 | |||
| f887f4efdd | |||
| b37e54eead | |||
| ea4f458c1d | |||
| 394c76d64f | |||
| d34fc21a50 | |||
| f5435aa2de | |||
| e88f954cbf | |||
| fe897f291b | |||
| fbb6239299 | |||
| ae1633497c | |||
| 00b0e64bd2 | |||
| 2747c87893 | |||
| 2285c79ded | |||
| 230e784b9e | |||
| 4b88168edb | |||
| f29fbdf088 | |||
| 233acff3c4 | |||
| 5e625c9a68 | |||
| da4408835d | |||
| b78b8f0c82 | |||
| 484e8f07a0 | |||
| 504cdadd60 | |||
| 45c10229d9 | |||
| 973b92b8fd | |||
| 6ba0fd25a2 | |||
| 1dde8ad60b | |||
| 45b9cbe2b3 | |||
| 14912229b1 | |||
| 2b64df05e6 | |||
| 01d8d956da | |||
| 4f0d862cbe | |||
| e2ccc6f98e | |||
| d24ada7ab7 | |||
| 54e2316b65 | |||
| 58316a97d5 | |||
| 771ef3e8d5 | |||
| 65ed18960e | |||
| 799f8da333 | |||
| 40bb8bd9dc | |||
| 426f0273cb | |||
| 03ec2d6fc7 | |||
| e4f14fdc61 | |||
| 418c766493 | |||
| 4a65747a4b | |||
| 6dc194ed1d | |||
| 1aa69e77e9 | |||
| 6ac16867b4 | |||
| bbc679a5db | |||
| 592fb2b913 | |||
| f68f3f5f86 | |||
| 5f23860880 | |||
| faf59a7cba | |||
| cc2cb1142b | |||
| eb8be88866 | |||
| e43e1bd7f5 | |||
| eb586b0ed7 | |||
| 75aa96a4a6 | |||
| 10257f485a | |||
| deee6a73f0 | |||
| 84ba0a94c0 | |||
| 5d17cef55f | |||
| 70f1a7e3ca | |||
| 60785eab8e | |||
| 7e9af6f406 | |||
| 6b272ff585 | |||
| fecd679f33 | |||
| 2ab0e3521c | |||
| 9afd6b2858 | |||
| 670c88a64c | |||
| 425ff7cb00 | |||
| 1140b3ae83 | |||
| 5e1d1a52ba | |||
| e394d14cda | |||
| 9f073b6f1b | |||
| b375b130ba | |||
| 3fb6351212 | |||
| 61be01efc1 | |||
| 23bda38be0 | |||
| e6a0dd10a9 | |||
| ef68aa39f8 | |||
| b4b492c417 | |||
| a98e381c8e | |||
| 18f87b97d5 | |||
| c211f1d3fe | |||
| deb84cfdac | |||
| 7ad1b45d11 | |||
| 47161150d7 | |||
| 8e6832407a | |||
| 9166432ccf | |||
| 0107e74986 | |||
| c605e06e07 | |||
| 15a8e58225 | |||
| 4393b6b05f | |||
| ed037698fd | |||
| e870c22f87 | |||
| fd6f03cf74 | |||
| 706f407ed5 | |||
| dd3abd0f16 | |||
| 3fda804217 | |||
| 1d1440ac64 | |||
| 119768001c | |||
| 3ee92a2b33 | |||
| f87b607a53 | |||
| b4ba83ec34 | |||
| d807c4bf87 | |||
| 423f89c908 | |||
| 8d07bc41c9 | |||
| 86ef115e21 | |||
| 1dd8aa9b6f | |||
| f520257463 | |||
| 00dc3088c8 | |||
| e52e4b1a8c | |||
| 0ef3a30b84 | |||
| b375897374 | |||
| 2b2ce8bf3b | |||
| 47c8c15878 | |||
| fa36435290 | |||
| 4b83123cb8 | |||
| 37b17c8c78 | |||
| 51e81f4867 | |||
| ae7b61b040 | |||
| 5a2a534240 | |||
| 09258ca5c1 | |||
| e0966d99a1 | |||
| 66a700729b | |||
| a7266442c2 | |||
| cf34b9c04e | |||
| 530597347c | |||
| c543611897 | |||
| d88596e13c | |||
| c59bbe7c22 | |||
| d4670faafd | |||
| e772fb7d0e | |||
| 29ba8f9f1a | |||
| 61af4d715c | |||
| 535091e36c | |||
| 5b7f8c1816 | |||
| 18216ab1a9 | |||
| 5500ed9209 | |||
| 886f874ff3 | |||
| 466cac328f | |||
| 06caac2619 | |||
| 2691c33b55 | |||
| 7f6844e48d | |||
| a5a929ff72 | |||
| 84b5311257 | |||
| 6a97f6a327 | |||
| dfd02817fa | |||
| 222d2363cd | |||
| 14c117ffd3 | |||
| d5df2ad3ce | |||
| c56b2734fd | |||
| 5eebe73f79 | |||
| 21d400e3c6 | |||
| d270188578 | |||
| fcf9034c2b | |||
| 956e6f95ec | |||
| 50913948a0 | |||
| a5c02556e6 | |||
| 319f40462f | |||
| e5374f60c9 | |||
| 75679c959a | |||
| 628356a294 | |||
| 0fba3b0e1e | |||
| 92a650c827 | |||
| 3bbde05e0e | |||
| 3324bab81e | |||
| 81133769de | |||
| a7d3779dfa | |||
| 75fee8c11f | |||
| 9e11b0a8c6 | |||
| 5861920453 | |||
| eb277cc578 | |||
| 20fd648729 | |||
| 11caba9807 | |||
| 35b4b31d57 | |||
| a5c74e324c | |||
| e1cbf06653 | |||
| 5a1959f0cf | |||
| 7f5074949e | |||
| cf10a8d321 | |||
| a05006b06a | |||
| eb0b96752a | |||
| 2f453eba35 | |||
| 8b2e1fdd9a | |||
| c99b32a8ec | |||
| 92f95e4d94 | |||
| d1011f8d37 | |||
| a486045f7c | |||
| 0e7dc93681 | |||
| a7bbf7a741 | |||
| bfa782f329 | |||
| bed37a148c | |||
| bf19186223 | |||
| 087e75d47f | |||
| 9e2600cac4 | |||
| 3c27c24dec | |||
| 1b81642db5 | |||
| d3a6de3f86 | |||
| f4925a0e6a | |||
| b6b3ca6e6f | |||
| 53572da7de | |||
| 8a0e0265bc | |||
| 0ada7b2da5 | |||
| 1dee1245ff | |||
| e9da6950ee | |||
| 12abd75aed | |||
| 044774ed72 | |||
| cf56b0733b | |||
| 2b0a63003f | |||
| deef98658b | |||
| d9544d006b | |||
| 6a2b2a0aed | |||
| 9060d0cc36 | |||
| b4f9f89480 | |||
| a9b6b284c0 | |||
| da62f50528 | |||
| e84e38cc19 | |||
| 9266a37276 | |||
| ff8ee68852 | |||
| 470b506952 | |||
| de8a447ea5 | |||
| b2f4520ba1 | |||
| a4b1239f45 | |||
| 43350f9066 | |||
| 0988023d30 | |||
| e81e20446f | |||
| 64080250ff | |||
| 4e19f82a2b | |||
| 97743e32c2 | |||
| b8d53fb7e9 | |||
| 390d94ec97 | |||
| e01092a0da | |||
| 312e9a436d | |||
| e43470da7a | |||
| d3e7a26db6 | |||
| 8c2a2a5c9d | |||
| bf2ac6625c | |||
| edb386eb1e | |||
| cc3dd648ac | |||
| 98b2fa6cb5 | |||
| b615c7d0a2 | |||
| 7e06a10f73 | |||
| d46db2f648 | |||
| 6d77aabb23 | |||
| a7b9ee6bcb | |||
| 0e5c221a3c | |||
| 25f7c27043 | |||
| ec3b78e52d | |||
| 4e903c84cf | |||
| ae3ec4e767 | |||
| fd22226242 | |||
| fe1e046ea6 | |||
| 2171aaa35c | |||
| 97024151e4 | |||
| 62dfea43c6 | |||
| a4f8408150 | |||
| 80f2b787ef | |||
| 404cfde33e | |||
| 145bc6da6b | |||
| 69b10e2d7c | |||
| 25e86e8e91 | |||
| 780417ba39 | |||
| 9f159bfb33 | |||
| c2e9cda2d1 | |||
| 1d6ecee64f | |||
| 3ee2826565 | |||
| 0ceea27b44 | |||
| 0dc5837b82 | |||
| b4cbb3380a | |||
| d9cb2baf4a | |||
| 8f456f68ff | |||
| 54a421ec58 | |||
| 6ce420afe3 | |||
| 8028770901 | |||
| d51b93f869 | |||
| ab2b62c980 | |||
| 97fa7cc9ac | |||
| 2648a9b011 | |||
| 1fdc25df75 | |||
| 4db24af59a | |||
| d85c12c385 | |||
| ccd8cbc2a9 | |||
| 1075cce7b3 | |||
| 89f438df71 | |||
| 97027a7ad9 | |||
| 3a8ef2f0d6 | |||
| 4c8e6dead1 | |||
| c19a7408d9 | |||
| c7b9d27b85 | |||
| 30510dc478 | |||
| b788ae52b0 | |||
| ccbd67eab6 | |||
| f21b1eefda | |||
| 6cd55a0a10 | |||
| 0c5c63f4ba | |||
| 3dcd1e793e | |||
| 419294cddd | |||
| b9448a476e | |||
| 238a747414 | |||
| c35433ec7a | |||
| e8c9da0124 | |||
| 18cf6e3210 | |||
| c9205a58ae | |||
| 23d693cd06 | |||
| 724ad0d893 | |||
| 7a0df8553f | |||
| 477215883f | |||
| 05114815ba | |||
| 9080d5fda0 | |||
| 108b43458f | |||
| 3dfd67680c | |||
| 3a2fa18744 | |||
| 370c9f553d | |||
| e80aa008b2 | |||
| 812d91cbf8 | |||
| 942c8bf8a7 | |||
| b6b3e2f1cc | |||
| ee5ff943f3 | |||
| b28f48c1bd | |||
| 49e2fa428f | |||
| 2fcf97e207 | |||
| f3ac3cd1e2 | |||
| dd74757319 | |||
| ab0b5d9890 | |||
| 23f576360c | |||
| d7bd9c7559 | |||
| 9fb91f70aa | |||
| a32a3bcda8 | |||
| 16dc73ff48 | |||
| 0a1321aaae | |||
| 189add1d5a | |||
| 755062fb76 | |||
| 7d577832cd | |||
| c4866afbe0 | |||
| ee60248d19 | |||
| d546813c05 | |||
| f02d9e22d7 | |||
| cc67f45892 | |||
| c6a110ec59 | |||
| 7408396fd4 | |||
| da081b81c4 | |||
| 500ad776ea | |||
| e4a2b69b37 | |||
| 8eaa9bb469 | |||
| b283dd3682 | |||
| 4a5dd73a3c | |||
| 950570b8c3 | |||
| 72beb577b6 | |||
| de65ee08c9 | |||
| c06f4eb7f7 | |||
| 0abe13e3ad | |||
| 2ac808ffa2 | |||
| 58078e2c1e | |||
| 01503f8a7b | |||
| aa99e1220b | |||
| 783375af56 | |||
| 1d9f21f6dc | |||
| 0900c281a3 | |||
| f8c4b16c30 | |||
| c567339718 | |||
| 5eceb593e9 | |||
| 82244f298c | |||
| 3ab20d4ccb | |||
| ccc2644e6b | |||
| 7e2155d937 | |||
| c696d4dbb2 | |||
| f5195ee4f2 | |||
| 9f25ad42c1 | |||
| 1d4dc7d7a9 | |||
| 65d42083e1 | |||
| 6992a67dd9 | |||
| 922f5fa081 | |||
| 199df253ca | |||
| c1f435cc18 | |||
| 858592832f | |||
| a97211b572 | |||
| f196a9fc67 | |||
| 7ea71d8bfa | |||
| 9b615a0add | |||
| 4540034039 | |||
| 29d58f3d84 | |||
| 5290c820b4 | |||
| 22ad15e1f1 | |||
| 80b8abb0ec | |||
| 529ff3197a | |||
| b036bc9e04 | |||
| 9989f33fc2 | |||
| ba4456d24a | |||
| 00718ca03f | |||
| 6b8475b435 | |||
| e51295c79e | |||
| b40aa8636b | |||
| b3645df56f | |||
| 711f0a29ec | |||
| e8e1286572 | |||
| 3d722b9ba0 | |||
| 4ac0a507e0 | |||
| d54908d946 | |||
| 6ba5128f72 | |||
| c96a6c2b1b | |||
| 0b0588cc37 | |||
| 742bb12498 | |||
| f00017c8c1 | |||
| d976d02936 | |||
| 45f0886eba | |||
| 057fef88ae | |||
| 8148626ba3 | |||
| 14ffb8bd9b | |||
| 2f8510db31 | |||
| 38a4d9a6c5 | |||
| 9f5bf5f930 | |||
| 04dad28228 | |||
| a96f817738 | |||
| 8a51a7ea2d | |||
| b3cb511c06 | |||
| 7e3d02d991 | |||
| 412cec73de | |||
| a72c0f7470 | |||
| 45a245d7de | |||
| 1e60481040 | |||
| cda4c738e8 | |||
| f7c176e8ca | |||
| 3e2bc847d8 | |||
| b5092a6212 | |||
| 81d401eab5 | |||
| f986f7dfad | |||
| bcbc1dea25 | |||
| c8326ab328 | |||
| 91c6bc58dc | |||
| c722579c18 | |||
| 2f3bd5b5d9 | |||
| fad80a4f92 | |||
| 1b0a55f44c | |||
| 14b359beb0 | |||
| f32876d4bd | |||
| 13f9dbe582 | |||
| 8dfa2560b1 | |||
| 0c8c3b16d2 | |||
| 3d2812bd35 | |||
| a0e5cbc47f | |||
| d5ddc6acee | |||
| 30750d8763 | |||
| 3e4659076a | |||
| 7cd6327969 | |||
| 77128d298e | |||
| 1e8a379a03 | |||
| b889823b21 | |||
| 9723c553b6 | |||
| 6bfb0371eb | |||
| 1348bf2476 | |||
| 36446f3a58 | |||
| 5a484f7493 | |||
| 244d60fb96 | |||
| 0ae9638aa5 | |||
| 55b893c784 | |||
| c9b6bc848f | |||
| f97310c757 | |||
| 87b3520d02 | |||
| 887de0523f | |||
| a7a1f802a8 | |||
| 163cc62a00 | |||
| 5f566ebf05 | |||
| 1622986467 | |||
| ce6db53e5f | |||
| 292ea0607d | |||
| 3bd7256dc8 | |||
| da2429a1d0 | |||
| 54b5f35125 | |||
| 23bfb03d2a | |||
| 7381b1a696 | |||
| 99bcb7a0f6 | |||
| 17773c5644 | |||
| e1e47c6e43 | |||
| 2bb3d31d5c | |||
| 2a7bf1234b | |||
| e56e462317 | |||
| 3245e992c3 | |||
| 1299fa2801 | |||
| 52c78194b3 | |||
| 58466a304b | |||
| 51c09e94b8 | |||
| 22ccaf7f4a | |||
| b237ebba44 | |||
| 6038bbd6ec | |||
| 84a67ef766 | |||
| e03df97919 | |||
| 7bedd9ef7a | |||
| 72cd670636 | |||
| 9b028e76d2 | |||
| 479b4c9531 | |||
| 28f7d2151e | |||
| cd1560e2b0 | |||
| 87b4c93af9 | |||
| 0393d4ba71 | |||
| 717a0592ba | |||
| a67aff220f | |||
| e47e9c5ac3 | |||
| 4cd9367520 | |||
| c4ac014a0c | |||
| 21c99ca1e8 | |||
| 2cd3e9bcdb | |||
| f56fbbb777 | |||
| b64156aa2b | |||
| 5cb4129bc7 | |||
| bed264ad77 | |||
| f8be0448b0 | |||
| 75fa891e0a | |||
| 21574f7e16 | |||
| 0903a7f1e0 | |||
| c8d385c998 | |||
| 4c35bfbc10 | |||
| 83e322c5f3 | |||
| 6020b964c7 | |||
| b2d5367830 | |||
| d307ee8c2f | |||
| 202f57552a | |||
| 5ba864b6da | |||
| 30e97d5223 | |||
| 69be02c0fd | |||
| eefda551de | |||
| ac7ca07221 | |||
| b043390ec2 | |||
| 4c94ba6d8a | |||
| 7b87519c15 | |||
| 14bfe0293a | |||
| 931d422443 | |||
| 895150eebe | |||
| a5ccae5779 | |||
| 1635132fd5 | |||
| 048aee66cf | |||
| aea2868ce1 | |||
| 723755788d | |||
| 032d0836a7 | |||
| 5736bbc3e4 | |||
| 1b773a8585 | |||
| 3f0214ed6b | |||
| ea83608ee4 | |||
| 8cae1aee80 | |||
| 3db061e670 | |||
| efaaf9b5f9 | |||
| c451bf370d | |||
| 212b187447 | |||
| ac9a6e891f | |||
| 1fc44d5788 | |||
| 913c70557d | |||
| e8b785677d | |||
| 5c17eb69cb | |||
| f6d1e0f299 | |||
| e42bdc2022 | |||
| cf44f499b8 | |||
| 39c984fda8 | |||
| 9c23bc53b7 | |||
| 96b6cd46e6 | |||
| bc6e3879d4 | |||
| 3dcfd0dc98 | |||
| 40b8934487 | |||
| 0d39ac6528 | |||
| 157e1394d6 | |||
| edf78b077e | |||
| 753e64c76c | |||
| 3a072a294d | |||
| 23ae3c69b5 | |||
| bef9c5e2d5 | |||
| 58add24830 | |||
| fdffbfd2c4 | |||
| 357f841e88 | |||
| 7d73ac4405 | |||
| c429a5be25 | |||
| fba58fb1f0 | |||
| dad7f1cf0f | |||
| 8bee7a2b7f | |||
| 632b4e6332 | |||
| f26798bd19 | |||
| 7f4dcefc80 | |||
| d702cb9b49 | |||
| 2081228055 | |||
| f85283c036 | |||
| 14d6ab384d | |||
| 62036745f3 | |||
| 264274685a | |||
| 1babf28491 | |||
| 5a15dc4ddf | |||
| 0f782b385b | |||
| 1534fcfafd | |||
| 1c7ed6e693 | |||
| 0c5c56cf88 | |||
| 53c5275aa4 | |||
| c93d7a1721 | |||
| 9c7dad1bdf | |||
| bfe09b933e | |||
| 823f5779e1 | |||
| 96a18ba1d5 | |||
| b8bb41107c | |||
| ccffb7e380 | |||
| 39088b2035 | |||
| 8db05b8c17 | |||
| ba069ded40 | |||
| 6b8209fdc9 | |||
| ccf62fc525 | |||
| 6bfab6427a | |||
| aab4f85383 | |||
| 99b9208896 | |||
| 7402e3743d | |||
| 7ddfacb58f | |||
| c7a80418d9 | |||
| e98104dac8 | |||
| 884f668855 | |||
| 2bbe9d1b1f | |||
| 91c3cffe41 | |||
| 60a55aa897 | |||
| 9325a78043 | |||
| cd0e80126c | |||
| 1778c0d7d8 | |||
| b07901f1a0 | |||
| a15a1abb21 | |||
| 7da2eea8f0 | |||
| 596a1af7d9 | |||
| 6b6a7757ce | |||
| 8a6266239c | |||
| d83af679bd | |||
| af005668da | |||
| d07e94056d | |||
| 4d7aab1df4 | |||
| c3cbfecbae | |||
| a9d9553fff | |||
| 5cdf774ea7 | |||
| b75d4beb1a | |||
| 35a0430c81 | |||
| 1b5caa4112 | |||
| cbbb04eb40 | |||
| 7396aaf2c2 | |||
| 555ccce4ee | |||
| b838d123f8 | |||
| 1d3926e187 | |||
| 194f8fc791 | |||
| c316766144 | |||
| c00b2f9254 | |||
| 35c38e0b5e | |||
| 87ef4eeb36 | |||
| 06f5f0b7c8 | |||
| 9f91ff4734 | |||
| f7936b4709 | |||
| 60965e3a6c | |||
| b5cb2d633c | |||
| 810734718b | |||
| ca48c2e51b | |||
| 86ed2ee72b | |||
| 2abeed069b | |||
| 569106acd3 | |||
| 507d2f8afb | |||
| 54769a823e | |||
| cf3287f8ec | |||
| c5fbc9f05c | |||
| 2940b0f390 | |||
| 442e41f825 | |||
| e95b718cf4 | |||
| 143c08bfcb | |||
| b3902c8950 | |||
| 7210796cb8 | |||
| 949cfe2ceb | |||
| c39f27d5f8 | |||
| c9ac4f06ff | |||
| 674b14faa3 | |||
| a8fdcd30a5 | |||
| db3cb23c1d | |||
| 7972f7a2da | |||
| 8c3d50be28 | |||
| 4198f3062c | |||
| c2a6efc77a | |||
| 6928487aa1 | |||
| e608317e70 | |||
| 64b5d7a519 | |||
| eef41e76d7 | |||
| d583f7f307 | |||
| f97eca34df | |||
| 1363e044ac | |||
| 9967d4eadd | |||
| 2972de1047 | |||
| 38db4115fc | |||
| 0e824914b2 | |||
| 7832a6d1d8 | |||
| 0cce93a1f8 | |||
| 679f2480c9 | |||
| db7ca2c7ca | |||
| e2850df07e | |||
| 48def2fecb | |||
| ba236ad108 | |||
| 9a28402b90 | |||
| 8c705cc4ea | |||
| 24aaa24b5c | |||
| fd795a7eeb | |||
| abdc254e55 | |||
| f843b7e2e3 | |||
| eea86ab891 | |||
| d7a452588c | |||
| 56d9418119 | |||
| 0109104027 | |||
| c9c965ef85 | |||
| af3adf5244 | |||
| 43f97b4da1 | |||
| 63f07db303 | |||
| 2e9ca89dd3 | |||
| 8586aeabe8 | |||
| c031b4d5d0 | |||
| d91b3464a4 | |||
| 650d94e1a6 | |||
| 543134a6d2 | |||
| ab2626f9df | |||
| d50f9249d6 | |||
| 10a9753183 | |||
| 1e8718fe87 | |||
| 678d0b87d0 | |||
| 319dfce300 | |||
| c3e86933d0 | |||
| 936acf8c10 | |||
| 358d402cd0 | |||
| d11593eb5c | |||
| 4bdedc7fde | |||
| 9be625d6e8 | |||
| 898b245bb2 | |||
| be37f10fed | |||
| a87f651b4d | |||
| 575195a283 | |||
| 5621ee4239 | |||
| f5c4e67aef | |||
| 2f7de9d696 | |||
| 9cee723e92 | |||
| 4a1c0fedca | |||
| b510958f9e | |||
| d6c8bb35b4 | |||
| 4899674b6c | |||
| 4eeed5376f | |||
| 77ad538e68 | |||
| b699aca65b | |||
| ffd19fe961 | |||
| 208912ceac | |||
| 89c253ce41 | |||
| b1d4508d90 | |||
| 8249dc8559 | |||
| 59fe4f8a36 | |||
| acb493665d | |||
| 73123bc313 | |||
| 947aa1342c | |||
| 20c8f9fe31 | |||
| 66ee3bc217 | |||
| 031a2a1b1e | |||
| 9c87b73ad5 | |||
| 97139a530f | |||
| b483b1e380 | |||
| d9126eeb2c | |||
| d8048e136f | |||
| fd64fea279 | |||
| 667fd24c84 | |||
| 9ffb38d6be | |||
| 13397feccf | |||
| 57b05fb6d4 | |||
| 41a2c25b5a | |||
| b214249290 | |||
| 8dad1c382b | |||
| 6713a47d38 | |||
| 02e0223fe8 | |||
| 6c4add67e1 | |||
| 2b7324c06e | |||
| c95bd6cadf | |||
| d73694d3e6 | |||
| 5d607f9484 | |||
| 816c38e9e4 | |||
| 09130e5dcd | |||
| b87447787a | |||
| 5a548f8366 | |||
| 023658605e | |||
| 031111014b | |||
| b5b9303e66 | |||
| 3deaa2fad3 | |||
| c3cd4c80b2 | |||
| be3f3c4bf0 | |||
| d1ca8b4470 | |||
| 72e3386c6a | |||
| 4010a6b745 | |||
| 0218957eb5 | |||
| cd65ab7dfa | |||
| c4adf541c1 | |||
| 88e3a22772 | |||
| 191803ad53 | |||
| 1b7be672fa | |||
| 9581325b9c | |||
| 59990acc2a | |||
| 0bf7716332 | |||
| 3339e5dc6a | |||
| 30b3f68ddf | |||
| 75552f2765 | |||
| 4a0bf9fd44 | |||
| fa28098a83 | |||
| 646409cbdf | |||
| 9e8fb89a52 | |||
| 14441e0e53 | |||
| 7f5814c4d8 | |||
| e3afc3587e | |||
| 8a52c44d15 | |||
| e6e18732b5 | |||
| 3f8ae8f1ce | |||
| a79129835c | |||
| 6fcaecdc9f | |||
| 8dc8090888 | |||
| 4db2f1ec7d | |||
| 06fa030260 | |||
| 018f9fc278 | |||
| c0f6d46cd8 | |||
| 8e43b1fe04 | |||
| 04df919a1c | |||
| f82e628f08 | |||
| 07a7c03adb | |||
| e800f8c0a7 | |||
| d02dbef9d2 | |||
| 55262bc6e9 | |||
| 51ed22afb9 | |||
| 0cf32e2946 | |||
| 693ab4d8bc | |||
| e4869b447c | |||
| 547f356131 | |||
| 017ab1b3fd | |||
| 07ef566de1 | |||
| 3c8a29a179 | |||
| f74032d244 | |||
| eb489ac886 | |||
| 986628b8b2 | |||
| da4f5c6f96 | |||
| f09ae196a8 | |||
| 3e702ae2bc | |||
| 490d1c6a8e | |||
| 0e748d98d5 | |||
| c41e893361 | |||
| 2fd8d6916b | |||
| b4eaf1ab5a | |||
| 3c8e9a7f24 | |||
| 67ec72284d | |||
| 754a122aa0 | |||
| 0486d633c6 | |||
| 09b063002b | |||
| 8828f4d0e5 | |||
| 9495cf71fd | |||
| 4d0f70439c | |||
| d3bb5d4fcb | |||
| 61315d4dfb | |||
| 2a123a4760 | |||
| 4689ffb72d | |||
| d2895c7985 | |||
| 6abb9d151e | |||
| 08827efae3 | |||
| 16c05d2c05 | |||
| 4d4d699780 | |||
| ca1ec4b221 | |||
| facb922f3e | |||
| d7987677ac | |||
| 5fbbfa482f | |||
| 7287b5cd3c | |||
| 0692cf304d | |||
| 88ebe7e4c1 | |||
| d647ed60e8 | |||
| 1cb29ece08 | |||
| de8b7fbc5f | |||
| 98d78f7ff9 | |||
| 3d1eb7dcad | |||
| e1c0b5ea24 | |||
| 30820c1bde | |||
| 46b9802902 | |||
| b6fb28de1a | |||
| 17fc4ba5e3 | |||
| 596514f7aa | |||
| 6e3a6f90e9 | |||
| fbd6439bd2 | |||
| f72c735f9e | |||
| 9b23fc5db8 | |||
| aaff188b3b | |||
| 2595d85cca | |||
| 2c96c29938 | |||
| 65919b7037 | |||
| f1bb7c33f1 | |||
| 8e7a4046d0 | |||
| f4e0c6a348 | |||
| 885a5e9f90 | |||
| 22e3e9a18b | |||
| 445cde2dd4 | |||
| 3dd58cf765 | |||
| cd87061749 | |||
| 1311e051d9 | |||
| c9363832fe | |||
| 6ab22e7cbb | |||
| bb13f7f234 | |||
| 13ba253aec | |||
| c58469e234 | |||
| 57a03bc2b5 | |||
| a7b4e0b5c5 | |||
| bbb45e326c | |||
| dfe3e402a8 | |||
| e884da50ea | |||
| 4c576631ad | |||
| 5f6f046d25 | |||
| 65e033c64b | |||
| 07346da740 | |||
| c95f182a90 | |||
| 289c74788e | |||
| 65a8d9278d | |||
| 887c830d56 | |||
| 6db4e08efb | |||
| 4f81bce800 | |||
| 932fcfa8bf | |||
| 314832e35a | |||
| 6a9dd185e6 | |||
| 2172827f43 | |||
| 90e9cd970a | |||
| 845ca95888 | |||
| 92d8d2f8a4 | |||
| 7cd52b2857 | |||
| 9fbd6c6c3f | |||
| 08fdc5fa98 | |||
| 7e362249ff | |||
| 9fa2db0227 | |||
| 4c75a72a90 | |||
| a0b2778161 | |||
| bc6d94cd25 | |||
| e70141e57b | |||
| 2e70b82eaa | |||
| 117ed52091 | |||
| e9d5e53dbe | |||
| e308694521 | |||
| 7e498012ff | |||
| f98bf32be8 | |||
| 0f2ed8c84d | |||
| 8d67cdfaab | |||
| 67ba924ed3 | |||
| 764cfb6a0d | |||
| 4e3c945093 | |||
| 8558bc1d41 | |||
| 03f56419d0 | |||
| 3ee9d24c3f | |||
| 9b1ad6c873 | |||
| 97daaade8a | |||
| 8a1d5a21c3 | |||
| 301a8ba3a4 | |||
| 2d4453968d | |||
| a2580a85a8 | |||
| 8a0e15ff37 | |||
| 8953a73fb1 | |||
| 1a2883ae9a | |||
| a2358ffc41 | |||
| 33eb2786f8 | |||
| c8ec4fd505 | |||
| fe98ab5398 | |||
| 76be7eb1e7 | |||
| 6e32812bc1 | |||
| 50a7be6385 | |||
| 3763c95784 | |||
| 5fa5252648 | |||
| 1e82561a22 | |||
| ba32a52bb6 | |||
| 6027fda0ce | |||
| e5cae87502 | |||
| ba0ec1b4ba | |||
| 2acd6f52f1 | |||
| b520228bc6 | |||
| 343a8241ab | |||
| 00525274a0 | |||
| 2915d9dbd9 | |||
| 0c49e5ba56 | |||
| b65bc45236 | |||
| 94b7e5a227 | |||
| 928572d384 | |||
| 2d1988bb6f | |||
| e007dc3614 | |||
| 2ed929eadc | |||
| f1924fa7ea | |||
| df822513fa | |||
| 762bdaeee1 | |||
| 8003278a55 | |||
| 5f22d30fc9 | |||
| d6dc855511 | |||
| 8f49f2c25e | |||
| f4304ca062 | |||
| 044662e4b7 | |||
| d9d8319c22 | |||
| 56b094767b | |||
| 98bc60cfb7 | |||
| 2aacca76de | |||
| aea615edb3 | |||
| f6b2dfd09f | |||
| 7f9bcfbc7d | |||
| 22cc5af1fe | |||
| 0dc3f1984e | |||
| e74976e645 | |||
| 91278608c5 | |||
| 8e2d765671 | |||
| 2af39e51f8 | |||
| 1504cf8812 | |||
| 3bece35bbd | |||
| ae41ad5d1e | |||
| ee61f7a55c | |||
| 241ddf76d4 | |||
| fe6e73ede9 | |||
| 8dab4c418c | |||
| 41e2c41ecc | |||
| 30108c7855 | |||
| 40ba9db406 | |||
| f1f2941511 | |||
| d886fb118b | |||
| 46d46c49a8 | |||
| 40dd1fb853 | |||
| ab77fc14d5 | |||
| e0d0edc0fc | |||
| 7eb124d99c | |||
| 88f236ccd3 | |||
| 34a0c998cd | |||
| e658df493a | |||
| b2a257b6b0 | |||
| cde577690a | |||
| c85d53cfbe | |||
| 26127cd2f2 | |||
| 42d9140afe | |||
| 52ad28df92 | |||
| 58ba5fd0dd | |||
| 71cc91cc4a | |||
| 6db3463d17 | |||
| 969818db6f | |||
| d4b191d27d | |||
| 6b23f2dfa3 | |||
| 17e6840f92 | |||
| a1f987c016 | |||
| cff805e0a3 | |||
| 25a941666a | |||
| 8c59849ea4 | |||
| f9e569099c | |||
| 6fd6e4eacf | |||
| ce07270973 | |||
| ac05863f72 | |||
| 7f6df7695c | |||
| ed58571079 | |||
| 80fbe8a788 | |||
| 0fdec056fa | |||
| 1915fe831f | |||
| 98c01a40e6 | |||
| 33234d605a | |||
| c6defe9a6d | |||
| 244daba501 | |||
| 43dadcd9e4 | |||
| 90db244b5f | |||
| e98f1205e5 | |||
| 2205f91e5f | |||
| da1dee351d | |||
| 694e9a5fec | |||
| 9ac5d8ad2d | |||
| 706b9f2357 | |||
| 55b3675dee | |||
| dc86563486 | |||
| ebccfa93c3 | |||
| e9f4576d4d | |||
| 880902fecc | |||
| 96cf5b7282 | |||
| f89c9f7ea4 | |||
| 27a4c871fd | |||
| 37190b2caf | |||
| c6b948323e | |||
| ad2957ed98 | |||
| c469bfcb9e | |||
| 3d16be1822 | |||
| ad10d4ee74 | |||
| 3ba3c1ca31 | |||
| 4ad28964de | |||
| 15ce7fb8f7 | |||
| 80a22b6484 | |||
| 8cfac7c6b8 | |||
| 9ac6b4c2c8 | |||
| 861a933b7b | |||
| 58e5404d61 | |||
| 3676fdc4db | |||
| e7a555a953 | |||
| 1e6ba29cd2 | |||
| c5c83882b3 | |||
| ea3bc0518c | |||
| 2d46a1001e | |||
| 4edd7fe647 | |||
| ad5dfab428 | |||
| 85838c1d57 | |||
| 4fbb3ccf66 | |||
| 7f533c6a25 | |||
| 6dab9d54d1 | |||
| 7ed5d12717 | |||
| 23b2c1f902 | |||
| 5d579dd1a8 | |||
| 0ce138341c | |||
| 61b682131e | |||
| a53e3dda75 | |||
| 2220c22c90 | |||
| e3a70e5021 | |||
| af4faaf666 | |||
| f2548570b8 | |||
| d678f1d88b | |||
| f0ce1bff3e | |||
| ab3c23478d | |||
| 4e65e9bfa9 | |||
| 053aeee5d3 | |||
| 1652dc02ab | |||
| 099c2f3593 | |||
| 0378422fcb | |||
| 0760415d08 | |||
| 5730ccaa39 | |||
| aaa7082aa8 | |||
| 5d7815beed | |||
| a0ee2ccce7 | |||
| 110be7f500 | |||
| 52663e8a44 | |||
| 8646647b3e | |||
| a04dac670e | |||
| 81dd71dd71 | |||
| 4d15391c88 | |||
| fc2473f826 | |||
| 000d848f0b | |||
| 3c5007352e | |||
| e0fa497948 | |||
| f082c73539 | |||
| d4f8bd665f | |||
| 58d0db6eab | |||
| 1544ddf0a5 | |||
| 488ec612bb | |||
| 484702a2e5 | |||
| 371058fb9e | |||
| 97b00670f5 | |||
| 704b386cc5 | |||
| aace50ebf4 | |||
| 49201e892b | |||
| 19b8deba66 | |||
| 068c0076af | |||
| 37c93a6ad8 | |||
| 1b1c76da34 | |||
| 5db1aec1d1 | |||
| 05ca5c88ef | |||
| 980167c99b | |||
| 76f8c1e4e2 | |||
| b273d616ad | |||
| c16b895460 |
+68
-43
@@ -47,11 +47,11 @@ typedef struct ConfigEntry {
|
||||
typedef struct ConfigBlock {
|
||||
char *name;
|
||||
ConfigEntry *entries;
|
||||
size_t entryCount;
|
||||
unsigned int entryCount;
|
||||
} ConfigBlock;
|
||||
|
||||
static ConfigBlock *cfgBlocks;
|
||||
static size_t cfgCount;
|
||||
static unsigned int cfgCount;
|
||||
|
||||
static char buffer[1024];
|
||||
|
||||
@@ -62,7 +62,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
|
||||
while(fgets(buffer, sizeof(buffer), f))
|
||||
{
|
||||
size_t i = 0;
|
||||
int i = 0;
|
||||
|
||||
while(isspace(buffer[i]))
|
||||
i++;
|
||||
@@ -74,6 +74,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
if(buffer[0] == '[')
|
||||
{
|
||||
ConfigBlock *nextBlock;
|
||||
unsigned int i;
|
||||
|
||||
i = 1;
|
||||
while(buffer[i] && buffer[i] != ']')
|
||||
@@ -81,7 +82,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
|
||||
if(!buffer[i])
|
||||
{
|
||||
AL_PRINT("config parse error: bad line \"%s\"\n", buffer);
|
||||
ERR("config parse error: bad line \"%s\"\n", buffer);
|
||||
continue;
|
||||
}
|
||||
buffer[i] = 0;
|
||||
@@ -91,7 +92,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
if(buffer[i] && !isspace(buffer[i]))
|
||||
{
|
||||
if(buffer[i] != '#')
|
||||
AL_PRINT("config warning: extra data after block: \"%s\"\n", buffer+i);
|
||||
WARN("config warning: extra data after block: \"%s\"\n", buffer+i);
|
||||
break;
|
||||
}
|
||||
} while(buffer[i]);
|
||||
@@ -102,7 +103,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
if(strcasecmp(cfgBlocks[i].name, buffer+1) == 0)
|
||||
{
|
||||
nextBlock = cfgBlocks+i;
|
||||
// AL_PRINT("found block '%s'\n", nextBlock->name);
|
||||
TRACE("found block '%s'\n", nextBlock->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +113,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
nextBlock = realloc(cfgBlocks, (cfgCount+1)*sizeof(ConfigBlock));
|
||||
if(!nextBlock)
|
||||
{
|
||||
AL_PRINT("config parse error: error reallocating config blocks\n");
|
||||
ERR("config parse error: error reallocating config blocks\n");
|
||||
continue;
|
||||
}
|
||||
cfgBlocks = nextBlock;
|
||||
@@ -123,7 +124,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
nextBlock->entries = NULL;
|
||||
nextBlock->entryCount = 0;
|
||||
|
||||
// AL_PRINT("found new block '%s'\n", nextBlock->name);
|
||||
TRACE("found new block '%s'\n", nextBlock->name);
|
||||
}
|
||||
curBlock = nextBlock;
|
||||
continue;
|
||||
@@ -137,7 +138,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
|
||||
if(!buffer[i] || buffer[i] == '#' || i == 0)
|
||||
{
|
||||
AL_PRINT("config parse error: malformed option line: \"%s\"\n", buffer);
|
||||
ERR("config parse error: malformed option line: \"%s\"\n", buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -150,7 +151,7 @@ static void LoadConfigFromFile(FILE *f)
|
||||
i++;
|
||||
if(buffer[i] != '=')
|
||||
{
|
||||
AL_PRINT("config parse error: option without a value: \"%s\"\n", buffer);
|
||||
ERR("config parse error: option without a value: \"%s\"\n", buffer);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -161,20 +162,20 @@ static void LoadConfigFromFile(FILE *f)
|
||||
|
||||
/* Check if we already have this option set */
|
||||
ent = curBlock->entries;
|
||||
while((size_t)(ent-curBlock->entries) < curBlock->entryCount)
|
||||
while((unsigned int)(ent-curBlock->entries) < curBlock->entryCount)
|
||||
{
|
||||
if(strcasecmp(ent->key, buffer) == 0)
|
||||
break;
|
||||
ent++;
|
||||
}
|
||||
|
||||
if((size_t)(ent-curBlock->entries) >= curBlock->entryCount)
|
||||
if((unsigned int)(ent-curBlock->entries) >= curBlock->entryCount)
|
||||
{
|
||||
/* Allocate a new option entry */
|
||||
ent = realloc(curBlock->entries, (curBlock->entryCount+1)*sizeof(ConfigEntry));
|
||||
if(!ent)
|
||||
{
|
||||
AL_PRINT("config parse error: error reallocating config entries\n");
|
||||
ERR("config parse error: error reallocating config entries\n");
|
||||
continue;
|
||||
}
|
||||
curBlock->entries = ent;
|
||||
@@ -194,18 +195,19 @@ static void LoadConfigFromFile(FILE *f)
|
||||
i++;
|
||||
do {
|
||||
i--;
|
||||
} while(isspace(buffer[i]));
|
||||
} while(i >= 0 && isspace(buffer[i]));
|
||||
buffer[++i] = 0;
|
||||
|
||||
free(ent->value);
|
||||
ent->value = strdup(buffer);
|
||||
|
||||
// AL_PRINT("found '%s' = '%s'\n", ent->key, ent->value);
|
||||
TRACE("found '%s' = '%s'\n", ent->key, ent->value);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadALConfig(void)
|
||||
{
|
||||
const char *str;
|
||||
FILE *f;
|
||||
|
||||
cfgBlocks = calloc(1, sizeof(ConfigBlock));
|
||||
@@ -231,9 +233,9 @@ void ReadALConfig(void)
|
||||
LoadConfigFromFile(f);
|
||||
fclose(f);
|
||||
}
|
||||
if(getenv("HOME") && *(getenv("HOME")))
|
||||
if((str=getenv("HOME")) != NULL && *str)
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME"));
|
||||
snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str);
|
||||
f = fopen(buffer, "r");
|
||||
if(f)
|
||||
{
|
||||
@@ -242,9 +244,9 @@ void ReadALConfig(void)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(getenv("ALSOFT_CONF"))
|
||||
if((str=getenv("ALSOFT_CONF")) != NULL && *str)
|
||||
{
|
||||
f = fopen(getenv("ALSOFT_CONF"), "r");
|
||||
f = fopen(str, "r");
|
||||
if(f)
|
||||
{
|
||||
LoadConfigFromFile(f);
|
||||
@@ -255,11 +257,11 @@ void ReadALConfig(void)
|
||||
|
||||
void FreeALConfig(void)
|
||||
{
|
||||
size_t i;
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0;i < cfgCount;i++)
|
||||
{
|
||||
size_t j;
|
||||
unsigned int j;
|
||||
for(j = 0;j < cfgBlocks[i].entryCount;j++)
|
||||
{
|
||||
free(cfgBlocks[i].entries[j].key);
|
||||
@@ -275,30 +277,33 @@ void FreeALConfig(void)
|
||||
|
||||
const char *GetConfigValue(const char *blockName, const char *keyName, const char *def)
|
||||
{
|
||||
size_t i, j;
|
||||
unsigned int i, j;
|
||||
|
||||
if(keyName)
|
||||
if(!keyName)
|
||||
return def;
|
||||
|
||||
if(!blockName)
|
||||
blockName = "general";
|
||||
|
||||
for(i = 0;i < cfgCount;i++)
|
||||
{
|
||||
if(!blockName)
|
||||
blockName = "general";
|
||||
if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
|
||||
continue;
|
||||
|
||||
for(i = 0;i < cfgCount;i++)
|
||||
for(j = 0;j < cfgBlocks[i].entryCount;j++)
|
||||
{
|
||||
if(strcasecmp(cfgBlocks[i].name, blockName) != 0)
|
||||
continue;
|
||||
|
||||
for(j = 0;j < cfgBlocks[i].entryCount;j++)
|
||||
if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
|
||||
{
|
||||
if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
|
||||
{
|
||||
if(cfgBlocks[i].entries[j].value[0])
|
||||
return cfgBlocks[i].entries[j].value;
|
||||
return def;
|
||||
}
|
||||
TRACE("Found %s:%s = \"%s\"\n", blockName, keyName,
|
||||
cfgBlocks[i].entries[j].value);
|
||||
if(cfgBlocks[i].entries[j].value[0])
|
||||
return cfgBlocks[i].entries[j].value;
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Key %s:%s not found\n", blockName, keyName);
|
||||
return def;
|
||||
}
|
||||
|
||||
@@ -308,24 +313,44 @@ int ConfigValueExists(const char *blockName, const char *keyName)
|
||||
return !!val[0];
|
||||
}
|
||||
|
||||
int GetConfigValueInt(const char *blockName, const char *keyName, int def)
|
||||
int ConfigValueStr(const char *blockName, const char *keyName, const char **ret)
|
||||
{
|
||||
const char *val = GetConfigValue(blockName, keyName, "");
|
||||
if(!val[0]) return 0;
|
||||
|
||||
if(!val[0]) return def;
|
||||
return strtol(val, NULL, 0);
|
||||
*ret = val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
float GetConfigValueFloat(const char *blockName, const char *keyName, float def)
|
||||
int ConfigValueInt(const char *blockName, const char *keyName, int *ret)
|
||||
{
|
||||
const char *val = GetConfigValue(blockName, keyName, "");
|
||||
if(!val[0]) return 0;
|
||||
|
||||
*ret = strtol(val, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ConfigValueUInt(const char *blockName, const char *keyName, unsigned int *ret)
|
||||
{
|
||||
const char *val = GetConfigValue(blockName, keyName, "");
|
||||
if(!val[0]) return 0;
|
||||
|
||||
*ret = strtoul(val, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ConfigValueFloat(const char *blockName, const char *keyName, float *ret)
|
||||
{
|
||||
const char *val = GetConfigValue(blockName, keyName, "");
|
||||
if(!val[0]) return 0;
|
||||
|
||||
if(!val[0]) return def;
|
||||
#ifdef HAVE_STRTOF
|
||||
return strtof(val, NULL);
|
||||
*ret = strtof(val, NULL);
|
||||
#else
|
||||
return (float)strtod(val, NULL);
|
||||
*ret = (float)strtod(val, NULL);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetConfigValueBool(const char *blockName, const char *keyName, int def)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2011 by Chris Robinson.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alFilter.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alError.h"
|
||||
#include "alu.h"
|
||||
|
||||
|
||||
typedef struct ALdedicatedState {
|
||||
// Must be first in all effects!
|
||||
ALeffectState state;
|
||||
|
||||
ALfloat gains[MAXCHANNELS];
|
||||
} ALdedicatedState;
|
||||
|
||||
|
||||
static ALvoid DedicatedDestroy(ALeffectState *effect)
|
||||
{
|
||||
ALdedicatedState *state = (ALdedicatedState*)effect;
|
||||
free(state);
|
||||
}
|
||||
|
||||
static ALboolean DedicatedDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
|
||||
{
|
||||
(void)effect;
|
||||
(void)Device;
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
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++)
|
||||
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;
|
||||
}
|
||||
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])
|
||||
{
|
||||
ALdedicatedState *state = (ALdedicatedState*)effect;
|
||||
const ALfloat *gains = state->gains;
|
||||
ALuint i, s;
|
||||
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
ALfloat sample;
|
||||
|
||||
sample = SamplesIn[i];
|
||||
for(s = 0;s < MAXCHANNELS;s++)
|
||||
SamplesOut[i][s] = sample * gains[s];
|
||||
}
|
||||
}
|
||||
|
||||
ALeffectState *DedicatedCreate(void)
|
||||
{
|
||||
ALdedicatedState *state;
|
||||
ALsizei s;
|
||||
|
||||
state = malloc(sizeof(*state));
|
||||
if(!state)
|
||||
return NULL;
|
||||
|
||||
state->state.Destroy = DedicatedDestroy;
|
||||
state->state.DeviceUpdate = DedicatedDeviceUpdate;
|
||||
state->state.Update = DedicatedUpdate;
|
||||
state->state.Process = DedicatedProcess;
|
||||
|
||||
for(s = 0;s < MAXCHANNELS;s++)
|
||||
state->gains[s] = 0.0f;
|
||||
|
||||
return &state->state;
|
||||
}
|
||||
+59
-45
@@ -43,9 +43,8 @@ typedef struct ALechoState {
|
||||
ALuint delay;
|
||||
} Tap[2];
|
||||
ALuint Offset;
|
||||
// The LR gains for the first tap. The second tap uses the reverse
|
||||
ALfloat GainL;
|
||||
ALfloat GainR;
|
||||
/* The panning gains for the two taps */
|
||||
ALfloat Gain[2][MAXCHANNELS];
|
||||
|
||||
ALfloat FeedGain;
|
||||
|
||||
@@ -53,7 +52,7 @@ typedef struct ALechoState {
|
||||
ALfloat history[2];
|
||||
} ALechoState;
|
||||
|
||||
ALvoid EchoDestroy(ALeffectState *effect)
|
||||
static ALvoid EchoDestroy(ALeffectState *effect)
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
if(state)
|
||||
@@ -64,15 +63,15 @@ ALvoid EchoDestroy(ALeffectState *effect)
|
||||
}
|
||||
}
|
||||
|
||||
ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
|
||||
static ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
ALuint maxlen, i;
|
||||
|
||||
// Use the next power of 2 for the buffer length, so the tap offsets can be
|
||||
// wrapped using a mask instead of a modulo
|
||||
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
|
||||
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
|
||||
maxlen = fastf2u(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
|
||||
maxlen += fastf2u(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
|
||||
maxlen = NextPowerOf2(maxlen);
|
||||
|
||||
if(maxlen != state->BufferLength)
|
||||
@@ -91,67 +90,84 @@ ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Effect)
|
||||
static ALvoid EchoUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
ALuint frequency = Context->Device->Frequency;
|
||||
ALfloat lrpan, cw, a, g;
|
||||
ALuint frequency = Device->Frequency;
|
||||
ALfloat dirGain, ambientGain;
|
||||
const ALfloat *ChannelGain;
|
||||
ALfloat lrpan, cw, g, gain;
|
||||
ALuint i, pos;
|
||||
|
||||
state->Tap[0].delay = (ALuint)(Effect->Echo.Delay * frequency) + 1;
|
||||
state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * frequency);
|
||||
state->Tap[0].delay = fastf2u(Slot->effect.Echo.Delay * frequency) + 1;
|
||||
state->Tap[1].delay = fastf2u(Slot->effect.Echo.LRDelay * frequency);
|
||||
state->Tap[1].delay += state->Tap[0].delay;
|
||||
|
||||
lrpan = Effect->Echo.Spread*0.5f + 0.5f;
|
||||
state->GainL = aluSqrt( lrpan);
|
||||
state->GainR = aluSqrt(1.0f-lrpan);
|
||||
lrpan = Slot->effect.Echo.Spread;
|
||||
|
||||
state->FeedGain = Effect->Echo.Feedback;
|
||||
state->FeedGain = Slot->effect.Echo.Feedback;
|
||||
|
||||
cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / frequency);
|
||||
g = 1.0f - Effect->Echo.Damping;
|
||||
a = 0.0f;
|
||||
if(g < 0.9999f) // 1-epsilon
|
||||
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
|
||||
state->iirFilter.coeff = a;
|
||||
cw = aluCos(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++)
|
||||
{
|
||||
state->Gain[0][i] = 0.0f;
|
||||
state->Gain[1][i] = 0.0f;
|
||||
}
|
||||
|
||||
ambientGain = aluSqrt(1.0f/Device->NumChan);
|
||||
dirGain = aluFabs(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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
|
||||
static ALvoid EchoProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
const ALuint mask = state->BufferLength-1;
|
||||
const ALuint tap1 = state->Tap[0].delay;
|
||||
const ALuint tap2 = state->Tap[1].delay;
|
||||
ALuint offset = state->Offset;
|
||||
const ALfloat gain = Slot->Gain;
|
||||
ALfloat samp[2], smp;
|
||||
ALuint i;
|
||||
ALfloat smp;
|
||||
ALuint i, k;
|
||||
|
||||
for(i = 0;i < SamplesToDo;i++,offset++)
|
||||
{
|
||||
// Sample first tap
|
||||
/* First tap */
|
||||
smp = state->SampleBuffer[(offset-tap1) & mask];
|
||||
samp[0] = smp * state->GainL;
|
||||
samp[1] = smp * state->GainR;
|
||||
// Sample second tap. Reverse LR panning
|
||||
for(k = 0;k < MAXCHANNELS;k++)
|
||||
SamplesOut[i][k] += smp * state->Gain[0][k];
|
||||
|
||||
/* Second tap */
|
||||
smp = state->SampleBuffer[(offset-tap2) & mask];
|
||||
samp[0] += smp * state->GainR;
|
||||
samp[1] += smp * state->GainL;
|
||||
for(k = 0;k < MAXCHANNELS;k++)
|
||||
SamplesOut[i][k] += smp * state->Gain[1][k];
|
||||
|
||||
// Apply damping and feedback gain to the second tap, and mix in the
|
||||
// new sample
|
||||
smp = lpFilter2P(&state->iirFilter, 0, smp+SamplesIn[i]);
|
||||
state->SampleBuffer[offset&mask] = smp * state->FeedGain;
|
||||
|
||||
// Apply slot gain
|
||||
samp[0] *= gain;
|
||||
samp[1] *= gain;
|
||||
|
||||
SamplesOut[i][FRONT_LEFT] += samp[0];
|
||||
SamplesOut[i][FRONT_RIGHT] += samp[1];
|
||||
SamplesOut[i][SIDE_LEFT] += samp[0];
|
||||
SamplesOut[i][SIDE_RIGHT] += samp[1];
|
||||
SamplesOut[i][BACK_LEFT] += samp[0];
|
||||
SamplesOut[i][BACK_RIGHT] += samp[1];
|
||||
}
|
||||
state->Offset = offset;
|
||||
}
|
||||
@@ -175,8 +191,6 @@ ALeffectState *EchoCreate(void)
|
||||
state->Tap[0].delay = 0;
|
||||
state->Tap[1].delay = 0;
|
||||
state->Offset = 0;
|
||||
state->GainL = 0.0f;
|
||||
state->GainR = 0.0f;
|
||||
|
||||
state->iirFilter.coeff = 0.0f;
|
||||
state->iirFilter.history[0] = 0.0f;
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2009 by Chris Robinson.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alFilter.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alError.h"
|
||||
#include "alu.h"
|
||||
|
||||
|
||||
typedef struct ALmodulatorState {
|
||||
// Must be first in all effects!
|
||||
ALeffectState state;
|
||||
|
||||
enum {
|
||||
SINUSOID,
|
||||
SAWTOOTH,
|
||||
SQUARE
|
||||
} Waveform;
|
||||
|
||||
ALuint index;
|
||||
ALuint step;
|
||||
|
||||
ALfloat Gain[MAXCHANNELS];
|
||||
|
||||
FILTER iirFilter;
|
||||
ALfloat history[1];
|
||||
} ALmodulatorState;
|
||||
|
||||
#define WAVEFORM_FRACBITS 16
|
||||
#define WAVEFORM_FRACONE (1<<WAVEFORM_FRACBITS)
|
||||
#define WAVEFORM_FRACMASK (WAVEFORM_FRACONE-1)
|
||||
|
||||
static __inline ALfloat Sin(ALuint index)
|
||||
{
|
||||
return aluSin(index * (F_PI*2.0f / WAVEFORM_FRACONE));
|
||||
}
|
||||
|
||||
static __inline ALfloat Saw(ALuint index)
|
||||
{
|
||||
return index*(2.0f/WAVEFORM_FRACONE) - 1.0f;
|
||||
}
|
||||
|
||||
static __inline ALfloat Square(ALuint index)
|
||||
{
|
||||
return ((index>>(WAVEFORM_FRACBITS-1))&1)*2.0f - 1.0f;
|
||||
}
|
||||
|
||||
|
||||
static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
|
||||
{
|
||||
ALfloat *history = &iir->history[offset];
|
||||
ALfloat a = iir->coeff;
|
||||
ALfloat output = input;
|
||||
|
||||
output = output + (history[0]-output)*a;
|
||||
history[0] = output;
|
||||
|
||||
return input - output;
|
||||
}
|
||||
|
||||
|
||||
#define DECL_TEMPLATE(func) \
|
||||
static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \
|
||||
const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \
|
||||
{ \
|
||||
const ALuint step = state->step; \
|
||||
ALuint index = state->index; \
|
||||
ALfloat samp; \
|
||||
ALuint i, k; \
|
||||
\
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
samp = SamplesIn[i]; \
|
||||
\
|
||||
index += step; \
|
||||
index &= WAVEFORM_FRACMASK; \
|
||||
samp *= func(index); \
|
||||
\
|
||||
samp = hpFilter1P(&state->iirFilter, 0, samp); \
|
||||
\
|
||||
for(k = 0;k < MAXCHANNELS;k++) \
|
||||
SamplesOut[i][k] += state->Gain[k] * samp; \
|
||||
} \
|
||||
state->index = index; \
|
||||
}
|
||||
|
||||
DECL_TEMPLATE(Sin)
|
||||
DECL_TEMPLATE(Saw)
|
||||
DECL_TEMPLATE(Square)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
|
||||
static ALvoid ModulatorDestroy(ALeffectState *effect)
|
||||
{
|
||||
ALmodulatorState *state = (ALmodulatorState*)effect;
|
||||
free(state);
|
||||
}
|
||||
|
||||
static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
|
||||
{
|
||||
return AL_TRUE;
|
||||
(void)effect;
|
||||
(void)Device;
|
||||
}
|
||||
|
||||
static ALvoid ModulatorUpdate(ALeffectState *effect, ALCdevice *Device, const ALeffectslot *Slot)
|
||||
{
|
||||
ALmodulatorState *state = (ALmodulatorState*)effect;
|
||||
ALfloat gain, cw, a = 0.0f;
|
||||
ALuint index;
|
||||
|
||||
if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
|
||||
state->Waveform = SINUSOID;
|
||||
else if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
|
||||
state->Waveform = SAWTOOTH;
|
||||
else if(Slot->effect.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)
|
||||
state->Waveform = SQUARE;
|
||||
|
||||
state->step = fastf2u(Slot->effect.Modulator.Frequency*WAVEFORM_FRACONE /
|
||||
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);
|
||||
state->iirFilter.coeff = a;
|
||||
|
||||
gain = aluSqrt(1.0f/Device->NumChan);
|
||||
gain *= Slot->Gain;
|
||||
for(index = 0;index < MAXCHANNELS;index++)
|
||||
state->Gain[index] = 0.0f;
|
||||
for(index = 0;index < Device->NumChan;index++)
|
||||
{
|
||||
enum Channel chan = Device->Speaker2Chan[index];
|
||||
state->Gain[chan] = gain;
|
||||
}
|
||||
}
|
||||
|
||||
static ALvoid ModulatorProcess(ALeffectState *effect, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
|
||||
{
|
||||
ALmodulatorState *state = (ALmodulatorState*)effect;
|
||||
|
||||
switch(state->Waveform)
|
||||
{
|
||||
case SINUSOID:
|
||||
ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut);
|
||||
break;
|
||||
|
||||
case SAWTOOTH:
|
||||
ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut);
|
||||
break;
|
||||
|
||||
case SQUARE:
|
||||
ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ALeffectState *ModulatorCreate(void)
|
||||
{
|
||||
ALmodulatorState *state;
|
||||
|
||||
state = malloc(sizeof(*state));
|
||||
if(!state)
|
||||
return NULL;
|
||||
|
||||
state->state.Destroy = ModulatorDestroy;
|
||||
state->state.DeviceUpdate = ModulatorDeviceUpdate;
|
||||
state->state.Update = ModulatorUpdate;
|
||||
state->state.Process = ModulatorProcess;
|
||||
|
||||
state->index = 0;
|
||||
state->step = 1;
|
||||
|
||||
state->iirFilter.coeff = 0.0f;
|
||||
state->iirFilter.history[0] = 0.0f;
|
||||
|
||||
return &state->state;
|
||||
}
|
||||
+612
-645
File diff suppressed because it is too large
Load Diff
+23
-21
@@ -40,18 +40,15 @@ struct RingBuffer {
|
||||
|
||||
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length)
|
||||
{
|
||||
RingBuffer *ring = calloc(1, sizeof(*ring));
|
||||
RingBuffer *ring = calloc(1, sizeof(*ring) + ((length+1) * frame_size));
|
||||
if(ring)
|
||||
{
|
||||
ring->mem = (ALubyte*)(ring+1);
|
||||
|
||||
ring->frame_size = frame_size;
|
||||
ring->length = length+1;
|
||||
ring->write_pos = 1;
|
||||
ring->mem = malloc((length+1)*frame_size);
|
||||
if(!ring->mem)
|
||||
{
|
||||
free(ring);
|
||||
ring = NULL;
|
||||
}
|
||||
ring->read_pos = 0;
|
||||
ring->write_pos = 0;
|
||||
|
||||
InitializeCriticalSection(&ring->cs);
|
||||
}
|
||||
@@ -63,7 +60,6 @@ void DestroyRingBuffer(RingBuffer *ring)
|
||||
if(ring)
|
||||
{
|
||||
DeleteCriticalSection(&ring->cs);
|
||||
free(ring->mem);
|
||||
free(ring);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +69,7 @@ ALsizei RingBufferSize(RingBuffer *ring)
|
||||
ALsizei s;
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
s = (ring->write_pos-ring->read_pos-1+ring->length) % ring->length;
|
||||
s = (ring->write_pos-ring->read_pos+ring->length) % ring->length;
|
||||
LeaveCriticalSection(&ring->cs);
|
||||
|
||||
return s;
|
||||
@@ -85,20 +81,26 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
|
||||
remain = ring->length - ring->write_pos;
|
||||
if((ring->read_pos-ring->write_pos+ring->length)%ring->length < len)
|
||||
ring->read_pos = (ring->write_pos+len) % ring->length;
|
||||
remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length;
|
||||
if(remain < len) len = remain;
|
||||
|
||||
if(remain < len)
|
||||
if(len > 0)
|
||||
{
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, remain*ring->frame_size);
|
||||
memcpy(ring->mem, data+(remain*ring->frame_size), (len-remain)*ring->frame_size);
|
||||
}
|
||||
else
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, len*ring->frame_size);
|
||||
remain = ring->length - ring->write_pos;
|
||||
if(remain < len)
|
||||
{
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
|
||||
remain*ring->frame_size);
|
||||
memcpy(ring->mem, data+(remain*ring->frame_size),
|
||||
(len-remain)*ring->frame_size);
|
||||
}
|
||||
else
|
||||
memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
|
||||
len*ring->frame_size);
|
||||
|
||||
ring->write_pos += len;
|
||||
ring->write_pos %= ring->length;
|
||||
ring->write_pos += len;
|
||||
ring->write_pos %= ring->length;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&ring->cs);
|
||||
}
|
||||
|
||||
-1104
File diff suppressed because it is too large
Load Diff
+1298
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,701 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <unistd.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
AudioUnit audioUnit;
|
||||
|
||||
ALuint frameSize;
|
||||
ALdouble sampleRateRatio; // Ratio of hardware sample rate / requested sample rate
|
||||
AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD
|
||||
|
||||
AudioConverterRef audioConverter; // Sample rate converter if needed
|
||||
AudioBufferList *bufferList; // Buffer for data coming from the input device
|
||||
ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling
|
||||
|
||||
RingBuffer *ring;
|
||||
} ca_data;
|
||||
|
||||
static const ALCchar ca_device[] = "CoreAudio Default";
|
||||
|
||||
|
||||
static void destroy_buffer_list(AudioBufferList* list)
|
||||
{
|
||||
if(list)
|
||||
{
|
||||
UInt32 i;
|
||||
for(i = 0;i < list->mNumberBuffers;i++)
|
||||
free(list->mBuffers[i].mData);
|
||||
free(list);
|
||||
}
|
||||
}
|
||||
|
||||
static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
|
||||
{
|
||||
AudioBufferList *list;
|
||||
|
||||
list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer));
|
||||
if(list)
|
||||
{
|
||||
list->mNumberBuffers = 1;
|
||||
|
||||
list->mBuffers[0].mNumberChannels = channelCount;
|
||||
list->mBuffers[0].mDataByteSize = byteSize;
|
||||
list->mBuffers[0].mData = malloc(byteSize);
|
||||
if(list->mBuffers[0].mData == NULL)
|
||||
{
|
||||
free(list);
|
||||
list = NULL;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)inRefCon;
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
|
||||
aluMixData(device, ioData->mBuffers[0].mData,
|
||||
ioData->mBuffers[0].mDataByteSize / data->frameSize);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
|
||||
AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)inUserData;
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
|
||||
// Read from the ring buffer and store temporarily in a large buffer
|
||||
ReadRingBuffer(data->ring, data->resampleBuffer, (ALsizei)(*ioNumberDataPackets));
|
||||
|
||||
// Set the input data
|
||||
ioData->mNumberBuffers = 1;
|
||||
ioData->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
|
||||
ioData->mBuffers[0].mData = data->resampleBuffer;
|
||||
ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * data->format.mBytesPerFrame;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames, AudioBufferList *ioData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)inRefCon;
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
AudioUnitRenderActionFlags flags = 0;
|
||||
OSStatus err;
|
||||
|
||||
// fill the bufferList with data from the input device
|
||||
err = AudioUnitRender(data->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, data->bufferList);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitRender error: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
ComponentDescription desc;
|
||||
Component comp;
|
||||
ca_data *data;
|
||||
OSStatus err;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = ca_device;
|
||||
else if(strcmp(deviceName, ca_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
/* open the default output unit */
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(comp == NULL)
|
||||
{
|
||||
ERR("FindNextComponent failed\n");
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
|
||||
err = OpenAComponent(comp, &data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("OpenAComponent failed\n");
|
||||
free(data);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
/* init and start the default audio unit... */
|
||||
err = AudioUnitInitialize(data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitInitialize failed\n");
|
||||
CloseComponent(data->audioUnit);
|
||||
free(data);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void ca_close_playback(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
|
||||
AudioUnitUninitialize(data->audioUnit);
|
||||
CloseComponent(data->audioUnit);
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean ca_reset_playback(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
AudioStreamBasicDescription streamFormat;
|
||||
AURenderCallbackStruct input;
|
||||
OSStatus err;
|
||||
UInt32 size;
|
||||
|
||||
err = AudioUnitUninitialize(data->audioUnit);
|
||||
if(err != noErr)
|
||||
ERR("-- AudioUnitUninitialize failed.\n");
|
||||
|
||||
/* retrieve default output unit's properties (output side) */
|
||||
size = sizeof(AudioStreamBasicDescription);
|
||||
err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size);
|
||||
if(err != noErr || size != sizeof(AudioStreamBasicDescription))
|
||||
{
|
||||
ERR("AudioUnitGetProperty failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
TRACE("Output streamFormat of default output unit -\n");
|
||||
TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket);
|
||||
TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame);
|
||||
TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel);
|
||||
TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket);
|
||||
TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame);
|
||||
TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate);
|
||||
#endif
|
||||
|
||||
/* set default output unit's input side to match output side */
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(device->Frequency != streamFormat.mSampleRate)
|
||||
{
|
||||
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
||||
streamFormat.mSampleRate /
|
||||
device->Frequency);
|
||||
device->Frequency = streamFormat.mSampleRate;
|
||||
}
|
||||
|
||||
/* FIXME: How to tell what channels are what in the output device, and how
|
||||
* to specify what we're giving? eg, 6.0 vs 5.1 */
|
||||
switch(streamFormat.mChannelsPerFrame)
|
||||
{
|
||||
case 1:
|
||||
device->FmtChans = DevFmtMono;
|
||||
break;
|
||||
case 2:
|
||||
device->FmtChans = DevFmtStereo;
|
||||
break;
|
||||
case 4:
|
||||
device->FmtChans = DevFmtQuad;
|
||||
break;
|
||||
case 6:
|
||||
device->FmtChans = DevFmtX51;
|
||||
break;
|
||||
case 7:
|
||||
device->FmtChans = DevFmtX61;
|
||||
break;
|
||||
case 8:
|
||||
device->FmtChans = DevFmtX71;
|
||||
break;
|
||||
default:
|
||||
ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame);
|
||||
device->FmtChans = DevFmtStereo;
|
||||
streamFormat.mChannelsPerFrame = 2;
|
||||
break;
|
||||
}
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
/* use channel count and sample rate from the default output unit's current
|
||||
* parameters, but reset everything else */
|
||||
streamFormat.mFramesPerPacket = 1;
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtUByte:
|
||||
device->FmtType = DevFmtByte;
|
||||
/* fall-through */
|
||||
case DevFmtByte:
|
||||
streamFormat.mBitsPerChannel = 8;
|
||||
streamFormat.mBytesPerPacket = streamFormat.mChannelsPerFrame;
|
||||
streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame;
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
case DevFmtFloat:
|
||||
device->FmtType = DevFmtShort;
|
||||
/* fall-through */
|
||||
case DevFmtShort:
|
||||
streamFormat.mBitsPerChannel = 16;
|
||||
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
|
||||
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
device->FmtType = DevFmtInt;
|
||||
/* fall-through */
|
||||
case DevFmtInt:
|
||||
streamFormat.mBitsPerChannel = 32;
|
||||
streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame;
|
||||
streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame;
|
||||
break;
|
||||
}
|
||||
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger |
|
||||
kAudioFormatFlagsNativeEndian |
|
||||
kLinearPCMFormatFlagIsPacked;
|
||||
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
/* setup callback */
|
||||
data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
input.inputProc = ca_callback;
|
||||
input.inputProcRefCon = device;
|
||||
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
/* init the default audio unit... */
|
||||
err = AudioUnitInitialize(data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitInitialize failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean ca_start_playback(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
OSStatus err;
|
||||
|
||||
err = AudioOutputUnitStart(data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioOutputUnitStart failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void ca_stop_playback(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
OSStatus err;
|
||||
|
||||
err = AudioOutputUnitStop(data->audioUnit);
|
||||
if(err != noErr)
|
||||
ERR("AudioOutputUnitStop failed\n");
|
||||
}
|
||||
|
||||
static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
AudioStreamBasicDescription requestedFormat; // The application requested format
|
||||
AudioStreamBasicDescription hardwareFormat; // The hardware format
|
||||
AudioStreamBasicDescription outputFormat; // The AudioUnit output format
|
||||
AURenderCallbackStruct input;
|
||||
ComponentDescription desc;
|
||||
AudioDeviceID inputDevice;
|
||||
UInt32 outputFrameCount;
|
||||
UInt32 propertySize;
|
||||
UInt32 enableIO;
|
||||
Component comp;
|
||||
ca_data *data;
|
||||
OSStatus err;
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_HALOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
||||
// Search for component with given description
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if(comp == NULL)
|
||||
{
|
||||
ERR("FindNextComponent failed\n");
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
device->ExtraData = data;
|
||||
|
||||
// Open the component
|
||||
err = OpenAComponent(comp, &data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("OpenAComponent failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Turn off AudioUnit output
|
||||
enableIO = 0;
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Turn on AudioUnit input
|
||||
enableIO = 1;
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Get the default input device
|
||||
propertySize = sizeof(AudioDeviceID);
|
||||
err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioHardwareGetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(inputDevice == kAudioDeviceUnknown)
|
||||
{
|
||||
ERR("No input device found\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Track the input device
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// set capture callback
|
||||
input.inputProc = ca_capture_callback;
|
||||
input.inputProcRefCon = device;
|
||||
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Initialize the device
|
||||
err = AudioUnitInitialize(data->audioUnit);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitInitialize failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Get the hardware format
|
||||
propertySize = sizeof(AudioStreamBasicDescription);
|
||||
err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
|
||||
if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription))
|
||||
{
|
||||
ERR("AudioUnitGetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set up the requested format description
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtUByte:
|
||||
requestedFormat.mBitsPerChannel = 8;
|
||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
|
||||
break;
|
||||
case DevFmtShort:
|
||||
requestedFormat.mBitsPerChannel = 16;
|
||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
break;
|
||||
case DevFmtInt:
|
||||
requestedFormat.mBitsPerChannel = 32;
|
||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
|
||||
break;
|
||||
case DevFmtFloat:
|
||||
requestedFormat.mBitsPerChannel = 32;
|
||||
requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked;
|
||||
break;
|
||||
case DevFmtByte:
|
||||
case DevFmtUShort:
|
||||
case DevFmtUInt:
|
||||
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch(device->FmtChans)
|
||||
{
|
||||
case DevFmtMono:
|
||||
requestedFormat.mChannelsPerFrame = 1;
|
||||
break;
|
||||
case DevFmtStereo:
|
||||
requestedFormat.mChannelsPerFrame = 2;
|
||||
break;
|
||||
|
||||
case DevFmtQuad:
|
||||
case DevFmtX51:
|
||||
case DevFmtX51Side:
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
|
||||
goto error;
|
||||
}
|
||||
|
||||
requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8;
|
||||
requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame;
|
||||
requestedFormat.mSampleRate = device->Frequency;
|
||||
requestedFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
requestedFormat.mReserved = 0;
|
||||
requestedFormat.mFramesPerPacket = 1;
|
||||
|
||||
// save requested format description for later use
|
||||
data->format = requestedFormat;
|
||||
data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
|
||||
// Use intermediate format for sample rate conversion (outputFormat)
|
||||
// Set sample rate to the same as hardware for resampling later
|
||||
outputFormat = requestedFormat;
|
||||
outputFormat.mSampleRate = hardwareFormat.mSampleRate;
|
||||
|
||||
// Determine sample rate ratio for resampling
|
||||
data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency;
|
||||
|
||||
// The output format should be the requested format, but using the hardware sample rate
|
||||
// This is because the AudioUnit will automatically scale other properties, except for sample rate
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set the AudioUnit output format frame count
|
||||
outputFrameCount = device->UpdateSize * data->sampleRateRatio;
|
||||
err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioUnitSetProperty failed: %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set up sample converter
|
||||
err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioConverterNew failed: %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Create a buffer for use in the resample callback
|
||||
data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio);
|
||||
|
||||
// Allocate buffer for the AudioUnit output
|
||||
data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio);
|
||||
if(data->bufferList == NULL)
|
||||
goto error;
|
||||
|
||||
data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates);
|
||||
if(data->ring == NULL)
|
||||
goto error;
|
||||
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
error:
|
||||
DestroyRingBuffer(data->ring);
|
||||
free(data->resampleBuffer);
|
||||
destroy_buffer_list(data->bufferList);
|
||||
|
||||
if(data->audioConverter)
|
||||
AudioConverterDispose(data->audioConverter);
|
||||
if(data->audioUnit)
|
||||
CloseComponent(data->audioUnit);
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void ca_close_capture(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
|
||||
DestroyRingBuffer(data->ring);
|
||||
free(data->resampleBuffer);
|
||||
destroy_buffer_list(data->bufferList);
|
||||
|
||||
AudioConverterDispose(data->audioConverter);
|
||||
CloseComponent(data->audioUnit);
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void ca_start_capture(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
OSStatus err = AudioOutputUnitStart(data->audioUnit);
|
||||
if(err != noErr)
|
||||
ERR("AudioOutputUnitStart failed\n");
|
||||
}
|
||||
|
||||
static void ca_stop_capture(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
OSStatus err = AudioOutputUnitStop(data->audioUnit);
|
||||
if(err != noErr)
|
||||
ERR("AudioOutputUnitStop failed\n");
|
||||
}
|
||||
|
||||
static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
|
||||
{
|
||||
ca_data *data = (ca_data*)device->ExtraData;
|
||||
AudioBufferList *list;
|
||||
UInt32 frameCount;
|
||||
OSStatus err;
|
||||
|
||||
// If no samples are requested, just return
|
||||
if(samples == 0)
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
// Allocate a temporary AudioBufferList to use as the return resamples data
|
||||
list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer));
|
||||
|
||||
// Point the resampling buffer to the capture buffer
|
||||
list->mNumberBuffers = 1;
|
||||
list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
|
||||
list->mBuffers[0].mDataByteSize = samples * data->frameSize;
|
||||
list->mBuffers[0].mData = buffer;
|
||||
|
||||
// Resample into another AudioBufferList
|
||||
frameCount = samples;
|
||||
err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback,
|
||||
device, &frameCount, list, NULL);
|
||||
if(err != noErr)
|
||||
{
|
||||
ERR("AudioConverterFillComplexBuffer error: %d\n", err);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static ALCuint ca_available_samples(ALCdevice *device)
|
||||
{
|
||||
ca_data *data = device->ExtraData;
|
||||
return RingBufferSize(data->ring) / data->sampleRateRatio;
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs ca_funcs = {
|
||||
ca_open_playback,
|
||||
ca_close_playback,
|
||||
ca_reset_playback,
|
||||
ca_start_playback,
|
||||
ca_stop_playback,
|
||||
ca_open_capture,
|
||||
ca_close_capture,
|
||||
ca_start_capture,
|
||||
ca_stop_capture,
|
||||
ca_capture_samples,
|
||||
ca_available_samples
|
||||
};
|
||||
|
||||
ALCboolean alc_ca_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = ca_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_ca_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_ca_probe(enum DevProbe type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(ca_device);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
AppendCaptureDeviceList(ca_device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2011 by Chris Robinson
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
|
||||
static ALCenum loopback_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void loopback_close_playback(ALCdevice *device)
|
||||
{
|
||||
(void)device;
|
||||
}
|
||||
|
||||
static ALCboolean loopback_reset_playback(ALCdevice *device)
|
||||
{
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean loopback_start_playback(ALCdevice *device)
|
||||
{
|
||||
return ALC_TRUE;
|
||||
(void)device;
|
||||
}
|
||||
|
||||
static void loopback_stop_playback(ALCdevice *device)
|
||||
{
|
||||
(void)device;
|
||||
}
|
||||
|
||||
static const BackendFuncs loopback_funcs = {
|
||||
loopback_open_playback,
|
||||
loopback_close_playback,
|
||||
loopback_reset_playback,
|
||||
loopback_start_playback,
|
||||
loopback_stop_playback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
ALCboolean alc_loopback_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = loopback_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_loopback_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_loopback_probe(enum DevProbe type)
|
||||
{
|
||||
(void)type;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2010 by Chris Robinson
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} null_data;
|
||||
|
||||
|
||||
static const ALCchar nullDevice[] = "No Output";
|
||||
|
||||
static ALuint NullProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *Device = (ALCdevice*)ptr;
|
||||
null_data *data = (null_data*)Device->ExtraData;
|
||||
ALuint now, start;
|
||||
ALuint64 avail, done;
|
||||
const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
|
||||
Device->Frequency / 2;
|
||||
|
||||
done = 0;
|
||||
start = timeGetTime();
|
||||
while(!data->killNow && Device->Connected)
|
||||
{
|
||||
now = timeGetTime();
|
||||
|
||||
avail = (ALuint64)(now-start) * Device->Frequency / 1000;
|
||||
if(avail < done)
|
||||
{
|
||||
/* Timer wrapped (50 days???). Add the remainder of the cycle to
|
||||
* the available count and reset the number of samples done */
|
||||
avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
|
||||
done = 0;
|
||||
}
|
||||
if(avail-done < Device->UpdateSize)
|
||||
{
|
||||
Sleep(restTime);
|
||||
continue;
|
||||
}
|
||||
|
||||
while(avail-done >= Device->UpdateSize)
|
||||
{
|
||||
aluMixData(Device, NULL, Device->UpdateSize);
|
||||
done += Device->UpdateSize;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALCenum null_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
null_data *data;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = nullDevice;
|
||||
else if(strcmp(deviceName, nullDevice) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (null_data*)calloc(1, sizeof(*data));
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void null_close_playback(ALCdevice *device)
|
||||
{
|
||||
null_data *data = (null_data*)device->ExtraData;
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean null_reset_playback(ALCdevice *device)
|
||||
{
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean null_start_playback(ALCdevice *device)
|
||||
{
|
||||
null_data *data = (null_data*)device->ExtraData;
|
||||
|
||||
data->thread = StartThread(NullProc, device);
|
||||
if(data->thread == NULL)
|
||||
return ALC_FALSE;
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void null_stop_playback(ALCdevice *device)
|
||||
{
|
||||
null_data *data = (null_data*)device->ExtraData;
|
||||
|
||||
if(!data->thread)
|
||||
return;
|
||||
|
||||
data->killNow = 1;
|
||||
StopThread(data->thread);
|
||||
data->thread = NULL;
|
||||
|
||||
data->killNow = 0;
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs null_funcs = {
|
||||
null_open_playback,
|
||||
null_close_playback,
|
||||
null_reset_playback,
|
||||
null_start_playback,
|
||||
null_stop_playback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
ALCboolean alc_null_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = null_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_null_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_null_probe(enum DevProbe type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(nullDevice);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This is an OpenAL backend for Android using the native audio APIs based on
|
||||
* OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
|
||||
* bundled with NDK.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
|
||||
#include <SLES/OpenSLES.h>
|
||||
#if 1
|
||||
#include <SLES/OpenSLES_Android.h>
|
||||
#else
|
||||
extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
|
||||
struct SLAndroidSimpleBufferQueueItf_;
|
||||
typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf;
|
||||
|
||||
typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext);
|
||||
|
||||
typedef struct SLAndroidSimpleBufferQueueState_ {
|
||||
SLuint32 count;
|
||||
SLuint32 index;
|
||||
} SLAndroidSimpleBufferQueueState;
|
||||
|
||||
|
||||
struct SLAndroidSimpleBufferQueueItf_ {
|
||||
SLresult (*Enqueue) (
|
||||
SLAndroidSimpleBufferQueueItf self,
|
||||
const void *pBuffer,
|
||||
SLuint32 size
|
||||
);
|
||||
SLresult (*Clear) (
|
||||
SLAndroidSimpleBufferQueueItf self
|
||||
);
|
||||
SLresult (*GetState) (
|
||||
SLAndroidSimpleBufferQueueItf self,
|
||||
SLAndroidSimpleBufferQueueState *pState
|
||||
);
|
||||
SLresult (*RegisterCallback) (
|
||||
SLAndroidSimpleBufferQueueItf self,
|
||||
slAndroidSimpleBufferQueueCallback callback,
|
||||
void* pContext
|
||||
);
|
||||
};
|
||||
|
||||
#define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD)
|
||||
|
||||
typedef struct SLDataLocator_AndroidSimpleBufferQueue {
|
||||
SLuint32 locatorType;
|
||||
SLuint32 numBuffers;
|
||||
} SLDataLocator_AndroidSimpleBufferQueue;
|
||||
|
||||
#endif
|
||||
|
||||
/* Helper macros */
|
||||
#define SLObjectItf_Realize(a,b) ((*(a))->Realize((a),(b)))
|
||||
#define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c)))
|
||||
#define SLObjectItf_Destroy(a) ((*(a))->Destroy((a)))
|
||||
|
||||
#define SLEngineItf_CreateOutputMix(a,b,c,d,e) ((*(a))->CreateOutputMix((a),(b),(c),(d),(e)))
|
||||
#define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g)))
|
||||
|
||||
#define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b)))
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* engine interfaces */
|
||||
SLObjectItf engineObject;
|
||||
SLEngineItf engine;
|
||||
|
||||
/* output mix interfaces */
|
||||
SLObjectItf outputMix;
|
||||
|
||||
/* buffer queue player interfaces */
|
||||
SLObjectItf bufferQueueObject;
|
||||
|
||||
void *buffer;
|
||||
ALuint bufferSize;
|
||||
|
||||
ALuint frameSize;
|
||||
} osl_data;
|
||||
|
||||
|
||||
static const ALCchar opensl_device[] = "OpenSL";
|
||||
|
||||
|
||||
static SLuint32 GetChannelMask(enum DevFmtChannels chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
|
||||
case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
|
||||
case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
|
||||
SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
|
||||
case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
|
||||
SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
|
||||
SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
|
||||
case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
|
||||
SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
|
||||
SL_SPEAKER_BACK_CENTER|
|
||||
SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
|
||||
case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
|
||||
SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
|
||||
SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
|
||||
SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
|
||||
case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
|
||||
SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
|
||||
SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *res_str(SLresult result)
|
||||
{
|
||||
switch(result)
|
||||
{
|
||||
case SL_RESULT_SUCCESS: return "Success";
|
||||
case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
|
||||
case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
|
||||
case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
|
||||
case SL_RESULT_RESOURCE_ERROR: return "Resource error";
|
||||
case SL_RESULT_RESOURCE_LOST: return "Resource lost";
|
||||
case SL_RESULT_IO_ERROR: return "I/O error";
|
||||
case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
|
||||
case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
|
||||
case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
|
||||
case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
|
||||
case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
|
||||
case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
|
||||
case SL_RESULT_INTERNAL_ERROR: return "Internal error";
|
||||
case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
|
||||
case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
|
||||
case SL_RESULT_CONTROL_LOST: return "Control lost";
|
||||
case SL_RESULT_READONLY: return "ReadOnly";
|
||||
case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
|
||||
case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
|
||||
}
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
||||
#define PRINTERR(x, s) do { \
|
||||
if((x) != SL_RESULT_SUCCESS) \
|
||||
ERR("%s: %s\n", (s), res_str((x))); \
|
||||
} while(0)
|
||||
|
||||
/* this callback handler is called every time a buffer finishes playing */
|
||||
static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||
{
|
||||
ALCdevice *Device = context;
|
||||
osl_data *data = Device->ExtraData;
|
||||
SLresult result;
|
||||
|
||||
aluMixData(Device, data->buffer, data->bufferSize/data->frameSize);
|
||||
|
||||
result = (*bq)->Enqueue(bq, data->buffer, data->bufferSize);
|
||||
PRINTERR(result, "bq->Enqueue");
|
||||
}
|
||||
|
||||
|
||||
static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName)
|
||||
{
|
||||
osl_data *data = NULL;
|
||||
SLresult result;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = opensl_device;
|
||||
else if(strcmp(deviceName, opensl_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
if(!data)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
|
||||
// create engine
|
||||
result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL);
|
||||
PRINTERR(result, "slCreateEngine");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "engine->Realize");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine);
|
||||
PRINTERR(result, "engine->GetInterface");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL);
|
||||
PRINTERR(result, "engine->CreateOutputMix");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "outputMix->Realize");
|
||||
}
|
||||
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
if(data->outputMix != NULL)
|
||||
SLObjectItf_Destroy(data->outputMix);
|
||||
data->outputMix = NULL;
|
||||
|
||||
if(data->engineObject != NULL)
|
||||
SLObjectItf_Destroy(data->engineObject);
|
||||
data->engineObject = NULL;
|
||||
data->engine = NULL;
|
||||
|
||||
free(data);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
Device->szDeviceName = strdup(deviceName);
|
||||
Device->ExtraData = data;
|
||||
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void opensl_close_playback(ALCdevice *Device)
|
||||
{
|
||||
osl_data *data = Device->ExtraData;
|
||||
|
||||
if(data->bufferQueueObject != NULL)
|
||||
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||
data->bufferQueueObject = NULL;
|
||||
|
||||
SLObjectItf_Destroy(data->outputMix);
|
||||
data->outputMix = NULL;
|
||||
|
||||
SLObjectItf_Destroy(data->engineObject);
|
||||
data->engineObject = NULL;
|
||||
data->engine = NULL;
|
||||
|
||||
free(data);
|
||||
Device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean opensl_reset_playback(ALCdevice *Device)
|
||||
{
|
||||
osl_data *data = Device->ExtraData;
|
||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
|
||||
SLDataLocator_OutputMix loc_outmix;
|
||||
SLDataFormat_PCM format_pcm;
|
||||
SLDataSource audioSrc;
|
||||
SLDataSink audioSnk;
|
||||
SLInterfaceID id;
|
||||
SLboolean req;
|
||||
SLresult result;
|
||||
|
||||
|
||||
Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;
|
||||
Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2;
|
||||
Device->NumUpdates = 2;
|
||||
|
||||
Device->Frequency = 44100;
|
||||
Device->FmtChans = DevFmtStereo;
|
||||
Device->FmtType = DevFmtShort;
|
||||
|
||||
SetDefaultWFXChannelOrder(Device);
|
||||
|
||||
|
||||
id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
req = SL_BOOLEAN_TRUE;
|
||||
|
||||
loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
loc_bufq.numBuffers = Device->NumUpdates;
|
||||
|
||||
format_pcm.formatType = SL_DATAFORMAT_PCM;
|
||||
format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans);
|
||||
format_pcm.samplesPerSec = Device->Frequency * 1000;
|
||||
format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
|
||||
format_pcm.containerSize = format_pcm.bitsPerSample;
|
||||
format_pcm.channelMask = GetChannelMask(Device->FmtChans);
|
||||
format_pcm.endianness = SL_BYTEORDER_NATIVE;
|
||||
|
||||
audioSrc.pLocator = &loc_bufq;
|
||||
audioSrc.pFormat = &format_pcm;
|
||||
|
||||
loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
|
||||
loc_outmix.outputMix = data->outputMix;
|
||||
audioSnk.pLocator = &loc_outmix;
|
||||
audioSnk.pFormat = NULL;
|
||||
|
||||
|
||||
if(data->bufferQueueObject != NULL)
|
||||
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||
data->bufferQueueObject = NULL;
|
||||
|
||||
result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
|
||||
PRINTERR(result, "engine->CreateAudioPlayer");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);
|
||||
PRINTERR(result, "bufferQueue->Realize");
|
||||
}
|
||||
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
if(data->bufferQueueObject != NULL)
|
||||
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||
data->bufferQueueObject = NULL;
|
||||
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean opensl_start_playback(ALCdevice *Device)
|
||||
{
|
||||
osl_data *data = Device->ExtraData;
|
||||
SLAndroidSimpleBufferQueueItf bufferQueue;
|
||||
SLPlayItf player;
|
||||
SLresult result;
|
||||
ALuint i;
|
||||
|
||||
result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
|
||||
PRINTERR(result, "bufferQueue->GetInterface");
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);
|
||||
PRINTERR(result, "bufferQueue->RegisterCallback");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
|
||||
data->bufferSize = Device->UpdateSize * data->frameSize;
|
||||
data->buffer = calloc(1, data->bufferSize);
|
||||
if(!data->buffer)
|
||||
{
|
||||
result = SL_RESULT_MEMORY_FAILURE;
|
||||
PRINTERR(result, "calloc");
|
||||
}
|
||||
}
|
||||
/* enqueue the first buffer to kick off the callbacks */
|
||||
for(i = 0;i < Device->NumUpdates;i++)
|
||||
{
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize);
|
||||
PRINTERR(result, "bufferQueue->Enqueue");
|
||||
}
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player);
|
||||
PRINTERR(result, "bufferQueue->GetInterface");
|
||||
}
|
||||
if(SL_RESULT_SUCCESS == result)
|
||||
{
|
||||
result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING);
|
||||
PRINTERR(result, "player->SetPlayState");
|
||||
}
|
||||
|
||||
if(SL_RESULT_SUCCESS != result)
|
||||
{
|
||||
if(data->bufferQueueObject != NULL)
|
||||
SLObjectItf_Destroy(data->bufferQueueObject);
|
||||
data->bufferQueueObject = NULL;
|
||||
|
||||
free(data->buffer);
|
||||
data->buffer = NULL;
|
||||
data->bufferSize = 0;
|
||||
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void opensl_stop_playback(ALCdevice *Device)
|
||||
{
|
||||
osl_data *data = Device->ExtraData;
|
||||
|
||||
free(data->buffer);
|
||||
data->buffer = NULL;
|
||||
data->bufferSize = 0;
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs opensl_funcs = {
|
||||
opensl_open_playback,
|
||||
opensl_close_playback,
|
||||
opensl_reset_playback,
|
||||
opensl_start_playback,
|
||||
opensl_stop_playback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
ALCboolean alc_opensl_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = opensl_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_opensl_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_opensl_probe(enum DevProbe type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(opensl_device);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
+132
-122
@@ -47,8 +47,10 @@
|
||||
#define SOUND_MIXER_WRITE MIXER_WRITE
|
||||
#endif
|
||||
|
||||
static const ALCchar oss_device[] = "OSS Software";
|
||||
static const ALCchar oss_device_capture[] = "OSS Capture";
|
||||
static const ALCchar oss_device[] = "OSS Default";
|
||||
|
||||
static const char *oss_driver = "/dev/dsp";
|
||||
static const char *oss_capture = "/dev/dsp";
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
@@ -82,10 +84,9 @@ static ALuint OSSProc(ALvoid *ptr)
|
||||
ALint frameSize;
|
||||
ssize_t wrote;
|
||||
|
||||
EnableRTPrio(RTPrioLevel);
|
||||
SetRTPriority();
|
||||
|
||||
frameSize = aluChannelsFromFormat(pDevice->Format) *
|
||||
aluBytesFromFormat(pDevice->Format);
|
||||
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
while(!data->killNow && pDevice->Connected)
|
||||
{
|
||||
@@ -100,7 +101,7 @@ static ALuint OSSProc(ALvoid *ptr)
|
||||
{
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
ERR("write failed: %s\n", strerror(errno));
|
||||
aluHandleDisconnect(pDevice);
|
||||
break;
|
||||
}
|
||||
@@ -124,17 +125,16 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
|
||||
int frameSize;
|
||||
int amt;
|
||||
|
||||
EnableRTPrio(RTPrioLevel);
|
||||
SetRTPriority();
|
||||
|
||||
frameSize = aluBytesFromFormat(pDevice->Format);
|
||||
frameSize *= aluChannelsFromFormat(pDevice->Format);
|
||||
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
while(!data->killNow)
|
||||
{
|
||||
amt = read(data->fd, data->mix_data, data->data_size);
|
||||
if(amt < 0)
|
||||
{
|
||||
AL_PRINT("read failed: %s\n", strerror(errno));
|
||||
ERR("read failed: %s\n", strerror(errno));
|
||||
aluHandleDisconnect(pDevice);
|
||||
break;
|
||||
}
|
||||
@@ -150,33 +150,29 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
static ALCenum oss_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
char driver[64];
|
||||
oss_data *data;
|
||||
|
||||
strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1);
|
||||
driver[sizeof(driver)-1] = 0;
|
||||
if(!deviceName)
|
||||
deviceName = oss_device;
|
||||
else if(strcmp(deviceName, oss_device) != 0)
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (oss_data*)calloc(1, sizeof(oss_data));
|
||||
data->killNow = 0;
|
||||
|
||||
data->fd = open(driver, O_WRONLY);
|
||||
data->fd = open(oss_driver, O_WRONLY);
|
||||
if(data->fd == -1)
|
||||
{
|
||||
free(data);
|
||||
if(errno != ENOENT)
|
||||
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
ERR("Could not open %s: %s\n", oss_driver, strerror(errno));
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
return ALC_TRUE;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void oss_close_playback(ALCdevice *device)
|
||||
@@ -200,35 +196,29 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
||||
int ossFormat;
|
||||
int ossSpeed;
|
||||
char *err;
|
||||
int i;
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case 1:
|
||||
case DevFmtByte:
|
||||
ossFormat = AFMT_S8;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
ossFormat = AFMT_U8;
|
||||
break;
|
||||
case 4:
|
||||
switch(aluChannelsFromFormat(device->Format))
|
||||
{
|
||||
case 1: device->Format = AL_FORMAT_MONO16; break;
|
||||
case 2: device->Format = AL_FORMAT_STEREO16; break;
|
||||
case 4: device->Format = AL_FORMAT_QUAD16; break;
|
||||
case 6: device->Format = AL_FORMAT_51CHN16; break;
|
||||
case 7: device->Format = AL_FORMAT_61CHN16; break;
|
||||
case 8: device->Format = AL_FORMAT_71CHN16; break;
|
||||
}
|
||||
case DevFmtUShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtUInt:
|
||||
case DevFmtFloat:
|
||||
device->FmtType = DevFmtShort;
|
||||
/* fall-through */
|
||||
case 2:
|
||||
case DevFmtShort:
|
||||
ossFormat = AFMT_S16_NE;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
periods = device->NumUpdates;
|
||||
numChannels = aluChannelsFromFormat(device->Format);
|
||||
frameSize = numChannels * aluBytesFromFormat(device->Format);
|
||||
numChannels = ChannelsFromDevFmt(device->FmtChans);
|
||||
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
|
||||
|
||||
ossSpeed = device->Frequency;
|
||||
log2FragmentSize = log2i(device->UpdateSize * frameSize);
|
||||
@@ -241,30 +231,36 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
||||
if(periods > 2) periods--;
|
||||
numFragmentsLogSize = (periods << 16) | log2FragmentSize;
|
||||
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
#define CHECKERR(func) if((func) < 0) { \
|
||||
err = #func; \
|
||||
goto err; \
|
||||
}
|
||||
/* Don't fail if SETFRAGMENT fails. We can handle just about anything
|
||||
* that's reported back via GETOSPACE */
|
||||
ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize);
|
||||
if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels), "set channels") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info), "get space")))
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info));
|
||||
if(0)
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, strerror(errno));
|
||||
err:
|
||||
ERR("%s failed: %s\n", err, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#undef ok
|
||||
#undef CHECKERR
|
||||
|
||||
if((int)aluChannelsFromFormat(device->Format) != numChannels)
|
||||
if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
|
||||
{
|
||||
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), numChannels);
|
||||
ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(!((ossFormat == AFMT_U8 && aluBytesFromFormat(device->Format) == 1) ||
|
||||
(ossFormat == AFMT_S16_NE && aluBytesFromFormat(device->Format) == 2)))
|
||||
if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
|
||||
(ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
|
||||
(ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
|
||||
{
|
||||
AL_PRINT("Could not set %d-bit output, got format %#x\n", aluBytesFromFormat(device->Format)*8, ossFormat);
|
||||
ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
@@ -272,11 +268,18 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
||||
device->UpdateSize = info.fragsize / frameSize;
|
||||
device->NumUpdates = info.fragments + 1;
|
||||
|
||||
data->data_size = device->UpdateSize * frameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean oss_start_playback(ALCdevice *device)
|
||||
{
|
||||
oss_data *data = (oss_data*)device->ExtraData;
|
||||
|
||||
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
data->thread = StartThread(OSSProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
@@ -301,14 +304,14 @@ static void oss_stop_playback(ALCdevice *device)
|
||||
|
||||
data->killNow = 0;
|
||||
if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0)
|
||||
AL_PRINT("Error resetting device: %s\n", strerror(errno));
|
||||
ERR("Error resetting device: %s\n", strerror(errno));
|
||||
|
||||
free(data->mix_data);
|
||||
data->mix_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
static ALCenum oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
int numFragmentsLogSize;
|
||||
int log2FragmentSize;
|
||||
@@ -316,50 +319,50 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
audio_buf_info info;
|
||||
ALuint frameSize;
|
||||
int numChannels;
|
||||
char driver[64];
|
||||
oss_data *data;
|
||||
int ossFormat;
|
||||
int ossSpeed;
|
||||
char *err;
|
||||
int i;
|
||||
|
||||
strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1);
|
||||
driver[sizeof(driver)-1] = 0;
|
||||
if(!deviceName)
|
||||
deviceName = oss_device_capture;
|
||||
else if(strcmp(deviceName, oss_device_capture) != 0)
|
||||
return ALC_FALSE;
|
||||
deviceName = oss_device;
|
||||
else if(strcmp(deviceName, oss_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (oss_data*)calloc(1, sizeof(oss_data));
|
||||
data->killNow = 0;
|
||||
|
||||
data->fd = open(driver, O_RDONLY);
|
||||
data->fd = open(oss_capture, O_RDONLY);
|
||||
if(data->fd == -1)
|
||||
{
|
||||
free(data);
|
||||
if(errno != ENOENT)
|
||||
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
ERR("Could not open %s: %s\n", oss_capture, strerror(errno));
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case 1:
|
||||
case DevFmtByte:
|
||||
ossFormat = AFMT_S8;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
ossFormat = AFMT_U8;
|
||||
break;
|
||||
case 2:
|
||||
case DevFmtShort:
|
||||
ossFormat = AFMT_S16_NE;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
close(data->fd);
|
||||
case DevFmtUShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtUInt:
|
||||
case DevFmtFloat:
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
periods = 4;
|
||||
numChannels = aluChannelsFromFormat(device->Format);
|
||||
frameSize = numChannels * aluBytesFromFormat(device->Format);
|
||||
numChannels = ChannelsFromDevFmt(device->FmtChans);
|
||||
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
|
||||
ossSpeed = device->Frequency;
|
||||
log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
|
||||
frameSize / periods);
|
||||
@@ -369,44 +372,50 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
log2FragmentSize = 4;
|
||||
numFragmentsLogSize = (periods << 16) | log2FragmentSize;
|
||||
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
if (!(ok(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize), "set fragment") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat), "set format") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels), "set channels") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed), "set speed") &&
|
||||
ok(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info), "get space")))
|
||||
#define CHECKERR(func) if((func) < 0) { \
|
||||
err = #func; \
|
||||
goto err; \
|
||||
}
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed));
|
||||
CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info));
|
||||
if(0)
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, strerror(errno));
|
||||
err:
|
||||
ERR("%s failed: %s\n", err, strerror(errno));
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
#undef ok
|
||||
#undef CHECKERR
|
||||
|
||||
if((int)aluChannelsFromFormat(device->Format) != numChannels)
|
||||
if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
|
||||
{
|
||||
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), numChannels);
|
||||
ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if(!((ossFormat == AFMT_U8 && aluBytesFromFormat(device->Format) == 1) ||
|
||||
(ossFormat == AFMT_S16_NE && aluBytesFromFormat(device->Format) == 2)))
|
||||
if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
|
||||
(ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
|
||||
(ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
|
||||
{
|
||||
AL_PRINT("Could not set %d-bit input, got format %#x\n", aluBytesFromFormat(device->Format)*8, ossFormat);
|
||||
ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat);
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
data->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates);
|
||||
if(!data->ring)
|
||||
{
|
||||
AL_PRINT("ring buffer create failed\n");
|
||||
ERR("Ring buffer create failed\n");
|
||||
close(data->fd);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
data->data_size = info.fragsize;
|
||||
@@ -419,11 +428,11 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
device->ExtraData = NULL;
|
||||
free(data->mix_data);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
return ALC_TRUE;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void oss_close_capture(ALCdevice *device)
|
||||
@@ -453,13 +462,11 @@ static void oss_stop_capture(ALCdevice *pDevice)
|
||||
data->doCapture = 0;
|
||||
}
|
||||
|
||||
static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
static ALCenum oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
|
||||
ReadRingBuffer(data->ring, pBuffer, lSamples);
|
||||
else
|
||||
alcSetError(pDevice, ALC_INVALID_VALUE);
|
||||
ReadRingBuffer(data->ring, pBuffer, lSamples);
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static ALCuint oss_available_samples(ALCdevice *pDevice)
|
||||
@@ -469,10 +476,11 @@ static ALCuint oss_available_samples(ALCdevice *pDevice)
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs oss_funcs = {
|
||||
static const BackendFuncs oss_funcs = {
|
||||
oss_open_playback,
|
||||
oss_close_playback,
|
||||
oss_reset_playback,
|
||||
oss_start_playback,
|
||||
oss_stop_playback,
|
||||
oss_open_capture,
|
||||
oss_close_capture,
|
||||
@@ -482,39 +490,41 @@ BackendFuncs oss_funcs = {
|
||||
oss_available_samples
|
||||
};
|
||||
|
||||
void alc_oss_init(BackendFuncs *func_list)
|
||||
ALCboolean alc_oss_init(BackendFuncs *func_list)
|
||||
{
|
||||
ConfigValueStr("oss", "device", &oss_driver);
|
||||
ConfigValueStr("oss", "capture", &oss_capture);
|
||||
|
||||
*func_list = oss_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_oss_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_oss_probe(int type)
|
||||
void alc_oss_probe(enum DevProbe type)
|
||||
{
|
||||
if(type == DEVICE_PROBE)
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
{
|
||||
#ifdef HAVE_STAT
|
||||
struct stat buf;
|
||||
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
|
||||
struct stat buf;
|
||||
if(stat(oss_device, &buf) == 0)
|
||||
#endif
|
||||
AppendDeviceList(oss_device);
|
||||
}
|
||||
else if(type == ALL_DEVICE_PROBE)
|
||||
{
|
||||
AppendAllDeviceList(oss_device);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
{
|
||||
#ifdef HAVE_STAT
|
||||
struct stat buf;
|
||||
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
|
||||
struct stat buf;
|
||||
if(stat(oss_capture, &buf) == 0)
|
||||
#endif
|
||||
AppendAllDeviceList(oss_device);
|
||||
}
|
||||
else if(type == CAPTURE_DEVICE_PROBE)
|
||||
{
|
||||
#ifdef HAVE_STAT
|
||||
struct stat buf;
|
||||
if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0)
|
||||
#endif
|
||||
AppendCaptureDeviceList(oss_device_capture);
|
||||
AppendCaptureDeviceList(oss_device);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
|
||||
static const ALCchar pa_device[] = "PortAudio Default";
|
||||
|
||||
|
||||
#ifdef HAVE_DYNLOAD
|
||||
static void *pa_handle;
|
||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||
MAKE_FUNC(Pa_Initialize);
|
||||
MAKE_FUNC(Pa_Terminate);
|
||||
MAKE_FUNC(Pa_GetErrorText);
|
||||
MAKE_FUNC(Pa_StartStream);
|
||||
MAKE_FUNC(Pa_StopStream);
|
||||
MAKE_FUNC(Pa_OpenStream);
|
||||
MAKE_FUNC(Pa_CloseStream);
|
||||
MAKE_FUNC(Pa_GetDefaultOutputDevice);
|
||||
MAKE_FUNC(Pa_GetStreamInfo);
|
||||
#undef MAKE_FUNC
|
||||
|
||||
#define Pa_Initialize pPa_Initialize
|
||||
#define Pa_Terminate pPa_Terminate
|
||||
#define Pa_GetErrorText pPa_GetErrorText
|
||||
#define Pa_StartStream pPa_StartStream
|
||||
#define Pa_StopStream pPa_StopStream
|
||||
#define Pa_OpenStream pPa_OpenStream
|
||||
#define Pa_CloseStream pPa_CloseStream
|
||||
#define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice
|
||||
#define Pa_GetStreamInfo pPa_GetStreamInfo
|
||||
#endif
|
||||
|
||||
static ALCboolean pa_load(void)
|
||||
{
|
||||
PaError err;
|
||||
|
||||
#ifdef HAVE_DYNLOAD
|
||||
if(!pa_handle)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
# define PALIB "portaudio.dll"
|
||||
#elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define PALIB "libportaudio.2.dylib"
|
||||
#elif defined(__OpenBSD__)
|
||||
# define PALIB "libportaudio.so"
|
||||
#else
|
||||
# define PALIB "libportaudio.so.2"
|
||||
#endif
|
||||
|
||||
pa_handle = LoadLib(PALIB);
|
||||
if(!pa_handle)
|
||||
return ALC_FALSE;
|
||||
|
||||
#define LOAD_FUNC(f) do { \
|
||||
p##f = GetSymbol(pa_handle, #f); \
|
||||
if(p##f == NULL) \
|
||||
{ \
|
||||
CloseLib(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
return ALC_FALSE; \
|
||||
} \
|
||||
} while(0)
|
||||
LOAD_FUNC(Pa_Initialize);
|
||||
LOAD_FUNC(Pa_Terminate);
|
||||
LOAD_FUNC(Pa_GetErrorText);
|
||||
LOAD_FUNC(Pa_StartStream);
|
||||
LOAD_FUNC(Pa_StopStream);
|
||||
LOAD_FUNC(Pa_OpenStream);
|
||||
LOAD_FUNC(Pa_CloseStream);
|
||||
LOAD_FUNC(Pa_GetDefaultOutputDevice);
|
||||
LOAD_FUNC(Pa_GetStreamInfo);
|
||||
#undef LOAD_FUNC
|
||||
|
||||
if((err=Pa_Initialize()) != paNoError)
|
||||
{
|
||||
ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
|
||||
CloseLib(pa_handle);
|
||||
pa_handle = NULL;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if((err=Pa_Initialize()) != paNoError)
|
||||
{
|
||||
ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#endif
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
PaStream *stream;
|
||||
PaStreamParameters params;
|
||||
ALuint update_size;
|
||||
|
||||
RingBuffer *ring;
|
||||
} pa_data;
|
||||
|
||||
|
||||
static int pa_callback(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
|
||||
const PaStreamCallbackFlags statusFlags, void *userData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)userData;
|
||||
|
||||
(void)inputBuffer;
|
||||
(void)timeInfo;
|
||||
(void)statusFlags;
|
||||
|
||||
aluMixData(device, outputBuffer, framesPerBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pa_capture_cb(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
|
||||
const PaStreamCallbackFlags statusFlags, void *userData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)userData;
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
|
||||
(void)outputBuffer;
|
||||
(void)timeInfo;
|
||||
(void)statusFlags;
|
||||
|
||||
WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
pa_data *data;
|
||||
PaError err;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = pa_device;
|
||||
else if(strcmp(deviceName, pa_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (pa_data*)calloc(1, sizeof(pa_data));
|
||||
data->update_size = device->UpdateSize;
|
||||
|
||||
data->params.device = -1;
|
||||
if(!ConfigValueInt("port", "device", &data->params.device) ||
|
||||
data->params.device < 0)
|
||||
data->params.device = Pa_GetDefaultOutputDevice();
|
||||
data->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
|
||||
(float)device->Frequency;
|
||||
data->params.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
data->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
|
||||
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtByte:
|
||||
data->params.sampleFormat = paInt8;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
data->params.sampleFormat = paUInt8;
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
/* fall-through */
|
||||
case DevFmtShort:
|
||||
data->params.sampleFormat = paInt16;
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
/* fall-through */
|
||||
case DevFmtInt:
|
||||
data->params.sampleFormat = paInt32;
|
||||
break;
|
||||
case DevFmtFloat:
|
||||
data->params.sampleFormat = paFloat32;
|
||||
break;
|
||||
}
|
||||
|
||||
retry_open:
|
||||
err = Pa_OpenStream(&data->stream, NULL, &data->params, device->Frequency,
|
||||
device->UpdateSize, paNoFlag, pa_callback, device);
|
||||
if(err != paNoError)
|
||||
{
|
||||
if(data->params.sampleFormat == paFloat32)
|
||||
{
|
||||
data->params.sampleFormat = paInt16;
|
||||
goto retry_open;
|
||||
}
|
||||
ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
|
||||
free(data);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->ExtraData = data;
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void pa_close_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_CloseStream(data->stream);
|
||||
if(err != paNoError)
|
||||
ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean pa_reset_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
const PaStreamInfo *streamInfo;
|
||||
|
||||
streamInfo = Pa_GetStreamInfo(data->stream);
|
||||
device->Frequency = streamInfo->sampleRate;
|
||||
device->UpdateSize = data->update_size;
|
||||
|
||||
if(data->params.sampleFormat == paInt8)
|
||||
device->FmtType = DevFmtByte;
|
||||
else if(data->params.sampleFormat == paUInt8)
|
||||
device->FmtType = DevFmtUByte;
|
||||
else if(data->params.sampleFormat == paInt16)
|
||||
device->FmtType = DevFmtShort;
|
||||
else if(data->params.sampleFormat == paInt32)
|
||||
device->FmtType = DevFmtInt;
|
||||
else if(data->params.sampleFormat == paFloat32)
|
||||
device->FmtType = DevFmtFloat;
|
||||
else
|
||||
{
|
||||
ERR("Unexpected sample format: 0x%lx\n", data->params.sampleFormat);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(data->params.channelCount == 2)
|
||||
device->FmtChans = DevFmtStereo;
|
||||
else if(data->params.channelCount == 1)
|
||||
device->FmtChans = DevFmtMono;
|
||||
else
|
||||
{
|
||||
ERR("Unexpected channel count: %u\n", data->params.channelCount);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean pa_start_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_StartStream(data->stream);
|
||||
if(err != paNoError)
|
||||
{
|
||||
ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void pa_stop_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_StopStream(data->stream);
|
||||
if(err != paNoError)
|
||||
ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
|
||||
}
|
||||
|
||||
|
||||
static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
ALuint frame_size;
|
||||
pa_data *data;
|
||||
PaError err;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = pa_device;
|
||||
else if(strcmp(deviceName, pa_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (pa_data*)calloc(1, sizeof(pa_data));
|
||||
if(data == NULL)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
|
||||
frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
|
||||
if(data->ring == NULL)
|
||||
goto error;
|
||||
|
||||
data->params.device = -1;
|
||||
if(!ConfigValueInt("port", "capture", &data->params.device) ||
|
||||
data->params.device < 0)
|
||||
data->params.device = Pa_GetDefaultOutputDevice();
|
||||
data->params.suggestedLatency = 0.0f;
|
||||
data->params.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtByte:
|
||||
data->params.sampleFormat = paInt8;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
data->params.sampleFormat = paUInt8;
|
||||
break;
|
||||
case DevFmtShort:
|
||||
data->params.sampleFormat = paInt16;
|
||||
break;
|
||||
case DevFmtInt:
|
||||
data->params.sampleFormat = paInt32;
|
||||
break;
|
||||
case DevFmtFloat:
|
||||
data->params.sampleFormat = paFloat32;
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
case DevFmtUShort:
|
||||
ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
|
||||
goto error;
|
||||
}
|
||||
data->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
|
||||
|
||||
err = Pa_OpenStream(&data->stream, &data->params, NULL, device->Frequency,
|
||||
paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
|
||||
if(err != paNoError)
|
||||
{
|
||||
ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
|
||||
goto error;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
|
||||
device->ExtraData = data;
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
error:
|
||||
DestroyRingBuffer(data->ring);
|
||||
free(data);
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void pa_close_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_CloseStream(data->stream);
|
||||
if(err != paNoError)
|
||||
ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void pa_start_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_StartStream(data->stream);
|
||||
if(err != paNoError)
|
||||
ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
|
||||
}
|
||||
|
||||
static void pa_stop_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = Pa_StopStream(data->stream);
|
||||
if(err != paNoError)
|
||||
ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
|
||||
}
|
||||
|
||||
static ALCenum pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
ReadRingBuffer(data->ring, buffer, samples);
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static ALCuint pa_available_samples(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
return RingBufferSize(data->ring);
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs pa_funcs = {
|
||||
pa_open_playback,
|
||||
pa_close_playback,
|
||||
pa_reset_playback,
|
||||
pa_start_playback,
|
||||
pa_stop_playback,
|
||||
pa_open_capture,
|
||||
pa_close_capture,
|
||||
pa_start_capture,
|
||||
pa_stop_capture,
|
||||
pa_capture_samples,
|
||||
pa_available_samples
|
||||
};
|
||||
|
||||
ALCboolean alc_pa_init(BackendFuncs *func_list)
|
||||
{
|
||||
if(!pa_load())
|
||||
return ALC_FALSE;
|
||||
*func_list = pa_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_pa_deinit(void)
|
||||
{
|
||||
#ifdef HAVE_DYNLOAD
|
||||
if(pa_handle)
|
||||
{
|
||||
Pa_Terminate();
|
||||
CloseLib(pa_handle);
|
||||
pa_handle = NULL;
|
||||
}
|
||||
#else
|
||||
Pa_Terminate();
|
||||
#endif
|
||||
}
|
||||
|
||||
void alc_pa_probe(enum DevProbe type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(pa_device);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
AppendCaptureDeviceList(pa_device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,372 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#include <sndio.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct sio_hdl *sndHandle;
|
||||
|
||||
ALvoid *mix_data;
|
||||
ALsizei data_size;
|
||||
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} sndio_data;
|
||||
|
||||
|
||||
static ALuint sndio_proc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *device = ptr;
|
||||
sndio_data *data = device->ExtraData;
|
||||
ALsizei frameSize;
|
||||
size_t wrote;
|
||||
|
||||
SetRTPriority();
|
||||
|
||||
frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
|
||||
while(!data->killNow && device->Connected)
|
||||
{
|
||||
ALsizei len = data->data_size;
|
||||
ALubyte *WritePtr = data->mix_data;
|
||||
|
||||
aluMixData(device, WritePtr, len/frameSize);
|
||||
while(len > 0 && !data->killNow)
|
||||
{
|
||||
wrote = sio_write(data->sndHandle, WritePtr, len);
|
||||
if(wrote == 0)
|
||||
{
|
||||
ERR("sio_write failed\n");
|
||||
aluHandleDisconnect(device);
|
||||
break;
|
||||
}
|
||||
|
||||
len -= wrote;
|
||||
WritePtr += wrote;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
sndio_data *data;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = sndio_device;
|
||||
else if(strcmp(deviceName, sndio_device) != 0)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = calloc(1, sizeof(*data));
|
||||
data->killNow = 0;
|
||||
|
||||
data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
|
||||
if(data->sndHandle == NULL)
|
||||
{
|
||||
free(data);
|
||||
ERR("Could not open device\n");
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void sndio_close_playback(ALCdevice *device)
|
||||
{
|
||||
sndio_data *data = device->ExtraData;
|
||||
|
||||
sio_close(data->sndHandle);
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean sndio_reset_playback(ALCdevice *device)
|
||||
{
|
||||
sndio_data *data = device->ExtraData;
|
||||
struct sio_par par;
|
||||
|
||||
sio_initpar(&par);
|
||||
|
||||
par.rate = device->Frequency;
|
||||
par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
|
||||
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case DevFmtByte:
|
||||
par.bits = 8;
|
||||
par.sig = 1;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
par.bits = 8;
|
||||
par.sig = 0;
|
||||
break;
|
||||
case DevFmtFloat:
|
||||
case DevFmtShort:
|
||||
par.bits = 16;
|
||||
par.sig = 1;
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
par.bits = 16;
|
||||
par.sig = 0;
|
||||
break;
|
||||
case DevFmtInt:
|
||||
par.bits = 32;
|
||||
par.sig = 1;
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
par.bits = 32;
|
||||
par.sig = 0;
|
||||
break;
|
||||
}
|
||||
par.le = SIO_LE_NATIVE;
|
||||
|
||||
par.round = device->UpdateSize;
|
||||
par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
|
||||
if(!par.appbufsz) par.appbufsz = device->UpdateSize;
|
||||
|
||||
if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
|
||||
{
|
||||
ERR("Failed to set device parameters\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(par.bits != par.bps*8)
|
||||
{
|
||||
ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->Frequency = par.rate;
|
||||
device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
|
||||
|
||||
if(par.bits == 8 && par.sig == 1)
|
||||
device->FmtType = DevFmtByte;
|
||||
else if(par.bits == 8 && par.sig == 0)
|
||||
device->FmtType = DevFmtUByte;
|
||||
else if(par.bits == 16 && par.sig == 1)
|
||||
device->FmtType = DevFmtShort;
|
||||
else if(par.bits == 16 && par.sig == 0)
|
||||
device->FmtType = DevFmtUShort;
|
||||
else if(par.bits == 32 && par.sig == 1)
|
||||
device->FmtType = DevFmtInt;
|
||||
else if(par.bits == 32 && par.sig == 0)
|
||||
device->FmtType = DevFmtUInt;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateSize = par.round;
|
||||
device->NumUpdates = (par.bufsz/par.round) + 1;
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean sndio_start_playback(ALCdevice *device)
|
||||
{
|
||||
sndio_data *data = device->ExtraData;
|
||||
|
||||
if(!sio_start(data->sndHandle))
|
||||
{
|
||||
ERR("Error starting playback\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
data->thread = StartThread(sndio_proc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
sio_stop(data->sndHandle);
|
||||
free(data->mix_data);
|
||||
data->mix_data = NULL;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void sndio_stop_playback(ALCdevice *device)
|
||||
{
|
||||
sndio_data *data = device->ExtraData;
|
||||
|
||||
if(!data->thread)
|
||||
return;
|
||||
|
||||
data->killNow = 1;
|
||||
StopThread(data->thread);
|
||||
data->thread = NULL;
|
||||
|
||||
data->killNow = 0;
|
||||
if(!sio_stop(data->sndHandle))
|
||||
ERR("Error stopping device\n");
|
||||
|
||||
free(data->mix_data);
|
||||
data->mix_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs sndio_funcs = {
|
||||
sndio_open_playback,
|
||||
sndio_close_playback,
|
||||
sndio_reset_playback,
|
||||
sndio_start_playback,
|
||||
sndio_stop_playback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
ALCboolean alc_sndio_init(BackendFuncs *func_list)
|
||||
{
|
||||
if(!sndio_load())
|
||||
return ALC_FALSE;
|
||||
*func_list = sndio_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(sndio_device);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,9 @@
|
||||
#include <sys/audioio.h>
|
||||
|
||||
|
||||
static const ALCchar solaris_device[] = "Solaris Software";
|
||||
static const ALCchar solaris_device[] = "Solaris Default";
|
||||
|
||||
static const char *solaris_driver = "/dev/audio";
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
@@ -53,14 +55,12 @@ static ALuint SolarisProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
solaris_data *data = (solaris_data*)pDevice->ExtraData;
|
||||
int remaining = 0;
|
||||
ALint frameSize;
|
||||
int wrote;
|
||||
|
||||
EnableRTPrio(RTPrioLevel);
|
||||
SetRTPriority();
|
||||
|
||||
frameSize = aluChannelsFromFormat(pDevice->Format) *
|
||||
aluBytesFromFormat(pDevice->Format);
|
||||
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
while(!data->killNow && pDevice->Connected)
|
||||
{
|
||||
@@ -75,7 +75,7 @@ static ALuint SolarisProc(ALvoid *ptr)
|
||||
{
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
ERR("write failed: %s\n", strerror(errno));
|
||||
aluHandleDisconnect(pDevice);
|
||||
break;
|
||||
}
|
||||
@@ -93,33 +93,29 @@ static ALuint SolarisProc(ALvoid *ptr)
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
char driver[64];
|
||||
solaris_data *data;
|
||||
|
||||
strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1);
|
||||
driver[sizeof(driver)-1] = 0;
|
||||
if(!deviceName)
|
||||
deviceName = solaris_device;
|
||||
else if(strcmp(deviceName, solaris_device) != 0)
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (solaris_data*)calloc(1, sizeof(solaris_data));
|
||||
data->killNow = 0;
|
||||
|
||||
data->fd = open(driver, O_WRONLY);
|
||||
data->fd = open(solaris_driver, O_WRONLY);
|
||||
if(data->fd == -1)
|
||||
{
|
||||
free(data);
|
||||
if(errno != ENOENT)
|
||||
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
return ALC_TRUE;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void solaris_close_playback(ALCdevice *device)
|
||||
@@ -140,66 +136,75 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
info.play.sample_rate = device->Frequency;
|
||||
|
||||
if(device->FmtChans != DevFmtMono)
|
||||
device->FmtChans = DevFmtStereo;
|
||||
numChannels = ChannelsFromDevFmt(device->FmtChans);
|
||||
info.play.channels = numChannels;
|
||||
|
||||
switch(device->FmtType)
|
||||
{
|
||||
case 1:
|
||||
case DevFmtByte:
|
||||
info.play.precision = 8;
|
||||
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
info.play.precision = 8;
|
||||
info.play.encoding = AUDIO_ENCODING_LINEAR8;
|
||||
break;
|
||||
case 4:
|
||||
switch(numChannels)
|
||||
{
|
||||
case 1: device->Format = AL_FORMAT_MONO16; break;
|
||||
case 2: device->Format = AL_FORMAT_STEREO16; break;
|
||||
case 4: device->Format = AL_FORMAT_QUAD16; break;
|
||||
case 6: device->Format = AL_FORMAT_51CHN16; break;
|
||||
case 7: device->Format = AL_FORMAT_61CHN16; break;
|
||||
case 8: device->Format = AL_FORMAT_71CHN16; break;
|
||||
}
|
||||
case DevFmtUShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtUInt:
|
||||
case DevFmtFloat:
|
||||
device->FmtType = DevFmtShort;
|
||||
/* fall-through */
|
||||
case 2:
|
||||
case DevFmtShort:
|
||||
info.play.precision = 16;
|
||||
info.play.encoding = AUDIO_ENCODING_LINEAR;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
numChannels = aluChannelsFromFormat(device->Format);
|
||||
info.play.sample_rate = device->Frequency;
|
||||
info.play.channels = numChannels;
|
||||
|
||||
frameSize = numChannels * aluBytesFromFormat(device->Format);
|
||||
frameSize = numChannels * BytesFromDevFmt(device->FmtType);
|
||||
info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
|
||||
|
||||
if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0)
|
||||
{
|
||||
AL_PRINT("ioctl failed: %s\n", strerror(errno));
|
||||
ERR("ioctl failed: %s\n", strerror(errno));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(aluChannelsFromFormat(device->Format) != info.play.channels)
|
||||
if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels)
|
||||
{
|
||||
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), info.play.channels);
|
||||
ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(!((info.play.precision == 8 && aluBytesFromFormat(device->Format) == 1) ||
|
||||
(info.play.precision == 16 && aluBytesFromFormat(device->Format) == 2)))
|
||||
if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) ||
|
||||
(info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) ||
|
||||
(info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) ||
|
||||
(info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt)))
|
||||
{
|
||||
AL_PRINT("Could not set %d-bit output, got %d\n", aluBytesFromFormat(device->Format)*8, info.play.precision);
|
||||
ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType),
|
||||
info.play.precision, info.play.encoding);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->Frequency = info.play.sample_rate;
|
||||
device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
|
||||
|
||||
data->data_size = device->UpdateSize * frameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean solaris_start_playback(ALCdevice *device)
|
||||
{
|
||||
solaris_data *data = (solaris_data*)device->ExtraData;
|
||||
|
||||
data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
data->thread = StartThread(SolarisProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
@@ -223,83 +228,55 @@ static void solaris_stop_playback(ALCdevice *device)
|
||||
data->thread = NULL;
|
||||
|
||||
data->killNow = 0;
|
||||
if(ioctl(data->fd, AUDIO_DRAIN) < 0)
|
||||
ERR("Error draining device: %s\n", strerror(errno));
|
||||
|
||||
free(data->mix_data);
|
||||
data->mix_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean solaris_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
|
||||
{
|
||||
(void)device;
|
||||
(void)deviceName;
|
||||
(void)frequency;
|
||||
(void)format;
|
||||
(void)SampleSize;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void solaris_close_capture(ALCdevice *device)
|
||||
{
|
||||
(void)device;
|
||||
}
|
||||
|
||||
static void solaris_start_capture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void solaris_stop_capture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void solaris_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)pBuffer;
|
||||
(void)lSamples;
|
||||
}
|
||||
|
||||
static ALCuint solaris_available_samples(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs solaris_funcs = {
|
||||
static const BackendFuncs solaris_funcs = {
|
||||
solaris_open_playback,
|
||||
solaris_close_playback,
|
||||
solaris_reset_playback,
|
||||
solaris_start_playback,
|
||||
solaris_stop_playback,
|
||||
solaris_open_capture,
|
||||
solaris_close_capture,
|
||||
solaris_start_capture,
|
||||
solaris_stop_capture,
|
||||
solaris_capture_samples,
|
||||
solaris_available_samples
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
void alc_solaris_init(BackendFuncs *func_list)
|
||||
ALCboolean alc_solaris_init(BackendFuncs *func_list)
|
||||
{
|
||||
ConfigValueStr("solaris", "device", &solaris_driver);
|
||||
|
||||
*func_list = solaris_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_solaris_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_solaris_probe(int type)
|
||||
void alc_solaris_probe(enum DevProbe type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
{
|
||||
#ifdef HAVE_STAT
|
||||
struct stat buf;
|
||||
if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0)
|
||||
return;
|
||||
struct stat buf;
|
||||
if(stat(solaris_driver, &buf) == 0)
|
||||
#endif
|
||||
AppendAllDeviceList(solaris_device);
|
||||
}
|
||||
break;
|
||||
|
||||
if(type == DEVICE_PROBE)
|
||||
AppendDeviceList(solaris_device);
|
||||
else if(type == ALL_DEVICE_PROBE)
|
||||
AppendAllDeviceList(solaris_device);
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
+107
-119
@@ -63,55 +63,77 @@ static const ALuint channel_masks[] = {
|
||||
0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */
|
||||
};
|
||||
|
||||
|
||||
static void fwrite16le(ALushort val, FILE *f)
|
||||
{
|
||||
fputc(val&0xff, f);
|
||||
fputc((val>>8)&0xff, f);
|
||||
}
|
||||
|
||||
static void fwrite32le(ALuint val, FILE *f)
|
||||
{
|
||||
fputc(val&0xff, f);
|
||||
fputc((val>>8)&0xff, f);
|
||||
fputc((val>>16)&0xff, f);
|
||||
fputc((val>>24)&0xff, f);
|
||||
}
|
||||
|
||||
|
||||
static ALuint WaveProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
wave_data *data = (wave_data*)pDevice->ExtraData;
|
||||
ALuint frameSize;
|
||||
ALuint now, last;
|
||||
ALuint now, start;
|
||||
ALuint64 avail, done;
|
||||
size_t fs;
|
||||
ALuint avail;
|
||||
union {
|
||||
short s;
|
||||
char b[sizeof(short)];
|
||||
} uSB;
|
||||
const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 /
|
||||
pDevice->Frequency / 2;
|
||||
|
||||
uSB.s = 1;
|
||||
frameSize = aluBytesFromFormat(pDevice->Format) *
|
||||
aluChannelsFromFormat(pDevice->Format);
|
||||
frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
last = timeGetTime()<<8;
|
||||
done = 0;
|
||||
start = timeGetTime();
|
||||
while(!data->killNow && pDevice->Connected)
|
||||
{
|
||||
now = timeGetTime()<<8;
|
||||
now = timeGetTime();
|
||||
|
||||
avail = (ALuint64)(now-last) * pDevice->Frequency / (1000<<8);
|
||||
if(avail < pDevice->UpdateSize)
|
||||
avail = (ALuint64)(now-start) * pDevice->Frequency / 1000;
|
||||
if(avail < done)
|
||||
{
|
||||
Sleep(1);
|
||||
/* 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;
|
||||
done = 0;
|
||||
}
|
||||
if(avail-done < pDevice->UpdateSize)
|
||||
{
|
||||
Sleep(restTime);
|
||||
continue;
|
||||
}
|
||||
|
||||
while(avail >= pDevice->UpdateSize)
|
||||
while(avail-done >= pDevice->UpdateSize)
|
||||
{
|
||||
aluMixData(pDevice, data->buffer, pDevice->UpdateSize);
|
||||
done += pDevice->UpdateSize;
|
||||
|
||||
if(uSB.b[0] != 1)
|
||||
if(!IS_LITTLE_ENDIAN)
|
||||
{
|
||||
ALuint bytesize = BytesFromDevFmt(pDevice->FmtType);
|
||||
ALubyte *bytes = data->buffer;
|
||||
ALuint i;
|
||||
|
||||
if(aluBytesFromFormat(pDevice->Format) == 1)
|
||||
if(bytesize == 1)
|
||||
{
|
||||
for(i = 0;i < data->size;i++)
|
||||
fputc(bytes[i], data->f);
|
||||
}
|
||||
else if(aluBytesFromFormat(pDevice->Format) == 2)
|
||||
else if(bytesize == 2)
|
||||
{
|
||||
for(i = 0;i < data->size;i++)
|
||||
fputc(bytes[i^1], data->f);
|
||||
}
|
||||
else if(aluBytesFromFormat(pDevice->Format) == 4)
|
||||
else if(bytesize == 4)
|
||||
{
|
||||
for(i = 0;i < data->size;i++)
|
||||
fputc(bytes[i^3], data->f);
|
||||
@@ -122,32 +144,29 @@ static ALuint WaveProc(ALvoid *ptr)
|
||||
data->f);
|
||||
if(ferror(data->f))
|
||||
{
|
||||
AL_PRINT("Error writing to file\n");
|
||||
ERR("Error writing to file\n");
|
||||
aluHandleDisconnect(pDevice);
|
||||
break;
|
||||
}
|
||||
|
||||
avail -= pDevice->UpdateSize;
|
||||
last += (ALuint64)pDevice->UpdateSize * (1000<<8) / pDevice->Frequency;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
wave_data *data;
|
||||
const char *fname;
|
||||
|
||||
fname = GetConfigValue("wave", "file", "");
|
||||
if(!fname[0])
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = waveDevice;
|
||||
else if(strcmp(deviceName, waveDevice) != 0)
|
||||
return ALC_FALSE;
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
data = (wave_data*)calloc(1, sizeof(wave_data));
|
||||
|
||||
@@ -155,13 +174,13 @@ static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceNam
|
||||
if(!data->f)
|
||||
{
|
||||
free(data);
|
||||
AL_PRINT("Could not open file '%s': %s\n", fname, strerror(errno));
|
||||
return ALC_FALSE;
|
||||
ERR("Could not open file '%s': %s\n", fname, strerror(errno));
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = data;
|
||||
return ALC_TRUE;
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static void wave_close_playback(ALCdevice *device)
|
||||
@@ -176,106 +195,88 @@ static void wave_close_playback(ALCdevice *device)
|
||||
static ALCboolean wave_reset_playback(ALCdevice *device)
|
||||
{
|
||||
wave_data *data = (wave_data*)device->ExtraData;
|
||||
ALuint channels, bits, i;
|
||||
ALuint channels=0, bits=0;
|
||||
size_t val;
|
||||
|
||||
fseek(data->f, 0, SEEK_SET);
|
||||
clearerr(data->f);
|
||||
|
||||
bits = aluBytesFromFormat(device->Format) * 8;
|
||||
channels = aluChannelsFromFormat(device->Format);
|
||||
|
||||
/* 7.1 max */
|
||||
if(channels > 8)
|
||||
switch(device->FmtType)
|
||||
{
|
||||
if(bits == 8)
|
||||
device->Format = AL_FORMAT_71CHN8;
|
||||
else if(bits == 16)
|
||||
device->Format = AL_FORMAT_71CHN16;
|
||||
else
|
||||
{
|
||||
device->Format = AL_FORMAT_71CHN32;
|
||||
bits = 32;
|
||||
}
|
||||
channels = 8;
|
||||
case DevFmtByte:
|
||||
device->FmtType = DevFmtUByte;
|
||||
break;
|
||||
case DevFmtUShort:
|
||||
device->FmtType = DevFmtShort;
|
||||
break;
|
||||
case DevFmtUInt:
|
||||
device->FmtType = DevFmtInt;
|
||||
break;
|
||||
case DevFmtUByte:
|
||||
case DevFmtShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtFloat:
|
||||
break;
|
||||
}
|
||||
bits = BytesFromDevFmt(device->FmtType) * 8;
|
||||
channels = ChannelsFromDevFmt(device->FmtChans);
|
||||
|
||||
fprintf(data->f, "RIFF");
|
||||
fputc(0xFF, data->f); // 'RIFF' header len; filled in at close
|
||||
fputc(0xFF, data->f);
|
||||
fputc(0xFF, data->f);
|
||||
fputc(0xFF, data->f);
|
||||
fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close
|
||||
|
||||
fprintf(data->f, "WAVE");
|
||||
|
||||
fprintf(data->f, "fmt ");
|
||||
fputc(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE
|
||||
fputc(0, data->f);
|
||||
fputc(0, data->f);
|
||||
fputc(0, data->f);
|
||||
fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE
|
||||
|
||||
// 16-bit val, format type id (extensible: 0xFFFE)
|
||||
fputc(0xFE, data->f);
|
||||
fputc(0xFF, data->f);
|
||||
fwrite16le(0xFFFE, data->f);
|
||||
// 16-bit val, channel count
|
||||
fputc(channels&0xff, data->f);
|
||||
fputc((channels>>8)&0xff, data->f);
|
||||
fwrite16le(channels, data->f);
|
||||
// 32-bit val, frequency
|
||||
fputc(device->Frequency&0xff, data->f);
|
||||
fputc((device->Frequency>>8)&0xff, data->f);
|
||||
fputc((device->Frequency>>16)&0xff, data->f);
|
||||
fputc((device->Frequency>>24)&0xff, data->f);
|
||||
fwrite32le(device->Frequency, data->f);
|
||||
// 32-bit val, bytes per second
|
||||
i = device->Frequency * channels * bits / 8;
|
||||
fputc(i&0xff, data->f);
|
||||
fputc((i>>8)&0xff, data->f);
|
||||
fputc((i>>16)&0xff, data->f);
|
||||
fputc((i>>24)&0xff, data->f);
|
||||
fwrite32le(device->Frequency * channels * bits / 8, data->f);
|
||||
// 16-bit val, frame size
|
||||
i = channels * bits / 8;
|
||||
fputc(i&0xff, data->f);
|
||||
fputc((i>>8)&0xff, data->f);
|
||||
fwrite16le(channels * bits / 8, data->f);
|
||||
// 16-bit val, bits per sample
|
||||
fputc(bits&0xff, data->f);
|
||||
fputc((bits>>8)&0xff, data->f);
|
||||
fwrite16le(bits, data->f);
|
||||
// 16-bit val, extra byte count
|
||||
fputc(22, data->f);
|
||||
fputc(0, data->f);
|
||||
fwrite16le(22, data->f);
|
||||
// 16-bit val, valid bits per sample
|
||||
fputc(bits&0xff, data->f);
|
||||
fputc((bits>>8)&0xff, data->f);
|
||||
fwrite16le(bits, data->f);
|
||||
// 32-bit val, channel mask
|
||||
i = channel_masks[channels];
|
||||
fputc(i&0xff, data->f);
|
||||
fputc((i>>8)&0xff, data->f);
|
||||
fputc((i>>16)&0xff, data->f);
|
||||
fputc((i>>24)&0xff, data->f);
|
||||
fwrite32le(channel_masks[channels], data->f);
|
||||
// 16 byte GUID, sub-type format
|
||||
val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f);
|
||||
|
||||
fprintf(data->f, "data");
|
||||
fputc(0xFF, data->f); // 'data' header len; filled in at close
|
||||
fputc(0xFF, data->f);
|
||||
fputc(0xFF, data->f);
|
||||
fputc(0xFF, data->f);
|
||||
fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close
|
||||
|
||||
if(ferror(data->f))
|
||||
{
|
||||
AL_PRINT("Error writing header: %s\n", strerror(errno));
|
||||
ERR("Error writing header: %s\n", strerror(errno));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
data->DataStart = ftell(data->f);
|
||||
|
||||
data->size = device->UpdateSize * channels * bits / 8;
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean wave_start_playback(ALCdevice *device)
|
||||
{
|
||||
wave_data *data = (wave_data*)device->ExtraData;
|
||||
|
||||
data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
data->buffer = malloc(data->size);
|
||||
if(!data->buffer)
|
||||
{
|
||||
AL_PRINT("buffer malloc failed\n");
|
||||
ERR("Buffer malloc failed\n");
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
data->thread = StartThread(WaveProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
@@ -310,38 +311,20 @@ static void wave_stop_playback(ALCdevice *device)
|
||||
{
|
||||
dataLen = size - data->DataStart;
|
||||
if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0)
|
||||
{
|
||||
fputc(dataLen&0xff, data->f); // 'data' header len
|
||||
fputc((dataLen>>8)&0xff, data->f);
|
||||
fputc((dataLen>>16)&0xff, data->f);
|
||||
fputc((dataLen>>24)&0xff, data->f);
|
||||
}
|
||||
fwrite32le(dataLen, data->f); // 'data' header len
|
||||
if(fseek(data->f, 4, SEEK_SET) == 0)
|
||||
{
|
||||
size -= 8;
|
||||
fputc(size&0xff, data->f); // 'WAVE' header len
|
||||
fputc((size>>8)&0xff, data->f);
|
||||
fputc((size>>16)&0xff, data->f);
|
||||
fputc((size>>24)&0xff, data->f);
|
||||
}
|
||||
fwrite32le(size-8, data->f); // 'WAVE' header len
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)deviceName;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs wave_funcs = {
|
||||
static const BackendFuncs wave_funcs = {
|
||||
wave_open_playback,
|
||||
wave_close_playback,
|
||||
wave_reset_playback,
|
||||
wave_start_playback,
|
||||
wave_stop_playback,
|
||||
wave_open_capture,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -349,22 +332,27 @@ BackendFuncs wave_funcs = {
|
||||
NULL
|
||||
};
|
||||
|
||||
void alc_wave_init(BackendFuncs *func_list)
|
||||
ALCboolean alc_wave_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = wave_funcs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alc_wave_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_wave_probe(int type)
|
||||
void alc_wave_probe(enum DevProbe type)
|
||||
{
|
||||
if(!ConfigValueExists("wave", "file"))
|
||||
return;
|
||||
|
||||
if(type == DEVICE_PROBE)
|
||||
AppendDeviceList(waveDevice);
|
||||
else if(type == ALL_DEVICE_PROBE)
|
||||
AppendAllDeviceList(waveDevice);
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
AppendAllDeviceList(waveDevice);
|
||||
break;
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,777 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#ifndef WAVE_FORMAT_IEEE_FLOAT
|
||||
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
// MMSYSTEM Device
|
||||
volatile ALboolean bWaveShutdown;
|
||||
HANDLE hWaveThreadEvent;
|
||||
HANDLE hWaveThread;
|
||||
DWORD ulWaveThreadID;
|
||||
volatile LONG lWaveBuffersCommitted;
|
||||
WAVEHDR WaveBuffer[4];
|
||||
|
||||
union {
|
||||
HWAVEIN In;
|
||||
HWAVEOUT Out;
|
||||
} hWaveHandle;
|
||||
|
||||
WAVEFORMATEX wfexFormat;
|
||||
|
||||
RingBuffer *pRing;
|
||||
} WinMMData;
|
||||
|
||||
|
||||
static ALCchar **PlaybackDeviceList;
|
||||
static ALuint NumPlaybackDevices;
|
||||
static ALCchar **CaptureDeviceList;
|
||||
static ALuint NumCaptureDevices;
|
||||
|
||||
|
||||
static void ProbePlaybackDevices(void)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
free(PlaybackDeviceList[i]);
|
||||
|
||||
NumPlaybackDevices = waveOutGetNumDevs();
|
||||
PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices);
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
WAVEOUTCAPS WaveCaps;
|
||||
|
||||
PlaybackDeviceList[i] = NULL;
|
||||
if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
|
||||
{
|
||||
char name[1024];
|
||||
ALuint count, j;
|
||||
|
||||
count = 0;
|
||||
do {
|
||||
if(count == 0)
|
||||
snprintf(name, sizeof(name), "%s", WaveCaps.szPname);
|
||||
else
|
||||
snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1);
|
||||
count++;
|
||||
|
||||
for(j = 0;j < i;j++)
|
||||
{
|
||||
if(strcmp(name, PlaybackDeviceList[j]) == 0)
|
||||
break;
|
||||
}
|
||||
} while(j != i);
|
||||
|
||||
PlaybackDeviceList[i] = strdup(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ProbeCaptureDevices(void)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
free(CaptureDeviceList[i]);
|
||||
|
||||
NumCaptureDevices = waveInGetNumDevs();
|
||||
CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
WAVEINCAPS WaveInCaps;
|
||||
|
||||
CaptureDeviceList[i] = NULL;
|
||||
if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
|
||||
{
|
||||
char name[1024];
|
||||
ALuint count, j;
|
||||
|
||||
count = 0;
|
||||
do {
|
||||
if(count == 0)
|
||||
snprintf(name, sizeof(name), "%s", WaveInCaps.szPname);
|
||||
else
|
||||
snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1);
|
||||
count++;
|
||||
|
||||
for(j = 0;j < i;j++)
|
||||
{
|
||||
if(strcmp(name, CaptureDeviceList[j]) == 0)
|
||||
break;
|
||||
}
|
||||
} while(j != i);
|
||||
|
||||
CaptureDeviceList[i] = strdup(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
WaveOutProc
|
||||
|
||||
Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
|
||||
returns to the application (for more data)
|
||||
*/
|
||||
static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)dwInstance;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
|
||||
(void)hDevice;
|
||||
(void)dwParam2;
|
||||
|
||||
if(uMsg != WOM_DONE)
|
||||
return;
|
||||
|
||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||
PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
|
||||
}
|
||||
|
||||
/*
|
||||
PlaybackThreadProc
|
||||
|
||||
Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its
|
||||
audio data.
|
||||
*/
|
||||
static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)lpParameter;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
LPWAVEHDR pWaveHdr;
|
||||
ALuint FrameSize;
|
||||
MSG msg;
|
||||
|
||||
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
SetRTPriority();
|
||||
|
||||
while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WOM_DONE)
|
||||
continue;
|
||||
|
||||
if(pData->bWaveShutdown)
|
||||
{
|
||||
if(pData->lWaveBuffersCommitted == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
|
||||
aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
|
||||
|
||||
// Send buffer back to play more data
|
||||
waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
}
|
||||
|
||||
// Signal Wave Thread completed event
|
||||
if(pData->hWaveThreadEvent)
|
||||
SetEvent(pData->hWaveThreadEvent);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
WaveInProc
|
||||
|
||||
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)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)dwInstance;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
|
||||
(void)hDevice;
|
||||
(void)dwParam2;
|
||||
|
||||
if(uMsg != WIM_DATA)
|
||||
return;
|
||||
|
||||
InterlockedDecrement(&pData->lWaveBuffersCommitted);
|
||||
PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
|
||||
}
|
||||
|
||||
/*
|
||||
CaptureThreadProc
|
||||
|
||||
Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
|
||||
audio data.
|
||||
*/
|
||||
static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)lpParameter;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
LPWAVEHDR pWaveHdr;
|
||||
ALuint FrameSize;
|
||||
MSG msg;
|
||||
|
||||
FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
|
||||
|
||||
while(GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if(msg.message != WIM_DATA)
|
||||
continue;
|
||||
/* Don't wait for other buffers to finish before quitting. We're
|
||||
* closing so we don't need them. */
|
||||
if(pData->bWaveShutdown)
|
||||
break;
|
||||
|
||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
|
||||
WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData,
|
||||
pWaveHdr->dwBytesRecorded/FrameSize);
|
||||
|
||||
// Send buffer back to capture more data
|
||||
waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
}
|
||||
|
||||
// Signal Wave Thread completed event
|
||||
if(pData->hWaveThreadEvent)
|
||||
SetEvent(pData->hWaveThreadEvent);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
{
|
||||
WinMMData *pData = NULL;
|
||||
UINT lDeviceID = 0;
|
||||
MMRESULT res;
|
||||
ALuint i = 0;
|
||||
|
||||
if(!PlaybackDeviceList)
|
||||
ProbePlaybackDevices();
|
||||
|
||||
// Find the Device ID matching the deviceName if valid
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
if(PlaybackDeviceList[i] &&
|
||||
(!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0))
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NumPlaybackDevices)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
pData = calloc(1, sizeof(*pData));
|
||||
if(!pData)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
pDevice->ExtraData = pData;
|
||||
|
||||
retry_open:
|
||||
memset(&pData->wfexFormat, 0, sizeof(WAVEFORMATEX));
|
||||
if(pDevice->FmtType == DevFmtFloat)
|
||||
{
|
||||
pData->wfexFormat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
pData->wfexFormat.wBitsPerSample = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData->wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
if(pDevice->FmtType == DevFmtUByte || pDevice->FmtType == DevFmtByte)
|
||||
pData->wfexFormat.wBitsPerSample = 8;
|
||||
else
|
||||
pData->wfexFormat.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;
|
||||
|
||||
if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
if(pDevice->FmtType == DevFmtFloat)
|
||||
{
|
||||
pDevice->FmtType = DevFmtShort;
|
||||
goto retry_open;
|
||||
}
|
||||
ERR("waveOutOpen failed: %u\n", res);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(pData->hWaveThreadEvent == NULL)
|
||||
{
|
||||
ERR("CreateEvent failed: %lu\n", GetLastError());
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pDevice->szDeviceName = strdup(PlaybackDeviceList[lDeviceID]);
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
failure:
|
||||
if(pData->hWaveThreadEvent)
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
|
||||
if(pData->hWaveHandle.Out)
|
||||
waveOutClose(pData->hWaveHandle.Out);
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void WinMMClosePlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
|
||||
// Close the Wave device
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
pData->hWaveThreadEvent = 0;
|
||||
|
||||
waveOutClose(pData->hWaveHandle.Out);
|
||||
pData->hWaveHandle.Out = 0;
|
||||
|
||||
free(pData);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static ALCboolean WinMMResetPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *data = (WinMMData*)device->ExtraData;
|
||||
|
||||
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
|
||||
data->wfexFormat.nSamplesPerSec /
|
||||
device->Frequency);
|
||||
device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
|
||||
device->NumUpdates = 4;
|
||||
device->Frequency = data->wfexFormat.nSamplesPerSec;
|
||||
|
||||
if(data->wfexFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
|
||||
{
|
||||
if(data->wfexFormat.wBitsPerSample == 32)
|
||||
device->FmtType = DevFmtFloat;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled IEEE float sample depth: %d\n", data->wfexFormat.wBitsPerSample);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
else if(data->wfexFormat.wFormatTag == WAVE_FORMAT_PCM)
|
||||
{
|
||||
if(data->wfexFormat.wBitsPerSample == 16)
|
||||
device->FmtType = DevFmtShort;
|
||||
else if(data->wfexFormat.wBitsPerSample == 8)
|
||||
device->FmtType = DevFmtUByte;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled PCM sample depth: %d\n", data->wfexFormat.wBitsPerSample);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Unhandled format tag: 0x%04x\n", data->wfexFormat.wFormatTag);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if(data->wfexFormat.nChannels == 2)
|
||||
device->FmtChans = DevFmtStereo;
|
||||
else if(data->wfexFormat.nChannels == 1)
|
||||
device->FmtChans = DevFmtMono;
|
||||
else
|
||||
{
|
||||
ERR("Unhandled channel count: %d\n", data->wfexFormat.nChannels);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static ALCboolean WinMMStartPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
ALbyte *BufferData;
|
||||
ALint lBufferSize;
|
||||
ALuint i;
|
||||
|
||||
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID);
|
||||
if(pData->hWaveThread == NULL)
|
||||
return ALC_FALSE;
|
||||
|
||||
pData->lWaveBuffersCommitted = 0;
|
||||
|
||||
// Create 4 Buffers
|
||||
lBufferSize = device->UpdateSize*device->NumUpdates / 4;
|
||||
lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
|
||||
|
||||
BufferData = calloc(4, lBufferSize);
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
|
||||
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(pData->WaveBuffer[i-1].lpData +
|
||||
pData->WaveBuffer[i-1].dwBufferLength));
|
||||
waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void WinMMStopPlayback(ALCdevice *device)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)device->ExtraData;
|
||||
void *buffer = NULL;
|
||||
int i;
|
||||
|
||||
if(pData->hWaveThread == NULL)
|
||||
return;
|
||||
|
||||
// Set flag to stop processing headers
|
||||
pData->bWaveShutdown = AL_TRUE;
|
||||
|
||||
// Wait for signal that Wave Thread has been destroyed
|
||||
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
||||
|
||||
CloseHandle(pData->hWaveThread);
|
||||
pData->hWaveThread = 0;
|
||||
|
||||
pData->bWaveShutdown = AL_FALSE;
|
||||
|
||||
// Release the wave buffers
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
if(i == 0) buffer = pData->WaveBuffer[i].lpData;
|
||||
pData->WaveBuffer[i].lpData = NULL;
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
{
|
||||
ALbyte *BufferData = NULL;
|
||||
DWORD ulCapturedDataSize;
|
||||
WinMMData *pData = NULL;
|
||||
UINT lDeviceID = 0;
|
||||
ALint lBufferSize;
|
||||
MMRESULT res;
|
||||
ALuint i;
|
||||
|
||||
if(!CaptureDeviceList)
|
||||
ProbeCaptureDevices();
|
||||
|
||||
// Find the Device ID matching the deviceName if valid
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i] &&
|
||||
(!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NumCaptureDevices)
|
||||
return ALC_INVALID_VALUE;
|
||||
|
||||
switch(pDevice->FmtChans)
|
||||
{
|
||||
case DevFmtMono:
|
||||
case DevFmtStereo:
|
||||
break;
|
||||
|
||||
case DevFmtQuad:
|
||||
case DevFmtX51:
|
||||
case DevFmtX51Side:
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
return ALC_INVALID_ENUM;
|
||||
}
|
||||
|
||||
switch(pDevice->FmtType)
|
||||
{
|
||||
case DevFmtUByte:
|
||||
case DevFmtShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtFloat:
|
||||
break;
|
||||
|
||||
case DevFmtByte:
|
||||
case DevFmtUShort:
|
||||
case DevFmtUInt:
|
||||
return ALC_INVALID_ENUM;
|
||||
}
|
||||
|
||||
pData = calloc(1, sizeof(*pData));
|
||||
if(!pData)
|
||||
return ALC_OUT_OF_MEMORY;
|
||||
pDevice->ExtraData = pData;
|
||||
|
||||
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;
|
||||
|
||||
if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &pData->wfexFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
|
||||
{
|
||||
ERR("waveInOpen failed: %u\n", res);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if(pData->hWaveThreadEvent == NULL)
|
||||
{
|
||||
ERR("CreateEvent failed: %lu\n", GetLastError());
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// Allocate circular memory buffer for the captured audio
|
||||
ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
|
||||
|
||||
// Make sure circular buffer is at least 100ms in size
|
||||
if(ulCapturedDataSize < (pData->wfexFormat.nSamplesPerSec / 10))
|
||||
ulCapturedDataSize = pData->wfexFormat.nSamplesPerSec / 10;
|
||||
|
||||
pData->pRing = CreateRingBuffer(pData->wfexFormat.nBlockAlign, ulCapturedDataSize);
|
||||
if(!pData->pRing)
|
||||
goto failure;
|
||||
|
||||
pData->lWaveBuffersCommitted = 0;
|
||||
|
||||
// Create 4 Buffers of 50ms each
|
||||
lBufferSize = pData->wfexFormat.nAvgBytesPerSec / 20;
|
||||
lBufferSize -= (lBufferSize % pData->wfexFormat.nBlockAlign);
|
||||
|
||||
BufferData = calloc(4, lBufferSize);
|
||||
if(!BufferData)
|
||||
goto failure;
|
||||
|
||||
for(i = 0;i < 4;i++)
|
||||
{
|
||||
memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
|
||||
pData->WaveBuffer[i].dwBufferLength = lBufferSize;
|
||||
pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
|
||||
(pData->WaveBuffer[i-1].lpData +
|
||||
pData->WaveBuffer[i-1].dwBufferLength));
|
||||
pData->WaveBuffer[i].dwFlags = 0;
|
||||
pData->WaveBuffer[i].dwLoops = 0;
|
||||
waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
InterlockedIncrement(&pData->lWaveBuffersCommitted);
|
||||
}
|
||||
|
||||
pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
|
||||
if (pData->hWaveThread == NULL)
|
||||
goto failure;
|
||||
|
||||
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
|
||||
return ALC_NO_ERROR;
|
||||
|
||||
failure:
|
||||
if(pData->hWaveThread)
|
||||
CloseHandle(pData->hWaveThread);
|
||||
|
||||
if(BufferData)
|
||||
{
|
||||
for(i = 0;i < 4;i++)
|
||||
waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
|
||||
free(BufferData);
|
||||
}
|
||||
|
||||
if(pData->pRing)
|
||||
DestroyRingBuffer(pData->pRing);
|
||||
|
||||
if(pData->hWaveThreadEvent)
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
|
||||
if(pData->hWaveHandle.In)
|
||||
waveInClose(pData->hWaveHandle.In);
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
return ALC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
static void WinMMCloseCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->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);
|
||||
|
||||
WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
|
||||
|
||||
/* Make sure capture is stopped and all pending buffers are flushed. */
|
||||
waveInReset(pData->hWaveHandle.In);
|
||||
|
||||
CloseHandle(pData->hWaveThread);
|
||||
pData->hWaveThread = 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;
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
DestroyRingBuffer(pData->pRing);
|
||||
pData->pRing = NULL;
|
||||
|
||||
// Close the Wave device
|
||||
CloseHandle(pData->hWaveThreadEvent);
|
||||
pData->hWaveThreadEvent = 0;
|
||||
|
||||
waveInClose(pData->hWaveHandle.In);
|
||||
pData->hWaveHandle.In = 0;
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void WinMMStartCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStart(pData->hWaveHandle.In);
|
||||
}
|
||||
|
||||
static void WinMMStopCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStop(pData->hWaveHandle.In);
|
||||
}
|
||||
|
||||
static ALCenum WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
ReadRingBuffer(pData->pRing, pBuffer, lSamples);
|
||||
return ALC_NO_ERROR;
|
||||
}
|
||||
|
||||
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
return RingBufferSize(pData->pRing);
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs WinMMFuncs = {
|
||||
WinMMOpenPlayback,
|
||||
WinMMClosePlayback,
|
||||
WinMMResetPlayback,
|
||||
WinMMStartPlayback,
|
||||
WinMMStopPlayback,
|
||||
WinMMOpenCapture,
|
||||
WinMMCloseCapture,
|
||||
WinMMStartCapture,
|
||||
WinMMStopCapture,
|
||||
WinMMCaptureSamples,
|
||||
WinMMAvailableSamples
|
||||
};
|
||||
|
||||
ALCboolean alcWinMMInit(BackendFuncs *FuncList)
|
||||
{
|
||||
*FuncList = WinMMFuncs;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
void alcWinMMDeinit()
|
||||
{
|
||||
ALuint lLoop;
|
||||
|
||||
for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++)
|
||||
free(PlaybackDeviceList[lLoop]);
|
||||
free(PlaybackDeviceList);
|
||||
PlaybackDeviceList = NULL;
|
||||
|
||||
NumPlaybackDevices = 0;
|
||||
|
||||
|
||||
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
|
||||
free(CaptureDeviceList[lLoop]);
|
||||
free(CaptureDeviceList);
|
||||
CaptureDeviceList = NULL;
|
||||
|
||||
NumCaptureDevices = 0;
|
||||
}
|
||||
|
||||
void alcWinMMProbe(enum DevProbe type)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ALL_DEVICE_PROBE:
|
||||
ProbePlaybackDevices();
|
||||
for(i = 0;i < NumPlaybackDevices;i++)
|
||||
{
|
||||
if(PlaybackDeviceList[i])
|
||||
AppendAllDeviceList(PlaybackDeviceList[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case CAPTURE_DEVICE_PROBE:
|
||||
ProbeCaptureDevices();
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i])
|
||||
AppendCaptureDeviceList(CaptureDeviceList[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
+5
-21
@@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bs2b.h"
|
||||
|
||||
@@ -112,7 +113,7 @@ static void init(struct bs2b *bs2b)
|
||||
bs2b->a0_hi = 1.0 - G_hi * (1.0 - x);
|
||||
bs2b->a1_hi = -x;
|
||||
|
||||
bs2b->gain = 1.0 / (1.0 - G_hi + G_lo);
|
||||
bs2b->gain = 1.0f / (float)(1.0 - G_hi + G_lo);
|
||||
} /* init */
|
||||
|
||||
/* Exported functions.
|
||||
@@ -147,26 +148,9 @@ int bs2b_get_srate(struct bs2b *bs2b)
|
||||
|
||||
void bs2b_clear(struct bs2b *bs2b)
|
||||
{
|
||||
int loopv = sizeof(bs2b->last_sample);
|
||||
|
||||
while (loopv)
|
||||
{
|
||||
((char *)&bs2b->last_sample)[--loopv] = 0;
|
||||
}
|
||||
memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample));
|
||||
} /* bs2b_clear */
|
||||
|
||||
int bs2b_is_clear(struct bs2b *bs2b)
|
||||
{
|
||||
int loopv = sizeof(bs2b->last_sample);
|
||||
|
||||
while (loopv)
|
||||
{
|
||||
if (((char *)&bs2b->last_sample)[--loopv] != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
} /* bs2b_is_clear */
|
||||
|
||||
void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
|
||||
{
|
||||
/* Lowpass filter */
|
||||
@@ -180,8 +164,8 @@ void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
|
||||
bs2b->last_sample.asis[1] = sample[1];
|
||||
|
||||
/* Crossfeed */
|
||||
sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
|
||||
sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
|
||||
sample[0] = (float)(bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]);
|
||||
sample[1] = (float)(bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]);
|
||||
|
||||
/* Bass boost cause allpass attenuation */
|
||||
sample[0] *= bs2b->gain;
|
||||
|
||||
-591
@@ -1,591 +0,0 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#define INITGUID
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <dsound.h>
|
||||
#include <mmreg.h>
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
#include <ks.h>
|
||||
#include <ksmedia.h>
|
||||
#endif
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#ifndef DSSPEAKER_5POINT1
|
||||
#define DSSPEAKER_5POINT1 6
|
||||
#endif
|
||||
#ifndef DSSPEAKER_7POINT1
|
||||
#define DSSPEAKER_7POINT1 7
|
||||
#endif
|
||||
|
||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
static void *ds_handle;
|
||||
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
|
||||
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
|
||||
|
||||
|
||||
typedef struct {
|
||||
// DirectSound Playback Device
|
||||
LPDIRECTSOUND lpDS;
|
||||
LPDIRECTSOUNDBUFFER DSpbuffer;
|
||||
LPDIRECTSOUNDBUFFER DSsbuffer;
|
||||
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} DSoundData;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ALCchar *name;
|
||||
GUID guid;
|
||||
} DevMap;
|
||||
|
||||
static const ALCchar dsDevice[] = "DirectSound Software";
|
||||
static DevMap *DeviceList;
|
||||
static ALuint NumDevices;
|
||||
static volatile ALuint load_count;
|
||||
|
||||
|
||||
void *DSoundLoad(void)
|
||||
{
|
||||
if(load_count == 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ds_handle = LoadLibraryA("dsound.dll");
|
||||
if(ds_handle == NULL)
|
||||
{
|
||||
AL_PRINT("Failed to load dsound.dll\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define LOAD_FUNC(f) do { \
|
||||
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
|
||||
if(p##f == NULL) \
|
||||
{ \
|
||||
FreeLibrary(ds_handle); \
|
||||
ds_handle = NULL; \
|
||||
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
ds_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(f) p##f = f
|
||||
#endif
|
||||
|
||||
LOAD_FUNC(DirectSoundCreate);
|
||||
LOAD_FUNC(DirectSoundEnumerateA);
|
||||
#undef LOAD_FUNC
|
||||
}
|
||||
++load_count;
|
||||
|
||||
return ds_handle;
|
||||
}
|
||||
|
||||
void DSoundUnload(void)
|
||||
{
|
||||
if(load_count == 0 || --load_count > 0)
|
||||
return;
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(ds_handle);
|
||||
#endif
|
||||
ds_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data)
|
||||
{
|
||||
(void)data;
|
||||
(void)drvname;
|
||||
|
||||
if(guid)
|
||||
{
|
||||
char str[128];
|
||||
void *temp;
|
||||
|
||||
temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1));
|
||||
if(temp)
|
||||
{
|
||||
DeviceList = temp;
|
||||
|
||||
snprintf(str, sizeof(str), "DirectSound Software on %s", desc);
|
||||
|
||||
DeviceList[NumDevices].name = strdup(str);
|
||||
DeviceList[NumDevices].guid = *guid;
|
||||
NumDevices++;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static ALuint DSoundProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
DSoundData *pData = (DSoundData*)pDevice->ExtraData;
|
||||
DSBCAPS DSBCaps;
|
||||
DWORD LastCursor = 0;
|
||||
DWORD PlayCursor;
|
||||
VOID *WritePtr1, *WritePtr2;
|
||||
DWORD WriteCnt1, WriteCnt2;
|
||||
DWORD FrameSize;
|
||||
DWORD FragSize;
|
||||
DWORD avail;
|
||||
HRESULT err;
|
||||
|
||||
EnableRTPrio(RTPrioLevel);
|
||||
|
||||
memset(&DSBCaps, 0, sizeof(DSBCaps));
|
||||
DSBCaps.dwSize = sizeof(DSBCaps);
|
||||
err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
|
||||
if(FAILED(err))
|
||||
{
|
||||
AL_PRINT("Failed to get buffer caps: 0x%lx\n", err);
|
||||
aluHandleDisconnect(pDevice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
FrameSize = aluChannelsFromFormat(pDevice->Format) *
|
||||
aluBytesFromFormat(pDevice->Format);
|
||||
FragSize = pDevice->UpdateSize * FrameSize;
|
||||
|
||||
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
|
||||
while(!pData->killNow)
|
||||
{
|
||||
// Get current play and write cursors
|
||||
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
|
||||
avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
|
||||
|
||||
if(avail < FragSize)
|
||||
{
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
avail -= avail%FragSize;
|
||||
|
||||
// Lock output buffer
|
||||
WriteCnt1 = 0;
|
||||
WriteCnt2 = 0;
|
||||
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
|
||||
|
||||
// If the buffer is lost, restore it, play and lock
|
||||
if(err == DSERR_BUFFERLOST)
|
||||
{
|
||||
err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
|
||||
if(SUCCEEDED(err))
|
||||
err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
|
||||
if(SUCCEEDED(err))
|
||||
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
|
||||
}
|
||||
|
||||
// Successfully locked the output buffer
|
||||
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);
|
||||
|
||||
// Unlock output buffer only when successfully locked
|
||||
IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
|
||||
}
|
||||
else
|
||||
AL_PRINT("Buffer lock error: %#lx\n", err);
|
||||
|
||||
// Update old write cursor location
|
||||
LastCursor += WriteCnt1+WriteCnt2;
|
||||
LastCursor %= DSBCaps.dwBufferBytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
DSoundData *pData = NULL;
|
||||
LPGUID guid = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
if(!DSoundLoad())
|
||||
return ALC_FALSE;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = dsDevice;
|
||||
else if(strcmp(deviceName, dsDevice) != 0)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
if(!DeviceList)
|
||||
{
|
||||
hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL);
|
||||
if(FAILED(hr))
|
||||
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
||||
}
|
||||
|
||||
for(i = 0;i < NumDevices;i++)
|
||||
{
|
||||
if(strcmp(deviceName, DeviceList[i].name) == 0)
|
||||
{
|
||||
guid = &DeviceList[i].guid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == NumDevices)
|
||||
{
|
||||
DSoundUnload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//Initialise requested device
|
||||
pData = calloc(1, sizeof(DSoundData));
|
||||
if(!pData)
|
||||
{
|
||||
alcSetError(device, ALC_OUT_OF_MEMORY);
|
||||
DSoundUnload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
//DirectSound Init code
|
||||
hr = pDirectSoundCreate(guid, &pData->lpDS, NULL);
|
||||
if(SUCCEEDED(hr))
|
||||
hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if(pData->lpDS)
|
||||
IDirectSound_Release(pData->lpDS);
|
||||
free(pData);
|
||||
DSoundUnload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->ExtraData = pData;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void DSoundClosePlayback(ALCdevice *device)
|
||||
{
|
||||
DSoundData *pData = device->ExtraData;
|
||||
|
||||
IDirectSound_Release(pData->lpDS);
|
||||
free(pData);
|
||||
device->ExtraData = NULL;
|
||||
|
||||
DSoundUnload();
|
||||
}
|
||||
|
||||
static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
||||
{
|
||||
DSoundData *pData = (DSoundData*)device->ExtraData;
|
||||
DSBUFFERDESC DSBDescription;
|
||||
WAVEFORMATEXTENSIBLE OutputType;
|
||||
DWORD frameSize = 0;
|
||||
ALenum format = 0;
|
||||
DWORD speakers;
|
||||
HRESULT hr;
|
||||
|
||||
memset(&OutputType, 0, sizeof(OutputType));
|
||||
|
||||
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
|
||||
if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format"))
|
||||
{
|
||||
if(aluChannelsFromFormat(device->Format) == 1)
|
||||
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
|
||||
else if(aluChannelsFromFormat(device->Format) == 2)
|
||||
speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
|
||||
else if(aluChannelsFromFormat(device->Format) == 4)
|
||||
speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
|
||||
else if(aluChannelsFromFormat(device->Format) == 6)
|
||||
speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
|
||||
else if(aluChannelsFromFormat(device->Format) == 8)
|
||||
speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
|
||||
else
|
||||
{
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
}
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
speakers = DSSPEAKER_CONFIG(speakers);
|
||||
if(speakers == DSSPEAKER_MONO)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
format = AL_FORMAT_MONO8;
|
||||
else if(aluBytesFromFormat(device->Format) == 2)
|
||||
format = AL_FORMAT_MONO16;
|
||||
else if(aluBytesFromFormat(device->Format) == 4)
|
||||
format = AL_FORMAT_MONO_FLOAT32;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_STEREO)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
format = AL_FORMAT_STEREO8;
|
||||
else if(aluBytesFromFormat(device->Format) == 2)
|
||||
format = AL_FORMAT_STEREO16;
|
||||
else if(aluBytesFromFormat(device->Format) == 4)
|
||||
format = AL_FORMAT_STEREO_FLOAT32;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_QUAD)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
format = AL_FORMAT_QUAD8;
|
||||
else if(aluBytesFromFormat(device->Format) == 2)
|
||||
format = AL_FORMAT_QUAD16;
|
||||
else if(aluBytesFromFormat(device->Format) == 4)
|
||||
format = AL_FORMAT_QUAD32;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_BACK_LEFT |
|
||||
SPEAKER_BACK_RIGHT;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_5POINT1)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
format = AL_FORMAT_51CHN8;
|
||||
else if(aluBytesFromFormat(device->Format) == 2)
|
||||
format = AL_FORMAT_51CHN16;
|
||||
else if(aluBytesFromFormat(device->Format) == 4)
|
||||
format = AL_FORMAT_51CHN32;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_FRONT_CENTER |
|
||||
SPEAKER_LOW_FREQUENCY |
|
||||
SPEAKER_BACK_LEFT |
|
||||
SPEAKER_BACK_RIGHT;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_7POINT1)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
format = AL_FORMAT_71CHN8;
|
||||
else if(aluBytesFromFormat(device->Format) == 2)
|
||||
format = AL_FORMAT_71CHN16;
|
||||
else if(aluBytesFromFormat(device->Format) == 4)
|
||||
format = AL_FORMAT_71CHN32;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_FRONT_CENTER |
|
||||
SPEAKER_LOW_FREQUENCY |
|
||||
SPEAKER_BACK_LEFT |
|
||||
SPEAKER_BACK_RIGHT |
|
||||
SPEAKER_SIDE_LEFT |
|
||||
SPEAKER_SIDE_RIGHT;
|
||||
}
|
||||
else
|
||||
format = device->Format;
|
||||
frameSize = aluBytesFromFormat(format) * aluChannelsFromFormat(format);
|
||||
|
||||
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
OutputType.Format.nChannels = aluChannelsFromFormat(format);
|
||||
OutputType.Format.wBitsPerSample = aluBytesFromFormat(format) * 8;
|
||||
OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
|
||||
OutputType.Format.nSamplesPerSec = device->Frequency;
|
||||
OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign;
|
||||
OutputType.Format.cbSize = 0;
|
||||
}
|
||||
|
||||
if(OutputType.Format.nChannels > 2 || OutputType.Format.wBitsPerSample > 16)
|
||||
{
|
||||
OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
|
||||
OutputType.Format.cbSize = 22;
|
||||
if(OutputType.Format.wBitsPerSample == 32)
|
||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
else
|
||||
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
|
||||
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
|
||||
DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
|
||||
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL);
|
||||
}
|
||||
if(SUCCEEDED(hr))
|
||||
hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format);
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
|
||||
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
|
||||
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
|
||||
DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * frameSize;
|
||||
DSBDescription.lpwfxFormat=&OutputType.Format;
|
||||
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
device->Format = format;
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
pData->thread = StartThread(DSoundProc, device);
|
||||
if(!pData->thread)
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if(FAILED(hr))
|
||||
{
|
||||
if (pData->DSsbuffer)
|
||||
IDirectSoundBuffer_Release(pData->DSsbuffer);
|
||||
pData->DSsbuffer = NULL;
|
||||
if (pData->DSpbuffer)
|
||||
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
||||
pData->DSpbuffer = NULL;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void DSoundStopPlayback(ALCdevice *device)
|
||||
{
|
||||
DSoundData *pData = device->ExtraData;
|
||||
|
||||
if(!pData->thread)
|
||||
return;
|
||||
|
||||
pData->killNow = 1;
|
||||
StopThread(pData->thread);
|
||||
pData->thread = NULL;
|
||||
|
||||
pData->killNow = 0;
|
||||
|
||||
IDirectSoundBuffer_Release(pData->DSsbuffer);
|
||||
pData->DSsbuffer = NULL;
|
||||
if (pData->DSpbuffer)
|
||||
IDirectSoundBuffer_Release(pData->DSpbuffer);
|
||||
pData->DSpbuffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean DSoundOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)deviceName;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void DSoundCloseCapture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void DSoundStartCapture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void DSoundStopCapture(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static void DSoundCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
(void)pDevice;
|
||||
(void)pBuffer;
|
||||
(void)lSamples;
|
||||
}
|
||||
|
||||
static ALCuint DSoundAvailableSamples(ALCdevice *pDevice)
|
||||
{
|
||||
(void)pDevice;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs DSoundFuncs = {
|
||||
DSoundOpenPlayback,
|
||||
DSoundClosePlayback,
|
||||
DSoundResetPlayback,
|
||||
DSoundStopPlayback,
|
||||
DSoundOpenCapture,
|
||||
DSoundCloseCapture,
|
||||
DSoundStartCapture,
|
||||
DSoundStopCapture,
|
||||
DSoundCaptureSamples,
|
||||
DSoundAvailableSamples
|
||||
};
|
||||
|
||||
|
||||
void alcDSoundInit(BackendFuncs *FuncList)
|
||||
{
|
||||
*FuncList = DSoundFuncs;
|
||||
}
|
||||
|
||||
void alcDSoundDeinit(void)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < NumDevices;++i)
|
||||
free(DeviceList[i].name);
|
||||
free(DeviceList);
|
||||
DeviceList = NULL;
|
||||
NumDevices = 0;
|
||||
}
|
||||
|
||||
void alcDSoundProbe(int type)
|
||||
{
|
||||
if(!DSoundLoad()) return;
|
||||
|
||||
if(type == DEVICE_PROBE)
|
||||
AppendDeviceList(dsDevice);
|
||||
else if(type == ALL_DEVICE_PROBE)
|
||||
{
|
||||
HRESULT hr;
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < NumDevices;++i)
|
||||
free(DeviceList[i].name);
|
||||
free(DeviceList);
|
||||
DeviceList = NULL;
|
||||
NumDevices = 0;
|
||||
|
||||
hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL);
|
||||
if(FAILED(hr))
|
||||
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
||||
else
|
||||
{
|
||||
for(i = 0;i < NumDevices;i++)
|
||||
AppendAllDeviceList(DeviceList[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
DSoundUnload();
|
||||
}
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2011 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
|
||||
#define INITGUID
|
||||
#include <windows.h>
|
||||
#ifdef HAVE_GUIDDEF_H
|
||||
#include <guiddef.h>
|
||||
#else
|
||||
#include <initguid.h>
|
||||
#endif
|
||||
|
||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71);
|
||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71);
|
||||
|
||||
DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16);
|
||||
|
||||
DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e);
|
||||
DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6);
|
||||
DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
|
||||
DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
|
||||
|
||||
#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
|
||||
|
||||
#include "alMain.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
void pthread_once(pthread_once_t *once, void (*callback)(void))
|
||||
{
|
||||
LONG ret;
|
||||
while((ret=InterlockedExchange(once, 1)) == 1)
|
||||
sched_yield();
|
||||
if(ret == 0)
|
||||
callback();
|
||||
InterlockedExchange(once, 2);
|
||||
}
|
||||
|
||||
|
||||
int pthread_key_create(pthread_key_t *key, void (*callback)(void*))
|
||||
{
|
||||
*key = TlsAlloc();
|
||||
if(callback)
|
||||
InsertUIntMapEntry(&TlsDestructor, *key, callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_key_delete(pthread_key_t key)
|
||||
{
|
||||
InsertUIntMapEntry(&TlsDestructor, key, NULL);
|
||||
TlsFree(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *pthread_getspecific(pthread_key_t key)
|
||||
{ return TlsGetValue(key); }
|
||||
|
||||
int pthread_setspecific(pthread_key_t key, void *val)
|
||||
{
|
||||
TlsSetValue(key, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *LoadLib(const char *name)
|
||||
{ return LoadLibraryA(name); }
|
||||
void CloseLib(void *handle)
|
||||
{ FreeLibrary((HANDLE)handle); }
|
||||
void *GetSymbol(void *handle, const char *name)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
ret = (void*)GetProcAddress((HANDLE)handle, name);
|
||||
if(ret == NULL)
|
||||
ERR("Failed to load %s\n", name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
WCHAR *strdupW(const WCHAR *str)
|
||||
{
|
||||
const WCHAR *n;
|
||||
WCHAR *ret;
|
||||
size_t len;
|
||||
|
||||
n = str;
|
||||
while(*n) n++;
|
||||
len = n - str;
|
||||
|
||||
ret = calloc(sizeof(WCHAR), len+1);
|
||||
if(ret != NULL)
|
||||
memcpy(ret, str, sizeof(WCHAR)*len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void InitializeCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
pthread_mutexattr_t attrib;
|
||||
int ret;
|
||||
|
||||
ret = pthread_mutexattr_init(&attrib);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
|
||||
#ifdef HAVE_PTHREAD_NP_H
|
||||
if(ret != 0)
|
||||
ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
|
||||
#endif
|
||||
assert(ret == 0);
|
||||
ret = pthread_mutex_init(cs, &attrib);
|
||||
assert(ret == 0);
|
||||
|
||||
pthread_mutexattr_destroy(&attrib);
|
||||
}
|
||||
void DeleteCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_destroy(cs);
|
||||
assert(ret == 0);
|
||||
}
|
||||
void EnterCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_lock(cs);
|
||||
assert(ret == 0);
|
||||
}
|
||||
void LeaveCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_unlock(cs);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
|
||||
* to the expected DWORD. Both are defined as unsigned 32-bit types, however.
|
||||
* Additionally, Win32 is supposed to measure the time since Windows started,
|
||||
* as opposed to the actual time. */
|
||||
ALuint timeGetTime(void)
|
||||
{
|
||||
#if _POSIX_TIMERS > 0
|
||||
struct timespec ts;
|
||||
int ret = -1;
|
||||
|
||||
#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
|
||||
#if _POSIX_MONOTONIC_CLOCK == 0
|
||||
static int hasmono = 0;
|
||||
if(hasmono > 0 || (hasmono == 0 &&
|
||||
(hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0))
|
||||
#endif
|
||||
ret = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
if(ret != 0)
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
assert(ret == 0);
|
||||
|
||||
return ts.tv_nsec/1000000 + ts.tv_sec*1000;
|
||||
#else
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
ret = gettimeofday(&tv, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
return tv.tv_usec/1000 + tv.tv_sec*1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Sleep(ALuint t)
|
||||
{
|
||||
struct timespec tv, rem;
|
||||
tv.tv_nsec = (t*1000000)%1000000000;
|
||||
tv.tv_sec = t/1000;
|
||||
|
||||
while(nanosleep(&tv, &rem) == -1 && errno == EINTR)
|
||||
tv = rem;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
|
||||
void *LoadLib(const char *name)
|
||||
{
|
||||
const char *err;
|
||||
void *handle;
|
||||
|
||||
dlerror();
|
||||
handle = dlopen(name, RTLD_NOW);
|
||||
if((err=dlerror()) != NULL)
|
||||
handle = NULL;
|
||||
return handle;
|
||||
}
|
||||
void CloseLib(void *handle)
|
||||
{ dlclose(handle); }
|
||||
void *GetSymbol(void *handle, const char *name)
|
||||
{
|
||||
const char *err;
|
||||
void *sym;
|
||||
|
||||
dlerror();
|
||||
sym = dlsym(handle, name);
|
||||
if((err=dlerror()) != NULL)
|
||||
{
|
||||
WARN("Failed to load %s: %s\n", name, err);
|
||||
sym = NULL;
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void al_print(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)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(str+i, sizeof(str)-i, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
str[sizeof(str)-1] = 0;
|
||||
|
||||
fprintf(LogFile, "%s", str);
|
||||
fflush(LogFile);
|
||||
}
|
||||
|
||||
|
||||
void SetRTPriority(void)
|
||||
{
|
||||
ALboolean failed = AL_FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
if(RTPrioLevel > 0)
|
||||
failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__)
|
||||
if(RTPrioLevel > 0)
|
||||
{
|
||||
struct sched_param param;
|
||||
/* Use the minimum real-time priority possible for now (on Linux this
|
||||
* should be 1 for SCHED_RR) */
|
||||
param.sched_priority = sched_get_priority_min(SCHED_RR);
|
||||
failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, ¶m);
|
||||
}
|
||||
#else
|
||||
/* Real-time priority not available */
|
||||
failed = (RTPrioLevel>0);
|
||||
#endif
|
||||
if(failed)
|
||||
ERR("Failed to set priority level for thread\n");
|
||||
}
|
||||
|
||||
|
||||
static void Lock(volatile ALenum *l)
|
||||
{
|
||||
while(ExchangeInt(l, AL_TRUE) == AL_TRUE)
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
static void Unlock(volatile ALenum *l)
|
||||
{
|
||||
ExchangeInt(l, AL_FALSE);
|
||||
}
|
||||
|
||||
void RWLockInit(RWLock *lock)
|
||||
{
|
||||
lock->read_count = 0;
|
||||
lock->write_count = 0;
|
||||
lock->read_lock = AL_FALSE;
|
||||
lock->read_entry_lock = AL_FALSE;
|
||||
lock->write_lock = AL_FALSE;
|
||||
}
|
||||
|
||||
void ReadLock(RWLock *lock)
|
||||
{
|
||||
Lock(&lock->read_entry_lock);
|
||||
Lock(&lock->read_lock);
|
||||
if(IncrementRef(&lock->read_count) == 1)
|
||||
Lock(&lock->write_lock);
|
||||
Unlock(&lock->read_lock);
|
||||
Unlock(&lock->read_entry_lock);
|
||||
}
|
||||
|
||||
void ReadUnlock(RWLock *lock)
|
||||
{
|
||||
if(DecrementRef(&lock->read_count) == 0)
|
||||
Unlock(&lock->write_lock);
|
||||
}
|
||||
|
||||
void WriteLock(RWLock *lock)
|
||||
{
|
||||
if(IncrementRef(&lock->write_count) == 1)
|
||||
Lock(&lock->read_lock);
|
||||
Lock(&lock->write_lock);
|
||||
}
|
||||
|
||||
void WriteUnlock(RWLock *lock)
|
||||
{
|
||||
Unlock(&lock->write_lock);
|
||||
if(DecrementRef(&lock->write_count) == 0)
|
||||
Unlock(&lock->read_lock);
|
||||
}
|
||||
|
||||
|
||||
void InitUIntMap(UIntMap *map, ALsizei limit)
|
||||
{
|
||||
map->array = NULL;
|
||||
map->size = 0;
|
||||
map->maxsize = 0;
|
||||
map->limit = limit;
|
||||
RWLockInit(&map->lock);
|
||||
}
|
||||
|
||||
void ResetUIntMap(UIntMap *map)
|
||||
{
|
||||
WriteLock(&map->lock);
|
||||
free(map->array);
|
||||
map->array = NULL;
|
||||
map->size = 0;
|
||||
map->maxsize = 0;
|
||||
WriteUnlock(&map->lock);
|
||||
}
|
||||
|
||||
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
|
||||
{
|
||||
ALsizei pos = 0;
|
||||
|
||||
WriteLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei low = 0;
|
||||
ALsizei high = map->size - 1;
|
||||
while(low < high)
|
||||
{
|
||||
ALsizei mid = low + (high-low)/2;
|
||||
if(map->array[mid].key < key)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
if(map->array[low].key < key)
|
||||
low++;
|
||||
pos = low;
|
||||
}
|
||||
|
||||
if(pos == map->size || map->array[pos].key != key)
|
||||
{
|
||||
if(map->size == map->limit)
|
||||
{
|
||||
WriteUnlock(&map->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(map->size == map->maxsize)
|
||||
{
|
||||
ALvoid *temp = NULL;
|
||||
ALsizei newsize;
|
||||
|
||||
newsize = (map->maxsize ? (map->maxsize<<1) : 4);
|
||||
if(newsize >= map->maxsize)
|
||||
temp = realloc(map->array, newsize*sizeof(map->array[0]));
|
||||
if(!temp)
|
||||
{
|
||||
WriteUnlock(&map->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
map->array = temp;
|
||||
map->maxsize = newsize;
|
||||
}
|
||||
|
||||
if(pos < map->size)
|
||||
memmove(&map->array[pos+1], &map->array[pos],
|
||||
(map->size-pos)*sizeof(map->array[0]));
|
||||
map->size++;
|
||||
}
|
||||
map->array[pos].key = key;
|
||||
map->array[pos].value = value;
|
||||
WriteUnlock(&map->lock);
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
|
||||
{
|
||||
ALvoid *ptr = NULL;
|
||||
WriteLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei low = 0;
|
||||
ALsizei high = map->size - 1;
|
||||
while(low < high)
|
||||
{
|
||||
ALsizei mid = low + (high-low)/2;
|
||||
if(map->array[mid].key < key)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
if(map->array[low].key == key)
|
||||
{
|
||||
ptr = map->array[low].value;
|
||||
if(low < map->size-1)
|
||||
memmove(&map->array[low], &map->array[low+1],
|
||||
(map->size-1-low)*sizeof(map->array[0]));
|
||||
map->size--;
|
||||
}
|
||||
}
|
||||
WriteUnlock(&map->lock);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
|
||||
{
|
||||
ALvoid *ptr = NULL;
|
||||
ReadLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei low = 0;
|
||||
ALsizei high = map->size - 1;
|
||||
while(low < high)
|
||||
{
|
||||
ALsizei mid = low + (high-low)/2;
|
||||
if(map->array[mid].key < key)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
if(map->array[low].key == key)
|
||||
ptr = map->array[low].value;
|
||||
}
|
||||
ReadUnlock(&map->lock);
|
||||
return ptr;
|
||||
}
|
||||
+457
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2011 by Chris Robinson
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alMain.h"
|
||||
#include "alSource.h"
|
||||
|
||||
|
||||
static const ALchar magicMarker[8] = "MinPHR00";
|
||||
|
||||
#define HRIR_COUNT 828
|
||||
#define ELEV_COUNT 19
|
||||
|
||||
static const ALushort evOffset[ELEV_COUNT] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 };
|
||||
static const ALubyte azCount[ELEV_COUNT] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 };
|
||||
|
||||
|
||||
static const struct Hrtf {
|
||||
ALuint sampleRate;
|
||||
ALshort coeffs[HRIR_COUNT][HRIR_LENGTH];
|
||||
ALubyte delays[HRIR_COUNT];
|
||||
} DefaultHrtf = {
|
||||
44100,
|
||||
#include "hrtf_tables.inc"
|
||||
};
|
||||
|
||||
static struct Hrtf *LoadedHrtfs = NULL;
|
||||
static ALuint NumLoadedHrtfs = 0;
|
||||
|
||||
|
||||
// Calculate the elevation indices given the polar elevation in radians.
|
||||
// This will return two indices between 0 and (ELEV_COUNT-1) and an
|
||||
// interpolation factor between 0.0 and 1.0.
|
||||
static void CalcEvIndices(ALfloat ev, ALuint *evidx, ALfloat *evmu)
|
||||
{
|
||||
ev = (F_PI_2 + ev) * (ELEV_COUNT-1) / F_PI;
|
||||
evidx[0] = fastf2u(ev);
|
||||
evidx[1] = minu(evidx[0] + 1, ELEV_COUNT-1);
|
||||
*evmu = ev - evidx[0];
|
||||
}
|
||||
|
||||
// Calculate the azimuth indices given the polar azimuth in radians. This
|
||||
// will return two indices between 0 and (azCount [ei] - 1) and an
|
||||
// interpolation factor between 0.0 and 1.0.
|
||||
static void CalcAzIndices(ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu)
|
||||
{
|
||||
az = (F_PI*2.0f + az) * azCount[evidx] / (F_PI*2.0f);
|
||||
azidx[0] = fastf2u(az) % azCount[evidx];
|
||||
azidx[1] = (azidx[0] + 1) % azCount[evidx];
|
||||
*azmu = az - aluFloor(az);
|
||||
}
|
||||
|
||||
// Calculates the normalized HRTF transition factor (delta) from the changes
|
||||
// in gain and listener to source angle between updates. The result is a
|
||||
// normalized delta factor than can be used to calculate moving HRIR stepping
|
||||
// values.
|
||||
ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
|
||||
{
|
||||
ALfloat gainChange, angleChange, change;
|
||||
|
||||
// Calculate the normalized dB gain change.
|
||||
newGain = maxf(newGain, 0.0001f);
|
||||
oldGain = maxf(oldGain, 0.0001f);
|
||||
gainChange = aluFabs(aluLog10(newGain / oldGain) / aluLog10(0.0001f));
|
||||
|
||||
// Calculate the normalized listener to source angle change when there is
|
||||
// enough gain to notice it.
|
||||
angleChange = 0.0f;
|
||||
if(gainChange > 0.0001f || newGain > 0.0001f)
|
||||
{
|
||||
// No angle change when the directions are equal or degenerate (when
|
||||
// both have zero length).
|
||||
if(newdir[0]-olddir[0] || newdir[1]-olddir[1] || newdir[2]-olddir[2])
|
||||
angleChange = aluAcos(olddir[0]*newdir[0] +
|
||||
olddir[1]*newdir[1] +
|
||||
olddir[2]*newdir[2]) / F_PI;
|
||||
|
||||
}
|
||||
|
||||
// Use the largest of the two changes for the delta factor, and apply a
|
||||
// significance shaping function to it.
|
||||
change = maxf(angleChange, gainChange) * 2.0f;
|
||||
return minf(change, 1.0f);
|
||||
}
|
||||
|
||||
// Calculates static HRIR coefficients and delays for the given polar
|
||||
// elevation and azimuth in radians. Linear interpolation is used to
|
||||
// increase the apparent resolution of the HRIR dataset. The coefficients
|
||||
// are also normalized and attenuated by the specified gain.
|
||||
void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
|
||||
{
|
||||
ALuint evidx[2], azidx[2];
|
||||
ALfloat mu[3];
|
||||
ALuint lidx[4], ridx[4];
|
||||
ALuint i;
|
||||
|
||||
// Claculate elevation indices and interpolation factor.
|
||||
CalcEvIndices(elevation, evidx, &mu[2]);
|
||||
|
||||
// Calculate azimuth indices and interpolation factor for the first
|
||||
// elevation.
|
||||
CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]);
|
||||
|
||||
// Calculate the first set of linear HRIR indices for left and right
|
||||
// channels.
|
||||
lidx[0] = evOffset[evidx[0]] + azidx[0];
|
||||
lidx[1] = evOffset[evidx[0]] + azidx[1];
|
||||
ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]);
|
||||
ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]);
|
||||
|
||||
// Calculate azimuth indices and interpolation factor for the second
|
||||
// elevation.
|
||||
CalcAzIndices(evidx[1], azimuth, azidx, &mu[1]);
|
||||
|
||||
// Calculate the second set of linear HRIR indices for left and right
|
||||
// channels.
|
||||
lidx[2] = evOffset[evidx[1]] + azidx[0];
|
||||
lidx[3] = evOffset[evidx[1]] + azidx[1];
|
||||
ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]);
|
||||
ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]);
|
||||
|
||||
// Calculate the normalized and attenuated HRIR coefficients using linear
|
||||
// interpolation when there is enough gain to warrant it. Zero the
|
||||
// coefficients if gain is too low.
|
||||
if(gain > 0.0001f)
|
||||
{
|
||||
gain *= 1.0f/32767.0f;
|
||||
for(i = 0;i < HRIR_LENGTH;i++)
|
||||
{
|
||||
coeffs[i][0] = lerp(lerp(Hrtf->coeffs[lidx[0]][i], Hrtf->coeffs[lidx[1]][i], mu[0]),
|
||||
lerp(Hrtf->coeffs[lidx[2]][i], Hrtf->coeffs[lidx[3]][i], mu[1]),
|
||||
mu[2]) * gain;
|
||||
coeffs[i][1] = lerp(lerp(Hrtf->coeffs[ridx[0]][i], Hrtf->coeffs[ridx[1]][i], mu[0]),
|
||||
lerp(Hrtf->coeffs[ridx[2]][i], Hrtf->coeffs[ridx[3]][i], mu[1]),
|
||||
mu[2]) * gain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0;i < HRIR_LENGTH;i++)
|
||||
{
|
||||
coeffs[i][0] = 0.0f;
|
||||
coeffs[i][1] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the HRIR delays using linear interpolation.
|
||||
delays[0] = fastf2u(lerp(lerp(Hrtf->delays[lidx[0]], Hrtf->delays[lidx[1]], mu[0]),
|
||||
lerp(Hrtf->delays[lidx[2]], Hrtf->delays[lidx[3]], mu[1]),
|
||||
mu[2]) * 65536.0f);
|
||||
delays[1] = fastf2u(lerp(lerp(Hrtf->delays[ridx[0]], Hrtf->delays[ridx[1]], mu[0]),
|
||||
lerp(Hrtf->delays[ridx[2]], Hrtf->delays[ridx[3]], mu[1]),
|
||||
mu[2]) * 65536.0f);
|
||||
}
|
||||
|
||||
// Calculates the moving HRIR target coefficients, target delays, and
|
||||
// stepping values for the given polar elevation and azimuth in radians.
|
||||
// Linear interpolation is used to increase the apparent resolution of the
|
||||
// HRIR dataset. The coefficients are also normalized and attenuated by the
|
||||
// specified gain. Stepping resolution and count is determined using the
|
||||
// given delta factor between 0.0 and 1.0.
|
||||
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)
|
||||
{
|
||||
ALuint evidx[2], azidx[2];
|
||||
ALuint lidx[4], ridx[4];
|
||||
ALfloat left, right;
|
||||
ALfloat mu[3];
|
||||
ALfloat step;
|
||||
ALuint i;
|
||||
|
||||
// Claculate elevation indices and interpolation factor.
|
||||
CalcEvIndices(elevation, evidx, &mu[2]);
|
||||
|
||||
// Calculate azimuth indices and interpolation factor for the first
|
||||
// elevation.
|
||||
CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]);
|
||||
|
||||
// Calculate the first set of linear HRIR indices for left and right
|
||||
// channels.
|
||||
lidx[0] = evOffset[evidx[0]] + azidx[0];
|
||||
lidx[1] = evOffset[evidx[0]] + azidx[1];
|
||||
ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]);
|
||||
ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]);
|
||||
|
||||
// Calculate azimuth indices and interpolation factor for the second
|
||||
// elevation.
|
||||
CalcAzIndices(evidx[1], azimuth, azidx, &mu[1]);
|
||||
|
||||
// Calculate the second set of linear HRIR indices for left and right
|
||||
// channels.
|
||||
lidx[2] = evOffset[evidx[1]] + azidx[0];
|
||||
lidx[3] = evOffset[evidx[1]] + azidx[1];
|
||||
ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]);
|
||||
ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]);
|
||||
|
||||
// Calculate the stepping parameters.
|
||||
delta = maxf(aluFloor(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
|
||||
step = 1.0f / delta;
|
||||
|
||||
// Calculate the normalized and attenuated target HRIR coefficients using
|
||||
// linear interpolation when there is enough gain to warrant it. Zero
|
||||
// the target coefficients if gain is too low. Then calculate the
|
||||
// coefficient stepping values using the target and previous running
|
||||
// coefficients.
|
||||
if(gain > 0.0001f)
|
||||
{
|
||||
gain *= 1.0f/32767.0f;
|
||||
for(i = 0;i < HRIR_LENGTH;i++)
|
||||
{
|
||||
left = coeffs[i][0] - (coeffStep[i][0] * counter);
|
||||
right = coeffs[i][1] - (coeffStep[i][1] * counter);
|
||||
|
||||
coeffs[i][0] = lerp(lerp(Hrtf->coeffs[lidx[0]][i], Hrtf->coeffs[lidx[1]][i], mu[0]),
|
||||
lerp(Hrtf->coeffs[lidx[2]][i], Hrtf->coeffs[lidx[3]][i], mu[1]),
|
||||
mu[2]) * gain;
|
||||
coeffs[i][1] = lerp(lerp(Hrtf->coeffs[ridx[0]][i], Hrtf->coeffs[ridx[1]][i], mu[0]),
|
||||
lerp(Hrtf->coeffs[ridx[2]][i], Hrtf->coeffs[ridx[3]][i], mu[1]),
|
||||
mu[2]) * gain;
|
||||
|
||||
coeffStep[i][0] = step * (coeffs[i][0] - left);
|
||||
coeffStep[i][1] = step * (coeffs[i][1] - right);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0;i < HRIR_LENGTH;i++)
|
||||
{
|
||||
left = coeffs[i][0] - (coeffStep[i][0] * counter);
|
||||
right = coeffs[i][1] - (coeffStep[i][1] * counter);
|
||||
|
||||
coeffs[i][0] = 0.0f;
|
||||
coeffs[i][1] = 0.0f;
|
||||
|
||||
coeffStep[i][0] = step * -left;
|
||||
coeffStep[i][1] = step * -right;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the HRIR delays using linear interpolation. Then calculate
|
||||
// the delay stepping values using the target and previous running
|
||||
// delays.
|
||||
left = (ALfloat)(delays[0] - (delayStep[0] * counter));
|
||||
right = (ALfloat)(delays[1] - (delayStep[1] * counter));
|
||||
|
||||
delays[0] = fastf2u(lerp(lerp(Hrtf->delays[lidx[0]], Hrtf->delays[lidx[1]], mu[0]),
|
||||
lerp(Hrtf->delays[lidx[2]], Hrtf->delays[lidx[3]], mu[1]),
|
||||
mu[2]) * 65536.0f);
|
||||
delays[1] = fastf2u(lerp(lerp(Hrtf->delays[ridx[0]], Hrtf->delays[ridx[1]], mu[0]),
|
||||
lerp(Hrtf->delays[ridx[2]], Hrtf->delays[ridx[3]], mu[1]),
|
||||
mu[2]) * 65536.0f);
|
||||
|
||||
delayStep[0] = fastf2i(step * (delays[0] - left));
|
||||
delayStep[1] = fastf2i(step * (delays[1] - right));
|
||||
|
||||
// The stepping count is the number of samples necessary for the HRIR to
|
||||
// complete its transition. The mixer will only apply stepping for this
|
||||
// many samples.
|
||||
return fastf2u(delta);
|
||||
}
|
||||
|
||||
const struct Hrtf *GetHrtf(ALCdevice *device)
|
||||
{
|
||||
if(device->FmtChans == DevFmtStereo)
|
||||
{
|
||||
ALuint i;
|
||||
for(i = 0;i < NumLoadedHrtfs;i++)
|
||||
{
|
||||
if(device->Frequency == LoadedHrtfs[i].sampleRate)
|
||||
return &LoadedHrtfs[i];
|
||||
}
|
||||
if(device->Frequency == DefaultHrtf.sampleRate)
|
||||
return &DefaultHrtf;
|
||||
}
|
||||
ERR("Incompatible format: %s %uhz\n",
|
||||
DevFmtChannelsString(device->FmtChans), device->Frequency);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void InitHrtf(void)
|
||||
{
|
||||
char *fnamelist=NULL, *next=NULL;
|
||||
const char *val;
|
||||
|
||||
if(ConfigValueStr(NULL, "hrtf_tables", &val))
|
||||
next = fnamelist = strdup(val);
|
||||
while(next && *next)
|
||||
{
|
||||
const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
|
||||
struct Hrtf newdata;
|
||||
ALboolean failed;
|
||||
ALchar magic[9];
|
||||
ALsizei i, j;
|
||||
char *fname;
|
||||
FILE *f;
|
||||
|
||||
fname = next;
|
||||
next = strchr(fname, ',');
|
||||
if(next)
|
||||
{
|
||||
while(next != fname)
|
||||
{
|
||||
next--;
|
||||
if(!isspace(*next))
|
||||
{
|
||||
*(next++) = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(isspace(*next) || *next == ',')
|
||||
next++;
|
||||
}
|
||||
|
||||
if(!fname[0])
|
||||
continue;
|
||||
TRACE("Loading %s\n", fname);
|
||||
f = fopen(fname, "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
ERR("Could not open %s\n", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
failed = AL_FALSE;
|
||||
if(fread(magic, 1, sizeof(magicMarker), f) != sizeof(magicMarker))
|
||||
{
|
||||
ERR("Failed to read magic marker\n");
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
else if(memcmp(magic, magicMarker, sizeof(magicMarker)) != 0)
|
||||
{
|
||||
magic[8] = 0;
|
||||
ERR("Invalid magic marker: \"%s\"\n", magic);
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
|
||||
if(!failed)
|
||||
{
|
||||
ALushort hrirCount, hrirSize;
|
||||
ALubyte evCount;
|
||||
|
||||
newdata.sampleRate = fgetc(f);
|
||||
newdata.sampleRate |= fgetc(f)<<8;
|
||||
newdata.sampleRate |= fgetc(f)<<16;
|
||||
newdata.sampleRate |= fgetc(f)<<24;
|
||||
|
||||
hrirCount = fgetc(f);
|
||||
hrirCount |= fgetc(f)<<8;
|
||||
|
||||
hrirSize = fgetc(f);
|
||||
hrirSize |= fgetc(f)<<8;
|
||||
|
||||
evCount = fgetc(f);
|
||||
|
||||
if(hrirCount != HRIR_COUNT || hrirSize != HRIR_LENGTH || evCount != ELEV_COUNT)
|
||||
{
|
||||
ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n",
|
||||
hrirCount, HRIR_COUNT, hrirSize, HRIR_LENGTH, evCount, ELEV_COUNT);
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(!failed)
|
||||
{
|
||||
for(i = 0;i < ELEV_COUNT;i++)
|
||||
{
|
||||
ALushort offset;
|
||||
offset = fgetc(f);
|
||||
offset |= fgetc(f)<<8;
|
||||
if(offset != evOffset[i])
|
||||
{
|
||||
ERR("Unsupported evOffset[%d] value: %d (%d)\n", i, offset, evOffset[i]);
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!failed)
|
||||
{
|
||||
for(i = 0;i < HRIR_COUNT;i++)
|
||||
{
|
||||
for(j = 0;j < HRIR_LENGTH;j++)
|
||||
{
|
||||
ALshort coeff;
|
||||
coeff = fgetc(f);
|
||||
coeff |= fgetc(f)<<8;
|
||||
newdata.coeffs[i][j] = coeff;
|
||||
}
|
||||
}
|
||||
for(i = 0;i < HRIR_COUNT;i++)
|
||||
{
|
||||
ALubyte delay;
|
||||
delay = fgetc(f);
|
||||
newdata.delays[i] = delay;
|
||||
if(delay > maxDelay)
|
||||
{
|
||||
ERR("Invalid delay[%d]: %d (%d)\n", i, delay, maxDelay);
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(feof(f))
|
||||
{
|
||||
ERR("Premature end of data\n");
|
||||
failed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
|
||||
if(!failed)
|
||||
{
|
||||
void *temp = realloc(LoadedHrtfs, (NumLoadedHrtfs+1)*sizeof(LoadedHrtfs[0]));
|
||||
if(temp != NULL)
|
||||
{
|
||||
LoadedHrtfs = temp;
|
||||
TRACE("Loaded HRTF support for format: %s %uhz\n",
|
||||
DevFmtChannelsString(DevFmtStereo), newdata.sampleRate);
|
||||
LoadedHrtfs[NumLoadedHrtfs++] = newdata;
|
||||
}
|
||||
}
|
||||
else
|
||||
ERR("Failed to load %s\n", fname);
|
||||
}
|
||||
free(fnamelist);
|
||||
fnamelist = NULL;
|
||||
}
|
||||
|
||||
void FreeHrtf(void)
|
||||
{
|
||||
NumLoadedHrtfs = 0;
|
||||
free(LoadedHrtfs);
|
||||
LoadedHrtfs = NULL;
|
||||
}
|
||||
@@ -0,0 +1,839 @@
|
||||
/* This data is Copyright 1994 by the MIT Media Laboratory. It is provided free
|
||||
* with no restrictions on use, provided the authors are cited when the data is
|
||||
* used in any research or commercial application. */
|
||||
/* Bill Gardner <billg@media.mit.edu> and Keith Martin <kdm@media.mit.edu> */
|
||||
|
||||
/* HRIR Coefficients */
|
||||
{
|
||||
{ +5817, +7833, +3253, +2795, +1080, +403, +948, -690, -2207, -1110, +658, -33, -481, -949, -839, -287, -146, -103, +7, -47, -269, -105, -316, -221, -304, -497, -373, -231, -114, -14, +66, -62, },
|
||||
{ +6586, +8107, +2781, +3167, +1095, +99, +922, -641, -2255, -1457, +602, +170, -469, -781, -818, -773, -258, +8, -111, -125, -368, -216, -345, -265, -298, -447, -408, -158, -22, +0, +63, -96, },
|
||||
{ +5986, +7570, +2713, +2756, +1080, +403, +921, -758, -2112, -1067, +565, -93, -431, -738, -604, -361, -238, +10, +63, -88, -302, -101, -306, -243, -358, -488, -341, -224, -98, -1, +79, -55, },
|
||||
{ +5571, +7005, +2499, +2549, +974, +438, +959, -688, -1966, -793, +755, -35, -305, -631, -545, -165, -118, -72, +26, -36, -228, -36, -253, -158, -261, -436, -311, -197, -85, +11, +82, -47, },
|
||||
{ +5472, +6865, +2460, +2524, +978, +492, +1057, -561, -1857, -706, +813, -3, -353, -739, -587, -120, -98, -94, +21, -32, -228, -31, -232, -119, -204, -399, -293, -197, -124, -45, +34, -81, },
|
||||
{ +5627, +7081, +2487, +2449, +858, +396, +981, -676, -2051, -899, +820, +82, -332, -774, -643, -127, -26, -14, +72, +27, -183, -16, -234, -142, -240, -422, -289, -151, -36, +63, +108, -65, },
|
||||
{ +6172, +7677, +2541, +2564, +874, +397, +966, -927, -2421, -1117, +905, +38, -545, -990, -785, -200, -66, -60, +50, +17, -244, -35, -244, -146, -246, -433, -290, -139, -42, +40, +108, -37, },
|
||||
{ +6521, +8320, +2827, +2690, +909, +230, +917, -1084, -2525, -1115, +652, -122, -480, -974, -823, -289, -150, +21, +73, -58, -296, -90, -299, -198, -317, -480, -327, -206, -64, +25, +103, -47, },
|
||||
{ +6956, +8505, +2738, +3040, +1131, +209, +719, -1389, -2419, -516, +530, -857, -697, -801, -443, -77, -328, -117, +128, -70, -281, -49, -356, -233, -419, -579, -344, -271, -169, -16, +76, -98, },
|
||||
{ +7928, +9215, +2040, +2470, +595, +264, +1348, -1308, -2698, -258, +1302, -836, -1179, -1210, -483, +125, -403, -370, +81, -61, -416, -45, -378, -208, -426, -708, -383, -223, -150, -20, +82, -119, },
|
||||
{ +8205, +9593, +2241, +2306, +197, +241, +1480, -1080, -3081, -704, +1757, -153, -1144, -1906, -912, +311, -4, -441, -129, -99, -476, -104, -467, -207, -379, -660, -412, -194, -106, -31, +48, -172, },
|
||||
{ +7822, +9388, +3008, +2690, +349, +155, +1066, -976, -3351, -1396, +1366, +202, -165, -1794, -1686, +63, +209, -110, -81, -164, -375, -114, -487, -174, -394, -771, -456, -312, -109, +27, +100, -71, },
|
||||
{ +7342, +9001, +2833, +2968, +859, +118, +830, -1009, -2609, -1583, +1030, +177, -566, -888, -1564, -882, +55, +78, +62, +48, -275, -224, -531, -354, -242, -534, -487, -241, -107, +31, +92, -76, },
|
||||
{ +7420, +8277, +2251, +3723, +1049, -308, +945, -518, -2311, -1945, +592, +496, -502, -565, -848, -1420, -265, +189, -293, -192, -468, -339, -342, -319, -275, -379, -474, -58, +77, -10, +55, -134, },
|
||||
{ +6584, +7746, +2495, +3374, +1000, -52, +897, -756, -2030, -1406, +280, +34, -398, -477, -456, -856, -571, +107, +104, -158, -435, -199, -286, -253, -345, -425, -316, -178, -107, -66, +74, -62, },
|
||||
{ +6049, +7215, +2251, +2809, +1129, +395, +858, -790, -1953, -1091, +399, -101, -343, -474, -371, -537, -334, +183, +103, -155, -328, -94, -287, -281, -418, -457, -307, -226, -82, +10, +91, -45, },
|
||||
{ +5611, +6654, +2026, +2614, +1122, +421, +846, -730, -1795, -787, +486, -181, -199, -331, -331, -290, -184, +57, +64, -94, -264, -59, -241, -160, -276, -381, -321, -242, -63, +33, +98, -44, },
|
||||
{ +5099, +6036, +1921, +2401, +945, +508, +937, -640, -1638, -506, +755, -23, -74, -266, -268, -108, -114, -39, +41, -26, -172, +33, -185, -102, -220, -366, -254, -174, -58, +33, +94, -28, },
|
||||
{ +4863, +5622, +1644, +2154, +818, +547, +1098, -307, -1280, -210, +982, +96, -111, -376, -319, -58, -43, -22, +51, -10, -188, -3, -174, -47, -165, -316, -201, -114, -14, +20, +16, -134, },
|
||||
{ +4874, +5742, +1871, +2357, +961, +630, +1147, -376, -1424, -337, +863, +34, -193, -499, -332, +8, -81, -97, +36, -13, -175, +46, -137, -17, -102, -297, -226, -178, -147, -83, +1, -91, },
|
||||
{ +4960, +5827, +1797, +2194, +842, +622, +1162, -376, -1492, -421, +910, +56, -246, -568, -430, +32, +120, +83, +106, +18, -182, -19, -208, -85, -152, -240, -94, -64, -84, -82, -30, -123, },
|
||||
{ +5228, +6194, +1872, +2175, +707, +445, +1001, -617, -1837, -723, +933, +227, -167, -586, -451, +10, +86, +68, +127, +106, -88, +66, -146, -70, -175, -339, -208, -74, +41, +139, +139, -76, },
|
||||
{ +5697, +6722, +1953, +2283, +727, +469, +969, -882, -2258, -1037, +972, +175, -413, -806, -593, -28, +130, +87, +177, +163, -115, +43, -180, -84, -142, -297, -156, -24, +4, +49, +85, -29, },
|
||||
{ +6473, +7408, +1826, +2417, +711, +442, +966, -1188, -2613, -1118, +1193, +107, -644, -1020, -716, -117, +16, -26, +92, +89, -223, +39, -164, -76, -190, -362, -208, -46, +24, +86, +145, -12, },
|
||||
{ +7101, +8208, +1841, +2445, +711, +357, +985, -1505, -2879, -1121, +1181, +70, -658, -1173, -814, -168, -29, +29, +47, +36, -265, -40, -293, -166, -283, -429, -229, -63, +43, +81, +160, -20, },
|
||||
{ +7271, +8783, +2298, +2617, +755, +48, +900, -1532, -2806, -1083, +615, -189, -449, -1001, -807, -311, -150, +184, +122, -88, -322, -71, -273, -179, -335, -451, -278, -188, -9, +60, +138, -32, },
|
||||
{ +7519, +8972, +2519, +3099, +1077, -70, +527, -1818, -2665, -568, +208, -889, -424, -657, -398, -291, -483, +67, +222, -56, -219, -19, -307, -204, -436, -529, -306, -304, -126, +27, +128, -48, },
|
||||
{ +8267, +9086, +2039, +3441, +1167, -66, +449, -2175, -2478, +261, +170, -1844, -741, -537, +19, +68, -620, -86, +289, -131, -285, +19, -414, -244, -560, -647, -289, -330, -230, -5, +89, -141, },
|
||||
{ +9334, +10020, +1039, +2681, +800, -36, +1253, -2153, -2906, +675, +921, -2082, -1336, -748, +118, +362, -708, -352, +305, -89, -430, +16, -461, -267, -609, -817, -292, -288, -287, -70, +134, -107, },
|
||||
{ +10490, +10443, +234, +2319, +106, +215, +1880, -2162, -3146, +928, +1870, -2011, -1861, -1339, +44, +548, -846, -647, +252, -93, -597, +65, -464, -180, -581, -943, -344, -209, -200, -20, +104, -191, },
|
||||
{ +11090, +10859, +176, +1929, -492, +415, +2257, -1899, -3660, +617, +2693, -1436, -2083, -2245, -339, +944, -576, -854, +49, -173, -603, +64, -607, -194, -525, -910, -310, -113, -162, +10, +55, -268, },
|
||||
{ +11123, +11231, +589, +1885, -762, +272, +2193, -1677, -4087, +10, +3036, -569, -1972, -2950, -747, +1099, +20, -922, -216, -122, -721, -53, -651, -153, -474, -845, -423, -135, -107, -57, +30, -304, },
|
||||
{ +10803, +11222, +1474, +2265, -883, +91, +1845, -1667, -4470, -728, +2793, +190, -972, -3366, -1480, +1091, +471, -617, -486, -175, -639, -113, -591, -51, -507, -934, -502, -309, -106, -118, +53, -177, },
|
||||
{ +10246, +10868, +2402, +2554, -531, +31, +1268, -1323, -4728, -1500, +2335, +359, +174, -2966, -2559, +743, +585, -219, -198, -287, -474, -103, -696, -72, -517, -1094, -493, -391, -81, +78, +133, -87, },
|
||||
{ +9638, +10459, +2554, +3136, -109, -170, +1213, -1306, -4339, -2094, +2099, +264, +202, -1798, -3312, -170, +781, +126, +63, -260, -424, +20, -759, -504, -338, -983, -510, -236, -85, +153, +125, -96, },
|
||||
{ +9150, +10114, +2114, +3243, +563, -199, +731, -1335, -3018, -2131, +1610, +397, -733, -785, -2524, -1463, +491, +266, +80, +156, -304, -383, -768, -471, -118, -592, -631, -225, -95, +87, +113, -96, },
|
||||
{ +8454, +9243, +2047, +3497, +881, -249, +701, -1042, -2617, -2062, +1294, +712, -942, -676, -1397, -1797, -57, +250, -231, -14, -250, -237, -521, -454, -179, -387, -649, -192, -30, +13, +161, -121, },
|
||||
{ +8323, +8323, +1685, +4494, +893, -823, +1049, -315, -2397, -2598, +672, +957, -622, -284, -950, -2240, -109, +425, -567, -229, -570, -475, -300, -391, -228, -295, -579, +83, +176, -48, +44, -175, },
|
||||
{ +7274, +7900, +2262, +4107, +785, -714, +918, -662, -1986, -1894, +51, +378, -372, -108, -420, -1664, -750, +303, +73, -176, -577, -344, -248, -256, -255, -331, -406, -129, -13, -101, +50, -88, },
|
||||
{ +6560, +7256, +2146, +3528, +960, -9, +858, -751, -1783, -1572, +54, +101, -313, -181, -229, -1133, -648, +400, +128, -265, -444, -160, -232, -331, -449, -399, -265, -206, -153, -62, +116, -28, },
|
||||
{ +5980, +6790, +1905, +2935, +1217, +364, +757, -764, -1730, -1213, +165, -24, -228, -158, -154, -831, -410, +428, +110, -247, -340, -86, -256, -338, -480, -399, -278, -238, -61, +18, +103, -30, },
|
||||
{ +5480, +6206, +1692, +2736, +1300, +391, +709, -692, -1565, -861, +226, -147, -68, -24, -127, -550, -217, +281, +49, -181, -257, -43, -247, -249, -345, -298, -274, -270, -50, +56, +119, -43, },
|
||||
{ +4953, +5620, +1632, +2478, +1119, +519, +800, -639, -1430, -598, +380, -73, +141, +70, -109, -295, -151, +126, +65, -105, -195, +54, -97, -104, -271, -314, -265, -208, -14, +48, +99, +5, },
|
||||
{ +4358, +4972, +1588, +2310, +986, +595, +869, -526, -1223, -277, +652, +34, +216, +141, -22, -120, -122, +1, +49, -14, -101, +99, -108, -54, -180, -284, -207, -160, -31, +53, +104, -2, },
|
||||
{ +4049, +4526, +1367, +2016, +774, +619, +1057, -193, -943, +8, +975, +238, +224, +73, -43, -96, -105, -16, +104, +54, -140, +64, -50, +12, -174, -276, -142, -78, +11, +66, +70, -116, },
|
||||
{ +3893, +4241, +1180, +1972, +964, +806, +1165, +33, -630, +212, +995, +139, -10, -165, -98, +59, +41, +7, +5, -42, -115, +70, -77, +64, -30, -184, -140, -90, -15, -39, -72, -166, },
|
||||
{ +3974, +4515, +1563, +2245, +1024, +802, +1202, -117, -913, -34, +802, +109, -1, -233, -83, +92, -89, -104, +51, +9, -107, +121, -30, +82, +5, -192, -173, -173, -183, -127, -31, -91, },
|
||||
{ +4054, +4585, +1487, +2101, +966, +877, +1249, -118, -989, -177, +776, +97, -55, -258, -131, +135, +150, +93, +56, -19, -114, +43, -129, +22, -1, -45, +2, -139, -203, -156, -63, -102, },
|
||||
{ +4259, +4784, +1375, +1894, +699, +649, +1161, -136, -1098, -231, +956, +281, +11, -419, -371, +109, +241, +228, +268, +110, -100, +71, -147, -93, -92, -157, -42, +95, +87, -12, -90, -205, },
|
||||
{ +4579, +5216, +1470, +1933, +626, +538, +991, -498, -1568, -608, +1002, +425, +4, -387, -268, +119, +196, +143, +174, +193, +16, +138, -48, -8, -110, -248, -134, +1, +116, +214, +157, -94, },
|
||||
{ +5066, +5749, +1521, +2044, +640, +538, +926, -811, -2022, -949, +1051, +371, -252, -591, -377, +160, +302, +178, +234, +199, -60, +136, -88, +2, -40, -201, -104, +47, +67, +67, +148, +54, },
|
||||
{ +5824, +6357, +1417, +2188, +604, +584, +938, -1093, -2439, -1140, +1270, +283, -550, -828, -547, +25, +209, +96, +231, +241, -75, +150, -72, -37, -72, -173, -85, +78, +65, +65, +106, -26, },
|
||||
{ +6705, +7034, +1139, +2353, +584, +531, +931, -1467, -2777, -1121, +1528, +169, -787, -1030, -630, -42, +104, -4, +133, +171, -212, +119, -74, -14, -133, -284, -130, +49, +82, +127, +179, +14, },
|
||||
{ +7494, +7838, +930, +2406, +628, +447, +939, -1854, -3086, -1058, +1655, +110, -889, -1206, -690, -58, +26, -36, +86, +157, -264, +21, -209, -75, -225, -353, -152, +18, +88, +139, +234, +25, },
|
||||
{ +7942, +8659, +1161, +2413, +549, +251, +1028, -2079, -3182, -1091, +1258, +58, -663, -1281, -862, -154, +30, +213, +47, +25, -289, -45, -300, -173, -306, -391, -167, -32, +123, +117, +202, -22, },
|
||||
{ +8068, +9218, +1660, +2593, +617, -151, +900, -2038, -3036, -1021, +535, -219, -391, -1036, -790, -354, -141, +391, +141, -138, -345, -47, -238, -167, -360, -407, -230, -180, +55, +90, +173, -18, },
|
||||
{ +8265, +9463, +2020, +3087, +909, -384, +486, -2292, -2858, -489, -42, -958, -218, -589, -423, -435, -531, +296, +255, -79, -195, -39, -305, -178, -439, -471, -257, -338, -66, +74, +175, -25, },
|
||||
{ +8828, +9479, +1858, +3692, +1200, -444, +108, -2595, -2598, +225, -443, -1837, -211, -338, +130, -297, -878, +233, +403, -155, -160, +68, -348, -198, -618, -577, -252, -401, -165, +50, +123, -106, },
|
||||
{ +9769, +9532, +1154, +4053, +1153, -433, +152, -3044, -2341, +1209, -501, -2958, -549, -180, +526, +122, -1023, +24, +484, -243, -273, +98, -497, -249, -730, -696, -208, -420, -294, +24, +104, -194, },
|
||||
{ +10963, +10314, -18, +3480, +928, -378, +839, -3146, -2679, +1815, +181, -3477, -1184, -280, +767, +456, -1173, -196, +557, -284, -445, +171, -561, -316, -811, -844, -191, -379, -352, -44, +133, -183, },
|
||||
{ +12437, +11094, -1445, +2785, +310, -110, +1926, -3295, -3171, +2280, +1217, -3589, -1908, -710, +881, +724, -1458, -605, +653, -147, -678, +163, -557, -237, -805, -1040, -224, -349, -355, -12, +190, -216, },
|
||||
{ +13565, +11394, -2213, +2503, -423, +267, +2542, -3317, -3490, +2485, +2267, -3594, -2432, -1318, +735, +938, -1508, -888, +536, -170, -812, +241, -591, -131, -780, -1195, -241, -201, -267, -8, +131, -283, },
|
||||
{ +14365, +11785, -2502, +2065, -1128, +690, +3071, -3145, -4082, +2294, +3294, -3126, -2782, -2332, +449, +1450, -1337, -1152, +323, -232, -796, +274, -707, -133, -760, -1160, -175, -77, -224, +1, +81, -344, },
|
||||
{ +14713, +12188, -2245, +1714, -1545, +697, +3166, -2769, -4728, +1796, +4066, -2366, -3022, -3257, +104, +1860, -844, -1416, +119, -254, -847, +177, -909, -97, -642, -1112, -239, -41, -190, +38, +3, -445, },
|
||||
{ +14645, +12610, -1772, +1687, -1818, +544, +3067, -2552, -5197, +1109, +4450, -1369, -2921, -4051, -284, +2048, -140, -1537, -208, -123, -1018, +64, -886, -45, -602, -1050, -397, -58, -122, -90, +12, -460, },
|
||||
{ +14311, +12744, -823, +2013, -2087, +348, +2751, -2573, -5594, +298, +4380, -359, -2003, -4793, -1003, +2181, +482, -1298, -654, -93, -995, -9, -758, +71, -678, -1141, -461, -235, -94, -220, +50, -343, },
|
||||
{ +13776, +12639, +346, +2236, -2014, +116, +2251, -2236, -6147, -504, +3963, +239, -615, -5033, -2049, +2178, +726, -876, -698, -265, -701, -87, -865, +185, -648, -1310, -522, -464, -75, -87, +92, -171, },
|
||||
{ +13149, +12169, +1402, +2459, -1565, +84, +1536, -1759, -6362, -1341, +3564, +365, +555, -4522, -3382, +1810, +905, -453, -324, -409, -562, -71, -953, +103, -691, -1468, -465, -480, -26, +135, +160, -111, },
|
||||
{ +12380, +11681, +1885, +3275, -1333, -131, +1419, -1701, -5961, -2232, +3308, +405, +924, -3382, -4610, +1021, +1316, -94, -127, -370, -464, +43, -1042, -366, -474, -1380, -504, -384, +12, +312, +117, -135, },
|
||||
{ +11903, +11393, +1499, +3646, -589, -712, +1361, -1471, -5102, -2585, +2953, +277, +167, -1768, -4726, -478, +1438, +247, +197, -198, -524, -85, -1094, -602, -205, -1156, -495, -151, -147, +245, +126, -155, },
|
||||
{ +11277, +11106, +1068, +3696, +162, -535, +662, -1668, -3438, -2767, +2450, +580, -999, -611, -3766, -1971, +1197, +402, +51, +288, -364, -586, -1018, -564, +72, -690, -805, -170, -83, +153, +125, -123, },
|
||||
{ +10588, +10248, +1041, +3990, +549, -596, +503, -1508, -2940, -2531, +2104, +852, -1356, -383, -2481, -2696, +537, +474, -251, +251, -199, -459, -926, -574, +197, -420, -1013, -187, +29, +54, +181, -131, },
|
||||
{ +9521, +9264, +1317, +4316, +722, -767, +764, -816, -2661, -2833, +1508, +1326, -1203, -394, -1458, -2679, +165, +492, -606, -94, -331, -324, -381, -536, -231, -294, -717, -35, +53, -16, +190, -183, },
|
||||
{ +9295, +8224, +1109, +5503, +566, -1438, +1272, -36, -2542, -3436, +897, +1558, -877, +95, -1150, -3243, +276, +686, -962, -210, -683, -628, -208, -496, -150, -199, -735, +279, +265, -118, +39, -219, },
|
||||
{ +7955, +7915, +2062, +4941, +392, -1429, +1053, -497, -1939, -2532, -124, +882, -416, +352, -483, -2672, -726, +593, -30, -164, -732, -489, -159, -285, -145, -245, -559, -60, +99, -150, +30, -106, },
|
||||
{ +7031, +7277, +2031, +4336, +697, -646, +955, -623, -1641, -2182, -233, +535, -317, +229, -165, -1960, -826, +699, +101, -378, -580, -260, -151, -369, -398, -280, -286, -150, -143, -139, +125, -38, },
|
||||
{ +6295, +6730, +1892, +3559, +1033, +63, +744, -685, -1521, -1804, -171, +306, -225, +149, +4, -1512, -648, +773, +80, -370, -396, -159, -189, -414, -539, -344, -273, -228, -102, -44, +122, +2, },
|
||||
{ +5567, +6186, +1652, +2969, +1443, +344, +573, -641, -1422, -1343, -105, +121, -57, +247, +28, -1174, -348, +731, +56, -360, -317, -47, -217, -426, -532, -288, -251, -274, -18, +48, +118, -19, },
|
||||
{ +4996, +5539, +1497, +2838, +1501, +319, +538, -541, -1215, -962, -91, -26, +159, +383, +48, -835, -191, +492, -4, -250, -216, -31, -205, -289, -352, -182, -273, -311, -10, +79, +133, -33, },
|
||||
{ +4369, +4911, +1493, +2561, +1337, +470, +618, -484, -1046, -662, +27, +2, +405, +487, +57, -528, -160, +283, +46, -156, -163, +53, -43, -114, -258, -209, -289, -247, +29, +65, +110, +22, },
|
||||
{ +3634, +4210, +1572, +2321, +1183, +650, +679, -395, -859, -352, +291, +111, +541, +545, +126, -276, -117, +132, +29, -68, -30, +169, -23, -64, -184, -195, -205, -180, +9, +60, +105, +51, },
|
||||
{ +3016, +3577, +1500, +2051, +987, +707, +858, -234, -596, +114, +631, +273, +558, +609, +229, -166, -145, -29, +96, +94, -41, +113, +28, +51, -118, -204, -138, -123, -4, +88, +117, +1, },
|
||||
{ +2776, +3142, +1225, +1761, +847, +791, +1067, +272, -238, +302, +902, +413, +488, +421, +138, -130, -62, +38, +115, +77, -79, +99, +64, +85, -110, -151, -69, -33, +59, +61, +9, -164, },
|
||||
{ +2597, +2855, +1075, +1771, +1129, +1005, +1152, +473, +68, +492, +881, +270, +197, +161, +118, +79, +88, +32, -20, -32, -27, +115, +32, +153, +68, -66, -90, -62, +9, -70, -139, -184, },
|
||||
{ +2669, +3145, +1471, +2033, +1221, +1035, +1183, +275, -243, +270, +725, +249, +159, +52, +151, +138, -51, -81, +23, -1, -18, +190, +86, +173, +118, -82, -134, -156, -186, -160, -81, -98, },
|
||||
{ +2819, +3343, +1567, +2048, +1169, +1075, +1248, +244, -402, -85, +455, +306, +297, +79, +134, +124, +55, +91, +34, -77, +10, +181, -46, +108, +219, +134, -56, -289, -273, -145, -92, -88, },
|
||||
{ +2900, +3386, +1384, +1773, +1008, +1084, +1261, +225, -495, +12, +783, +242, +37, -53, -9, +253, +383, +202, +102, +70, -62, +11, -40, +64, +31, +110, +190, -6, -190, -236, -126, -117, },
|
||||
{ +3231, +3701, +1275, +1612, +705, +788, +1133, +122, -729, -179, +937, +566, +221, -206, -199, +166, +308, +308, +335, +202, +36, +131, -62, -37, -38, -83, +43, +191, +169, +38, -106, -235, },
|
||||
{ +3635, +4205, +1339, +1662, +626, +662, +937, -299, -1254, -578, +1037, +699, +166, -176, -99, +200, +312, +211, +211, +294, +129, +195, +63, +39, -40, -148, -70, +74, +192, +288, +163, -117, },
|
||||
{ +4194, +4783, +1346, +1788, +630, +642, +840, -677, -1766, -952, +1124, +635, -123, -376, -187, +304, +462, +242, +276, +259, +18, +219, +17, +71, +61, -99, -59, +121, +125, +97, +206, +113, },
|
||||
{ +4979, +5362, +1202, +1940, +602, +719, +840, -1009, -2235, -1155, +1361, +510, -477, -624, -359, +169, +423, +212, +324, +400, +17, +168, -5, +20, +47, -58, +31, +174, +74, +79, +86, +27, },
|
||||
{ +6045, +6030, +859, +2185, +506, +725, +848, -1395, -2650, -1218, +1701, +338, -794, -842, -492, +56, +296, +67, +259, +328, -97, +236, +42, +27, -10, -99, -27, +180, +116, +105, +139, -10, },
|
||||
{ +7127, +6787, +391, +2413, +495, +620, +850, -1887, -2997, -1109, +1985, +195, -1031, -1079, -541, +28, +148, +5, +155, +227, -224, +200, +4, -1, -101, -203, -81, +123, +136, +165, +254, +85, },
|
||||
{ +8041, +7641, +54, +2482, +542, +525, +873, -2340, -3303, -988, +2101, +103, -1125, -1253, -590, +7, +85, -30, +110, +254, -288, +69, -159, -33, -202, -285, -79, +104, +146, +180, +291, +49, },
|
||||
{ +8670, +8596, +151, +2444, +429, +355, +1004, -2691, -3423, -1007, +1694, +127, -881, -1445, -767, -93, +121, +297, -11, +97, -290, +1, -294, -164, -296, -328, -78, +89, +211, +122, +240, -5, },
|
||||
{ +8845, +9339, +619, +2533, +443, -115, +1042, -2670, -3312, -1004, +882, -48, -483, -1247, -888, -243, +10, +511, +67, -76, -337, -56, -239, -164, -351, -335, -149, -114, +174, +149, +241, -25, },
|
||||
{ +8992, +9809, +1188, +2897, +625, -583, +690, -2700, -3089, -635, -11, -646, -104, -790, -618, -507, -344, +619, +168, -148, -236, -69, -262, -132, -414, -375, -196, -304, +74, +121, +206, -26, },
|
||||
{ +9299, +9977, +1439, +3466, +927, -820, +224, -3016, -2800, -12, -737, -1360, +110, -354, -169, -639, -802, +553, +363, -141, -128, +0, -287, -205, -550, -443, -225, -438, -58, +99, +221, -4, },
|
||||
{ +10058, +9879, +1163, +4263, +1177, -922, -219, -3311, -2434, +862, -1303, -2457, +248, -70, +493, -501, -1236, +540, +538, -275, -74, +119, -379, -193, -775, -553, -189, -513, -161, +91, +140, -128, },
|
||||
{ +11144, +9761, +369, +4862, +1071, -936, -203, -3855, -2065, +1997, -1565, -3828, +38, +198, +979, -90, -1513, +341, +661, -404, -156, +165, -600, -237, -878, -660, -142, -564, -301, +70, +104, -215, },
|
||||
{ +12546, +10246, -966, +4691, +927, -833, +309, -4199, -2112, +2959, -1144, -4789, -535, +243, +1329, +364, -1689, +85, +795, -505, -386, +288, -677, -309, -1025, -827, -61, -516, -419, +27, +137, -278, },
|
||||
{ +14045, +11382, -2788, +3760, +580, -650, +1686, -4408, -2934, +3566, -51, -5174, -1321, +73, +1428, +705, -1911, -307, +891, -369, -599, +281, -731, -286, -1048, -1082, -16, -454, -510, -50, +248, -211, },
|
||||
{ +15970, +11714, -4486, +3446, -223, -120, +2672, -4778, -3223, +4216, +1130, -5477, -2203, -468, +1756, +960, -2402, -712, +1105, -303, -935, +391, -711, -185, -1048, -1265, -82, -424, -432, +54, +241, -341, },
|
||||
{ +17220, +11916, -5327, +3210, -1072, +444, +3327, -4843, -3644, +4439, +2382, -5600, -2783, -1154, +1580, +1254, -2411, -1038, +941, -324, -1057, +499, -778, -47, -1032, -1459, -61, -214, -352, +22, +162, -398, },
|
||||
{ +18240, +12274, -5799, +2731, -1899, +1079, +3952, -4749, -4376, +4334, +3662, -5208, -3266, -2349, +1378, +1910, -2296, -1381, +715, -370, -1038, +545, -912, -20, -1028, -1437, +31, -67, -319, +18, +102, -464, },
|
||||
{ +18833, +12668, -5683, +2184, -2439, +1329, +4171, -4328, -5232, +3901, +4824, -4546, -3741, -3476, +1105, +2561, -1914, -1779, +533, -418, -1036, +485, -1184, +14, -859, -1412, +1, +27, -315, +91, +5, -584, },
|
||||
{ +19008, +13162, -5318, +1926, -2788, +1224, +4180, -3950, -5962, +3321, +5549, -3543, -3998, -4445, +848, +2902, -1193, -2106, +263, -305, -1180, +327, -1267, +112, -828, -1285, -169, +16, -197, +33, -71, -637, },
|
||||
{ +18737, +13681, -4618, +1963, -3145, +1044, +4007, -3789, -6476, +2407, +5985, -2289, -3707, -5492, +344, +3198, -328, -2230, -228, -74, -1401, +254, -1150, +181, -810, -1310, -322, -25, -144, -179, +21, -629, },
|
||||
{ +18348, +13822, -3468, +2221, -3496, +867, +3623, -3756, -6961, +1517, +5968, -1098, -2716, -6475, -416, +3438, +367, -2015, -778, +7, -1351, +154, -986, +288, -914, -1395, -403, -225, -85, -331, +78, -475, },
|
||||
{ +17731, +13756, -2024, +2354, -3509, +578, +3074, -3309, -7685, +628, +5586, -260, -1146, -7037, -1592, +3604, +681, -1553, -946, -177, -966, +4, -1088, +448, -897, -1594, -473, -493, -35, -196, +111, -266, },
|
||||
{ +16988, +13672, -858, +2219, -2857, +446, +2261, -2723, -8186, -143, +5173, +8, +354, -6856, -3083, +3505, +877, -1058, -660, -442, -746, +8, -1186, +419, -932, -1761, -398, -679, +86, +39, +115, -97, },
|
||||
{ +16138, +12803, +575, +2903, -2738, +274, +1624, -2112, -8167, -1458, +4911, +239, +1463, -6034, -4971, +3030, +1336, -611, -295, -547, -554, +6, -1339, +184, -852, -1914, -351, -543, +76, +333, +176, -169, },
|
||||
{ +15265, +12532, +737, +3734, -2365, -148, +1753, -2212, -7519, -2381, +4804, +154, +1395, -4336, -6360, +1992, +1942, -242, -104, -546, -503, +190, -1457, -473, -403, -1767, -438, -339, +44, +430, +96, -165, },
|
||||
{ +14708, +12215, +282, +4265, -1521, -1002, +1719, -1840, -6421, -2928, +4336, +115, +445, -2293, -6587, +102, +2286, +140, +231, -302, -617, -45, -1479, -669, -78, -1505, -452, -92, -181, +382, +108, -202, },
|
||||
{ +13989, +12100, -300, +4352, -584, -894, +751, -1879, -4250, -3597, +3863, +484, -1133, -527, -5742, -1882, +2289, +370, +107, +366, -557, -756, -1254, -675, +260, -958, -884, -49, -127, +270, +110, -168, },
|
||||
{ +13107, +11235, -316, +4649, +46, -886, +387, -2126, -3083, -3291, +3067, +1077, -1914, +82, -4188, -3391, +1793, +547, -349, +600, -246, -893, -1266, -562, +499, -574, -1293, -81, +40, +122, +177, -141, },
|
||||
{ +12123, +10207, -26, +5040, +240, -1159, +554, -1339, -3049, -3489, +2834, +1553, -2088, +86, -2702, -3839, +1078, +690, -758, +264, -223, -525, -820, -718, +257, -322, -1226, +21, +75, +12, +282, -234, },
|
||||
{ +10747, +9168, +566, +5397, +351, -1371, +926, -546, -2786, -3752, +1902, +1979, -1557, -9, -1749, -3706, +668, +745, -1061, -69, -419, -453, -245, -659, -216, -192, -848, +155, +137, -64, +205, -239, },
|
||||
{ +10338, +7957, +561, +6771, -2, -2128, +1652, +306, -2773, -4474, +1333, +2284, -1324, +617, -1488, -4429, +966, +918, -1497, -98, -822, -796, -54, -649, -27, -96, -951, +551, +331, -223, +48, -268, },
|
||||
{ +8720, +7871, +1937, +5955, -252, -2274, +1362, -265, -1942, -3385, -195, +1599, -597, +942, -704, -3945, -437, +923, -232, -93, -938, -655, -8, -340, +19, -166, -798, +69, +242, -236, +6, -124, },
|
||||
{ +7602, +7369, +1980, +5375, +188, -1525, +1271, -440, -1548, -3046, -447, +1237, -466, +757, -218, -3077, -861, +1080, +8, -496, -751, -394, -12, -415, -286, -141, -377, -40, -114, -262, +138, -57, },
|
||||
{ +6659, +6622, +2031, +4526, +599, -537, +864, -488, -1252, -2664, -491, +837, -265, +650, -6, -2474, -736, +1187, -23, -536, -523, -192, -58, -543, -514, -195, -232, -228, -227, -106, +203, +4, },
|
||||
{ +5900, +6258, +1847, +3648, +1138, +55, +581, -518, -1216, -2232, -426, +663, -175, +546, +190, -2072, -582, +1218, -57, -487, -330, -182, -121, -530, -618, -248, -293, -250, -52, -43, +131, +41, },
|
||||
{ +5056, +5699, +1640, +3073, +1682, +223, +366, -415, -1093, -1701, -428, +436, +76, +685, +156, -1697, -250, +1101, -72, -482, -271, -35, -164, -545, -578, -155, -255, -314, +31, +57, +129, +2, },
|
||||
{ +4420, +5031, +1526, +2971, +1795, +154, +317, -287, -871, -1279, -467, +257, +332, +803, +167, -1309, -82, +802, -141, -342, -151, -34, -185, -411, -382, -26, -278, -370, +32, +101, +150, -29, },
|
||||
{ +3741, +4414, +1550, +2755, +1697, +240, +358, -209, -641, -963, -482, +156, +636, +955, +153, -952, -130, +526, -22, -234, -141, -29, -17, -156, -225, -73, -393, -324, +91, +81, +127, +14, },
|
||||
{ +2974, +3771, +1714, +2268, +1466, +609, +473, -195, -532, -642, -208, +371, +868, +928, +168, -618, -68, +350, +7, -152, -30, +198, +164, -106, -265, -109, -239, -204, +88, +59, +101, +117, },
|
||||
{ +2091, +3036, +1907, +2129, +1391, +724, +464, -41, -262, -310, +40, +365, +939, +1032, +282, -384, -88, +174, -12, -37, +129, +229, +41, -48, -98, -70, -190, -179, +36, +72, +111, +99, },
|
||||
{ +1445, +2433, +1850, +1781, +1171, +805, +720, +119, +17, +232, +387, +551, +917, +1092, +388, -310, -142, -4, +121, +154, +38, +139, +164, +94, -72, -106, -103, -116, +22, +112, +121, +28, },
|
||||
{ +1185, +1993, +1603, +1441, +986, +909, +956, +692, +298, +365, +753, +730, +851, +889, +295, -301, -75, +80, +163, +139, -24, +148, +231, +110, -113, -59, -17, -3, +88, +93, +26, -171, },
|
||||
{ +929, +1455, +1263, +1389, +1207, +1075, +1117, +1195, +937, +623, +608, +551, +588, +631, +253, -42, +158, +103, +4, +39, +49, +61, +131, +212, +119, +81, -26, +0, +138, -59, -235, -232, },
|
||||
{ +822, +1583, +1506, +1563, +1699, +1350, +1018, +900, +685, +649, +736, +432, +188, +378, +360, +160, +134, -13, -136, -75, +123, +246, +203, +257, +240, +33, -106, -86, -100, -185, -187, -131, },
|
||||
{ +1055, +2056, +2052, +1866, +1431, +1170, +1157, +723, +299, +248, +365, +522, +438, +367, +368, +108, -145, -117, +92, +69, +74, +249, +238, +249, +240, +27, -128, -200, -286, -220, -88, -53, },
|
||||
{ +1205, +2171, +1980, +1773, +1441, +1300, +1201, +725, +193, -127, +142, +624, +550, +387, +335, +108, +110, +159, +2, -95, +146, +227, +29, +177, +403, +337, -41, -376, -330, -171, -140, -61, },
|
||||
{ +1241, +2158, +1760, +1464, +1328, +1398, +1227, +684, +95, +70, +568, +408, +149, +304, +228, +314, +526, +203, +21, +102, +15, -27, +94, +161, +134, +344, +341, -75, -343, -352, -143, -62, },
|
||||
{ +1622, +2444, +1530, +1228, +926, +1008, +1151, +744, -34, -42, +764, +765, +377, -38, -176, +304, +572, +431, +399, +163, +15, +139, +7, -83, +139, +174, +132, +311, +140, -144, -288, -260, },
|
||||
{ +1988, +2810, +1493, +1199, +762, +896, +984, +329, -524, -369, +974, +1088, +421, +50, +39, +109, +262, +367, +396, +394, +294, +181, +60, +66, -63, -115, +123, +273, +319, +228, -43, -271, },
|
||||
{ +2526, +3457, +1538, +1318, +724, +747, +744, -154, -1107, -804, +1097, +1060, +234, +52, +56, +324, +531, +217, +162, +419, +225, +256, +263, +67, +92, -2, -93, +88, +240, +428, +251, -76, },
|
||||
{ +3196, +4012, +1429, +1473, +720, +771, +686, -545, -1618, -1131, +1253, +952, -133, -206, -51, +422, +646, +293, +343, +345, +85, +287, +111, +124, +185, +14, -5, +226, +158, +71, +246, +198, },
|
||||
{ +4055, +4548, +1209, +1653, +679, +876, +676, -915, -2105, -1296, +1540, +778, -521, -439, -221, +267, +627, +274, +404, +557, +82, +190, +96, +57, +173, +67, +122, +268, +75, +91, +69, +85, },
|
||||
{ +5274, +5182, +788, +1972, +519, +928, +689, -1324, -2574, -1398, +1954, +556, -880, -663, -380, +149, +471, +122, +381, +459, +18, +339, +145, +8, +122, +110, +27, +301, +132, +67, +132, +6, },
|
||||
{ +6463, +5753, +204, +2322, +409, +883, +685, -1827, -2887, -1237, +2299, +272, -1164, -830, -425, +53, +394, -18, +257, +435, -217, +313, +174, +118, +26, -101, +42, +280, +156, +192, +176, +19, },
|
||||
{ +7727, +6595, -464, +2628, +421, +701, +721, -2439, -3227, -1064, +2569, +149, -1378, -1132, -432, +91, +148, +15, +160, +263, -252, +291, +71, -34, -78, -110, -65, +186, +193, +201, +372, +187, },
|
||||
{ +8674, +7441, -887, +2687, +475, +615, +762, -2918, -3490, -885, +2619, +32, -1422, -1271, -474, +50, +151, -43, +133, +383, -345, +103, -122, +5, -192, -218, -4, +192, +197, +219, +350, +56, },
|
||||
{ +9426, +8468, -909, +2618, +320, +470, +937, -3379, -3580, -906, +2153, +153, -1146, -1581, -641, -54, +224, +390, -97, +193, -307, +44, -287, -162, -284, -252, +7, +204, +290, +112, +287, +9, },
|
||||
{ +9648, +9372, -545, +2609, +289, -35, +1177, -3423, -3509, -971, +1312, +111, -652, -1474, -971, -83, +171, +613, -45, +26, -344, -79, -230, -165, -334, -249, -69, -50, +303, +195, +309, -45, },
|
||||
{ +9794, +9998, +39, +2769, +379, -638, +980, -3266, -3261, -859, +205, -83, -237, -1162, -748, -518, -59, +946, +29, -268, -354, +5, -131, -183, -422, -257, -155, -194, +224, +120, +248, +7, },
|
||||
{ +9981, +10397, +622, +3286, +610, -1141, +509, -3403, -3000, -195, -811, -998, +359, -548, -477, -751, -558, +952, +151, -164, -95, -136, -277, -86, -487, -322, -168, -469, +127, +155, +238, -39, },
|
||||
{ +10400, +10438, +745, +3939, +894, -1363, +3, -3769, -2585, +471, -1670, -1614, +581, -153, +52, -948, -1056, +930, +424, -236, -31, +17, -267, -241, -666, -379, -196, -563, -20, +129, +269, +14, },
|
||||
{ +11293, +10206, +442, +4923, +1094, -1505, -530, -3996, -2130, +1419, -2437, -2806, +924, +121, +806, -871, -1571, +1001, +618, -424, +58, +151, -379, -185, -956, -481, -127, -651, -119, +140, +160, -149, },
|
||||
{ +12405, +9835, -281, +5828, +885, -1582, -583, -4592, -1654, +2615, -2996, -4362, +959, +504, +1380, -564, -2020, +895, +761, -610, +81, +185, -720, -204, -1012, -549, -116, -759, -235, +116, +85, -201, },
|
||||
{ +13934, +9778, -1546, +6319, +686, -1381, -382, -5271, -1119, +3944, -3172, -5767, +686, +682, +1741, +77, -2181, +507, +979, -721, -237, +318, -773, -227, -1265, -756, +92, -716, -477, +162, +134, -400, },
|
||||
{ +15591, +10583, -3448, +5772, +592, -1315, +577, -5494, -1701, +4790, -2265, -6627, -93, +745, +2160, +357, -2547, +377, +1130, -881, -407, +529, -934, -349, -1319, -885, +105, -673, -507, +45, +171, -344, },
|
||||
{ +17313, +11801, -5808, +4851, +227, -980, +2385, -6012, -2746, +5567, -996, -7076, -952, +586, +2154, +773, -2812, -169, +1297, -600, -709, +461, -948, -242, -1337, -1246, +226, -600, -658, -10, +354, -281, },
|
||||
{ +19637, +11754, -7792, +4845, -732, -208, +3348, -6604, -2889, +6378, +241, -7587, -1944, +32, +2714, +992, -3500, -540, +1647, -590, -1131, +670, -931, -134, -1354, -1421, +144, -583, -536, +136, +307, -469, },
|
||||
{ +21056, +11745, -8787, +4783, -1622, +469, +3944, -6753, -3241, +6740, +1590, -8058, -2609, -411, +2588, +1199, -3554, -896, +1543, -588, -1309, +826, -1017, +54, -1317, -1707, +140, -326, -455, +92, +212, -518, },
|
||||
{ +22470, +11991, -9701, +4389, -2684, +1431, +4782, -6942, -4015, +6909, +3084, -7923, -3158, -1809, +2522, +1950, -3598, -1289, +1296, -609, -1331, +920, -1125, +160, -1425, -1754, +339, -152, -445, +42, +154, -583, },
|
||||
{ +23333, +12284, -9893, +3816, -3344, +2109, +5145, -6669, -4930, +6673, +4509, -7499, -3802, -2971, +2448, +2729, -3461, -1700, +1131, -635, -1249, +918, -1341, +144, -1300, -1646, +329, -23, -418, +82, +75, -652, },
|
||||
{ +23907, +12687, -9670, +3149, -3819, +2297, +5278, -6129, -6015, +6230, +5855, -6823, -4412, -4207, +2246, +3493, -3012, -2245, +989, -670, -1278, +815, -1685, +265, -1083, -1694, +279, +79, -444, +187, -65, -803, },
|
||||
{ +24068, +13242, -9317, +2853, -4157, +2181, +5293, -5711, -6874, +5677, +6685, -5741, -4828, -5227, +2103, +3851, -2196, -2705, +724, -483, -1476, +639, -1724, +395, -1100, -1511, +43, +72, -276, +84, -146, -836, },
|
||||
{ +23835, +13868, -8722, +2737, -4517, +2057, +5139, -5437, -7512, +4767, +7374, -4441, -4873, -6362, +1764, +4214, -1258, -3060, +266, -145, -1812, +589, -1602, +416, -1030, -1500, -192, +122, -223, -168, -12, -862, },
|
||||
{ +23307, +14493, -7616, +2886, -5061, +1805, +4905, -5438, -8024, +3633, +7772, -2910, -4088, -7840, +1069, +4716, -316, -3023, -501, +151, -1943, +531, -1399, +596, -1194, -1653, -168, -131, -123, -407, +123, -804, },
|
||||
{ +22971, +14195, -6115, +3007, -5341, +1777, +4268, -5238, -8637, +2925, +7500, -1787, -2907, -8792, +313, +4922, +197, -2731, -1003, +162, -1684, +337, -1204, +594, -1286, -1645, -381, -303, -37, -516, +148, -504, },
|
||||
{ +22070, +14375, -4392, +2868, -5223, +1286, +3714, -4447, -9674, +1907, +7159, -860, -973, -9579, -1209, +5344, +421, -2142, -1115, -130, -1112, +96, -1456, +898, -1239, -2004, -343, -667, +59, -231, +163, -308, },
|
||||
{ +21240, +14393, -3174, +2492, -4298, +1094, +2745, -3688, -10265, +1178, +6777, -618, +645, -9443, -2927, +5381, +636, -1617, -791, -478, -882, +115, -1535, +816, -1293, -2149, -223, -878, +246, +6, +122, -102, },
|
||||
{ +20341, +13345, -1099, +2866, -4191, +914, +1804, -2626, -10582, -327, +6635, -287, +2111, -8876, -5214, +5209, +1109, -1120, -336, -736, -608, +24, -1715, +729, -1303, -2434, -80, -706, +170, +364, +230, -221, },
|
||||
{ +19164, +13059, -468, +4105, -4326, +617, +1911, -2785, -9817, -1770, +6595, -131, +2540, -7381, -7331, +4587, +2019, -857, -311, -599, -501, +196, -1861, -41, -744, -2295, -231, -641, +296, +624, -2, -206, },
|
||||
{ +18422, +13001, -808, +4597, -3422, -211, +2249, -2884, -9087, -2495, +6668, -543, +1814, -4858, -8725, +3134, +2718, -437, +54, -836, -508, +440, -2036, -713, -94, -2244, -301, -159, -24, +549, +64, -190, },
|
||||
{ +17855, +12583, -1366, +5362, -2553, -1443, +2178, -2151, -7613, -3290, +5904, -270, +528, -2457, -8756, +644, +3333, -90, +363, -320, -761, -106, -1922, -663, +147, -1870, -338, +6, -294, +558, +55, -269, },
|
||||
{ +16989, +12653, -2050, +5407, -1459, -1174, +828, -2193, -4917, -4430, +5563, +243, -1454, -249, -7905, -1684, +3547, +136, +95, +521, -741, -985, -1507, -732, +567, -1249, -1016, +108, -174, +393, +77, -205, },
|
||||
{ +15955, +11844, -2035, +5709, -643, -1173, +284, -2723, -3123, -4229, +4384, +1201, -2654, +769, -6230, -3909, +3368, +375, -503, +1015, -370, -1372, -1549, -501, +871, -801, -1619, +110, +41, +191, +164, -153, },
|
||||
{ +15076, +10787, -1651, +6161, -494, -1528, +363, -1853, -3374, -4091, +4325, +1345, -2786, +774, -4553, -4709, +2401, +708, -854, +734, -248, -874, -1363, -746, +954, -560, -1815, +201, +149, +40, +297, -250, },
|
||||
{ +13619, +9790, -1075, +6480, -296, -1830, +805, -986, -3179, -4836, +3833, +2526, -3239, +844, -2857, -5293, +1983, +856, -1538, +348, -255, -582, -521, -965, +224, -130, -1436, +334, +56, -57, +433, -405, },
|
||||
{ +11990, +8803, -122, +6797, -290, -2053, +1262, -151, -2986, -4897, +2471, +2765, -2059, +507, -2148, -4881, +1467, +956, -1677, +43, -545, -596, -9, -842, -196, -59, -1007, +415, +207, -148, +219, -297, },
|
||||
{ +12081, +7961, -53, +8316, -2153, -3098, +1599, -1374, -4780, -3918, +6091, +1729, -1658, +3619, -1653, -4298, +1906, +240, -2274, -904, -1646, -475, -581, -1417, -48, -621, -760, +583, -70, -397, +372, +38, },
|
||||
{ +10221, +7710, +913, +7396, -744, -3594, +288, -1159, -3490, -2578, +4228, +2100, -676, +2348, -1090, -3898, +283, +166, -1419, -166, -1389, -451, +154, -1605, +30, -242, -1341, +92, +30, -175, +146, +10, },
|
||||
{ +8688, +6964, +1507, +6729, -314, -2703, +315, -1206, -2584, -2071, +3004, +1882, -602, +1784, -753, -3344, +27, -28, -1040, +36, -1038, -169, +101, -1356, +51, -283, -1249, -154, -166, -180, +96, -77, },
|
||||
{ +7115, +6222, +2194, +6013, +21, -1813, +346, -984, -1850, -1758, +2164, +1394, -547, +1436, -539, -2734, -356, -16, -801, -44, -393, +279, +133, -1115, -80, -420, -1086, -375, -460, -339, +102, +64, },
|
||||
{ +5945, +5731, +2369, +5160, +628, -1311, +172, -355, -1302, -1644, +1506, +1052, -512, +980, -248, -2308, -600, +61, -662, +216, +230, +430, +21, -924, -262, -525, -975, -595, -515, -352, +24, +58, },
|
||||
{ +4951, +5289, +2362, +4475, +1066, -1021, +399, +107, -1048, -1369, +919, +662, -450, +769, -110, -1957, -639, +150, -163, +531, +305, +258, +28, -774, -421, -578, -897, -479, -486, -369, -53, -38, },
|
||||
{ +4363, +4902, +2175, +3906, +1203, -661, +681, +254, -736, -1138, +362, +420, -286, +700, -78, -1616, -376, +371, +225, +620, +133, +107, -31, -735, -442, -346, -613, -527, -506, -305, -33, +11, },
|
||||
{ +3887, +4410, +1997, +3432, +1166, -200, +836, +280, -488, -1038, -68, +289, -94, +640, +127, -1246, -284, +556, +413, +412, -66, +15, -158, -547, -132, -220, -649, -561, -395, -212, +21, +92, },
|
||||
{ +3376, +3956, +1885, +2975, +1204, +193, +869, +327, -309, -968, -279, +153, +258, +942, +175, -1108, -255, +727, +480, +101, -239, +78, +89, -338, -137, -200, -570, -519, -230, -33, +148, +121, },
|
||||
{ +2882, +3708, +1714, +2272, +1421, +628, +806, +292, -242, -915, -154, +676, +462, +684, +167, -864, -170, +750, +347, -82, -16, +193, +144, -210, -259, -192, -347, -281, -16, +141, -8, -250, },
|
||||
{ +2046, +3121, +1820, +2057, +1654, +693, +650, +385, +140, -232, -150, +593, +684, +440, +155, -506, -275, +602, +454, -11, +56, +206, +86, -187, -110, +2, -156, -45, +18, -158, -271, -285, },
|
||||
{ +1488, +2866, +1983, +1297, +1310, +1249, +896, +455, +406, +318, +200, +433, +517, +126, +107, -107, -188, +504, +467, +57, +7, +98, +167, +102, +54, +69, +57, -187, -324, -266, -204, -157, },
|
||||
{ +1053, +2185, +1754, +1283, +1374, +1384, +1276, +1018, +579, +445, +413, +125, +270, +305, -100, -39, +315, +357, +242, +93, +19, +226, +393, +295, +143, -27, -218, -292, -266, -226, -155, -132, },
|
||||
{ +1057, +1688, +1471, +1786, +1766, +1650, +1060, +783, +933, +472, +248, +183, +76, +69, +137, +183, +238, +233, +230, +317, +365, +313, +253, +237, +26, -223, -314, -259, -170, -175, -164, -190, },
|
||||
{ +1484, +2348, +1611, +1846, +1758, +1472, +1102, +423, +268, +233, +403, +262, +27, +176, +309, +97, -27, +318, +563, +614, +474, +195, -31, -203, -192, -193, -175, -172, -180, -189, -226, -227, },
|
||||
{ +1189, +2150, +2013, +2091, +1722, +1365, +885, +462, +260, +102, +413, +490, +320, +96, +1, +58, +212, +334, +486, +716, +577, +224, -92, -268, -289, -245, -180, -118, -126, -201, -214, -200, },
|
||||
{ +1538, +2422, +1826, +1858, +1328, +1049, +982, +559, +11, +288, +803, +359, +369, +46, -142, +244, +201, +241, +677, +674, +409, +408, -39, -390, -282, -219, -225, -163, -112, -102, -144, -262, },
|
||||
{ +1451, +2242, +1550, +1542, +1259, +1129, +1099, +613, +12, +373, +659, +432, +541, +134, +290, +219, +14, +256, +292, +393, +633, +888, +287, -211, -275, -432, -238, -88, -138, -127, -59, -184, },
|
||||
{ +1889, +2552, +1389, +1386, +798, +799, +1037, +440, -97, +313, +902, +615, +250, +224, +305, +196, +454, +188, +213, +467, +218, +428, +693, +519, -184, -445, -344, -230, -88, -89, -79, -137, },
|
||||
{ +2363, +3156, +1398, +1195, +447, +518, +860, +263, -393, +80, +1073, +455, +343, +419, -4, +307, +535, +250, +536, +315, -34, +496, +401, +321, +495, -3, -404, -292, -153, -89, -99, -128, },
|
||||
{ +2825, +3421, +1231, +1466, +685, +599, +704, -461, -1098, +100, +1264, +329, +295, +180, +24, +419, +226, +386, +756, +380, +127, +240, +62, +328, +348, +131, +263, +30, -341, -335, -68, -108, },
|
||||
{ +3491, +4043, +1102, +1542, +710, +589, +566, -937, -1530, +137, +1469, +122, -70, -161, -43, +468, +450, +426, +430, +401, +160, +372, +284, +90, +60, +56, +234, +293, +163, -117, -305, -271, },
|
||||
{ +4318, +4870, +895, +1479, +603, +516, +626, -1326, -2005, +237, +1656, -115, -219, -418, -328, +396, +406, +377, +591, +338, -178, +469, +312, +158, +217, -234, -8, +329, +210, +69, +187, -16, },
|
||||
{ +5303, +5497, +566, +1592, +649, +557, +509, -1916, -2395, +604, +1814, -332, -334, -762, -437, +361, +208, +350, +554, +119, -140, +409, +18, +313, +179, -239, +98, -40, +40, +299, +419, +154, },
|
||||
{ +6339, +6214, +236, +1676, +646, +546, +369, -2580, -2680, +1136, +1943, -586, -423, -1111, -529, +411, +162, +286, +376, -36, -255, +422, +29, +77, +2, -290, -43, +175, +135, +31, +367, +299, },
|
||||
{ +7425, +6991, -61, +1742, +482, +489, +257, -3260, -2805, +1599, +1929, -688, -450, -1459, -633, +395, +140, +359, +251, -272, -354, +408, -47, +55, -274, -528, -51, +174, +73, +63, +482, +141, },
|
||||
{ +8275, +7928, -159, +1756, +330, +237, +226, -3790, -2846, +1890, +1754, -690, -422, -1605, -800, +248, +185, +442, +143, -377, -482, +428, -180, -145, -222, -605, -186, -18, +24, +140, +387, +163, },
|
||||
{ +8779, +8969, +132, +1669, +354, -215, +82, -3976, -2837, +1984, +1471, -648, -422, -1570, -842, -60, +130, +630, +84, -403, -597, +177, +30, -221, -403, -610, -358, +87, -64, -83, +409, +63, },
|
||||
{ +8644, +10014, +1089, +1453, +493, -603, -298, -3906, -2820, +1754, +1240, -552, -546, -1453, -849, -345, +44, +672, +148, -531, -682, +196, +32, -233, -584, -609, -409, -84, -103, -217, +378, +199, },
|
||||
{ +8306, +10593, +2458, +1598, +488, -758, -657, -3861, -2849, +1369, +1000, -322, -680, -1443, -722, -668, -37, +677, -45, -127, -673, -156, +70, -281, -443, -635, -631, -315, -160, -54, +479, +139, },
|
||||
{ +8399, +10550, +3351, +2403, +311, -794, -759, -3852, -2757, +792, +477, +47, -726, -1554, -558, -902, -349, +816, +82, -285, -484, -159, +82, -356, -623, -644, -824, -243, +7, -98, +292, +151, },
|
||||
{ +8816, +10302, +3569, +3594, +382, -1029, -763, -3770, -2393, +191, -597, +339, -557, -1492, -281, -1488, -279, +1005, -143, -84, -408, -266, +120, -345, -812, -549, -772, -407, -193, -80, +533, +172, },
|
||||
{ +9548, +9994, +3253, +4643, +623, -1187, -749, -3597, -1800, -143, -2200, +304, -135, -1804, +254, -1488, -709, +1187, -140, -38, -318, -470, +133, -281, -894, -381, -819, -627, -170, -88, +384, +19, },
|
||||
{ +10751, +9616, +2488, +5649, +553, -1161, -620, -3463, -848, -358, -3996, +121, +130, -2080, +871, -1563, -750, +1416, -465, -119, -39, -417, +70, -275, -1074, -309, -632, -645, -410, -224, +390, -12, },
|
||||
{ +12014, +9312, +1365, +6755, +300, -1330, -113, -3321, +199, -72, -5935, -749, +987, -2491, +1095, -1087, -1039, +1478, -609, -197, +278, -296, -103, -265, -1088, -288, -651, -818, -474, -102, +420, -351, },
|
||||
{ +13420, +9342, -277, +7865, +178, -2087, +567, -3307, +1525, +754, -7969, -2060, +1804, -2289, +1011, -875, -1158, +1512, -570, -399, +356, -20, -88, -202, -1219, -576, -573, -671, -574, -252, +223, -435, },
|
||||
{ +14807, +9961, -2295, +8150, +567, -2864, +1147, -3390, +2627, +2008, -9297, -3776, +2200, -1711, +807, -518, -1276, +1360, -541, -609, +222, +438, +75, -495, -1315, -653, -426, -658, -1054, -304, +558, -512, },
|
||||
{ +16799, +11079, -4722, +7037, +966, -2929, +1994, -3796, +2704, +3553, -9595, -5358, +1866, -912, +909, -200, -1483, +979, -455, -806, +207, +669, +68, -725, -1243, -745, -665, -630, -1077, -219, +691, -658, },
|
||||
{ +18748, +11700, -6587, +6122, +943, -2914, +2664, -4426, +2804, +5554, -10085, -6616, +1486, -372, +1328, -285, -1517, +471, -396, -837, +75, +587, +104, -751, -1461, -967, -816, -312, -988, -264, +684, -677, },
|
||||
{ +20863, +12866, -8572, +4385, +266, -1602, +3832, -5716, +2704, +6971, -9876, -6842, +1023, -479, +1689, -35, -1641, +123, -340, -939, -107, +662, +89, -932, -1675, -1081, -768, +37, -888, -310, +796, -570, },
|
||||
{ +22765, +13783, -10202, +2941, -746, -81, +4256, -6846, +2898, +7803, -8917, -6979, +238, -972, +2079, +576, -1912, -370, -306, -915, -363, +634, -131, -948, -1776, -1303, -718, +235, -798, -279, +1030, -691, },
|
||||
{ +24585, +14272, -11287, +1831, -1784, +1157, +4160, -7450, +3079, +8440, -7630, -7341, -269, -1716, +2654, +1114, -2449, -581, -181, -975, -680, +550, -325, -686, -1945, -1634, -616, +402, -659, -135, +1021, -867, },
|
||||
{ +25869, +14987, -12073, +934, -2610, +1696, +3918, -7361, +2532, +9076, -6029, -7754, -590, -2620, +3019, +1624, -2920, -652, -46, -1264, -966, +600, -472, -467, -2153, -1908, -503, +517, -451, -126, +848, -860, },
|
||||
{ +26886, +15454, -12309, +371, -3390, +1840, +3592, -7055, +1669, +9594, -4128, -8018, -1017, -3459, +3063, +2189, -3137, -722, +61, -1655, -1121, +760, -729, -326, -2158, -2099, -462, +648, -404, -166, +686, -817, },
|
||||
{ +27684, +15653, -11980, +24, -4099, +1713, +3246, -6955, +802, +10113, -2356, -7981, -1587, -4226, +3032, +2573, -2987, -885, +150, -1954, -1167, +794, -988, -168, -2014, -2167, -434, +666, -569, -144, +540, -855, },
|
||||
{ +27741, +16216, -11243, -193, -4856, +1352, +3238, -7293, -125, +10598, -852, -7518, -2157, -4853, +2670, +2868, -2470, -1300, +205, -1901, -1416, +672, -1092, +16, -1804, -2095, -591, +514, -688, -235, +476, -797, },
|
||||
{ +27272, +16910, -10056, -159, -5917, +966, +3706, -8117, -996, +10790, +336, -6433, -2511, -5475, +1946, +3049, -1685, -1717, +71, -1629, -1727, +569, -1061, +184, -1403, -2279, -872, +450, -920, -127, +585, -861, },
|
||||
{ +26292, +17598, -8440, +25, -7051, +509, +4314, -9076, -1994, +10815, +1175, -4930, -2295, -6533, +1145, +3192, -1111, -1763, -328, -1487, -1778, +538, -867, +358, -1413, -2301, -1193, +94, -600, -21, +592, -845, },
|
||||
{ +24908, +18211, -6510, +265, -7874, +12, +4724, -9478, -3509, +10716, +2192, -3778, -1219, -7880, +248, +3471, -999, -1541, -792, -1628, -1421, +841, -1035, +457, -1363, -2591, -1213, -67, -308, +27, +657, -759, },
|
||||
{ +23173, +18778, -4279, +420, -8200, -952, +4606, -8583, -5614, +10055, +3892, -3343, +694, -8935, -1196, +3813, -1288, -1146, -860, -1990, -933, +977, -1325, +807, -1645, -2747, -714, -417, -75, +218, +548, -805, },
|
||||
{ +22000, +18365, -2003, +631, -8453, -1561, +3477, -6891, -7183, +8672, +5645, -3122, +2529, -8996, -3276, +3955, -1630, -956, -275, -2341, -1164, +1321, -1481, +629, -1309, -2933, -330, -280, -173, +221, +483, -718, },
|
||||
{ +21112, +17584, -502, +1334, -8158, -2273, +2292, -5787, -7662, +7007, +7216, -2614, +3372, -7775, -5664, +3835, -1591, -1170, +244, -2374, -1158, +1090, -1550, +627, -758, -3019, +93, -274, -410, +438, +348, -800, },
|
||||
{ +20632, +17088, -637, +2364, -7070, -3739, +1695, -4935, -8217, +5848, +8673, -2173, +3453, -6082, -7678, +3590, -1152, -1978, +580, -2279, -1275, +1124, -1750, +530, -17, -2783, -114, -166, -296, +284, +223, -679, },
|
||||
{ +20783, +15919, -1263, +4036, -6965, -4754, +1892, -4346, -8539, +4539, +9671, -1610, +3670, -4797, -8663, +2624, -468, -2009, +28, -2355, -1460, +1576, -1563, +142, +565, -2599, -176, -95, -480, +333, +227, -736, },
|
||||
{ +19898, +14834, -883, +5611, -7741, -5058, +2778, -4286, -8109, +2022, +9952, -268, +3452, -2598, -9652, +1195, +498, -1859, -458, -2733, -1925, +1990, -998, -244, +1156, -2794, -697, +541, -558, +197, +87, -769, },
|
||||
{ +18353, +13734, -294, +6773, -7182, -5247, +2895, -3546, -8000, -248, +9510, +1071, +3101, -432, -9279, -621, +1397, -1978, -692, -2518, -2682, +1633, -584, +363, +1428, -3524, -1018, +1348, -563, -124, +38, -581, },
|
||||
{ +17879, +12019, -1720, +8332, -4976, -5136, +2334, -3753, -7617, -1708, +9554, +1908, +1367, +1443, -7575, -1992, +1783, -1645, -1254, -2425, -2861, +887, -188, +457, +1489, -3426, -1450, +1731, -415, -317, +8, -369, },
|
||||
{ +16652, +10730, -1605, +9069, -4100, -5114, +2342, -2722, -7212, -3184, +9140, +2114, -706, +3732, -5117, -4057, +2505, -1340, -2078, -1590, -2693, +151, -496, -93, +1733, -2286, -1942, +1173, +71, -202, +59, -356, },
|
||||
{ +15156, +9682, -934, +8954, -3661, -4339, +2035, -2043, -6405, -3988, +8467, +1700, -1521, +4564, -3502, -4488, +2506, -991, -2469, -1109, -2320, -118, -899, -916, +1437, -1210, -1567, +612, -176, -55, +492, -295, },
|
||||
{ +13768, +8771, -687, +8850, -3021, -3693, +1828, -1815, -5404, -4221, +7310, +1847, -1818, +4247, -2573, -4214, +2383, -697, -2275, -1002, -2080, -223, -830, -1342, +608, -827, -917, +655, -473, -208, +715, -175, },
|
||||
{ +14260, +8470, -4402, +9252, +637, -4904, +113, -702, -4629, -3590, +7432, -364, -3180, +3406, -815, -2084, +3326, +846, -1128, +174, -1402, -361, -2087, -2634, -411, -921, -1460, -69, -168, +123, +619, -314, },
|
||||
{ +12203, +8042, -2103, +8153, +36, -4209, +166, -837, -3973, -3102, +5672, +328, -1860, +2823, -972, -1947, +2514, +629, -644, +18, -1399, -247, -1603, -2116, -289, -1032, -1262, -81, -282, -111, +472, -81, },
|
||||
{ +9978, +7761, -851, +7167, +518, -3404, +616, -905, -3552, -2875, +4478, +661, -1312, +2289, -665, -1823, +1788, +811, -693, -46, -1135, -436, -1105, -1539, -267, -710, -1155, -219, -156, -293, +133, -138, },
|
||||
{ +8252, +7011, +325, +6475, +571, -2476, +1105, -925, -3370, -2437, +3577, +876, -1052, +1795, -250, -1885, +1251, +954, -652, -129, -973, -426, -862, -997, +85, -618, -1083, -201, -130, -385, -107, -293, },
|
||||
{ +6990, +6408, +794, +5771, +1007, -1732, +1092, -813, -2841, -2294, +2966, +1185, -1180, +1392, +18, -1807, +929, +855, -550, -195, -860, -345, -413, -570, +52, -503, -888, -152, -282, -552, -210, -339, },
|
||||
{ +6315, +5794, +807, +5067, +1552, -954, +511, -614, -2056, -2084, +2442, +1235, -1125, +916, +7, -1376, +711, +581, -457, -233, -563, +16, -83, -537, -90, -310, -669, -307, -465, -561, -130, -413, },
|
||||
{ +5495, +5067, +1235, +4594, +1625, -330, +383, -413, -1595, -1679, +1966, +934, -895, +616, -4, -1020, +465, +389, -292, +92, -212, +95, -14, -517, -157, -268, -599, -430, -445, -406, -157, -409, },
|
||||
{ +4664, +4577, +1540, +4071, +1781, +42, +302, -196, -1100, -1341, +1290, +763, -650, +297, +59, -796, +256, +526, +78, +88, -122, +237, -54, -604, -266, -281, -530, -328, -364, -356, -110, -313, },
|
||||
{ +3851, +4119, +1861, +3768, +1681, +225, +590, +32, -804, -1149, +865, +588, -638, +296, +218, -632, +437, +631, +5, +112, +96, +233, -258, -721, -220, -100, -390, -319, -297, -172, -5, -185, },
|
||||
{ +3336, +3750, +1919, +3488, +1574, +321, +813, +276, -570, -1058, +527, +383, -558, +511, +605, -444, +230, +571, +103, +183, +137, -15, -469, -450, -1, -70, -317, -262, -110, +31, -67, -427, },
|
||||
{ +3049, +3510, +1714, +3215, +1488, +383, +1012, +442, -405, -1074, +260, +303, -38, +921, +427, -524, +201, +517, +216, +135, -99, -116, -221, -179, +46, -34, -244, -78, -50, -204, -303, -502, },
|
||||
{ +2844, +3234, +1490, +2937, +1418, +496, +1224, +481, -359, -986, +230, +762, +253, +708, +333, -527, +155, +538, +90, +24, +59, +6, -45, -70, +130, +103, -256, -256, -271, -304, -297, -325, },
|
||||
{ +2647, +2909, +1294, +2675, +1363, +698, +1331, +460, -184, -366, +335, +522, +431, +628, +210, -521, -47, +509, +303, +218, +56, +23, +150, +170, +182, -200, -553, -341, -197, -165, -211, -392, },
|
||||
{ +2534, +2823, +1022, +1970, +1429, +1221, +1392, +703, +196, -392, +319, +726, +304, +316, -41, -517, +273, +763, +274, +109, +137, +366, +348, -105, -308, -391, -404, -192, -101, -238, -327, -356, },
|
||||
{ +1989, +2468, +1081, +1801, +1546, +1331, +1957, +1126, +247, -246, -18, +528, +333, +129, -70, -149, +414, +761, +386, +169, +318, +372, +30, -395, -334, -284, -295, -143, -195, -279, -332, -341, },
|
||||
{ +1620, +2490, +1471, +1655, +2013, +1585, +1301, +1138, +603, -161, -181, -90, -24, +524, +502, +148, +414, +612, +427, +246, +105, +30, -174, -325, -240, -291, -355, -203, -136, -260, -309, -267, },
|
||||
{ +1263, +2410, +2075, +1764, +1891, +1970, +1489, +641, +109, -195, -152, +183, +214, +240, +589, +646, +460, +466, +334, +34, -111, -86, -179, -264, -241, -257, -328, -326, -184, -161, -161, -211, },
|
||||
{ +1659, +2476, +1676, +2229, +1972, +1422, +1669, +708, -448, -272, +296, +223, +206, +469, +501, +694, +819, +331, -104, -205, -133, -45, -56, -253, -357, -286, -277, -167, -214, -215, -128, -196, },
|
||||
{ +1539, +2551, +1891, +1969, +1762, +1252, +1228, +862, +110, -20, +303, +230, +166, +358, +647, +849, +752, +128, -158, -145, -243, -82, -52, -123, -279, -382, -292, -181, -163, -170, -155, -213, },
|
||||
{ +1700, +2807, +1619, +1270, +1372, +1179, +1161, +1231, +504, +52, +504, +136, +92, +640, +736, +453, +675, +669, -252, -473, -51, +20, -170, -152, -154, -240, -345, -332, -109, -89, -138, -173, },
|
||||
{ +1694, +2657, +1452, +968, +771, +1023, +1613, +1199, +359, +667, +624, -76, +382, +536, +594, +753, +564, +532, +330, -84, -457, -257, +116, +14, -260, -224, -186, -331, -270, -123, -32, -136, },
|
||||
{ +1868, +2708, +1232, +929, +844, +827, +1033, +736, +424, +738, +823, +481, +179, +246, +857, +667, +444, +613, +612, +119, -110, -152, -501, -78, +116, -202, -290, -173, -262, -254, -131, -141, },
|
||||
{ +2010, +2795, +1111, +875, +1109, +1106, +857, -4, -401, +861, +1319, +394, +265, +408, +467, +655, +737, +455, +536, +705, +304, -158, -205, -280, -395, +24, +44, -233, -199, -207, -233, -158, },
|
||||
{ +2330, +2991, +964, +1027, +1208, +1180, +792, -487, -765, +646, +1124, +466, +294, +78, +501, +769, +452, +561, +675, +354, +514, +630, -115, -307, -312, -411, -176, +29, -28, -209, -223, -273, },
|
||||
{ +2824, +3565, +965, +943, +1112, +1083, +667, -717, -987, +738, +1121, +2, +110, +106, +412, +576, +458, +606, +513, +519, +535, +409, +396, +221, -406, -363, -190, -297, -93, +42, -95, -282, },
|
||||
{ +3349, +3983, +872, +1076, +1173, +1134, +531, -1288, -1216, +1017, +1171, -131, -155, -369, +349, +670, +365, +458, +453, +375, +399, +660, +331, +266, +204, -128, -309, -306, -200, -192, -42, -94, },
|
||||
{ +3961, +4442, +707, +1254, +1277, +1123, +361, -1769, -1366, +1301, +1136, -328, -227, -538, +131, +409, +403, +542, +281, +118, +332, +560, +285, +456, +66, +169, +247, -283, -261, -198, -228, -289, },
|
||||
{ +4686, +5052, +536, +1343, +1245, +1005, +207, -2188, -1265, +1645, +926, -588, -346, -640, +177, +285, +106, +548, +311, +27, +151, +303, +255, +325, +75, +299, +196, +155, +118, -260, -236, -300, },
|
||||
{ +5534, +5563, +318, +1536, +1252, +806, -127, -2646, -995, +2082, +649, -787, -525, -824, +252, +141, +115, +500, +81, -14, +111, +227, +28, +135, -85, +201, +321, +171, +203, +214, -19, -500, },
|
||||
{ +6386, +6175, +93, +1727, +1236, +541, -519, -3046, -559, +2421, +322, -926, -609, -965, +269, -57, +33, +671, -21, -197, +21, +165, +4, +40, -436, +106, +232, +49, +425, +144, +66, +0, },
|
||||
{ +7130, +6925, -88, +1879, +1277, +209, -950, -3419, -58, +2693, -41, -998, -710, -991, +321, -320, -82, +770, -64, -189, -88, -19, +13, -38, -523, -42, -30, +68, +150, +89, +365, -23, },
|
||||
{ +7792, +7702, -133, +1956, +1357, -128, -1415, -3772, +482, +2874, -375, -1048, -862, -936, +402, -512, -233, +760, -129, -149, -81, -155, -78, -100, -630, -36, -59, -442, +95, +280, +185, +75, },
|
||||
{ +8084, +8648, +147, +1800, +1588, -465, -1801, -4057, +739, +3060, -585, -1055, -1095, -889, +484, -597, -294, +651, -254, -145, -54, -182, -110, -282, -564, -209, -393, -202, +61, +14, +171, +1, },
|
||||
{ +7950, +9589, +964, +1429, +1845, -635, -2157, -4183, +602, +3177, -602, -1039, -1301, -965, +529, -614, -333, +613, -355, -295, -22, -253, -53, -255, -948, -322, -205, -347, -6, +31, +59, -71, },
|
||||
{ +7608, +10215, +2256, +1215, +1866, -509, -2499, -4150, +252, +3102, -462, -1007, -1377, -1131, +543, -620, -361, +628, -344, -407, -176, -143, -39, -636, -843, -265, -361, -355, -99, +51, +143, +45, },
|
||||
{ +7478, +10350, +3382, +1641, +1562, -364, -2671, -4182, +82, +2795, -422, -952, -1415, -1234, +496, -705, -369, +637, -288, -460, -139, -421, -273, -301, -1004, -427, -393, -387, -99, +121, +207, -128, },
|
||||
{ +7601, +10277, +3938, +2546, +1409, -546, -2604, -4195, -39, +2430, -446, -937, -1542, -1235, +449, -844, -397, +623, -239, -176, -592, -583, -41, -478, -953, -587, -540, -343, +32, +110, -10, -156, },
|
||||
{ +7999, +10060, +3982, +3415, +1699, -807, -2609, -3807, -190, +1946, -508, -758, -1860, -1306, +494, -1071, -466, +696, -160, -448, -342, -561, -316, -440, -936, -533, -717, -285, -33, -87, +138, +52, },
|
||||
{ +8868, +9667, +3696, +4220, +1884, -786, -2974, -3169, -25, +1022, -611, -333, -2076, -1587, +587, -1486, -187, +551, -545, +152, -427, -718, -238, -557, -971, -356, -742, -544, -186, +78, +286, -144, },
|
||||
{ +10008, +9228, +3019, +5173, +1730, -514, -3173, -2654, +674, -266, -982, +303, -2059, -1915, +478, -1617, -384, +327, -296, +313, -485, -639, -255, -549, -996, -197, -986, -652, +62, -23, +48, -97, },
|
||||
{ +11234, +8968, +1867, +6284, +1449, -576, -2850, -2320, +1671, -1457, -1966, +1061, -1777, -2251, +610, -2387, -502, +717, -908, +856, -362, -807, -179, -457, -950, -356, -981, -565, +70, -205, +52, -184, },
|
||||
{ +12424, +9043, +307, +7301, +1477, -1225, -2226, -1811, +2733, -2240, -3502, +1512, -1095, -2186, +52, -2767, -416, +476, -1043, +1163, -163, -967, -182, -310, -939, -309, -1033, -648, +172, -197, -66, -313, },
|
||||
{ +13850, +9410, -1577, +7710, +1903, -2007, -1727, -1126, +3784, -2445, -5373, +1368, +274, -2547, -214, -2859, -931, +830, -1404, +1283, +192, -1142, -131, -304, -939, -130, -968, -870, +367, -211, -179, -446, },
|
||||
{ +15689, +10650, -4191, +6439, +2855, -1819, -1216, -1122, +4356, -1735, -7082, +796, +1337, -2613, -354, -3165, -1020, +960, -1511, +1143, +338, -957, -254, -411, -1003, +93, -787, -961, +276, -120, -242, -590, },
|
||||
{ +17568, +11974, -6732, +4560, +3824, -1109, -754, -1349, +4606, -843, -8100, -287, +1911, -2056, -658, -3260, -1157, +899, -1412, +975, +487, -915, -443, -511, -909, +161, -686, -992, +148, +70, -223, -830, },
|
||||
{ +19484, +13084, -9012, +2638, +4382, +24, -354, -1619, +4661, +92, -8630, -1472, +1971, -1185, -834, -3443, -1007, +624, -1325, +1001, +434, -935, -492, -574, -862, +109, -756, -815, +84, +193, -327, -1033, },
|
||||
{ +21524, +13678, -10956, +1222, +4385, +1297, -139, -2069, +5017, +1156, -9307, -2582, +2096, -601, -528, -3661, -796, +152, -1389, +1321, +257, -1041, -461, -535, -1092, +104, -751, -637, +26, +127, -265, -1109, },
|
||||
{ +23605, +13718, -12574, +568, +3860, +2238, -103, -2760, +6167, +2019, -10424, -3226, +2099, -412, +299, -3787, -992, -294, -1323, +1597, -108, -1067, -318, -600, -1468, +200, -723, -642, -34, +135, -184, -1205, },
|
||||
{ +25071, +14148, -13932, +471, +3008, +2768, -76, -3611, +7895, +2700, -11593, -3451, +1646, -185, +1383, -3748, -1496, -431, -1263, +1534, -312, -957, -121, -752, -1802, +171, -636, -694, -65, +159, -201, -1248, },
|
||||
{ +26816, +13743, -14786, +862, +1921, +2946, -342, -4385, +10015, +2577, -12171, -3354, +671, +309, +2238, -3598, -1940, -465, -1278, +1149, -315, -796, +17, -1000, -2051, +76, -546, -729, -117, +138, -282, -1090, },
|
||||
{ +27951, +14104, -15590, +1273, +860, +2927, -633, -4986, +11529, +2744, -11887, -3827, +2, +498, +2997, -3184, -2478, -171, -1514, +556, -142, -469, -72, -1148, -2207, -3, -362, -847, -143, +170, -197, -1176, },
|
||||
{ +28803, +14580, -16123, +1472, -187, +3073, -1250, -5325, +12182, +3270, -11190, -4406, -641, +391, +3646, -2789, -2835, +205, -1933, -111, +62, -112, -330, -1167, -2390, +48, -212, -1112, -86, +341, -303, -1353, },
|
||||
{ +30323, +13889, -15910, +1407, -1171, +3553, -2383, -5267, +12463, +3540, -10099, -4882, -1197, +116, +4331, -2625, -2785, +375, -2274, -723, +301, +72, -494, -1132, -2662, +359, -286, -1255, +88, +360, -528, -1375, },
|
||||
{ +30968, +14210, -15671, +1048, -1781, +3667, -3019, -5566, +12074, +4371, -8903, -5378, -1555, -380, +4891, -2272, -2787, +479, -2516, -1197, +410, +143, -580, -995, -2832, +409, -254, -1218, +75, +188, -590, -1406, },
|
||||
{ +30975, +15165, -15312, +546, -2218, +3398, -2954, -6444, +11217, +5687, -7852, -5572, -1909, -880, +5215, -1819, -2692, +359, -2645, -1443, +355, +103, -656, -709, -2922, +164, -25, -1239, -84, +72, -690, -1273, },
|
||||
{ +30424, +16368, -14573, +92, -2674, +2748, -2205, -7930, +10058, +7372, -7052, -5344, -2312, -1403, +5238, -1260, -2430, -1, -2723, -1529, +312, -177, -560, -464, -2980, -55, -69, -1190, -231, -99, -594, -932, },
|
||||
{ +29455, +17526, -13363, -127, -3235, +1964, -1140, -9860, +8781, +9245, -6389, -4845, -2498, -2034, +4995, -530, -2084, -491, -2825, -1345, +221, -559, -398, -274, -2983, -380, -142, -1168, -371, +10, -384, -724, },
|
||||
{ +28118, +18400, -11563, -157, -4012, +1308, -199, -11792, +7222, +10997, -5639, -4233, -2301, -2934, +4504, +364, -1845, -1024, -2737, -1299, +240, -966, -422, -53, -3194, -483, -435, -1176, -132, +127, -258, -452, },
|
||||
{ +26552, +19152, -9368, -160, -4867, +986, +473, -13162, +5114, +12399, -4354, -3860, -1375, -4191, +3967, +1296, -1787, -1124, -2703, -1337, +286, -1074, -1007, +244, -3127, -928, -436, -993, +94, +254, +31, -338, },
|
||||
{ +24559, +20217, -7367, -220, -5053, +163, +912, -13440, +2241, +12957, -1945, -4140, -3, -5230, +2779, +2633, -1975, -895, -2652, -1685, +399, -1133, -1787, +451, -3100, -1099, -141, -1148, +476, +550, +59, -556, },
|
||||
{ +23258, +20668, -6394, +41, -4001, -1343, +259, -12280, -447, +12376, +814, -4410, +990, -5553, +1277, +3778, -1842, -823, -2296, -2428, +66, -675, -2623, +69, -2488, -1174, +108, -1212, +763, +685, -33, -620, },
|
||||
{ +23142, +19464, -5694, +1043, -3149, -2286, -1288, -10731, -2354, +11827, +2425, -4171, +1875, -6154, +693, +4142, -1325, -613, -2234, -3206, -20, -772, -3178, +251, -2328, -913, +289, -1277, +940, +736, -150, -671, },
|
||||
{ +22552, +18662, -5393, +2289, -1879, -3683, -2436, -8894, -4473, +11069, +4563, -5019, +3166, -6153, -527, +5142, -1047, -592, -2109, -3335, -857, -775, -3407, +489, -1798, -1280, +535, -1129, +1014, +574, -236, -416, },
|
||||
{ +22401, +17758, -5842, +3364, -812, -4784, -3176, -6717, -5712, +8976, +6974, -6176, +3397, -4371, -2591, +6388, -734, -1317, -1243, -3549, -1586, -824, -3469, +452, -886, -1990, +679, -751, +619, +748, -301, -324, },
|
||||
{ +22309, +16537, -6181, +4660, -360, -5405, -3571, -5406, -6202, +6988, +8656, -6084, +2058, -2265, -3682, +6212, +772, -2272, -843, -3239, -2023, -881, -3727, +370, -424, -2103, +394, -539, +433, +863, -135, -441, },
|
||||
{ +21791, +15541, -6192, +5616, -505, -5546, -3072, -4658, -6616, +5207, +9841, -5865, +904, -1208, -3643, +5823, +1664, -2499, -798, -2591, -2431, -478, -3918, -635, -47, -1868, +308, -596, +226, +890, +22, -361, },
|
||||
{ +21324, +14642, -6583, +6799, -1051, -6105, -1417, -3904, -7362, +3483, +10991, -5815, -496, +549, -4041, +4979, +2787, -2309, -896, -2206, -2499, +60, -3674, -2156, -266, -1362, +446, -246, -422, +573, +555, -41, },
|
||||
{ +20752, +13927, -7556, +7887, -383, -7140, -472, -2508, -7640, +1050, +11820, -4742, -2329, +2225, -4014, +3077, +4488, -1969, -1094, -1484, -3038, +789, -3176, -3637, -596, -1084, +354, +499, -803, -174, +1114, +269, },
|
||||
{ +19965, +13135, -8141, +8473, +760, -7513, -787, -971, -6960, -1942, +12233, -3129, -3764, +3112, -3442, +1359, +4791, -618, -1183, -1102, -2895, +601, -2684, -3990, -954, -1401, +153, +1055, -625, -482, +888, +405, },
|
||||
{ +19143, +11685, -8033, +9384, +754, -7209, -418, -807, -6484, -2771, +11238, -2375, -3772, +3580, -3133, +167, +4612, -12, -608, -927, -2580, +196, -2728, -3474, -1079, -1676, -444, +1107, -287, -167, +508, -54, },
|
||||
{ +17857, +10290, -7109, +9878, +454, -6436, -46, -1046, -5905, -3006, +10009, -1912, -3542, +3960, -2520, -1113, +4554, +356, -838, +40, -2468, -172, -2487, -3471, -559, -1557, -1179, +703, -47, +127, +577, -318, },
|
||||
{ +16296, +9009, -5714, +9900, +226, -5547, +70, -922, -5384, -3238, +8823, -1282, -3406, +3868, -1537, -1923, +3996, +793, -1145, +249, -1720, -492, -2325, -3083, -467, -1071, -1564, +201, -55, +203, +765, -336, },
|
||||
{ +15841, +6997, -6669, +11869, +1968, -7696, -859, +385, -4403, -1539, +6206, -3126, -2033, +3213, -1498, -707, +2441, -260, -30, +640, -527, +1221, -934, -1381, +294, -1105, -1226, -270, -1487, -1152, -350, -611, },
|
||||
{ +13568, +6667, -4985, +10337, +1992, -6022, -629, +40, -3621, -1574, +5221, -2329, -1990, +2774, -1185, -903, +2184, +6, -131, +493, -301, +1057, -963, -1225, +288, -1053, -961, -56, -1078, -893, -506, -522, },
|
||||
{ +11497, +6501, -3490, +8587, +2327, -4433, -803, -59, -2956, -1671, +4442, -1603, -1990, +2273, -678, -964, +1803, +277, -100, +341, -258, +879, -733, -1205, +106, -817, -829, +182, -726, -774, -439, -507, },
|
||||
{ +9657, +6295, -2357, +7055, +2839, -3195, -922, +87, -2426, -1717, +3756, -1022, -1971, +1799, -285, -852, +1503, +322, +17, +329, -329, +745, -562, -1092, +21, -498, -600, +37, -450, -530, -354, -499, },
|
||||
{ +8080, +5958, -1527, +5929, +3206, -2314, -807, +279, -2098, -1713, +3210, -663, -1953, +1446, +14, -682, +1140, +403, +168, +150, -283, +600, -477, -850, +175, -366, -595, +17, -334, -374, -332, -390, },
|
||||
{ +6742, +5563, -934, +5119, +3472, -1654, -579, +468, -1830, -1693, +2733, -440, -1854, +1199, +270, -615, +927, +597, +39, +58, -146, +541, -282, -642, +203, -260, -523, -66, -324, -342, -189, -288, },
|
||||
{ +5645, +5082, -470, +4564, +3569, -1149, -280, +632, -1648, -1657, +2279, -195, -1747, +997, +500, -550, +854, +535, -56, +205, +54, +502, -244, -453, +284, -250, -567, -159, -320, -231, -40, -147, },
|
||||
{ +4739, +4548, -15, +4161, +3424, -612, +92, +576, -1502, -1483, +1923, -133, -1573, +1049, +513, -481, +827, +418, +204, +407, -41, +456, -23, -319, +105, -295, -566, -165, -125, -78, -45, -303, },
|
||||
{ +4000, +4116, +315, +3739, +3361, -78, +141, +471, -1088, -1423, +1428, +104, -1192, +778, +494, -118, +776, +531, +352, +301, +46, +496, -16, -403, -75, -250, -372, +7, -75, -290, -272, -334, },
|
||||
{ +3315, +3731, +744, +3252, +3208, +505, +104, +326, -724, -1258, +1022, +253, -920, +621, +766, +320, +638, +429, +479, +312, +62, +342, -149, -425, +78, -14, -324, -163, -364, -342, -177, -191, },
|
||||
{ +2721, +3507, +1076, +2691, +3219, +926, -155, +334, -235, -1266, +533, +565, -478, +790, +1052, +241, +481, +577, +434, +197, -68, +166, +67, -116, +62, -279, -535, -276, -242, -195, -120, -171, },
|
||||
{ +2164, +3272, +1472, +2240, +2998, +1160, -8, +380, -347, -1061, +577, +981, +39, +670, +997, +273, +443, +502, +183, +101, +156, +367, +108, -320, -359, -368, -337, -186, -156, -185, -219, -252, },
|
||||
{ +1934, +3190, +1503, +1841, +2991, +1228, -234, +344, -22, -479, +868, +985, +160, +811, +840, +155, +222, +329, +446, +340, +153, +57, -306, -454, -236, -196, -253, -198, -267, -270, -212, -218, },
|
||||
{ +1850, +2863, +1570, +2109, +2264, +770, +377, +952, +272, -269, +977, +887, +259, +859, +502, -89, +465, +710, +360, -49, -274, -104, -140, -299, -180, -223, -354, -327, -223, -222, -195, -175, },
|
||||
{ +1880, +2606, +1259, +1967, +2141, +1272, +1090, +983, +171, -143, +1137, +1038, +78, +386, +659, +433, +428, +299, -214, -286, +0, +94, -163, -340, -274, -342, -349, -267, -185, -155, -161, -219, },
|
||||
{ +1397, +2225, +1498, +2218, +2597, +1375, +970, +1179, +446, +55, +983, +782, +92, +766, +779, +21, -117, -30, -43, +45, +38, -51, -292, -398, -291, -331, -321, -187, -130, -199, -179, -163, },
|
||||
{ +1635, +3062, +2249, +1880, +1916, +1343, +1114, +965, +534, +333, +634, +1026, +601, -88, -96, -36, +19, +140, +79, -54, -187, -223, -327, -363, -331, -232, -228, -189, -124, -136, -165, -244, },
|
||||
{ +1621, +2982, +2331, +1859, +1672, +1505, +1317, +1168, +916, +338, +486, +1012, +283, -527, -167, +103, +151, +173, -30, -202, -207, -185, -337, -340, -290, -264, -241, -183, -115, -121, -178, -226, },
|
||||
{ +1602, +2643, +1775, +1564, +1563, +1546, +1646, +1829, +1322, +708, +618, +118, +151, +107, -304, -55, +284, +102, -151, -125, -138, -202, -309, -317, -234, -259, -302, -184, -120, -109, -170, -206, },
|
||||
{ +1689, +2725, +1687, +1342, +1018, +1221, +1839, +1792, +1379, +895, +468, +478, +768, +67, -215, -9, -169, +55, +46, -227, -303, -177, -209, -261, -200, -191, -162, -205, -213, -154, -174, -239, },
|
||||
{ +1884, +2685, +1171, +1190, +1175, +880, +977, +1283, +1525, +1401, +1097, +684, +686, +975, +274, -642, -241, -46, -48, +8, -211, -255, -203, -172, -169, -156, -217, -131, -186, -249, -160, -234, },
|
||||
{ +1711, +2523, +1308, +1090, +1055, +1174, +1022, +299, +477, +1301, +1459, +1119, +863, +804, +1042, +601, -340, -501, -204, -29, -21, -94, -220, -196, -156, -184, -116, -170, -201, -183, -255, -271, },
|
||||
{ +1817, +2536, +946, +809, +944, +1085, +1157, +217, -175, +767, +1098, +779, +1147, +1424, +1313, +1026, +631, +198, -302, -492, -270, -64, -131, -189, -253, -238, -160, -88, -70, -213, -184, -209, },
|
||||
{ +2191, +2839, +854, +984, +1168, +1002, +768, -219, -19, +1063, +561, +60, +636, +861, +1348, +1294, +885, +891, +475, -73, -432, -506, -288, -67, -118, -220, -240, -103, -74, -138, -148, -245, },
|
||||
{ +2451, +2833, +673, +1459, +1780, +1173, +305, -947, -35, +1449, +504, -211, +108, +410, +948, +640, +824, +1192, +884, +675, +272, -177, -565, -472, -224, -108, -84, -125, -187, -164, -89, -188, },
|
||||
{ +3086, +3702, +648, +1075, +1515, +1169, +441, -1098, -143, +1309, +271, -221, +106, +208, +526, +378, +428, +792, +941, +752, +488, +344, +62, -247, -504, -376, -181, +22, -47, -250, -217, -168, },
|
||||
{ +3569, +4097, +532, +1316, +1840, +1093, -29, -1514, +254, +1604, -129, -469, -58, +189, +685, +94, +33, +566, +399, +418, +683, +566, +398, +298, -51, -324, -429, -122, -77, -175, -112, -284, },
|
||||
{ +4125, +4461, +378, +1609, +2191, +994, -587, -1865, +674, +1689, -401, -500, -250, +88, +680, -19, +36, +317, +78, +227, +154, +381, +584, +347, +348, +259, -144, -157, -249, -295, -182, -189, },
|
||||
{ +4867, +5214, +256, +1466, +2150, +866, -894, -1915, +1051, +1495, -779, -414, -262, +45, +633, -205, +3, +311, -89, +0, -11, +125, +199, +237, +418, +383, +270, +312, -107, -370, -261, -364, },
|
||||
{ +5316, +5480, +203, +2110, +2686, +411, -1842, -1931, +1799, +1361, -1123, -406, -380, +95, +608, -401, +32, +304, -272, -6, -184, -72, +198, -153, +69, +403, +277, +536, +348, -42, -176, -397, },
|
||||
{ +5892, +6233, +160, +2100, +2860, +142, -2433, -1800, +2326, +963, -1427, -273, -439, +158, +610, -591, -43, +281, -390, -16, -246, -165, +68, -360, -9, +156, +82, +484, +326, +166, +189, -170, },
|
||||
{ +6296, +6975, +282, +2083, +3088, -133, -3093, -1657, +2878, +590, -1820, -143, -472, +190, +638, -719, -106, +233, -510, -92, -328, -237, +113, -522, -223, +109, -26, +254, +179, +32, +200, +156, },
|
||||
{ +6592, +7845, +648, +1757, +3189, -161, -3619, -1575, +3255, +370, -2151, -143, -426, +168, +727, -779, -195, +244, -572, -180, -428, -336, +66, -505, -282, -26, -117, +217, +77, -98, +16, -149, },
|
||||
{ +6774, +8708, +1082, +1524, +3240, -264, -3922, -1540, +3434, +295, -2349, -304, -372, +149, +756, -675, -383, +223, -505, -236, -520, -494, -9, -552, -315, -62, -148, +121, +173, -299, -365, -62, },
|
||||
{ +6908, +9422, +1625, +1424, +3190, -389, -4004, -1611, +3471, +335, -2543, -391, -396, +68, +811, -604, -534, +182, -441, -272, -536, -643, -94, -634, -428, -131, -91, +267, -223, -392, -234, -275, },
|
||||
{ +7138, +10189, +2126, +1133, +2968, -382, -3722, -1762, +3018, +580, -2559, -606, -255, -134, +669, -325, -681, -12, -293, -317, -621, -648, -141, -715, -656, -53, -111, -126, -38, -347, -470, -236, },
|
||||
{ +7313, +10455, +2943, +1070, +2390, +272, -3497, -2310, +2731, +755, -2380, -670, -474, -246, +602, -255, -558, -320, -482, -158, -477, -799, -319, -604, -503, -410, -501, +108, -160, -398, -359, -347, },
|
||||
{ +7826, +10161, +3173, +1967, +2130, +423, -3555, -2463, +2451, +634, -1952, -839, -706, -181, +512, -312, -450, -587, -636, +17, -569, -882, -377, -371, -655, -672, -473, -170, -109, -345, -438, -377, },
|
||||
{ +8467, +9477, +3103, +3430, +2024, +440, -3655, -2401, +2236, -26, -1277, -712, -1114, -26, +375, -495, -221, -726, -826, +29, -851, -620, -323, -809, -370, -647, -794, -102, -163, -412, -424, -337, },
|
||||
{ +9286, +8516, +2179, +5700, +2660, -483, -3558, -1721, +1619, -1074, -311, -359, -1649, +39, +247, -528, -41, -857, -1059, -36, -827, -638, -733, -625, -208, -781, -693, -299, -176, -287, -276, -526, },
|
||||
{ +10487, +8297, +724, +7001, +3276, -1546, -2976, -375, +714, -2874, +551, +663, -2103, -61, +34, -604, +320, -1061, -1370, +301, -1334, -957, -278, -1039, -89, -630, -732, -236, -218, -112, -316, -769, },
|
||||
{ +11694, +8483, -1085, +7688, +4377, -2639, -2748, +1388, +290, -5170, +695, +2234, -2233, -376, -167, -879, +703, -1107, -1401, -21, -1755, -792, -436, -1099, +19, -701, -676, +56, -177, -420, -299, -499, },
|
||||
{ +12813, +8986, -2960, +7720, +5822, -3441, -2888, +3186, +503, -7344, -143, +3835, -1619, -861, -365, -1277, +915, -643, -1945, -184, -1723, -1371, -165, -1036, -149, -608, -623, +361, -273, -675, -81, -360, },
|
||||
{ +14282, +9854, -5144, +6666, +7543, -3247, -3573, +4303, +1159, -8673, -1552, +4734, -435, -1066, -737, -1669, +1323, -711, -2400, +154, -2059, -1735, -117, -896, -79, -641, -571, +431, -255, -662, -37, -376, },
|
||||
{ +15850, +10514, -7059, +5564, +8654, -2773, -4154, +5402, +1737, -9668, -3061, +5015, +1018, -866, -1440, -1886, +1527, -978, -2388, +41, -2052, -1988, -323, -629, -13, -650, -699, +444, -203, -546, -140, -354, },
|
||||
{ +17808, +11057, -9134, +4383, +9339, -1778, -4546, +6062, +2149, -10167, -4257, +4712, +2487, -456, -1988, -2239, +1739, -1173, -2546, +134, -2148, -2055, -395, -540, +91, -587, -935, +488, -19, -574, -174, -369, },
|
||||
{ +20383, +11132, -11423, +3225, +9645, -449, -4728, +6097, +2297, -10259, -4895, +4011, +3369, +308, -2432, -2790, +2050, -1452, -2764, +266, -2368, -1811, -610, -479, +220, -714, -1063, +583, +89, -687, -231, -413, },
|
||||
{ +22418, +11798, -13840, +2373, +9532, +812, -4649, +5776, +2876, -10183, -5672, +3197, +3848, +1355, -2692, -3324, +2269, -1738, -2840, +474, -2481, -1785, -640, -534, +229, -841, -1060, +727, -62, -819, -169, -447, },
|
||||
{ +24894, +11396, -15645, +2370, +8933, +1292, -4281, +5629, +3954, -10488, -6364, +2682, +3969, +2394, -2882, -3405, +2175, -2174, -2424, +697, -2794, -1803, -440, -660, +159, -906, -842, +819, -413, -760, -126, -429, },
|
||||
{ +26219, +12293, -17420, +2685, +7926, +1207, -3924, +5306, +5940, -10486, -7929, +2418, +4103, +2810, -2438, -3395, +1620, -2289, -1991, +723, -2963, -1849, -215, -902, +78, -722, -742, +870, -694, -718, -23, -517, },
|
||||
{ +28416, +11175, -18030, +3639, +6517, +524, -3997, +5626, +7964, -10885, -9328, +2435, +4025, +2769, -1736, -3204, +870, -2252, -1569, +634, -3242, -1541, -240, -1235, +91, -529, -623, +850, -941, -678, +99, -756, },
|
||||
{ +29176, +11689, -18551, +4399, +5252, -160, -4585, +5761, +10465, -11051, -10563, +2051, +3915, +2524, -384, -3448, +237, -1642, -1718, +678, -3401, -1225, -371, -1551, +5, -226, -521, +663, -896, -768, +144, -1146, },
|
||||
{ +29021, +13077, -18841, +4810, +4427, -776, -5593, +5564, +12643, -10486, -11302, +1156, +3758, +2201, +1006, -3601, -405, -695, -2158, +611, -3242, -1002, -587, -1809, -96, +32, -433, +355, -533, -1081, -66, -1282, },
|
||||
{ +30639, +12013, -18276, +5087, +3533, -892, -7519, +6359, +13438, -9871, -11200, +130, +3528, +2142, +1859, -3611, -530, -415, -2173, +244, -2952, -752, -1000, -1830, -214, +226, -496, +424, -528, -1428, -247, -1261, },
|
||||
{ +31129, +12133, -17589, +4753, +3258, -1123, -8951, +6078, +13955, -8365, -10965, -1246, +3253, +2362, +2106, -3221, -543, -421, -2041, -9, -2564, -798, -1213, -1842, -312, +214, -362, +364, -897, -1374, -502, -1281, },
|
||||
{ +30719, +13121, -16780, +4200, +3198, -1555, -9649, +4676, +14307, -6216, -10726, -2675, +2883, +2776, +1878, -2607, -273, -769, -1833, +57, -2369, -947, -1301, -1967, -305, +248, -529, +122, -1019, -1330, -719, -996, },
|
||||
{ +29697, +14733, -15818, +3462, +3061, -1780, -9577, +2144, +14501, -3727, -10382, -3699, +2209, +3218, +1410, -1818, +264, -1375, -1409, +257, -2249, -1183, -1411, -1971, -160, -60, -974, +340, -1284, -1182, -516, -1030, },
|
||||
{ +28002, +16846, -14478, +2412, +2676, -1519, -8873, -1372, +14440, -1063, -9859, -4131, +1096, +3328, +1195, -1203, +1073, -1927, -1076, +655, -2259, -1480, -1460, -1775, -599, -341, -1181, +468, -1245, -932, -470, -1164, },
|
||||
{ +25869, +18455, -12266, +1637, +1978, -1262, -8280, -4934, +14128, +1672, -9443, -4041, -152, +2529, +1995, -1259, +1882, -1726, -1545, +1491, -2530, -1653, -1433, -2120, -1079, -408, -1374, +717, -856, -1223, -178, -1188, },
|
||||
{ +24864, +17912, -9358, +1641, +576, -357, -8615, -7257, +13351, +3934, -9073, -3482, -838, +841, +3250, -1322, +2217, -796, -2111, +1754, -2153, -2158, -1467, -2434, -1624, -253, -1302, +874, -576, -1341, -96, -1263, },
|
||||
{ +23420, +17860, -6501, +1165, -717, +588, -8140, -9637, +11644, +6449, -8639, -3126, -461, -1536, +4057, -378, +1614, +434, -2303, +1248, -1439, -2499, -1782, -2484, -2002, -134, -998, +651, -243, -1476, -235, -998, },
|
||||
{ +22006, +18635, -5893, +1609, -295, -1121, -6611, -10352, +8438, +8556, -7366, -3845, +1086, -3469, +3525, +1549, +597, +1088, -1819, +227, -740, -2416, -2356, -1773, -2500, -256, -642, +230, -150, -1358, -351, -903, },
|
||||
{ +22224, +17778, -6386, +3076, +518, -3282, -6409, -9035, +5543, +9128, -5573, -4587, +2339, -4194, +2628, +2481, +473, +849, -1362, -75, -999, -1551, -2497, -1277, -2514, -1057, -402, -20, +22, -1408, -555, -809, },
|
||||
{ +22103, +17015, -6884, +4461, +1233, -5006, -6070, -7906, +2832, +9189, -3231, -5657, +3433, -4282, +1463, +3242, -717, +1493, -1177, -711, -254, -881, -2411, -866, -2491, -1884, -465, -353, +374, -1387, -1115, -592, },
|
||||
{ +22560, +15777, -7251, +5550, +797, -5686, -5009, -7186, +427, +9113, -1133, -6601, +3854, -2859, -422, +3276, -587, +291, -113, -529, +173, -114, -2517, -809, -1886, -2312, -1324, -304, +246, -1137, -1252, -701, },
|
||||
{ +22731, +15350, -9222, +6868, +2173, -7663, -4747, -4975, -1211, +7055, +1768, -6971, +2930, -1113, -1589, +2833, -506, -636, +510, +745, -151, +413, -2257, -1147, -1254, -2415, -1827, -858, -136, -928, -699, -812, },
|
||||
{ +23304, +14017, -11279, +9072, +3099, -9814, -4178, -2550, -2580, +4834, +3988, -6788, +1843, +177, -2381, +2443, -295, -988, +882, +1070, +364, +564, -2129, -1074, -1171, -2223, -1782, -1409, -1115, -600, -62, -717, },
|
||||
{ +23618, +12255, -12665, +11454, +3209, -11235, -3282, -912, -3248, +2468, +5358, -5978, +1078, +518, -3093, +2872, +91, -1576, +1462, +574, +484, +1620, -2554, -835, -966, -2532, -1116, -1629, -2136, -622, +243, -448, },
|
||||
{ +23507, +10176, -12976, +13613, +2604, -11794, -2177, +221, -4379, +941, +6866, -5844, +60, +1571, -3421, +2227, +1420, -1610, +744, +868, +160, +1913, -1757, -1375, -527, -2462, -1299, -900, -2681, -1245, +284, -163, },
|
||||
{ +22437, +8395, -11784, +14554, +1462, -10835, -1161, -107, -4923, +595, +7185, -5944, -419, +2664, -3581, +1327, +2496, -1354, +156, +805, -57, +1910, -1336, -1388, -199, -2269, -1525, -558, -2342, -1654, -242, -88, },
|
||||
{ +20519, +7379, -9918, +14135, +1130, -9407, -1215, -80, -4674, -389, +7077, -5070, -1127, +3004, -2779, +575, +2442, -923, +375, +352, -401, +2124, -1583, -1128, +325, -2275, -1384, -459, -2045, -1486, -593, -444, },
|
||||
{ +18163, +7171, -8342, +13120, +1703, -8708, -1203, +485, -4645, -1323, +6947, -3981, -1909, +3255, -1914, -231, +2372, -512, +246, +503, -605, +1638, -1102, -1353, +431, -1611, -1452, -256, -1866, -1326, -460, -644, },
|
||||
{ +14734, +5366, -4938, +13261, +853, -8371, +138, +318, -3336, +134, +2204, -3293, +1697, +2006, -2237, -277, +1106, -520, -774, +253, -99, +68, -412, +780, +809, +219, +346, -370, -906, -336, -779, -1298, },
|
||||
{ +12591, +5345, -3597, +11397, +1333, -6737, -45, +46, -2876, +145, +2069, -2657, +1229, +1805, -1739, -516, +791, -312, -657, +44, -12, +385, -291, +437, +830, +261, +90, -313, -700, -424, -611, -816, },
|
||||
{ +10805, +5339, -2604, +9725, +1921, -5525, -310, +43, -2429, +58, +1959, -2032, +690, +1674, -1216, -766, +650, -159, -575, +29, +105, +445, -262, +423, +590, +102, +242, -169, -667, -426, -434, -541, },
|
||||
{ +9340, +5201, -1982, +8478, +2304, -4592, -320, +86, -2009, +7, +1880, -1679, +320, +1616, -995, -817, +572, -17, -496, +83, +280, +281, -168, +371, +343, +122, +380, -5, -602, -322, -317, -483, },
|
||||
{ +8188, +4843, -1495, +7540, +2395, -3667, -312, +176, -1589, -77, +1770, -1446, +114, +1442, -804, -782, +564, +82, -423, +254, +211, +181, -62, +208, +366, +208, +389, +140, -452, -279, -247, -426, },
|
||||
{ +7139, +4447, -1005, +6621, +2495, -2780, -305, +313, -1320, -50, +1606, -1337, +16, +1312, -654, -711, +624, +129, -237, +218, +117, +290, -83, +217, +421, +287, +411, +153, -317, -192, -175, -342, },
|
||||
{ +6157, +4147, -661, +5795, +2719, -2091, -278, +447, -1015, -108, +1345, -1106, -12, +1133, -544, -455, +616, +156, -87, +162, +222, +352, -56, +280, +494, +294, +391, +184, -187, +6, -183, -528, },
|
||||
{ +5279, +3795, -302, +5095, +2792, -1423, -200, +524, -834, -167, +1181, -897, -46, +946, -299, -307, +520, +329, -7, +248, +337, +305, +68, +311, +476, +300, +386, +295, -101, -189, -428, -616, },
|
||||
{ +4525, +3459, -28, +4546, +2834, -885, -89, +549, -694, -192, +1043, -644, -76, +759, -74, -153, +593, +505, +119, +343, +347, +334, +158, +340, +453, +359, +386, +40, -308, -328, -435, -568, },
|
||||
{ +3930, +3246, +221, +4012, +2721, -518, +143, +558, -699, -125, +1073, -572, -271, +859, +240, +26, +775, +548, +199, +453, +346, +378, +240, +360, +327, +89, +121, -123, -319, -354, -529, -642, },
|
||||
{ +3660, +3270, +329, +3382, +2495, -259, +336, +625, -667, -168, +978, -390, -146, +1158, +544, +64, +837, +706, +404, +422, +317, +415, +105, -19, +35, +69, +43, -172, -504, -539, -442, -551, },
|
||||
{ +3142, +2802, +557, +3432, +2389, -71, +540, +456, -686, +42, +1063, -160, +119, +1196, +649, +468, +1015, +684, +339, +353, +244, +13, -220, -126, +48, +81, -160, -332, -500, -382, -372, -555, },
|
||||
{ +2901, +2760, +686, +3156, +2256, -27, +369, +564, -227, +172, +1095, +54, +380, +1501, +986, +535, +850, +558, +60, -34, -144, -62, -229, -185, +27, -136, -229, -282, -406, -348, -382, -501, },
|
||||
{ +2508, +2594, +1005, +2823, +1909, +401, +624, +677, +80, +149, +1195, +622, +765, +1450, +899, +441, +488, -3, -301, -63, -155, -197, -378, -249, +15, -114, -216, -325, -386, -326, -435, -465, },
|
||||
{ +2206, +2342, +933, +2683, +2333, +903, +669, +761, +492, +499, +1258, +984, +954, +1127, +508, -78, +61, +24, -139, -253, -442, -276, -171, -30, -76, -244, -225, -191, -331, -440, -399, -321, },
|
||||
{ +1974, +2815, +1553, +2323, +2233, +1046, +992, +1282, +753, +707, +1323, +599, +390, +690, +158, -204, -61, -149, -350, -307, -284, -187, -98, -47, -143, -282, -239, -272, -323, -315, -319, -272, },
|
||||
{ +1654, +2776, +1836, +2401, +3022, +1959, +967, +1094, +948, +444, +652, +267, +140, +546, +166, -270, -194, -277, -387, -222, -184, -102, -101, -213, -211, -214, -174, -207, -336, -339, -249, -198, },
|
||||
{ +1869, +3354, +2494, +2832, +2716, +1654, +1450, +1127, +173, -258, +546, +432, -146, +288, +167, -560, -266, -9, -321, -261, -193, -155, -101, -190, -238, -205, -240, -223, -233, -279, -241, -223, },
|
||||
{ +2251, +4370, +3095, +2273, +2143, +1471, +1134, +828, +318, +171, +218, -108, -7, +202, -108, -329, -135, -186, -250, -123, -231, -173, -170, -206, -184, -240, -217, -223, -224, -243, -163, -183, },
|
||||
{ +2659, +4415, +2723, +1899, +1660, +1369, +1422, +927, +331, +708, +366, -215, -222, -87, +228, -79, -456, -205, +38, -181, -201, -158, -281, -171, -233, -218, -175, -209, -188, -206, -158, -146, },
|
||||
{ +2110, +3925, +2617, +1488, +1521, +1321, +1000, +1375, +1006, +577, +1002, +281, -242, +99, -57, -249, -82, -20, -257, -120, -41, -272, -333, -251, -182, -210, -176, -126, -157, -179, -176, -194, },
|
||||
{ +1815, +3251, +2187, +1550, +1381, +941, +1057, +773, +515, +1445, +1370, +807, +715, +171, +116, +49, -344, -256, +25, -69, -365, -300, -115, -199, -312, -112, -74, -117, -199, -216, -192, -267, },
|
||||
{ +1453, +2017, +1172, +1714, +1993, +1501, +661, -199, +441, +1198, +925, +1207, +1374, +1313, +1201, +202, -18, +29, -479, -298, -15, -198, -383, -148, -84, -172, -178, -112, -77, -224, -241, -216, },
|
||||
{ +1882, +2639, +981, +885, +1287, +1149, +657, -264, +342, +1130, +630, +742, +1292, +1636, +1472, +886, +568, +182, -94, -158, -412, -373, +6, -144, -402, -52, +23, -169, -270, -217, -171, -242, },
|
||||
{ +2138, +2960, +1101, +1064, +1446, +1136, +291, -438, +715, +1105, +64, +265, +594, +767, +1266, +1060, +858, +969, +438, -42, -101, -297, -344, -218, -121, -114, -231, -67, -73, -307, -272, -133, },
|
||||
{ +2460, +3291, +1078, +1222, +1735, +1211, -80, -710, +954, +1086, -141, +205, +328, +431, +693, +253, +688, +1146, +655, +645, +331, -174, -61, -188, -361, -99, -16, -187, -277, -187, -156, -227, },
|
||||
{ +2893, +3811, +1105, +1203, +1818, +1171, -395, -714, +1243, +818, -421, +245, +254, +371, +579, -124, +129, +613, +507, +652, +517, +400, +268, -71, -95, -9, -228, -164, -144, -359, -299, -148, },
|
||||
{ +3308, +4221, +1114, +1356, +2071, +1044, -891, -658, +1576, +583, -594, +223, +142, +308, +585, -177, -43, +346, +34, +199, +317, +405, +505, +368, +236, +145, +52, -93, -322, -363, -224, -252, },
|
||||
{ +3900, +4867, +998, +1260, +2220, +839, -1162, -422, +1621, +246, -664, +254, +85, +242, +512, -240, -75, +270, -146, -7, -102, +10, +325, +287, +509, +621, +248, +30, -87, -358, -365, -226, },
|
||||
{ +4379, +5375, +1025, +1329, +2414, +620, -1641, -92, +1872, -196, -752, +327, -63, +215, +556, -301, -147, +211, -180, -88, -262, -176, -67, -67, +404, +602, +521, +379, +47, -155, -101, -270, },
|
||||
{ +4917, +5923, +933, +1451, +2663, +215, -2061, +412, +1970, -661, -792, +379, -89, +99, +514, -309, -198, +208, -222, -155, -360, -296, -176, -258, +109, +365, +340, +336, +360, +108, +10, -101, },
|
||||
{ +5325, +6387, +1044, +1617, +2857, -114, -2569, +894, +2226, -1191, -880, +471, -93, +10, +443, -288, -328, +216, -163, -257, -444, -325, -267, -361, +2, +132, +152, +154, +168, +115, +205, +89, },
|
||||
{ +5680, +6946, +1250, +1595, +2986, -178, -3103, +1203, +2516, -1694, -900, +579, -179, -49, +355, -219, -348, +53, -131, -293, -494, -294, -363, -474, -96, +59, +126, -24, -77, -107, +65, +185, },
|
||||
{ +6420, +7593, +839, +1808, +3146, -725, -3065, +1505, +2329, -1963, -819, +612, -243, -161, +340, -128, -458, -62, -108, -328, -544, -296, -472, -531, -38, -40, +40, -115, -239, -173, -70, -95, },
|
||||
{ +6890, +8125, +798, +2033, +3239, -1037, -3175, +1581, +2439, -2196, -937, +706, -276, -254, +344, -74, -579, -163, -59, -291, -673, -428, -436, -541, -74, -59, -108, -153, -248, -283, -175, -228, },
|
||||
{ +7112, +8504, +1011, +2420, +3353, -1361, -3255, +1549, +2556, -2243, -1200, +741, -167, -319, +199, +28, -584, -316, +19, -391, -797, -406, -435, -548, -248, -164, +60, -169, -402, -374, -175, -285, },
|
||||
{ +7285, +8820, +1447, +2597, +3239, -1169, -3229, +1126, +2635, -2125, -1498, +885, -99, -519, +165, +47, -347, -428, -288, -299, -829, -481, -398, -641, -383, -145, +82, -141, -416, -423, -333, -478, },
|
||||
{ +7520, +8869, +2021, +2814, +2876, -582, -3127, +494, +2536, -1844, -1576, +724, +34, -625, -7, +239, -155, -630, -485, -225, -859, -553, -623, -612, -241, -315, +42, -51, -367, -610, -501, -479, },
|
||||
{ +7879, +8478, +2398, +3646, +2683, -425, -3110, +367, +2156, -1723, -1287, +263, +38, -359, -259, +217, +107, -737, -613, -82, -1068, -775, -685, -547, -228, -402, +0, +62, -472, -776, -425, -752, },
|
||||
{ +8205, +7639, +2366, +5376, +3131, -1245, -3272, +1332, +1408, -2244, -393, -194, -320, +234, -603, -6, +519, -774, -631, -35, -1347, -848, -738, -677, -167, -469, +8, -127, -364, -733, -690, -706, },
|
||||
{ +9071, +7121, +1359, +7044, +3754, -2464, -2808, +2381, +60, -2776, +793, -372, -1036, +563, -545, -275, +838, -803, -718, +19, -1374, -976, -1066, -680, +3, -628, -230, -55, -414, -742, -545, -882, },
|
||||
{ +10148, +7203, -207, +7831, +4875, -3407, -2535, +3529, -1225, -3617, +2016, -129, -1945, +583, -98, -688, +1031, -623, -939, +116, -1314, -1178, -1259, -633, -72, -818, -379, -21, -446, -673, -502, -1013, },
|
||||
{ +11044, +7769, -1943, +7882, +6483, -3989, -2591, +4784, -2149, -4901, +3054, +635, -2734, +50, +522, -825, +921, -244, -1180, +190, -1284, -1180, -1357, -904, -121, -897, -516, -101, -271, -733, -400, -911, },
|
||||
{ +11990, +8411, -3500, +7279, +8002, -4096, -2789, +6028, -2844, -6395, +3677, +1736, -3160, -867, +846, -555, +671, +81, -1262, +34, -1076, -1221, -1513, -1089, -353, -964, -456, -261, -256, -672, -256, -770, },
|
||||
{ +13335, +8653, -4769, +6560, +8870, -3919, -2715, +7255, -3621, -7665, +3846, +2827, -3088, -1854, +732, -91, +613, +191, -1151, -200, -889, -1355, -1616, -1202, -620, -945, -484, -248, -378, -527, -120, -768, },
|
||||
{ +14852, +8670, -5913, +6073, +9001, -3654, -2195, +8358, -4463, -8616, +3590, +3721, -2575, -2699, +236, +272, +868, +133, -945, -394, -1059, -1238, -1780, -1341, -641, -1048, -561, -27, -440, -570, -19, -740, },
|
||||
{ +16451, +8693, -7064, +5832, +8573, -3576, -1333, +9514, -5301, -9295, +3094, +4207, -1784, -3244, -399, +318, +1449, +54, -659, -662, -1314, -1021, -2073, -1203, -803, -1212, -404, +103, -451, -722, -56, -638, },
|
||||
{ +18423, +8132, -8075, +6128, +7681, -4035, +138, +10573, -6216, -9800, +2747, +4350, -1192, -3295, -1042, +104, +2016, +289, -589, -954, -1505, -917, -2153, -1097, -1071, -1185, -298, +285, -530, -966, -69, -449, },
|
||||
{ +20202, +8717, -10102, +5865, +7549, -3841, +390, +11057, -6161, -10160, +2346, +4324, -998, -3105, -1402, -423, +2652, +520, -1022, -905, -1505, -1084, -2016, -1271, -995, -1072, -334, +432, -570, -1222, +2, -286, },
|
||||
{ +22529, +8456, -11824, +5892, +7303, -4055, +930, +11197, -5866, -10497, +2199, +4298, -1350, -2705, -1409, -1011, +2979, +873, -1590, -561, -1535, -1262, -1879, -1318, -879, -952, -350, +491, -720, -1269, +134, -272, },
|
||||
{ +23974, +9134, -13513, +5844, +7038, -4057, +615, +11611, -4790, -11317, +1983, +4325, -1634, -2352, -1084, -1939, +3123, +1383, -1969, -242, -1583, -1428, -1611, -1435, -861, -839, -383, +423, -787, -1337, +408, -512, },
|
||||
{ +25044, +9817, -14614, +5833, +6675, -4269, -71, +12212, -3614, -11890, +1484, +4440, -1786, -1990, -859, -2687, +2944, +1877, -2005, -175, -1440, -1495, -1418, -1531, -909, -716, -428, +289, -816, -1306, +466, -753, },
|
||||
{ +26536, +9314, -14645, +5829, +6191, -4884, -796, +12908, -2788, -12074, +1081, +4219, -1691, -1613, -960, -3033, +2556, +2030, -1647, -335, -1214, -1268, -1603, -1435, -985, -580, -535, +122, -796, -1260, +177, -737, },
|
||||
{ +27183, +9606, -14376, +5620, +5875, -5416, -2052, +13586, -1628, -12058, +571, +3654, -1110, -1358, -1213, -3155, +2048, +1957, -895, -643, -907, -799, -1977, -1199, -984, -549, -700, +25, -836, -1353, +35, -751, },
|
||||
{ +27148, +10286, -13645, +5373, +5534, -6103, -3440, +14036, -378, -11705, -177, +2878, -226, -1089, -1747, -3125, +1710, +1453, +80, -816, -863, -89, -2314, -1012, -907, -744, -724, -326, -1037, -1054, -249, -864, },
|
||||
{ +26584, +11121, -12486, +5232, +5105, -6806, -4740, +13839, +1078, -11022, -1066, +2034, +722, -813, -2405, -2897, +1499, +637, +937, -473, -1208, +661, -2238, -1145, -718, -867, -1215, -685, -932, -951, -292, -941, },
|
||||
{ +25805, +11950, -11123, +5119, +4637, -7115, -6017, +12797, +2771, -10082, -1948, +1322, +1341, -452, -2821, -2640, +1355, -222, +1382, +402, -1584, +1029, -1649, -1467, -434, -1354, -1712, -685, -1153, -608, -115, -1081, },
|
||||
{ +24754, +12672, -9499, +5075, +3967, -6831, -7500, +11069, +4769, -9261, -2671, +911, +1238, +136, -2811, -2628, +1336, -1074, +1459, +1369, -1523, +816, -817, -1570, -995, -1254, -2045, -954, -1214, -280, +201, -1144, },
|
||||
{ +23625, +13743, -8416, +5130, +3177, -5952, -8511, +8195, +6835, -8201, -3226, +701, +799, +463, -2132, -2701, +1161, -1431, +1042, +2182, -1162, +681, -474, -1699, -1321, -1011, -2142, -1212, -1223, -47, +480, -1192, },
|
||||
{ +22165, +15115, -7785, +5546, +2568, -5733, -8429, +4589, +8489, -6649, -4078, +663, +623, +133, -953, -2723, +670, -1020, -128, +2751, -525, +300, -532, -1412, -1518, -711, -1869, -1605, -920, -465, +529, -917, },
|
||||
{ +22262, +14424, -6906, +6480, +1678, -6039, -7848, +2265, +8205, -4418, -5059, +773, +1015, -648, +127, -2327, +238, -660, -1047, +2455, +302, -278, -464, -941, -1372, -464, -1422, -1493, -1408, -881, +595, -495, },
|
||||
{ +21426, +14579, -5798, +6478, +1251, -5676, -7497, -360, +8046, -2301, -6017, +896, +1618, -1474, +1197, -1714, -587, -84, -1747, +1143, +1103, -253, -569, -193, -1153, -2, -1077, -1593, -1678, -1403, +210, -122, },
|
||||
{ +19944, +15360, -4754, +5956, +1176, -5025, -7238, -2954, +7860, -653, -6260, +621, +2153, -1709, +1912, -1547, -1249, +742, -2688, +57, +1079, +401, -432, +447, -710, -64, -484, -1682, -1600, -2206, -540, +94, },
|
||||
{ +20147, +14018, -3775, +6372, +90, -4104, -7066, -4495, +7159, +825, -6523, +620, +3112, -2199, +2066, -1581, -1430, +939, -2947, -332, +348, +613, +1047, +312, -702, +618, -378, -1616, -1651, -2440, -1434, -218, },
|
||||
{ +19984, +13391, -3853, +7072, -294, -4065, -6337, -5631, +5959, +2227, -6012, -65, +4276, -2601, +1149, -793, -2128, +1041, -2372, -946, +540, +152, +1289, +1452, -1002, +964, +82, -1959, -1450, -2309, -2165, -747, },
|
||||
{ +20430, +12454, -5495, +8998, +65, -5776, -5336, -5251, +4459, +2909, -5003, -707, +4833, -2860, -19, +113, -2229, +469, -1412, -634, +320, -217, +361, +2809, -484, +184, +1137, -2340, -1770, -1410, -2528, -1555, },
|
||||
{ +21692, +10456, -7798, +12335, +68, -8763, -3715, -3473, +2378, +2906, -3129, -2190, +5102, -2356, -1660, +915, -1539, -297, -715, +276, -315, -459, +27, +2282, +814, +228, +658, -1653, -2043, -1236, -2088, -2094, },
|
||||
{ +22414, +8463, -8975, +14734, -856, -9903, -2019, -2434, +827, +2536, -1717, -3048, +4909, -1972, -2551, +1285, -549, -637, -715, +674, -143, -626, -627, +1991, +1177, +722, +464, -1119, -1865, -1815, -1391, -1829, },
|
||||
{ +22530, +6646, -9511, +16483, -1322, -11024, -644, -496, -1479, +1598, +531, -3996, +3822, -711, -2705, +845, +188, -390, -681, +346, -68, -65, -1383, +1684, +1452, +284, +1178, -797, -2128, -1411, -1375, -1644, },
|
||||
{ +21322, +5400, -8796, +17260, -1500, -11305, +474, +113, -2907, +1438, +1455, -4669, +3322, +481, -2925, +742, +471, -590, -202, +63, -265, +281, -1317, +1179, +1229, +431, +1123, -441, -2004, -992, -1149, -2020, },
|
||||
{ +19175, +5030, -7462, +16622, -929, -10530, +416, +343, -3120, +766, +1767, -4343, +2822, +1079, -2638, +519, +570, -563, -289, +165, -315, +82, -803, +997, +763, +599, +901, -468, -1286, -794, -1066, -1838, },
|
||||
{ +16819, +5384, -6370, +14965, +290, -9700, +208, +612, -3392, +183, +2183, -3797, +2080, +1803, -2493, -16, +1023, -550, -707, +329, -153, -121, -550, +1037, +727, +224, +746, -397, -1126, -361, -1019, -1629, },
|
||||
{ +14912, +6709, -4328, +10591, -498, -7109, +111, -741, -770, +328, -733, -960, +2191, +30, -1474, -311, +350, -380, -1280, +108, +235, +180, +74, +223, +54, +624, +423, -99, +35, -79, -285, -105, },
|
||||
{ +12603, +6186, -2629, +9885, -405, -6060, +108, -976, -537, +418, -737, -896, +2184, +171, -1454, -339, +212, -324, -1080, +111, +88, +93, +170, +250, +211, +621, +320, -131, +116, -1, -403, -106, },
|
||||
{ +10408, +5748, -848, +8724, -167, -4613, -400, -1217, -70, +524, -929, -678, +2111, +202, -1239, -402, +223, -337, -970, +153, +57, +16, +164, +314, +375, +524, +121, +6, +131, -34, -146, -32, },
|
||||
{ +8810, +5752, -110, +7195, +525, -3549, -713, -1201, +150, +589, -802, -524, +1697, +366, -971, -531, +153, -232, -820, +124, +74, +31, +92, +425, +518, +160, +114, +336, +59, -121, +192, +176, },
|
||||
{ +7707, +5602, +35, +6275, +1122, -3180, -685, -740, +80, +415, -374, -403, +1135, +566, -689, -718, +117, -57, -675, +45, +161, +35, +47, +597, +362, +73, +358, +355, +34, +128, +414, +95, },
|
||||
{ +7097, +5535, -192, +5388, +1340, -2724, -316, -506, -92, +415, +68, -445, +787, +694, -670, -663, +194, +20, -606, +105, +221, -83, +318, +654, +165, +211, +501, +464, +163, +305, +282, -143, },
|
||||
{ +6452, +5181, -188, +4851, +1397, -2250, -47, -387, -147, +524, +273, -528, +602, +655, -502, -522, +157, +53, -489, +203, +143, +158, +611, +321, +242, +571, +633, +422, +125, +234, -5, -218, },
|
||||
{ +5779, +4631, +28, +4565, +1363, -1816, +67, -196, +8, +488, +200, -488, +649, +572, -444, -381, +184, +6, -287, +343, +218, +465, +530, +350, +563, +605, +532, +190, +1, +83, -90, -218, },
|
||||
{ +5208, +4384, +145, +3924, +1403, -1285, +290, -147, -75, +540, +306, -396, +492, +507, -283, -289, +166, +176, +48, +344, +475, +764, +468, +481, +475, +299, +347, +79, -73, +8, -92, -335, },
|
||||
{ +4512, +3969, +359, +3651, +1556, -960, +277, -42, +99, +522, +205, -303, +469, +444, -138, -122, +272, +416, +283, +588, +781, +710, +302, +187, +175, +216, +260, +77, -143, -145, -168, -400, },
|
||||
{ +3801, +3629, +701, +3369, +1505, -562, +487, -64, +147, +580, +155, -276, +520, +581, +54, +7, +535, +858, +532, +711, +669, +180, +6, +159, +92, +196, +192, -93, -202, -135, -272, -498, },
|
||||
{ +3442, +3530, +703, +2812, +1660, -44, +424, -101, +187, +562, +336, -54, +523, +647, +416, +546, +884, +888, +356, +303, +242, +72, +10, +71, +14, +72, +66, -163, -241, -221, -397, -501, },
|
||||
{ +2690, +3000, +1279, +2876, +1515, +205, +493, -52, +442, +658, +264, +192, +1000, +1052, +635, +643, +744, +413, +42, +208, +138, +112, -80, -143, -63, -30, +7, -171, -300, -327, -429, -392, },
|
||||
{ +2478, +3269, +1270, +2133, +1692, +521, +531, +45, +514, +1060, +829, +686, +1118, +1030, +491, +45, +183, +420, +250, +132, -125, -159, -155, -121, -114, -108, -174, -265, -205, -328, -363, -352, },
|
||||
{ +1870, +2687, +1568, +2459, +1988, +651, +612, +481, +1093, +1477, +1114, +836, +591, +278, +48, +164, +470, +379, -76, -182, +38, -195, -357, -228, -185, -143, -188, -137, -211, -282, -321, -361, },
|
||||
{ +2002, +3298, +2072, +1782, +1264, +1387, +2004, +1233, +1029, +1042, +338, -15, +176, +284, +423, +207, -57, +116, -13, -210, -269, -453, -350, -132, -143, -177, -143, -97, -213, -359, -341, -306, },
|
||||
{ +2146, +3307, +2355, +2752, +2119, +1859, +2021, +710, +97, +234, +110, +124, +235, +191, +340, -11, -121, +97, -245, -337, -346, -487, -277, -43, -78, -145, -151, -149, -204, -284, -366, -347, },
|
||||
{ +2369, +3977, +3947, +3602, +1697, +1277, +778, -51, +139, +274, +157, +44, -14, +65, +388, -56, -226, -108, -386, -368, -349, -275, -166, -135, -161, -68, -48, -184, -269, -324, -303, -300, },
|
||||
{ +2991, +5611, +4893, +2413, +32, +530, +1206, +716, -81, -249, -72, +167, +231, -189, +96, +62, -289, -321, -341, -226, -287, -249, -289, -147, -48, -120, -84, -169, -256, -385, -287, -211, },
|
||||
{ +3480, +5919, +3215, +1230, +711, +1536, +1856, +445, -348, +146, +147, -235, +202, -60, -65, -10, -330, -145, -168, -321, -230, -233, -366, -152, -34, -139, -131, -161, -196, -267, -285, -233, },
|
||||
{ +2004, +3234, +1971, +1898, +2099, +2208, +2155, +993, +558, +802, +440, -18, -153, -3, +129, -234, -279, -55, -99, -109, -245, -275, -242, -234, -224, -178, -205, -148, -89, -176, -206, -280, },
|
||||
{ +1279, +2318, +1457, +1126, +1665, +2069, +1778, +1033, +1441, +1718, +1054, +741, +475, +244, +79, -171, -166, -218, -231, -69, -145, -125, -126, -248, -153, -180, -287, -235, -255, -196, -120, -109, },
|
||||
{ +1453, +2492, +1452, +1154, +1435, +1406, +842, +362, +1287, +1720, +1252, +1179, +1008, +731, +566, +64, -227, -101, -154, -275, -230, -121, -97, -71, -157, -175, -212, -268, -250, -286, -220, -166, },
|
||||
{ +1879, +2842, +1125, +1084, +1653, +1253, +390, -18, +973, +1151, +667, +1023, +1287, +1158, +966, +422, +174, +136, -200, -125, -209, -336, -116, -116, -96, -37, -181, -264, -245, -282, -257, -233, },
|
||||
{ +2149, +3242, +1318, +1052, +1535, +1017, +118, +168, +1096, +645, +127, +653, +733, +907, +1209, +756, +503, +444, +179, +76, -160, -223, -173, -251, -109, -40, -121, -158, -228, -282, -247, -243, },
|
||||
{ +2317, +3435, +1467, +1216, +1790, +944, -476, +147, +1327, +465, +25, +491, +329, +437, +651, +458, +687, +794, +439, +296, +209, +11, -156, -194, -142, -157, -160, -145, -173, -218, -241, -271, },
|
||||
{ +2632, +3865, +1576, +1194, +1850, +818, -747, +351, +1336, +91, -24, +570, +326, +220, +377, +87, +100, +501, +607, +596, +401, +255, +179, -41, -117, -38, -173, -278, -200, -177, -186, -241, },
|
||||
{ +2913, +4307, +1690, +1174, +1997, +721, -1042, +507, +1361, -158, -88, +596, +317, +156, +293, -13, -74, +80, +115, +344, +456, +579, +399, +152, +182, +78, -95, -162, -227, -292, -160, -212, },
|
||||
{ +3419, +4851, +1663, +1035, +2035, +628, -1177, +737, +1236, -536, -64, +690, +334, +51, +172, -13, -135, -42, -10, -2, -68, +347, +513, +426, +347, +211, +168, -24, -193, -236, -186, -272, },
|
||||
{ +3767, +5304, +1782, +1016, +2102, +463, -1378, +1048, +1239, -936, -179, +746, +362, +62, +89, -105, -187, -70, -33, -113, -245, -31, +98, +248, +442, +396, +305, +172, +12, -165, -166, -183, },
|
||||
{ +4285, +5774, +1650, +1174, +2192, +50, -1405, +1467, +1118, -1334, -217, +829, +333, +12, +50, -124, -225, -140, -22, -146, -307, -135, -82, -31, +86, +236, +387, +312, +118, +25, +51, -123, },
|
||||
{ +4848, +6188, +1491, +1445, +2261, -490, -1401, +1942, +965, -1671, -300, +836, +385, -47, +8, -178, -306, -200, +51, -186, -351, -153, -292, -30, +25, -103, +13, +150, +219, +188, +112, +17, },
|
||||
{ +5454, +6649, +1314, +1669, +2321, -943, -1366, +2334, +803, -1890, -325, +781, +385, -83, +115, -228, -488, -225, +76, -126, -377, -187, -365, -53, +30, -174, -150, -173, -42, +89, +185, +106, },
|
||||
{ +5926, +7107, +1339, +1747, +2383, -1252, -1530, +2755, +780, -2246, -303, +735, +323, -85, +73, -145, -589, -384, +135, -187, -469, -43, -386, -191, +46, -215, -180, -236, -326, -211, +7, +83, },
|
||||
{ +6333, +7526, +1384, +2014, +2467, -1782, -1590, +3195, +714, -2494, -349, +719, +280, -145, +55, -69, -636, -504, +150, -221, -574, -43, -314, -228, -37, -138, -204, -369, -416, -299, -97, -205, },
|
||||
{ +6696, +8017, +1498, +2006, +2624, -2005, -1798, +3417, +748, -2614, -432, +706, +173, -173, +53, -56, -573, -718, +132, -67, -717, -164, -301, -196, -38, -159, -197, -465, -469, -327, -185, -358, },
|
||||
{ +6930, +8687, +1750, +1599, +2863, -1765, -2210, +3311, +900, -2491, -605, +596, +191, -265, +91, -35, -551, -808, +27, +34, -661, -338, -391, -71, -59, -282, -167, -426, -499, -386, -346, -349, },
|
||||
{ +7032, +9112, +2294, +1319, +2928, -1295, -2725, +3058, +1141, -2349, -736, +409, +218, -319, +37, -5, -474, -896, -105, +108, -719, -327, -414, -210, -8, -342, -280, -290, -610, -529, -264, -398, },
|
||||
{ +7290, +9148, +2788, +1517, +2890, -1004, -3145, +2936, +1182, -2207, -713, +170, +226, -310, -137, +66, -236, -1052, -288, +218, -703, -396, -407, -298, -61, -288, -332, -407, -637, -624, -99, -427, },
|
||||
{ +8295, +8777, +2246, +2812, +2858, -1707, -2793, +3041, +460, -1834, -416, -196, +229, -361, -255, +143, -68, -1152, -427, +236, -539, -557, -489, -199, -168, -280, -301, -623, -729, -417, -190, -475, },
|
||||
{ +8813, +8385, +2070, +3791, +3408, -2249, -3089, +3581, -338, -1829, +311, -486, -198, -209, -270, -126, +417, -1313, -692, +394, -483, -630, -627, -124, -246, -308, -391, -642, -737, -489, -253, -480, },
|
||||
{ +9480, +7764, +1344, +5665, +3938, -3530, -2582, +4359, -1779, -1905, +1349, -610, -594, -360, -91, -401, +691, -1075, -1088, +435, -349, -619, -660, -124, -373, -324, -465, -444, -823, -782, -95, -634, },
|
||||
{ +10219, +7759, +108, +6635, +4903, -4328, -2227, +5026, -3212, -2275, +2513, -596, -1046, -594, +196, -690, +587, -537, -1473, +302, -113, -638, -684, -100, -439, -459, -480, -472, -766, -889, -314, -724, },
|
||||
{ +11359, +8080, -1537, +6725, +6202, -4589, -2055, +5443, -4331, -2746, +3483, -358, -1535, -803, +500, -787, +107, +0, -1473, -127, +202, -644, -687, +80, -605, -513, -488, -741, -549, -859, -768, -615, },
|
||||
{ +12561, +8515, -3181, +6443, +7273, -4422, -1771, +5642, -5238, -3343, +4113, +235, -1988, -1143, +783, -757, -401, +173, -1070, -614, +288, -431, -703, +306, -751, -608, -594, -870, -585, -862, -824, -695, },
|
||||
{ +13637, +9078, -4327, +5307, +8230, -3683, -1700, +6016, -6052, -3983, +4365, +989, -2192, -1647, +1018, -629, -785, -62, -507, -850, +26, -33, -720, +529, -810, -802, -657, -1006, -784, -809, -610, -865, },
|
||||
{ +14620, +9720, -5196, +3985, +8621, -2703, -1406, +6384, -6867, -4537, +4323, +1689, -2163, -2167, +1076, -438, -1009, -536, -136, -784, -345, +300, -530, +532, -827, -847, -766, -1246, -914, -773, -428, -804, },
|
||||
{ +16072, +9930, -6183, +3360, +8255, -2295, -119, +6470, -7878, -4616, +4153, +2063, -2029, -2471, +1020, -386, -950, -1040, -67, -497, -520, +425, -98, +296, -886, -669, -1038, -1392, -1030, -835, -225, -497, },
|
||||
{ +17538, +10139, -7275, +3167, +7496, -2312, +1507, +6655, -8887, -4746, +4122, +2161, -1895, -2506, +749, -326, -908, -1248, -345, -284, -377, +510, +186, +31, -841, -583, -1261, -1430, -1259, -849, -50, -134, },
|
||||
{ +18795, +10599, -8283, +2946, +6835, -2703, +2875, +7278, -9742, -5079, +4325, +2043, -1829, -2306, +376, -514, -590, -1442, -695, -362, +63, +785, +55, -22, -629, -692, -1264, -1504, -1464, -809, +17, +195, },
|
||||
{ +19828, +11378, -9267, +2629, +6374, -3347, +3612, +8402, -10339, -5537, +4515, +1859, -1884, -1929, -100, -800, -262, -1561, -976, -577, +410, +1421, -419, +34, -250, -981, -1080, -1605, -1632, -802, +11, +380, },
|
||||
{ +21206, +11505, -9851, +2389, +6035, -4347, +4232, +9433, -10759, -5759, +4577, +1581, -1877, -1583, -452, -1192, +46, -1648, -1025, -873, +537, +2263, -927, +52, +224, -1290, -882, -1564, -1935, -752, -159, +454, },
|
||||
{ +21951, +12180, -10180, +1892, +5955, -5226, +3946, +10828, -10791, -5984, +4342, +1308, -1588, -1445, -711, -1558, +306, -1741, -844, -1199, +362, +3030, -1015, -204, +814, -1397, -873, -1354, -2329, -849, -416, +417, },
|
||||
{ +22506, +12779, -10294, +1612, +5688, -5970, +3299, +11834, -10475, -5915, +3858, +872, -1070, -1438, -1116, -1691, +435, -1836, -594, -1442, -11, +3401, -605, -538, +1220, -1085, -1193, -1113, -2738, -1072, -644, +153, },
|
||||
{ +23186, +13097, -10391, +2031, +4838, -6522, +2825, +12019, -9671, -5661, +3239, +340, -378, -1439, -1649, -1540, +599, -1995, -278, -1529, -462, +3340, +152, -492, +1137, -401, -1605, -1222, -2820, -1325, -987, -68, },
|
||||
{ +22882, +14119, -9689, +1389, +4734, -6999, +1524, +12257, -8386, -5521, +2330, +28, +188, -1505, -1990, -1510, +944, -2230, -172, -1187, -1194, +2809, +1343, -197, +605, +402, -2099, -1365, -2620, -1824, -1038, -503, },
|
||||
{ +21870, +15422, -8022, +32, +4928, -6961, -638, +12423, -6481, -5741, +1679, -358, +537, -1263, -2316, -1338, +1170, -2350, -127, -788, -1648, +1934, +2335, +603, -234, +775, -1895, -1692, -2402, -2007, -1134, -816, },
|
||||
{ +21377, +15848, -6611, -135, +4095, -6589, -2340, +11613, -4347, -6089, +1401, -892, +589, -722, -2599, -1204, +1299, -2460, -64, -474, -1793, +1309, +2278, +1468, -710, +729, -1381, -1948, -2200, -1989, -1059, -1104, },
|
||||
{ +21825, +15338, -6288, +1723, +2245, -6807, -2394, +9743, -2760, -5631, +785, -1266, +822, -455, -2395, -1291, +1244, -2162, -287, +63, -1716, +759, +1340, +2033, -170, +136, -645, -1936, -2205, -1413, -1181, -1687, },
|
||||
{ +22088, +14986, -6294, +3940, +475, -7388, -1931, +7563, -1485, -4751, -302, -1228, +1282, -606, -1733, -1685, +1011, -1322, -834, +679, -1560, -371, +652, +2168, +634, +122, -548, -1338, -1967, -1463, -1230, -1785, },
|
||||
{ +21218, +15763, -6154, +5244, -207, -8203, -1741, +5343, +1, -4070, -1324, -1042, +1940, -1042, -1041, -1719, +173, +234, -1546, +421, -980, -1263, -189, +2163, +1362, +537, -295, -894, -1836, -1649, -862, -1860, },
|
||||
{ +20943, +15351, -5193, +5824, -681, -8421, -2182, +3733, +912, -3280, -2125, -629, +2393, -1338, -793, -1272, -318, +619, -1449, -542, -613, -929, -1049, +1622, +1869, +1834, -606, -1014, -899, -1858, -1052, -1583, },
|
||||
{ +20467, +15036, -4299, +6074, -972, -8163, -2993, +2103, +1953, -2525, -2906, +84, +2478, -1496, -381, -1209, -661, +522, -1431, -1137, -494, -29, -1724, +1410, +1857, +2078, +198, -1222, -492, -1845, -1016, -1459, },
|
||||
{ +19997, +14492, -3439, +6231, -1292, -7499, -3870, +428, +3016, -1672, -3589, +505, +3009, -1682, -424, -1271, -888, +168, -1633, -640, -998, +512, -655, +572, +1038, +2022, +1564, -1436, -837, -970, -1064, -1590, },
|
||||
{ +19121, +13891, -1956, +5864, -1769, -5712, -5524, -1209, +4728, -1224, -4384, +1529, +2886, -1835, -216, -2037, -717, +368, -2459, +62, -470, -20, +501, +397, +27, +1794, +1472, -406, -774, -1035, -530, -1651, },
|
||||
{ +18795, +12787, -866, +5679, -2785, -3778, -6009, -3416, +6104, -148, -5120, +1968, +2942, -2232, -361, -2334, -318, +255, -2810, +772, +147, -722, +931, +1048, -622, +926, +926, +464, +8, -1388, -195, -1234, },
|
||||
{ +19769, +11583, -2448, +6778, -3321, -3974, -5178, -3690, +5661, +410, -4626, +1587, +2861, -2687, -704, -1965, -264, +354, -2735, +728, +431, -372, +846, +890, -556, +313, +642, +248, +534, -654, -743, -572, },
|
||||
{ +20742, +9918, -4333, +9177, -3673, -5562, -3412, -3017, +4558, +903, -4422, +932, +3308, -2821, -1440, -1193, +107, +341, -2476, +352, +665, +234, +482, +681, -223, -107, +450, +161, +378, +311, -786, -592, },
|
||||
{ +20393, +8513, -5551, +11591, -3341, -7618, -1960, -1344, +2974, +225, -3410, +284, +3332, -2616, -1768, -458, +23, +66, -1947, +502, +187, +334, +642, +553, -324, +98, +28, -212, +831, +137, -320, -307, },
|
||||
{ +19863, +7195, -5891, +13080, -3237, -8975, -179, -735, +1159, +597, -2780, -566, +3377, -1932, -1835, -26, +57, -431, -1301, +563, -286, +265, +803, +515, -423, +180, +122, -246, +644, +165, -191, +77, },
|
||||
{ +18658, +6850, -5751, +12388, -2703, -7823, +255, -1504, +610, +770, -2248, -983, +3161, -1268, -1738, +128, -21, -478, -1161, +338, -70, +251, +391, +591, -323, +20, +528, -36, +54, +115, -36, +34, },
|
||||
{ +17076, +6736, -5238, +11355, -1525, -7217, -40, -1078, -147, +458, -1371, -990, +2637, -628, -1439, -189, +204, -339, -1390, +203, +285, +214, +63, +453, -132, +311, +558, +23, -66, -152, +62, -43, },
|
||||
{ +13623, +7663, -736, +5443, -2593, -2244, -1530, -1649, +1729, -32, -2266, +999, +1978, -1230, -677, -1107, +219, -259, -1521, +393, -253, -340, +340, +425, +603, +1120, -212, -683, -191, -585, -148, +387, },
|
||||
{ +11820, +7583, -426, +4965, -1356, -2529, -1167, -1245, +983, +124, -1778, +794, +1769, -842, -700, -980, +259, -378, -1380, +412, -355, -376, +513, +422, +537, +830, -258, -264, -158, -658, +7, +383, },
|
||||
{ +10321, +7312, -105, +4864, -813, -2658, -650, -1140, +594, +154, -1345, +747, +1470, -560, -589, -773, +109, -428, -1061, +264, -409, -228, +464, +450, +557, +455, -229, +107, -87, -614, +63, +459, },
|
||||
{ +8832, +6788, +754, +4529, -737, -2058, -537, -1141, +593, +102, -1073, +689, +1331, -427, -481, -535, -57, -390, -871, +136, -280, -172, +355, +496, +482, +211, +7, +299, +18, -389, +32, +568, },
|
||||
{ +7264, +6341, +1804, +3830, -547, -1150, -702, -1198, +746, +193, -1033, +629, +1243, -340, -243, -463, -211, -272, -673, +38, -232, -89, +255, +491, +349, +237, +305, +440, +181, -306, +96, +481, },
|
||||
{ +5764, +5793, +2760, +3310, -250, -431, -863, -1206, +942, +277, -1025, +490, +1124, +11, -135, -654, -133, +3, -652, -89, -115, -120, +324, +473, +214, +489, +656, +578, +94, -300, +162, +271, },
|
||||
{ +4877, +5432, +2934, +2887, +9, -98, -665, -1051, +773, +328, -754, +397, +892, +204, -54, -717, +22, +137, -707, -136, -8, -16, +384, +457, +358, +804, +826, +406, -152, -241, +83, +160, },
|
||||
{ +4273, +4974, +2996, +2688, +19, +236, -317, -1082, +645, +529, -499, +171, +725, +487, -28, -702, +171, +109, -663, +33, +8, +168, +685, +509, +520, +907, +639, +123, -222, -249, +142, +242, },
|
||||
{ +3881, +4471, +2801, +2721, +214, +232, -276, -784, +726, +443, -495, +187, +790, +514, -89, -624, +292, +140, -590, +200, +269, +545, +770, +316, +532, +788, +265, -82, -82, -100, +41, +29, },
|
||||
{ +3766, +4300, +2408, +2391, +333, +347, -106, -602, +651, +407, -345, +364, +720, +250, +52, -284, +220, +186, -143, +547, +529, +560, +390, +206, +482, +471, +188, -7, -119, -170, +39, -9, },
|
||||
{ +3436, +3912, +2322, +2385, +450, +371, -77, -417, +729, +455, -307, +332, +707, +317, +188, -91, +487, +565, +170, +463, +431, +296, +60, +230, +424, +421, +106, -107, -113, -167, +28, -121, },
|
||||
{ +3183, +3685, +2212, +2271, +537, +324, +19, -108, +778, +330, -270, +582, +667, +327, +729, +405, +569, +537, +26, +242, +252, -24, +148, +398, +218, +251, +64, -101, -137, -167, -61, -180, },
|
||||
{ +2975, +3602, +2238, +1946, +368, +615, +350, -208, +659, +572, -66, +604, +1024, +904, +959, +291, +202, +264, -144, +133, +221, +2, +109, +243, +252, +133, -64, -129, -180, -137, -144, -273, },
|
||||
{ +2802, +3321, +2156, +2179, +535, +317, +283, +375, +791, +445, +493, +1260, +1224, +697, +585, -84, -52, +130, -53, +215, +5, -34, +157, +233, +121, -41, -96, -197, -124, -177, -272, -304, },
|
||||
{ +2567, +3351, +2539, +1843, +97, +744, +689, +452, +1235, +1224, +767, +951, +804, +213, +156, -203, +95, +139, -182, +93, +76, +25, +66, +145, -99, -130, -124, -168, -143, -326, -266, -289, },
|
||||
{ +2718, +3449, +2308, +1797, +208, +761, +1522, +1644, +1223, +789, +460, +314, +454, -11, +113, +21, -170, +13, +13, +85, +59, -34, -70, +29, -183, -196, -119, -202, -174, -262, -320, -243, },
|
||||
{ +2540, +3343, +2399, +2066, +1062, +1501, +1604, +1736, +1082, -140, -197, +490, +498, -164, -13, -43, -88, +38, +21, +50, -52, -74, -79, -137, -262, -173, -156, -121, -156, -298, -206, -189, },
|
||||
{ +2234, +3727, +3392, +2599, +1296, +1388, +1575, +990, +120, +142, -3, +141, +343, -173, +83, -53, -176, +87, -65, -57, -14, -108, -214, -261, -285, -100, -90, -157, -152, -234, -209, -204, },
|
||||
{ +2985, +5564, +3761, +1458, +757, +1364, +784, +451, +634, -7, -242, +3, +522, +51, -283, +33, -103, -187, +6, +14, -99, -195, -315, -245, -150, -121, -75, -132, -198, -215, -225, -243, },
|
||||
{ +3536, +5654, +3321, +1733, +414, +394, +1272, +1090, -2, -98, +317, +30, +224, +141, -65, -151, -228, -176, -28, +9, -112, -143, -326, -205, -121, -146, -154, -155, -169, -220, -257, -233, },
|
||||
{ +2423, +4490, +3856, +2307, +306, +542, +1485, +1042, +272, +121, +367, +345, +305, +76, +54, -98, -197, -211, -235, -76, +30, -102, -249, -110, -163, -144, -218, -256, -176, -211, -237, -223, },
|
||||
{ +2207, +4508, +3055, +1310, +930, +958, +1117, +900, +798, +352, +193, +679, +614, +197, +54, +57, -131, -330, -215, -106, -182, -79, -43, -101, -76, -110, -233, -306, -312, -262, -203, -241, },
|
||||
{ +2155, +4216, +2568, +1005, +1213, +966, +459, +898, +1067, +401, +559, +752, +475, +636, +473, -23, -19, +1, -327, -285, -98, -96, -180, -15, +129, -115, -171, -209, -363, -372, -286, -209, },
|
||||
{ +2070, +3883, +2353, +1160, +1380, +728, +99, +912, +928, +215, +528, +873, +808, +593, +419, +448, +247, -17, -66, -137, -244, -204, -83, -38, -42, +64, -18, -242, -235, -315, -412, -310, },
|
||||
{ +2125, +3872, +2333, +1117, +1382, +652, -82, +932, +929, -32, +165, +810, +760, +591, +704, +380, +171, +402, +223, -173, -55, +18, -230, -138, +84, +9, -127, -88, -152, -290, -286, -341, },
|
||||
{ +2204, +3829, +2303, +1430, +1528, +266, -259, +1194, +944, -279, +37, +705, +496, +385, +633, +421, +252, +297, +317, +192, +43, +66, +57, +9, -58, -33, -24, -181, -247, -150, -214, -284, },
|
||||
{ +2377, +4116, +2337, +1342, +1538, +248, -324, +1198, +907, -340, -9, +552, +446, +300, +373, +259, +71, +202, +429, +213, +40, +308, +228, +122, +212, +69, -122, -224, -230, -240, -255, -174, },
|
||||
{ +2547, +4334, +2430, +1433, +1566, +87, -418, +1351, +878, -486, -33, +547, +363, +146, +403, +264, -240, -131, +304, +205, +66, +265, +312, +373, +311, +248, +138, -166, -373, -314, -205, -258, },
|
||||
{ +2830, +4723, +2442, +1353, +1596, +57, -445, +1370, +794, -551, +26, +483, +302, +84, +326, +353, -232, -336, -50, +55, -20, +99, +386, +443, +376, +430, +300, -2, -200, -321, -318, -255, },
|
||||
{ +3101, +5094, +2484, +1317, +1620, -48, -486, +1479, +713, -731, +26, +531, +246, -26, +207, +395, -120, -435, -199, -118, -261, -82, +201, +404, +445, +420, +397, +148, -80, -175, -230, -288, },
|
||||
{ +3513, +5583, +2388, +1169, +1692, -102, -510, +1532, +632, -825, +39, +484, +162, -19, +107, +357, -62, -406, -271, -220, -305, -288, -44, +301, +381, +318, +417, +216, -33, -33, -125, -197, },
|
||||
{ +3971, +6063, +2297, +1049, +1754, -235, -496, +1678, +453, -941, +114, +521, +25, -141, +100, +323, -30, -393, -314, -245, -341, -357, -157, +129, +280, +188, +259, +194, -7, -19, -69, -59, },
|
||||
{ +4462, +6601, +2162, +929, +1825, -406, -449, +1847, +245, -1033, +198, +531, -55, -243, +34, +274, -46, -317, -280, -344, -378, -331, -147, -22, +200, +127, +86, +97, -172, -74, +29, -12, },
|
||||
{ +4929, +7134, +2067, +832, +1905, -671, -420, +2107, +13, -1176, +285, +566, -115, -373, -56, +231, -88, -317, -242, -369, -432, -373, -60, -90, +32, +212, -22, -102, -274, -226, -80, -18, },
|
||||
{ +5380, +7722, +2007, +689, +2018, -933, -447, +2383, -171, -1301, +369, +562, -128, -427, -220, +187, -78, -332, -233, -409, -419, -408, -34, +5, -132, +185, +51, -252, -327, -342, -282, -98, },
|
||||
{ +5728, +8332, +2054, +461, +2152, -1109, -551, +2612, -297, -1395, +446, +591, -229, -430, -303, +22, -78, -336, -214, -416, -470, -471, -25, +180, -147, -54, +113, -193, -423, -380, -487, -230, },
|
||||
{ +6113, +8894, +2133, +278, +2235, -1274, -667, +2769, -471, -1368, +504, +562, -301, -464, -281, -179, -193, -277, -163, -442, -520, -538, -26, +230, -9, -150, -82, -60, -486, -442, -508, -419, },
|
||||
{ +6822, +9262, +1874, +539, +2127, -1579, -524, +2787, -765, -1217, +595, +512, -360, -580, -126, -403, -358, -224, -134, -389, -601, -579, +2, +211, +8, +23, -240, -219, -412, -487, -530, -498, },
|
||||
{ +7515, +9472, +1708, +950, +1940, -1744, -475, +2685, -890, -1100, +601, +523, -322, -777, -22, -467, -558, -250, -104, -316, -558, -673, -18, +285, -56, +161, -229, -389, -420, -494, -565, -489, },
|
||||
{ +7940, +9637, +1858, +1251, +1898, -1722, -763, +2646, -912, -1044, +619, +459, -176, -902, -97, -399, -684, -474, -18, -221, -503, -687, -201, +491, -97, +79, -100, -413, -500, -584, -564, -465, },
|
||||
{ +8437, +9625, +1884, +1715, +2059, -1879, -1105, +2725, -1064, -1040, +741, +338, -154, -826, -248, -438, -648, -774, -57, -33, -524, -628, -313, +497, +49, -120, -60, -285, -620, -701, -513, -517, },
|
||||
{ +9220, +9383, +1442, +2663, +2411, -2496, -1180, +2907, -1426, -1017, +899, +285, -271, -686, -239, -660, -556, -895, -297, +126, -442, -632, -203, +342, +145, -93, -144, -242, -638, -729, -500, -582, },
|
||||
{ +9906, +8999, +886, +4046, +2822, -3537, -956, +3303, -2122, -1097, +1212, +287, -466, -677, -82, -821, -584, -919, -622, +120, -110, -798, -101, +317, +50, +139, -325, -314, -494, -726, -682, -494, },
|
||||
{ +10165, +8622, +635, +5498, +3208, -4703, -409, +3974, -3274, -1343, +1812, +349, -758, -791, +168, -846, -676, -904, -937, -105, +296, -819, -186, +443, -101, +357, -353, -431, -390, -698, -845, -370, },
|
||||
{ +10778, +9125, -461, +5499, +4480, -4885, -762, +4363, -3869, -1600, +2274, +309, -1021, -799, +442, -989, -823, -718, -1054, -519, +402, -449, -376, +548, -68, +372, -259, -484, -358, -718, -919, -405, },
|
||||
{ +11808, +9598, -1631, +4810, +5752, -4539, -1177, +4391, -4229, -1790, +2570, +358, -1408, -786, +715, -1102, -1041, -581, -992, -885, +191, -44, -368, +438, +142, +323, -208, -398, -399, -804, -937, -537, },
|
||||
{ +12864, +10102, -2814, +4041, +6509, -3716, -1366, +4112, -4371, -1965, +2757, +499, -1803, -807, +909, -1173, -1234, -559, -856, -1084, -225, +261, -140, +202, +383, +376, -191, -207, -486, -953, -891, -645, },
|
||||
{ +13770, +10842, -3762, +2948, +6944, -2626, -1423, +3706, -4498, -2054, +2738, +733, -2151, -912, +1063, -1203, -1347, -631, -679, -1132, -639, +290, +229, +18, +464, +552, -134, -53, -593, -1082, -910, -725, },
|
||||
{ +14673, +11578, -4475, +1691, +7096, -1713, -1082, +3280, -4814, -1919, +2563, +861, -2306, -1111, +1114, -1240, -1354, -818, -528, -1086, -897, +19, +528, +85, +343, +790, +8, -1, -705, -1107, -997, -856, },
|
||||
{ +15287, +12615, -5054, +450, +7031, -997, -525, +3136, -5350, -1613, +2407, +806, -2180, -1353, +994, -1181, -1315, -1000, -400, -980, -938, -358, +637, +322, +261, +1020, +234, -8, -727, -1060, -1088, -991, },
|
||||
{ +16341, +13198, -5831, -183, +6631, -925, +450, +3048, -6132, -1100, +2328, +438, -1973, -1456, +665, -1224, -1147, -1229, -302, -819, -969, -597, +502, +511, +258, +1295, +390, -116, -684, -1059, -1180, -1113, },
|
||||
{ +17889, +13289, -7003, +251, +5613, -1102, +1630, +2856, -6736, -544, +2351, -201, -1577, -1545, +280, -1291, -936, -1371, -191, -616, -996, -677, +307, +583, +290, +1693, +557, -380, -523, -1129, -1279, -1128, },
|
||||
{ +19421, +13294, -8130, +984, +4304, -1338, +2588, +2708, -7031, -194, +2313, -845, -1057, -1787, -127, -1222, -940, -1254, -198, -479, -881, -843, +201, +539, +228, +2168, +760, -747, -401, -1194, -1459, -1011, },
|
||||
{ +20606, +13470, -8907, +1610, +3084, -1671, +3262, +2674, -6933, -54, +2126, -1222, -615, -2058, -501, -1073, -920, -1108, -226, -364, -678, -985, +112, +592, +23, +2550, +1067, -1061, -439, -1160, -1596, -844, },
|
||||
{ +21678, +13397, -9105, +1972, +1964, -2147, +3689, +2647, -6634, +29, +1710, -1374, -333, -2266, -901, -865, -791, -1224, -108, -330, -517, -988, -65, +848, -297, +2505, +1436, -1115, -771, -1020, -1548, -824, },
|
||||
{ +22043, +13828, -8808, +1968, +1087, -2691, +3735, +2813, -6153, -63, +1327, -1523, -22, -2413, -1231, -625, -620, -1517, +116, -296, -490, -687, -330, +1228, -654, +1883, +1897, -817, -1166, -848, -1353, -842, },
|
||||
{ +21862, +14553, -8083, +1733, +298, -3191, +3378, +3080, -5574, -270, +1014, -1790, +389, -2456, -1466, -480, -483, -1820, +297, -178, -667, -4, -656, +1283, -726, +917, +2011, -106, -1245, -999, -903, -756, },
|
||||
{ +21352, +15281, -6885, +1395, -334, -3665, +2670, +3546, -5077, -445, +803, -2146, +977, -2334, -1692, -440, -333, -2064, +440, -23, -774, +810, -1201, +1101, -364, -194, +1769, +892, -1065, -1132, -267, -995, },
|
||||
{ +20861, +15614, -5482, +1081, -870, -4341, +1898, +3930, -4851, -435, +471, -2413, +1653, -2264, -1871, -605, -244, -2109, +276, +437, -945, +994, -1311, +557, +83, -748, +1003, +1546, -293, -1147, -222, -1064, },
|
||||
{ +20341, +15837, -4243, +1301, -1450, -5105, +1347, +3961, -4522, -413, +325, -2497, +2316, -2115, -2138, -652, -297, -1870, +211, +677, -1276, +1047, -1153, -118, +720, -740, -74, +2033, +582, -1274, -145, -714, },
|
||||
{ +19636, +16119, -3188, +1683, -1865, -5991, +823, +3722, -4115, -322, +190, -2340, +2786, -2019, -2280, -876, -206, -1208, -519, +732, -1211, +541, -669, -258, +512, +140, -566, +1174, +1263, -677, -170, -802, },
|
||||
{ +18858, +16285, -2143, +1991, -1980, -6784, +50, +3403, -3485, -245, +189, -2095, +3079, -1823, -2721, -438, -196, -1206, -875, +432, -1124, +431, -376, -252, +414, +1193, -856, -296, +1960, -172, -317, -664, },
|
||||
{ +18488, +15830, -1291, +2547, -2229, -7386, -730, +2796, -2460, -104, -268, -1138, +2825, -2015, -2015, -709, -496, -920, -1536, +112, -516, +216, -578, +707, +252, +875, +136, -1180, +1044, +302, +130, -464, },
|
||||
{ +18032, +15462, -771, +3171, -2446, -7862, -1764, +2636, -1567, +5, -496, -701, +2816, -1760, -1991, -874, -746, -1167, -1739, +343, -701, +364, +15, +532, +203, +973, +810, -1570, -221, +371, +695, -210, },
|
||||
{ +18183, +14237, -213, +3919, -3116, -7974, -2292, +2020, -153, +42, -1423, +627, +2562, -2113, -1333, -1554, -1186, -770, -1762, -91, -66, +691, -288, +385, +793, +1048, +304, -885, -866, -584, +1104, +190, },
|
||||
{ +17916, +13240, +200, +4684, -3796, -7718, -2760, +1604, +850, +225, -1927, +1081, +2619, -2191, -1377, -2216, -746, -653, -2263, +733, +68, +56, +169, +482, +600, +1299, +31, -544, -723, -1663, +902, +562, },
|
||||
{ +17044, +12267, +1399, +4803, -4676, -5966, -3841, +281, +3320, -114, -3303, +2279, +2401, -2496, -1283, -2365, -671, -464, -1900, +808, -230, -25, +729, +96, +303, +1800, +66, -835, -309, -1837, -28, +731, },
|
||||
{ +17131, +11616, +1113, +3708, -4510, -4182, -4413, -204, +4141, -354, -3431, +2353, +1909, -2319, -1067, -2887, -24, -22, -2046, +700, -301, +199, +609, -123, +449, +1846, +102, -822, -495, -1668, -259, +595, },
|
||||
{ +17804, +10827, -833, +4161, -4620, -3463, -2984, -1411, +4085, +122, -3689, +2063, +1883, -2404, -1128, -2081, +2, -158, -1877, +784, -113, -307, +389, +403, +575, +1373, +163, -658, -728, -1403, -144, +238, },
|
||||
{ +17770, +9675, -2120, +5437, -4251, -3736, -2292, -788, +3134, -434, -2948, +1807, +1772, -2590, -638, -1520, -124, -311, -1778, +1073, -328, -581, +430, +559, +654, +1248, -5, -604, -701, -1222, +85, +89, },
|
||||
{ +16983, +8744, -2777, +6694, -3792, -4443, -901, -815, +1755, -54, -2575, +1415, +1766, -2182, -536, -1198, -147, -428, -1414, +749, -461, -344, +355, +328, +855, +1312, -290, -626, -512, -1025, +51, +365, },
|
||||
{ +15530, +7980, -1979, +6512, -3528, -3269, -860, -1658, +1879, -8, -2551, +1210, +1950, -1724, -587, -1052, -96, -226, -1441, +427, -306, -235, +212, +345, +877, +1182, -243, -745, -344, -674, -107, +390, },
|
||||
{ +13644, +7839, +340, +4237, -4066, -2089, +181, -157, -98, -716, -1664, +1617, +1169, -1811, +342, -1102, -326, +22, -1305, +431, -226, -614, +436, +265, -325, +880, +370, -95, +206, -791, -194, -105, },
|
||||
{ +11477, +7542, +1372, +3307, -3045, -1070, -418, -498, +213, -531, -1761, +1305, +1366, -1451, +150, -939, -219, -56, -1110, +275, -259, -524, +318, +167, -195, +840, +316, +6, -31, -753, +66, +40, },
|
||||
{ +9185, +7569, +2375, +2356, -1914, -448, -695, -709, +367, -353, -1571, +1152, +1173, -975, +111, -735, -206, -120, -786, +213, -329, -455, +368, +102, -13, +690, +287, +199, -74, -549, +265, +253, },
|
||||
{ +7687, +7172, +2505, +2384, -1188, -623, -434, -481, +255, -398, -1198, +1009, +1022, -762, +89, -484, -279, -47, -579, +42, -268, -226, +195, +11, +172, +581, +417, +303, -47, -184, +406, +81, },
|
||||
{ +6794, +6483, +2410, +2627, -840, -796, -81, -127, -26, -355, -786, +799, +900, -672, +188, -249, -386, -6, -336, -8, -247, -119, +38, +96, +339, +606, +665, +312, -3, +47, +278, -125, },
|
||||
{ +5907, +5826, +2525, +2670, -555, -752, +41, +149, -99, -234, -613, +533, +888, -428, +180, -214, -321, +180, -187, -225, -103, +27, -39, +368, +489, +694, +754, +175, -13, +28, +125, -216, },
|
||||
{ +5068, +5227, +2668, +2678, -280, -715, +86, +472, -115, -212, -504, +385, +890, -299, +204, -116, -199, +274, -206, -202, +165, +190, +121, +464, +488, +765, +530, -95, +33, +85, +32, -285, },
|
||||
{ +4430, +4893, +2607, +2422, +45, -558, +143, +594, -112, -70, -407, +181, +893, +9, +138, -80, -17, +293, -18, +126, +441, +150, +103, +549, +369, +433, +333, -10, +90, +43, -106, -245, },
|
||||
{ +3711, +4345, +2802, +2585, +142, -598, +212, +846, -12, -130, -349, +202, +915, +136, +144, +26, +282, +585, +264, +261, +271, +98, +65, +247, +259, +366, +292, +2, +95, +26, -184, -171, },
|
||||
{ +3270, +4161, +2763, +2345, +192, -419, +378, +857, +49, -39, -256, +254, +934, +196, +366, +592, +573, +461, +232, +248, -23, -159, +76, +241, +206, +248, +207, +95, +139, -106, -191, -197, },
|
||||
{ +2943, +3918, +2802, +2227, +112, -304, +629, +924, +29, +150, -154, +182, +1323, +752, +534, +526, +437, +413, +22, -194, -72, +85, -38, +83, +224, +251, +213, +42, +65, -167, -226, -198, },
|
||||
{ +2772, +3851, +2788, +1975, +65, -69, +845, +1077, -57, +182, +530, +759, +1311, +513, +472, +465, +64, +67, -3, -148, -49, +2, -85, +278, +204, -7, +177, +109, -60, -207, -187, -266, },
|
||||
{ +2741, +3962, +2753, +1658, -41, +420, +934, +1003, +697, +759, +554, +442, +1100, +376, +43, +199, +55, +12, -47, -241, +16, +219, -40, +38, -37, +66, +191, +16, -90, -266, -234, -204, },
|
||||
{ +3100, +4428, +2177, +1205, +75, +902, +1974, +1358, +427, +424, +567, +206, +484, +165, +130, +95, -110, -9, -43, +93, +142, -69, -204, -13, -9, +23, +198, -26, -264, -205, -104, -146, },
|
||||
{ +3210, +4553, +1862, +1097, +1209, +1702, +1662, +1004, +308, +184, +225, +17, +388, +79, +50, +47, -163, +200, +252, -95, -147, -45, -164, -179, -57, +145, +35, -75, -120, -139, -145, -187, },
|
||||
{ +2744, +4295, +2964, +2006, +764, +1468, +1817, +756, +4, +41, +245, +14, +163, +49, +70, +100, +168, +231, -53, -108, -40, -137, -327, -125, -50, -25, +121, +79, -87, -207, -216, -224, },
|
||||
{ +3644, +5506, +2291, +880, +1111, +1504, +1276, +605, -113, -2, +218, +64, +212, -104, +192, +519, +136, -208, +41, +48, -219, -274, -268, -122, -133, +102, +215, +67, -186, -291, -229, -287, },
|
||||
{ +3729, +5991, +1991, +263, +1099, +1310, +1186, +802, +62, -222, +346, +155, +106, +141, +330, +491, +26, -42, +16, -23, -226, -214, -280, -265, -52, +117, +214, +32, -128, -310, -288, -270, },
|
||||
{ +2626, +5352, +3385, +581, +252, +872, +1262, +1271, +175, -237, +438, +384, +61, +61, +469, +546, +232, -19, -21, +71, -83, -296, -233, -189, -195, +42, +177, +99, -95, -207, -255, -295, },
|
||||
{ +2086, +4619, +3769, +1305, +139, +491, +966, +1193, +432, -210, +327, +607, +212, +43, +405, +422, +412, +221, +64, +98, -131, -143, -94, -220, -249, -9, +178, +14, -136, -131, -163, -256, },
|
||||
{ +2139, +4433, +3497, +1555, +347, +189, +878, +1324, +318, -496, +231, +753, +258, +26, +394, +493, +349, +186, +248, +240, -44, -89, -49, -142, -57, -56, +21, +118, -122, -273, -226, -136, },
|
||||
{ +2311, +4528, +3281, +1515, +485, +155, +824, +1324, +265, -492, +160, +527, +142, +7, +422, +391, +265, +431, +202, +86, +149, +36, +38, -14, +14, +37, +95, +88, -115, -263, -276, -244, },
|
||||
{ +2483, +4762, +3179, +1400, +563, +131, +828, +1336, +202, -523, +128, +527, +103, -226, +171, +342, +142, +412, +338, +45, +92, -94, +172, +187, +6, +205, +202, +105, -77, -196, -299, -324, },
|
||||
{ +2726, +5137, +3097, +1180, +674, +184, +755, +1346, +184, -531, +98, +477, +195, -246, -36, +193, -87, +205, +506, +62, -30, -76, +59, +215, +91, +296, +329, +186, +97, -139, -324, -248, },
|
||||
{ +3045, +5527, +3012, +1062, +756, +111, +709, +1423, +99, -641, +145, +477, +146, -204, -123, +100, -177, -119, +444, +91, -147, -88, -72, +196, +100, +177, +408, +293, +113, +30, -141, -297, },
|
||||
{ +3436, +6020, +2910, +889, +868, +57, +655, +1504, +22, -713, +161, +469, +124, -165, -125, -15, -195, -258, +287, +219, -316, -262, -35, +129, +77, +61, +409, +298, +70, +141, -16, -144, },
|
||||
{ +3894, +6586, +2783, +668, +954, -13, +635, +1573, -146, -783, +246, +445, +2, -172, -63, -91, -294, -318, +133, +279, -237, -506, -107, +75, +8, +47, +226, +248, +95, +53, -4, -57, },
|
||||
{ +4405, +7200, +2656, +443, +1039, -128, +662, +1690, -398, -841, +393, +450, -138, -226, +1, -146, -386, -359, +40, +223, -89, -563, -227, +109, -110, -3, +147, +88, +56, +29, -5, -116, },
|
||||
{ +4876, +7873, +2612, +205, +1070, -269, +712, +1849, -697, -944, +597, +475, -291, -315, +82, -190, -515, -429, -4, +168, -34, -473, -351, +121, -57, -127, +140, -117, -82, +81, -67, -139, },
|
||||
{ +5345, +8532, +2640, -20, +1042, -466, +776, +2045, -1057, -1078, +828, +511, -446, -439, +123, -190, -656, -517, -117, +119, +9, -405, -323, -39, +71, -105, -9, -130, -314, -1, -54, -197, },
|
||||
{ +5755, +9172, +2804, -162, +957, -687, +828, +2288, -1359, -1285, +1083, +619, -595, -549, +140, -166, -730, -627, -255, +75, +66, -414, -171, -94, -6, +93, -105, -228, -284, -205, -114, -134, },
|
||||
{ +6053, +9828, +3094, -338, +874, -821, +750, +2423, -1504, -1522, +1217, +797, -715, -693, +145, -172, -790, -680, -456, -66, +242, -494, -151, +117, -189, +150, +39, -395, -358, -190, -293, -70, },
|
||||
{ +6365, +10439, +3396, -513, +841, -814, +596, +2360, -1502, -1631, +1210, +940, -723, -805, +124, -197, -871, -667, -563, -359, +324, -281, -332, +308, -121, -25, +252, -378, -573, -197, -328, -115, },
|
||||
{ +6691, +10976, +3599, -570, +917, -864, +376, +2212, -1463, -1679, +1089, +1036, -703, -886, +72, -213, -1017, -664, -582, -629, +140, +41, -340, +170, +189, -205, +228, -137, -721, -390, -282, -214, },
|
||||
{ +7655, +11301, +2983, -165, +1190, -1185, +265, +2137, -1680, -1486, +973, +1045, -655, -1003, +145, -320, -1056, -774, -554, -718, -142, +148, -1, -9, +263, -7, +1, +12, -602, -637, -348, -173, },
|
||||
{ +8725, +11372, +2035, +795, +1645, -1977, +191, +2335, -2001, -1434, +933, +1003, -589, -1155, +213, -455, -1024, -893, -641, -701, -356, -16, +344, +128, +51, +231, -87, -31, -405, -710, -562, -171, },
|
||||
{ +9575, +11154, +1237, +2394, +2028, -3285, +418, +2886, -2551, -1615, +1186, +934, -650, -1197, +283, -624, -1011, -875, -759, -706, -442, -240, +477, +441, -54, +319, -30, -127, -305, -565, -677, -372, },
|
||||
{ +10190, +10640, +774, +4347, +2002, -4744, +1042, +3458, -3410, -1873, +1669, +748, -934, -1066, +314, -877, -1066, -778, -875, -839, -432, -417, +363, +615, +59, +388, -7, -218, -333, -323, -683, -569, },
|
||||
{ +11656, +10948, -887, +4545, +3052, -4722, +604, +3331, -3530, -1765, +1917, +460, -1170, -858, +331, -1145, -1038, -801, -770, -934, -391, -415, +118, +836, +219, +336, +68, -117, -415, -229, -603, -466, },
|
||||
{ +13296, +11164, -2472, +4349, +3911, -4234, +37, +3058, -3561, -1609, +2035, +238, -1451, -733, +380, -1485, -961, -904, -594, -975, -451, -230, -189, +825, +484, +313, +29, -4, -374, -223, -531, -267, },
|
||||
{ +14547, +11879, -3970, +3666, +4639, -3257, -708, +2677, -3398, -1566, +2096, +56, -1592, -844, +432, -1787, -948, -1000, -471, -858, -654, +26, -371, +599, +668, +477, -138, +127, -242, -320, -341, -194, },
|
||||
{ +16244, +12044, -5188, +3051, +4787, -2203, -1047, +2078, -3288, -1206, +1927, -153, -1529, -1122, +410, -1934, -1051, -951, -400, -689, -749, +91, -214, +211, +759, +692, -292, +255, -104, -432, -82, -239, },
|
||||
{ +17280, +12976, -6370, +2340, +4641, -1173, -1098, +1398, -2972, -1077, +1787, -398, -1249, -1610, +388, -1966, -1197, -775, -431, -518, -766, +52, -3, +3, +536, +1033, -423, +244, +74, -499, +32, -201, },
|
||||
{ +18875, +13104, -7286, +2064, +3976, -486, -755, +780, -2840, -753, +1487, -511, -1136, -1879, +201, -1926, -1197, -654, -442, -429, -635, -89, +257, -23, +237, +1321, -511, +32, +268, -506, +24, +2, },
|
||||
{ +20130, +13417, -7954, +1823, +3146, -160, -302, +339, -2656, -706, +1344, -730, -995, -2122, -28, -1814, -1115, -678, -496, -246, -631, -73, +307, +224, -38, +1338, -479, -375, +351, -455, +133, +122, },
|
||||
{ +20900, +14050, -8284, +1502, +2221, -215, +187, +146, -2582, -775, +1230, -1057, -723, -2335, -281, -1549, -1106, -814, -527, -46, -662, -26, +311, +623, -314, +1032, -275, -849, +139, -141, +262, +150, },
|
||||
{ +21506, +14520, -8163, +1322, +1076, -434, +702, +70, -2585, -746, +944, -1321, -256, -2471, -490, -1259, -1129, -1001, -507, +204, -799, +188, +407, +732, -431, +631, -175, -1085, -90, -20, +511, +450, },
|
||||
{ +22045, +14638, -7551, +1339, -401, -605, +1069, +20, -2608, -672, +522, -1429, +425, -2597, -667, -990, -1249, -1112, -381, +216, -660, +423, +180, +808, -430, +149, -101, -901, -420, -144, +988, +646, },
|
||||
{ +22374, +14605, -6584, +1379, -2012, -818, +1269, -52, -2715, -579, +90, -1306, +1138, -2771, -762, -975, -1284, -1081, -478, +502, -689, +317, +67, +770, -529, -3, +37, -932, -233, -321, +645, +1063, },
|
||||
{ +21971, +14982, -5381, +1465, -3401, -1307, +1361, -157, -2826, -434, -42, -1263, +1888, -2842, -1101, -790, -1377, -899, -394, +320, -814, +398, -273, +728, -246, -176, +85, -530, -151, -691, +222, +1349, },
|
||||
{ +21578, +15032, -3953, +1480, -4478, -2119, +1347, -259, -2912, +19, -196, -1128, +2559, -2963, -1432, -703, -946, -870, -888, +371, -914, +216, -287, +839, -198, -30, +401, -611, -215, -354, -239, +533, },
|
||||
{ +20935, +14892, -2350, +1522, -5169, -3135, +939, +47, -2856, +331, -223, -886, +3031, -3198, -1627, +82, -1303, -1105, -934, +12, -879, +350, -351, +790, +317, +101, -59, -207, +109, -776, -140, -183, },
|
||||
{ +19989, +14916, -1024, +1608, -5475, -4473, +295, +1065, -2834, +220, +84, -593, +2619, -2455, -1492, -396, -1160, -1373, -1255, +21, -642, +54, -86, +1220, -111, +160, +248, -322, +230, -981, +131, -465, },
|
||||
{ +19442, +14440, -244, +2209, -5944, -5867, +441, +1708, -2969, +837, -323, -569, +3451, -2723, -1540, -344, -1757, -1134, -1142, -251, -519, +531, -17, +686, +62, +600, -73, -568, +824, -1013, -326, +77, },
|
||||
{ +19215, +13282, +497, +2823, -6861, -6114, +314, +2076, -2340, +432, -449, +228, +3074, -2653, -1482, -1155, -1421, -644, -1745, -8, +375, -76, -205, +1100, -38, +316, +113, -497, +839, -778, -681, +216, },
|
||||
{ +18399, +12398, +1273, +2931, -6997, -6116, +179, +2120, -1724, +857, -1704, +1041, +3221, -3315, -1375, -1169, -1113, -795, -1352, +352, -102, -102, +206, +701, -238, +511, +174, -405, +646, -548, -516, -399, },
|
||||
{ +17103, +12076, +1628, +2442, -6317, -5062, -1021, +2253, +17, -617, -1910, +2032, +2182, -3218, -758, -1593, -918, +124, -1676, +57, +262, -74, -107, +549, -37, +456, +200, -287, +594, -479, -420, -621, },
|
||||
{ +17339, +11281, -244, +2822, -5940, -4177, +36, +1140, -56, -183, -2196, +2015, +1763, -3155, -461, -1392, -347, -94, -1944, +612, +306, -660, +4, +659, -17, +432, +20, -3, +720, -783, -494, -283, },
|
||||
{ +16567, +9681, +78, +3330, -6088, -2392, -403, +490, +834, -1104, -2339, +2535, +1400, -3259, +240, -1123, -378, -183, -1760, +840, -40, -771, +203, +636, -208, +524, +221, -45, +609, -787, -453, -228, },
|
||||
{ +15277, +8488, +278, +3885, -5037, -2468, -191, +698, +82, -1238, -1833, +2336, +911, -2516, +590, -1228, -341, -135, -1481, +650, -204, -726, +413, +395, -341, +823, +281, -147, +494, -733, -476, -140, },
|
||||
{ +14508, +10388, +2390, +614, -9568, -3171, +2824, +3138, -360, -1806, -3125, +365, +1587, -1832, +1166, -336, -464, +624, -617, +527, +1, -567, -177, -592, -325, +573, -499, -34, +977, -258, +261, -46, },
|
||||
{ +12204, +10145, +3137, +1381, -8141, -4350, +1999, +2595, +500, -763, -2949, -365, +1128, -983, +987, -357, -350, +719, -509, +347, +303, -394, -148, -488, -492, +295, -634, +121, +1110, -75, +436, -20, },
|
||||
{ +10618, +9407, +3284, +1743, -6720, -3899, +1478, +1813, +596, -356, -2413, -640, +1096, -622, +604, -220, -317, +679, -315, +187, +316, -151, -180, -467, -394, +122, -486, +261, +994, +154, +417, -67, },
|
||||
{ +8737, +8566, +3830, +1870, -5294, -3295, +668, +1407, +736, -98, -1874, -761, +1017, -457, +347, -65, -252, +598, -129, +108, +374, +35, -238, -389, -303, +101, -170, +351, +816, +261, +307, -90, },
|
||||
{ +7322, +7990, +4204, +1759, -4233, -2859, +204, +1225, +706, +89, -1428, -779, +812, -371, +310, +13, -255, +576, +48, +68, +394, +93, -230, -185, -105, +97, -62, +325, +596, +234, +208, -140, },
|
||||
{ +5934, +7313, +4453, +1864, -3250, -2602, -73, +1073, +737, +266, -1100, -695, +649, -339, +267, +163, -183, +531, +195, +93, +388, +271, +42, +55, -87, -115, -13, +235, +333, +198, +167, -56, },
|
||||
{ +5000, +6676, +4573, +2086, -2672, -2459, -188, +999, +803, +304, -865, -518, +450, -355, +364, +251, -120, +548, +192, +279, +680, +344, +32, +73, -196, -341, +1, +192, +208, +250, +135, -143, },
|
||||
{ +4456, +6275, +4433, +1984, -2322, -2108, -127, +872, +815, +394, -642, -454, +355, -269, +459, +303, -78, +714, +511, +458, +618, +237, -33, -56, -404, -289, +129, +56, +240, +141, -2, +127, },
|
||||
{ +3914, +5714, +4351, +2080, -2013, -1928, -97, +902, +872, +413, -420, -323, +306, -177, +447, +601, +422, +769, +448, +347, +442, +17, -200, -32, -412, -202, +177, -120, +89, +302, +138, +79, },
|
||||
{ +3687, +5529, +4104, +1830, -1878, -1601, +73, +886, +904, +439, -190, -238, +213, +104, +832, +826, +315, +493, +327, +220, +233, -30, -126, -120, -318, -150, -96, +60, +301, +96, +30, +144, },
|
||||
{ +3580, +5372, +3781, +1521, -1776, -1190, +327, +859, +987, +532, -67, +9, +629, +331, +636, +568, +95, +278, +193, +191, +184, -23, -203, -172, -324, -16, +176, -130, +89, +51, +115, +194, },
|
||||
{ +3492, +5329, +3471, +1350, -1561, -940, +597, +949, +959, +721, +441, +128, +352, +175, +389, +425, +9, +204, +280, +156, +63, -22, -262, -158, +108, -5, -216, -107, +108, +31, +78, +239, },
|
||||
{ +3432, +5245, +3183, +1194, -1128, -596, +840, +1170, +1253, +888, +199, -114, +53, +17, +302, +263, +132, +181, +140, +117, +66, -50, -59, +236, -176, -301, -113, -66, -72, -13, +269, +19, },
|
||||
{ +3390, +5248, +2963, +1119, -596, -247, +1125, +1471, +935, +484, +120, -201, +1, -69, +296, +276, +64, +116, +141, +246, -26, +224, +239, -232, -240, -143, -165, -208, -22, +53, +4, +96, },
|
||||
{ +3459, +5308, +2829, +1096, -226, +235, +1196, +1070, +638, +314, +33, -149, +26, -184, +259, +284, -110, +166, +359, +85, +180, +500, -207, -255, -125, -253, -294, -112, -3, -243, +82, +267, },
|
||||
{ +3444, +5608, +3052, +1048, -153, +152, +952, +951, +500, +280, +174, -297, -12, -51, +82, +247, +11, +278, +212, +303, +571, -23, -220, +24, -291, -435, -178, -82, -257, -114, +197, +358, },
|
||||
{ +3631, +5987, +3171, +840, -377, -261, +737, +1132, +564, +264, +192, -346, -126, +1, +155, +186, +152, +235, +119, +688, +415, -209, -47, -46, -307, -433, -160, -284, -252, +134, +257, +168, },
|
||||
{ +3555, +6368, +3416, +601, -552, -585, +576, +1098, +540, +380, +255, -412, -120, +84, +90, +257, +276, +51, +139, +958, +303, -229, +70, -105, -327, -291, -183, -450, -241, +244, +389, -20, },
|
||||
{ +3304, +6445, +3877, +542, -780, -691, +604, +1149, +403, +125, +220, -232, -86, +58, +247, +261, +126, +140, +91, +859, +535, -186, +15, -49, -295, -232, -192, -427, -225, +175, +356, +33, },
|
||||
{ +3095, +6398, +4320, +718, -1060, -852, +617, +1319, +551, -131, -94, -318, -227, +167, +484, +239, +130, +167, -116, +734, +786, -134, -76, +64, -201, -204, -176, -362, -225, +158, +343, -8, },
|
||||
{ +3043, +6443, +4566, +841, -1213, -1017, +635, +1471, +644, -187, -192, -362, -461, -72, +479, +445, +148, +181, -13, +421, +845, +87, -217, -18, -79, -55, -112, -366, -227, +211, +309, +49, },
|
||||
{ +3132, +6650, +4683, +897, -1394, -1203, +748, +1560, +723, -251, -284, -272, -531, -243, +278, +347, +138, +203, +193, +288, +760, +331, -284, -258, -57, +43, +11, -256, -228, +216, +280, +136, },
|
||||
{ +3367, +6988, +4849, +842, -1674, -1375, +807, +1795, +719, -420, -285, -270, -512, -280, +138, +254, -47, -57, +304, +307, +642, +594, -125, -511, -291, +9, +125, -134, -237, +289, +287, +139, },
|
||||
{ +3586, +7407, +5080, +656, -1907, -1495, +823, +2057, +683, -633, -291, -228, -494, -258, +64, +194, -36, -286, +173, +318, +479, +623, +210, -460, -540, -128, +140, -101, -240, +315, +252, +163, },
|
||||
{ +3913, +8036, +5294, +392, -2186, -1751, +902, +2457, +567, -915, -352, -187, -458, -275, +94, +106, -67, -364, +29, +257, +307, +466, +372, -273, -572, -259, +20, -46, -279, +200, +193, +90, },
|
||||
{ +4032, +8688, +5666, +129, -2445, -1998, +927, +2764, +585, -1205, -445, -136, -465, -297, +145, +30, -86, -398, -75, +234, +196, +315, +365, -111, -602, -339, +4, +2, -305, +120, +111, -149, },
|
||||
{ +4592, +9563, +5846, -404, -2900, -2105, +1130, +3189, +362, -1558, -421, -109, -448, -336, +218, +21, -218, -346, -123, +178, +175, +130, +357, -19, -545, -388, -95, -2, -115, +87, -12, -264, },
|
||||
{ +5108, +10372, +5960, -878, -3340, -2212, +1378, +3487, +158, -1928, -397, -33, -497, -372, +269, +15, -353, -346, -123, +153, +121, -36, +345, +17, -453, -394, -151, -80, -129, +237, -86, -306, },
|
||||
{ +5903, +11205, +5822, -1373, -3825, -2282, +1849, +3676, -196, -2204, -349, +96, -588, -398, +334, +40, -480, -394, -80, +155, +103, -202, +283, +76, -376, -305, -191, -130, -153, +273, -64, -333, },
|
||||
{ +6463, +12077, +6105, -1736, -4427, -2497, +2172, +3937, -457, -2637, -316, +269, -650, -515, +328, +128, -574, -464, -145, +165, +112, -359, +102, +133, -284, -189, -158, -224, -158, +175, +22, -412, },
|
||||
{ +6842, +12772, +6370, -1805, -4912, -2802, +2482, +4054, -577, -3009, -381, +505, -711, -614, +320, +143, -632, -456, -212, +124, +133, -429, -89, +129, -159, -163, +4, -302, -109, +98, -9, -351, },
|
||||
{ +7495, +13436, +6402, -1641, -5389, -3222, +2902, +4096, -819, -3320, -508, +760, -709, -801, +367, +144, -733, -443, -242, +90, +109, -405, -353, -3, +96, -160, +135, -243, -147, +159, -109, -342, },
|
||||
{ +8302, +13982, +6007, -1545, -5551, -3449, +3272, +3931, -1108, -3384, -659, +902, -637, -984, +381, +171, -829, -414, -266, +67, +40, -321, -455, -318, +312, -35, +128, -72, -215, +189, -55, -445, },
|
||||
{ +9896, +14670, +4570, -1730, -5262, -3249, +3511, +3414, -1572, -3150, -826, +851, -414, -1191, +310, +159, -852, -430, -228, +45, -97, -288, -414, -643, +337, +260, +1, +181, -141, +21, +120, -543, },
|
||||
{ +11175, +14744, +3448, -993, -4976, -3811, +3696, +3441, -2038, -3160, -852, +834, -325, -1343, +248, +102, -877, -401, -118, -49, -199, -292, -342, -788, +115, +605, -66, +267, +58, -136, +206, -540, },
|
||||
{ +12433, +14644, +2289, -11, -4664, -4428, +3847, +3503, -2546, -3196, -721, +719, -321, -1413, +201, -27, -944, -298, +67, -214, -293, -242, -375, -807, -141, +822, +24, +219, +276, -175, +133, -469, },
|
||||
{ +14253, +15077, +91, +194, -3679, -4227, +3554, +3173, -2873, -3182, -505, +510, -236, -1531, +106, -141, -941, -242, +293, -223, -457, -200, -494, -638, -319, +772, +318, +229, +335, -59, -21, -432, },
|
||||
{ +16147, +15220, -1962, +114, -2901, -3609, +3134, +2739, -3044, -3270, -314, +358, -218, -1704, +85, -332, -895, -157, +414, -203, -648, -134, -650, -486, -341, +596, +483, +347, +229, -1, -55, -568, },
|
||||
{ +17862, +15961, -4207, -422, -1951, -2655, +2484, +2264, -2914, -3618, -117, +208, -161, -1924, +25, -473, -800, -35, +478, -79, -937, -17, -769, -367, -225, +425, +413, +582, +113, -133, +87, -734, },
|
||||
{ +19449, +16392, -5859, -1112, -1427, -1629, +1942, +1918, -2765, -3978, -8, +84, -134, -2062, -13, -566, -654, +37, +477, +32, -1157, +83, -816, -331, +13, +340, +96, +768, +67, -341, +213, -694, },
|
||||
{ +21050, +17015, -7348, -2198, -1140, -508, +1499, +1662, -2610, -4451, +6, -138, -34, -2121, -29, -596, -503, +48, +407, +189, -1351, +208, -923, -200, +286, +156, -272, +696, +143, -514, +278, -464, },
|
||||
{ +22180, +17691, -8318, -3153, -1264, +222, +1444, +1546, -2552, -4822, -136, -360, +172, -2054, -32, -523, -483, -7, +341, +375, -1419, +217, -913, -27, +273, +51, -545, +431, +314, -476, +252, -284, },
|
||||
{ +23145, +18305, -8899, -3912, -1872, +754, +1676, +1457, -2542, -5140, -436, -571, +593, -1943, -18, -391, -590, -105, +360, +600, -1486, +265, -834, -64, +157, -1, -808, +207, +535, -343, +188, -148, },
|
||||
{ +24201, +18791, -9169, -4533, -3193, +1197, +2201, +1353, -2588, -5477, -898, -646, +1316, -1907, +112, -361, -830, -56, +459, +703, -1301, +324, -1128, -106, +17, -169, -828, +111, +625, -123, +274, -146, },
|
||||
{ +25039, +18854, -8960, -4922, -4675, +1488, +2597, +1309, -2785, -5629, -1226, -537, +1894, -1872, +177, -569, -818, +47, +414, +930, -1141, -66, -1306, -147, -197, -117, -643, -26, +588, +205, +269, -377, },
|
||||
{ +25483, +18997, -8159, -5303, -6464, +1415, +3101, +1247, -3048, -5328, -1549, -448, +2627, -1908, -26, -525, -721, +144, +628, +830, -1334, -263, -1576, -203, -94, -5, -521, -41, +604, +221, +328, -313, },
|
||||
{ +25310, +19394, -7240, -5364, -8082, +861, +3602, +1021, -2853, -4841, -1925, -274, +3034, -1996, -184, -315, -585, +480, +190, +564, -1199, -604, -1602, -1, -64, +5, -267, -39, +307, +300, +702, -524, },
|
||||
{ +25187, +19126, -5747, -5306, -10048, +5, +3816, +1259, -2439, -4328, -2144, -285, +3285, -2132, -193, +313, -577, +11, -100, +308, -1123, -638, -1463, +80, -40, +174, -302, -152, +368, +273, +817, -512, },
|
||||
{ +24584, +19059, -4370, -5103, -11540, -1206, +4149, +1948, -2239, -3792, -2260, -463, +3232, -1933, +310, +264, -1049, -39, -461, +305, -807, -683, -1310, +216, -69, -19, -134, -7, +199, +192, +1012, -495, },
|
||||
{ +24229, +18498, -3219, -4673, -13052, -2239, +4802, +2529, -2152, -3029, -2527, -945, +3759, -1608, +81, +180, -1445, -83, -369, +279, -585, -589, -996, -15, -262, +176, +17, -164, +214, +234, +1010, -493, },
|
||||
{ +23479, +17761, -2169, -4054, -14542, -2764, +5166, +3024, -1593, -2674, -3100, -489, +3855, -1932, +199, -475, -1408, +376, -646, +385, -160, -507, -1201, -125, -73, +89, +2, -134, +277, +184, +889, -456, },
|
||||
{ +22902, +16611, -1241, -3921, -14659, -3126, +5151, +3820, -1738, -2209, -3026, -680, +3843, -2076, -205, -376, -1050, +290, -561, +675, -171, -734, -967, -54, -279, +107, +127, -143, +289, +105, +906, -440, },
|
||||
{ +21520, +15491, -466, -3170, -14169, -3623, +5060, +3934, -933, -1908, -3770, -160, +3317, -2389, +45, -293, -930, +570, -302, +294, -117, -531, -816, -259, -393, +309, +177, -338, +355, +325, +623, -455, },
|
||||
{ +20196, +14258, -26, -2087, -13378, -3959, +4522, +4579, -753, -2187, -3650, -282, +3062, -2403, +220, -314, -596, +900, -834, +333, +193, -640, -766, -353, -377, +474, -67, -401, +722, +187, +352, -286, },
|
||||
{ +18562, +12495, +606, -395, -12713, -4067, +4718, +3983, -631, -1865, -4106, +267, +2676, -2530, +544, -90, -270, +517, -885, +629, +178, -816, -539, -358, -375, +420, -176, -225, +814, +58, +205, -176, },
|
||||
{ +16507, +11335, +1670, +425, -11680, -3415, +3753, +3482, -140, -2175, -3676, +452, +2142, -2340, +899, +31, -525, +540, -719, +620, +74, -768, -288, -458, -444, +527, -237, -258, +969, -83, +155, -100, },
|
||||
{ +15749, +11088, +540, -1465, -10587, +5, +4768, +1482, -1271, -1294, -2408, -204, +2109, -2180, +700, +142, -524, +394, -343, +524, -78, -510, -510, -119, -176, +83, +45, -8, -121, -132, +846, -57, },
|
||||
{ +12780, +11168, +3101, -713, -10375, -2419, +3165, +2486, +741, -926, -2637, -901, +1193, -1380, +1171, +201, -695, +683, -287, +203, +326, -265, -402, +216, -760, -316, +56, -240, +385, +349, +800, +38, },
|
||||
{ +10481, +10174, +3731, +12, -8189, -2627, +2287, +2162, +639, -620, -1980, -947, +827, -877, +947, +162, -591, +622, -179, +124, +414, -151, -214, +218, -687, -257, +155, -179, +273, +413, +653, +58, },
|
||||
{ +8668, +9236, +4001, +664, -6447, -2669, +1688, +1709, +604, -245, -1509, -943, +653, -570, +711, +170, -456, +560, -83, +116, +460, +30, -144, +259, -390, -222, +102, -244, +172, +370, +519, +108, },
|
||||
{ +7283, +8384, +4111, +1067, -5156, -2491, +1257, +1309, +661, +29, -1138, -850, +514, -376, +522, +237, -336, +496, +41, +153, +499, +232, +59, +319, -295, -329, -17, -275, -28, +319, +573, +102, },
|
||||
{ +6272, +7691, +4060, +1222, -4187, -2162, +939, +1051, +723, +183, -806, -720, +436, -270, +454, +290, -208, +496, +100, +362, +696, +335, +52, +222, -281, -423, -148, -305, -83, +332, +591, +108, },
|
||||
{ +5580, +7158, +3875, +1174, -3460, -1834, +755, +904, +761, +294, -524, -552, +331, -184, +477, +333, -134, +601, +379, +449, +583, +227, -20, +147, -340, -469, -157, -333, -172, +385, +542, +14, },
|
||||
{ +5099, +6769, +3611, +1012, -2865, -1522, +671, +853, +823, +385, -298, -392, +284, -75, +496, +488, +66, +592, +366, +331, +409, +167, -75, +79, -239, -485, -266, -327, -145, +317, +622, +200, },
|
||||
{ +4774, +6505, +3318, +801, -2367, -1254, +708, +915, +878, +465, -124, -221, +265, +118, +634, +457, -4, +374, +332, +279, +241, +173, -17, +50, -250, -474, -271, -392, +13, +518, +389, +79, },
|
||||
{ +4533, +6373, +3052, +547, -1931, -979, +831, +1054, +874, +581, -34, -52, +431, +69, +479, +349, -93, +183, +314, +308, +170, +203, +2, -44, -122, -409, -440, -16, +135, +84, +235, +185, },
|
||||
{ +4382, +6335, +2815, +384, -1572, -712, +951, +1234, +846, +634, +201, -204, +344, +11, +311, +320, -174, +46, +261, +434, +123, +92, +101, +62, -245, -261, -49, -321, -116, +108, +125, +189, },
|
||||
{ +4310, +6316, +2697, +377, -1265, -560, +1000, +1283, +976, +592, +177, -342, +94, +124, +234, +277, -211, -42, +322, +339, +136, +155, +187, -53, -7, +128, -468, -481, -77, +89, +78, +112, },
|
||||
{ +4220, +6370, +2803, +455, -1043, -593, +884, +1257, +898, +647, +131, -407, +17, -24, +259, +268, -143, -71, +248, +315, +54, +318, +56, +134, +452, -358, -580, -280, -245, +17, +207, +32, },
|
||||
{ +4238, +6578, +2947, +418, -979, -561, +705, +1063, +778, +509, +327, -311, -141, -2, +117, +252, +15, +34, +169, +147, +205, +145, +62, +724, +153, -621, -342, -314, -253, +63, +216, -198, },
|
||||
{ +4312, +6878, +3119, +203, -1024, -566, +664, +1052, +477, +317, +296, -326, +41, -20, +78, +256, -64, +129, +238, +109, +104, +11, +281, +812, -119, -527, -289, -348, -126, +151, +43, -331, },
|
||||
{ +4243, +7275, +3432, -18, -1154, -711, +722, +1244, +373, +111, +88, -498, -48, +145, +283, +267, -58, +72, +167, +174, +186, -87, +222, +896, -239, -530, -150, -376, +16, +248, -104, -319, },
|
||||
{ +4240, +7629, +3820, -212, -1418, -875, +841, +1446, +395, +35, -59, -651, -337, +57, +348, +394, +138, +74, +125, +94, +212, -51, +148, +896, -296, -557, -109, -348, +139, +310, -89, -337, },
|
||||
{ +4267, +8079, +4161, -358, -1708, -1137, +1013, +1624, +419, -13, -148, -667, -486, -153, +260, +306, +109, +213, +291, +100, +122, +47, -84, +791, +19, -750, -253, -252, +190, +325, -24, -265, },
|
||||
{ +4428, +8579, +4533, -649, -2161, -1157, +1152, +1818, +471, -285, -99, -625, -629, -167, +110, +208, -67, +58, +397, +149, +182, +241, -312, +521, +338, -764, -423, -220, +99, +352, +41, -277, },
|
||||
{ +4663, +9147, +5017, -957, -2713, -1191, +1270, +2062, +456, -561, -64, -490, -728, -151, +48, +95, -93, -149, +333, +236, +4, +377, -80, +107, +501, -359, -693, -415, +113, +346, +3, -240, },
|
||||
{ +4794, +9798, +5715, -1328, -3293, -1331, +1372, +2391, +376, -861, -165, -318, -751, -218, +113, -43, -176, -257, +208, +326, -101, +123, +104, -60, +376, +187, -610, -661, -80, +210, +60, -231, },
|
||||
{ +4706, +10404, +6857, -1587, -4043, -1501, +1416, +2768, +428, -1274, -318, -83, -773, -321, +190, -68, -276, -333, +89, +301, +70, -126, -66, -7, +48, +426, +52, -740, -438, +212, -62, -314, },
|
||||
{ +5492, +11533, +6802, -2410, -4639, -1493, +1942, +3028, +51, -1662, -327, +15, -748, -355, +194, -55, -404, -364, +59, +221, +123, -131, -285, -124, -44, +334, +429, -330, -642, -6, -1, -451, },
|
||||
{ +5983, +12434, +7309, -2945, -5475, -1428, +2301, +3203, -66, -2148, -439, +316, -869, -393, +284, -166, -434, -371, -45, +257, +65, -121, -270, -467, -42, +274, +467, +199, -506, -380, +16, -415, },
|
||||
{ +6553, +13345, +7759, -3488, -6279, -1393, +2735, +3371, -353, -2547, -584, +610, -877, -578, +354, -136, -577, -381, +10, +115, +137, -230, -229, -570, -338, +370, +460, +362, -28, -508, -363, -242, },
|
||||
{ +7471, +14327, +7633, -4021, -6946, -1337, +3324, +3391, -814, -2875, -657, +809, -860, -751, +399, -191, -586, -460, +66, +94, +17, -214, -308, -558, -507, +258, +589, +343, +231, -149, -748, -423, },
|
||||
{ +8279, +15118, +7553, -4198, -7540, -1469, +3893, +3301, -1178, -3117, -875, +1005, -790, -1000, +413, -197, -660, -436, +72, +94, -104, -258, -361, -556, -505, +12, +646, +436, +181, +263, -660, -907, },
|
||||
{ +9124, +15874, +7171, -4175, -7769, -1782, +4384, +3236, -1562, -3240, -1066, +1125, -708, -1207, +337, -154, -693, -392, +105, +118, -192, -387, -322, -628, -341, -94, +398, +659, +143, +329, -199, -1184, },
|
||||
{ +10600, +16582, +5950, -4368, -7541, -1867, +4737, +3086, -2067, -3335, -1044, +1123, -740, -1306, +237, -176, -627, -343, +172, +164, -330, -475, -330, -675, -210, +76, +40, +658, +284, +168, +174, -1087, },
|
||||
{ +12376, +17175, +4171, -4522, -7036, -1733, +4785, +2866, -2442, -3529, -868, +972, -750, -1432, +142, -233, -536, -280, +203, +260, -566, -441, -421, -666, -125, +321, -234, +424, +421, +32, +318, -810, },
|
||||
{ +14090, +17881, +2149, -4729, -6335, -1510, +4556, +2689, -2622, -3826, -676, +683, -672, -1544, +43, -207, -493, -179, +161, +384, -803, -320, -525, -640, -11, +437, -358, +48, +480, -16, +337, -499, },
|
||||
{ +16479, +18100, -251, -5038, -5617, -895, +4158, +2494, -2872, -4087, -506, +369, -589, -1544, +53, -264, -351, -200, +196, +385, -925, -184, -637, -545, +96, +400, -519, -169, +313, +46, +383, -236, },
|
||||
{ +18719, +18354, -2535, -5382, -5077, -235, +3760, +2374, -3095, -4427, -427, +22, -354, -1411, +7, -243, -275, -312, +263, +406, -941, -99, -688, -428, +90, +202, -566, -359, +122, +172, +472, -78, },
|
||||
{ +20632, +18711, -4603, -5686, -4881, +473, +3484, +2242, -3308, -4836, -393, -315, +167, -1349, -10, -178, -419, -353, +354, +511, -957, -1, -751, -448, -19, +72, -604, -458, +57, +275, +400, +168, },
|
||||
{ +22360, +19050, -6299, -6014, -5124, +1226, +3414, +2007, -3540, -5278, -311, -473, +850, -1407, +137, -306, -606, -202, +424, +682, -953, +71, -1092, -494, -36, -56, -597, -263, -49, +181, +480, +340, },
|
||||
{ +23853, +19254, -7494, -6434, -5724, +1855, +3501, +1649, -3877, -5514, -94, -559, +1541, -1479, +150, -510, -585, -3, +419, +893, -1016, -259, -1392, -389, -165, +23, -418, -178, -252, +244, +451, +239, },
|
||||
{ +25329, +18892, -8176, -6707, -6565, +2362, +3636, +1174, -4256, -5023, -220, -362, +2101, -1684, +93, -508, -345, +44, +530, +734, -1282, -474, -1490, -397, +61, +190, -464, -83, -222, +71, +299, +421, },
|
||||
{ +26132, +18615, -8557, -6606, -7720, +2662, +3828, +564, -4070, -4493, -377, -142, +2382, -2009, +159, -193, -269, +57, +124, +489, -1273, -596, -1558, -23, +257, +40, -292, +5, -420, -52, +361, +377, },
|
||||
{ +26097, +18760, -8279, -6563, -9338, +2395, +4427, +354, -3683, -4052, -417, -411, +2686, -2127, +394, +208, -612, -267, -183, +547, -1260, -477, -1400, +110, +235, +53, -183, -98, -337, -206, +404, +296, },
|
||||
{ +26298, +17883, -7539, -6429, -11135, +2349, +5208, +297, -3531, -3208, -932, -479, +3059, -2027, +586, +52, -1210, -243, -201, +410, -847, -361, -1398, +182, +205, +3, -91, -95, -338, -279, +476, +239, },
|
||||
{ +25890, +16998, -6703, -6158, -12691, +2616, +5823, +131, -2985, -2746, -1498, -267, +3567, -2288, +598, -395, -1379, +90, -420, +614, -490, -504, -1389, +217, +123, -23, -40, -116, -280, -344, +578, +55, },
|
||||
{ +24947, +16037, -5788, -5689, -13461, +2608, +6096, +412, -2813, -2278, -1596, -192, +3523, -2540, +252, -341, -1212, +134, -205, +703, -394, -619, -1225, +253, -81, +26, +22, -90, -211, -394, +628, +37, },
|
||||
{ +23244, +14939, -4628, -4799, -13452, +2196, +6207, +481, -2338, -1733, -1999, -166, +3296, -2924, +380, -214, -1290, +655, -260, +536, -282, -573, -1003, -3, -66, +82, +42, -31, -237, -351, +712, -93, },
|
||||
{ +21175, +13481, -2942, -3774, -12857, +1570, +5657, +1162, -1877, -1714, -2063, -297, +2743, -2620, +466, -249, -749, +711, -463, +451, -19, -579, -1025, +20, -106, +79, +79, -61, -143, -304, +645, -60, },
|
||||
{ +18636, +12183, -1209, -2590, -11846, +582, +5371, +1609, -1826, -1340, -2309, -463, +2623, -2468, +485, +42, -543, +537, -540, +593, +20, -722, -705, -39, -175, +121, +49, +1, -116, -325, +749, +25, },
|
||||
{ +14783, +9489, -2982, -1023, -3993, +3280, +1929, -1888, -1700, +251, +285, -164, +1356, -1971, +151, -32, -982, +252, -342, +144, -27, -417, -521, +840, -3, +115, +200, -545, +44, -370, -154, +120, },
|
||||
{ +12635, +9338, -1709, -1092, -3762, +2615, +2298, -1249, -1537, +64, +39, -164, +1209, -1626, +74, +120, -732, +178, -175, +161, -27, -373, -563, +683, +104, +109, +334, -384, -11, -279, -152, +39, },
|
||||
{ +10824, +8969, -613, -1061, -3373, +2063, +2390, -782, -1282, -126, -128, -73, +1005, -1268, +42, +226, -527, +136, -29, +165, -13, -304, -520, +542, +230, +129, +323, -272, -56, -204, -196, -8, },
|
||||
{ +9429, +8572, +94, -1038, -2958, +1688, +2332, -399, -1026, -257, -166, -8, +812, -970, +100, +281, -355, +129, +93, +200, -9, -181, -418, +422, +262, +108, +261, -198, -85, -190, -163, -35, },
|
||||
{ +8397, +8228, +487, -1075, -2536, +1429, +2193, -104, -809, -286, -144, +0, +671, -693, +170, +287, -214, +140, +163, +259, +27, -77, -357, +258, +245, +93, +144, -149, -82, -138, -162, -157, },
|
||||
{ +7612, +7949, +682, -1088, -2127, +1227, +2044, +150, -627, -240, -104, +9, +638, -490, +230, +309, -107, +161, +239, +304, +6, -19, -321, +91, +206, +63, +62, -59, -63, -155, -170, -131, },
|
||||
{ +6952, +7827, +766, -1099, -1787, +1048, +1937, +367, -509, -160, +31, -46, +675, -344, +225, +366, -39, +163, +218, +347, -43, -35, -270, -73, +151, +125, +10, -31, -65, -114, -144, -245, },
|
||||
{ +6683, +7602, +752, -1154, -1469, +1022, +1800, +518, -463, -59, +237, -126, +665, -182, +167, +400, +1, +65, +208, +350, -66, -128, -244, -86, +66, +169, -26, -43, +21, -177, -95, +91, },
|
||||
{ +6328, +7603, +798, -1168, -1193, +1003, +1709, +558, -362, -97, +468, -68, +448, +37, +143, +230, +82, +36, +95, +341, -19, -201, -272, +32, -38, +101, +81, -48, -56, +78, +109, -161, },
|
||||
{ +6163, +7555, +882, -1153, -951, +1060, +1636, +512, -380, -40, +469, +81, +403, -73, +284, +126, -61, +146, +60, +209, +16, -67, -335, -42, +24, +86, +40, -88, +270, +181, -136, -94, },
|
||||
{ +6061, +7646, +945, -1152, -751, +1127, +1592, +462, -481, -102, +513, +8, +479, -8, +120, +232, -121, -17, +188, +182, -85, +28, -226, -217, -8, +203, -144, +134, +478, -84, -37, -109, },
|
||||
{ +6159, +7784, +897, -1252, -582, +1290, +1597, +367, -567, -244, +423, +7, +359, +71, +248, +105, -133, +44, +12, +207, +16, -67, -239, -155, +10, -42, -17, +448, +145, -81, +130, -268, },
|
||||
{ +6295, +8059, +874, -1507, -476, +1456, +1680, +362, -767, -349, +394, -179, +254, +82, +233, +237, -141, -70, +113, +103, -91, +65, -321, -165, +80, -154, +82, +449, -28, -5, +49, -241, },
|
||||
{ +6464, +8458, +884, -1785, -437, +1608, +1780, +391, -878, -494, +409, -232, +50, -6, +273, +208, -116, +68, +65, +99, -84, -65, -354, -36, +94, -209, +217, +427, -208, -3, +52, -229, },
|
||||
{ +6683, +8970, +878, -2165, -376, +1753, +1869, +420, -1047, -513, +453, -325, -68, -78, +177, +166, -163, +34, +201, +156, -170, -62, -410, -135, +213, -121, +156, +486, -231, -110, -45, -202, },
|
||||
{ +7075, +9466, +776, -2530, -318, +1953, +1897, +349, -1235, -528, +610, -389, -209, -190, +180, +87, -332, -2, +206, +167, -129, -48, -464, -135, +204, -153, +111, +606, -167, -304, -61, -230, },
|
||||
{ +7586, +10041, +588, -2915, -206, +2202, +1934, +234, -1428, -528, +819, -402, -344, -230, +142, +32, -392, -123, +176, +151, -193, +34, -366, -138, +241, -59, -155, +594, +203, -426, -180, -174, },
|
||||
{ +8284, +10637, +233, -3349, -82, +2488, +1888, +4, -1707, -479, +1011, -436, -518, -321, +180, -80, -546, -130, +97, -3, -257, -57, -259, -35, +170, +42, -299, +295, +418, -294, -381, -148, },
|
||||
{ +9095, +11203, -132, -3724, +50, +2818, +1819, -242, -2019, -371, +1236, -443, -675, -423, +213, -107, -683, -188, +152, -197, -308, -122, -264, +206, +142, +61, -245, -25, +422, +25, -540, -195, },
|
||||
{ +9889, +11877, -498, -4104, +128, +3146, +1756, -530, -2290, -350, +1519, -489, -802, -515, +198, -156, -758, -285, +204, -324, -438, -107, -349, +396, +198, +14, -193, -173, +148, +358, -427, -465, },
|
||||
{ +10582, +12562, -764, -4376, +91, +3406, +1737, -827, -2467, -415, +1769, -548, -939, -576, +195, -234, -826, -350, +190, -335, -585, -69, -435, +512, +288, -37, -200, -225, -129, +406, -34, -688, },
|
||||
{ +11306, +13237, -1039, -4536, -26, +3591, +1718, -1098, -2614, -469, +1956, -571, -1083, -632, +173, -288, -912, -416, +136, -318, -675, -9, -461, +518, +395, -47, -243, -278, -292, +231, +360, -602, },
|
||||
{ +12126, +13732, -1324, -4530, -169, +3644, +1688, -1289, -2721, -525, +2075, -627, -1199, -662, +140, -328, -973, -491, +59, -292, -671, -19, -361, +462, +431, -38, -247, -401, -359, +38, +478, -239, },
|
||||
{ +13174, +14048, -1834, -4351, -231, +3530, +1631, -1424, -2802, -592, +2109, -667, -1235, -700, +112, -376, -980, -597, +19, -296, -588, -73, -240, +447, +337, +12, -264, -517, -447, +2, +295, +152, },
|
||||
{ +13912, +14689, -2549, -4087, -276, +3213, +1690, -1511, -2845, -778, +2173, -760, -1162, -780, +32, -364, -1053, -628, -102, -130, -603, -57, -165, +414, +214, +87, -300, -593, -470, -60, +82, +348, },
|
||||
{ +15735, +14399, -3901, -3481, -192, +2964, +1469, -1601, -3017, -661, +2045, -910, -920, -980, +113, -561, -1039, -685, -48, -104, -573, +16, -218, +402, +105, +138, -407, -536, -465, -206, -44, +459, },
|
||||
{ +17507, +14116, -5426, -2751, -192, +2764, +1237, -1736, -3152, -642, +2056, -1032, -638, -1128, +153, -726, -1046, -569, -51, -121, -478, +1, -396, +547, -27, +111, -333, -501, -516, -340, +19, +317, },
|
||||
{ +19177, +13698, -6887, -1985, -243, +2671, +917, -1892, -3302, -557, +2196, -1213, -249, -1266, +144, -850, -933, -377, -271, +44, -521, -211, -328, +623, -195, +277, -239, -659, -459, -299, -118, +155, },
|
||||
{ +20876, +12896, -8162, -1221, -405, +2653, +504, -2083, -3425, -193, +2142, -1312, +212, -1534, +162, -820, -758, -426, -316, +25, -728, -166, -380, +694, -108, +401, -373, -670, -277, -461, -291, +192, },
|
||||
{ +22269, +11988, -9087, -514, -824, +2741, +141, -2324, -3367, +226, +1930, -1209, +579, -1900, +451, -737, -828, -320, -621, -37, -648, -370, -319, +1024, -166, +363, -328, -614, -348, -565, -333, +183, },
|
||||
{ +22436, +12036, -9756, +12, -1484, +2839, +192, -2651, -3134, +304, +2024, -1272, +960, -2016, +603, -606, -966, -471, -868, +179, -932, -258, -187, +1149, -274, +472, -264, -806, -269, -673, -333, +115, },
|
||||
{ +22976, +10737, -9315, +116, -2333, +3251, +276, -2916, -2945, +644, +1634, -1050, +1433, -2250, +799, -568, -1370, -360, -902, +24, -701, -266, -133, +1143, -162, +431, -320, -856, -257, -656, -421, +206, },
|
||||
{ +22156, +10670, -8825, +31, -3255, +3766, +558, -3195, -2534, +719, +1180, -629, +1637, -2399, +832, -768, -1413, -237, -975, +241, -538, -329, -188, +1315, -228, +362, -275, -900, -124, -757, -357, +287, },
|
||||
{ +21278, +9846, -7554, -398, -3803, +4159, +764, -3114, -2412, +808, +1003, -456, +1754, -2523, +558, -585, -1493, -124, -765, +323, -452, -399, -154, +1291, -276, +265, -134, -876, -130, -701, -238, +296, },
|
||||
{ +19461, +9711, -6136, -768, -4103, +4127, +1289, -3000, -2181, +873, +525, -145, +1756, -2618, +563, -484, -1372, +57, -547, +215, -362, -384, -264, +1161, -298, +275, -17, -893, -58, -554, -229, +265, },
|
||||
{ +17277, +9611, -4621, -998, -4208, +3875, +1658, -2589, -1841, +534, +392, -46, +1442, -2298, +316, -236, -1201, +192, -408, +85, -140, -396, -437, +993, -150, +202, +81, -782, +50, -474, -177, +231, },
|
||||
{ +14172, +9673, -3573, -888, -1759, +2079, +423, -1986, -1744, +555, +790, -69, +1145, -1353, +372, +59, -818, -47, -210, +85, -314, -228, -308, +651, -194, +55, +187, -514, -187, -359, -318, -25, },
|
||||
{ +12049, +9447, -2228, -1231, -1752, +1946, +840, -1465, -1503, +155, +682, -24, +949, -1008, +142, +192, -555, +85, -44, +97, -161, -260, -418, +506, -91, +11, +275, -348, -145, -288, -275, -84, },
|
||||
{ +10303, +9142, -1241, -1401, -1603, +1679, +1080, -926, -1326, -100, +605, -40, +855, -692, +34, +292, -275, +96, +72, +212, -127, -202, -437, +334, -5, -31, +233, -223, -120, -232, -200, -174, },
|
||||
{ +9017, +8838, -619, -1486, -1392, +1440, +1205, -522, -1133, -209, +558, -14, +754, -391, +50, +313, -71, +90, +164, +296, -77, -139, -435, +174, +4, -91, +133, -78, -72, -176, -176, -213, },
|
||||
{ +8142, +8597, -267, -1538, -1157, +1261, +1254, -258, -963, -244, +541, +75, +679, -187, +160, +270, +1, +140, +187, +302, -55, -83, -444, +4, -35, -132, +106, +52, -76, -189, -49, -190, },
|
||||
{ +7622, +8383, -48, -1578, -899, +1181, +1234, -71, -944, -214, +551, +137, +707, -144, +260, +320, -94, +109, +245, +239, -123, -2, -426, -196, -30, -52, +38, -6, +17, -57, -187, -8, },
|
||||
{ +7332, +8319, +57, -1601, -631, +1238, +1135, +21, -967, -327, +659, +76, +672, +38, +199, +349, -41, -97, +208, +331, -233, -127, -295, -155, -164, -26, -20, -11, +90, -178, +192, +245, },
|
||||
{ +7317, +8418, -7, -1642, -367, +1419, +1147, -111, -974, -384, +550, +84, +565, +94, +364, +313, -68, -10, +86, +197, -143, -149, -385, -44, -17, -229, -53, +121, -114, +140, +435, -168, },
|
||||
{ +7367, +8733, -36, -1826, -124, +1616, +1200, -184, -1158, -452, +570, -113, +408, +131, +319, +450, -22, -49, +185, +112, -380, -100, -266, -117, -72, -71, +10, -213, +51, +444, +58, -226, },
|
||||
{ +7780, +9068, -243, -2044, +77, +1858, +1206, -274, -1289, -551, +596, -178, +200, -29, +344, +432, -90, +103, +283, +41, -414, -210, -414, +8, +0, -140, +15, -152, +111, +292, -78, -206, },
|
||||
{ +8345, +9580, -574, -2318, +346, +2040, +1168, -408, -1458, -527, +676, -258, +1, -124, +320, +310, -183, +87, +370, +84, -415, -236, -480, -21, -74, -20, +45, -230, +106, +351, -132, -434, },
|
||||
{ +9094, +10154, -1025, -2554, +632, +2229, +994, -595, -1621, -437, +874, -416, -132, -257, +352, +267, -420, +47, +366, +3, -398, -143, -510, +98, -129, -195, +92, -138, -60, +248, +111, -492, },
|
||||
{ +10041, +10768, -1614, -2719, +916, +2381, +756, -898, -1763, -304, +1151, -599, -325, -310, +358, +208, -536, -91, +282, -46, -529, -37, -456, +197, -31, -321, -13, -176, -156, +116, +291, -363, },
|
||||
{ +11107, +11413, -2234, -2770, +1108, +2450, +521, -1208, -1885, -154, +1431, -759, -498, -367, +419, +97, -627, -128, +121, -90, -589, -28, -356, +273, +33, -279, -81, -291, -313, -16, +331, +7, },
|
||||
{ +12280, +12021, -2906, -2717, +1134, +2377, +314, -1466, -2001, -37, +1641, -947, -595, -443, +445, +1, -745, -215, +22, -112, -652, -10, -293, +280, +22, -180, -159, -383, -467, -188, +208, +307, },
|
||||
{ +13475, +12606, -3625, -2517, +1014, +2161, +183, -1625, -2084, +8, +1791, -1103, -612, -507, +435, -57, -847, -324, -41, -71, -678, +57, -282, +263, -37, -62, -209, -455, -522, -398, +113, +417, },
|
||||
{ +14812, +13011, -4511, -2154, +806, +1834, +70, -1725, -2175, +16, +1867, -1208, -532, -590, +417, -130, -929, -396, -58, -66, -662, +121, -368, +291, -144, -1, -180, -513, -541, -616, +106, +375, },
|
||||
{ +16380, +13067, -5650, -1592, +605, +1495, -131, -1780, -2290, +40, +2010, -1367, -305, -662, +396, -248, -905, -354, -222, +46, -645, +6, -354, +338, -292, +124, -80, -658, -520, -638, -12, +271, },
|
||||
{ +17982, +12702, -6846, -878, +421, +1177, -463, -1808, -2473, +274, +2108, -1572, +121, -826, +355, -267, -731, -513, -308, +176, -908, +60, -376, +313, -223, +268, -136, -780, -340, -699, -278, +268, },
|
||||
{ +19157, +12247, -7860, -132, +149, +912, -724, -1957, -2452, +536, +2076, -1557, +521, -1124, +525, -122, -855, -442, -535, +76, -863, -69, -379, +601, -217, +257, -79, -739, -389, -790, -342, +200, },
|
||||
{ +19711, +11522, -8169, +401, -329, +905, -928, -2048, -2370, +752, +2017, -1467, +767, -1174, +691, -185, -760, -679, -713, +177, -1039, -25, -158, +692, -291, +423, -59, -878, -408, -762, -397, +110, },
|
||||
{ +19465, +10779, -7703, +460, -893, +1187, -817, -2234, -2246, +1019, +1640, -1190, +1218, -1460, +857, -119, -1111, -511, -817, +81, -770, -57, -137, +805, -201, +370, -136, -863, -389, -713, -437, +67, },
|
||||
{ +18333, +10203, -6584, +85, -1382, +1684, -563, -2346, -2049, +928, +1357, -671, +1226, -1413, +733, -229, -1009, -521, -666, +153, -618, -188, -102, +925, -315, +267, -79, -795, -334, -687, -385, +130, },
|
||||
{ +16441, +9946, -5138, -473, -1669, +2005, -91, -2252, -1996, +837, +1093, -412, +1392, -1542, +535, -11, -1080, -203, -475, +134, -478, -260, -105, +753, -285, +165, +32, -670, -301, -515, -295, +22, },
|
||||
{ +13089, +9529, -4017, -237, +483, +1183, -334, -1490, -1552, +647, +1264, -471, +629, -605, +562, -36, -643, -387, -501, +84, -371, -60, -86, +640, -100, +137, -1, -574, -350, -440, -324, -139, },
|
||||
{ +11898, +9621, -3405, -1165, +243, +1679, +179, -1312, -1709, +64, +1140, -239, +692, -458, +479, +250, -561, -188, -174, +41, -320, -165, -304, +589, -101, -43, +124, -435, -309, -354, -282, -103, },
|
||||
{ +10997, +9658, -2780, -1802, -26, +1783, +569, -947, -1662, -248, +967, -127, +729, -294, +466, +390, -354, -145, +46, +95, -329, -112, -479, +387, +17, -149, +90, -226, -277, -280, -149, -147, },
|
||||
{ +10403, +9825, -2433, -2099, -53, +1814, +738, -808, -1574, -372, +873, -167, +701, -213, +490, +502, -294, -53, +103, +45, -399, -57, -537, +124, +113, -120, +21, -185, -188, -248, -114, -74, },
|
||||
{ +10392, +9882, -2497, -2112, +324, +1944, +702, -937, -1618, -322, +898, -262, +449, -113, +460, +482, -188, -10, +186, -20, -556, -166, -451, +104, +9, -20, +13, -185, -148, -338, -76, +107, },
|
||||
{ +10862, +9834, -2867, -1780, +884, +2063, +422, -1170, -1644, -165, +979, -389, +198, -268, +566, +314, -335, +218, +172, -127, -560, -306, -505, +230, +61, -85, -17, -114, -234, -393, -69, +141, },
|
||||
{ +11578, +9958, -3241, -1267, +1305, +1835, +61, -1353, -1523, +172, +1158, -610, -59, -256, +501, +100, -434, +87, +156, -173, -554, -216, -452, +238, -8, +72, -57, -233, -279, -439, -54, +128, },
|
||||
{ +12590, +10282, -3669, -831, +1213, +1299, -204, -1324, -1305, +642, +1310, -929, -150, -265, +378, -166, -511, -226, -25, -77, -591, -30, -316, +195, -77, +192, -79, -444, -281, -501, -173, +158, },
|
||||
{ +13820, +10820, -4370, -641, +688, +719, -208, -1170, -1120, +1054, +1422, -1268, +60, -395, +126, -158, -785, -547, -55, -15, -622, +139, -270, +187, +11, +211, -203, -518, -250, -711, -272, +251, },
|
||||
{ +14973, +10840, -5035, -319, +215, +327, -180, -1056, -1001, +1357, +1436, -1376, +373, -623, +75, -133, -1012, -696, -148, +89, -603, +166, -149, +257, +111, +201, -249, -478, -375, -806, -271, +241, },
|
||||
{ +15155, +10582, -5238, +16, +115, +211, -361, -1141, -1066, +1374, +1522, -1325, +512, -561, +33, -137, -860, -968, -261, +174, -757, +281, -16, +297, +93, +272, -236, -631, -384, -770, -341, +145, },
|
||||
{ +14475, +9926, -4814, +144, +323, +523, -528, -1336, -1319, +1198, +1433, -1025, +675, -646, +308, -70, -834, -739, -508, +86, -551, +161, +29, +400, +61, +248, -225, -631, -389, -587, -390, -22, },
|
||||
{ +11096, +9607, -2841, -481, +1236, +612, -162, -1033, -885, +1058, +1197, -645, +47, -150, +202, +5, -433, -652, -254, -16, -605, +40, +33, +357, +315, +288, -273, -769, -633, -453, +2, +259, },
|
||||
},
|
||||
|
||||
/* HRIR Delays */
|
||||
{ 12, 12, 13, 14, 14, 14, 13, 12, 11, 10, 10, 10, 11, 12, 13, 14, 15, 15, 16, 16, 16, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 18, 18, 18, 18, 17, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 20, 20, 20, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 5, 5, 5, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 21, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 24, 24, 24, 23, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 24, 25, 26, 26, 26, 26, 26, 25, 24, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 24, 25, 26, 26, 26, 26, 26, 25, 24, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 24, 24, 24, 23, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 21, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 20, 20, 20, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 5, 5, 5, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 18, 18, 18, 18, 17, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 16, 16, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 14, 14, 13, 12, 11, 10, 10, 10, 11, 12, }
|
||||
+822
@@ -0,0 +1,822 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alSource.h"
|
||||
#include "alBuffer.h"
|
||||
#include "alListener.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alu.h"
|
||||
#include "bs2b.h"
|
||||
|
||||
|
||||
static __inline 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); }
|
||||
|
||||
static __inline ALfloat Sample_ALshort(ALshort val)
|
||||
{ return val * (1.0f/32767.0f); }
|
||||
|
||||
static __inline ALfloat Sample_ALfloat(ALfloat val)
|
||||
{ return val; }
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static void Load_##T(ALfloat *dst, const T *src, ALuint samples) \
|
||||
{ \
|
||||
ALuint i; \
|
||||
for(i = 0;i < samples;i++) \
|
||||
dst[i] = Sample_##T(src[i]); \
|
||||
}
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
static void LoadStack(ALfloat *dst, const ALvoid *src, enum FmtType srctype, ALuint samples)
|
||||
{
|
||||
switch(srctype)
|
||||
{
|
||||
case FmtByte:
|
||||
Load_ALbyte(dst, src, samples);
|
||||
break;
|
||||
case FmtShort:
|
||||
Load_ALshort(dst, src, samples);
|
||||
break;
|
||||
case FmtFloat:
|
||||
Load_ALfloat(dst, src, samples);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SilenceStack(ALfloat *dst, ALuint samples)
|
||||
{
|
||||
ALuint i;
|
||||
for(i = 0;i < samples;i++)
|
||||
dst[i] = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
|
||||
{
|
||||
ALbufferlistitem *BufferListItem;
|
||||
ALuint DataPosInt, DataPosFrac;
|
||||
ALuint BuffersPlayed;
|
||||
ALboolean Looping;
|
||||
ALuint increment;
|
||||
enum Resampler Resampler;
|
||||
ALenum State;
|
||||
ALuint OutPos;
|
||||
ALuint NumChannels;
|
||||
ALuint FrameSize;
|
||||
ALint64 DataSize64;
|
||||
ALuint i;
|
||||
|
||||
/* Get source info */
|
||||
State = Source->state;
|
||||
BuffersPlayed = Source->BuffersPlayed;
|
||||
DataPosInt = Source->position;
|
||||
DataPosFrac = Source->position_fraction;
|
||||
Looping = Source->bLooping;
|
||||
increment = Source->Params.Step;
|
||||
Resampler = Source->Resampler;
|
||||
NumChannels = Source->NumChannels;
|
||||
FrameSize = NumChannels * Source->SampleSize;
|
||||
|
||||
/* Get current buffer queue item */
|
||||
BufferListItem = Source->queue;
|
||||
for(i = 0;i < BuffersPlayed;i++)
|
||||
BufferListItem = BufferListItem->next;
|
||||
|
||||
OutPos = 0;
|
||||
do {
|
||||
const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
|
||||
const ALuint BufferPadding = ResamplerPadding[Resampler];
|
||||
ALfloat StackData[STACK_DATA_SIZE/sizeof(ALfloat)];
|
||||
ALfloat *SrcData = StackData;
|
||||
ALuint SrcDataSize = 0;
|
||||
ALuint BufferSize;
|
||||
|
||||
/* Figure out how many buffer bytes will be needed */
|
||||
DataSize64 = SamplesToDo-OutPos+1;
|
||||
DataSize64 *= increment;
|
||||
DataSize64 += DataPosFrac+FRACTIONMASK;
|
||||
DataSize64 >>= FRACTIONBITS;
|
||||
DataSize64 += BufferPadding+BufferPrePadding;
|
||||
DataSize64 *= NumChannels;
|
||||
|
||||
BufferSize = (ALuint)mini64(DataSize64, STACK_DATA_SIZE/sizeof(ALfloat));
|
||||
BufferSize /= NumChannels;
|
||||
|
||||
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;
|
||||
DataSize64 -= BufferPadding+BufferPrePadding;
|
||||
DataSize64 <<= FRACTIONBITS;
|
||||
DataSize64 -= increment;
|
||||
DataSize64 -= DataPosFrac;
|
||||
|
||||
BufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
|
||||
BufferSize = minu(BufferSize, (SamplesToDo-OutPos));
|
||||
|
||||
SrcData += BufferPrePadding*NumChannels;
|
||||
Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac,
|
||||
OutPos, SamplesToDo, BufferSize);
|
||||
OutPos += BufferSize;
|
||||
|
||||
/* Handle looping sources */
|
||||
while(1)
|
||||
{
|
||||
const ALbuffer *ALBuffer;
|
||||
ALuint DataSize = 0;
|
||||
ALuint LoopStart = 0;
|
||||
ALuint LoopEnd = 0;
|
||||
|
||||
if((ALBuffer=BufferListItem->buffer) != NULL)
|
||||
{
|
||||
DataSize = ALBuffer->SampleLen;
|
||||
LoopStart = ALBuffer->LoopStart;
|
||||
LoopEnd = ALBuffer->LoopEnd;
|
||||
if(LoopEnd > DataPosInt)
|
||||
break;
|
||||
}
|
||||
|
||||
if(Looping && Source->lSourceType == AL_STATIC)
|
||||
{
|
||||
DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
|
||||
break;
|
||||
}
|
||||
|
||||
if(DataSize > DataPosInt)
|
||||
break;
|
||||
|
||||
if(BufferListItem->next)
|
||||
{
|
||||
BufferListItem = BufferListItem->next;
|
||||
BuffersPlayed++;
|
||||
}
|
||||
else if(Looping)
|
||||
{
|
||||
BufferListItem = Source->queue;
|
||||
BuffersPlayed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
State = AL_STOPPED;
|
||||
BufferListItem = Source->queue;
|
||||
BuffersPlayed = Source->BuffersInQueue;
|
||||
DataPosInt = 0;
|
||||
DataPosFrac = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
DataPosInt -= DataSize;
|
||||
}
|
||||
} while(State == AL_PLAYING && OutPos < SamplesToDo);
|
||||
|
||||
/* Update source info */
|
||||
Source->state = State;
|
||||
Source->BuffersPlayed = BuffersPlayed;
|
||||
Source->position = DataPosInt;
|
||||
Source->position_fraction = DataPosFrac;
|
||||
Source->HrtfOffset += OutPos;
|
||||
if(State == AL_PLAYING)
|
||||
{
|
||||
Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos;
|
||||
Source->HrtfMoving = AL_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Source->HrtfCounter = 0;
|
||||
Source->HrtfMoving = AL_FALSE;
|
||||
}
|
||||
}
|
||||
+318
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2010 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alu.h"
|
||||
|
||||
static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS],
|
||||
enum Channel Speaker2Chan[MAXCHANNELS], ALint chans)
|
||||
{
|
||||
char *confkey, *next;
|
||||
char *layout_str;
|
||||
char *sep, *end;
|
||||
enum Channel val;
|
||||
const char *str;
|
||||
int i;
|
||||
|
||||
if(!ConfigValueStr(NULL, name, &str) && !ConfigValueStr(NULL, "layout", &str))
|
||||
return;
|
||||
|
||||
layout_str = strdup(str);
|
||||
next = confkey = layout_str;
|
||||
while(next && *next)
|
||||
{
|
||||
confkey = next;
|
||||
next = strchr(confkey, ',');
|
||||
if(next)
|
||||
{
|
||||
*next = 0;
|
||||
do {
|
||||
next++;
|
||||
} while(isspace(*next) || *next == ',');
|
||||
}
|
||||
|
||||
sep = strchr(confkey, '=');
|
||||
if(!sep || confkey == sep)
|
||||
{
|
||||
ERR("Malformed speaker key: %s\n", confkey);
|
||||
continue;
|
||||
}
|
||||
|
||||
end = sep - 1;
|
||||
while(isspace(*end) && end != confkey)
|
||||
end--;
|
||||
*(++end) = 0;
|
||||
|
||||
if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
|
||||
val = FRONT_LEFT;
|
||||
else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
|
||||
val = FRONT_RIGHT;
|
||||
else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
|
||||
val = FRONT_CENTER;
|
||||
else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
|
||||
val = BACK_LEFT;
|
||||
else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
|
||||
val = BACK_RIGHT;
|
||||
else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
|
||||
val = BACK_CENTER;
|
||||
else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
|
||||
val = SIDE_LEFT;
|
||||
else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
|
||||
val = SIDE_RIGHT;
|
||||
else
|
||||
{
|
||||
ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
|
||||
continue;
|
||||
}
|
||||
|
||||
*(sep++) = 0;
|
||||
while(isspace(*sep))
|
||||
sep++;
|
||||
|
||||
for(i = 0;i < chans;i++)
|
||||
{
|
||||
if(Speaker2Chan[i] == val)
|
||||
{
|
||||
long angle = strtol(sep, NULL, 10);
|
||||
if(angle >= -180 && angle <= 180)
|
||||
SpeakerAngle[i] = angle * F_PI/180.0f;
|
||||
else
|
||||
ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(layout_str);
|
||||
layout_str = NULL;
|
||||
|
||||
for(i = 0;i < chans;i++)
|
||||
{
|
||||
int min = i;
|
||||
int i2;
|
||||
|
||||
for(i2 = i+1;i2 < chans;i2++)
|
||||
{
|
||||
if(SpeakerAngle[i2] < SpeakerAngle[min])
|
||||
min = i2;
|
||||
}
|
||||
|
||||
if(min != i)
|
||||
{
|
||||
ALfloat tmpf;
|
||||
enum Channel tmpc;
|
||||
|
||||
tmpf = SpeakerAngle[i];
|
||||
SpeakerAngle[i] = SpeakerAngle[min];
|
||||
SpeakerAngle[min] = tmpf;
|
||||
|
||||
tmpc = Speaker2Chan[i];
|
||||
Speaker2Chan[i] = Speaker2Chan[min];
|
||||
Speaker2Chan[min] = tmpc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ALfloat aluLUTpos2Angle(ALint pos)
|
||||
{
|
||||
if(pos < QUADRANT_NUM)
|
||||
return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos));
|
||||
if(pos < 2 * QUADRANT_NUM)
|
||||
return 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Speaker2Chan = Device->Speaker2Chan;
|
||||
switch(Device->FmtChans)
|
||||
{
|
||||
case DevFmtMono:
|
||||
Device->NumChan = 1;
|
||||
Speaker2Chan[0] = FRONT_CENTER;
|
||||
SpeakerAngle[0] = F_PI/180.0f * 0.0f;
|
||||
layoutname = NULL;
|
||||
break;
|
||||
|
||||
case DevFmtStereo:
|
||||
Device->NumChan = 2;
|
||||
Speaker2Chan[0] = FRONT_LEFT;
|
||||
Speaker2Chan[1] = FRONT_RIGHT;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * 90.0f;
|
||||
layoutname = "layout_stereo";
|
||||
break;
|
||||
|
||||
case DevFmtQuad:
|
||||
Device->NumChan = 4;
|
||||
Speaker2Chan[0] = BACK_LEFT;
|
||||
Speaker2Chan[1] = FRONT_LEFT;
|
||||
Speaker2Chan[2] = FRONT_RIGHT;
|
||||
Speaker2Chan[3] = BACK_RIGHT;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -135.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * -45.0f;
|
||||
SpeakerAngle[2] = F_PI/180.0f * 45.0f;
|
||||
SpeakerAngle[3] = F_PI/180.0f * 135.0f;
|
||||
layoutname = "layout_quad";
|
||||
break;
|
||||
|
||||
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;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -110.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
|
||||
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||
SpeakerAngle[4] = F_PI/180.0f * 110.0f;
|
||||
layoutname = "layout_surround51";
|
||||
break;
|
||||
|
||||
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;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
|
||||
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
||||
layoutname = "layout_side51";
|
||||
break;
|
||||
|
||||
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;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -90.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * -30.0f;
|
||||
SpeakerAngle[2] = F_PI/180.0f * 0.0f;
|
||||
SpeakerAngle[3] = F_PI/180.0f * 30.0f;
|
||||
SpeakerAngle[4] = F_PI/180.0f * 90.0f;
|
||||
SpeakerAngle[5] = F_PI/180.0f * 180.0f;
|
||||
layoutname = "layout_surround61";
|
||||
break;
|
||||
|
||||
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;
|
||||
SpeakerAngle[0] = F_PI/180.0f * -150.0f;
|
||||
SpeakerAngle[1] = F_PI/180.0f * -90.0f;
|
||||
SpeakerAngle[2] = F_PI/180.0f * -30.0f;
|
||||
SpeakerAngle[3] = F_PI/180.0f * 0.0f;
|
||||
SpeakerAngle[4] = F_PI/180.0f * 30.0f;
|
||||
SpeakerAngle[5] = F_PI/180.0f * 90.0f;
|
||||
SpeakerAngle[6] = F_PI/180.0f * 150.0f;
|
||||
layoutname = "layout_surround71";
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
-457
@@ -1,457 +0,0 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
static void *pa_handle;
|
||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||
MAKE_FUNC(Pa_Initialize);
|
||||
MAKE_FUNC(Pa_Terminate);
|
||||
MAKE_FUNC(Pa_GetErrorText);
|
||||
MAKE_FUNC(Pa_StartStream);
|
||||
MAKE_FUNC(Pa_StopStream);
|
||||
MAKE_FUNC(Pa_OpenStream);
|
||||
MAKE_FUNC(Pa_CloseStream);
|
||||
MAKE_FUNC(Pa_GetDefaultOutputDevice);
|
||||
MAKE_FUNC(Pa_GetStreamInfo);
|
||||
#undef MAKE_FUNC
|
||||
|
||||
|
||||
static const ALCchar pa_device[] = "PortAudio Software";
|
||||
static const ALCchar pa_capture[] = "PortAudio Capture";
|
||||
static volatile ALuint load_count;
|
||||
|
||||
|
||||
void *pa_load(void)
|
||||
{
|
||||
if(load_count == 0)
|
||||
{
|
||||
PaError err;
|
||||
|
||||
#ifdef _WIN32
|
||||
pa_handle = LoadLibrary("portaudio.dll");
|
||||
#define LOAD_FUNC(x) do { \
|
||||
p##x = (typeof(p##x))GetProcAddress(pa_handle, #x); \
|
||||
if(!(p##x)) { \
|
||||
AL_PRINT("Could not load %s from portaudio.dll\n", #x); \
|
||||
FreeLibrary(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
|
||||
const char *str;
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# define PALIB "libportaudio.2.dylib"
|
||||
#else
|
||||
# define PALIB "libportaudio.so.2"
|
||||
#endif
|
||||
pa_handle = dlopen(PALIB, RTLD_NOW);
|
||||
dlerror();
|
||||
|
||||
#define LOAD_FUNC(f) do { \
|
||||
p##f = (typeof(f)*)dlsym(pa_handle, #f); \
|
||||
if((str=dlerror()) != NULL) \
|
||||
{ \
|
||||
dlclose(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
str = NULL;
|
||||
pa_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(f) p##f = f
|
||||
#endif
|
||||
|
||||
if(!pa_handle)
|
||||
return NULL;
|
||||
|
||||
LOAD_FUNC(Pa_Initialize);
|
||||
LOAD_FUNC(Pa_Terminate);
|
||||
LOAD_FUNC(Pa_GetErrorText);
|
||||
LOAD_FUNC(Pa_StartStream);
|
||||
LOAD_FUNC(Pa_StopStream);
|
||||
LOAD_FUNC(Pa_OpenStream);
|
||||
LOAD_FUNC(Pa_CloseStream);
|
||||
LOAD_FUNC(Pa_GetDefaultOutputDevice);
|
||||
LOAD_FUNC(Pa_GetStreamInfo);
|
||||
|
||||
#undef LOAD_FUNC
|
||||
|
||||
if((err=pPa_Initialize()) != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(pa_handle);
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
dlclose(pa_handle);
|
||||
#endif
|
||||
pa_handle = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
++load_count;
|
||||
|
||||
return pa_handle;
|
||||
}
|
||||
|
||||
void pa_unload(void)
|
||||
{
|
||||
if(load_count == 0 || --load_count > 0)
|
||||
return;
|
||||
|
||||
pPa_Terminate();
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(pa_handle);
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
dlclose(pa_handle);
|
||||
#endif
|
||||
pa_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
PaStream *stream;
|
||||
ALuint update_size;
|
||||
|
||||
RingBuffer *ring;
|
||||
} pa_data;
|
||||
|
||||
|
||||
static int pa_callback(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
|
||||
const PaStreamCallbackFlags statusFlags, void *userData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)userData;
|
||||
|
||||
(void)inputBuffer;
|
||||
(void)timeInfo;
|
||||
(void)statusFlags;
|
||||
|
||||
aluMixData(device, outputBuffer, framesPerBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pa_capture_cb(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
|
||||
const PaStreamCallbackFlags statusFlags, void *userData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)userData;
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
|
||||
(void)outputBuffer;
|
||||
(void)timeInfo;
|
||||
(void)statusFlags;
|
||||
|
||||
WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
const PaStreamInfo *streamInfo;
|
||||
PaStreamParameters outParams;
|
||||
pa_data *data;
|
||||
PaError err;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = pa_device;
|
||||
else if(strcmp(deviceName, pa_device) != 0)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(!pa_load())
|
||||
return ALC_FALSE;
|
||||
|
||||
data = (pa_data*)calloc(1, sizeof(pa_data));
|
||||
data->update_size = device->UpdateSize;
|
||||
|
||||
device->ExtraData = data;
|
||||
|
||||
outParams.device = GetConfigValueInt("port", "device", -1);
|
||||
if(outParams.device < 0)
|
||||
outParams.device = pPa_GetDefaultOutputDevice();
|
||||
outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
|
||||
(float)device->Frequency;
|
||||
outParams.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
{
|
||||
case 1:
|
||||
outParams.sampleFormat = paUInt8;
|
||||
break;
|
||||
case 2:
|
||||
outParams.sampleFormat = paInt16;
|
||||
break;
|
||||
case 4:
|
||||
outParams.sampleFormat = paFloat32;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
device->ExtraData = NULL;
|
||||
free(data);
|
||||
pa_unload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
outParams.channelCount = aluChannelsFromFormat(device->Format);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
|
||||
device->UpdateSize, paNoFlag, pa_callback, device);
|
||||
if(err != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
device->ExtraData = NULL;
|
||||
free(data);
|
||||
pa_unload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
streamInfo = pPa_GetStreamInfo(data->stream);
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
device->Frequency = streamInfo->sampleRate;
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void pa_close_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = pPa_CloseStream(data->stream);
|
||||
if(err != paNoError)
|
||||
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
|
||||
pa_unload();
|
||||
}
|
||||
|
||||
static ALCboolean pa_reset_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
const PaStreamInfo *streamInfo;
|
||||
PaError err;
|
||||
|
||||
streamInfo = pPa_GetStreamInfo(data->stream);
|
||||
device->Frequency = streamInfo->sampleRate;
|
||||
device->UpdateSize = data->update_size;
|
||||
|
||||
err = pPa_StartStream(data->stream);
|
||||
if(err != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
static void pa_stop_playback(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = pPa_StopStream(data->stream);
|
||||
if(err != paNoError)
|
||||
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
PaStreamParameters inParams;
|
||||
ALuint frame_size;
|
||||
pa_data *data;
|
||||
PaError err;
|
||||
|
||||
if(!deviceName)
|
||||
deviceName = pa_capture;
|
||||
else if(strcmp(deviceName, pa_capture) != 0)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(!pa_load())
|
||||
return ALC_FALSE;
|
||||
|
||||
data = (pa_data*)calloc(1, sizeof(pa_data));
|
||||
if(data == NULL)
|
||||
{
|
||||
alcSetError(device, ALC_OUT_OF_MEMORY);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
frame_size = aluChannelsFromFormat(device->Format) *
|
||||
aluBytesFromFormat(device->Format);
|
||||
data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
|
||||
if(data->ring == NULL)
|
||||
{
|
||||
alcSetError(device, ALC_OUT_OF_MEMORY);
|
||||
goto error;
|
||||
}
|
||||
|
||||
inParams.device = GetConfigValueInt("port", "capture", -1);
|
||||
if(inParams.device < 0)
|
||||
inParams.device = pPa_GetDefaultOutputDevice();
|
||||
inParams.suggestedLatency = 0.0f;
|
||||
inParams.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
{
|
||||
case 1:
|
||||
inParams.sampleFormat = paUInt8;
|
||||
break;
|
||||
case 2:
|
||||
inParams.sampleFormat = paInt16;
|
||||
break;
|
||||
case 4:
|
||||
inParams.sampleFormat = paFloat32;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: 0x%x\n", device->Format);
|
||||
goto error;
|
||||
}
|
||||
inParams.channelCount = aluChannelsFromFormat(device->Format);
|
||||
|
||||
err = pPa_OpenStream(&data->stream, &inParams, NULL, device->Frequency,
|
||||
paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
|
||||
if(err != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
goto error;
|
||||
}
|
||||
|
||||
device->szDeviceName = strdup(deviceName);
|
||||
|
||||
device->ExtraData = data;
|
||||
return ALC_TRUE;
|
||||
|
||||
error:
|
||||
DestroyRingBuffer(data->ring);
|
||||
free(data);
|
||||
pa_unload();
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void pa_close_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = pPa_CloseStream(data->stream);
|
||||
if(err != paNoError)
|
||||
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
|
||||
pa_unload();
|
||||
}
|
||||
|
||||
static void pa_start_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = pPa_StartStream(data->stream);
|
||||
if(err != paNoError)
|
||||
AL_PRINT("Error starting stream: %s\n", pPa_GetErrorText(err));
|
||||
}
|
||||
|
||||
static void pa_stop_capture(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = (pa_data*)device->ExtraData;
|
||||
PaError err;
|
||||
|
||||
err = pPa_StopStream(data->stream);
|
||||
if(err != paNoError)
|
||||
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
|
||||
}
|
||||
|
||||
static void pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
if(samples <= (ALCuint)RingBufferSize(data->ring))
|
||||
ReadRingBuffer(data->ring, buffer, samples);
|
||||
else
|
||||
alcSetError(device, ALC_INVALID_VALUE);
|
||||
}
|
||||
|
||||
static ALCuint pa_available_samples(ALCdevice *device)
|
||||
{
|
||||
pa_data *data = device->ExtraData;
|
||||
return RingBufferSize(data->ring);
|
||||
}
|
||||
|
||||
|
||||
static const BackendFuncs pa_funcs = {
|
||||
pa_open_playback,
|
||||
pa_close_playback,
|
||||
pa_reset_playback,
|
||||
pa_stop_playback,
|
||||
pa_open_capture,
|
||||
pa_close_capture,
|
||||
pa_start_capture,
|
||||
pa_stop_capture,
|
||||
pa_capture_samples,
|
||||
pa_available_samples
|
||||
};
|
||||
|
||||
void alc_pa_init(BackendFuncs *func_list)
|
||||
{
|
||||
*func_list = pa_funcs;
|
||||
}
|
||||
|
||||
void alc_pa_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void alc_pa_probe(int type)
|
||||
{
|
||||
if(!pa_load()) return;
|
||||
|
||||
if(type == DEVICE_PROBE)
|
||||
AppendDeviceList(pa_device);
|
||||
else if(type == ALL_DEVICE_PROBE)
|
||||
AppendAllDeviceList(pa_device);
|
||||
else if(type == CAPTURE_DEVICE_PROBE)
|
||||
AppendCaptureDeviceList(pa_capture);
|
||||
|
||||
pa_unload();
|
||||
}
|
||||
-1030
File diff suppressed because it is too large
Load Diff
-495
@@ -1,495 +0,0 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
// MMSYSTEM Capture Device
|
||||
ALboolean bWaveInShutdown;
|
||||
HANDLE hWaveInHdrEvent;
|
||||
HANDLE hWaveInThreadEvent;
|
||||
HANDLE hWaveInThread;
|
||||
DWORD ulWaveInThreadID;
|
||||
ALint lWaveInBuffersCommitted;
|
||||
HWAVEIN hWaveInHandle;
|
||||
WAVEHDR WaveInBuffer[4];
|
||||
ALCchar *pCapturedSampleData;
|
||||
ALuint ulCapturedDataSize;
|
||||
ALuint ulReadCapturedDataPos;
|
||||
ALuint ulWriteCapturedDataPos;
|
||||
} WinMMData;
|
||||
|
||||
|
||||
static ALCchar **CaptureDeviceList;
|
||||
static ALuint NumCaptureDevices;
|
||||
|
||||
static void ProbeDevices(void)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
free(CaptureDeviceList[i]);
|
||||
|
||||
NumCaptureDevices = waveInGetNumDevs();
|
||||
CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
WAVEINCAPS WaveInCaps;
|
||||
|
||||
CaptureDeviceList[i] = NULL;
|
||||
if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
|
||||
{
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "WaveIn on %s", WaveInCaps.szPname);
|
||||
CaptureDeviceList[i] = strdup(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
WaveInProc
|
||||
|
||||
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)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice *)dwInstance;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
|
||||
(void)hDevice;
|
||||
(void)dwParam2;
|
||||
|
||||
if ((uMsg==WIM_DATA))
|
||||
{
|
||||
// Decrement number of buffers in use
|
||||
pData->lWaveInBuffersCommitted--;
|
||||
|
||||
if (pData->bWaveInShutdown == AL_FALSE)
|
||||
{
|
||||
// Notify Wave Processor Thread that a Wave Header has returned
|
||||
PostThreadMessage(pData->ulWaveInThreadID,uMsg,0,dwParam1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pData->lWaveInBuffersCommitted == 0)
|
||||
{
|
||||
// Signal Wave Buffers Returned event
|
||||
if (pData->hWaveInHdrEvent)
|
||||
SetEvent(pData->hWaveInHdrEvent);
|
||||
|
||||
// Post 'Quit' Message to WaveIn Processor Thread
|
||||
PostThreadMessage(pData->ulWaveInThreadID,WM_QUIT,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CaptureThreadProc
|
||||
|
||||
Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
|
||||
audio data.
|
||||
*/
|
||||
DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)lpParameter;
|
||||
WinMMData *pData = pDevice->ExtraData;
|
||||
ALuint ulOffset, ulMaxSize, ulSection;
|
||||
LPWAVEHDR pWaveHdr;
|
||||
MSG msg;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
if ((msg.message==WIM_DATA)&&(!pData->bWaveInShutdown))
|
||||
{
|
||||
SuspendContext(NULL);
|
||||
|
||||
pWaveHdr = ((LPWAVEHDR)msg.lParam);
|
||||
|
||||
// Calculate offset in local buffer to write data to
|
||||
ulOffset = pData->ulWriteCapturedDataPos % pData->ulCapturedDataSize;
|
||||
|
||||
if ((ulOffset + pWaveHdr->dwBytesRecorded) > pData->ulCapturedDataSize)
|
||||
{
|
||||
ulSection = pData->ulCapturedDataSize - ulOffset;
|
||||
memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, ulSection);
|
||||
memcpy(pData->pCapturedSampleData, pWaveHdr->lpData + ulSection, pWaveHdr->dwBytesRecorded - ulSection);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pData->pCapturedSampleData + ulOffset, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded);
|
||||
}
|
||||
|
||||
pData->ulWriteCapturedDataPos += pWaveHdr->dwBytesRecorded;
|
||||
|
||||
if (pData->ulWriteCapturedDataPos > (pData->ulReadCapturedDataPos + pData->ulCapturedDataSize))
|
||||
{
|
||||
// Application has not read enough audio data from the capture buffer so data has been
|
||||
// overwritten. Reset ReadPosition.
|
||||
pData->ulReadCapturedDataPos = pData->ulWriteCapturedDataPos - pData->ulCapturedDataSize;
|
||||
}
|
||||
|
||||
// To prevent an over-flow prevent the offset values from getting too large
|
||||
ulMaxSize = pData->ulCapturedDataSize << 4;
|
||||
if ((pData->ulReadCapturedDataPos > ulMaxSize) && (pData->ulWriteCapturedDataPos > ulMaxSize))
|
||||
{
|
||||
pData->ulReadCapturedDataPos -= ulMaxSize;
|
||||
pData->ulWriteCapturedDataPos -= ulMaxSize;
|
||||
}
|
||||
|
||||
// Send buffer back to capture more data
|
||||
waveInAddBuffer(pData->hWaveInHandle,pWaveHdr,sizeof(WAVEHDR));
|
||||
pData->lWaveInBuffersCommitted++;
|
||||
|
||||
ProcessContext(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Signal Wave Thread completed event
|
||||
if (pData->hWaveInThreadEvent)
|
||||
SetEvent(pData->hWaveInThreadEvent);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean WinMMOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
(void)device;
|
||||
(void)deviceName;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void WinMMClosePlayback(ALCdevice *device)
|
||||
{
|
||||
(void)device;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
|
||||
{
|
||||
WAVEFORMATEX wfexCaptureFormat;
|
||||
WinMMData *pData = NULL;
|
||||
ALint lDeviceID = 0;
|
||||
ALint lBufferSize;
|
||||
ALuint i;
|
||||
|
||||
if(!CaptureDeviceList)
|
||||
ProbeDevices();
|
||||
|
||||
// Find the Device ID matching the deviceName if valid
|
||||
if(deviceName)
|
||||
{
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i] &&
|
||||
strcmp(deviceName, CaptureDeviceList[i]) == 0)
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i])
|
||||
{
|
||||
lDeviceID = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(i == NumCaptureDevices)
|
||||
return ALC_FALSE;
|
||||
|
||||
pData = calloc(1, sizeof(*pData));
|
||||
if(!pData)
|
||||
{
|
||||
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
|
||||
wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfexCaptureFormat.nChannels = aluChannelsFromFormat(pDevice->Format);
|
||||
wfexCaptureFormat.wBitsPerSample = aluBytesFromFormat(pDevice->Format) * 8;
|
||||
wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
|
||||
wfexCaptureFormat.nChannels / 8;
|
||||
wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
|
||||
wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
|
||||
wfexCaptureFormat.nBlockAlign;
|
||||
wfexCaptureFormat.cbSize = 0;
|
||||
|
||||
if (waveInOpen(&pData->hWaveInHandle, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION) != MMSYSERR_NOERROR)
|
||||
goto failure;
|
||||
|
||||
pData->hWaveInHdrEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInAllHeadersReturned");
|
||||
if (pData->hWaveInHdrEvent == NULL)
|
||||
goto failure;
|
||||
|
||||
pData->hWaveInThreadEvent = CreateEvent(NULL, AL_TRUE, AL_FALSE, "WaveInThreadDestroyed");
|
||||
if (pData->hWaveInThreadEvent == NULL)
|
||||
goto failure;
|
||||
|
||||
// Allocate circular memory buffer for the captured audio
|
||||
pData->ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates *
|
||||
wfexCaptureFormat.nBlockAlign;
|
||||
|
||||
// Make sure circular buffer is at least 100ms in size (and an exact multiple of
|
||||
// the block alignment
|
||||
if (pData->ulCapturedDataSize < (wfexCaptureFormat.nAvgBytesPerSec / 10))
|
||||
{
|
||||
pData->ulCapturedDataSize = wfexCaptureFormat.nAvgBytesPerSec / 10;
|
||||
pData->ulCapturedDataSize -= (pData->ulCapturedDataSize % wfexCaptureFormat.nBlockAlign);
|
||||
}
|
||||
|
||||
pData->pCapturedSampleData = (ALCchar*)malloc(pData->ulCapturedDataSize);
|
||||
pData->lWaveInBuffersCommitted=0;
|
||||
|
||||
// Create 4 Buffers of 50ms each
|
||||
lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
|
||||
lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
|
||||
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
memset(&pData->WaveInBuffer[i], 0, sizeof(WAVEHDR));
|
||||
pData->WaveInBuffer[i].dwBufferLength = lBufferSize;
|
||||
pData->WaveInBuffer[i].lpData = calloc(1,pData->WaveInBuffer[i].dwBufferLength);
|
||||
pData->WaveInBuffer[i].dwFlags = 0;
|
||||
pData->WaveInBuffer[i].dwLoops = 0;
|
||||
waveInPrepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
|
||||
waveInAddBuffer(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
|
||||
pData->lWaveInBuffersCommitted++;
|
||||
}
|
||||
|
||||
pData->ulReadCapturedDataPos = 0;
|
||||
pData->ulWriteCapturedDataPos = 0;
|
||||
|
||||
pDevice->ExtraData = pData;
|
||||
|
||||
pData->hWaveInThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveInThreadID);
|
||||
if (pData->hWaveInThread == NULL)
|
||||
goto failure;
|
||||
|
||||
pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
|
||||
return ALC_TRUE;
|
||||
|
||||
failure:
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
if(pData->WaveInBuffer[i].lpData)
|
||||
{
|
||||
waveInUnprepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
|
||||
free(pData->WaveInBuffer[i].lpData);
|
||||
}
|
||||
}
|
||||
|
||||
free(pData->pCapturedSampleData);
|
||||
if(pData->hWaveInHandle)
|
||||
waveInClose(pData->hWaveInHandle);
|
||||
if(pData->hWaveInThread)
|
||||
CloseHandle(pData->hWaveInThread);
|
||||
if (pData->hWaveInHdrEvent)
|
||||
CloseHandle(pData->hWaveInHdrEvent);
|
||||
if (pData->hWaveInThreadEvent)
|
||||
CloseHandle(pData->hWaveInThreadEvent);
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
static void WinMMCloseCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
int i;
|
||||
|
||||
// Call waveOutReset to shutdown wave device
|
||||
pData->bWaveInShutdown = AL_TRUE;
|
||||
waveInReset(pData->hWaveInHandle);
|
||||
|
||||
// Wait for signal that all Wave Buffers have returned
|
||||
WaitForSingleObjectEx(pData->hWaveInHdrEvent, 5000, FALSE);
|
||||
|
||||
// Wait for signal that Wave Thread has been destroyed
|
||||
WaitForSingleObjectEx(pData->hWaveInThreadEvent, 5000, FALSE);
|
||||
|
||||
// Release the wave buffers
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
waveInUnprepareHeader(pData->hWaveInHandle, &pData->WaveInBuffer[i], sizeof(WAVEHDR));
|
||||
free(pData->WaveInBuffer[i].lpData);
|
||||
}
|
||||
|
||||
// Free Audio Buffer data
|
||||
free(pData->pCapturedSampleData);
|
||||
pData->pCapturedSampleData = NULL;
|
||||
|
||||
// Close the Wave device
|
||||
waveInClose(pData->hWaveInHandle);
|
||||
pData->hWaveInHandle = 0;
|
||||
|
||||
CloseHandle(pData->hWaveInThread);
|
||||
pData->hWaveInThread = 0;
|
||||
|
||||
if (pData->hWaveInHdrEvent)
|
||||
{
|
||||
CloseHandle(pData->hWaveInHdrEvent);
|
||||
pData->hWaveInHdrEvent = 0;
|
||||
}
|
||||
|
||||
if (pData->hWaveInThreadEvent)
|
||||
{
|
||||
CloseHandle(pData->hWaveInThreadEvent);
|
||||
pData->hWaveInThreadEvent = 0;
|
||||
}
|
||||
|
||||
free(pData);
|
||||
pDevice->ExtraData = NULL;
|
||||
}
|
||||
|
||||
static void WinMMStartCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStart(pData->hWaveInHandle);
|
||||
}
|
||||
|
||||
static void WinMMStopCapture(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
waveInStop(pData->hWaveInHandle);
|
||||
}
|
||||
|
||||
static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
ALuint ulSamples = (unsigned long)lSamples;
|
||||
ALuint ulBytes, ulBytesToCopy;
|
||||
ALuint ulCapturedSamples;
|
||||
ALuint ulReadOffset;
|
||||
ALuint frameSize = aluBytesFromFormat(pDevice->Format) *
|
||||
aluChannelsFromFormat(pDevice->Format);
|
||||
|
||||
// Check that we have the requested numbers of Samples
|
||||
ulCapturedSamples = (pData->ulWriteCapturedDataPos -
|
||||
pData->ulReadCapturedDataPos) /
|
||||
frameSize;
|
||||
if(ulSamples > ulCapturedSamples)
|
||||
{
|
||||
alcSetError(pDevice, ALC_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
ulBytes = ulSamples * frameSize;
|
||||
|
||||
// Get Read Offset
|
||||
ulReadOffset = (pData->ulReadCapturedDataPos % pData->ulCapturedDataSize);
|
||||
|
||||
// Check for wrap-around condition
|
||||
if ((ulReadOffset + ulBytes) > pData->ulCapturedDataSize)
|
||||
{
|
||||
// Copy data from last Read position to end of data
|
||||
ulBytesToCopy = pData->ulCapturedDataSize - ulReadOffset;
|
||||
memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytesToCopy);
|
||||
|
||||
// Copy rest of the data from the start of the captured data
|
||||
memcpy(((char *)pBuffer) + ulBytesToCopy, pData->pCapturedSampleData, ulBytes - ulBytesToCopy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy data from the read position in the captured data
|
||||
memcpy(pBuffer, pData->pCapturedSampleData + ulReadOffset, ulBytes);
|
||||
}
|
||||
|
||||
// Update Read Position
|
||||
pData->ulReadCapturedDataPos += ulBytes;
|
||||
}
|
||||
|
||||
static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
|
||||
{
|
||||
WinMMData *pData = (WinMMData*)pDevice->ExtraData;
|
||||
ALCuint lCapturedBytes = (pData->ulWriteCapturedDataPos - pData->ulReadCapturedDataPos);
|
||||
return lCapturedBytes / (aluBytesFromFormat(pDevice->Format) *
|
||||
aluChannelsFromFormat(pDevice->Format));
|
||||
}
|
||||
|
||||
|
||||
BackendFuncs WinMMFuncs = {
|
||||
WinMMOpenPlayback,
|
||||
WinMMClosePlayback,
|
||||
NULL,
|
||||
NULL,
|
||||
WinMMOpenCapture,
|
||||
WinMMCloseCapture,
|
||||
WinMMStartCapture,
|
||||
WinMMStopCapture,
|
||||
WinMMCaptureSamples,
|
||||
WinMMAvailableSamples
|
||||
};
|
||||
|
||||
void alcWinMMInit(BackendFuncs *FuncList)
|
||||
{
|
||||
*FuncList = WinMMFuncs;
|
||||
}
|
||||
|
||||
void alcWinMMDeinit()
|
||||
{
|
||||
ALuint lLoop;
|
||||
|
||||
for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
|
||||
free(CaptureDeviceList[lLoop]);
|
||||
free(CaptureDeviceList);
|
||||
CaptureDeviceList = NULL;
|
||||
|
||||
NumCaptureDevices = 0;
|
||||
}
|
||||
|
||||
void alcWinMMProbe(int type)
|
||||
{
|
||||
ALuint i;
|
||||
|
||||
if(type != CAPTURE_DEVICE_PROBE)
|
||||
return;
|
||||
|
||||
ProbeDevices();
|
||||
for(i = 0;i < NumCaptureDevices;i++)
|
||||
{
|
||||
if(CaptureDeviceList[i])
|
||||
AppendCaptureDeviceList(CaptureDeviceList[i]);
|
||||
}
|
||||
}
|
||||
+362
-85
@@ -10,13 +10,14 @@ SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
INCLUDE(CheckFunctionExists)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckSharedLibraryExists)
|
||||
INCLUDE(CheckSharedFunctionExists)
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
INCLUDE(CheckTypeSize)
|
||||
INCLUDE(FindPkgConfig)
|
||||
|
||||
|
||||
PROJECT(OpenAL C)
|
||||
@@ -28,40 +29,65 @@ SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
|
||||
OPTION(ALSA "Check for ALSA backend" ON)
|
||||
OPTION(OSS "Check for OSS backend" ON)
|
||||
OPTION(SOLARIS "Check for Solaris backend" ON)
|
||||
OPTION(SNDIO "Check for SndIO backend" ON)
|
||||
OPTION(MMDEVAPI "Check for MMDevApi" ON)
|
||||
OPTION(DSOUND "Check for DirectSound backend" ON)
|
||||
OPTION(WINMM "Check for Windows Multimedia backend" ON)
|
||||
OPTION(PORTAUDIO "Check for PortAudio backend" ON)
|
||||
OPTION(PULSEAUDIO "Check for PulseAudio backend" ON)
|
||||
OPTION(COREAUDIO "Check for CoreAudio backend" ON)
|
||||
OPTION(OPENSL "Check for OpenSL backend" ON)
|
||||
OPTION(WAVE "Enable Wave Writer backend" ON)
|
||||
|
||||
OPTION(REQUIRE_ALSA "Require ALSA backend" OFF)
|
||||
OPTION(REQUIRE_OSS "Require OSS backend" OFF)
|
||||
OPTION(REQUIRE_SOLARIS "Require Solaris backend" OFF)
|
||||
OPTION(REQUIRE_SNDIO "Require SndIO backend" OFF)
|
||||
OPTION(REQUIRE_MMDEVAPI "Require MMDevApi" OFF)
|
||||
OPTION(REQUIRE_DSOUND "Require DirectSound backend" OFF)
|
||||
OPTION(REQUIRE_WINMM "Require Windows Multimedia backend" OFF)
|
||||
OPTION(REQUIRE_PORTAUDIO "Require PortAudio backend" OFF)
|
||||
OPTION(REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF)
|
||||
OPTION(REQUIRE_COREAUDIO "Require CoreAudio backend" OFF)
|
||||
OPTION(REQUIRE_OPENSL "Require OpenSL backend" OFF)
|
||||
|
||||
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
|
||||
|
||||
OPTION(WERROR "Treat compile warnings as errors" OFF)
|
||||
|
||||
OPTION(EXAMPLES "Build example programs" ON)
|
||||
OPTION(UTILS "Build and install utility programs" ON)
|
||||
|
||||
OPTION(EXAMPLES "Build and install example programs" ON)
|
||||
|
||||
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
SET(LIBNAME OpenAL32)
|
||||
ADD_DEFINITIONS("-D_WIN32")
|
||||
ADD_DEFINITIONS("-D_WIN32 -D_WIN32_WINNT=0x0501")
|
||||
ELSE()
|
||||
SET(LIBNAME openal)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT LIBTYPE)
|
||||
SET(LIBTYPE SHARED)
|
||||
ENDIF()
|
||||
|
||||
SET(LIB_MAJOR_VERSION "1")
|
||||
SET(LIB_MINOR_VERSION "12")
|
||||
SET(LIB_BUILD_VERSION "854")
|
||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
|
||||
IF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
SET(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
|
||||
ENDIF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
SET(LIB_MINOR_VERSION "14")
|
||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}")
|
||||
|
||||
SET(EXPORT_DECL "")
|
||||
|
||||
|
||||
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
|
||||
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
|
||||
CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
|
||||
CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# Add definitions, compiler switches, etc.
|
||||
@@ -99,8 +125,18 @@ IF(MSVC)
|
||||
LINK_DIRECTORIES("${DXSDK_DIR}/Lib")
|
||||
ENDIF()
|
||||
|
||||
OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
|
||||
IF(FORCE_STATIC_VCRT)
|
||||
FOREACH(flag_var
|
||||
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
|
||||
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
|
||||
IF(${flag_var} MATCHES "/MD")
|
||||
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
ENDIF()
|
||||
ENDFOREACH(flag_var)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-Wall)
|
||||
ADD_DEFINITIONS(-Winline -Wall)
|
||||
CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
|
||||
IF(HAVE_W_EXTRA)
|
||||
ADD_DEFINITIONS(-Wextra)
|
||||
@@ -110,52 +146,111 @@ ELSE()
|
||||
ADD_DEFINITIONS(-Werror)
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -funroll-loops -D_DEBUG" CACHE STRING
|
||||
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING
|
||||
"Flags used by the compiler during Release with Debug Info builds."
|
||||
FORCE)
|
||||
SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING
|
||||
"Flags used by the compiler during release minsize builds."
|
||||
FORCE)
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O2 -funroll-loops -fomit-frame-pointer -DNDEBUG" CACHE STRING
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-O2 -fomit-frame-pointer -DNDEBUG" CACHE STRING
|
||||
"Flags used by the compiler during release builds"
|
||||
FORCE)
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING
|
||||
"Flags used by the compiler during debug builds."
|
||||
FORCE)
|
||||
|
||||
# Set visibility options if available
|
||||
IF(NOT WIN32)
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
|
||||
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
|
||||
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
|
||||
ENDIF()
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_SWITCH)
|
||||
IF(HAVE_VISIBILITY_SWITCH)
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
|
||||
int main() {return 0;}" HAVE_GCC_VISIBILITY)
|
||||
IF(HAVE_GCC_VISIBILITY)
|
||||
ADD_DEFINITIONS(-fvisibility=hidden -DHAVE_GCC_VISIBILITY)
|
||||
# Set visibility/export options if available
|
||||
IF(WIN32)
|
||||
SET(EXPORT_DECL "__declspec(dllexport)")
|
||||
|
||||
OPTION(WINE "Enable use of Wine headers when compiling" OFF)
|
||||
IF(WINE)
|
||||
FIND_PATH(WINE_INCLUDE_DIR library.h
|
||||
PATHS
|
||||
/usr/include/wine
|
||||
/usr/local/include/wine
|
||||
CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
IF(WINE_INCLUDE_DIR)
|
||||
MESSAGE(STATUS "Found Wine header files - ${WINE_INCLUDE_DIR}" )
|
||||
INCLUDE_DIRECTORIES("${WINE_INCLUDE_DIR}/windows")
|
||||
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${WINE_INCLUDE_DIR}/windows")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Could not find Wine header files" )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
# Yes GCC, really don't accept visibility modes you don't support
|
||||
SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -Wattributes -Werror")
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"protected\")));
|
||||
int main() {return 0;}" HAVE_GCC_PROTECTED_VISIBILITY)
|
||||
IF(HAVE_GCC_PROTECTED_VISIBILITY)
|
||||
SET(EXPORT_DECL "__attribute__((visibility(\"protected\")))")
|
||||
ELSE()
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
|
||||
int main() {return 0;}" HAVE_GCC_DEFAULT_VISIBILITY)
|
||||
IF(HAVE_GCC_DEFAULT_VISIBILITY)
|
||||
SET(EXPORT_DECL "__attribute__((visibility(\"default\")))")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_GCC_PROTECTED_VISIBILITY OR HAVE_GCC_DEFAULT_VISIBILITY)
|
||||
CHECK_C_COMPILER_FLAG(-fvisibility=internal HAVE_VISIBILITY_INTERNAL_SWITCH)
|
||||
IF(HAVE_VISIBILITY_INTERNAL_SWITCH)
|
||||
ADD_DEFINITIONS(-fvisibility=internal)
|
||||
ELSE()
|
||||
CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH)
|
||||
IF(HAVE_VISIBILITY_HIDDEN_SWITCH)
|
||||
ADD_DEFINITIONS(-fvisibility=hidden)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}")
|
||||
ENDIF()
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2)));
|
||||
int main() {return 0;}" HAVE_GCC_FORMAT)
|
||||
|
||||
CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H)
|
||||
CHECK_INCLUDE_FILE(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)
|
||||
|
||||
CHECK_LIBRARY_EXISTS(m powf "" HAVE_POWF)
|
||||
CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
|
||||
CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF)
|
||||
CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF)
|
||||
CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF)
|
||||
IF(HAVE_FENV_H)
|
||||
CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND)
|
||||
ENDIF()
|
||||
IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND)
|
||||
# Some systems need libm for some of the following math functions to work
|
||||
CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIBM)
|
||||
IF(HAVE_LIBM)
|
||||
SET(EXTRA_LIBS m ${EXTRA_LIBS})
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m)
|
||||
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)
|
||||
|
||||
IF(HAVE_FENV_H)
|
||||
CHECK_SYMBOL_EXISTS(fesetround fenv.h HAVE_FESETROUND)
|
||||
ENDIF()
|
||||
|
||||
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
|
||||
CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP)
|
||||
|
||||
@@ -200,6 +295,20 @@ IF(NOT HAVE_VSNPRINTF)
|
||||
ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf)
|
||||
ENDIF()
|
||||
|
||||
CHECK_SYMBOL_EXISTS(isfinite math.h HAVE_ISFINITE)
|
||||
IF(NOT HAVE_ISFINITE)
|
||||
CHECK_FUNCTION_EXISTS(finite HAVE_FINITE)
|
||||
IF(NOT HAVE_FINITE)
|
||||
CHECK_FUNCTION_EXISTS(_finite HAVE__FINITE)
|
||||
IF(NOT HAVE__FINITE)
|
||||
MESSAGE(FATAL_ERROR "No isfinite function found, please report!")
|
||||
ENDIF()
|
||||
ADD_DEFINITIONS(-Disfinite=_finite)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-Disfinite=finite)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN)
|
||||
IF(NOT HAVE_ISNAN)
|
||||
CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN)
|
||||
@@ -223,7 +332,7 @@ IF(DLOPEN)
|
||||
ENDIF()
|
||||
|
||||
# Check if we have Windows headers
|
||||
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500)
|
||||
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0501)
|
||||
IF(NOT HAVE_WINDOWS_H)
|
||||
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
|
||||
IF(NOT HAVE_GETTIMEOFDAY)
|
||||
@@ -269,7 +378,7 @@ ENDIF()
|
||||
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
|
||||
IF(NOT HAVE_STDINT_H)
|
||||
IF(HAVE_WINDOWS_H)
|
||||
CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500
|
||||
CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0501
|
||||
\#include <windows.h>
|
||||
__int64 foo;
|
||||
int main() {return 0;}" HAVE___INT64)
|
||||
@@ -283,10 +392,16 @@ IF(NOT HAVE_STDINT_H)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Windows needs winmm for timeGetTime, even if the backend is disabled
|
||||
CHECK_SHARED_FUNCTION_EXISTS(timeGetTime "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM)
|
||||
IF(HAVE_LIBWINMM)
|
||||
SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
|
||||
SET(PKG_CONFIG_LIBS ${PKG_CONFIG_LIBS} -lwinmm)
|
||||
ENDIF()
|
||||
|
||||
|
||||
SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
|
||||
OpenAL32/alBuffer.c
|
||||
OpenAL32/alDatabuffer.c
|
||||
OpenAL32/alEffect.c
|
||||
OpenAL32/alError.c
|
||||
OpenAL32/alExtension.c
|
||||
@@ -299,24 +414,44 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
|
||||
SET(ALC_OBJS Alc/ALc.c
|
||||
Alc/ALu.c
|
||||
Alc/alcConfig.c
|
||||
Alc/alcDedicated.c
|
||||
Alc/alcEcho.c
|
||||
Alc/alcModulator.c
|
||||
Alc/alcReverb.c
|
||||
Alc/alcRing.c
|
||||
Alc/alcThread.c
|
||||
Alc/bs2b.c
|
||||
Alc/wave.c
|
||||
Alc/helpers.c
|
||||
Alc/hrtf.c
|
||||
Alc/mixer.c
|
||||
Alc/panning.c
|
||||
# Default backends, always available
|
||||
Alc/backends/loopback.c
|
||||
Alc/backends/null.c
|
||||
)
|
||||
|
||||
SET(BACKENDS "")
|
||||
SET(HAVE_ALSA 0)
|
||||
SET(HAVE_OSS 0)
|
||||
SET(HAVE_SOLARIS 0)
|
||||
SET(HAVE_SNDIO 0)
|
||||
SET(HAVE_DSOUND 0)
|
||||
SET(HAVE_MMDEVAPI 0)
|
||||
SET(HAVE_WINMM 0)
|
||||
SET(HAVE_PORTAUDIO 0)
|
||||
SET(HAVE_PULSEAUDIO 0)
|
||||
SET(HAVE_COREAUDIO 0)
|
||||
SET(HAVE_OPENSL 0)
|
||||
SET(HAVE_WAVE 0)
|
||||
|
||||
# Check ALSA backend
|
||||
IF(ALSA)
|
||||
CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H)
|
||||
IF(HAVE_ALSA_ASOUNDLIB_H)
|
||||
CHECK_SHARED_LIBRARY_EXISTS(asound snd_pcm_open 4 "" HAVE_LIBASOUND)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(snd_pcm_open "alsa/asoundlib.h" asound "" HAVE_LIBASOUND)
|
||||
IF(HAVE_LIBASOUND OR HAVE_DLFCN_H OR WIN32)
|
||||
SET(HAVE_ALSA 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/alsa.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/alsa.c)
|
||||
IF(HAVE_DLFCN_H OR WIN32)
|
||||
SET(BACKENDS "${BACKENDS} ALSA,")
|
||||
ELSE()
|
||||
@@ -326,35 +461,81 @@ IF(ALSA)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_ALSA AND NOT HAVE_ALSA)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required ALSA backend")
|
||||
ENDIF()
|
||||
|
||||
# Check OSS backend
|
||||
IF(OSS)
|
||||
CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
|
||||
IF(HAVE_SYS_SOUNDCARD_H)
|
||||
SET(HAVE_OSS 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/oss.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/oss.c)
|
||||
SET(BACKENDS "${BACKENDS} OSS,")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_OSS AND NOT HAVE_OSS)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required OSS backend")
|
||||
ENDIF()
|
||||
|
||||
# Check Solaris backend
|
||||
IF(SOLARIS)
|
||||
CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H)
|
||||
IF(HAVE_SYS_AUDIOIO_H)
|
||||
SET(HAVE_SOLARIS 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/solaris.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/solaris.c)
|
||||
SET(BACKENDS "${BACKENDS} Solaris,")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_SOLARIS AND NOT HAVE_SOLARIS)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required Solaris backend")
|
||||
ENDIF()
|
||||
|
||||
# Check SndIO backend
|
||||
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)
|
||||
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()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_SNDIO AND NOT HAVE_SNDIO)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required SndIO backend")
|
||||
ENDIF()
|
||||
|
||||
# Check for MMDevApi backend
|
||||
IF(HAVE_WINDOWS_H)
|
||||
IF(MMDEVAPI)
|
||||
CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H)
|
||||
IF(HAVE_MMDEVICEAPI_H)
|
||||
SET(HAVE_MMDEVAPI 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c)
|
||||
|
||||
SET(BACKENDS "${BACKENDS} MMDevApi,")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend")
|
||||
ENDIF()
|
||||
|
||||
# Check DSound/MMSystem backend
|
||||
IF(DSOUND)
|
||||
CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
|
||||
IF(HAVE_DSOUND_H)
|
||||
CHECK_SHARED_LIBRARY_EXISTS(dsound DirectSoundCreate 3 "" HAVE_LIBDSOUND)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(DirectSoundCreate "dsound.h" dsound "" HAVE_LIBDSOUND)
|
||||
IF(HAVE_LIBDSOUND OR HAVE_DLFCN_H OR WIN32)
|
||||
SET(HAVE_DSOUND 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c)
|
||||
|
||||
IF(HAVE_DLFCN_H OR WIN32)
|
||||
SET(BACKENDS "${BACKENDS} DirectSound,")
|
||||
@@ -365,30 +546,32 @@ IF(DSOUND)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_DSOUND AND NOT HAVE_DSOUND)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_WINDOWS_H)
|
||||
IF(WINMM)
|
||||
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
|
||||
IF(HAVE_MMSYSTEM_H)
|
||||
CHECK_SHARED_LIBRARY_EXISTS(winmm waveInOpen 6 "" HAVE_LIBWINMM)
|
||||
IF(HAVE_LIBWINMM)
|
||||
SET(HAVE_WINMM 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
|
||||
SET(BACKENDS "${BACKENDS} WinMM,")
|
||||
|
||||
SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0501)
|
||||
IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM)
|
||||
SET(HAVE_WINMM 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c)
|
||||
SET(BACKENDS "${BACKENDS} WinMM,")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_WINMM AND NOT HAVE_WINMM)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required WinMM backend")
|
||||
ENDIF()
|
||||
|
||||
# Check PortAudio backend
|
||||
IF(PORTAUDIO)
|
||||
CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H)
|
||||
IF(HAVE_PORTAUDIO_H)
|
||||
CHECK_SHARED_LIBRARY_EXISTS(portaudio Pa_Initialize 0 "" HAVE_LIBPORTAUDIO)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(Pa_Initialize "portaudio.h" portaudio "" HAVE_LIBPORTAUDIO)
|
||||
IF(HAVE_LIBPORTAUDIO OR HAVE_DLFCN_H OR WIN32)
|
||||
SET(HAVE_PORTAUDIO 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/portaudio.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/portaudio.c)
|
||||
IF(HAVE_DLFCN_H OR WIN32)
|
||||
SET(BACKENDS "${BACKENDS} PortAudio,")
|
||||
ELSE()
|
||||
@@ -398,15 +581,18 @@ IF(PORTAUDIO)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required PortAudio backend")
|
||||
ENDIF()
|
||||
|
||||
# Check PortAudio backend
|
||||
# Check PulseAudio backend
|
||||
IF(PULSEAUDIO)
|
||||
CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H)
|
||||
IF(HAVE_PULSE_PULSEAUDIO_H)
|
||||
CHECK_SHARED_LIBRARY_EXISTS(pulse pa_context_new 2 "" HAVE_LIBPULSE)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(pa_context_new "pulse/pulseaudio.h" pulse "" HAVE_LIBPULSE)
|
||||
IF(HAVE_LIBPULSE OR HAVE_DLFCN_H OR WIN32)
|
||||
SET(HAVE_PULSEAUDIO 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/pulseaudio.c)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c)
|
||||
IF(HAVE_DLFCN_H OR WIN32)
|
||||
SET(BACKENDS "${BACKENDS} PulseAudio,")
|
||||
ELSE()
|
||||
@@ -416,14 +602,79 @@ IF(PULSEAUDIO)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend")
|
||||
ENDIF()
|
||||
|
||||
# Check CoreAudio backend
|
||||
IF(COREAUDIO)
|
||||
CHECK_INCLUDE_FILE(/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h HAVE_COREAUDIO_FRAMEWORK)
|
||||
IF(HAVE_COREAUDIO_FRAMEWORK)
|
||||
SET(HAVE_COREAUDIO 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/coreaudio.c)
|
||||
SET(BACKENDS "${BACKENDS} CoreAudio,")
|
||||
SET(EXTRA_LIBS /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS})
|
||||
SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS})
|
||||
SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS})
|
||||
|
||||
# Some versions of OSX may need the AudioToolbox framework. Add it if
|
||||
# it's found.
|
||||
FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY
|
||||
NAMES AudioToolbox
|
||||
PATHS ~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/System/Library/Frameworks
|
||||
)
|
||||
IF(AUDIOTOOLBOX_LIBRARY)
|
||||
SET(EXTRA_LIBS ${AUDIOTOOLBOX_LIBRARY} ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required CoreAudio backend")
|
||||
ENDIF()
|
||||
|
||||
# Check for OpenSL (Android) backend
|
||||
IF(OPENSL)
|
||||
CHECK_INCLUDE_FILES("SLES/OpenSLES.h;SLES/OpenSLES_Android.h" HAVE_SLES_OPENSLES_ANDROID_H)
|
||||
IF(HAVE_SLES_OPENSLES_ANDROID_H)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(slCreateEngine "SLES/OpenSLES.h" OpenSLES "" HAVE_LIBOPENSLES)
|
||||
IF(HAVE_LIBOPENSLES)
|
||||
SET(HAVE_OPENSL 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/opensl.c)
|
||||
SET(BACKENDS "${BACKENDS} OpenSL,")
|
||||
SET(EXTRA_LIBS OpenSLES ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(REQUIRE_OPENSL AND NOT HAVE_OPENSL)
|
||||
MESSAGE(FATAL_ERROR "Failed to enabled required OpenSL backend")
|
||||
ENDIF()
|
||||
|
||||
# Optionally enable the Wave Writer backend
|
||||
IF(WAVE)
|
||||
SET(HAVE_WAVE 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wave.c)
|
||||
SET(BACKENDS "${BACKENDS} WaveFile,")
|
||||
ENDIF()
|
||||
|
||||
# This is always available
|
||||
SET(BACKENDS "${BACKENDS} WaveFile")
|
||||
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)
|
||||
ENDIF()
|
||||
|
||||
IF(LIBTYPE STREQUAL "STATIC")
|
||||
ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC)
|
||||
SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS})
|
||||
ENDIF()
|
||||
|
||||
# Needed for openal.pc.in
|
||||
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(exec_prefix "\${prefix}")
|
||||
SET(libdir "\${exec_prefix}/${LIB_INSTALL_DIR}")
|
||||
SET(libdir "\${exec_prefix}/lib${LIB_SUFFIX}")
|
||||
SET(bindir "\${exec_prefix}/bin")
|
||||
SET(includedir "\${prefix}/include")
|
||||
SET(PACKAGE_VERSION "${LIB_VERSION}")
|
||||
@@ -438,15 +689,12 @@ CONFIGURE_FILE(
|
||||
@ONLY)
|
||||
|
||||
# Build a library
|
||||
IF(NOT LIBTYPE)
|
||||
SET(LIBTYPE SHARED)
|
||||
ENDIF()
|
||||
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}
|
||||
VERSION ${LIB_VERSION}.0
|
||||
SOVERSION ${LIB_MAJOR_VERSION})
|
||||
IF(WIN32)
|
||||
IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
|
||||
ENDIF()
|
||||
|
||||
@@ -455,35 +703,20 @@ TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
|
||||
# Add an install target here
|
||||
INSTALL(TARGETS ${LIBNAME}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
)
|
||||
INSTALL(FILES include/AL/al.h
|
||||
include/AL/alc.h
|
||||
include/AL/alext.h
|
||||
include/AL/efx.h
|
||||
include/AL/efx-creative.h
|
||||
include/AL/efx-presets.h
|
||||
DESTINATION include/AL
|
||||
)
|
||||
INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
|
||||
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
|
||||
DESTINATION "lib${LIB_SUFFIX}/pkgconfig")
|
||||
|
||||
# Install alsoft.conf configuration file
|
||||
IF(ALSOFT_CONFIG)
|
||||
INSTALL(FILES alsoftrc.sample
|
||||
DESTINATION /etc/openal
|
||||
RENAME alsoft.conf
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(EXAMPLES)
|
||||
ADD_EXECUTABLE(openal-info examples/openal-info.c)
|
||||
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
|
||||
INSTALL(TARGETS openal-info
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
MESSAGE(STATUS "")
|
||||
MESSAGE(STATUS "Building OpenAL with support for the following backends:")
|
||||
@@ -497,3 +730,47 @@ IF(WIN32)
|
||||
MESSAGE(STATUS "")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Install alsoft.conf configuration file
|
||||
IF(ALSOFT_CONFIG)
|
||||
INSTALL(FILES alsoftrc.sample
|
||||
DESTINATION /etc/openal
|
||||
RENAME alsoft.conf
|
||||
)
|
||||
MESSAGE(STATUS "Installing sample alsoft.conf")
|
||||
MESSAGE(STATUS "")
|
||||
ENDIF()
|
||||
|
||||
IF(UTILS)
|
||||
ADD_EXECUTABLE(openal-info utils/openal-info.c)
|
||||
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
|
||||
|
||||
ADD_EXECUTABLE(makehrtf utils/makehrtf.c)
|
||||
IF(HAVE_LIBM)
|
||||
TARGET_LINK_LIBRARIES(makehrtf m)
|
||||
ENDIF()
|
||||
|
||||
INSTALL(TARGETS openal-info makehrtf
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
)
|
||||
MESSAGE(STATUS "Building utility programs")
|
||||
MESSAGE(STATUS "")
|
||||
ENDIF()
|
||||
|
||||
IF(EXAMPLES)
|
||||
IF(FFMPEG_FOUND)
|
||||
ADD_EXECUTABLE(alstream examples/alhelpers.c examples/alffmpeg.c examples/alstream.c)
|
||||
TARGET_LINK_LIBRARIES(alstream ${FFMPEG_LIBRARIES} ${LIBNAME})
|
||||
SET_TARGET_PROPERTIES(alstream PROPERTIES COMPILE_FLAGS "${FFMPEG_CFLAGS}")
|
||||
INSTALL(TARGETS alstream
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}"
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
)
|
||||
|
||||
MESSAGE(STATUS "Building ffmpeg example programs")
|
||||
MESSAGE(STATUS "")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
@@ -15,14 +15,18 @@ typedef struct ALeffectslot
|
||||
{
|
||||
ALeffect effect;
|
||||
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
volatile ALfloat Gain;
|
||||
volatile ALboolean AuxSendAuto;
|
||||
|
||||
volatile ALenum NeedsUpdate;
|
||||
ALeffectState *EffectState;
|
||||
|
||||
ALfloat WetBuffer[BUFFERSIZE];
|
||||
|
||||
ALuint refcount;
|
||||
ALfloat ClickRemoval[1];
|
||||
ALfloat PendingClicks[1];
|
||||
|
||||
RefCount ref;
|
||||
|
||||
// Index to itself
|
||||
ALuint effectslot;
|
||||
@@ -31,26 +35,28 @@ typedef struct ALeffectslot
|
||||
} 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, ALCcontext *Context, const ALeffect *Effect);
|
||||
ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
|
||||
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 *EAXVerbCreate(void);
|
||||
ALeffectState *VerbCreate(void);
|
||||
ALeffectState *ReverbCreate(void);
|
||||
ALeffectState *EchoCreate(void);
|
||||
ALeffectState *ModulatorCreate(void);
|
||||
ALeffectState *DedicatedCreate(void);
|
||||
|
||||
#define ALEffect_Destroy(a) ((a)->Destroy((a)))
|
||||
#define ALEffect_DeviceUpdate(a,b) ((a)->DeviceUpdate((a),(b)))
|
||||
#define ALEffect_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
||||
#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e)))
|
||||
#define ALeffectState_Destroy(a) ((a)->Destroy((a)))
|
||||
#define ALeffectState_DeviceUpdate(a,b) ((a)->DeviceUpdate((a),(b)))
|
||||
#define ALeffectState_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
||||
#define ALeffectState_Process(a,b,c,d) ((a)->Process((a),(b),(c),(d)))
|
||||
|
||||
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -7,23 +7,89 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BUFFER_PADDING 2
|
||||
/* User formats */
|
||||
enum UserFmtType {
|
||||
UserFmtByte = AL_BYTE_SOFT,
|
||||
UserFmtUByte = AL_UNSIGNED_BYTE_SOFT,
|
||||
UserFmtShort = AL_SHORT_SOFT,
|
||||
UserFmtUShort = AL_UNSIGNED_SHORT_SOFT,
|
||||
UserFmtInt = AL_INT_SOFT,
|
||||
UserFmtUInt = AL_UNSIGNED_INT_SOFT,
|
||||
UserFmtFloat = AL_FLOAT_SOFT,
|
||||
UserFmtDouble = AL_DOUBLE_SOFT,
|
||||
UserFmtByte3 = AL_BYTE3_SOFT,
|
||||
UserFmtUByte3 = AL_UNSIGNED_BYTE3_SOFT,
|
||||
UserFmtMulaw,
|
||||
UserFmtAlaw,
|
||||
UserFmtIMA4,
|
||||
};
|
||||
enum UserFmtChannels {
|
||||
UserFmtMono = AL_MONO_SOFT,
|
||||
UserFmtStereo = AL_STEREO_SOFT,
|
||||
UserFmtRear = AL_REAR_SOFT,
|
||||
UserFmtQuad = AL_QUAD_SOFT,
|
||||
UserFmtX51 = AL_5POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX61 = AL_6POINT1_SOFT, /* (WFX order) */
|
||||
UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */
|
||||
};
|
||||
|
||||
ALuint BytesFromUserFmt(enum UserFmtType type);
|
||||
ALuint ChannelsFromUserFmt(enum UserFmtChannels chans);
|
||||
static __inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans,
|
||||
enum UserFmtType type)
|
||||
{
|
||||
return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type);
|
||||
}
|
||||
|
||||
|
||||
/* Storable formats */
|
||||
enum FmtType {
|
||||
FmtByte = UserFmtByte,
|
||||
FmtShort = UserFmtShort,
|
||||
FmtFloat = UserFmtFloat,
|
||||
};
|
||||
enum FmtChannels {
|
||||
FmtMono = UserFmtMono,
|
||||
FmtStereo = UserFmtStereo,
|
||||
FmtRear = UserFmtRear,
|
||||
FmtQuad = UserFmtQuad,
|
||||
FmtX51 = UserFmtX51,
|
||||
FmtX61 = UserFmtX61,
|
||||
FmtX71 = UserFmtX71,
|
||||
};
|
||||
|
||||
ALuint BytesFromFmt(enum FmtType type);
|
||||
ALuint ChannelsFromFmt(enum FmtChannels chans);
|
||||
static __inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
|
||||
{
|
||||
return ChannelsFromFmt(chans) * BytesFromFmt(type);
|
||||
}
|
||||
|
||||
|
||||
typedef struct ALbuffer
|
||||
{
|
||||
ALfloat *data;
|
||||
ALsizei size;
|
||||
ALvoid *data;
|
||||
|
||||
ALenum format;
|
||||
ALenum eOriginalFormat;
|
||||
ALsizei frequency;
|
||||
ALsizei Frequency;
|
||||
ALenum Format;
|
||||
ALsizei SampleLen;
|
||||
|
||||
ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0)
|
||||
enum FmtChannels FmtChannels;
|
||||
enum FmtType FmtType;
|
||||
|
||||
enum UserFmtChannels OriginalChannels;
|
||||
enum UserFmtType OriginalType;
|
||||
ALsizei OriginalSize;
|
||||
|
||||
ALsizei LoopStart;
|
||||
ALsizei LoopEnd;
|
||||
|
||||
RefCount ref; // Number of sources using this buffer (deletion can only occur when this is 0)
|
||||
|
||||
RWLock lock;
|
||||
|
||||
// Index to itself
|
||||
ALuint buffer;
|
||||
|
||||
struct ALbuffer *next;
|
||||
} ALbuffer;
|
||||
|
||||
ALvoid ReleaseALBuffers(ALCdevice *device);
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#ifndef _AL_DATABUFFER_H_
|
||||
#define _AL_DATABUFFER_H_
|
||||
|
||||
#include "AL/al.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UNMAPPED 0
|
||||
#define MAPPED 1
|
||||
|
||||
typedef struct ALdatabuffer
|
||||
{
|
||||
ALubyte *data;
|
||||
ALintptrEXT size;
|
||||
|
||||
ALenum state;
|
||||
ALenum usage;
|
||||
|
||||
/* Index to self */
|
||||
ALuint databuffer;
|
||||
|
||||
struct ALdatabuffer *next;
|
||||
} ALdatabuffer;
|
||||
|
||||
ALvoid ReleaseALDatabuffers(ALCdevice *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,3 @@
|
||||
// NOTE: The effect structure is getting too large, it may be a good idea to
|
||||
// start using a union or another form of unified storage.
|
||||
#ifndef _AL_EFFECT_H_
|
||||
#define _AL_EFFECT_H_
|
||||
|
||||
@@ -13,11 +11,16 @@ enum {
|
||||
EAXREVERB = 0,
|
||||
REVERB,
|
||||
ECHO,
|
||||
MODULATOR,
|
||||
DEDICATED,
|
||||
|
||||
MAX_EFFECTS
|
||||
};
|
||||
extern ALboolean DisabledEffects[MAX_EFFECTS];
|
||||
|
||||
extern ALfloat ReverbBoost;
|
||||
extern ALboolean EmulateEAXReverb;
|
||||
|
||||
typedef struct ALeffect
|
||||
{
|
||||
// Effect type (AL_EFFECT_NULL, ...)
|
||||
@@ -62,15 +65,48 @@ typedef struct ALeffect
|
||||
ALfloat Spread;
|
||||
} Echo;
|
||||
|
||||
struct {
|
||||
ALfloat Frequency;
|
||||
ALfloat HighPassCutoff;
|
||||
ALint Waveform;
|
||||
} Modulator;
|
||||
|
||||
struct {
|
||||
ALfloat Gain;
|
||||
} Dedicated;
|
||||
|
||||
void (*SetParami)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALint val);
|
||||
void (*SetParamiv)(struct ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals);
|
||||
void (*SetParamf)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val);
|
||||
void (*SetParamfv)(struct ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals);
|
||||
|
||||
void (*GetParami)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALint *val);
|
||||
void (*GetParamiv)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals);
|
||||
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;
|
||||
|
||||
struct ALeffect *next;
|
||||
} ALeffect;
|
||||
|
||||
#define ALeffect_SetParami(x, c, p, v) ((x)->SetParami((x),(c),(p),(v)))
|
||||
#define ALeffect_SetParamiv(x, c, p, v) ((x)->SetParamiv((x),(c),(p),(v)))
|
||||
#define ALeffect_SetParamf(x, c, p, v) ((x)->SetParamf((x),(c),(p),(v)))
|
||||
#define ALeffect_SetParamfv(x, c, p, v) ((x)->SetParamfv((x),(c),(p),(v)))
|
||||
|
||||
#define ALeffect_GetParami(x, c, p, v) ((x)->GetParami((x),(c),(p),(v)))
|
||||
#define ALeffect_GetParamiv(x, c, p, v) ((x)->GetParamiv((x),(c),(p),(v)))
|
||||
#define ALeffect_GetParamf(x, c, p, v) ((x)->GetParamf((x),(c),(p),(v)))
|
||||
#define ALeffect_GetParamfv(x, c, p, v) ((x)->GetParamfv((x),(c),(p),(v)))
|
||||
|
||||
static __inline ALboolean IsReverbEffect(ALenum type)
|
||||
{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; }
|
||||
|
||||
ALenum InitEffect(ALeffect *effect);
|
||||
ALvoid ReleaseALEffects(ALCdevice *device);
|
||||
|
||||
ALvoid LoadReverbPreset(const char *name, ALeffect *effect);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern ALboolean TrapALError;
|
||||
|
||||
ALvoid alSetError(ALCcontext *Context, ALenum errorCode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+44
-37
@@ -17,27 +17,9 @@ typedef struct {
|
||||
#endif
|
||||
} FILTER;
|
||||
|
||||
static __inline ALfloat lpFilter4P(FILTER *iir, ALuint offset, ALfloat input)
|
||||
{
|
||||
ALfloat *history = &iir->history[offset];
|
||||
ALfloat a = iir->coeff;
|
||||
ALfloat output = input;
|
||||
|
||||
output = output + (history[0]-output)*a;
|
||||
history[0] = output;
|
||||
output = output + (history[1]-output)*a;
|
||||
history[1] = output;
|
||||
output = output + (history[2]-output)*a;
|
||||
history[2] = output;
|
||||
output = output + (history[3]-output)*a;
|
||||
history[3] = output;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
|
||||
{
|
||||
ALfloat *history = &iir->history[offset];
|
||||
ALfloat *history = &iir->history[offset*2];
|
||||
ALfloat a = iir->coeff;
|
||||
ALfloat output = input;
|
||||
|
||||
@@ -48,7 +30,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];
|
||||
@@ -61,38 +42,64 @@ static __inline ALfloat lpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
|
||||
return output;
|
||||
}
|
||||
|
||||
static __inline ALfloat lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat input)
|
||||
{
|
||||
const ALfloat *history = &iir->history[offset*2];
|
||||
ALfloat a = iir->coeff;
|
||||
ALfloat output = input;
|
||||
|
||||
output = output + (history[0]-output)*a;
|
||||
output = output + (history[1]-output)*a;
|
||||
|
||||
return output;
|
||||
}
|
||||
static __inline ALfloat lpFilter1PC(FILTER *iir, ALuint offset, ALfloat input)
|
||||
{
|
||||
const ALfloat *history = &iir->history[offset];
|
||||
ALfloat a = iir->coeff;
|
||||
ALfloat output = input;
|
||||
|
||||
output = output + (history[0]-output)*a;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/* Calculates the low-pass filter coefficient given the pre-scaled gain and
|
||||
* cos(w) value. Note that g should be pre-scaled (sqr(gain) for one-pole,
|
||||
* sqrt(gain) for four-pole, etc) */
|
||||
static __inline ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
|
||||
{
|
||||
ALfloat a = 0.0f;
|
||||
|
||||
/* Be careful with gains < 0.01, as that causes the coefficient
|
||||
* head towards 1, which will flatten the signal */
|
||||
g = __max(g, 0.01f);
|
||||
if(g < 0.9999f) /* 1-epsilon */
|
||||
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
|
||||
(1 - g);
|
||||
|
||||
return a;
|
||||
}
|
||||
ALfloat lpCoeffCalc(ALfloat g, ALfloat cw);
|
||||
|
||||
|
||||
typedef struct ALfilter
|
||||
{
|
||||
typedef struct ALfilter {
|
||||
// Filter type (AL_FILTER_NULL, ...)
|
||||
ALenum type;
|
||||
|
||||
ALfloat Gain;
|
||||
ALfloat GainHF;
|
||||
|
||||
void (*SetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val);
|
||||
void (*SetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals);
|
||||
void (*SetParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val);
|
||||
void (*SetParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals);
|
||||
|
||||
void (*GetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *val);
|
||||
void (*GetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals);
|
||||
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;
|
||||
|
||||
struct ALfilter *next;
|
||||
} ALfilter;
|
||||
|
||||
#define ALfilter_SetParami(x, c, p, v) ((x)->SetParami((x),(c),(p),(v)))
|
||||
#define ALfilter_SetParamiv(x, c, p, v) ((x)->SetParamiv((x),(c),(p),(v)))
|
||||
#define ALfilter_SetParamf(x, c, p, v) ((x)->SetParamf((x),(c),(p),(v)))
|
||||
#define ALfilter_SetParamfv(x, c, p, v) ((x)->SetParamfv((x),(c),(p),(v)))
|
||||
|
||||
#define ALfilter_GetParami(x, c, p, v) ((x)->GetParami((x),(c),(p),(v)))
|
||||
#define ALfilter_GetParamiv(x, c, p, v) ((x)->GetParamiv((x),(c),(p),(v)))
|
||||
#define ALfilter_GetParamf(x, c, p, v) ((x)->GetParamf((x),(c),(p),(v)))
|
||||
#define ALfilter_GetParamfv(x, c, p, v) ((x)->GetParamfv((x),(c),(p),(v)))
|
||||
|
||||
ALvoid ReleaseALFilters(ALCdevice *device);
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@ extern "C" {
|
||||
|
||||
typedef struct ALlistener_struct
|
||||
{
|
||||
ALfloat Position[3];
|
||||
ALfloat Velocity[3];
|
||||
ALfloat Forward[3];
|
||||
ALfloat Up[3];
|
||||
ALfloat Gain;
|
||||
ALfloat MetersPerUnit;
|
||||
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;
|
||||
} ALlistener;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+551
-174
@@ -9,10 +9,26 @@
|
||||
#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"
|
||||
|
||||
#ifndef AL_SOFT_deferred_updates
|
||||
#define AL_SOFT_deferred_updates 1
|
||||
#define AL_DEFERRED_UPDATES_SOFT 0xC002
|
||||
typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void);
|
||||
typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void);
|
||||
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
#include <stdint.h>
|
||||
typedef int64_t ALint64;
|
||||
@@ -28,24 +44,55 @@ typedef long long ALint64;
|
||||
typedef unsigned long long ALuint64;
|
||||
#endif
|
||||
|
||||
typedef ptrdiff_t ALintptrEXT;
|
||||
typedef ptrdiff_t ALsizeiptrEXT;
|
||||
|
||||
#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;
|
||||
ALubyte b[sizeof(ALuint)];
|
||||
} EndianTest = { 1 };
|
||||
#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
|
||||
|
||||
#define COUNTOF(x) (sizeof((x))/sizeof((x)[0]))
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
typedef DWORD tls_type;
|
||||
#define tls_create(x) (*(x) = TlsAlloc())
|
||||
#define tls_delete(x) TlsFree((x))
|
||||
#define tls_get(x) TlsGetValue((x))
|
||||
#define tls_set(x, a) TlsSetValue((x), (a))
|
||||
typedef DWORD pthread_key_t;
|
||||
int pthread_key_create(pthread_key_t *key, void (*callback)(void*));
|
||||
int pthread_key_delete(pthread_key_t key);
|
||||
void *pthread_getspecific(pthread_key_t key);
|
||||
int pthread_setspecific(pthread_key_t key, void *val);
|
||||
|
||||
#define HAVE_DYNLOAD 1
|
||||
void *LoadLib(const char *name);
|
||||
void CloseLib(void *handle);
|
||||
void *GetSymbol(void *handle, const char *name);
|
||||
|
||||
WCHAR *strdupW(const WCHAR *str);
|
||||
|
||||
typedef LONG pthread_once_t;
|
||||
#define PTHREAD_ONCE_INIT 0
|
||||
void pthread_once(pthread_once_t *once, void (*callback)(void));
|
||||
|
||||
static __inline int sched_yield(void)
|
||||
{ SwitchToThread(); return 0; }
|
||||
|
||||
#else
|
||||
|
||||
@@ -61,88 +108,238 @@ typedef DWORD tls_type;
|
||||
|
||||
#define IsBadWritePtr(a,b) ((a) == NULL && (b) != 0)
|
||||
|
||||
typedef pthread_key_t tls_type;
|
||||
#define tls_create(x) pthread_key_create((x), NULL)
|
||||
#define tls_delete(x) pthread_key_delete((x))
|
||||
#define tls_get(x) pthread_getspecific((x))
|
||||
#define tls_set(x, a) pthread_setspecific((x), (a))
|
||||
|
||||
typedef pthread_mutex_t CRITICAL_SECTION;
|
||||
static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_lock(cs);
|
||||
assert(ret == 0);
|
||||
}
|
||||
static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_unlock(cs);
|
||||
assert(ret == 0);
|
||||
}
|
||||
static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
|
||||
{
|
||||
pthread_mutexattr_t attrib;
|
||||
int ret;
|
||||
void InitializeCriticalSection(CRITICAL_SECTION *cs);
|
||||
void DeleteCriticalSection(CRITICAL_SECTION *cs);
|
||||
void EnterCriticalSection(CRITICAL_SECTION *cs);
|
||||
void LeaveCriticalSection(CRITICAL_SECTION *cs);
|
||||
|
||||
ret = pthread_mutexattr_init(&attrib);
|
||||
assert(ret == 0);
|
||||
ALuint timeGetTime(void);
|
||||
void Sleep(ALuint t);
|
||||
|
||||
ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
|
||||
#ifdef HAVE_PTHREAD_NP_H
|
||||
if(ret != 0)
|
||||
ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
|
||||
#if defined(HAVE_DLFCN_H)
|
||||
#define HAVE_DYNLOAD 1
|
||||
void *LoadLib(const char *name);
|
||||
void CloseLib(void *handle);
|
||||
void *GetSymbol(void *handle, const char *name);
|
||||
#endif
|
||||
assert(ret == 0);
|
||||
ret = pthread_mutex_init(cs, &attrib);
|
||||
assert(ret == 0);
|
||||
|
||||
pthread_mutexattr_destroy(&attrib);
|
||||
#endif
|
||||
|
||||
typedef void *volatile XchgPtr;
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
|
||||
typedef ALuint RefCount;
|
||||
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
||||
{ return __sync_add_and_fetch(ptr, 1); }
|
||||
static __inline RefCount DecrementRef(volatile RefCount *ptr)
|
||||
{ return __sync_sub_and_fetch(ptr, 1); }
|
||||
|
||||
static __inline int ExchangeInt(volatile int *ptr, int newval)
|
||||
{
|
||||
return __sync_lock_test_and_set(ptr, newval);
|
||||
}
|
||||
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||
{
|
||||
return __sync_lock_test_and_set(ptr, newval);
|
||||
}
|
||||
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
||||
}
|
||||
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||
{
|
||||
return __sync_bool_compare_and_swap(ptr, oldval, newval);
|
||||
}
|
||||
|
||||
static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
static __inline int xaddl(volatile int *dest, int incr)
|
||||
{
|
||||
int ret;
|
||||
ret = pthread_mutex_destroy(cs);
|
||||
assert(ret == 0);
|
||||
__asm__ __volatile__("lock; xaddl %0,(%1)"
|
||||
: "=r" (ret)
|
||||
: "r" (dest), "0" (incr)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
|
||||
* to the expected DWORD. Both are defined as unsigned 32-bit types, however.
|
||||
* Additionally, Win32 is supposed to measure the time since Windows started,
|
||||
* as opposed to the actual time. */
|
||||
static inline ALuint timeGetTime(void)
|
||||
typedef int RefCount;
|
||||
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
||||
{ return xaddl(ptr, 1)+1; }
|
||||
static __inline RefCount DecrementRef(volatile RefCount *ptr)
|
||||
{ return xaddl(ptr, -1)-1; }
|
||||
|
||||
static __inline int ExchangeInt(volatile int *dest, int newval)
|
||||
{
|
||||
int ret;
|
||||
#if _POSIX_TIMERS > 0
|
||||
struct timespec ts;
|
||||
__asm__ __volatile__("lock; xchgl %0,(%1)"
|
||||
: "=r" (ret)
|
||||
: "r" (dest), "0" (newval)
|
||||
: "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
assert(ret == 0);
|
||||
static __inline ALboolean CompExchangeInt(volatile int *dest, int oldval, int newval)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__("lock; cmpxchgl %2,(%1)"
|
||||
: "=a" (ret)
|
||||
: "r" (dest), "r" (newval), "0" (oldval)
|
||||
: "memory");
|
||||
return ret == oldval;
|
||||
}
|
||||
|
||||
return ts.tv_nsec/1000000 + ts.tv_sec*1000;
|
||||
static __inline void *ExchangePtr(XchgPtr *dest, void *newval)
|
||||
{
|
||||
void *ret;
|
||||
__asm__ __volatile__(
|
||||
#ifdef __i386__
|
||||
"lock; xchgl %0,(%1)"
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
ret = gettimeofday(&tv, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
return tv.tv_usec/1000 + tv.tv_sec*1000;
|
||||
"lock; xchgq %0,(%1)"
|
||||
#endif
|
||||
: "=r" (ret)
|
||||
: "r" (dest), "0" (newval)
|
||||
: "memory"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void Sleep(ALuint t)
|
||||
static __inline ALboolean CompExchangePtr(XchgPtr *dest, void *oldval, void *newval)
|
||||
{
|
||||
struct timespec tv, rem;
|
||||
tv.tv_nsec = (t*1000000)%1000000000;
|
||||
tv.tv_sec = t/1000;
|
||||
|
||||
while(nanosleep(&tv, &rem) == -1 && errno == EINTR)
|
||||
tv = rem;
|
||||
}
|
||||
#define min(x,y) (((x)<(y))?(x):(y))
|
||||
#define max(x,y) (((x)>(y))?(x):(y))
|
||||
void *ret;
|
||||
__asm__ __volatile__(
|
||||
#ifdef __i386__
|
||||
"lock; cmpxchgl %2,(%1)"
|
||||
#else
|
||||
"lock; cmpxchgq %2,(%1)"
|
||||
#endif
|
||||
: "=a" (ret)
|
||||
: "r" (dest), "r" (newval), "0" (oldval)
|
||||
: "memory"
|
||||
);
|
||||
return ret == oldval;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
typedef LONG RefCount;
|
||||
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
||||
{ return InterlockedIncrement(ptr); }
|
||||
static __inline RefCount DecrementRef(volatile RefCount *ptr)
|
||||
{ return InterlockedDecrement(ptr); }
|
||||
|
||||
extern ALbyte LONG_size_does_not_match_int[(sizeof(LONG)==sizeof(int))?1:-1];
|
||||
|
||||
static __inline int ExchangeInt(volatile int *ptr, int newval)
|
||||
{
|
||||
union {
|
||||
volatile int *i;
|
||||
volatile LONG *l;
|
||||
} u = { ptr };
|
||||
return InterlockedExchange(u.l, newval);
|
||||
}
|
||||
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||
{
|
||||
return InterlockedExchangePointer(ptr, newval);
|
||||
}
|
||||
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
|
||||
{
|
||||
union {
|
||||
volatile int *i;
|
||||
volatile LONG *l;
|
||||
} u = { ptr };
|
||||
return InterlockedCompareExchange(u.l, newval, oldval) == oldval;
|
||||
}
|
||||
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||
{
|
||||
return InterlockedCompareExchangePointer(ptr, newval, oldval) == oldval;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
typedef int32_t RefCount;
|
||||
static __inline RefCount IncrementRef(volatile RefCount *ptr)
|
||||
{ return OSAtomicIncrement32Barrier(ptr); }
|
||||
static __inline RefCount DecrementRef(volatile RefCount *ptr)
|
||||
{ return OSAtomicDecrement32Barrier(ptr); }
|
||||
|
||||
static __inline int ExchangeInt(volatile int *ptr, int newval)
|
||||
{
|
||||
/* Really? No regular old atomic swap? */
|
||||
int oldval;
|
||||
do {
|
||||
oldval = *ptr;
|
||||
} while(!OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr));
|
||||
return oldval;
|
||||
}
|
||||
static __inline void *ExchangePtr(XchgPtr *ptr, void *newval)
|
||||
{
|
||||
void *oldval;
|
||||
do {
|
||||
oldval = *ptr;
|
||||
} while(!OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr));
|
||||
return oldval;
|
||||
}
|
||||
static __inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval)
|
||||
{
|
||||
return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr);
|
||||
}
|
||||
static __inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval)
|
||||
{
|
||||
return OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "No atomic functions available on this platform!"
|
||||
typedef ALuint RefCount;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
volatile RefCount read_count;
|
||||
volatile RefCount write_count;
|
||||
volatile ALenum read_lock;
|
||||
volatile ALenum read_entry_lock;
|
||||
volatile ALenum write_lock;
|
||||
} RWLock;
|
||||
|
||||
void RWLockInit(RWLock *lock);
|
||||
void ReadLock(RWLock *lock);
|
||||
void ReadUnlock(RWLock *lock);
|
||||
void WriteLock(RWLock *lock);
|
||||
void WriteUnlock(RWLock *lock);
|
||||
|
||||
|
||||
typedef struct UIntMap {
|
||||
struct {
|
||||
ALuint key;
|
||||
ALvoid *value;
|
||||
} *array;
|
||||
ALsizei size;
|
||||
ALsizei maxsize;
|
||||
ALsizei limit;
|
||||
RWLock lock;
|
||||
} UIntMap;
|
||||
extern UIntMap TlsDestructor;
|
||||
|
||||
void InitUIntMap(UIntMap *map, ALsizei limit);
|
||||
void ResetUIntMap(UIntMap *map);
|
||||
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value);
|
||||
ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key);
|
||||
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key);
|
||||
|
||||
static __inline void LockUIntMapRead(UIntMap *map)
|
||||
{ ReadLock(&map->lock); }
|
||||
static __inline void UnlockUIntMapRead(UIntMap *map)
|
||||
{ ReadUnlock(&map->lock); }
|
||||
static __inline void LockUIntMapWrite(UIntMap *map)
|
||||
{ WriteLock(&map->lock); }
|
||||
static __inline void UnlockUIntMapWrite(UIntMap *map)
|
||||
{ WriteUnlock(&map->lock); }
|
||||
|
||||
#include "alListener.h"
|
||||
#include "alu.h"
|
||||
@@ -152,14 +349,16 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define SWMIXER_OUTPUT_RATE 44100
|
||||
#define DEFAULT_OUTPUT_RATE (44100)
|
||||
#define MIN_OUTPUT_RATE (8000)
|
||||
|
||||
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
||||
#define AIRABSORBGAINDBHF (-0.05f)
|
||||
#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */
|
||||
|
||||
#define LOWPASSFREQCUTOFF (5000)
|
||||
#define LOWPASSFREQREF (5000)
|
||||
|
||||
#define DEFAULT_HEAD_DAMPEN (0.25f)
|
||||
|
||||
struct Hrtf;
|
||||
|
||||
|
||||
// Find the next power-of-2 for non-power-of-2 numbers.
|
||||
@@ -179,66 +378,170 @@ static __inline ALuint NextPowerOf2(ALuint value)
|
||||
return powerOf2;
|
||||
}
|
||||
|
||||
/* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
|
||||
* mode. */
|
||||
static __inline ALint fastf2i(ALfloat f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||
void (*ClosePlayback)(ALCdevice*);
|
||||
ALCboolean (*ResetPlayback)(ALCdevice*);
|
||||
void (*StopPlayback)(ALCdevice*);
|
||||
/* Fast float-to-uint conversion. Assumes the FPU is already in round-to-zero
|
||||
* mode. */
|
||||
static __inline ALuint fastf2u(ALfloat f)
|
||||
{ return fastf2i(f); }
|
||||
|
||||
ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*);
|
||||
void (*CloseCapture)(ALCdevice*);
|
||||
void (*StartCapture)(ALCdevice*);
|
||||
void (*StopCapture)(ALCdevice*);
|
||||
void (*CaptureSamples)(ALCdevice*, void*, ALCuint);
|
||||
ALCuint (*AvailableSamples)(ALCdevice*);
|
||||
} BackendFuncs;
|
||||
|
||||
enum {
|
||||
DEVICE_PROBE,
|
||||
enum DevProbe {
|
||||
ALL_DEVICE_PROBE,
|
||||
CAPTURE_DEVICE_PROBE
|
||||
};
|
||||
|
||||
void alc_alsa_init(BackendFuncs *func_list);
|
||||
void alc_alsa_deinit(void);
|
||||
void alc_alsa_probe(int type);
|
||||
void alc_oss_init(BackendFuncs *func_list);
|
||||
void alc_oss_deinit(void);
|
||||
void alc_oss_probe(int type);
|
||||
void alc_solaris_init(BackendFuncs *func_list);
|
||||
void alc_solaris_deinit(void);
|
||||
void alc_solaris_probe(int type);
|
||||
void alcDSoundInit(BackendFuncs *func_list);
|
||||
void alcDSoundDeinit(void);
|
||||
void alcDSoundProbe(int type);
|
||||
void alcWinMMInit(BackendFuncs *FuncList);
|
||||
void alcWinMMDeinit(void);
|
||||
void alcWinMMProbe(int type);
|
||||
void alc_pa_init(BackendFuncs *func_list);
|
||||
void alc_pa_deinit(void);
|
||||
void alc_pa_probe(int type);
|
||||
void alc_wave_init(BackendFuncs *func_list);
|
||||
void alc_wave_deinit(void);
|
||||
void alc_wave_probe(int type);
|
||||
void alc_pulse_init(BackendFuncs *func_list);
|
||||
void alc_pulse_deinit(void);
|
||||
void alc_pulse_probe(int type);
|
||||
typedef struct {
|
||||
ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||
void (*ClosePlayback)(ALCdevice*);
|
||||
ALCboolean (*ResetPlayback)(ALCdevice*);
|
||||
ALCboolean (*StartPlayback)(ALCdevice*);
|
||||
void (*StopPlayback)(ALCdevice*);
|
||||
|
||||
ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
|
||||
void (*CloseCapture)(ALCdevice*);
|
||||
void (*StartCapture)(ALCdevice*);
|
||||
void (*StopCapture)(ALCdevice*);
|
||||
ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
|
||||
ALCuint (*AvailableSamples)(ALCdevice*);
|
||||
} BackendFuncs;
|
||||
|
||||
struct BackendInfo {
|
||||
const char *name;
|
||||
ALCboolean (*Init)(BackendFuncs*);
|
||||
void (*Deinit)(void);
|
||||
void (*Probe)(enum DevProbe);
|
||||
BackendFuncs Funcs;
|
||||
};
|
||||
|
||||
ALCboolean alc_alsa_init(BackendFuncs *func_list);
|
||||
void alc_alsa_deinit(void);
|
||||
void alc_alsa_probe(enum DevProbe type);
|
||||
ALCboolean alc_oss_init(BackendFuncs *func_list);
|
||||
void alc_oss_deinit(void);
|
||||
void alc_oss_probe(enum DevProbe type);
|
||||
ALCboolean alc_solaris_init(BackendFuncs *func_list);
|
||||
void alc_solaris_deinit(void);
|
||||
void alc_solaris_probe(enum DevProbe type);
|
||||
ALCboolean alc_sndio_init(BackendFuncs *func_list);
|
||||
void alc_sndio_deinit(void);
|
||||
void alc_sndio_probe(enum DevProbe type);
|
||||
ALCboolean alcMMDevApiInit(BackendFuncs *func_list);
|
||||
void alcMMDevApiDeinit(void);
|
||||
void alcMMDevApiProbe(enum DevProbe type);
|
||||
ALCboolean alcDSoundInit(BackendFuncs *func_list);
|
||||
void alcDSoundDeinit(void);
|
||||
void alcDSoundProbe(enum DevProbe type);
|
||||
ALCboolean alcWinMMInit(BackendFuncs *FuncList);
|
||||
void alcWinMMDeinit(void);
|
||||
void alcWinMMProbe(enum DevProbe type);
|
||||
ALCboolean alc_pa_init(BackendFuncs *func_list);
|
||||
void alc_pa_deinit(void);
|
||||
void alc_pa_probe(enum DevProbe type);
|
||||
ALCboolean alc_wave_init(BackendFuncs *func_list);
|
||||
void alc_wave_deinit(void);
|
||||
void alc_wave_probe(enum DevProbe type);
|
||||
ALCboolean alc_pulse_init(BackendFuncs *func_list);
|
||||
void alc_pulse_deinit(void);
|
||||
void alc_pulse_probe(enum DevProbe type);
|
||||
ALCboolean alc_ca_init(BackendFuncs *func_list);
|
||||
void alc_ca_deinit(void);
|
||||
void alc_ca_probe(enum DevProbe type);
|
||||
ALCboolean alc_opensl_init(BackendFuncs *func_list);
|
||||
void alc_opensl_deinit(void);
|
||||
void alc_opensl_probe(enum DevProbe type);
|
||||
ALCboolean alc_null_init(BackendFuncs *func_list);
|
||||
void alc_null_deinit(void);
|
||||
void alc_null_probe(enum DevProbe type);
|
||||
ALCboolean alc_loopback_init(BackendFuncs *func_list);
|
||||
void alc_loopback_deinit(void);
|
||||
void alc_loopback_probe(enum DevProbe type);
|
||||
|
||||
|
||||
/* Device formats */
|
||||
enum DevFmtType {
|
||||
DevFmtByte = ALC_BYTE_SOFT,
|
||||
DevFmtUByte = ALC_UNSIGNED_BYTE_SOFT,
|
||||
DevFmtShort = ALC_SHORT_SOFT,
|
||||
DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
|
||||
DevFmtInt = ALC_INT_SOFT,
|
||||
DevFmtUInt = ALC_UNSIGNED_INT_SOFT,
|
||||
DevFmtFloat = ALC_FLOAT_SOFT,
|
||||
|
||||
DevFmtTypeDefault = DevFmtFloat
|
||||
};
|
||||
enum DevFmtChannels {
|
||||
DevFmtMono = ALC_MONO_SOFT,
|
||||
DevFmtStereo = ALC_STEREO_SOFT,
|
||||
DevFmtQuad = ALC_QUAD_SOFT,
|
||||
DevFmtX51 = ALC_5POINT1_SOFT,
|
||||
DevFmtX61 = ALC_6POINT1_SOFT,
|
||||
DevFmtX71 = ALC_7POINT1_SOFT,
|
||||
|
||||
/* Similar to 5.1, except using the side channels instead of back */
|
||||
DevFmtX51Side = 0x80000000,
|
||||
|
||||
DevFmtChannelsDefault = DevFmtStereo
|
||||
};
|
||||
|
||||
ALuint BytesFromDevFmt(enum DevFmtType type);
|
||||
ALuint ChannelsFromDevFmt(enum DevFmtChannels chans);
|
||||
static __inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans,
|
||||
enum DevFmtType type)
|
||||
{
|
||||
return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
|
||||
}
|
||||
|
||||
|
||||
extern const struct EffectList {
|
||||
const char *name;
|
||||
int type;
|
||||
const char *ename;
|
||||
ALenum val;
|
||||
} EffectList[];
|
||||
|
||||
|
||||
enum DeviceType {
|
||||
Playback,
|
||||
Capture,
|
||||
Loopback
|
||||
};
|
||||
|
||||
struct ALCdevice_struct
|
||||
{
|
||||
ALCboolean Connected;
|
||||
ALboolean IsCaptureDevice;
|
||||
volatile RefCount ref;
|
||||
|
||||
ALCboolean Connected;
|
||||
enum DeviceType Type;
|
||||
|
||||
CRITICAL_SECTION Mutex;
|
||||
|
||||
ALuint Frequency;
|
||||
ALuint UpdateSize;
|
||||
ALuint NumUpdates;
|
||||
ALenum Format;
|
||||
enum DevFmtChannels FmtChans;
|
||||
enum DevFmtType FmtType;
|
||||
|
||||
ALCchar *szDeviceName;
|
||||
|
||||
ALCenum LastError;
|
||||
volatile ALCenum LastError;
|
||||
|
||||
// Maximum number of sources that can be created
|
||||
ALuint MaxNoOfSources;
|
||||
@@ -249,47 +552,53 @@ struct ALCdevice_struct
|
||||
ALCuint NumStereoSources;
|
||||
ALuint NumAuxSends;
|
||||
|
||||
// Linked List of Buffers for this device
|
||||
struct ALbuffer *BufferList;
|
||||
ALuint BufferCount;
|
||||
// Map of Buffers for this device
|
||||
UIntMap BufferMap;
|
||||
|
||||
// Linked List of Effects for this device
|
||||
struct ALeffect *EffectList;
|
||||
ALuint EffectCount;
|
||||
// Map of Effects for this device
|
||||
UIntMap EffectMap;
|
||||
|
||||
// Linked List of Filters for this device
|
||||
struct ALfilter *FilterList;
|
||||
ALuint FilterCount;
|
||||
// Map of Filters for this device
|
||||
UIntMap FilterMap;
|
||||
|
||||
// Linked List of Databuffers for this device
|
||||
struct ALdatabuffer *DatabufferList;
|
||||
ALuint DatabufferCount;
|
||||
/* HRTF filter tables */
|
||||
const struct Hrtf *Hrtf;
|
||||
|
||||
// Stereo-to-binaural filter
|
||||
struct bs2b *Bs2b;
|
||||
ALCint Bs2bLevel;
|
||||
|
||||
// Simulated dampening from head occlusion
|
||||
ALfloat HeadDampen;
|
||||
// Device flags
|
||||
ALuint Flags;
|
||||
|
||||
// Dry path buffer mix
|
||||
float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
||||
ALfloat DryBuffer[BUFFERSIZE][MAXCHANNELS];
|
||||
|
||||
Channel DevChannels[OUTPUTCHANNELS];
|
||||
enum Channel DevChannels[MAXCHANNELS];
|
||||
|
||||
enum Channel Speaker2Chan[MAXCHANNELS];
|
||||
ALfloat PanningLUT[LUT_NUM][MAXCHANNELS];
|
||||
ALuint NumChan;
|
||||
|
||||
ALfloat ClickRemoval[MAXCHANNELS];
|
||||
ALfloat PendingClicks[MAXCHANNELS];
|
||||
|
||||
/* Default effect slot */
|
||||
struct ALeffectslot *DefaultSlot;
|
||||
|
||||
// Contexts created on this device
|
||||
ALCcontext **Contexts;
|
||||
ALuint NumContexts;
|
||||
ALCcontext *volatile ContextList;
|
||||
|
||||
BackendFuncs *Funcs;
|
||||
void *ExtraData; // For the backend's use
|
||||
|
||||
ALCdevice *next;
|
||||
ALCdevice *volatile next;
|
||||
};
|
||||
|
||||
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
|
||||
#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
|
||||
#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a)))
|
||||
#define ALCdevice_StartPlayback(a) ((a)->Funcs->StartPlayback((a)))
|
||||
#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a)))
|
||||
#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b)))
|
||||
#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))
|
||||
@@ -298,59 +607,88 @@ struct ALCdevice_struct
|
||||
#define ALCdevice_CaptureSamples(a,b,c) ((a)->Funcs->CaptureSamples((a), (b), (c)))
|
||||
#define ALCdevice_AvailableSamples(a) ((a)->Funcs->AvailableSamples((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
|
||||
#define DEVICE_CHANNELS_REQUEST (1<<2)
|
||||
// Sample type was requested by the config file
|
||||
#define DEVICE_SAMPLE_TYPE_REQUEST (1<<3)
|
||||
|
||||
// Specifies if the device is currently running
|
||||
#define DEVICE_RUNNING (1<<31)
|
||||
|
||||
#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)))
|
||||
#define RemoveBuffer(m, k) ((struct ALbuffer*)RemoveUIntMapKey(&(m)->BufferMap, (k)))
|
||||
#define RemoveEffect(m, k) ((struct ALeffect*)RemoveUIntMapKey(&(m)->EffectMap, (k)))
|
||||
#define RemoveFilter(m, k) ((struct ALfilter*)RemoveUIntMapKey(&(m)->FilterMap, (k)))
|
||||
|
||||
|
||||
struct ALCcontext_struct
|
||||
{
|
||||
volatile RefCount ref;
|
||||
|
||||
ALlistener Listener;
|
||||
|
||||
struct ALsource *SourceList;
|
||||
ALuint SourceCount;
|
||||
UIntMap SourceMap;
|
||||
UIntMap EffectSlotMap;
|
||||
|
||||
struct ALeffectslot *EffectSlotList;
|
||||
ALuint EffectSlotCount;
|
||||
ALenum LastError;
|
||||
|
||||
struct ALdatabuffer *SampleSource;
|
||||
struct ALdatabuffer *SampleSink;
|
||||
volatile ALenum UpdateSources;
|
||||
|
||||
ALenum LastError;
|
||||
volatile enum DistanceModel DistanceModel;
|
||||
volatile ALboolean SourceDistanceModel;
|
||||
|
||||
ALboolean Suspended;
|
||||
volatile ALfloat DopplerFactor;
|
||||
volatile ALfloat DopplerVelocity;
|
||||
volatile ALfloat flSpeedOfSound;
|
||||
volatile ALenum DeferUpdates;
|
||||
|
||||
ALenum DistanceModel;
|
||||
ALboolean SourceDistanceModel;
|
||||
struct ALsource **ActiveSources;
|
||||
ALsizei ActiveSourceCount;
|
||||
ALsizei MaxActiveSources;
|
||||
|
||||
ALfloat DopplerFactor;
|
||||
ALfloat DopplerVelocity;
|
||||
ALfloat flSpeedOfSound;
|
||||
|
||||
ALfloat PanningLUT[OUTPUTCHANNELS * LUT_NUM];
|
||||
ALint NumChan;
|
||||
|
||||
ALfloat ChannelMatrix[OUTPUTCHANNELS][OUTPUTCHANNELS];
|
||||
struct ALeffectslot **ActiveEffectSlots;
|
||||
ALsizei ActiveEffectSlotCount;
|
||||
ALsizei MaxActiveEffectSlots;
|
||||
|
||||
ALCdevice *Device;
|
||||
const ALCchar *ExtensionList;
|
||||
|
||||
ALCcontext *next;
|
||||
ALCcontext *volatile next;
|
||||
};
|
||||
|
||||
extern ALint RTPrioLevel;
|
||||
#define LookupSource(m, k) ((struct ALsource*)LookupUIntMapKey(&(m)->SourceMap, (k)))
|
||||
#define LookupEffectSlot(m, k) ((struct ALeffectslot*)LookupUIntMapKey(&(m)->EffectSlotMap, (k)))
|
||||
#define RemoveSource(m, k) ((struct ALsource*)RemoveUIntMapKey(&(m)->SourceMap, (k)))
|
||||
#define RemoveEffectSlot(m, k) ((struct ALeffectslot*)RemoveUIntMapKey(&(m)->EffectSlotMap, (k)))
|
||||
|
||||
ALCvoid ReleaseALC(ALCvoid);
|
||||
ALCcontext *GetContextRef(void);
|
||||
|
||||
void ALCcontext_IncRef(ALCcontext *context);
|
||||
void ALCcontext_DecRef(ALCcontext *context);
|
||||
|
||||
void AppendDeviceList(const ALCchar *name);
|
||||
void AppendAllDeviceList(const ALCchar *name);
|
||||
void AppendCaptureDeviceList(const ALCchar *name);
|
||||
|
||||
ALCvoid alcSetError(ALCdevice *device, ALenum errorCode);
|
||||
static __inline void LockDevice(ALCdevice *device)
|
||||
{ EnterCriticalSection(&device->Mutex); }
|
||||
static __inline void UnlockDevice(ALCdevice *device)
|
||||
{ LeaveCriticalSection(&device->Mutex); }
|
||||
|
||||
static __inline void LockContext(ALCcontext *context)
|
||||
{ LockDevice(context->Device); }
|
||||
static __inline void UnlockContext(ALCcontext *context)
|
||||
{ UnlockDevice(context->Device); }
|
||||
|
||||
ALCvoid SuspendContext(ALCcontext *context);
|
||||
ALCvoid ProcessContext(ALCcontext *context);
|
||||
|
||||
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr);
|
||||
ALuint StopThread(ALvoid *thread);
|
||||
|
||||
ALCcontext *GetContextSuspended(void);
|
||||
|
||||
typedef struct RingBuffer RingBuffer;
|
||||
RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length);
|
||||
void DestroyRingBuffer(RingBuffer *ring);
|
||||
@@ -362,26 +700,65 @@ void ReadALConfig(void);
|
||||
void FreeALConfig(void);
|
||||
int ConfigValueExists(const char *blockName, const char *keyName);
|
||||
const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
|
||||
int GetConfigValueInt(const char *blockName, const char *keyName, int def);
|
||||
float GetConfigValueFloat(const char *blockName, const char *keyName, float def);
|
||||
int GetConfigValueBool(const char *blockName, const char *keyName, int def);
|
||||
int ConfigValueStr(const char *blockName, const char *keyName, const char **ret);
|
||||
int ConfigValueInt(const char *blockName, const char *keyName, int *ret);
|
||||
int ConfigValueUInt(const char *blockName, const char *keyName, unsigned int *ret);
|
||||
int ConfigValueFloat(const char *blockName, const char *keyName, float *ret);
|
||||
|
||||
void EnableRTPrio(ALint level);
|
||||
void SetRTPriority(void);
|
||||
|
||||
void SetDefaultChannelOrder(ALCdevice *device);
|
||||
void SetDefaultWFXChannelOrder(ALCdevice *device);
|
||||
|
||||
void al_print(const char *fname, unsigned int line, const char *fmt, ...)
|
||||
PRINTF_STYLE(3,4);
|
||||
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
|
||||
const ALCchar *DevFmtTypeString(enum DevFmtType type);
|
||||
const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
|
||||
|
||||
#define DECL_VERIFIER(name, type, field) \
|
||||
static type* Verify##name(type *list, ALuint id) \
|
||||
{ \
|
||||
while(list && list->field != id) \
|
||||
list = list->next; \
|
||||
return list; \
|
||||
}
|
||||
#define HRIR_BITS (5)
|
||||
#define HRIR_LENGTH (1<<HRIR_BITS)
|
||||
#define HRIR_MASK (HRIR_LENGTH-1)
|
||||
void InitHrtf(void);
|
||||
void FreeHrtf(void);
|
||||
const struct Hrtf *GetHrtf(ALCdevice *device);
|
||||
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__)
|
||||
|
||||
extern FILE *LogFile;
|
||||
enum LogLevel {
|
||||
NoLog,
|
||||
LogError,
|
||||
LogWarning,
|
||||
LogTrace,
|
||||
LogRef
|
||||
};
|
||||
extern enum LogLevel LogLevel;
|
||||
|
||||
#define TRACEREF(...) do { \
|
||||
if(LogLevel >= LogRef) \
|
||||
AL_PRINT(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define TRACE(...) do { \
|
||||
if(LogLevel >= LogTrace) \
|
||||
AL_PRINT(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define WARN(...) do { \
|
||||
if(LogLevel >= LogWarning) \
|
||||
AL_PRINT(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#define ERR(...) do { \
|
||||
if(LogLevel >= LogError) \
|
||||
AL_PRINT(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
|
||||
extern ALint RTPrioLevel;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+88
-63
@@ -1,7 +1,7 @@
|
||||
#ifndef _AL_SOURCE_H_
|
||||
#define _AL_SOURCE_H_
|
||||
|
||||
#define MAX_SENDS 2
|
||||
#define MAX_SENDS 4
|
||||
|
||||
#include "alFilter.h"
|
||||
#include "alu.h"
|
||||
@@ -11,102 +11,127 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
POINT_RESAMPLER = 0,
|
||||
LINEAR_RESAMPLER,
|
||||
COSINE_RESAMPLER,
|
||||
#define SRC_HISTORY_BITS (6)
|
||||
#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS)
|
||||
#define SRC_HISTORY_MASK (SRC_HISTORY_LENGTH-1)
|
||||
|
||||
extern enum Resampler DefaultResampler;
|
||||
|
||||
extern const ALsizei ResamplerPadding[ResamplerMax];
|
||||
extern const ALsizei ResamplerPrePadding[ResamplerMax];
|
||||
|
||||
RESAMPLER_MAX,
|
||||
RESAMPLER_MIN = -1,
|
||||
RESAMPLER_DEFAULT = LINEAR_RESAMPLER
|
||||
} resampler_t;
|
||||
extern resampler_t DefaultResampler;
|
||||
|
||||
typedef struct ALbufferlistitem
|
||||
{
|
||||
struct ALbuffer *buffer;
|
||||
struct ALbufferlistitem *next;
|
||||
struct ALbufferlistitem *prev;
|
||||
} ALbufferlistitem;
|
||||
|
||||
typedef struct ALsource
|
||||
{
|
||||
ALfloat flPitch;
|
||||
ALfloat flGain;
|
||||
ALfloat flOuterGain;
|
||||
ALfloat flMinGain;
|
||||
ALfloat flMaxGain;
|
||||
ALfloat flInnerAngle;
|
||||
ALfloat flOuterAngle;
|
||||
ALfloat flRefDistance;
|
||||
ALfloat flMaxDistance;
|
||||
ALfloat flRollOffFactor;
|
||||
ALfloat vPosition[3];
|
||||
ALfloat vVelocity[3];
|
||||
ALfloat vOrientation[3];
|
||||
ALboolean bHeadRelative;
|
||||
ALboolean bLooping;
|
||||
ALenum DistanceModel;
|
||||
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;
|
||||
|
||||
resampler_t Resampler;
|
||||
enum Resampler Resampler;
|
||||
|
||||
ALenum state;
|
||||
ALuint position;
|
||||
ALuint position_fraction;
|
||||
volatile ALenum state;
|
||||
ALenum new_state;
|
||||
ALuint position;
|
||||
ALuint position_fraction;
|
||||
|
||||
struct ALbuffer *Buffer;
|
||||
ALbufferlistitem *queue; // Linked list of buffers in queue
|
||||
ALuint BuffersInQueue; // Number of buffers in queue
|
||||
ALuint BuffersPlayed; // Number of buffers played on this loop
|
||||
|
||||
struct ALbufferlistitem *queue; // Linked list of buffers in queue
|
||||
ALuint BuffersInQueue; // Number of buffers in queue
|
||||
ALuint BuffersPlayed; // Number of buffers played on this loop
|
||||
|
||||
ALfilter DirectFilter;
|
||||
ALfloat DirectGain;
|
||||
ALfloat DirectGainHF;
|
||||
|
||||
struct {
|
||||
struct ALeffectslot *Slot;
|
||||
ALfilter WetFilter;
|
||||
ALfloat WetGain;
|
||||
ALfloat WetGainHF;
|
||||
} Send[MAX_SENDS];
|
||||
|
||||
ALboolean DryGainHFAuto;
|
||||
ALboolean WetGainAuto;
|
||||
ALboolean WetGainHFAuto;
|
||||
ALfloat OuterGainHF;
|
||||
volatile ALboolean DryGainHFAuto;
|
||||
volatile ALboolean WetGainAuto;
|
||||
volatile ALboolean WetGainHFAuto;
|
||||
volatile ALfloat OuterGainHF;
|
||||
|
||||
ALfloat AirAbsorptionFactor;
|
||||
ALfloat RoomRolloffFactor;
|
||||
ALfloat DopplerFactor;
|
||||
volatile ALfloat AirAbsorptionFactor;
|
||||
volatile ALfloat RoomRolloffFactor;
|
||||
volatile ALfloat DopplerFactor;
|
||||
|
||||
ALint lOffset;
|
||||
ALint lOffsetType;
|
||||
ALint lOffset;
|
||||
ALint lOffsetType;
|
||||
|
||||
// Source Type (Static, Streaming, or Undetermined)
|
||||
ALint lSourceType;
|
||||
volatile ALint lSourceType;
|
||||
|
||||
// Current gains, which are ramped while mixed
|
||||
ALfloat DryGains[OUTPUTCHANNELS];
|
||||
ALfloat WetGains[MAX_SENDS];
|
||||
ALboolean FirstStart;
|
||||
ALuint NumChannels;
|
||||
ALuint SampleSize;
|
||||
|
||||
// Current target parameters used for mixing
|
||||
ALboolean NeedsUpdate;
|
||||
/* HRTF info */
|
||||
ALboolean HrtfMoving;
|
||||
ALuint HrtfCounter;
|
||||
ALfloat HrtfHistory[MAXCHANNELS][SRC_HISTORY_LENGTH];
|
||||
ALfloat HrtfValues[MAXCHANNELS][HRIR_LENGTH][2];
|
||||
ALuint HrtfOffset;
|
||||
|
||||
/* Current target parameters used for mixing */
|
||||
struct {
|
||||
ALfloat DryGains[OUTPUTCHANNELS];
|
||||
ALfloat WetGains[MAX_SENDS];
|
||||
ALfloat Pitch;
|
||||
MixerFunc DoMix;
|
||||
|
||||
struct {
|
||||
FILTER iirFilter;
|
||||
ALfloat history[OUTPUTCHANNELS];
|
||||
} Send[MAX_SENDS];
|
||||
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];
|
||||
|
||||
/* 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[OUTPUTCHANNELS*2];
|
||||
ALfloat history[MAXCHANNELS*2];
|
||||
|
||||
struct {
|
||||
struct ALeffectslot *Slot;
|
||||
ALfloat WetGain;
|
||||
FILTER iirFilter;
|
||||
ALfloat history[MAXCHANNELS];
|
||||
} Send[MAX_SENDS];
|
||||
} Params;
|
||||
volatile ALenum NeedsUpdate;
|
||||
|
||||
ALvoid (*Update)(struct ALsource *self, const ALCcontext *context);
|
||||
|
||||
// Index to itself
|
||||
ALuint source;
|
||||
|
||||
struct ALsource *next;
|
||||
} ALsource;
|
||||
#define ALsource_Update(s,a) ((s)->Update(s,a))
|
||||
|
||||
ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state);
|
||||
ALboolean ApplyOffset(ALsource *Source);
|
||||
|
||||
ALvoid ReleaseALSources(ALCcontext *Context);
|
||||
|
||||
|
||||
@@ -1,42 +1,20 @@
|
||||
#ifndef _AL_THUNK_H_
|
||||
#define _AL_THUNK_H_
|
||||
#ifndef ALTHUNK_H
|
||||
#define ALTHUNK_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alMain.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void alThunkInit(void);
|
||||
void alThunkExit(void);
|
||||
ALuint alThunkAddEntry(ALvoid * ptr);
|
||||
void alThunkRemoveEntry(ALuint index);
|
||||
ALvoid *alThunkLookupEntry(ALuint index);
|
||||
|
||||
#if (SIZEOF_VOIDP > SIZEOF_UINT)
|
||||
|
||||
#define ALTHUNK_INIT() alThunkInit()
|
||||
#define ALTHUNK_EXIT() alThunkExit()
|
||||
#define ALTHUNK_ADDENTRY(p) alThunkAddEntry(p)
|
||||
#define ALTHUNK_REMOVEENTRY(i) alThunkRemoveEntry(i)
|
||||
#define ALTHUNK_LOOKUPENTRY(i) alThunkLookupEntry(i)
|
||||
|
||||
#else
|
||||
|
||||
#define ALTHUNK_INIT()
|
||||
#define ALTHUNK_EXIT()
|
||||
#define ALTHUNK_ADDENTRY(p) ((ALuint)p)
|
||||
#define ALTHUNK_REMOVEENTRY(i)
|
||||
#define ALTHUNK_LOOKUPENTRY(i) ((ALvoid*)(i))
|
||||
|
||||
#endif // (SIZEOF_VOIDP > SIZEOF_INT)
|
||||
void ThunkInit(void);
|
||||
void ThunkExit(void);
|
||||
ALenum NewThunkEntry(ALuint *index);
|
||||
void FreeThunkEntry(ALuint index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_AL_THUNK_H_
|
||||
#endif //ALTHUNK_H
|
||||
|
||||
|
||||
+234
-108
@@ -5,52 +5,109 @@
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.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>
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#endif
|
||||
|
||||
#define F_PI (3.14159265358979323846f) /* pi */
|
||||
#define F_PI_2 (1.57079632679489661923f) /* pi/2 */
|
||||
|
||||
#ifdef HAVE_POWF
|
||||
#define aluPow(x,y) ((ALfloat)powf((float)(x),(float)(y)))
|
||||
#define aluPow(x,y) (powf((x),(y)))
|
||||
#else
|
||||
#define aluPow(x,y) ((ALfloat)pow((double)(x),(double)(y)))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SQRTF
|
||||
#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
|
||||
#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) ((ALfloat)acosf((float)(x)))
|
||||
#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) ((ALfloat)atanf((float)(x)))
|
||||
#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) ((ALfloat)fabsf((float)(x)))
|
||||
#define aluFabs(x) (fabsf((x)))
|
||||
#else
|
||||
#define aluFabs(x) ((ALfloat)fabs((double)(x)))
|
||||
#endif
|
||||
|
||||
// fixes for mingw32.
|
||||
#if defined(max) && !defined(__max)
|
||||
#define __max max
|
||||
#ifdef HAVE_LOG10F
|
||||
#define aluLog10(x) (log10f((x)))
|
||||
#else
|
||||
#define aluLog10(x) ((ALfloat)log10((double)(x)))
|
||||
#endif
|
||||
#if defined(min) && !defined(__min)
|
||||
#define __min min
|
||||
|
||||
#ifdef HAVE_FLOORF
|
||||
#define aluFloor(x) (floorf((x)))
|
||||
#else
|
||||
#define aluFloor(x) ((ALfloat)floor((double)(x)))
|
||||
#endif
|
||||
|
||||
#define QUADRANT_NUM 128
|
||||
@@ -60,7 +117,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
struct ALsource;
|
||||
struct ALbuffer;
|
||||
|
||||
typedef ALvoid (*MixerFunc)(struct ALsource *self, ALCdevice *Device,
|
||||
const ALvoid *RESTRICT data,
|
||||
ALuint *DataPosInt, ALuint *DataPosFrac,
|
||||
ALuint OutPos, ALuint SamplesToDo,
|
||||
ALuint BufferSize);
|
||||
|
||||
enum Resampler {
|
||||
PointResampler,
|
||||
LinearResampler,
|
||||
CubicResampler,
|
||||
|
||||
ResamplerMax,
|
||||
};
|
||||
|
||||
enum Channel {
|
||||
FRONT_LEFT = 0,
|
||||
FRONT_RIGHT,
|
||||
FRONT_CENTER,
|
||||
@@ -71,114 +145,166 @@ typedef enum {
|
||||
SIDE_LEFT,
|
||||
SIDE_RIGHT,
|
||||
|
||||
OUTPUTCHANNELS
|
||||
} Channel;
|
||||
MAXCHANNELS
|
||||
};
|
||||
|
||||
#define BUFFERSIZE 16384
|
||||
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,
|
||||
|
||||
extern ALboolean DuplicateStereo;
|
||||
DefaultDistanceModel = InverseDistanceClamped
|
||||
};
|
||||
|
||||
/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
|
||||
* converted to AL_FORMAT_QUAD* when loaded */
|
||||
static __inline ALuint aluBytesFromFormat(ALenum format)
|
||||
#define BUFFERSIZE 4096
|
||||
|
||||
#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); }
|
||||
static __inline ALfloat maxf(ALfloat a, ALfloat b)
|
||||
{ return ((a > b) ? a : b); }
|
||||
static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
|
||||
{ return minf(max, maxf(min, val)); }
|
||||
|
||||
static __inline ALuint minu(ALuint a, ALuint b)
|
||||
{ return ((a > b) ? b : a); }
|
||||
static __inline ALuint maxu(ALuint a, ALuint b)
|
||||
{ return ((a > b) ? a : b); }
|
||||
static __inline ALuint clampu(ALuint val, ALuint min, ALuint max)
|
||||
{ return minu(max, maxu(min, val)); }
|
||||
|
||||
static __inline ALint mini(ALint a, ALint b)
|
||||
{ return ((a > b) ? b : a); }
|
||||
static __inline ALint maxi(ALint a, ALint b)
|
||||
{ return ((a > b) ? a : b); }
|
||||
static __inline ALint clampi(ALint val, ALint min, ALint max)
|
||||
{ return mini(max, maxi(min, val)); }
|
||||
|
||||
static __inline ALint64 mini64(ALint64 a, ALint64 b)
|
||||
{ return ((a > b) ? b : a); }
|
||||
static __inline ALint64 maxi64(ALint64 a, ALint64 b)
|
||||
{ return ((a > b) ? a : b); }
|
||||
static __inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
|
||||
{ return mini64(max, maxi64(min, val)); }
|
||||
|
||||
|
||||
static __inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case AL_FORMAT_MONO8:
|
||||
case AL_FORMAT_STEREO8:
|
||||
case AL_FORMAT_QUAD8_LOKI:
|
||||
case AL_FORMAT_QUAD8:
|
||||
case AL_FORMAT_51CHN8:
|
||||
case AL_FORMAT_61CHN8:
|
||||
case AL_FORMAT_71CHN8:
|
||||
return 1;
|
||||
|
||||
case AL_FORMAT_MONO16:
|
||||
case AL_FORMAT_STEREO16:
|
||||
case AL_FORMAT_QUAD16_LOKI:
|
||||
case AL_FORMAT_QUAD16:
|
||||
case AL_FORMAT_51CHN16:
|
||||
case AL_FORMAT_61CHN16:
|
||||
case AL_FORMAT_71CHN16:
|
||||
return 2;
|
||||
|
||||
case AL_FORMAT_MONO_FLOAT32:
|
||||
case AL_FORMAT_STEREO_FLOAT32:
|
||||
case AL_FORMAT_QUAD32:
|
||||
case AL_FORMAT_51CHN32:
|
||||
case AL_FORMAT_61CHN32:
|
||||
case AL_FORMAT_71CHN32:
|
||||
return 4;
|
||||
|
||||
case AL_FORMAT_MONO_DOUBLE_EXT:
|
||||
case AL_FORMAT_STEREO_DOUBLE_EXT:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return val1 + (val2-val1)*mu;
|
||||
}
|
||||
static __inline ALuint aluChannelsFromFormat(ALenum format)
|
||||
static __inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu)
|
||||
{
|
||||
switch(format)
|
||||
ALfloat mu2 = mu*mu;
|
||||
ALfloat a0 = -0.5f*val0 + 1.5f*val1 + -1.5f*val2 + 0.5f*val3;
|
||||
ALfloat a1 = val0 + -2.5f*val1 + 2.0f*val2 + -0.5f*val3;
|
||||
ALfloat a2 = -0.5f*val0 + 0.5f*val2;
|
||||
ALfloat a3 = val1;
|
||||
|
||||
return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
case AL_FORMAT_MONO8:
|
||||
case AL_FORMAT_MONO16:
|
||||
case AL_FORMAT_MONO_FLOAT32:
|
||||
case AL_FORMAT_MONO_DOUBLE_EXT:
|
||||
return 1;
|
||||
|
||||
case AL_FORMAT_STEREO8:
|
||||
case AL_FORMAT_STEREO16:
|
||||
case AL_FORMAT_STEREO_FLOAT32:
|
||||
case AL_FORMAT_STEREO_DOUBLE_EXT:
|
||||
return 2;
|
||||
|
||||
case AL_FORMAT_QUAD8_LOKI:
|
||||
case AL_FORMAT_QUAD16_LOKI:
|
||||
case AL_FORMAT_QUAD8:
|
||||
case AL_FORMAT_QUAD16:
|
||||
case AL_FORMAT_QUAD32:
|
||||
return 4;
|
||||
|
||||
case AL_FORMAT_51CHN8:
|
||||
case AL_FORMAT_51CHN16:
|
||||
case AL_FORMAT_51CHN32:
|
||||
return 6;
|
||||
|
||||
case AL_FORMAT_61CHN8:
|
||||
case AL_FORMAT_61CHN16:
|
||||
case AL_FORMAT_61CHN32:
|
||||
return 7;
|
||||
|
||||
case AL_FORMAT_71CHN8:
|
||||
case AL_FORMAT_71CHN16:
|
||||
case AL_FORMAT_71CHN32:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
inverse_length = 1.0f/length;
|
||||
inVector[0] *= inverse_length;
|
||||
inVector[1] *= inverse_length;
|
||||
inVector[2] *= inverse_length;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
|
||||
{
|
||||
ALint pos = 0;
|
||||
ALfloat denom = aluFabs(re) + aluFabs(im);
|
||||
if(denom > 0.0f)
|
||||
pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
|
||||
|
||||
if(re < 0.0)
|
||||
pos = 2 * QUADRANT_NUM - pos;
|
||||
if(im < 0.0)
|
||||
pos = LUT_NUM - pos;
|
||||
return pos%LUT_NUM;
|
||||
}
|
||||
ALvoid aluInitPanning(ALCdevice *Device);
|
||||
ALint aluCart2LUTpos(ALfloat re, ALfloat im);
|
||||
|
||||
ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
|
||||
ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
|
||||
|
||||
MixerFunc SelectMixer(enum Resampler Resampler);
|
||||
MixerFunc SelectHrtfMixer(enum Resampler Resampler);
|
||||
|
||||
ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo);
|
||||
|
||||
ALvoid aluInitPanning(ALCcontext *Context);
|
||||
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
|
||||
ALvoid aluHandleDisconnect(ALCdevice *device);
|
||||
|
||||
extern ALfloat ConeScale;
|
||||
extern ALfloat ZScale;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -60,7 +60,7 @@ struct bs2b {
|
||||
double b1_hi;
|
||||
|
||||
/* Global gain against overloading */
|
||||
double gain;
|
||||
float gain;
|
||||
|
||||
/* Buffer of last filtered sample.
|
||||
* [0] - first channel, [1] - second channel
|
||||
@@ -91,9 +91,6 @@ int bs2b_get_srate(struct bs2b *bs2b);
|
||||
/* Clear buffer */
|
||||
void bs2b_clear(struct bs2b *bs2b);
|
||||
|
||||
/* Return 1 if buffer is clear */
|
||||
int bs2b_is_clear(struct bs2b *bs2b);
|
||||
|
||||
/* Crossfeeds one stereo sample that are pointed by sample.
|
||||
* [0] - first channel, [1] - second channel.
|
||||
* Returns crossfided samle by sample pointer.
|
||||
|
||||
+300
-206
@@ -32,140 +32,118 @@
|
||||
#include "alSource.h"
|
||||
|
||||
|
||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);
|
||||
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count);
|
||||
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *val);
|
||||
|
||||
DECL_VERIFIER(EffectSlot, ALeffectslot, effectslot)
|
||||
DECL_VERIFIER(Effect, ALeffect, effect)
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALsizei i=0, j;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if (n > 0)
|
||||
if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
ALCdevice *Device = Context->Device;
|
||||
ALenum err;
|
||||
ALsizei i;
|
||||
|
||||
if(Context->EffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
|
||||
err = ResizeEffectSlotArray(Context, n);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
// Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
|
||||
if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
|
||||
{
|
||||
ALeffectslot *end;
|
||||
ALeffectslot **list = &Context->EffectSlotList;
|
||||
while(*list)
|
||||
list = &(*list)->next;
|
||||
|
||||
end = *list;
|
||||
while(i < n)
|
||||
{
|
||||
*list = calloc(1, sizeof(ALeffectslot));
|
||||
if(!(*list) || !((*list)->EffectState=NoneCreate()))
|
||||
{
|
||||
// We must have run out or memory
|
||||
free(*list); *list = NULL;
|
||||
while(end->next)
|
||||
{
|
||||
ALeffectslot *temp = end->next;
|
||||
end->next = temp->next;
|
||||
|
||||
ALEffect_Destroy(temp->EffectState);
|
||||
ALTHUNK_REMOVEENTRY(temp->effectslot);
|
||||
Context->EffectSlotCount--;
|
||||
free(temp);
|
||||
}
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
break;
|
||||
}
|
||||
|
||||
(*list)->Gain = 1.0;
|
||||
(*list)->AuxSendAuto = AL_TRUE;
|
||||
for(j = 0;j < BUFFERSIZE;j++)
|
||||
(*list)->WetBuffer[j] = 0.0f;
|
||||
(*list)->refcount = 0;
|
||||
|
||||
effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
(*list)->effectslot = effectslots[i];
|
||||
|
||||
Context->EffectSlotCount++;
|
||||
i++;
|
||||
|
||||
list = &(*list)->next;
|
||||
}
|
||||
}
|
||||
alSetError(Context, err);
|
||||
n = 0;
|
||||
}
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
ALeffectslot *slot = calloc(1, sizeof(ALeffectslot));
|
||||
if(!slot || InitEffectSlot(slot) != AL_NO_ERROR)
|
||||
{
|
||||
free(slot);
|
||||
// We must have run out or memory
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
alDeleteAuxiliaryEffectSlots(i, effectslots);
|
||||
break;
|
||||
}
|
||||
|
||||
LockContext(Context);
|
||||
err = ResizeEffectSlotArray(Context, 1);
|
||||
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);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
RemoveEffectSlotArray(Context, slot);
|
||||
FreeThunkEntry(slot->effectslot);
|
||||
ALeffectState_Destroy(slot->EffectState);
|
||||
free(slot);
|
||||
|
||||
alSetError(Context, err);
|
||||
alDeleteAuxiliaryEffectSlots(i, effectslots);
|
||||
break;
|
||||
}
|
||||
|
||||
effectslots[i] = slot->effectslot;
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALeffectslot *EffectSlot;
|
||||
ALsizei i;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if (n >= 0)
|
||||
if(n < 0)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
// Check that all effectslots are valid
|
||||
for (i = 0; i < n; i++)
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) == NULL)
|
||||
if((EffectSlot=LookupEffectSlot(Context, effectslots[i])) == NULL)
|
||||
{
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
else if(EffectSlot->ref != 0)
|
||||
{
|
||||
if(EffectSlot->refcount > 0)
|
||||
{
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
break;
|
||||
}
|
||||
alSetError(Context, AL_INVALID_OPERATION);
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == n)
|
||||
// All effectslots are valid
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
// All effectslots are valid
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Recheck that the effectslot is valid, because there could be duplicated names
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) != NULL)
|
||||
{
|
||||
ALeffectslot **list;
|
||||
// Recheck that the effectslot is valid, because there could be duplicated names
|
||||
if((EffectSlot=RemoveEffectSlot(Context, effectslots[i])) == NULL)
|
||||
continue;
|
||||
FreeThunkEntry(EffectSlot->effectslot);
|
||||
|
||||
// Remove Source from list of Sources
|
||||
list = &Context->EffectSlotList;
|
||||
while(*list && *list != EffectSlot)
|
||||
list = &(*list)->next;
|
||||
RemoveEffectSlotArray(Context, EffectSlot);
|
||||
ALeffectState_Destroy(EffectSlot->EffectState);
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
ALTHUNK_REMOVEENTRY(EffectSlot->effectslot);
|
||||
|
||||
ALEffect_Destroy(EffectSlot->EffectState);
|
||||
|
||||
memset(EffectSlot, 0, sizeof(ALeffectslot));
|
||||
free(EffectSlot);
|
||||
|
||||
Context->EffectSlotCount--;
|
||||
}
|
||||
}
|
||||
memset(EffectSlot, 0, sizeof(ALeffectslot));
|
||||
free(EffectSlot);
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
|
||||
@@ -173,27 +151,27 @@ AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
|
||||
ALCcontext *Context;
|
||||
ALboolean result;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
result = (VerifyEffectSlot(Context->EffectSlotList, effectslot) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
result = (LookupEffectSlot(Context, effectslot) ? AL_TRUE : AL_FALSE);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
|
||||
{
|
||||
ALCdevice *Device;
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
ALeffectslot *EffectSlot;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
|
||||
Device = Context->Device;
|
||||
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -201,10 +179,14 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
|
||||
ALeffect *effect = NULL;
|
||||
|
||||
if(iValue == 0 ||
|
||||
(effect=VerifyEffect(Context->Device->EffectList, iValue)) != NULL)
|
||||
(effect=LookupEffect(Device, iValue)) != NULL)
|
||||
{
|
||||
InitializeEffect(Context, EffectSlot, effect);
|
||||
updateSources = AL_TRUE;
|
||||
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);
|
||||
@@ -214,7 +196,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
|
||||
if(iValue == AL_TRUE || iValue == AL_FALSE)
|
||||
{
|
||||
EffectSlot->AuxSendAuto = iValue;
|
||||
updateSources = AL_TRUE;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
@@ -228,45 +210,28 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
// Force updating the sources that use this slot, since it affects the
|
||||
// sending parameters
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
{
|
||||
ALuint i;
|
||||
for(i = 0;i < MAX_SENDS;i++)
|
||||
{
|
||||
if(!source->Send[i].Slot ||
|
||||
source->Send[i].Slot->effectslot != effectslot)
|
||||
continue;
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return;
|
||||
|
||||
if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
|
||||
switch(param)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_EFFECT:
|
||||
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
|
||||
alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(LookupEffectSlot(Context, effectslot) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -275,7 +240,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
|
||||
@@ -283,16 +248,19 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
|
||||
ALCcontext *Context;
|
||||
ALeffectslot *EffectSlot;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
|
||||
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
@@ -305,24 +273,27 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_GAIN:
|
||||
alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
|
||||
if(LookupEffectSlot(Context, effectslot) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_GAIN:
|
||||
alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -331,7 +302,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
|
||||
@@ -339,10 +310,10 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
|
||||
ALCcontext *Context;
|
||||
ALeffectslot *EffectSlot;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
|
||||
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -362,25 +333,28 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return;
|
||||
|
||||
if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
|
||||
switch(param)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_EFFECT:
|
||||
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
|
||||
alGetAuxiliaryEffectSloti(effectslot, param, piValues);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(LookupEffectSlot(Context, effectslot) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -389,7 +363,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
|
||||
@@ -397,10 +371,10 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
|
||||
ALCcontext *Context;
|
||||
ALeffectslot *EffectSlot;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if((EffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
|
||||
if((EffectSlot=LookupEffectSlot(Context, effectslot)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -416,24 +390,27 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_GAIN:
|
||||
alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
|
||||
if(LookupEffectSlot(Context, effectslot) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EFFECTSLOT_GAIN:
|
||||
alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -442,7 +419,7 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
@@ -454,16 +431,15 @@ static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
|
||||
(void)State;
|
||||
(void)Device;
|
||||
}
|
||||
static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
|
||||
{
|
||||
(void)State;
|
||||
(void)Context;
|
||||
(void)Effect;
|
||||
}
|
||||
static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
|
||||
static ALvoid NoneUpdate(ALeffectState *State, ALCdevice *Device, const ALeffectslot *Slot)
|
||||
{
|
||||
(void)State;
|
||||
(void)Device;
|
||||
(void)Slot;
|
||||
}
|
||||
static ALvoid NoneProcess(ALeffectState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS])
|
||||
{
|
||||
(void)State;
|
||||
(void)SamplesToDo;
|
||||
(void)SamplesIn;
|
||||
(void)SamplesOut;
|
||||
@@ -484,53 +460,171 @@ ALeffectState *NoneCreate(void)
|
||||
return state;
|
||||
}
|
||||
|
||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
|
||||
|
||||
static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot)
|
||||
{
|
||||
if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
|
||||
ALeffectslot **slotlist, **slotlistend;
|
||||
|
||||
LockContext(Context);
|
||||
slotlist = Context->ActiveEffectSlots;
|
||||
slotlistend = slotlist + Context->ActiveEffectSlotCount;
|
||||
while(slotlist != slotlistend)
|
||||
{
|
||||
ALeffectState *NewState = NULL;
|
||||
if(!effect || effect->type == AL_EFFECT_NULL)
|
||||
NewState = NoneCreate();
|
||||
else if(effect->type == AL_EFFECT_EAXREVERB)
|
||||
NewState = EAXVerbCreate();
|
||||
else if(effect->type == AL_EFFECT_REVERB)
|
||||
NewState = VerbCreate();
|
||||
else if(effect->type == AL_EFFECT_ECHO)
|
||||
NewState = EchoCreate();
|
||||
/* No new state? An error occured.. */
|
||||
if(NewState == NULL ||
|
||||
ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
|
||||
if(*slotlist == slot)
|
||||
{
|
||||
if(NewState)
|
||||
ALEffect_Destroy(NewState);
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
return;
|
||||
*slotlist = *(--slotlistend);
|
||||
Context->ActiveEffectSlotCount--;
|
||||
break;
|
||||
}
|
||||
if(EffectSlot->EffectState)
|
||||
ALEffect_Destroy(EffectSlot->EffectState);
|
||||
EffectSlot->EffectState = NewState;
|
||||
slotlist++;
|
||||
}
|
||||
if(!effect)
|
||||
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
|
||||
else
|
||||
memcpy(&EffectSlot->effect, effect, sizeof(*effect));
|
||||
ALEffect_Update(EffectSlot->EffectState, Context, effect);
|
||||
UnlockContext(Context);
|
||||
}
|
||||
|
||||
static ALenum ResizeEffectSlotArray(ALCcontext *Context, ALsizei count)
|
||||
{
|
||||
ALsizei newcount;
|
||||
void *temp;
|
||||
|
||||
if(count <= Context->MaxActiveEffectSlots-Context->ActiveEffectSlotCount)
|
||||
return AL_NO_ERROR;
|
||||
|
||||
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;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
|
||||
{
|
||||
ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
|
||||
ALeffectState *State = NULL;
|
||||
ALenum err = AL_NO_ERROR;
|
||||
|
||||
LockDevice(Device);
|
||||
if(newtype == AL_EFFECT_NULL && EffectSlot->effect.type != AL_EFFECT_NULL)
|
||||
{
|
||||
State = NoneCreate();
|
||||
if(!State) err = AL_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(newtype == AL_EFFECT_EAXREVERB || newtype == AL_EFFECT_REVERB)
|
||||
{
|
||||
if(EffectSlot->effect.type != AL_EFFECT_EAXREVERB && EffectSlot->effect.type != AL_EFFECT_REVERB)
|
||||
{
|
||||
State = ReverbCreate();
|
||||
if(!State) err = AL_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else if(newtype == AL_EFFECT_ECHO && EffectSlot->effect.type != AL_EFFECT_ECHO)
|
||||
{
|
||||
State = EchoCreate();
|
||||
if(!State) err = AL_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(newtype == AL_EFFECT_RING_MODULATOR && EffectSlot->effect.type != AL_EFFECT_RING_MODULATOR)
|
||||
{
|
||||
State = ModulatorCreate();
|
||||
if(!State) err = AL_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(newtype == AL_EFFECT_DEDICATED_DIALOGUE || newtype == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
|
||||
{
|
||||
if(EffectSlot->effect.type != AL_EFFECT_DEDICATED_DIALOGUE && EffectSlot->effect.type != AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
|
||||
{
|
||||
State = DedicatedCreate();
|
||||
if(!State) err = AL_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
UnlockDevice(Device);
|
||||
return err;
|
||||
}
|
||||
|
||||
if(State)
|
||||
{
|
||||
int oldMode;
|
||||
oldMode = SetMixerFPUMode();
|
||||
|
||||
if(ALeffectState_DeviceUpdate(State, Device) == AL_FALSE)
|
||||
{
|
||||
RestoreFPUMode(oldMode);
|
||||
UnlockDevice(Device);
|
||||
ALeffectState_Destroy(State);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State);
|
||||
|
||||
if(!effect)
|
||||
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
|
||||
else
|
||||
memcpy(&EffectSlot->effect, effect, sizeof(*effect));
|
||||
/* FIXME: This should be done asynchronously, but since the EffectState
|
||||
* object was changed, it needs an update before its Process method can
|
||||
* be called. */
|
||||
EffectSlot->NeedsUpdate = AL_FALSE;
|
||||
ALeffectState_Update(EffectSlot->EffectState, Device, EffectSlot);
|
||||
UnlockDevice(Device);
|
||||
|
||||
RestoreFPUMode(oldMode);
|
||||
|
||||
ALeffectState_Destroy(State);
|
||||
State = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!effect)
|
||||
memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect));
|
||||
else
|
||||
memcpy(&EffectSlot->effect, effect, sizeof(*effect));
|
||||
UnlockDevice(Device);
|
||||
EffectSlot->NeedsUpdate = AL_TRUE;
|
||||
}
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ALenum InitEffectSlot(ALeffectslot *slot)
|
||||
{
|
||||
ALint i;
|
||||
|
||||
if(!(slot->EffectState=NoneCreate()))
|
||||
return AL_OUT_OF_MEMORY;
|
||||
|
||||
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++)
|
||||
{
|
||||
slot->ClickRemoval[i] = 0.0f;
|
||||
slot->PendingClicks[i] = 0.0f;
|
||||
}
|
||||
slot->ref = 0;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||
{
|
||||
while(Context->EffectSlotList)
|
||||
ALsizei pos;
|
||||
for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
|
||||
{
|
||||
ALeffectslot *temp = Context->EffectSlotList;
|
||||
Context->EffectSlotList = temp->next;
|
||||
ALeffectslot *temp = Context->EffectSlotMap.array[pos].value;
|
||||
Context->EffectSlotMap.array[pos].value = NULL;
|
||||
|
||||
// Release effectslot structure
|
||||
ALEffect_Destroy(temp->EffectState);
|
||||
ALeffectState_Destroy(temp->EffectState);
|
||||
|
||||
ALTHUNK_REMOVEENTRY(temp->effectslot);
|
||||
FreeThunkEntry(temp->effectslot);
|
||||
memset(temp, 0, sizeof(ALeffectslot));
|
||||
free(temp);
|
||||
}
|
||||
Context->EffectSlotCount = 0;
|
||||
}
|
||||
|
||||
+1842
-848
File diff suppressed because it is too large
Load Diff
@@ -1,667 +0,0 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
#include "alError.h"
|
||||
#include "alDatabuffer.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
|
||||
DECL_VERIFIER(Databuffer, ALdatabuffer, databuffer)
|
||||
|
||||
/*
|
||||
* alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
|
||||
*
|
||||
* Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
|
||||
*/
|
||||
AL_API ALvoid AL_APIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALsizei i=0;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return;
|
||||
|
||||
/* Check that we are actually generation some Databuffers */
|
||||
if(n > 0)
|
||||
{
|
||||
ALCdevice *device = Context->Device;
|
||||
|
||||
/* Check the pointer is valid (and points to enough memory to store
|
||||
* Databuffer Names) */
|
||||
if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
|
||||
{
|
||||
ALdatabuffer *end;
|
||||
ALdatabuffer **list = &device->DatabufferList;
|
||||
while(*list)
|
||||
list = &(*list)->next;
|
||||
|
||||
/* Create all the new Databuffers */
|
||||
end = *list;
|
||||
while(i < n)
|
||||
{
|
||||
*list = calloc(1, sizeof(ALdatabuffer));
|
||||
if(!(*list))
|
||||
{
|
||||
while(end->next)
|
||||
{
|
||||
ALdatabuffer *temp = end->next;
|
||||
end->next = temp->next;
|
||||
|
||||
ALTHUNK_REMOVEENTRY(temp->databuffer);
|
||||
device->DatabufferCount--;
|
||||
free(temp);
|
||||
}
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
break;
|
||||
}
|
||||
|
||||
puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
(*list)->databuffer = puiBuffers[i];
|
||||
(*list)->state = UNMAPPED;
|
||||
device->DatabufferCount++;
|
||||
i++;
|
||||
|
||||
list = &(*list)->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
}
|
||||
|
||||
/*
|
||||
* alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
|
||||
*
|
||||
* Deletes the n AL Databuffers pointed to by puiBuffers
|
||||
*/
|
||||
AL_API ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALdatabuffer *ALBuf;
|
||||
ALsizei i;
|
||||
ALboolean bFailed = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return;
|
||||
|
||||
/* Check we are actually Deleting some Databuffers */
|
||||
if(n >= 0)
|
||||
{
|
||||
ALCdevice *device = Context->Device;
|
||||
|
||||
/* Check that all the databuffers are valid and can actually be
|
||||
* deleted */
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(!puiBuffers[i])
|
||||
continue;
|
||||
|
||||
/* Check for valid Buffer ID */
|
||||
if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
|
||||
{
|
||||
if(ALBuf->state != UNMAPPED)
|
||||
{
|
||||
/* Databuffer still in use, cannot be deleted */
|
||||
alSetError(Context, AL_INVALID_OPERATION);
|
||||
bFailed = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid Databuffer */
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
bFailed = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If all the Databuffers were valid (and unmapped), then we can
|
||||
* delete them */
|
||||
if(!bFailed)
|
||||
{
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
|
||||
{
|
||||
ALdatabuffer **list = &device->DatabufferList;
|
||||
|
||||
while(*list && *list != ALBuf)
|
||||
list = &(*list)->next;
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
|
||||
if(ALBuf == Context->SampleSource)
|
||||
Context->SampleSource = NULL;
|
||||
if(ALBuf == Context->SampleSink)
|
||||
Context->SampleSink = NULL;
|
||||
|
||||
// Release the memory used to store audio data
|
||||
free(ALBuf->data);
|
||||
|
||||
// Release buffer structure
|
||||
ALTHUNK_REMOVEENTRY(puiBuffers[i]);
|
||||
memset(ALBuf, 0, sizeof(ALdatabuffer));
|
||||
device->DatabufferCount--;
|
||||
free(ALBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(Context);
|
||||
}
|
||||
|
||||
/*
|
||||
* alIsDatabufferEXT(ALuint uiBuffer)
|
||||
*
|
||||
* Checks if ulBuffer is a valid Databuffer Name
|
||||
*/
|
||||
AL_API ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint uiBuffer)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean result = AL_TRUE;
|
||||
ALCdevice *device;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
device = Context->Device;
|
||||
if(uiBuffer)
|
||||
result = (VerifyDatabuffer(device->DatabufferList, uiBuffer) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
|
||||
ProcessContext(Context);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
|
||||
*
|
||||
* Fill databuffer with data
|
||||
*/
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALdatabuffer *ALBuf;
|
||||
ALCdevice *Device;
|
||||
ALvoid *temp;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if((ALBuf=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
|
||||
{
|
||||
if(ALBuf->state == UNMAPPED)
|
||||
{
|
||||
if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
|
||||
usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
|
||||
usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
|
||||
usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
|
||||
usage == AL_DYNAMIC_COPY_EXT)
|
||||
{
|
||||
if(size >= 0)
|
||||
{
|
||||
/* (Re)allocate data */
|
||||
temp = realloc(ALBuf->data, size);
|
||||
if(temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
ALBuf->size = size;
|
||||
ALBuf->usage = usage;
|
||||
if(data)
|
||||
memcpy(ALBuf->data, data, size);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_OPERATION);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
|
||||
{
|
||||
if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
|
||||
{
|
||||
if(pBuffer->state == UNMAPPED)
|
||||
memcpy(pBuffer->data+start, data, length);
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_OPERATION);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
|
||||
{
|
||||
if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
|
||||
{
|
||||
if(pBuffer->state == UNMAPPED)
|
||||
memcpy(data, pBuffer->data+start, length);
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_OPERATION);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
(void)flValue;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
(void)flValues;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
(void)lValue;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
(void)plValues;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
if(pflValue)
|
||||
{
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
if(pflValues)
|
||||
{
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
if(plValue)
|
||||
{
|
||||
Device = pContext->Device;
|
||||
if((pBuffer=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_SIZE:
|
||||
*plValue = (ALint)pBuffer->size;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
if(plValues)
|
||||
{
|
||||
Device = pContext->Device;
|
||||
if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
|
||||
{
|
||||
switch (eParam)
|
||||
{
|
||||
case AL_SIZE:
|
||||
alGetDatabufferiEXT(buffer, eParam, plValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer = NULL;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if(uiBuffer == 0 ||
|
||||
(pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
|
||||
{
|
||||
if(target == AL_SAMPLE_SOURCE_EXT)
|
||||
pContext->SampleSource = pBuffer;
|
||||
else if(target == AL_SAMPLE_SINK_EXT)
|
||||
pContext->SampleSink = pBuffer;
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer;
|
||||
ALvoid *ret = NULL;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return NULL;
|
||||
|
||||
Device = pContext->Device;
|
||||
if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
|
||||
{
|
||||
if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
|
||||
{
|
||||
if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
|
||||
access == AL_READ_WRITE_EXT)
|
||||
{
|
||||
if(pBuffer->state == UNMAPPED)
|
||||
{
|
||||
ret = pBuffer->data + start;
|
||||
pBuffer->state = MAPPED;
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_OPERATION);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALdatabuffer *pBuffer;
|
||||
ALCdevice *Device;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
Device = pContext->Device;
|
||||
if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
|
||||
{
|
||||
if(pBuffer->state == MAPPED)
|
||||
pBuffer->state = UNMAPPED;
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_OPERATION);
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(pContext);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ReleaseALDatabuffers()
|
||||
*
|
||||
* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
|
||||
*/
|
||||
ALvoid ReleaseALDatabuffers(ALCdevice *device)
|
||||
{
|
||||
while(device->DatabufferList)
|
||||
{
|
||||
ALdatabuffer *temp = device->DatabufferList;
|
||||
device->DatabufferList = temp->next;
|
||||
|
||||
// Release buffer data
|
||||
free(temp->data);
|
||||
|
||||
// Release Buffer structure
|
||||
ALTHUNK_REMOVEENTRY(temp->databuffer);
|
||||
memset(temp, 0, sizeof(ALdatabuffer));
|
||||
free(temp);
|
||||
}
|
||||
device->DatabufferCount = 0;
|
||||
}
|
||||
+1237
-971
File diff suppressed because it is too large
Load Diff
+19
-7
@@ -20,28 +20,40 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alError.h"
|
||||
|
||||
AL_API ALenum AL_APIENTRY alGetError(ALvoid)
|
||||
ALboolean TrapALError = AL_FALSE;
|
||||
|
||||
AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALenum errorCode;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_INVALID_OPERATION;
|
||||
|
||||
errorCode = Context->LastError;
|
||||
Context->LastError = AL_NO_ERROR;
|
||||
errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
|
||||
{
|
||||
if(Context->LastError == AL_NO_ERROR)
|
||||
Context->LastError = errorCode;
|
||||
if(TrapALError)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
/* DebugBreak will cause an exception if there is no debugger */
|
||||
if(IsDebuggerPresent())
|
||||
DebugBreak();
|
||||
#elif defined(SIGTRAP)
|
||||
raise(SIGTRAP);
|
||||
#endif
|
||||
}
|
||||
CompExchangeInt(&Context->LastError, AL_NO_ERROR, errorCode);
|
||||
}
|
||||
|
||||
+112
-173
@@ -29,157 +29,17 @@
|
||||
#include "alFilter.h"
|
||||
#include "alEffect.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alDatabuffer.h"
|
||||
#include "alSource.h"
|
||||
#include "alBuffer.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
typedef struct ALfunction {
|
||||
const ALchar *funcName;
|
||||
ALvoid *address;
|
||||
} ALfunction;
|
||||
|
||||
typedef struct ALenums {
|
||||
const ALchar *enumName;
|
||||
ALenum value;
|
||||
} ALenums;
|
||||
|
||||
|
||||
static const ALfunction function[] = {
|
||||
{ "alEnable", (ALvoid *) alEnable },
|
||||
{ "alDisable", (ALvoid *) alDisable },
|
||||
{ "alIsEnabled", (ALvoid *) alIsEnabled },
|
||||
{ "alGetString", (ALvoid *) alGetString },
|
||||
{ "alGetBooleanv", (ALvoid *) alGetBooleanv },
|
||||
{ "alGetIntegerv", (ALvoid *) alGetIntegerv },
|
||||
{ "alGetFloatv", (ALvoid *) alGetFloatv },
|
||||
{ "alGetDoublev", (ALvoid *) alGetDoublev },
|
||||
{ "alGetBoolean", (ALvoid *) alGetBoolean },
|
||||
{ "alGetInteger", (ALvoid *) alGetInteger },
|
||||
{ "alGetFloat", (ALvoid *) alGetFloat },
|
||||
{ "alGetDouble", (ALvoid *) alGetDouble },
|
||||
{ "alGetError", (ALvoid *) alGetError },
|
||||
{ "alIsExtensionPresent", (ALvoid *) alIsExtensionPresent },
|
||||
{ "alGetProcAddress", (ALvoid *) alGetProcAddress },
|
||||
{ "alGetEnumValue", (ALvoid *) alGetEnumValue },
|
||||
{ "alListenerf", (ALvoid *) alListenerf },
|
||||
{ "alListener3f", (ALvoid *) alListener3f },
|
||||
{ "alListenerfv", (ALvoid *) alListenerfv },
|
||||
{ "alListeneri", (ALvoid *) alListeneri },
|
||||
{ "alListener3i", (ALvoid *) alListener3i },
|
||||
{ "alListeneriv", (ALvoid *) alListeneriv },
|
||||
{ "alGetListenerf", (ALvoid *) alGetListenerf },
|
||||
{ "alGetListener3f", (ALvoid *) alGetListener3f },
|
||||
{ "alGetListenerfv", (ALvoid *) alGetListenerfv },
|
||||
{ "alGetListeneri", (ALvoid *) alGetListeneri },
|
||||
{ "alGetListener3i", (ALvoid *) alGetListener3i },
|
||||
{ "alGetListeneriv", (ALvoid *) alGetListeneriv },
|
||||
{ "alGenSources", (ALvoid *) alGenSources },
|
||||
{ "alDeleteSources", (ALvoid *) alDeleteSources },
|
||||
{ "alIsSource", (ALvoid *) alIsSource },
|
||||
{ "alSourcef", (ALvoid *) alSourcef },
|
||||
{ "alSource3f", (ALvoid *) alSource3f },
|
||||
{ "alSourcefv", (ALvoid *) alSourcefv },
|
||||
{ "alSourcei", (ALvoid *) alSourcei },
|
||||
{ "alSource3i", (ALvoid *) alSource3i },
|
||||
{ "alSourceiv", (ALvoid *) alSourceiv },
|
||||
{ "alGetSourcef", (ALvoid *) alGetSourcef },
|
||||
{ "alGetSource3f", (ALvoid *) alGetSource3f },
|
||||
{ "alGetSourcefv", (ALvoid *) alGetSourcefv },
|
||||
{ "alGetSourcei", (ALvoid *) alGetSourcei },
|
||||
{ "alGetSource3i", (ALvoid *) alGetSource3i },
|
||||
{ "alGetSourceiv", (ALvoid *) alGetSourceiv },
|
||||
{ "alSourcePlayv", (ALvoid *) alSourcePlayv },
|
||||
{ "alSourceStopv", (ALvoid *) alSourceStopv },
|
||||
{ "alSourceRewindv", (ALvoid *) alSourceRewindv },
|
||||
{ "alSourcePausev", (ALvoid *) alSourcePausev },
|
||||
{ "alSourcePlay", (ALvoid *) alSourcePlay },
|
||||
{ "alSourceStop", (ALvoid *) alSourceStop },
|
||||
{ "alSourceRewind", (ALvoid *) alSourceRewind },
|
||||
{ "alSourcePause", (ALvoid *) alSourcePause },
|
||||
{ "alSourceQueueBuffers", (ALvoid *) alSourceQueueBuffers },
|
||||
{ "alSourceUnqueueBuffers", (ALvoid *) alSourceUnqueueBuffers },
|
||||
{ "alGenBuffers", (ALvoid *) alGenBuffers },
|
||||
{ "alDeleteBuffers", (ALvoid *) alDeleteBuffers },
|
||||
{ "alIsBuffer", (ALvoid *) alIsBuffer },
|
||||
{ "alBufferData", (ALvoid *) alBufferData },
|
||||
{ "alBufferf", (ALvoid *) alBufferf },
|
||||
{ "alBuffer3f", (ALvoid *) alBuffer3f },
|
||||
{ "alBufferfv", (ALvoid *) alBufferfv },
|
||||
{ "alBufferi", (ALvoid *) alBufferi },
|
||||
{ "alBuffer3i", (ALvoid *) alBuffer3i },
|
||||
{ "alBufferiv", (ALvoid *) alBufferiv },
|
||||
{ "alGetBufferf", (ALvoid *) alGetBufferf },
|
||||
{ "alGetBuffer3f", (ALvoid *) alGetBuffer3f },
|
||||
{ "alGetBufferfv", (ALvoid *) alGetBufferfv },
|
||||
{ "alGetBufferi", (ALvoid *) alGetBufferi },
|
||||
{ "alGetBuffer3i", (ALvoid *) alGetBuffer3i },
|
||||
{ "alGetBufferiv", (ALvoid *) alGetBufferiv },
|
||||
{ "alDopplerFactor", (ALvoid *) alDopplerFactor },
|
||||
{ "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
|
||||
{ "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
|
||||
{ "alDistanceModel", (ALvoid *) alDistanceModel },
|
||||
|
||||
{ "alGenFilters", (ALvoid *) alGenFilters },
|
||||
{ "alDeleteFilters", (ALvoid *) alDeleteFilters },
|
||||
{ "alIsFilter", (ALvoid *) alIsFilter },
|
||||
{ "alFilteri", (ALvoid *) alFilteri },
|
||||
{ "alFilteriv", (ALvoid *) alFilteriv },
|
||||
{ "alFilterf", (ALvoid *) alFilterf },
|
||||
{ "alFilterfv", (ALvoid *) alFilterfv },
|
||||
{ "alGetFilteri", (ALvoid *) alGetFilteri },
|
||||
{ "alGetFilteriv", (ALvoid *) alGetFilteriv },
|
||||
{ "alGetFilterf", (ALvoid *) alGetFilterf },
|
||||
{ "alGetFilterfv", (ALvoid *) alGetFilterfv },
|
||||
|
||||
{ "alGenEffects", (ALvoid *) alGenEffects },
|
||||
{ "alDeleteEffects", (ALvoid *) alDeleteEffects },
|
||||
{ "alIsEffect", (ALvoid *) alIsEffect },
|
||||
{ "alEffecti", (ALvoid *) alEffecti },
|
||||
{ "alEffectiv", (ALvoid *) alEffectiv },
|
||||
{ "alEffectf", (ALvoid *) alEffectf },
|
||||
{ "alEffectfv", (ALvoid *) alEffectfv },
|
||||
{ "alGetEffecti", (ALvoid *) alGetEffecti },
|
||||
{ "alGetEffectiv", (ALvoid *) alGetEffectiv },
|
||||
{ "alGetEffectf", (ALvoid *) alGetEffectf },
|
||||
{ "alGetEffectfv", (ALvoid *) alGetEffectfv },
|
||||
|
||||
{ "alGenAuxiliaryEffectSlots", (ALvoid *) alGenAuxiliaryEffectSlots },
|
||||
{ "alDeleteAuxiliaryEffectSlots",(ALvoid *) alDeleteAuxiliaryEffectSlots},
|
||||
{ "alIsAuxiliaryEffectSlot", (ALvoid *) alIsAuxiliaryEffectSlot },
|
||||
{ "alAuxiliaryEffectSloti", (ALvoid *) alAuxiliaryEffectSloti },
|
||||
{ "alAuxiliaryEffectSlotiv", (ALvoid *) alAuxiliaryEffectSlotiv },
|
||||
{ "alAuxiliaryEffectSlotf", (ALvoid *) alAuxiliaryEffectSlotf },
|
||||
{ "alAuxiliaryEffectSlotfv", (ALvoid *) alAuxiliaryEffectSlotfv },
|
||||
{ "alGetAuxiliaryEffectSloti", (ALvoid *) alGetAuxiliaryEffectSloti },
|
||||
{ "alGetAuxiliaryEffectSlotiv", (ALvoid *) alGetAuxiliaryEffectSlotiv},
|
||||
{ "alGetAuxiliaryEffectSlotf", (ALvoid *) alGetAuxiliaryEffectSlotf },
|
||||
{ "alGetAuxiliaryEffectSlotfv", (ALvoid *) alGetAuxiliaryEffectSlotfv},
|
||||
|
||||
{ "alBufferSubDataEXT", (ALvoid *) alBufferSubDataEXT },
|
||||
|
||||
{ "alGenDatabuffersEXT", (ALvoid *) alGenDatabuffersEXT },
|
||||
{ "alDeleteDatabuffersEXT", (ALvoid *) alDeleteDatabuffersEXT },
|
||||
{ "alIsDatabufferEXT", (ALvoid *) alIsDatabufferEXT },
|
||||
{ "alDatabufferDataEXT", (ALvoid *) alDatabufferDataEXT },
|
||||
{ "alDatabufferSubDataEXT", (ALvoid *) alDatabufferSubDataEXT },
|
||||
{ "alGetDatabufferSubDataEXT", (ALvoid *) alGetDatabufferSubDataEXT },
|
||||
{ "alDatabufferfEXT", (ALvoid *) alDatabufferfEXT },
|
||||
{ "alDatabufferfvEXT", (ALvoid *) alDatabufferfvEXT },
|
||||
{ "alDatabufferiEXT", (ALvoid *) alDatabufferiEXT },
|
||||
{ "alDatabufferivEXT", (ALvoid *) alDatabufferivEXT },
|
||||
{ "alGetDatabufferfEXT", (ALvoid *) alGetDatabufferfEXT },
|
||||
{ "alGetDatabufferfvEXT", (ALvoid *) alGetDatabufferfvEXT },
|
||||
{ "alGetDatabufferiEXT", (ALvoid *) alGetDatabufferiEXT },
|
||||
{ "alGetDatabufferivEXT", (ALvoid *) alGetDatabufferivEXT },
|
||||
{ "alSelectDatabufferEXT", (ALvoid *) alSelectDatabufferEXT },
|
||||
{ "alMapDatabufferEXT", (ALvoid *) alMapDatabufferEXT },
|
||||
{ "alUnmapDatabufferEXT", (ALvoid *) alUnmapDatabufferEXT },
|
||||
|
||||
{ NULL, (ALvoid *) NULL }
|
||||
};
|
||||
|
||||
static const ALenums enumeration[] = {
|
||||
// Types
|
||||
{ "AL_INVALID", AL_INVALID },
|
||||
@@ -207,12 +67,15 @@ static const ALenums enumeration[] = {
|
||||
{ "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 },
|
||||
@@ -264,20 +127,70 @@ static const ALenums enumeration[] = {
|
||||
{ "AL_FORMAT_REAR16", AL_FORMAT_REAR16 },
|
||||
{ "AL_FORMAT_REAR32", AL_FORMAT_REAR32 },
|
||||
{ "AL_FORMAT_MONO_MULAW", AL_FORMAT_MONO_MULAW },
|
||||
{ "AL_FORMAT_MONO_MULAW_EXT", AL_FORMAT_MONO_MULAW },
|
||||
{ "AL_FORMAT_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 },
|
||||
{ "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 },
|
||||
@@ -303,6 +216,8 @@ static const ALenums enumeration[] = {
|
||||
{ "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 },
|
||||
@@ -340,11 +255,15 @@ static const ALenums enumeration[] = {
|
||||
{ "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 },
|
||||
@@ -393,68 +312,88 @@ static const ALenums enumeration[] = {
|
||||
{ "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 },
|
||||
{ "reverb", REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB },
|
||||
{ "echo", ECHO, "AL_EFFECT_ECHO", AL_EFFECT_ECHO },
|
||||
{ "modulator", MODULATOR, "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
|
||||
{ "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
|
||||
{ "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE },
|
||||
{ NULL, 0, NULL, (ALenum)0 }
|
||||
};
|
||||
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
|
||||
{
|
||||
ALboolean bIsSupported = AL_FALSE;
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return AL_FALSE;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
if(!extName)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
ProcessContext(pContext);
|
||||
return AL_FALSE;
|
||||
}
|
||||
|
||||
len = strlen(extName);
|
||||
ptr = pContext->ExtensionList;
|
||||
while(ptr && *ptr)
|
||||
{
|
||||
if(strncasecmp(ptr, extName, len) == 0 &&
|
||||
(ptr[len] == '\0' || isspace(ptr[len])))
|
||||
len = strlen(extName);
|
||||
ptr = Context->ExtensionList;
|
||||
while(ptr && *ptr)
|
||||
{
|
||||
bIsSupported = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
if((ptr=strchr(ptr, ' ')) != NULL)
|
||||
{
|
||||
do {
|
||||
++ptr;
|
||||
} while(isspace(*ptr));
|
||||
if(strncasecmp(ptr, extName, len) == 0 &&
|
||||
(ptr[len] == '\0' || isspace(ptr[len])))
|
||||
{
|
||||
bIsSupported = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
if((ptr=strchr(ptr, ' ')) != NULL)
|
||||
{
|
||||
do {
|
||||
++ptr;
|
||||
} while(isspace(*ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
return bIsSupported;
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName)
|
||||
{
|
||||
ALsizei i = 0;
|
||||
|
||||
while(function[i].funcName && strcmp(function[i].funcName, funcName) != 0)
|
||||
i++;
|
||||
|
||||
return function[i].address;
|
||||
if(!funcName)
|
||||
return NULL;
|
||||
return alcGetProcAddress(NULL, funcName);
|
||||
}
|
||||
|
||||
AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName)
|
||||
{
|
||||
ALsizei i = 0;
|
||||
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++;
|
||||
|
||||
+239
-199
@@ -32,134 +32,110 @@
|
||||
|
||||
static void InitFilterParams(ALfilter *filter, ALenum type);
|
||||
|
||||
DECL_VERIFIER(Filter, ALfilter, filter)
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALsizei i=0;
|
||||
ALsizei i;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if (n > 0)
|
||||
if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
ALCdevice *device = Context->Device;
|
||||
ALenum err;
|
||||
|
||||
// Check that enough memory has been allocted in the 'filters' array for n Filters
|
||||
if (!IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
ALfilter *end;
|
||||
ALfilter **list = &device->FilterList;
|
||||
while(*list)
|
||||
list = &(*list)->next;
|
||||
|
||||
end = *list;
|
||||
while(i < n)
|
||||
ALfilter *filter = calloc(1, sizeof(ALfilter));
|
||||
if(!filter)
|
||||
{
|
||||
*list = calloc(1, sizeof(ALfilter));
|
||||
if(!(*list))
|
||||
{
|
||||
while(end->next)
|
||||
{
|
||||
ALfilter *temp = end->next;
|
||||
end->next = temp->next;
|
||||
|
||||
ALTHUNK_REMOVEENTRY(temp->filter);
|
||||
device->FilterCount--;
|
||||
free(temp);
|
||||
}
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
break;
|
||||
}
|
||||
|
||||
filters[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
(*list)->filter = filters[i];
|
||||
|
||||
InitFilterParams(*list, AL_FILTER_NULL);
|
||||
device->FilterCount++;
|
||||
i++;
|
||||
|
||||
list = &(*list)->next;
|
||||
alSetError(Context, AL_OUT_OF_MEMORY);
|
||||
alDeleteFilters(i, filters);
|
||||
break;
|
||||
}
|
||||
InitFilterParams(filter, AL_FILTER_NULL);
|
||||
|
||||
err = NewThunkEntry(&filter->filter);
|
||||
if(err == AL_NO_ERROR)
|
||||
err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
FreeThunkEntry(filter->filter);
|
||||
memset(filter, 0, sizeof(ALfilter));
|
||||
free(filter);
|
||||
|
||||
alSetError(Context, err);
|
||||
alDeleteFilters(i, filters);
|
||||
break;
|
||||
}
|
||||
|
||||
filters[i] = filter->filter;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALCdevice *device;
|
||||
ALfilter *ALFilter;
|
||||
ALsizei i;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if (n >= 0)
|
||||
device = Context->Device;
|
||||
if(n < 0)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
else
|
||||
{
|
||||
ALCdevice *device = Context->Device;
|
||||
|
||||
// Check that all filters are valid
|
||||
for (i = 0; i < n; i++)
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(!filters[i])
|
||||
continue;
|
||||
|
||||
if(!VerifyFilter(device->FilterList, filters[i]))
|
||||
if(LookupFilter(device, filters[i]) == NULL)
|
||||
{
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == n)
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
// All filters are valid
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Recheck that the filter is valid, because there could be duplicated names
|
||||
if((ALFilter=VerifyFilter(device->FilterList, filters[i])) != NULL)
|
||||
{
|
||||
ALfilter **list;
|
||||
// Recheck that the filter is valid, because there could be duplicated names
|
||||
if((ALFilter=RemoveFilter(device, filters[i])) == NULL)
|
||||
continue;
|
||||
FreeThunkEntry(ALFilter->filter);
|
||||
|
||||
// Remove Source from list of Sources
|
||||
list = &device->FilterList;
|
||||
while(*list && *list != ALFilter)
|
||||
list = &(*list)->next;
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
ALTHUNK_REMOVEENTRY(ALFilter->filter);
|
||||
|
||||
memset(ALFilter, 0, sizeof(ALfilter));
|
||||
free(ALFilter);
|
||||
|
||||
device->FilterCount--;
|
||||
}
|
||||
}
|
||||
memset(ALFilter, 0, sizeof(ALfilter));
|
||||
free(ALFilter);
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean result = AL_TRUE;
|
||||
ALboolean result;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
if(filter)
|
||||
result = (VerifyFilter(Context->Device->FilterList, filter) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
result = ((!filter || LookupFilter(Context->Device, filter)) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -170,59 +146,59 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if((ALFilter=VerifyFilter(Device->FilterList, filter)) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
if(iValue == AL_FILTER_NULL ||
|
||||
iValue == AL_FILTER_LOWPASS)
|
||||
if(iValue == AL_FILTER_NULL || iValue == AL_FILTER_LOWPASS)
|
||||
InitFilterParams(ALFilter, iValue);
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParami(ALFilter, Context, param, iValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
alFilteri(filter, param, piValues[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if(VerifyFilter(Device->FilterList, filter) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
alFilteri(filter, param, piValues[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamiv(ALFilter, Context, param, piValues);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
|
||||
@@ -231,70 +207,40 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if((ALFilter=VerifyFilter(Device->FilterList, filter)) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(ALFilter->type)
|
||||
{
|
||||
case AL_FILTER_LOWPASS:
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
ALFilter->Gain = flValue;
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
ALFilter->GainHF = flValue;
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamf(ALFilter, Context, param, flValue);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if(VerifyFilter(Device->FilterList, filter) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alFilterf(filter, param, pflValues[0]);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_SetParamfv(ALFilter, Context, param, pflValues);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
|
||||
@@ -303,11 +249,11 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piVal
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if((ALFilter=VerifyFilter(Device->FilterList, filter)) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -316,42 +262,43 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piVal
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParami(ALFilter, Context, param, piValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
alGetFilteri(filter, param, piValues);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if(VerifyFilter(Device->FilterList, filter) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
alGetFilteri(filter, param, piValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamiv(ALFilter, Context, param, piValues);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
|
||||
@@ -360,87 +307,180 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pfl
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if((ALFilter=VerifyFilter(Device->FilterList, filter)) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(ALFilter->type)
|
||||
{
|
||||
case AL_FILTER_LOWPASS:
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
*pflValue = ALFilter->Gain;
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
*pflValue = ALFilter->GainHF;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamf(ALFilter, Context, param, pflValue);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALCdevice *Device;
|
||||
ALfilter *ALFilter;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
Device = Context->Device;
|
||||
if(VerifyFilter(Device->FilterList, filter) != NULL)
|
||||
if((ALFilter=LookupFilter(Device, filter)) != NULL)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alGetFilterf(filter, param, pflValues);
|
||||
break;
|
||||
}
|
||||
/* Call the appropriate handler */
|
||||
ALfilter_GetParamfv(ALFilter, Context, param, pflValues);
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_NAME);
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
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 */
|
||||
{
|
||||
g = maxf(g, 0.001f);
|
||||
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
|
||||
(1 - g);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
static void lp_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void lp_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)
|
||||
filter->Gain = val;
|
||||
else
|
||||
alSetError(context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
if(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)
|
||||
filter->GainHF = val;
|
||||
else
|
||||
alSetError(context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
|
||||
{
|
||||
lp_SetParamf(filter, context, param, vals[0]);
|
||||
}
|
||||
|
||||
static void lp_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void lp_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
*val = filter->Gain;
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
*val = filter->GainHF;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
|
||||
{
|
||||
lp_GetParamf(filter, context, param, vals);
|
||||
}
|
||||
|
||||
|
||||
static void null_SetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_SetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
|
||||
static void null_GetParami(ALfilter *filter, ALCcontext *context, ALenum param, ALint *val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_GetParamiv(ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
|
||||
{ (void)filter;(void)param;(void)val; alSetError(context, AL_INVALID_ENUM); }
|
||||
static void null_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
|
||||
{ (void)filter;(void)param;(void)vals; alSetError(context, AL_INVALID_ENUM); }
|
||||
|
||||
|
||||
ALvoid ReleaseALFilters(ALCdevice *device)
|
||||
{
|
||||
while(device->FilterList)
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->FilterMap.size;i++)
|
||||
{
|
||||
ALfilter *temp = device->FilterList;
|
||||
device->FilterList = temp->next;
|
||||
ALfilter *temp = device->FilterMap.array[i].value;
|
||||
device->FilterMap.array[i].value = NULL;
|
||||
|
||||
// Release filter structure
|
||||
ALTHUNK_REMOVEENTRY(temp->filter);
|
||||
FreeThunkEntry(temp->filter);
|
||||
memset(temp, 0, sizeof(ALfilter));
|
||||
free(temp);
|
||||
}
|
||||
device->FilterCount = 0;
|
||||
}
|
||||
|
||||
|
||||
static void InitFilterParams(ALfilter *filter, ALenum type)
|
||||
{
|
||||
filter->type = type;
|
||||
if(type == AL_FILTER_LOWPASS)
|
||||
{
|
||||
filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
|
||||
filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
|
||||
|
||||
filter->Gain = 1.0;
|
||||
filter->GainHF = 1.0;
|
||||
filter->SetParami = lp_SetParami;
|
||||
filter->SetParamiv = lp_SetParamiv;
|
||||
filter->SetParamf = lp_SetParamf;
|
||||
filter->SetParamfv = lp_SetParamfv;
|
||||
filter->GetParami = lp_GetParami;
|
||||
filter->GetParamiv = lp_GetParamiv;
|
||||
filter->GetParamf = lp_GetParamf;
|
||||
filter->GetParamfv = lp_GetParamfv;
|
||||
}
|
||||
else
|
||||
{
|
||||
filter->SetParami = null_SetParami;
|
||||
filter->SetParamiv = null_SetParamiv;
|
||||
filter->SetParamf = null_SetParamf;
|
||||
filter->SetParamfv = null_SetParamfv;
|
||||
filter->GetParami = null_GetParami;
|
||||
filter->GetParamiv = null_GetParamiv;
|
||||
filter->GetParamf = null_GetParamf;
|
||||
filter->GetParamfv = null_GetParamfv;
|
||||
}
|
||||
filter->type = type;
|
||||
}
|
||||
|
||||
+228
-199
@@ -28,106 +28,91 @@
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alListenerf(ALenum eParam, ALfloat flValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALboolean updateAll = AL_FALSE;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_GAIN:
|
||||
if(flValue >= 0.0f)
|
||||
if(flValue >= 0.0f && isfinite(flValue))
|
||||
{
|
||||
pContext->Listener.Gain = flValue;
|
||||
updateAll = AL_TRUE;
|
||||
Context->Listener.Gain = flValue;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_METERS_PER_UNIT:
|
||||
if(flValue > 0.0f)
|
||||
if(flValue > 0.0f && isfinite(flValue))
|
||||
{
|
||||
pContext->Listener.MetersPerUnit = flValue;
|
||||
updateAll = AL_TRUE;
|
||||
Context->Listener.MetersPerUnit = flValue;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
// Force updating the sources for these parameters, since even head-
|
||||
// relative sources are affected
|
||||
if(updateAll)
|
||||
{
|
||||
ALsource *source = pContext->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALboolean updateWorld = AL_FALSE;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
pContext->Listener.Position[0] = flValue1;
|
||||
pContext->Listener.Position[1] = flValue2;
|
||||
pContext->Listener.Position[2] = flValue3;
|
||||
updateWorld = AL_TRUE;
|
||||
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:
|
||||
pContext->Listener.Velocity[0] = flValue1;
|
||||
pContext->Listener.Velocity[1] = flValue2;
|
||||
pContext->Listener.Velocity[2] = flValue3;
|
||||
updateWorld = AL_TRUE;
|
||||
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(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
if(updateWorld)
|
||||
{
|
||||
ALsource *source = pContext->SourceList;
|
||||
while(source)
|
||||
{
|
||||
if(!source->bHeadRelative)
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALboolean updateWorld = AL_FALSE;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
ALCcontext *Context;
|
||||
|
||||
if(pflValues)
|
||||
{
|
||||
@@ -136,109 +121,143 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
|
||||
case AL_GAIN:
|
||||
case AL_METERS_PER_UNIT:
|
||||
alListenerf(eParam, pflValues[0]);
|
||||
break;
|
||||
return;
|
||||
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(pflValues)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_ORIENTATION:
|
||||
// AT then UP
|
||||
pContext->Listener.Forward[0] = pflValues[0];
|
||||
pContext->Listener.Forward[1] = pflValues[1];
|
||||
pContext->Listener.Forward[2] = pflValues[2];
|
||||
pContext->Listener.Up[0] = pflValues[3];
|
||||
pContext->Listener.Up[1] = pflValues[4];
|
||||
pContext->Listener.Up[2] = pflValues[5];
|
||||
updateWorld = AL_TRUE;
|
||||
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(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
if(updateWorld)
|
||||
{
|
||||
ALsource *source = pContext->SourceList;
|
||||
while(source)
|
||||
{
|
||||
if(!source->bHeadRelative)
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alListeneri(ALenum eParam, ALint lValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
(void)lValue;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
ALCcontext *Context;
|
||||
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
ALfloat flValues[6];
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
|
||||
if(plValues)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
flValues[0] = (ALfloat)plValues[0];
|
||||
flValues[1] = (ALfloat)plValues[1];
|
||||
flValues[2] = (ALfloat)plValues[2];
|
||||
alListenerfv(eParam, flValues);
|
||||
break;
|
||||
alListener3f(eParam, (ALfloat)plValues[0], (ALfloat)plValues[1], (ALfloat)plValues[2]);
|
||||
return;
|
||||
|
||||
case AL_ORIENTATION:
|
||||
flValues[0] = (ALfloat)plValues[0];
|
||||
@@ -248,237 +267,247 @@ AL_API void AL_APIENTRY alListeneriv( ALenum eParam, const ALint* plValues )
|
||||
flValues[4] = (ALfloat)plValues[4];
|
||||
flValues[5] = (ALfloat)plValues[5];
|
||||
alListenerfv(eParam, flValues);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(plValues)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(pflValue)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_GAIN:
|
||||
*pflValue = pContext->Listener.Gain;
|
||||
*pflValue = Context->Listener.Gain;
|
||||
break;
|
||||
|
||||
case AL_METERS_PER_UNIT:
|
||||
*pflValue = pContext->Listener.MetersPerUnit;
|
||||
*pflValue = Context->Listener.MetersPerUnit;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(pflValue1 && pflValue2 && pflValue3)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
*pflValue1 = pContext->Listener.Position[0];
|
||||
*pflValue2 = pContext->Listener.Position[1];
|
||||
*pflValue3 = pContext->Listener.Position[2];
|
||||
LockContext(Context);
|
||||
*pflValue1 = Context->Listener.Position[0];
|
||||
*pflValue2 = Context->Listener.Position[1];
|
||||
*pflValue3 = Context->Listener.Position[2];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
*pflValue1 = pContext->Listener.Velocity[0];
|
||||
*pflValue2 = pContext->Listener.Velocity[1];
|
||||
*pflValue3 = pContext->Listener.Velocity[2];
|
||||
LockContext(Context);
|
||||
*pflValue1 = Context->Listener.Velocity[0];
|
||||
*pflValue2 = Context->Listener.Velocity[1];
|
||||
*pflValue3 = Context->Listener.Velocity[2];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_GAIN:
|
||||
case AL_METERS_PER_UNIT:
|
||||
alGetListenerf(eParam, pflValues);
|
||||
return;
|
||||
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alGetListener3f(eParam, pflValues+0, pflValues+1, pflValues+2);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(pflValues)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_GAIN:
|
||||
pflValues[0] = pContext->Listener.Gain;
|
||||
break;
|
||||
|
||||
case AL_METERS_PER_UNIT:
|
||||
pflValues[0] = pContext->Listener.MetersPerUnit;
|
||||
break;
|
||||
|
||||
case AL_POSITION:
|
||||
pflValues[0] = pContext->Listener.Position[0];
|
||||
pflValues[1] = pContext->Listener.Position[1];
|
||||
pflValues[2] = pContext->Listener.Position[2];
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
pflValues[0] = pContext->Listener.Velocity[0];
|
||||
pflValues[1] = pContext->Listener.Velocity[1];
|
||||
pflValues[2] = pContext->Listener.Velocity[2];
|
||||
break;
|
||||
|
||||
case AL_ORIENTATION:
|
||||
LockContext(Context);
|
||||
// AT then UP
|
||||
pflValues[0] = pContext->Listener.Forward[0];
|
||||
pflValues[1] = pContext->Listener.Forward[1];
|
||||
pflValues[2] = pContext->Listener.Forward[2];
|
||||
pflValues[3] = pContext->Listener.Up[0];
|
||||
pflValues[4] = pContext->Listener.Up[1];
|
||||
pflValues[5] = pContext->Listener.Up[2];
|
||||
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];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum eParam, ALint *plValue)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(plValue)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(plValue1 && plValue2 && plValue3)
|
||||
{
|
||||
switch (eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
*plValue1 = (ALint)pContext->Listener.Position[0];
|
||||
*plValue2 = (ALint)pContext->Listener.Position[1];
|
||||
*plValue3 = (ALint)pContext->Listener.Position[2];
|
||||
LockContext(Context);
|
||||
*plValue1 = (ALint)Context->Listener.Position[0];
|
||||
*plValue2 = (ALint)Context->Listener.Position[1];
|
||||
*plValue3 = (ALint)Context->Listener.Position[2];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
*plValue1 = (ALint)pContext->Listener.Velocity[0];
|
||||
*plValue2 = (ALint)pContext->Listener.Velocity[1];
|
||||
*plValue3 = (ALint)pContext->Listener.Velocity[2];
|
||||
LockContext(Context);
|
||||
*plValue1 = (ALint)Context->Listener.Velocity[0];
|
||||
*plValue2 = (ALint)Context->Listener.Velocity[1];
|
||||
*plValue3 = (ALint)Context->Listener.Velocity[2];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alGetListeneriv(ALenum eParam, ALint* plValues)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
case AL_VELOCITY:
|
||||
alGetListener3i(eParam, plValues+0, plValues+1, plValues+2);
|
||||
return;
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(plValues)
|
||||
{
|
||||
switch(eParam)
|
||||
{
|
||||
case AL_POSITION:
|
||||
plValues[0] = (ALint)pContext->Listener.Position[0];
|
||||
plValues[1] = (ALint)pContext->Listener.Position[1];
|
||||
plValues[2] = (ALint)pContext->Listener.Position[2];
|
||||
break;
|
||||
|
||||
case AL_VELOCITY:
|
||||
plValues[0] = (ALint)pContext->Listener.Velocity[0];
|
||||
plValues[1] = (ALint)pContext->Listener.Velocity[1];
|
||||
plValues[2] = (ALint)pContext->Listener.Velocity[2];
|
||||
break;
|
||||
|
||||
case AL_ORIENTATION:
|
||||
LockContext(Context);
|
||||
// AT then UP
|
||||
plValues[0] = (ALint)pContext->Listener.Forward[0];
|
||||
plValues[1] = (ALint)pContext->Listener.Forward[1];
|
||||
plValues[2] = (ALint)pContext->Listener.Forward[2];
|
||||
plValues[3] = (ALint)pContext->Listener.Up[0];
|
||||
plValues[4] = (ALint)pContext->Listener.Up[1];
|
||||
plValues[5] = (ALint)pContext->Listener.Up[2];
|
||||
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];
|
||||
UnlockContext(Context);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
+880
-773
File diff suppressed because it is too large
Load Diff
+204
-203
@@ -26,8 +26,8 @@
|
||||
#include "AL/alext.h"
|
||||
#include "alError.h"
|
||||
#include "alSource.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alState.h"
|
||||
#include "alDatabuffer.h"
|
||||
|
||||
static const ALchar alVendor[] = "OpenAL Community";
|
||||
static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
|
||||
@@ -44,16 +44,15 @@ static const ALchar alErrOutOfMemory[] = "Out of Memory";
|
||||
AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
case AL_SOURCE_DISTANCE_MODEL:
|
||||
Context->SourceDistanceModel = AL_TRUE;
|
||||
updateSources = AL_TRUE;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -61,32 +60,21 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
|
||||
break;
|
||||
}
|
||||
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
case AL_SOURCE_DISTANCE_MODEL:
|
||||
Context->SourceDistanceModel = AL_FALSE;
|
||||
updateSources = AL_TRUE;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -94,17 +82,7 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
|
||||
break;
|
||||
}
|
||||
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
|
||||
@@ -112,7 +90,7 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
|
||||
ALCcontext *Context;
|
||||
ALboolean value=AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
switch(capability)
|
||||
@@ -126,7 +104,7 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -136,7 +114,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
|
||||
ALCcontext *Context;
|
||||
ALboolean value=AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return AL_FALSE;
|
||||
|
||||
switch(pname)
|
||||
@@ -161,12 +139,16 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
|
||||
value = AL_TRUE;
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = Context->DeferUpdates;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -176,7 +158,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
|
||||
ALCcontext *Context;
|
||||
ALdouble value = 0.0;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return 0.0;
|
||||
|
||||
switch(pname)
|
||||
@@ -197,12 +179,16 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
|
||||
value = (double)Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALdouble)Context->DeferUpdates;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -212,7 +198,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
|
||||
ALCcontext *Context;
|
||||
ALfloat value = 0.0f;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return 0.0f;
|
||||
|
||||
switch(pname)
|
||||
@@ -233,12 +219,16 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
|
||||
value = Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALfloat)Context->DeferUpdates;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -248,7 +238,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
||||
ALCcontext *Context;
|
||||
ALint value = 0;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return 0;
|
||||
|
||||
switch(pname)
|
||||
@@ -269,18 +259,8 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
||||
value = (ALint)Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_SOURCE_EXT:
|
||||
if(Context->SampleSource)
|
||||
value = (ALint)Context->SampleSource->databuffer;
|
||||
else
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_SINK_EXT:
|
||||
if(Context->SampleSink)
|
||||
value = (ALint)Context->SampleSink->databuffer;
|
||||
else
|
||||
value = 0;
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
value = (ALint)Context->DeferUpdates;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -288,7 +268,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -297,29 +277,27 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
*data = alGetBoolean(pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*data = (ALboolean)((Context->DopplerFactor != 0.0f) ? AL_TRUE : AL_FALSE);
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
*data = (ALboolean)((Context->DopplerVelocity != 0.0f) ? AL_TRUE : AL_FALSE);
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
*data = (ALboolean)((Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) ? AL_TRUE : AL_FALSE);
|
||||
break;
|
||||
|
||||
case AL_SPEED_OF_SOUND:
|
||||
*data = (ALboolean)((Context->flSpeedOfSound != 0.0f) ? AL_TRUE : AL_FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -331,36 +309,34 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
*data = alGetDouble(pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*data = (double)Context->DopplerFactor;
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
*data = (double)Context->DopplerVelocity;
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
*data = (double)Context->DistanceModel;
|
||||
break;
|
||||
|
||||
case AL_SPEED_OF_SOUND:
|
||||
*data = (double)Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -372,36 +348,34 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
*data = alGetFloat(pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*data = Context->DopplerFactor;
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
*data = Context->DopplerVelocity;
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
*data = (float)Context->DistanceModel;
|
||||
break;
|
||||
|
||||
case AL_SPEED_OF_SOUND:
|
||||
*data = Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -413,50 +387,34 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
case AL_DISTANCE_MODEL:
|
||||
case AL_SPEED_OF_SOUND:
|
||||
case AL_DEFERRED_UPDATES_SOFT:
|
||||
*data = alGetInteger(pname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(data)
|
||||
{
|
||||
switch(pname)
|
||||
{
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*data = (ALint)Context->DopplerFactor;
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_VELOCITY:
|
||||
*data = (ALint)Context->DopplerVelocity;
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
*data = (ALint)Context->DistanceModel;
|
||||
break;
|
||||
|
||||
case AL_SPEED_OF_SOUND:
|
||||
*data = (ALint)Context->flSpeedOfSound;
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_SOURCE_EXT:
|
||||
if(Context->SampleSource)
|
||||
*data = (ALint)Context->SampleSource->databuffer;
|
||||
else
|
||||
*data = 0;
|
||||
break;
|
||||
|
||||
case AL_SAMPLE_SINK_EXT:
|
||||
if(Context->SampleSink)
|
||||
*data = (ALint)Context->SampleSink->databuffer;
|
||||
else
|
||||
*data = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -468,16 +426,16 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data)
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
||||
{
|
||||
const ALchar *value;
|
||||
ALCcontext *pContext;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return NULL;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return NULL;
|
||||
|
||||
switch(pname)
|
||||
{
|
||||
@@ -494,7 +452,7 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
||||
break;
|
||||
|
||||
case AL_EXTENSIONS:
|
||||
value=pContext->ExtensionList;//alExtensions;
|
||||
value=Context->ExtensionList;
|
||||
break;
|
||||
|
||||
case AL_NO_ERROR:
|
||||
@@ -523,11 +481,11 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
||||
|
||||
default:
|
||||
value=NULL;
|
||||
alSetError(pContext, AL_INVALID_ENUM);
|
||||
alSetError(Context, AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -535,98 +493,62 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
||||
AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(value >= 0.0f)
|
||||
if(value >= 0.0f && isfinite(value))
|
||||
{
|
||||
Context->DopplerFactor = value;
|
||||
updateSources = AL_TRUE;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
// Force updating the sources for these parameters, since even head-
|
||||
// relative sources are affected
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(value > 0.0f)
|
||||
if(value > 0.0f && isfinite(value))
|
||||
{
|
||||
Context->DopplerVelocity=value;
|
||||
updateSources = AL_TRUE;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
ALCcontext *Context;
|
||||
|
||||
pContext = GetContextSuspended();
|
||||
if(!pContext) return;
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(flSpeedOfSound > 0.0f)
|
||||
if(flSpeedOfSound > 0.0f && isfinite(flSpeedOfSound))
|
||||
{
|
||||
pContext->flSpeedOfSound = flSpeedOfSound;
|
||||
updateSources = AL_TRUE;
|
||||
Context->flSpeedOfSound = flSpeedOfSound;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
}
|
||||
else
|
||||
alSetError(pContext, AL_INVALID_VALUE);
|
||||
alSetError(Context, AL_INVALID_VALUE);
|
||||
|
||||
if(updateSources)
|
||||
{
|
||||
ALsource *source = pContext->SourceList;
|
||||
while(source)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessContext(pContext);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALboolean updateSources = AL_FALSE;
|
||||
|
||||
Context = GetContextSuspended();
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
switch(value)
|
||||
@@ -639,7 +561,7 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
|
||||
case AL_EXPONENT_DISTANCE:
|
||||
case AL_EXPONENT_DISTANCE_CLAMPED:
|
||||
Context->DistanceModel = value;
|
||||
updateSources = !Context->SourceDistanceModel;
|
||||
Context->UpdateSources = AL_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -647,15 +569,94 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
|
||||
break;
|
||||
}
|
||||
|
||||
if(updateSources)
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(!Context->DeferUpdates)
|
||||
{
|
||||
ALsource *source = Context->SourceList;
|
||||
while(source)
|
||||
ALboolean UpdateSources;
|
||||
ALsource **src, **src_end;
|
||||
ALeffectslot **slot, **slot_end;
|
||||
int fpuState;
|
||||
|
||||
fpuState = SetMixerFPUMode();
|
||||
|
||||
LockContext(Context);
|
||||
Context->DeferUpdates = AL_TRUE;
|
||||
|
||||
/* Make sure all pending updates are performed */
|
||||
UpdateSources = ExchangeInt(&Context->UpdateSources, AL_FALSE);
|
||||
|
||||
src = Context->ActiveSources;
|
||||
src_end = src + Context->ActiveSourceCount;
|
||||
while(src != src_end)
|
||||
{
|
||||
source->NeedsUpdate = AL_TRUE;
|
||||
source = source->next;
|
||||
if((*src)->state != AL_PLAYING)
|
||||
{
|
||||
Context->ActiveSourceCount--;
|
||||
*src = *(--src_end);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || UpdateSources)
|
||||
ALsource_Update(*src, Context);
|
||||
|
||||
src++;
|
||||
}
|
||||
|
||||
slot = Context->ActiveEffectSlots;
|
||||
slot_end = slot + Context->ActiveEffectSlotCount;
|
||||
while(slot != slot_end)
|
||||
{
|
||||
if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
|
||||
ALeffectState_Update((*slot)->EffectState, Context->Device, *slot);
|
||||
slot++;
|
||||
}
|
||||
|
||||
UnlockContext(Context);
|
||||
RestoreFPUMode(fpuState);
|
||||
}
|
||||
|
||||
ProcessContext(Context);
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
Context = GetContextRef();
|
||||
if(!Context) return;
|
||||
|
||||
if(ExchangeInt(&Context->DeferUpdates, AL_FALSE))
|
||||
{
|
||||
ALsizei pos;
|
||||
|
||||
LockContext(Context);
|
||||
LockUIntMapRead(&Context->SourceMap);
|
||||
for(pos = 0;pos < Context->SourceMap.size;pos++)
|
||||
{
|
||||
ALsource *Source = Context->SourceMap.array[pos].value;
|
||||
ALenum new_state;
|
||||
|
||||
if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
|
||||
Source->lOffset != -1)
|
||||
ApplyOffset(Source);
|
||||
|
||||
new_state = ExchangeInt(&Source->new_state, AL_NONE);
|
||||
if(new_state)
|
||||
SetSourceState(Source, Context, new_state);
|
||||
}
|
||||
UnlockUIntMapRead(&Context->SourceMap);
|
||||
UnlockContext(Context);
|
||||
}
|
||||
|
||||
ALCcontext_DecRef(Context);
|
||||
}
|
||||
|
||||
+41
-63
@@ -25,87 +25,65 @@
|
||||
#include "alMain.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
typedef struct {
|
||||
ALvoid *ptr;
|
||||
ALboolean InUse;
|
||||
} ThunkEntry;
|
||||
|
||||
static ThunkEntry *g_ThunkArray;
|
||||
static ALuint g_ThunkArraySize;
|
||||
static ALenum *ThunkArray;
|
||||
static ALuint ThunkArraySize;
|
||||
static RWLock ThunkLock;
|
||||
|
||||
static CRITICAL_SECTION g_ThunkLock;
|
||||
|
||||
void alThunkInit(void)
|
||||
void ThunkInit(void)
|
||||
{
|
||||
InitializeCriticalSection(&g_ThunkLock);
|
||||
g_ThunkArraySize = 1;
|
||||
g_ThunkArray = calloc(1, g_ThunkArraySize * sizeof(ThunkEntry));
|
||||
RWLockInit(&ThunkLock);
|
||||
ThunkArraySize = 1;
|
||||
ThunkArray = calloc(1, ThunkArraySize * sizeof(*ThunkArray));
|
||||
}
|
||||
|
||||
void alThunkExit(void)
|
||||
void ThunkExit(void)
|
||||
{
|
||||
free(g_ThunkArray);
|
||||
g_ThunkArray = NULL;
|
||||
g_ThunkArraySize = 0;
|
||||
DeleteCriticalSection(&g_ThunkLock);
|
||||
free(ThunkArray);
|
||||
ThunkArray = NULL;
|
||||
ThunkArraySize = 0;
|
||||
}
|
||||
|
||||
ALuint alThunkAddEntry(ALvoid *ptr)
|
||||
ALenum NewThunkEntry(ALuint *index)
|
||||
{
|
||||
ALuint index;
|
||||
ALenum *NewList;
|
||||
ALuint i;
|
||||
|
||||
EnterCriticalSection(&g_ThunkLock);
|
||||
|
||||
for(index = 0;index < g_ThunkArraySize;index++)
|
||||
ReadLock(&ThunkLock);
|
||||
for(i = 0;i < ThunkArraySize;i++)
|
||||
{
|
||||
if(g_ThunkArray[index].InUse == AL_FALSE)
|
||||
break;
|
||||
}
|
||||
|
||||
if(index == g_ThunkArraySize)
|
||||
{
|
||||
ThunkEntry *NewList;
|
||||
|
||||
NewList = realloc(g_ThunkArray, g_ThunkArraySize*2 * sizeof(ThunkEntry));
|
||||
if(!NewList)
|
||||
if(ExchangeInt(&ThunkArray[i], AL_TRUE) == AL_FALSE)
|
||||
{
|
||||
LeaveCriticalSection(&g_ThunkLock);
|
||||
AL_PRINT("Realloc failed to increase to %u enties!\n", g_ThunkArraySize*2);
|
||||
return 0;
|
||||
ReadUnlock(&ThunkLock);
|
||||
*index = i+1;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
memset(&NewList[g_ThunkArraySize], 0, g_ThunkArraySize*sizeof(ThunkEntry));
|
||||
g_ThunkArraySize *= 2;
|
||||
g_ThunkArray = NewList;
|
||||
}
|
||||
ReadUnlock(&ThunkLock);
|
||||
|
||||
g_ThunkArray[index].ptr = ptr;
|
||||
g_ThunkArray[index].InUse = AL_TRUE;
|
||||
WriteLock(&ThunkLock);
|
||||
NewList = realloc(ThunkArray, ThunkArraySize*2 * sizeof(*ThunkArray));
|
||||
if(!NewList)
|
||||
{
|
||||
WriteUnlock(&ThunkLock);
|
||||
ERR("Realloc failed to increase to %u enties!\n", ThunkArraySize*2);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
memset(&NewList[ThunkArraySize], 0, ThunkArraySize*sizeof(*ThunkArray));
|
||||
ThunkArraySize *= 2;
|
||||
ThunkArray = NewList;
|
||||
|
||||
LeaveCriticalSection(&g_ThunkLock);
|
||||
ThunkArray[i] = AL_TRUE;
|
||||
WriteUnlock(&ThunkLock);
|
||||
|
||||
return index+1;
|
||||
*index = i+1;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
void alThunkRemoveEntry(ALuint index)
|
||||
void FreeThunkEntry(ALuint index)
|
||||
{
|
||||
EnterCriticalSection(&g_ThunkLock);
|
||||
|
||||
if(index > 0 && index <= g_ThunkArraySize)
|
||||
g_ThunkArray[index-1].InUse = AL_FALSE;
|
||||
|
||||
LeaveCriticalSection(&g_ThunkLock);
|
||||
}
|
||||
|
||||
ALvoid *alThunkLookupEntry(ALuint index)
|
||||
{
|
||||
ALvoid *ptr = NULL;
|
||||
|
||||
EnterCriticalSection(&g_ThunkLock);
|
||||
|
||||
if(index > 0 && index <= g_ThunkArraySize)
|
||||
ptr = g_ThunkArray[index-1].ptr;
|
||||
|
||||
LeaveCriticalSection(&g_ThunkLock);
|
||||
|
||||
return ptr;
|
||||
ReadLock(&ThunkLock);
|
||||
if(index > 0 && index <= ThunkArraySize)
|
||||
ExchangeInt(&ThunkArray[index-1], AL_FALSE);
|
||||
ReadUnlock(&ThunkLock);
|
||||
}
|
||||
|
||||
@@ -18,3 +18,36 @@ backends were enabled.
|
||||
For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
|
||||
were detected (if your target system uses them). For Windows, make sure
|
||||
DirectSound was detected.
|
||||
|
||||
|
||||
Utilities
|
||||
=========
|
||||
|
||||
The source package comes with an informational utility, openal-info, and is
|
||||
built by default. It prints out information provided by the ALC and AL sub-
|
||||
systems, including discovered devices, version information, and extensions.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
OpenAL Soft can be configured on a per-user and per-system basis. This allows
|
||||
users and sysadmins to control information provided to applications, as well
|
||||
as application-agnostic behavior of the library. See alsoftrc.sample for
|
||||
available settings.
|
||||
|
||||
|
||||
Acknowledgements
|
||||
================
|
||||
|
||||
Special thanks go to:
|
||||
|
||||
Creative Labs for the original source code this is based off of.
|
||||
|
||||
Christopher Fitzgerald for the current reverb effect implementation, and
|
||||
helping with the low-pass filter.
|
||||
|
||||
Christian Borss for the 3D panning code the current implementation is heavilly
|
||||
based on.
|
||||
|
||||
Ben Davis for the idea behind the current click-removal code.
|
||||
|
||||
+16
-9
@@ -1,19 +1,21 @@
|
||||
# Cross-compiling requires CMake 2.6 or newer. To cross-compile, first modify
|
||||
# this file to set the proper settings and paths. Then use it from build/ like:
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt \
|
||||
# -DCMAKE_INSTALL_PREFIX=/usr/mingw32/mingw
|
||||
# If you already have a toolchain file setup, you may use that instead of this
|
||||
# file.
|
||||
# Cross-compiling requires CMake 2.6 or newer. To use it from build/, call it
|
||||
# like this:
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-pc-mingw32
|
||||
# Where 'i686-pc-mingw32' is the host prefix for your cross-compiler. If you
|
||||
# already have a toolchain file setup, you may use that instead of this file.
|
||||
|
||||
# the name of the target operating system
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
SET(CMAKE_C_COMPILER mingw32-gcc)
|
||||
SET(CMAKE_CXX_COMPILER mingw32-g++)
|
||||
SET(CMAKE_C_COMPILER "${HOST}-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "${HOST}-g++")
|
||||
|
||||
# here is the target environment located
|
||||
SET(CMAKE_FIND_ROOT_PATH /usr/mingw32/mingw)
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}")
|
||||
|
||||
# here is where stuff gets installed to
|
||||
SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/usr" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
@@ -21,3 +23,8 @@ SET(CMAKE_FIND_ROOT_PATH /usr/mingw32/mingw)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# set env vars so that pkg-config will look in the appropriate directory for
|
||||
# .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
|
||||
set(ENV{PKG_CONFIG_PATH} "")
|
||||
|
||||
+141
-89
@@ -5,35 +5,42 @@
|
||||
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
|
||||
# specific override settings in ~/.alsoftrc.
|
||||
# For Windows, these settings should go into %AppData%\alsoft.ini
|
||||
# The environment variable ALSOFT_CONF can be used to specify another config
|
||||
# override
|
||||
|
||||
# Option and block names are case-insenstive. The supplied values are only
|
||||
# hints and may not be honored (though generally it'll try to get as close as
|
||||
# possible). Note: options that are left unset may default to app- or system-
|
||||
# specified values. These are the current available settings:
|
||||
|
||||
## format:
|
||||
# Sets the output format. Can be one of:
|
||||
# AL_FORMAT_MONO8 (8-bit mono)
|
||||
# AL_FORMAT_STEREO8 (8-bit stereo)
|
||||
# AL_FORMAT_QUAD8 (8-bit 4-channel)
|
||||
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
|
||||
# AL_FORMAT_MONO16 (16-bit mono)
|
||||
# AL_FORMAT_STEREO16 (16-bit stereo)
|
||||
# AL_FORMAT_QUAD16 (16-bit 4-channel)
|
||||
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
|
||||
# AL_FORMAT_MONO32 (32-bit float mono)
|
||||
# AL_FORMAT_STEREO32 (32-bit float stereo)
|
||||
# AL_FORMAT_QUAD32 (32-bit float 4-channel)
|
||||
# AL_FORMAT_51CHN32 (32-bit float 5.1 output)
|
||||
# AL_FORMAT_61CHN32 (32-bit float 6.1 output)
|
||||
# AL_FORMAT_71CHN32 (32-bit float 7.1 output)
|
||||
#format = AL_FORMAT_STEREO16
|
||||
## 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
|
||||
# are: mono, stereo, quad, surround51, surround61, surround71
|
||||
#channels = stereo
|
||||
|
||||
## sample-type:
|
||||
# Sets the output sample type. Currently, all mixing is done with 32-bit float
|
||||
# and converted to the output sample type as needed. Available values are:
|
||||
# int8 - signed 8-bit int
|
||||
# uint8 - unsigned 8-bit int
|
||||
# int16 - signed 16-bit int
|
||||
# uint16 - unsigned 16-bit int
|
||||
# int32 - signed 32-bit int
|
||||
# uint32 - unsigned 32-bit int
|
||||
# float32 - 32-bit float
|
||||
#sample-type = float32
|
||||
|
||||
## hrtf:
|
||||
# Enables HRTF filters. These filters provide for better sound spatialization
|
||||
# while using headphones. The default filter will only work when output is
|
||||
# 44100hz stereo. While HRTF is active, the cf_level option is disabled.
|
||||
# Default is disabled since stereo speaker output quality may suffer.
|
||||
#hrtf = false
|
||||
|
||||
## 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.
|
||||
#hrtf_tables =
|
||||
|
||||
## cf_level:
|
||||
# Sets the crossfeed level for stereo output. Valid values are:
|
||||
@@ -48,29 +55,21 @@
|
||||
# stereo modes.
|
||||
#cf_level = 0
|
||||
|
||||
## head_dampen:
|
||||
# Sets the amount of dampening on sounds emanating from behind the listener.
|
||||
# This is used to simulate the natural occlusion of the head, which is
|
||||
# typically missing with mono and stereo output, and as such, only works on
|
||||
# mono and stereo output modes. Valid values range from 0 to 1 (inclusive),
|
||||
# and higher values provide a stronger effect.
|
||||
#head_dampen = 0.25
|
||||
|
||||
## frequency:
|
||||
# Sets the output frequency.
|
||||
#frequency = 44100
|
||||
|
||||
## resampler:
|
||||
# Selects the resampler used when mixing sources. Valid values are:
|
||||
# 0 - None (nearest sample, no interpolation)
|
||||
# 1 - Linear (extrapolates samples using a linear slope between samples)
|
||||
# 2 - Cosine (extrapolates using a (co)sine slope)
|
||||
# point - nearest sample, no interpolation
|
||||
# linear - extrapolates samples using a linear slope between samples
|
||||
# cubic - extrapolates samples using a Catmull-Rom spline
|
||||
# Specifying other values will result in using the default (linear).
|
||||
#resampler = 1
|
||||
#resampler = linear
|
||||
|
||||
## rt-prio:
|
||||
# Sets real-time priority for the mixing thread. Not all drivers may use this
|
||||
# (eg. PulseAudio) as they already control the priority of the mixing thread.
|
||||
# (eg. PortAudio) as they already control the priority of the mixing thread.
|
||||
# 0 and negative values will disable it. Note that this may constitute a
|
||||
# security risk since a real-time priority thread can indefinitely block
|
||||
# normal-priority threads if it fails to wait. As such, the default is
|
||||
@@ -79,14 +78,14 @@
|
||||
|
||||
## period_size:
|
||||
# Sets the update period size, in frames. This is the number of frames needed
|
||||
# for each mixing update. If the deprecated 'refresh' option is specified and
|
||||
# this isn't, the value will be calculated as size = refresh/periods.
|
||||
# for each mixing update. Acceptable values range between 64 and 8192.
|
||||
#period_size = 1024
|
||||
|
||||
## periods:
|
||||
# Sets the number of update periods. Higher values create a larger mix ahead,
|
||||
# which helps protect against skips when the CPU is under load, but increases
|
||||
# the delay between a sound getting mixed and being heard.
|
||||
# the delay between a sound getting mixed and being heard. Acceptable values
|
||||
# range between 2 and 16.
|
||||
#periods = 4
|
||||
|
||||
## sources:
|
||||
@@ -95,25 +94,29 @@
|
||||
#sources = 256
|
||||
|
||||
## stereodup:
|
||||
# Sets whether to duplicate stereo sounds on the rear and side speakers for 4+
|
||||
# channel output. This can make stereo sources substantially louder than mono
|
||||
# or even 4+ channel sources, but provides a "fuller" playback quality. True,
|
||||
# yes, on, and non-0 values will duplicate stereo sources. 0 and anything else
|
||||
# will cause stereo sounds to only play out the front speakers.
|
||||
#stereodup = false
|
||||
# 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
|
||||
# unless the list is ended with a comma (eg. 'oss,' will list OSS first
|
||||
# followed by all other available backends, while 'oss' will list OSS only).
|
||||
# An empty list means the default.
|
||||
#drivers = pulse,alsa,oss,solaris,dsound,winmm,port,wave
|
||||
# Backends prepended with - won't be available for use (eg. '-oss,' will allow
|
||||
# all available backends except OSS). An empty list means the default.
|
||||
#drivers = pulse,alsa,core,oss,solaris,sndio,mmdevapi,dsound,winmm,port,opensl,null,wave
|
||||
|
||||
## excludefx:
|
||||
# Sets which effects to exclude, preventing apps from using them. This can
|
||||
# help for apps that try to use effects which are too CPU intensive for the
|
||||
# system to handle. Available effects are: eaxreverb,reverb,echo
|
||||
# system to handle. Available effects are: eaxreverb,reverb,echo,modulator,
|
||||
# dedicated
|
||||
#excludefx =
|
||||
|
||||
## slots:
|
||||
@@ -124,40 +127,68 @@
|
||||
#slots = 4
|
||||
|
||||
## sends:
|
||||
# Sets the maximum number of auxiliary sends per source. The total number of
|
||||
# sends possible is defined at compile time and thus can not be increased
|
||||
# beyond the default (2).
|
||||
#sends = 2
|
||||
# Sets the number of auxiliary sends per source. When not specified (default),
|
||||
# it allows the app to request how many it wants. The maximum value currently
|
||||
# possible is 4.
|
||||
#sends =
|
||||
|
||||
## layout_STEREO:
|
||||
# Sets the speaker layout when using stereo output. Values are specified in
|
||||
# degrees, where 0 is straight in front, negative goes left, and positive goes
|
||||
# right. Unspecified speakers will remain at their default position. Available
|
||||
# speakers are front-left(fl) and front-right(fr).
|
||||
#layout_STEREO = fl=-90, fr=90
|
||||
|
||||
## laytout_QUAD:
|
||||
# Sets the speaker layout when using quadriphonic output. Available speakers
|
||||
# are back-left(bl), front-left(fl), front-right(fr), and back-right(br).
|
||||
#layout_QUAD = bl=-135, fl=-45, fr=45, br=135
|
||||
|
||||
## layout_51CHN:
|
||||
# Sets the speaker layout when using 5.1 output. Available speakers are back-
|
||||
# left(bl), front-left(fl), front-center(fc), front-right(fr), and back-
|
||||
# right(br).
|
||||
#layout_51CHN = bl=-110, fl=-30, fc=0, fr=30, br=110
|
||||
|
||||
## layout_61CHN:
|
||||
# Sets the speaker layout when using 6.1 output. Available speakers are side-
|
||||
# left(sl), front-left(fl), front-center(fc), front-right(fr), side-right(sr),
|
||||
## layout:
|
||||
# Sets the virtual speaker layout. Values are specified in degrees, where 0 is
|
||||
# straight in front, negative goes left, and positive goes right. Unspecified
|
||||
# speakers will remain at their default positions (which are dependant on the
|
||||
# output format). Available speakers are back-left(bl), side-left(sl), front-
|
||||
# left(fl), front-center(fc), front-right(fr), side-right(sr), back-right(br),
|
||||
# and back-center(bc).
|
||||
#layout_61CHN = sl=-90, fl=-30, fc=0, fr=30, sr=90, bc=180
|
||||
#layout =
|
||||
|
||||
## layout_71CHN:
|
||||
# Sets the speaker layout when using 7.1 output. Available speakers are back-
|
||||
# left(bl), side-left(sl), front-left(fl), front-center(fc), front-right(fr),
|
||||
# side-right(sr), and back-right(br).
|
||||
#layout_71CHN = bl=-150, sl=-90, fl=-30, fc=0, fr=30, sr=90, br=150
|
||||
## layout_*:
|
||||
# Channel-specific layouts may be specified to override the layout option. The
|
||||
# same speakers as the layout option are available, and the default settings
|
||||
# are shown below.
|
||||
#layout_stereo = fl=-90, fr=90
|
||||
#layout_quad = fl=-45, fr=45, bl=-135, br=135
|
||||
#layout_surround51 = fl=-30, fr=30, fc=0, bl=-110, br=110
|
||||
#layout_surround61 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180
|
||||
#layout_surround71 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150
|
||||
|
||||
## default-reverb:
|
||||
# A reverb preset that applies by default to all sources on send 0
|
||||
# (applications that set their own slots on send 0 will override this).
|
||||
# Available presets are: None, Generic, PaddedCell, Room, Bathroom,
|
||||
# Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar,
|
||||
# CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Moutains,
|
||||
# Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic.
|
||||
#default-reverb =
|
||||
|
||||
## trap-alc-error:
|
||||
# Generates a SIGTRAP signal when an ALC device error is generated, on systems
|
||||
# that support it. This helps when debugging, while trying to find the cause
|
||||
# of a device error. On Windows, a breakpoint exception is generated.
|
||||
#trap-alc-error = false
|
||||
|
||||
## trap-al-error:
|
||||
# Generates a SIGTRAP signal when an AL context error is generated, on systems
|
||||
# that support it. This helps when debugging, while trying to find the cause
|
||||
# of a context error. On Windows, a breakpoint exception is generated.
|
||||
#trap-al-error = false
|
||||
|
||||
##
|
||||
## Reverb effect stuff (includes EAX reverb)
|
||||
##
|
||||
[reverb]
|
||||
|
||||
## boost:
|
||||
# A global amplification for reverb output, expressed in decibels. The value
|
||||
# is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a
|
||||
# scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
|
||||
# value of 0 means no change.
|
||||
#boost = 0
|
||||
|
||||
## emulate-eax:
|
||||
# Allows the standard reverb effect to be used in place of EAX reverb. EAX
|
||||
# reverb processing is a bit more CPU intensive than standard, so this option
|
||||
# allows a simpler effect to be used at the loss of some quality.
|
||||
#emulate-eax = false
|
||||
|
||||
##
|
||||
## ALSA backend stuff
|
||||
@@ -168,10 +199,36 @@
|
||||
# Sets the device name for the default playback device.
|
||||
#device = default
|
||||
|
||||
## device-prefix:
|
||||
# Sets the prefix used by the discovered (non-default) playback devices. This
|
||||
# will be appended with "CARD=c,DEV=d", where c is the card id and d is the
|
||||
# device index for the requested device name.
|
||||
#device-prefix = plughw:
|
||||
|
||||
## device-prefix-*:
|
||||
# Card- and device-specific prefixes may be used to override the device-prefix
|
||||
# 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- =
|
||||
|
||||
## capture:
|
||||
# Sets the device name for the default capture device.
|
||||
#capture = default
|
||||
|
||||
## capture-prefix:
|
||||
# Sets the prefix used by the discovered (non-default) capture devices. This
|
||||
# will be appended with "CARD=c,DEV=d", where c is the card id and d is the
|
||||
# device number for the requested device name.
|
||||
#capture-prefix = plughw:
|
||||
|
||||
## capture-prefix-*:
|
||||
# Card- and device-specific prefixes may be used to override the
|
||||
# capture-prefix option. The option may specify the card id (eg,
|
||||
# capture-prefix-NVidia), or the card id and device index (eg,
|
||||
# capture-prefix-NVidia-0). The card id is case-sensitive.
|
||||
#capture-prefix- =
|
||||
|
||||
## mmap:
|
||||
# Sets whether to try using mmap mode (helps reduce latencies and CPU
|
||||
# consumption). If mmap isn't available, it will automatically fall back to
|
||||
@@ -201,6 +258,11 @@
|
||||
# Sets the device name for Solaris output.
|
||||
#device = /dev/audio
|
||||
|
||||
##
|
||||
## MMDevApi backend stuff
|
||||
##
|
||||
[mmdevapi]
|
||||
|
||||
##
|
||||
## DirectSound backend stuff
|
||||
##
|
||||
@@ -239,16 +301,6 @@
|
||||
# still prevent autospawning even if this is set to true.
|
||||
#spawn-server = false
|
||||
|
||||
## buffer-length:
|
||||
# Specifies the PulseAudio buffer length, in sample frames. When set to a
|
||||
# non-0 value, it specifies the total buffer length for the playback stream,
|
||||
# overriding the period settings. Otherwise it uses the period size and count
|
||||
# to calculate a buffer size. PulseAudio, unlike other backends, does not work
|
||||
# in period chunks, but instead just has one buffer block which is refilled as
|
||||
# it nears empty. Because of this, the usual buffering metrics are unsuitable,
|
||||
# with the default 4096 frames being needlessly large.
|
||||
#buffer-length = 2048
|
||||
|
||||
##
|
||||
## Wave File Writer stuff
|
||||
##
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#ifdef CHECK_SHARED_FUNCTION_EXISTS
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef CALLSTACK
|
||||
#define CALLSTACK
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef ARGSTACK
|
||||
char __stdcall CHECK_SHARED_FUNCTION_EXISTS(ARGSTACK);
|
||||
#else
|
||||
char __stdcall CHECK_SHARED_FUNCTION_EXISTS(void);
|
||||
#endif
|
||||
#else
|
||||
char CHECK_SHARED_FUNCTION_EXISTS();
|
||||
#endif
|
||||
|
||||
#ifdef __CLASSIC_C__
|
||||
int main(){
|
||||
int ac;
|
||||
char*av[];
|
||||
#else
|
||||
int main(int ac, char*av[]){
|
||||
#endif
|
||||
CHECK_SHARED_FUNCTION_EXISTS(CALLSTACK);
|
||||
if(ac > 1000)
|
||||
{
|
||||
return *av[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CHECK_SHARED_FUNCTION_EXISTS */
|
||||
|
||||
# error "CHECK_SHARED_FUNCTION_EXISTS has to specify the function"
|
||||
|
||||
#endif /* CHECK_SHARED_FUNCTION_EXISTS */
|
||||
@@ -0,0 +1,92 @@
|
||||
# - Check if a symbol exists as a function, variable, or macro
|
||||
# CHECK_SYMBOL_EXISTS(<symbol> <files> <variable>)
|
||||
#
|
||||
# Check that the <symbol> is available after including given header
|
||||
# <files> and store the result in a <variable>. Specify the list
|
||||
# of files in one argument as a semicolon-separated list.
|
||||
#
|
||||
# If the header files define the symbol as a macro it is considered
|
||||
# available and assumed to work. If the header files declare the
|
||||
# symbol as a function or variable then the symbol must also be
|
||||
# available for linking. If the symbol is a type or enum value
|
||||
# it will not be recognized (consider using CheckTypeSize or
|
||||
# CheckCSourceCompiles).
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2011 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE)
|
||||
IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||
SET(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n")
|
||||
SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
IF(CMAKE_REQUIRED_LIBRARIES)
|
||||
SET(CHECK_SYMBOL_EXISTS_LIBS
|
||||
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES};${LIBRARY}")
|
||||
ELSE(CMAKE_REQUIRED_LIBRARIES)
|
||||
SET(CHECK_SYMBOL_EXISTS_LIBS
|
||||
"-DLINK_LIBRARIES:STRING=${LIBRARY}")
|
||||
ENDIF(CMAKE_REQUIRED_LIBRARIES)
|
||||
IF(CMAKE_REQUIRED_INCLUDES)
|
||||
SET(CMAKE_SYMBOL_EXISTS_INCLUDES
|
||||
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
|
||||
ELSE(CMAKE_REQUIRED_INCLUDES)
|
||||
SET(CMAKE_SYMBOL_EXISTS_INCLUDES)
|
||||
ENDIF(CMAKE_REQUIRED_INCLUDES)
|
||||
FOREACH(FILE ${FILES})
|
||||
SET(CMAKE_CONFIGURABLE_FILE_CONTENT
|
||||
"${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n")
|
||||
ENDFOREACH(FILE)
|
||||
SET(CMAKE_CONFIGURABLE_FILE_CONTENT
|
||||
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n cmakeRequireSymbol(0,&${SYMBOL});\n return 0;\n}\n")
|
||||
|
||||
CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
|
||||
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY)
|
||||
|
||||
MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}")
|
||||
TRY_COMPILE(${VARIABLE}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
|
||||
CMAKE_FLAGS
|
||||
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
|
||||
-DLINK_DIRECTORIES:STRING=${LOCATION}
|
||||
"${CHECK_SYMBOL_EXISTS_LIBS}"
|
||||
"${CMAKE_SYMBOL_EXISTS_INCLUDES}"
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
IF(${VARIABLE})
|
||||
MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found")
|
||||
SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
|
||||
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Determining if the ${SYMBOL} "
|
||||
"exist in ${LIBRARY} passed with the following output:\n"
|
||||
"${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
|
||||
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
|
||||
ELSE(${VARIABLE})
|
||||
MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.")
|
||||
SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
|
||||
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Determining if the ${SYMBOL} "
|
||||
"exist in ${LIBRARY} failed with the following output:\n"
|
||||
"${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
|
||||
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
|
||||
ENDIF(${VARIABLE})
|
||||
ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||
ENDMACRO(CHECK_SHARED_FUNCTION_EXISTS)
|
||||
@@ -1,67 +0,0 @@
|
||||
# - Check if the function exists.
|
||||
# CHECK_LIBRARY_EXISTS (LIBRARY FUNCTION LOCATION VARIABLE)
|
||||
#
|
||||
# LIBRARY - the name of the library you are looking for
|
||||
# FUNCTION - the name of the function
|
||||
# ARGCOUNT - number of arguments for stdcall functions
|
||||
# LOCATION - location where the library should be found
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
|
||||
|
||||
MACRO(CHECK_SHARED_LIBRARY_EXISTS LIBRARY FUNCTION ARGCOUNT LOCATION VARIABLE)
|
||||
IF("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||
SET(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION
|
||||
"-DCHECK_SHARED_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}")
|
||||
IF(WIN32)
|
||||
IF(${ARGCOUNT} GREATER 0)
|
||||
SET(ARGSTACK "void*")
|
||||
SET(CALLSTACK "NULL")
|
||||
SET(CURARG 1)
|
||||
WHILE(${ARGCOUNT} GREATER ${CURARG})
|
||||
SET(ARGSTACK "${ARGSTACK},void*")
|
||||
SET(CALLSTACK "${CALLSTACK},NULL")
|
||||
MATH(EXPR CURARG "${CURARG} + 1")
|
||||
ENDWHILE(${ARGCOUNT} GREATER ${CURARG})
|
||||
ENDIF(${ARGCOUNT} GREATER 0)
|
||||
SET(MACRO_CHECK_LIBRARY_EXISTS_DEFINITION
|
||||
"-D_WIN32 -DARGSTACK=\"${ARGSTACK}\" -DCALLSTACK=\"${CALLSTACK}\" ${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION}")
|
||||
ENDIF(WIN32)
|
||||
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY}")
|
||||
SET(CHECK_LIBRARY_EXISTS_LIBRARIES ${LIBRARY})
|
||||
IF(CMAKE_REQUIRED_LIBRARIES)
|
||||
SET(CHECK_LIBRARY_EXISTS_LIBRARIES
|
||||
${CHECK_LIBRARY_EXISTS_LIBRARIES} ${CMAKE_REQUIRED_LIBRARIES})
|
||||
ENDIF(CMAKE_REQUIRED_LIBRARIES)
|
||||
TRY_COMPILE(${VARIABLE}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/cmake/CheckSharedFunctionExists.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
|
||||
CMAKE_FLAGS
|
||||
-DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION}
|
||||
-DLINK_DIRECTORIES:STRING=${LOCATION}
|
||||
"-DLINK_LIBRARIES:STRING=${CHECK_LIBRARY_EXISTS_LIBRARIES}"
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
|
||||
IF(${VARIABLE})
|
||||
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - found")
|
||||
SET(${VARIABLE} 1 CACHE INTERNAL "Have library ${LIBRARY}")
|
||||
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Determining if the function ${FUNCTION} exists in the ${LIBRARY} "
|
||||
"passed with the following output:\n"
|
||||
"${OUTPUT}\n\n")
|
||||
ELSE(${VARIABLE})
|
||||
MESSAGE(STATUS "Looking for ${FUNCTION} in ${LIBRARY} - not found")
|
||||
SET(${VARIABLE} "" CACHE INTERNAL "Have library ${LIBRARY}")
|
||||
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Determining if the function ${FUNCTION} exists in the ${LIBRARY} "
|
||||
"failed with the following output:\n"
|
||||
"${OUTPUT}\n\n")
|
||||
ENDIF(${VARIABLE})
|
||||
ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
|
||||
ENDMACRO(CHECK_SHARED_LIBRARY_EXISTS)
|
||||
+56
-9
@@ -1,5 +1,6 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
/* API declaration export attribute */
|
||||
#define AL_API ${EXPORT_DECL}
|
||||
#define ALC_API ${EXPORT_DECL}
|
||||
|
||||
/* Define to the library version */
|
||||
#define ALSOFT_VERSION "${LIB_VERSION}"
|
||||
@@ -13,6 +14,12 @@
|
||||
/* Define if we have the Solaris backend */
|
||||
#cmakedefine HAVE_SOLARIS
|
||||
|
||||
/* Define if we have the SndIO backend */
|
||||
#cmakedefine HAVE_SNDIO
|
||||
|
||||
/* Define if we have the MMDevApi backend */
|
||||
#cmakedefine HAVE_MMDEVAPI
|
||||
|
||||
/* Define if we have the DSound backend */
|
||||
#cmakedefine HAVE_DSOUND
|
||||
|
||||
@@ -25,6 +32,15 @@
|
||||
/* Define if we have the PulseAudio backend */
|
||||
#cmakedefine HAVE_PULSEAUDIO
|
||||
|
||||
/* Define if we have the CoreAudio backend */
|
||||
#cmakedefine HAVE_COREAUDIO
|
||||
|
||||
/* Define if we have the OpenSL backend */
|
||||
#cmakedefine HAVE_OPENSL
|
||||
|
||||
/* Define if we have the Wave Writer backend */
|
||||
#cmakedefine HAVE_WAVE
|
||||
|
||||
/* Define if we have dlfcn.h */
|
||||
#cmakedefine HAVE_DLFCN_H
|
||||
|
||||
@@ -37,15 +53,33 @@
|
||||
/* 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 strtof function */
|
||||
#cmakedefine HAVE_STRTOF
|
||||
|
||||
@@ -61,12 +95,6 @@
|
||||
/* Define to the size of a long long int type */
|
||||
#cmakedefine SIZEOF_LONG_LONG ${SIZEOF_LONG_LONG}
|
||||
|
||||
/* Define to the size of an unsigned int type */
|
||||
#cmakedefine SIZEOF_UINT ${SIZEOF_UINT}
|
||||
|
||||
/* Define to the size of a void pointer type */
|
||||
#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP}
|
||||
|
||||
/* Define if we have GCC's destructor attribute */
|
||||
#cmakedefine HAVE_GCC_DESTRUCTOR
|
||||
|
||||
@@ -76,9 +104,24 @@
|
||||
/* Define if we have pthread_np.h */
|
||||
#cmakedefine HAVE_PTHREAD_NP_H
|
||||
|
||||
/* Define if we have arm_neon.h */
|
||||
#cmakedefine HAVE_ARM_NEON_H
|
||||
|
||||
/* Define if we have guiddef.h */
|
||||
#cmakedefine HAVE_GUIDDEF_H
|
||||
|
||||
/* Define if we have guiddef.h */
|
||||
#cmakedefine HAVE_INITGUID_H
|
||||
|
||||
/* Define if we have ieeefp.h */
|
||||
#cmakedefine HAVE_IEEEFP_H
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -91,4 +134,8 @@
|
||||
/* Define if we have pthread_setschedparam() */
|
||||
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
|
||||
|
||||
#endif
|
||||
/* Define if we have the restrict keyword */
|
||||
#cmakedefine HAVE_RESTRICT
|
||||
|
||||
/* Define if we have the __restrict keyword */
|
||||
#cmakedefine HAVE___RESTRICT
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
Useful Environment Variables
|
||||
|
||||
Below is a list of environment variables that can be set to aid with running or
|
||||
debugging apps that use OpenAL Soft. They should be set before the app is run.
|
||||
|
||||
*** Logging ***
|
||||
|
||||
ALSOFT_LOGLEVEL
|
||||
Specifies the amount of logging OpenAL Soft will write out:
|
||||
0 - Effectively disables all logging
|
||||
1 - Prints out errors only
|
||||
2 - Prints out warnings and errors
|
||||
3 - Prints out additional information, as well as warnings and errors
|
||||
4 - Same as 3, but also device and context reference count changes. This will
|
||||
print out *a lot* of info, and is generally not useful unless you're trying
|
||||
to track a reference leak within the library.
|
||||
|
||||
ALSOFT_LOGFILE
|
||||
Specifies a filename that logged output will be written to. Note that the file
|
||||
will be first cleared when logging is initialized.
|
||||
|
||||
*** Overrides ***
|
||||
|
||||
ALSOFT_CONF
|
||||
Specifies an additional configuration file to load settings from. These
|
||||
settings will take precedence over the global and user configs, but not other
|
||||
environment variable settings.
|
||||
|
||||
ALSOFT_DRIVERS
|
||||
Overrides the drivers config option. This specifies which backend drivers to
|
||||
consider or not consider for use. Please see the drivers option in
|
||||
alsoftrc.sample for a list of available drivers.
|
||||
|
||||
ALSOFT_DEFAULT_REVERB
|
||||
Specifies the default reverb preset to apply to sources. Please see the
|
||||
default-reverb option in alsoftrc.sample for additional information and a list
|
||||
of available presets.
|
||||
|
||||
ALSOFT_TRAP_AL_ERROR
|
||||
Set to "true" or "1" to force trapping AL errors. Like the trap-al-error config
|
||||
option, this will raise a SIGTRAP signal (or a breakpoint exception under
|
||||
Windows) when a context-level error is generated. Useful when run under a
|
||||
debugger as it will break execution right when the error occurs, making it
|
||||
easier to track the cause.
|
||||
|
||||
ALSOFT_TRAP_ALC_ERROR
|
||||
Set to "true" or "1" to force trapping ALC errors. Like the trap-alc-error
|
||||
config option, this will raise a SIGTRAP signal (or a breakpoint exception
|
||||
under Windows) when a device-level error is generated. Useful when run under a
|
||||
debugger as it will break execution right when the error occurs, making it
|
||||
easier to track the cause.
|
||||
|
||||
ALSOFT_TRAP_ERROR
|
||||
Set to "true" or "1" to force trapping both ALC and AL errors.
|
||||
|
||||
*** Compatibility ***
|
||||
|
||||
__ALSOFT_HALF_ANGLE_CONES
|
||||
Older versions of OpenAL Soft incorrectly calculated the cone angles to range
|
||||
between 0 and 180 degrees, instead of the expected range of 0 to 360 degrees.
|
||||
Setting this to "true" or "1" restores the old buggy behavior, for apps that
|
||||
were written to expect the incorrect range.
|
||||
|
||||
__ALSOFT_REVERSE_Z
|
||||
Applications that don't natively use OpenAL's coordinate system have to convert
|
||||
to it before passing in 3D coordinates. Depending on how exactly this is done,
|
||||
it can cause correct output for stereo but incorrect Z panning for surround
|
||||
sound (i.e., sounds that are supposed to be behind you sound like they're in
|
||||
front, and vice-versa). Setting this to "true" or "1" will negate the localized
|
||||
Z coordinate to attempt to fix output for apps that have incorrect front/back
|
||||
panning.
|
||||
@@ -0,0 +1,633 @@
|
||||
/*
|
||||
* FFmpeg Decoder Helpers
|
||||
*
|
||||
* Copyright (c) 2011 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 routines for helping to decode audio using libavformat
|
||||
* and libavcodec (ffmpeg). There's very little OpenAL-specific code here. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#include "alhelpers.h"
|
||||
#include "alffmpeg.h"
|
||||
|
||||
|
||||
static size_t NextPowerOf2(size_t value)
|
||||
{
|
||||
size_t powerOf2 = 1;
|
||||
|
||||
if(value)
|
||||
{
|
||||
value--;
|
||||
while(value)
|
||||
{
|
||||
value >>= 1;
|
||||
powerOf2 <<= 1;
|
||||
}
|
||||
}
|
||||
return powerOf2;
|
||||
}
|
||||
|
||||
|
||||
struct MemData {
|
||||
char *buffer;
|
||||
size_t length;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
static int MemData_read(void *opaque, uint8_t *buf, int buf_size)
|
||||
{
|
||||
struct MemData *membuf = (struct MemData*)opaque;
|
||||
int rem = membuf->length - membuf->pos;
|
||||
|
||||
if(rem > buf_size)
|
||||
rem = buf_size;
|
||||
|
||||
memcpy(buf, &membuf->buffer[membuf->pos], rem);
|
||||
membuf->pos += rem;
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
static int MemData_write(void *opaque, uint8_t *buf, int buf_size)
|
||||
{
|
||||
struct MemData *membuf = (struct MemData*)opaque;
|
||||
int rem = membuf->length - membuf->pos;
|
||||
|
||||
if(rem > buf_size)
|
||||
rem = buf_size;
|
||||
|
||||
memcpy(&membuf->buffer[membuf->pos], buf, rem);
|
||||
membuf->pos += rem;
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
static int64_t MemData_seek(void *opaque, int64_t offset, int whence)
|
||||
{
|
||||
struct MemData *membuf = (struct MemData*)opaque;
|
||||
|
||||
whence &= ~AVSEEK_FORCE;
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
if(offset < 0 || 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))
|
||||
return -1;
|
||||
membuf->pos += offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if(offset > 0 || offset < -membuf->length)
|
||||
return -1;
|
||||
membuf->pos = membuf->length + offset;
|
||||
break;
|
||||
|
||||
case AVSEEK_SIZE:
|
||||
return membuf->length;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return membuf->pos;
|
||||
}
|
||||
|
||||
|
||||
struct PacketList {
|
||||
AVPacket pkt;
|
||||
struct PacketList *next;
|
||||
};
|
||||
|
||||
struct MyStream {
|
||||
AVCodecContext *CodecCtx;
|
||||
int StreamIdx;
|
||||
|
||||
struct PacketList *Packets;
|
||||
|
||||
char *DecodedData;
|
||||
size_t DecodedDataSize;
|
||||
|
||||
FilePtr parent;
|
||||
};
|
||||
|
||||
struct MyFile {
|
||||
AVFormatContext *FmtCtx;
|
||||
|
||||
StreamPtr *Streams;
|
||||
size_t StreamsSize;
|
||||
|
||||
struct MemData membuf;
|
||||
};
|
||||
|
||||
|
||||
static int done_init = 0;
|
||||
|
||||
FilePtr openAVFile(const char *fname)
|
||||
{
|
||||
FilePtr file;
|
||||
|
||||
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
||||
* output from the lib */
|
||||
if(!done_init) {av_register_all();
|
||||
av_log_set_level(AV_LOG_ERROR);
|
||||
done_init = 1;}
|
||||
|
||||
file = (FilePtr)calloc(1, sizeof(*file));
|
||||
if(file && avformat_open_input(&file->FmtCtx, fname, NULL, NULL) == 0)
|
||||
{
|
||||
/* After opening, we must search for the stream information because not
|
||||
* 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);
|
||||
}
|
||||
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FilePtr openAVData(const char *name, char *buffer, size_t buffer_len)
|
||||
{
|
||||
FilePtr file;
|
||||
|
||||
if(!done_init) {av_register_all();
|
||||
av_log_set_level(AV_LOG_ERROR);
|
||||
done_init = 1;}
|
||||
|
||||
if(!name)
|
||||
name = "";
|
||||
|
||||
file = (FilePtr)calloc(1, sizeof(*file));
|
||||
if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
|
||||
{
|
||||
file->membuf.buffer = buffer;
|
||||
file->membuf.length = buffer_len;
|
||||
file->membuf.pos = 0;
|
||||
|
||||
file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, &file->membuf,
|
||||
MemData_read, MemData_write,
|
||||
MemData_seek);
|
||||
if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
|
||||
{
|
||||
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
|
||||
return file;
|
||||
av_close_input_file(file->FmtCtx);
|
||||
file->FmtCtx = NULL;
|
||||
}
|
||||
if(file->FmtCtx)
|
||||
avformat_free_context(file->FmtCtx);
|
||||
file->FmtCtx = NULL;
|
||||
}
|
||||
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FilePtr openAVCustom(const char *name, void *user_data,
|
||||
int (*read_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||
int64_t (*seek)(void *user_data, int64_t offset, int whence))
|
||||
{
|
||||
FilePtr file;
|
||||
|
||||
if(!done_init) {av_register_all();
|
||||
av_log_set_level(AV_LOG_ERROR);
|
||||
done_init = 1;}
|
||||
|
||||
if(!name)
|
||||
name = "";
|
||||
|
||||
file = (FilePtr)calloc(1, sizeof(*file));
|
||||
if(file && (file->FmtCtx=avformat_alloc_context()) != NULL)
|
||||
{
|
||||
file->FmtCtx->pb = avio_alloc_context(NULL, 0, 0, user_data,
|
||||
read_packet, write_packet, seek);
|
||||
if(file->FmtCtx->pb && avformat_open_input(&file->FmtCtx, name, NULL, NULL) == 0)
|
||||
{
|
||||
if(avformat_find_stream_info(file->FmtCtx, NULL) >= 0)
|
||||
return file;
|
||||
av_close_input_file(file->FmtCtx);
|
||||
file->FmtCtx = NULL;
|
||||
}
|
||||
if(file->FmtCtx)
|
||||
avformat_free_context(file->FmtCtx);
|
||||
file->FmtCtx = NULL;
|
||||
}
|
||||
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void closeAVFile(FilePtr file)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if(!file) return;
|
||||
|
||||
for(i = 0;i < file->StreamsSize;i++)
|
||||
{
|
||||
StreamPtr stream = file->Streams[i];
|
||||
|
||||
while(stream->Packets)
|
||||
{
|
||||
struct PacketList *self;
|
||||
|
||||
self = stream->Packets;
|
||||
stream->Packets = self->next;
|
||||
|
||||
av_free_packet(&self->pkt);
|
||||
av_free(self);
|
||||
}
|
||||
|
||||
avcodec_close(stream->CodecCtx);
|
||||
av_free(stream->DecodedData);
|
||||
free(stream);
|
||||
}
|
||||
free(file->Streams);
|
||||
|
||||
av_close_input_file(file->FmtCtx);
|
||||
free(file);
|
||||
}
|
||||
|
||||
|
||||
int getAVFileInfo(FilePtr file, int *numaudiostreams)
|
||||
{
|
||||
unsigned int i;
|
||||
int audiocount = 0;
|
||||
|
||||
if(!file) return 1;
|
||||
for(i = 0;i < file->FmtCtx->nb_streams;i++)
|
||||
{
|
||||
if(file->FmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
audiocount++;
|
||||
}
|
||||
*numaudiostreams = audiocount;
|
||||
return 0;
|
||||
}
|
||||
|
||||
StreamPtr getAVAudioStream(FilePtr file, int streamnum)
|
||||
{
|
||||
unsigned int i;
|
||||
if(!file) return NULL;
|
||||
for(i = 0;i < file->FmtCtx->nb_streams;i++)
|
||||
{
|
||||
if(file->FmtCtx->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
continue;
|
||||
|
||||
if(streamnum == 0)
|
||||
{
|
||||
StreamPtr stream;
|
||||
AVCodec *codec;
|
||||
void *temp;
|
||||
size_t j;
|
||||
|
||||
/* Found the requested stream. Check if a handle to this stream
|
||||
* already exists and return it if it does */
|
||||
for(j = 0;j < file->StreamsSize;j++)
|
||||
{
|
||||
if(file->Streams[j]->StreamIdx == (int)i)
|
||||
return file->Streams[j];
|
||||
}
|
||||
|
||||
/* Doesn't yet exist. Now allocate a new stream object and fill in
|
||||
* its info */
|
||||
stream = (StreamPtr)calloc(1, sizeof(*stream));
|
||||
if(!stream) return NULL;
|
||||
|
||||
stream->parent = file;
|
||||
stream->CodecCtx = file->FmtCtx->streams[i]->codec;
|
||||
stream->StreamIdx = i;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
free(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
avcodec_close(stream->CodecCtx);
|
||||
free(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Append the new stream object to the stream list. The original
|
||||
* pointer will remain valid if realloc fails, so we need to use
|
||||
* another pointer to watch for errors and not leak memory */
|
||||
temp = realloc(file->Streams, (file->StreamsSize+1) *
|
||||
sizeof(*file->Streams));
|
||||
if(!temp)
|
||||
{
|
||||
avcodec_close(stream->CodecCtx);
|
||||
av_free(stream->DecodedData);
|
||||
free(stream);
|
||||
return NULL;
|
||||
}
|
||||
file->Streams = (StreamPtr*)temp;
|
||||
file->Streams[file->StreamsSize++] = stream;
|
||||
return stream;
|
||||
}
|
||||
streamnum--;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type)
|
||||
{
|
||||
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
return 1;
|
||||
|
||||
/* Get the sample type for OpenAL given the format detected by ffmpeg. */
|
||||
if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_U8)
|
||||
*type = AL_UNSIGNED_BYTE_SOFT;
|
||||
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S16)
|
||||
*type = AL_SHORT_SOFT;
|
||||
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_S32)
|
||||
*type = AL_INT_SOFT;
|
||||
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_FLT)
|
||||
*type = AL_FLOAT_SOFT;
|
||||
else if(stream->CodecCtx->sample_fmt == AV_SAMPLE_FMT_DBL)
|
||||
*type = AL_DOUBLE_SOFT;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unsupported ffmpeg sample format: %s\n",
|
||||
av_get_sample_fmt_name(stream->CodecCtx->sample_fmt));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the OpenAL channel configuration using the channel layout detected
|
||||
* by ffmpeg. NOTE: some file types may not specify a channel layout. In
|
||||
* that case, one must be guessed based on the channel count. */
|
||||
if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_MONO)
|
||||
*channels = AL_MONO_SOFT;
|
||||
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_STEREO)
|
||||
*channels = AL_STEREO_SOFT;
|
||||
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_QUAD)
|
||||
*channels = AL_QUAD_SOFT;
|
||||
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK)
|
||||
*channels = AL_5POINT1_SOFT;
|
||||
else if(stream->CodecCtx->channel_layout == AV_CH_LAYOUT_7POINT1)
|
||||
*channels = AL_7POINT1_SOFT;
|
||||
else if(stream->CodecCtx->channel_layout == 0)
|
||||
{
|
||||
/* Unknown channel layout. Try to guess. */
|
||||
if(stream->CodecCtx->channels == 1)
|
||||
*channels = AL_MONO_SOFT;
|
||||
else if(stream->CodecCtx->channels == 2)
|
||||
*channels = AL_STEREO_SOFT;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unsupported ffmpeg raw channel count: %d\n",
|
||||
stream->CodecCtx->channels);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[1024];
|
||||
av_get_channel_layout_string(str, sizeof(str), stream->CodecCtx->channels,
|
||||
stream->CodecCtx->channel_layout);
|
||||
fprintf(stderr, "Unsupported ffmpeg channel layout: %s\n", str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*rate = stream->CodecCtx->sample_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Used by getAV*Data to search for more compressed data, and buffer it in the
|
||||
* correct stream. It won't buffer data for streams that the app doesn't have a
|
||||
* handle for. */
|
||||
static int getNextPacket(FilePtr file, int streamidx)
|
||||
{
|
||||
struct PacketList *packet;
|
||||
|
||||
packet = (struct PacketList*)av_malloc(sizeof(*packet));
|
||||
packet->next = NULL;
|
||||
|
||||
next_packet:
|
||||
while(av_read_frame(file->FmtCtx, &packet->pkt) >= 0)
|
||||
{
|
||||
StreamPtr *iter = file->Streams;
|
||||
StreamPtr *iter_end = iter + file->StreamsSize;
|
||||
|
||||
/* Check each stream the user has a handle for, looking for the one
|
||||
* this packet belongs to */
|
||||
while(iter != iter_end)
|
||||
{
|
||||
if((*iter)->StreamIdx == packet->pkt.stream_index)
|
||||
{
|
||||
struct PacketList **last;
|
||||
|
||||
last = &(*iter)->Packets;
|
||||
while(*last != NULL)
|
||||
last = &(*last)->next;
|
||||
|
||||
*last = packet;
|
||||
if((*iter)->StreamIdx == streamidx)
|
||||
return 1;
|
||||
|
||||
packet = (struct PacketList*)av_malloc(sizeof(*packet));
|
||||
packet->next = NULL;
|
||||
goto next_packet;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
/* Free the packet and look for another */
|
||||
av_free_packet(&packet->pkt);
|
||||
}
|
||||
|
||||
av_free(packet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *getAVAudioData(StreamPtr stream, size_t *length)
|
||||
{
|
||||
int size;
|
||||
int len;
|
||||
|
||||
if(length) *length = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
struct PacketList *self;
|
||||
|
||||
if(size > 0)
|
||||
break;
|
||||
|
||||
/* Packet went unread and no data was given? Drop it and try the next,
|
||||
* I guess... */
|
||||
self = stream->Packets;
|
||||
stream->Packets = self->next;
|
||||
|
||||
av_free_packet(&self->pkt);
|
||||
av_free(self);
|
||||
|
||||
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 */
|
||||
int remaining = stream->Packets->pkt.size - len;
|
||||
memmove(stream->Packets->pkt.data, &stream->Packets->pkt.data[len],
|
||||
remaining);
|
||||
memset(&stream->Packets->pkt.data[remaining], 0,
|
||||
stream->Packets->pkt.size - remaining);
|
||||
stream->Packets->pkt.size -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct PacketList *self;
|
||||
|
||||
self = stream->Packets;
|
||||
stream->Packets = self->next;
|
||||
|
||||
av_free_packet(&self->pkt);
|
||||
av_free(self);
|
||||
}
|
||||
|
||||
if(size == 0)
|
||||
goto next_packet;
|
||||
|
||||
/* Set the output buffer size */
|
||||
stream->DecodedDataSize = size;
|
||||
if(length) *length = stream->DecodedDataSize;
|
||||
|
||||
return stream->DecodedData;
|
||||
}
|
||||
|
||||
size_t readAVAudioData(StreamPtr stream, void *data, size_t length)
|
||||
{
|
||||
size_t dec = 0;
|
||||
|
||||
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
return 0;
|
||||
|
||||
while(dec < length)
|
||||
{
|
||||
/* If there's no decoded data, find some */
|
||||
if(stream->DecodedDataSize == 0)
|
||||
{
|
||||
if(getAVAudioData(stream, NULL) == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if(stream->DecodedDataSize > 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;
|
||||
|
||||
/* Copy the data to the app's buffer and increment */
|
||||
if(data != NULL)
|
||||
{
|
||||
memcpy(data, stream->DecodedData, 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the number of bytes we were able to get */
|
||||
return dec;
|
||||
}
|
||||
|
||||
void *decodeAVAudioStream(StreamPtr stream, size_t *length)
|
||||
{
|
||||
char *outbuf = NULL;
|
||||
size_t buflen = 0;
|
||||
void *inbuf;
|
||||
size_t got;
|
||||
|
||||
*length = 0;
|
||||
if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
return NULL;
|
||||
|
||||
while((inbuf=getAVAudioData(stream, &got)) != NULL && got > 0)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = realloc(outbuf, NextPowerOf2(buflen+got));
|
||||
if(ptr == NULL)
|
||||
break;
|
||||
outbuf = (char*)ptr;
|
||||
|
||||
memcpy(&outbuf[buflen], inbuf, got);
|
||||
buflen += got;
|
||||
}
|
||||
outbuf = (char*)realloc(outbuf, buflen);
|
||||
|
||||
*length = buflen;
|
||||
return outbuf;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef ALFFMPEG_H
|
||||
#define ALFFMPEG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
/* Opaque handles to files and streams. Apps don't need to concern themselves
|
||||
* with the internals */
|
||||
typedef struct MyFile *FilePtr;
|
||||
typedef struct MyStream *StreamPtr;
|
||||
|
||||
/* Opens a file with ffmpeg and sets up the streams' information */
|
||||
FilePtr openAVFile(const char *fname);
|
||||
|
||||
/* Opens a named file image with ffmpeg and sets up the streams' information */
|
||||
FilePtr openAVData(const char *name, char *buffer, size_t buffer_len);
|
||||
|
||||
/* Opens a named data stream with ffmpeg, using the specified data pointer and
|
||||
* callbacks, and sets up the streams' information */
|
||||
FilePtr openAVCustom(const char *name, void *user_data,
|
||||
int (*read_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||
int (*write_packet)(void *user_data, uint8_t *buf, int buf_size),
|
||||
int64_t (*seek)(void *user_data, int64_t offset, int whence));
|
||||
|
||||
/* Closes/frees an opened file and any of its streams */
|
||||
void closeAVFile(FilePtr file);
|
||||
|
||||
/* Reports certain information from the file, eg, the number of audio
|
||||
* streams. Returns 0 on success. */
|
||||
int getAVFileInfo(FilePtr file, int *numaudiostreams);
|
||||
|
||||
/* Retrieves a handle for the given audio stream number (generally 0, but some
|
||||
* files can have multiple audio streams in one file). */
|
||||
StreamPtr getAVAudioStream(FilePtr file, int streamnum);
|
||||
|
||||
/* Returns information about the given audio stream. Returns 0 on success. */
|
||||
int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *type);
|
||||
|
||||
/* Returns a pointer to the next available packet of decoded audio. Any data
|
||||
* 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);
|
||||
|
||||
/* 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
|
||||
* conditions. Returns the number of bytes written. */
|
||||
size_t readAVAudioData(StreamPtr stream, void *data, size_t length);
|
||||
|
||||
/* Decodes all remaining data from the stream and returns a buffer containing
|
||||
* the audio data, with the size stored in 'length'. The returned pointer must
|
||||
* be freed with a call to free(). Note that since this decodes the whole
|
||||
* stream, using it on lengthy streams (eg, music) will use a lot of memory.
|
||||
* Such streams are better handled using getAVAudioData or readAVAudioData to
|
||||
* keep smaller chunks in memory at any given time. */
|
||||
void *decodeAVAudioStream(StreamPtr stream, size_t *length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ALFFMPEG_H */
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* OpenAL Helpers
|
||||
*
|
||||
* Copyright (c) 2011 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 routines to help with some menial OpenAL-related tasks,
|
||||
* such as opening a device and setting up a context, closing the device and
|
||||
* destroying its context, converting between frame counts and byte lengths,
|
||||
* finding an appropriate buffer format, and getting readable strings for
|
||||
* channel configs and sample types. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#include "alhelpers.h"
|
||||
|
||||
|
||||
const char *ChannelsName(ALenum chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
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";
|
||||
}
|
||||
return "Unknown Channels";
|
||||
}
|
||||
|
||||
const char *TypeName(ALenum type)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
|
||||
{
|
||||
ALenum format = AL_NONE;
|
||||
|
||||
/* If using AL_SOFT_buffer_samples, try looking through its formats */
|
||||
if(palIsBufferFormatSupportedSOFT)
|
||||
{
|
||||
/* AL_SOFT_buffer_samples is more lenient with matching formats. The
|
||||
* specified sample type does not need to match the returned format,
|
||||
* but it is nice to try to get something close. */
|
||||
if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
|
||||
}
|
||||
else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
|
||||
}
|
||||
else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
|
||||
type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
|
||||
type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
|
||||
}
|
||||
|
||||
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||
format = AL_NONE;
|
||||
|
||||
/* A matching format was not found or supported. Try 32-bit float. */
|
||||
if(format == AL_NONE)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
|
||||
|
||||
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||
format = AL_NONE;
|
||||
}
|
||||
/* 32-bit float not supported. Try 16-bit int. */
|
||||
if(format == AL_NONE)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
|
||||
|
||||
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||
format = AL_NONE;
|
||||
}
|
||||
/* 16-bit int not supported. Try 8-bit int. */
|
||||
if(format == AL_NONE)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
|
||||
else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
|
||||
else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
|
||||
else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
|
||||
else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
|
||||
else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
|
||||
|
||||
if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
|
||||
format = AL_NONE;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
/* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
|
||||
* and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
|
||||
* AL_EXT_DOUBLE for 64-bit float samples. */
|
||||
if(type == AL_UNSIGNED_BYTE_SOFT)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT)
|
||||
format = AL_FORMAT_MONO8;
|
||||
else if(channels == AL_STEREO_SOFT)
|
||||
format = AL_FORMAT_STEREO8;
|
||||
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||
{
|
||||
if(channels == AL_QUAD_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_QUAD8");
|
||||
else if(channels == AL_5POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_51CHN8");
|
||||
else if(channels == AL_6POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_61CHN8");
|
||||
else if(channels == AL_7POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_71CHN8");
|
||||
}
|
||||
}
|
||||
else if(type == AL_SHORT_SOFT)
|
||||
{
|
||||
if(channels == AL_MONO_SOFT)
|
||||
format = AL_FORMAT_MONO16;
|
||||
else if(channels == AL_STEREO_SOFT)
|
||||
format = AL_FORMAT_STEREO16;
|
||||
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||
{
|
||||
if(channels == AL_QUAD_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_QUAD16");
|
||||
else if(channels == AL_5POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_51CHN16");
|
||||
else if(channels == AL_6POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_61CHN16");
|
||||
else if(channels == AL_7POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_71CHN16");
|
||||
}
|
||||
}
|
||||
else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
|
||||
{
|
||||
if(channels == AL_MONO_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
|
||||
else if(channels == AL_STEREO_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
|
||||
else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
|
||||
{
|
||||
if(channels == AL_QUAD_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_QUAD32");
|
||||
else if(channels == AL_5POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_51CHN32");
|
||||
else if(channels == AL_6POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_61CHN32");
|
||||
else if(channels == AL_7POINT1_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_71CHN32");
|
||||
}
|
||||
}
|
||||
else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
|
||||
{
|
||||
if(channels == AL_MONO_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
|
||||
else if(channels == AL_STEREO_SOFT)
|
||||
format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
|
||||
}
|
||||
|
||||
/* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
|
||||
* opposed to 0. Correct it. */
|
||||
if(format == -1)
|
||||
format = 0;
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
|
||||
ALenum internalformat, ALsizei samples,
|
||||
ALenum channels, ALenum type,
|
||||
const ALvoid *data)
|
||||
{
|
||||
alBufferData(buffer, internalformat, data,
|
||||
FramesToBytes(samples, channels, type),
|
||||
samplerate);
|
||||
}
|
||||
|
||||
|
||||
int InitAL(void)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *ctx;
|
||||
|
||||
/* Open and initialize a device with default settings */
|
||||
device = alcOpenDevice(NULL);
|
||||
if(!device)
|
||||
{
|
||||
fprintf(stderr, "Could not open a device!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void CloseAL(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef ALHELPERS_H
|
||||
#define ALHELPERS_H
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#define Sleep(x) usleep((x)*1000)
|
||||
#else
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Some helper functions to get the name from the channel and type enums. */
|
||||
const char *ChannelsName(ALenum chans);
|
||||
const char *TypeName(ALenum type);
|
||||
|
||||
/* Helpers to convert frame counts and byte lengths. */
|
||||
ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type);
|
||||
ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type);
|
||||
|
||||
/* Retrieves a compatible buffer format given the channel configuration 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);
|
||||
|
||||
/* Loads samples into a buffer using the standard alBufferData call, but with a
|
||||
* LPALBUFFERSAMPLESSOFT-compatible prototype. Assumes internalformat is valid
|
||||
* for alBufferData, and that channels and type match it. */
|
||||
void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
|
||||
ALenum internalformat, ALsizei samples,
|
||||
ALenum channels, ALenum type,
|
||||
const ALvoid *data);
|
||||
|
||||
/* Easy device init/deinit functions. InitAL returns 0 on success. */
|
||||
int InitAL(void);
|
||||
void CloseAL(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* ALHELPERS_H */
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* OpenAL Audio Stream Example
|
||||
*
|
||||
* Copyright (c) 2011 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 a relatively simple streaming audio player. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#include "alhelpers.h"
|
||||
#include "alffmpeg.h"
|
||||
|
||||
|
||||
LPALBUFFERSAMPLESSOFT palBufferSamplesSOFT = wrap_BufferSamples;
|
||||
LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT = NULL;
|
||||
|
||||
|
||||
/* Define the number of buffers and buffer size (in samples) to use. 4 buffers
|
||||
* with 8192 samples each gives a nice per-chunk size, and lets the queue last
|
||||
* for almost 3/4ths of a second for a 44.1khz stream. */
|
||||
#define NUM_BUFFERS 4
|
||||
#define BUFFER_SIZE 8192
|
||||
|
||||
typedef struct StreamPlayer {
|
||||
/* These are the buffers and source to play out through OpenAL with */
|
||||
ALuint buffers[NUM_BUFFERS];
|
||||
ALuint source;
|
||||
|
||||
/* Handles for the audio stream */
|
||||
FilePtr file;
|
||||
StreamPtr stream;
|
||||
|
||||
/* A temporary data buffer for readAVAudioData to write to and pass to
|
||||
* OpenAL with */
|
||||
ALbyte *data;
|
||||
ALsizei datasize;
|
||||
|
||||
/* The format of the output stream */
|
||||
ALenum format;
|
||||
ALenum channels;
|
||||
ALenum type;
|
||||
ALuint rate;
|
||||
} StreamPlayer;
|
||||
|
||||
static StreamPlayer *NewPlayer(void);
|
||||
static void DeletePlayer(StreamPlayer *player);
|
||||
static int OpenPlayerFile(StreamPlayer *player, const char *filename);
|
||||
static void ClosePlayerFile(StreamPlayer *player);
|
||||
static int StartPlayer(StreamPlayer *player);
|
||||
static int UpdatePlayer(StreamPlayer *player);
|
||||
|
||||
/* Creates a new player object, and allocates the needed OpenAL source and
|
||||
* buffer objects. Error checking is simplified for the purposes of this
|
||||
* example, and will cause an abort if needed. */
|
||||
static StreamPlayer *NewPlayer(void)
|
||||
{
|
||||
StreamPlayer *player;
|
||||
|
||||
player = malloc(sizeof(*player));
|
||||
assert(player != NULL);
|
||||
|
||||
memset(player, 0, sizeof(*player));
|
||||
|
||||
/* Generate the buffers and source */
|
||||
alGenBuffers(NUM_BUFFERS, player->buffers);
|
||||
assert(alGetError() == AL_NO_ERROR && "Could not create buffers");
|
||||
|
||||
alGenSources(1, &player->source);
|
||||
assert(alGetError() == AL_NO_ERROR && "Could not create source");
|
||||
|
||||
/* Set parameters so mono sources play out the front-center speaker and
|
||||
* won't distance attenuate. */
|
||||
alSource3i(player->source, AL_POSITION, 0, 0, -1);
|
||||
alSourcei(player->source, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||
alSourcei(player->source, AL_ROLLOFF_FACTOR, 0);
|
||||
assert(alGetError() == AL_NO_ERROR && "Could not set source parameters");
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
/* Destroys a player object, deleting the source and buffers. No error handling
|
||||
* since these calls shouldn't fail with a properly-made player object. */
|
||||
static void DeletePlayer(StreamPlayer *player)
|
||||
{
|
||||
ClosePlayerFile(player);
|
||||
|
||||
alDeleteSources(1, &player->source);
|
||||
alDeleteBuffers(NUM_BUFFERS, player->buffers);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
fprintf(stderr, "Failed to delete object IDs\n");
|
||||
|
||||
memset(player, 0, sizeof(*player));
|
||||
free(player);
|
||||
}
|
||||
|
||||
|
||||
/* Opens the first audio stream of the named file. If a file is already open,
|
||||
* it will be closed first. */
|
||||
static int OpenPlayerFile(StreamPlayer *player, const char *filename)
|
||||
{
|
||||
ClosePlayerFile(player);
|
||||
|
||||
/* Open the file and get the first stream from it */
|
||||
player->file = openAVFile(filename);
|
||||
player->stream = getAVAudioStream(player->file, 0);
|
||||
if(!player->stream)
|
||||
{
|
||||
fprintf(stderr, "Could not open audio in %s\n", filename);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get the stream format, and figure out the OpenAL format */
|
||||
if(getAVAudioInfo(player->stream, &player->rate, &player->channels,
|
||||
&player->type) != 0)
|
||||
{
|
||||
fprintf(stderr, "Error getting audio info for %s\n", filename);
|
||||
goto error;
|
||||
}
|
||||
|
||||
player->format = GetFormat(player->channels, player->type, palIsBufferFormatSupportedSOFT);
|
||||
if(player->format == 0)
|
||||
{
|
||||
fprintf(stderr, "Unsupported format (%s, %s) for %s\n",
|
||||
ChannelsName(player->channels), TypeName(player->type),
|
||||
filename);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allocate enough space for the temp buffer, given the format */
|
||||
player->datasize = FramesToBytes(BUFFER_SIZE, player->channels,
|
||||
player->type);
|
||||
player->data = malloc(player->datasize);
|
||||
if(player->data == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating %d bytes\n", player->datasize);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
closeAVFile(player->file);
|
||||
player->file = NULL;
|
||||
player->stream = NULL;
|
||||
player->datasize = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Closes the audio file stream */
|
||||
static void ClosePlayerFile(StreamPlayer *player)
|
||||
{
|
||||
closeAVFile(player->file);
|
||||
player->file = NULL;
|
||||
player->stream = NULL;
|
||||
|
||||
free(player->data);
|
||||
player->data = NULL;
|
||||
player->datasize = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Prebuffers some audio from the file, and starts playing the source */
|
||||
static int StartPlayer(StreamPlayer *player)
|
||||
{
|
||||
size_t i, got;
|
||||
|
||||
/* Rewind the source position and clear the buffer queue */
|
||||
alSourceRewind(player->source);
|
||||
alSourcei(player->source, AL_BUFFER, 0);
|
||||
|
||||
/* Fill the buffer queue */
|
||||
for(i = 0;i < NUM_BUFFERS;i++)
|
||||
{
|
||||
/* Get some data to give it to the buffer */
|
||||
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);
|
||||
}
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error buffering for playback\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Now queue and start playback! */
|
||||
alSourceQueueBuffers(player->source, i, player->buffers);
|
||||
alSourcePlay(player->source);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error starting playback\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int UpdatePlayer(StreamPlayer *player)
|
||||
{
|
||||
ALint processed, state;
|
||||
|
||||
/* Get relevant source info */
|
||||
alGetSourcei(player->source, AL_SOURCE_STATE, &state);
|
||||
alGetSourcei(player->source, AL_BUFFERS_PROCESSED, &processed);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error checking source state\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unqueue and handle each processed buffer */
|
||||
while(processed > 0)
|
||||
{
|
||||
ALuint bufid;
|
||||
size_t got;
|
||||
|
||||
alSourceUnqueueBuffers(player->source, 1, &bufid);
|
||||
processed--;
|
||||
|
||||
/* Read the next chunk of data, refill the buffer, and queue it
|
||||
* back on the source */
|
||||
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);
|
||||
alSourceQueueBuffers(player->source, 1, &bufid);
|
||||
}
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error buffering data\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the source hasn't underrun */
|
||||
if(state != AL_PLAYING && state != AL_PAUSED)
|
||||
{
|
||||
ALint queued;
|
||||
|
||||
/* If no buffers are queued, playback is finished */
|
||||
alGetSourcei(player->source, AL_BUFFERS_QUEUED, &queued);
|
||||
if(queued == 0)
|
||||
return 0;
|
||||
|
||||
alSourcePlay(player->source);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error restarting playback\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
StreamPlayer *player;
|
||||
int i;
|
||||
|
||||
/* Print out usage if no file was specified */
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <filenames...>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(InitAL() != 0)
|
||||
return 1;
|
||||
|
||||
if(alIsExtensionPresent("AL_SOFT_buffer_samples"))
|
||||
{
|
||||
printf("AL_SOFT_buffer_samples supported!\n");
|
||||
palBufferSamplesSOFT = alGetProcAddress("alBufferSamplesSOFT");
|
||||
palIsBufferFormatSupportedSOFT = alGetProcAddress("alIsBufferFormatSupportedSOFT");
|
||||
}
|
||||
else
|
||||
printf("AL_SOFT_buffer_samples not supported\n");
|
||||
|
||||
player = NewPlayer();
|
||||
|
||||
/* Play each file listed on the command line */
|
||||
for(i = 1;i < argc;i++)
|
||||
{
|
||||
if(!OpenPlayerFile(player, argv[i]))
|
||||
continue;
|
||||
|
||||
fprintf(stderr, "Playing %s (%s, %s, %dhz)\n", argv[i],
|
||||
TypeName(player->type), ChannelsName(player->channels),
|
||||
player->rate);
|
||||
|
||||
if(!StartPlayer(player))
|
||||
{
|
||||
ClosePlayerFile(player);
|
||||
continue;
|
||||
}
|
||||
|
||||
while(UpdatePlayer(player))
|
||||
Sleep(10);
|
||||
|
||||
/* All done with this file. Close it and go to the next */
|
||||
ClosePlayerFile(player);
|
||||
}
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
/* All files done. Delete the player, and close OpenAL */
|
||||
DeletePlayer(player);
|
||||
player = NULL;
|
||||
|
||||
CloseAL();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
HRTF Support
|
||||
============
|
||||
|
||||
Starting with OpenAL Soft 1.14, HRTFs can be used to enable enhanced
|
||||
spatialization for both 3D (mono) and multi-channel sources, when used with
|
||||
headphones/stereo output. This can be enabled using the 'hrtf' config option.
|
||||
|
||||
For multi-channel sources this creates a virtual speaker effect, making it
|
||||
sound as if speakers provide a discrete position for each channel around the
|
||||
listener. For mono sources this provides much more versatility in the perceived
|
||||
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.
|
||||
|
||||
|
||||
External HRTF Data Sets
|
||||
=======================
|
||||
|
||||
OpenAL Soft also provides an option to use user-specified data sets, in
|
||||
addition to or in place of the built-in set. This allows users to provide their
|
||||
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).
|
||||
|
||||
==
|
||||
ALchar magic[8] = "MinPHR00";
|
||||
ALuint sampleRate;
|
||||
|
||||
ALushort hrirCount; /* Required value: 828 */
|
||||
ALushort hrirSize; /* Required value: 32 */
|
||||
ALubyte evCount; /* Required value: 19 */
|
||||
|
||||
ALushort evOffset[evCount]; /* Required values:
|
||||
{ 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755,
|
||||
791, 815, 827 } */
|
||||
|
||||
ALshort coefficients[hrirCount][hrirSize];
|
||||
ALubyte delays[hrirCount]; /* Element values must not exceed 127 */
|
||||
==
|
||||
|
||||
The data is described as thus:
|
||||
|
||||
The file first starts with the 8-byte marker, "MinPHR00", 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.
|
||||
|
||||
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 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
|
||||
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.
|
||||
+5
-9
@@ -5,15 +5,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#if defined(AL_BUILD_LIBRARY)
|
||||
#define AL_API __declspec(dllexport)
|
||||
#else
|
||||
#ifndef AL_API
|
||||
#if defined(AL_LIBTYPE_STATIC)
|
||||
#define AL_API
|
||||
#elif defined(_WIN32)
|
||||
#define AL_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
|
||||
#define AL_API __attribute__((visibility("protected")))
|
||||
#else
|
||||
#define AL_API extern
|
||||
#endif
|
||||
@@ -291,7 +287,7 @@ typedef void ALvoid;
|
||||
|
||||
|
||||
/** Errors: No Error. */
|
||||
#define AL_NO_ERROR AL_FALSE
|
||||
#define AL_NO_ERROR 0
|
||||
|
||||
/**
|
||||
* Invalid Name paramater passed to AL call.
|
||||
|
||||
+14
-9
@@ -5,15 +5,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#if defined(AL_BUILD_LIBRARY)
|
||||
#define ALC_API __declspec(dllexport)
|
||||
#else
|
||||
#ifndef ALC_API
|
||||
#if defined(AL_LIBTYPE_STATIC)
|
||||
#define ALC_API
|
||||
#elif defined(_WIN32)
|
||||
#define ALC_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined(AL_BUILD_LIBRARY) && defined(HAVE_GCC_VISIBILITY)
|
||||
#define ALC_API __attribute__((visibility("protected")))
|
||||
#else
|
||||
#define ALC_API extern
|
||||
#endif
|
||||
@@ -124,7 +120,7 @@ typedef void ALCvoid;
|
||||
/**
|
||||
* No error
|
||||
*/
|
||||
#define ALC_NO_ERROR ALC_FALSE
|
||||
#define ALC_NO_ERROR 0
|
||||
|
||||
/**
|
||||
* No device
|
||||
@@ -169,11 +165,20 @@ typedef void ALCvoid;
|
||||
/**
|
||||
* Capture extension
|
||||
*/
|
||||
#define ALC_EXT_CAPTURE 1
|
||||
#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
|
||||
#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
|
||||
#define ALC_CAPTURE_SAMPLES 0x312
|
||||
|
||||
|
||||
/**
|
||||
* ALC_ENUMERATE_ALL_EXT enums
|
||||
*/
|
||||
#define ALC_ENUMERATE_ALL_EXT 1
|
||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
|
||||
|
||||
/*
|
||||
* Context Management
|
||||
*/
|
||||
|
||||
+152
-72
@@ -61,6 +61,18 @@ extern "C" {
|
||||
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_MULAW
|
||||
#define AL_EXT_MULAW 1
|
||||
#define AL_FORMAT_MONO_MULAW_EXT 0x10014
|
||||
#define AL_FORMAT_STEREO_MULAW_EXT 0x10015
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_ALAW
|
||||
#define AL_EXT_ALAW 1
|
||||
#define AL_FORMAT_MONO_ALAW_EXT 0x10016
|
||||
#define AL_FORMAT_STEREO_ALAW_EXT 0x10017
|
||||
#endif
|
||||
|
||||
#ifndef ALC_LOKI_audio_channel
|
||||
#define ALC_LOKI_audio_channel 1
|
||||
#define ALC_CHAN_MAIN_LOKI 0x500001
|
||||
@@ -68,12 +80,6 @@ extern "C" {
|
||||
#define ALC_CHAN_CD_LOKI 0x500003
|
||||
#endif
|
||||
|
||||
#ifndef ALC_ENUMERATE_ALL_EXT
|
||||
#define ALC_ENUMERATE_ALL_EXT 1
|
||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_MCFORMATS
|
||||
#define AL_EXT_MCFORMATS 1
|
||||
#define AL_FORMAT_QUAD8 0x1204
|
||||
@@ -110,16 +116,6 @@ extern "C" {
|
||||
#define AL_FORMAT_STEREO_IMA4 0x1301
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_buffer_sub_data
|
||||
#define AL_EXT_buffer_sub_data 1
|
||||
#define AL_BYTE_RW_OFFSETS_EXT 0x1031
|
||||
#define AL_SAMPLE_RW_OFFSETS_EXT 0x1032
|
||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATAEXTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_STATIC_BUFFER
|
||||
#define AL_EXT_STATIC_BUFFER 1
|
||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
|
||||
@@ -128,62 +124,6 @@ AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_sample_buffer_object
|
||||
#define AL_EXT_sample_buffer_object 1
|
||||
typedef ptrdiff_t ALintptrEXT;
|
||||
typedef ptrdiff_t ALsizeiptrEXT;
|
||||
#define AL_SAMPLE_SOURCE_EXT 0x1040
|
||||
#define AL_SAMPLE_SINK_EXT 0x1041
|
||||
#define AL_READ_ONLY_EXT 0x1042
|
||||
#define AL_WRITE_ONLY_EXT 0x1043
|
||||
#define AL_READ_WRITE_EXT 0x1044
|
||||
#define AL_STREAM_WRITE_EXT 0x1045
|
||||
#define AL_STREAM_READ_EXT 0x1046
|
||||
#define AL_STREAM_COPY_EXT 0x1047
|
||||
#define AL_STATIC_WRITE_EXT 0x1048
|
||||
#define AL_STATIC_READ_EXT 0x1049
|
||||
#define AL_STATIC_COPY_EXT 0x104A
|
||||
#define AL_DYNAMIC_WRITE_EXT 0x104B
|
||||
#define AL_DYNAMIC_READ_EXT 0x104C
|
||||
#define AL_DYNAMIC_COPY_EXT 0x104D
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGENDATABUFFERSEXTPROC)(ALsizei n,ALuint *puiBuffers);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDELETEDATABUFFERSEXTPROC)(ALsizei n, const ALuint *puiBuffers);
|
||||
typedef ALboolean (AL_APIENTRY*PFNALISDATABUFFEREXTPROC)(ALuint uiBuffer);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERDATAEXTPROC)(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERSUBDATAEXTPROC)(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERFEXTPROC)(ALuint buffer, ALenum eParam, ALfloat flValue);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERFVEXTPROC)(ALuint buffer, ALenum eParam, const ALfloat* flValues);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERIEXTPROC)(ALuint buffer, ALenum eParam, ALint lValue);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALDATABUFFERIVEXTPROC)(ALuint buffer, ALenum eParam, const ALint* plValues);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERFEXTPROC)(ALuint buffer, ALenum eParam, ALfloat *pflValue);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERFVEXTPROC)(ALuint buffer, ALenum eParam, ALfloat* pflValues);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERIEXTPROC)(ALuint buffer, ALenum eParam, ALint *plValue);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALGETDATABUFFERIVEXTPROC)(ALuint buffer, ALenum eParam, ALint* plValues);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALSELECTDATABUFFEREXTPROC)(ALenum target, ALuint uiBuffer);
|
||||
typedef ALvoid* (AL_APIENTRY*PFNALMAPDATABUFFEREXTPROC)(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access);
|
||||
typedef ALvoid (AL_APIENTRY*PFNALUNMAPDATABUFFEREXTPROC)(ALuint uiBuffer);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers);
|
||||
AL_API ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint uiBuffer);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data);
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint buffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue);
|
||||
AL_API ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues);
|
||||
AL_API ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer);
|
||||
AL_API ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access);
|
||||
AL_API ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALC_EXT_EFX
|
||||
#define ALC_EXT_EFX 1
|
||||
#include "efx.h"
|
||||
@@ -209,6 +149,146 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void);
|
||||
#define AL_SOURCE_DISTANCE_MODEL 0x200
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_buffer_sub_data
|
||||
#define AL_SOFT_buffer_sub_data 1
|
||||
#define AL_BYTE_RW_OFFSETS_SOFT 0x1031
|
||||
#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032
|
||||
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_loop_points
|
||||
#define AL_SOFT_loop_points 1
|
||||
#define AL_LOOP_POINTS_SOFT 0x2015
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_FOLDBACK
|
||||
#define AL_EXT_FOLDBACK 1
|
||||
#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK"
|
||||
#define AL_FOLDBACK_EVENT_BLOCK 0x4112
|
||||
#define AL_FOLDBACK_EVENT_START 0x4111
|
||||
#define AL_FOLDBACK_EVENT_STOP 0x4113
|
||||
#define AL_FOLDBACK_MODE_MONO 0x4101
|
||||
#define AL_FOLDBACK_MODE_STEREO 0x4102
|
||||
typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei);
|
||||
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK);
|
||||
typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback);
|
||||
AL_API void AL_APIENTRY alRequestFoldbackStop(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALC_EXT_DEDICATED
|
||||
#define ALC_EXT_DEDICATED 1
|
||||
#define AL_DEDICATED_GAIN 0x0001
|
||||
#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001
|
||||
#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_buffer_samples
|
||||
#define AL_SOFT_buffer_samples 1
|
||||
/* Channel configurations */
|
||||
#define AL_MONO_SOFT 0x1500
|
||||
#define AL_STEREO_SOFT 0x1501
|
||||
#define AL_REAR_SOFT 0x1502
|
||||
#define AL_QUAD_SOFT 0x1503
|
||||
#define AL_5POINT1_SOFT 0x1504
|
||||
#define AL_6POINT1_SOFT 0x1505
|
||||
#define AL_7POINT1_SOFT 0x1506
|
||||
|
||||
/* Sample types */
|
||||
#define AL_BYTE_SOFT 0x1400
|
||||
#define AL_UNSIGNED_BYTE_SOFT 0x1401
|
||||
#define AL_SHORT_SOFT 0x1402
|
||||
#define AL_UNSIGNED_SHORT_SOFT 0x1403
|
||||
#define AL_INT_SOFT 0x1404
|
||||
#define AL_UNSIGNED_INT_SOFT 0x1405
|
||||
#define AL_FLOAT_SOFT 0x1406
|
||||
#define AL_DOUBLE_SOFT 0x1407
|
||||
#define AL_BYTE3_SOFT 0x1408
|
||||
#define AL_UNSIGNED_BYTE3_SOFT 0x1409
|
||||
|
||||
/* Storage formats */
|
||||
#define AL_MONO8_SOFT 0x1100
|
||||
#define AL_MONO16_SOFT 0x1101
|
||||
#define AL_MONO32F_SOFT 0x10010
|
||||
#define AL_STEREO8_SOFT 0x1102
|
||||
#define AL_STEREO16_SOFT 0x1103
|
||||
#define AL_STEREO32F_SOFT 0x10011
|
||||
#define AL_QUAD8_SOFT 0x1204
|
||||
#define AL_QUAD16_SOFT 0x1205
|
||||
#define AL_QUAD32F_SOFT 0x1206
|
||||
#define AL_REAR8_SOFT 0x1207
|
||||
#define AL_REAR16_SOFT 0x1208
|
||||
#define AL_REAR32F_SOFT 0x1209
|
||||
#define AL_5POINT1_8_SOFT 0x120A
|
||||
#define AL_5POINT1_16_SOFT 0x120B
|
||||
#define AL_5POINT1_32F_SOFT 0x120C
|
||||
#define AL_6POINT1_8_SOFT 0x120D
|
||||
#define AL_6POINT1_16_SOFT 0x120E
|
||||
#define AL_6POINT1_32F_SOFT 0x120F
|
||||
#define AL_7POINT1_8_SOFT 0x1210
|
||||
#define AL_7POINT1_16_SOFT 0x1211
|
||||
#define AL_7POINT1_32F_SOFT 0x1212
|
||||
|
||||
/* Buffer attributes */
|
||||
#define AL_INTERNAL_FORMAT_SOFT 0x2008
|
||||
#define AL_BYTE_LENGTH_SOFT 0x2009
|
||||
#define AL_SAMPLE_LENGTH_SOFT 0x200A
|
||||
#define AL_SEC_LENGTH_SOFT 0x200B
|
||||
|
||||
typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
|
||||
typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*);
|
||||
typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
|
||||
typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
||||
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
|
||||
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
|
||||
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_direct_channels
|
||||
#define AL_SOFT_direct_channels 1
|
||||
#define AL_DIRECT_CHANNELS_SOFT 0x1033
|
||||
#endif
|
||||
|
||||
#ifndef ALC_SOFT_loopback
|
||||
#define ALC_SOFT_loopback 1
|
||||
#define ALC_FORMAT_CHANNELS_SOFT 0x1990
|
||||
#define ALC_FORMAT_TYPE_SOFT 0x1991
|
||||
|
||||
/* Sample types */
|
||||
#define ALC_BYTE_SOFT 0x1400
|
||||
#define ALC_UNSIGNED_BYTE_SOFT 0x1401
|
||||
#define ALC_SHORT_SOFT 0x1402
|
||||
#define ALC_UNSIGNED_SHORT_SOFT 0x1403
|
||||
#define ALC_INT_SOFT 0x1404
|
||||
#define ALC_UNSIGNED_INT_SOFT 0x1405
|
||||
#define ALC_FLOAT_SOFT 0x1406
|
||||
|
||||
/* Channel configurations */
|
||||
#define ALC_MONO_SOFT 0x1500
|
||||
#define ALC_STEREO_SOFT 0x1501
|
||||
#define ALC_QUAD_SOFT 0x1503
|
||||
#define ALC_5POINT1_SOFT 0x1504
|
||||
#define ALC_6POINT1_SOFT 0x1505
|
||||
#define ALC_7POINT1_SOFT 0x1506
|
||||
|
||||
typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*);
|
||||
typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum);
|
||||
typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName);
|
||||
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type);
|
||||
ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/* The tokens that would be defined here are already defined in efx.h. This
|
||||
* empty file is here to provide compatibility with Windows-based projects
|
||||
* that would include it. */
|
||||
@@ -0,0 +1,402 @@
|
||||
/* Reverb presets for EFX */
|
||||
|
||||
#ifndef EFX_PRESETS_H
|
||||
#define EFX_PRESETS_H
|
||||
|
||||
#ifndef EFXEAXREVERBPROPERTIES_DEFINED
|
||||
#define EFXEAXREVERBPROPERTIES_DEFINED
|
||||
typedef struct {
|
||||
float flDensity;
|
||||
float flDiffusion;
|
||||
float flGain;
|
||||
float flGainHF;
|
||||
float flGainLF;
|
||||
float flDecayTime;
|
||||
float flDecayHFRatio;
|
||||
float flDecayLFRatio;
|
||||
float flReflectionsGain;
|
||||
float flReflectionsDelay;
|
||||
float flReflectionsPan[3];
|
||||
float flLateReverbGain;
|
||||
float flLateReverbDelay;
|
||||
float flLateReverbPan[3];
|
||||
float flEchoTime;
|
||||
float flEchoDepth;
|
||||
float flModulationTime;
|
||||
float flModulationDepth;
|
||||
float flAirAbsorptionGainHF;
|
||||
float flHFReference;
|
||||
float flLFReference;
|
||||
float flRoomRolloffFactor;
|
||||
int iDecayHFLimit;
|
||||
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
|
||||
#endif
|
||||
|
||||
/* Default Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_GENERIC \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PADDEDCELL \
|
||||
{ 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ROOM \
|
||||
{ 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_BATHROOM \
|
||||
{ 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_LIVINGROOM \
|
||||
{ 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_STONEROOM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_AUDITORIUM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CONCERTHALL \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CAVE \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ARENA \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_HANGAR \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CARPETEDHALLWAY \
|
||||
{ 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_HALLWAY \
|
||||
{ 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_STONECORRIDOR \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ALLEY \
|
||||
{ 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FOREST \
|
||||
{ 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY \
|
||||
{ 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_MOUNTAINS \
|
||||
{ 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_QUARRY \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PLAIN \
|
||||
{ 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PARKINGLOT \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SEWERPIPE \
|
||||
{ 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_UNDERWATER \
|
||||
{ 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRUGGED \
|
||||
{ 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DIZZY \
|
||||
{ 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PSYCHOTIC \
|
||||
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
/* Castle Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \
|
||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \
|
||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \
|
||||
{ 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \
|
||||
{ 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_HALL \
|
||||
{ 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \
|
||||
{ 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_COURTYARD \
|
||||
{ 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CASTLE_ALCOVE \
|
||||
{ 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Factory Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \
|
||||
{ 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \
|
||||
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \
|
||||
{ 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \
|
||||
{ 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \
|
||||
{ 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_HALL \
|
||||
{ 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \
|
||||
{ 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_COURTYARD \
|
||||
{ 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_FACTORY_ALCOVE \
|
||||
{ 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Ice Palace Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \
|
||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \
|
||||
{ 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \
|
||||
{ 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \
|
||||
{ 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \
|
||||
{ 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_HALL \
|
||||
{ 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \
|
||||
{ 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \
|
||||
{ 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \
|
||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Space Station Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \
|
||||
{ 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \
|
||||
{ 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \
|
||||
{ 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \
|
||||
{ 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \
|
||||
{ 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_HALL \
|
||||
{ 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \
|
||||
{ 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \
|
||||
{ 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Wooden Galleon Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_HALL \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_COURTYARD \
|
||||
{ 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_WOODEN_ALCOVE \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Sports Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \
|
||||
{ 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \
|
||||
{ 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \
|
||||
{ 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \
|
||||
{ 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Prefab Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \
|
||||
{ 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \
|
||||
{ 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \
|
||||
{ 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PREFAB_CARAVAN \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
/* Dome and Pipe Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_DOME_TOMB \
|
||||
{ 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PIPE_SMALL \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DOME_SAINTPAULS \
|
||||
{ 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PIPE_LONGTHIN \
|
||||
{ 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PIPE_LARGE \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_PIPE_RESONANT \
|
||||
{ 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 }
|
||||
|
||||
/* Outdoors Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \
|
||||
{ 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \
|
||||
{ 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \
|
||||
{ 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_OUTDOORS_CREEK \
|
||||
{ 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \
|
||||
{ 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||
|
||||
/* Mood Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_MOOD_HEAVEN \
|
||||
{ 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_MOOD_HELL \
|
||||
{ 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_MOOD_MEMORY \
|
||||
{ 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
/* Driving Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \
|
||||
{ 1.0000f, 0.0000f, 3.1623f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \
|
||||
{ 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \
|
||||
{ 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \
|
||||
{ 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \
|
||||
{ 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \
|
||||
{ 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_DRIVING_TUNNEL \
|
||||
{ 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 }
|
||||
|
||||
/* City Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_STREETS \
|
||||
{ 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_SUBWAY \
|
||||
{ 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_MUSEUM \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_LIBRARY \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_UNDERPASS \
|
||||
{ 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CITY_ABANDONED \
|
||||
{ 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
/* Misc. Presets */
|
||||
|
||||
#define EFX_REVERB_PRESET_DUSTYROOM \
|
||||
{ 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_CHAPEL \
|
||||
{ 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
|
||||
|
||||
#define EFX_REVERB_PRESET_SMALLWATERROOM \
|
||||
{ 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
|
||||
|
||||
#endif /* EFX_PRESETS_H */
|
||||
+39
-39
@@ -201,12 +201,12 @@ extern "C" {
|
||||
|
||||
/* Effect object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*);
|
||||
@@ -214,12 +214,12 @@ typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
/* Filter object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*);
|
||||
typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*);
|
||||
@@ -227,12 +227,12 @@ typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*);
|
||||
|
||||
/* Auxiliary Effect Slot object function types. */
|
||||
typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*);
|
||||
typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*);
|
||||
typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*);
|
||||
@@ -240,36 +240,36 @@ typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat
|
||||
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects);
|
||||
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
|
||||
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters);
|
||||
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
|
||||
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
|
||||
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots);
|
||||
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
|
||||
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
|
||||
@@ -279,35 +279,35 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
|
||||
/* Filter ranges and defaults. */
|
||||
|
||||
/* Lowpass filter */
|
||||
#define LOWPASS_MIN_GAIN (0.0f)
|
||||
#define LOWPASS_MAX_GAIN (1.0f)
|
||||
#define LOWPASS_DEFAULT_GAIN (1.0f)
|
||||
#define AL_LOWPASS_MIN_GAIN (0.0f)
|
||||
#define AL_LOWPASS_MAX_GAIN (1.0f)
|
||||
#define AL_LOWPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define LOWPASS_MIN_GAINHF (0.0f)
|
||||
#define LOWPASS_MAX_GAINHF (1.0f)
|
||||
#define LOWPASS_DEFAULT_GAINHF (1.0f)
|
||||
#define AL_LOWPASS_MIN_GAINHF (0.0f)
|
||||
#define AL_LOWPASS_MAX_GAINHF (1.0f)
|
||||
#define AL_LOWPASS_DEFAULT_GAINHF (1.0f)
|
||||
|
||||
/* Highpass filter */
|
||||
#define HIGHPASS_MIN_GAIN (0.0f)
|
||||
#define HIGHPASS_MAX_GAIN (1.0f)
|
||||
#define HIGHPASS_DEFAULT_GAIN (1.0f)
|
||||
#define AL_HIGHPASS_MIN_GAIN (0.0f)
|
||||
#define AL_HIGHPASS_MAX_GAIN (1.0f)
|
||||
#define AL_HIGHPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define HIGHPASS_MIN_GAINLF (0.0f)
|
||||
#define HIGHPASS_MAX_GAINLF (1.0f)
|
||||
#define HIGHPASS_DEFAULT_GAINLF (1.0f)
|
||||
#define AL_HIGHPASS_MIN_GAINLF (0.0f)
|
||||
#define AL_HIGHPASS_MAX_GAINLF (1.0f)
|
||||
#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f)
|
||||
|
||||
/* Bandpass filter */
|
||||
#define BANDPASS_MIN_GAIN (0.0f)
|
||||
#define BANDPASS_MAX_GAIN (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAIN (1.0f)
|
||||
#define AL_BANDPASS_MIN_GAIN (0.0f)
|
||||
#define AL_BANDPASS_MAX_GAIN (1.0f)
|
||||
#define AL_BANDPASS_DEFAULT_GAIN (1.0f)
|
||||
|
||||
#define BANDPASS_MIN_GAINHF (0.0f)
|
||||
#define BANDPASS_MAX_GAINHF (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAINHF (1.0f)
|
||||
#define AL_BANDPASS_MIN_GAINHF (0.0f)
|
||||
#define AL_BANDPASS_MAX_GAINHF (1.0f)
|
||||
#define AL_BANDPASS_DEFAULT_GAINHF (1.0f)
|
||||
|
||||
#define BANDPASS_MIN_GAINLF (0.0f)
|
||||
#define BANDPASS_MAX_GAINLF (1.0f)
|
||||
#define BANDPASS_DEFAULT_GAINLF (1.0f)
|
||||
#define AL_BANDPASS_MIN_GAINLF (0.0f)
|
||||
#define AL_BANDPASS_MAX_GAINLF (1.0f)
|
||||
#define AL_BANDPASS_DEFAULT_GAINLF (1.0f)
|
||||
|
||||
|
||||
/* Effect parameter ranges and defaults. */
|
||||
|
||||
+1
-1
@@ -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}
|
||||
Cflags: -I${includedir} @PKG_CONFIG_CFLAGS@
|
||||
|
||||
@@ -0,0 +1,753 @@
|
||||
/**
|
||||
* HRTF utility for producing and demonstrating the process of creating an
|
||||
* OpenAL Soft compatible HRIR data set.
|
||||
*
|
||||
* It can currently make use of the 44.1 KHz diffuse and compact KEMAR HRIRs
|
||||
* provided by MIT at:
|
||||
*
|
||||
* http://sound.media.mit.edu/resources/KEMAR.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
static double round(double val)
|
||||
{
|
||||
if(val < 0.0)
|
||||
return ceil(val - 0.5);
|
||||
return floor(val + 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The sample rate of the MIT HRIR data sets.
|
||||
#define MIT_IR_RATE (44100)
|
||||
|
||||
// The total number of used impulse responses from the MIT HRIR data sets.
|
||||
#define MIT_IR_COUNT (828)
|
||||
|
||||
// The size (in samples) of each HRIR in the MIT data sets.
|
||||
#define MIT_IR_SIZE (128)
|
||||
|
||||
// The total number of elevations given a step of 10 degrees.
|
||||
#define MIT_EV_COUNT (19)
|
||||
|
||||
// The first elevation that the MIT data sets have HRIRs for.
|
||||
#define MIT_EV_START (5)
|
||||
|
||||
// The head radius (in meters) used by the MIT data sets.
|
||||
#define MIT_RADIUS (0.09f)
|
||||
|
||||
// The source to listener distance (in meters) used by the MIT data sets.
|
||||
#define MIT_DISTANCE (1.4f)
|
||||
|
||||
// The resulting size (in samples) of a mininum-phase reconstructed HRIR.
|
||||
#define MIN_IR_SIZE (32)
|
||||
|
||||
// The size (in samples) of the real cepstrum used in reconstruction. This
|
||||
// needs to be large enough to reduce inaccuracy.
|
||||
#define CEP_SIZE (8192)
|
||||
|
||||
// The OpenAL Soft HRTF format marker. It stands for minimum-phase head
|
||||
// response protocol 00.
|
||||
#define MHR_FORMAT ("MinPHR00")
|
||||
|
||||
typedef struct ComplexT ComplexT;
|
||||
typedef struct HrirDataT HrirDataT;
|
||||
|
||||
// A complex number type.
|
||||
struct ComplexT {
|
||||
float mVec [2];
|
||||
};
|
||||
|
||||
// The HRIR data definition. This can be used to add support for new HRIR
|
||||
// sources in the future.
|
||||
struct HrirDataT {
|
||||
int mIrRate,
|
||||
mIrCount,
|
||||
mIrSize,
|
||||
mEvCount,
|
||||
mEvStart;
|
||||
const int * mEvOffset,
|
||||
* mAzCount;
|
||||
float mRadius,
|
||||
mDistance,
|
||||
* mHrirs,
|
||||
* mHrtds,
|
||||
mMaxHrtd;
|
||||
};
|
||||
|
||||
// The linear index of the first HRIR for each elevation of the MIT data set.
|
||||
static const int MIT_EV_OFFSET [MIT_EV_COUNT] = {
|
||||
0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827
|
||||
},
|
||||
|
||||
// The count of distinct azimuth steps for each elevation in the MIT data
|
||||
// set.
|
||||
MIT_AZ_COUNT [MIT_EV_COUNT] = {
|
||||
1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1
|
||||
};
|
||||
|
||||
// Performs a forward Fast Fourier Transform.
|
||||
static void FftProc (int n, const ComplexT * fftIn, ComplexT * fftOut) {
|
||||
int m2, rk, k, m;
|
||||
float a, b;
|
||||
int i;
|
||||
float wx, wy;
|
||||
int j, km2;
|
||||
float tx, ty, wyd;
|
||||
|
||||
// Data copy and bit-reversal ordering.
|
||||
m2 = (n >> 1);
|
||||
rk = 0;
|
||||
for (k = 0; k < n; k ++) {
|
||||
fftOut [rk] . mVec [0] = fftIn [k] . mVec [0];
|
||||
fftOut [rk] . mVec [1] = fftIn [k] . mVec [1];
|
||||
if (k < (n - 1)) {
|
||||
m = m2;
|
||||
while (rk >= m) {
|
||||
rk -= m;
|
||||
m >>= 1;
|
||||
}
|
||||
rk += m;
|
||||
}
|
||||
}
|
||||
// Perform the FFT.
|
||||
m2 = 1;
|
||||
for (m = 2; m <= n; m <<= 1) {
|
||||
a = sin (M_PI / m);
|
||||
a = 2.0f * a * a;
|
||||
b = sin (2.0f * M_PI / m);
|
||||
for (i = 0; i < n; i += m) {
|
||||
wx = 1.0f;
|
||||
wy = 0.0f;
|
||||
for (k = i, j = 0; j < m2; k ++, j ++) {
|
||||
km2 = k + m2;
|
||||
tx = (wx * fftOut [km2] . mVec [0]) - (wy * fftOut [km2] . mVec [1]);
|
||||
ty = (wx * fftOut [km2] . mVec [1]) + (wy * fftOut [km2] . mVec [0]);
|
||||
fftOut [km2] . mVec [0] = fftOut [k] . mVec [0] - tx;
|
||||
fftOut [km2] . mVec [1] = fftOut [k] . mVec [1] - ty;
|
||||
fftOut [k] . mVec [0] += tx;
|
||||
fftOut [k] . mVec [1] += ty;
|
||||
wyd = (a * wy) - (b * wx);
|
||||
wx -= (a * wx) + (b * wy);
|
||||
wy -= wyd;
|
||||
}
|
||||
}
|
||||
m2 = m;
|
||||
}
|
||||
}
|
||||
|
||||
// Performs an inverse Fast Fourier Transform.
|
||||
static void FftInvProc (int n, const ComplexT * fftIn, ComplexT * fftOut) {
|
||||
int m2, rk, k, m;
|
||||
float a, b;
|
||||
int i;
|
||||
float wx, wy;
|
||||
int j, km2;
|
||||
float tx, ty, wyd, invn;
|
||||
|
||||
// Data copy and bit-reversal ordering.
|
||||
m2 = (n >> 1);
|
||||
rk = 0;
|
||||
for (k = 0; k < n; k ++) {
|
||||
fftOut [rk] . mVec [0] = fftIn [k] . mVec [0];
|
||||
fftOut [rk] . mVec [1] = fftIn [k] . mVec [1];
|
||||
if (k < (n - 1)) {
|
||||
m = m2;
|
||||
while (rk >= m) {
|
||||
rk -= m;
|
||||
m >>= 1;
|
||||
}
|
||||
rk += m;
|
||||
}
|
||||
}
|
||||
// Perform the IFFT.
|
||||
m2 = 1;
|
||||
for (m = 2; m <= n; m <<= 1) {
|
||||
a = sin (M_PI / m);
|
||||
a = 2.0f * a * a;
|
||||
b = -sin (2.0f * M_PI / m);
|
||||
for (i = 0; i < n; i += m) {
|
||||
wx = 1.0f;
|
||||
wy = 0.0f;
|
||||
for (k = i, j = 0; j < m2; k ++, j ++) {
|
||||
km2 = k + m2;
|
||||
tx = (wx * fftOut [km2] . mVec [0]) - (wy * fftOut [km2] . mVec [1]);
|
||||
ty = (wx * fftOut [km2] . mVec [1]) + (wy * fftOut [km2] . mVec [0]);
|
||||
fftOut [km2] . mVec [0] = fftOut [k] . mVec [0] - tx;
|
||||
fftOut [km2] . mVec [1] = fftOut [k] . mVec [1] - ty;
|
||||
fftOut [k] . mVec [0] += tx;
|
||||
fftOut [k] . mVec [1] += ty;
|
||||
wyd = (a * wy) - (b * wx);
|
||||
wx -= (a * wx) + (b * wy);
|
||||
wy -= wyd;
|
||||
}
|
||||
}
|
||||
m2 = m;
|
||||
}
|
||||
// Normalize the samples.
|
||||
invn = 1.0f / n;
|
||||
for (i = 0; i < n; i ++) {
|
||||
fftOut [i] . mVec [0] *= invn;
|
||||
fftOut [i] . mVec [1] *= invn;
|
||||
}
|
||||
}
|
||||
|
||||
// Complex absolute value.
|
||||
static void ComplexAbs (const ComplexT * in, ComplexT * out) {
|
||||
out -> mVec [0] = sqrt ((in -> mVec [0] * in -> mVec [0]) + (in -> mVec [1] * in -> mVec [1]));
|
||||
out -> mVec [1] = 0.0f;
|
||||
}
|
||||
|
||||
// Complex logarithm.
|
||||
static void ComplexLog (const ComplexT * in, ComplexT * out) {
|
||||
float r, t;
|
||||
|
||||
r = sqrt ((in -> mVec [0] * in -> mVec [0]) + (in -> mVec [1] * in -> mVec [1]));
|
||||
t = atan2 (in -> mVec [1], in -> mVec [0]);
|
||||
if (t < 0.0f)
|
||||
t += 2.0f * M_PI;
|
||||
out -> mVec [0] = log (r);
|
||||
out -> mVec [1] = t;
|
||||
}
|
||||
|
||||
// Complex exponent.
|
||||
static void ComplexExp (const ComplexT * in, ComplexT * out) {
|
||||
float e;
|
||||
|
||||
e = exp (in -> mVec [0]);
|
||||
out -> mVec [0] = e * cos (in -> mVec [1]);
|
||||
out -> mVec [1] = e * sin (in -> mVec [1]);
|
||||
}
|
||||
|
||||
// Calculates the real cepstrum of a given impulse response. It currently
|
||||
// uses a fixed cepstrum size. To make this more robust, it should be
|
||||
// rewritten to handle a variable size cepstrum.
|
||||
static void RealCepstrum (int irSize, const float * ir, float cep [CEP_SIZE]) {
|
||||
ComplexT in [CEP_SIZE], out [CEP_SIZE];
|
||||
int index;
|
||||
|
||||
for (index = 0; index < irSize; index ++) {
|
||||
in [index] . mVec [0] = ir [index];
|
||||
in [index] . mVec [1] = 0.0f;
|
||||
}
|
||||
for (; index < CEP_SIZE; index ++) {
|
||||
in [index] . mVec [0] = 0.0f;
|
||||
in [index] . mVec [1] = 0.0f;
|
||||
}
|
||||
FftProc (CEP_SIZE, in, out);
|
||||
for (index = 0; index < CEP_SIZE; index ++) {
|
||||
ComplexAbs (& out [index], & out [index]);
|
||||
if (out [index] . mVec [0] < 0.000001f)
|
||||
out [index] . mVec [0] = 0.000001f;
|
||||
ComplexLog (& out [index], & in [index]);
|
||||
}
|
||||
FftInvProc (CEP_SIZE, in, out);
|
||||
for (index = 0; index < CEP_SIZE; index ++)
|
||||
cep [index] = out [index] . mVec [0];
|
||||
}
|
||||
|
||||
// Reconstructs the minimum-phase impulse response for a given real cepstrum.
|
||||
// Like the above function, this should eventually be modified to handle a
|
||||
// variable size cepstrum.
|
||||
static void MinimumPhase (const float cep [CEP_SIZE], int irSize, float * mpIr) {
|
||||
ComplexT in [CEP_SIZE], out [CEP_SIZE];
|
||||
int index;
|
||||
|
||||
in [0] . mVec [0] = cep [0];
|
||||
for (index = 1; index < (CEP_SIZE / 2); index ++)
|
||||
in [index] . mVec [0] = 2.0f * cep [index];
|
||||
if ((CEP_SIZE % 2) != 1) {
|
||||
in [index] . mVec [0] = cep [index];
|
||||
index ++;
|
||||
}
|
||||
for (; index < CEP_SIZE; index ++)
|
||||
in [index] . mVec [0] = 0.0f;
|
||||
for (index = 0; index < CEP_SIZE; index ++)
|
||||
in [index] . mVec [1] = 0.0f;
|
||||
FftProc (CEP_SIZE, in, out);
|
||||
for (index = 0; index < CEP_SIZE; index ++)
|
||||
ComplexExp (& out [index], & in [index]);
|
||||
FftInvProc (CEP_SIZE, in, out);
|
||||
for (index = 0; index < irSize; index ++)
|
||||
mpIr [index] = out [index] . mVec [0];
|
||||
}
|
||||
|
||||
// Calculate the left-ear time delay using a spherical head model.
|
||||
static float CalcLTD (float ev, float az, float rad, float dist) {
|
||||
float azp, dlp, l, al;
|
||||
|
||||
azp = asin (cos (ev) * sin (az));
|
||||
dlp = sqrt ((dist * dist) + (rad * rad) + (2.0f * dist * rad * sin (azp)));
|
||||
l = sqrt ((dist * dist) - (rad * rad));
|
||||
al = (0.5f * M_PI) + azp;
|
||||
if (dlp > l)
|
||||
dlp = l + (rad * (al - acos (rad / dist)));
|
||||
return (dlp / 343.3f);
|
||||
}
|
||||
|
||||
// Read a 16-bit little-endian integer from a file and convert it to a 32-bit
|
||||
// floating-point value in the range of -1.0 to 1.0.
|
||||
static int ReadInt16LeAsFloat32 (const char * fileName, FILE * fp, float * val) {
|
||||
ALubyte vb [2];
|
||||
ALushort vw;
|
||||
|
||||
if (fread (vb, 1, sizeof (vb), fp) != sizeof (vb)) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error reading from file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
vw = (((unsigned short) vb [1]) << 8) | vb [0];
|
||||
(* val) = ((short) vw) / 32768.0f;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Write a string to a file.
|
||||
static int WriteString (const char * val, const char * fileName, FILE * fp) {
|
||||
size_t len;
|
||||
|
||||
len = strlen (val);
|
||||
if (fwrite (val, 1, len, fp) != len) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error writing to file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Write a 32-bit floating-point value in the range of -1.0 to 1.0 to a file
|
||||
// as a 16-bit little-endian integer.
|
||||
static int WriteFloat32AsInt16Le (float val, const char * fileName, FILE * fp) {
|
||||
ALshort vw;
|
||||
ALubyte vb [2];
|
||||
|
||||
vw = (short) round (32767.0f * val);
|
||||
vb [0] = vw & 0x00FF;
|
||||
vb [1] = (vw >> 8) & 0x00FF;
|
||||
if (fwrite (vb, 1, sizeof (vb), fp) != sizeof (vb)) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error writing to file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Write a 32-bit little-endian unsigned integer to a file.
|
||||
static int WriteUInt32Le (ALuint val, const char * fileName, FILE * fp) {
|
||||
ALubyte vb [4];
|
||||
|
||||
vb [0] = val & 0x000000FF;
|
||||
vb [1] = (val >> 8) & 0x000000FF;
|
||||
vb [2] = (val >> 16) & 0x000000FF;
|
||||
vb [3] = (val >> 24) & 0x000000FF;
|
||||
if (fwrite (vb, 1, sizeof (vb), fp) != sizeof (vb)) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error writing to file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Write a 16-bit little-endian unsigned integer to a file.
|
||||
static int WriteUInt16Le (ALushort val, const char * fileName, FILE * fp) {
|
||||
ALubyte vb [2];
|
||||
|
||||
vb [0] = val & 0x00FF;
|
||||
vb [1] = (val >> 8) & 0x00FF;
|
||||
if (fwrite (vb, 1, sizeof (vb), fp) != sizeof (vb)) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error writing to file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Write an 8-bit unsigned integer to a file.
|
||||
static int WriteUInt8 (ALubyte val, const char * fileName, FILE * fp) {
|
||||
if (fwrite (& val, 1, sizeof (val), fp) != sizeof (val)) {
|
||||
fclose (fp);
|
||||
fprintf (stderr, "Error writing to file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Load the MIT HRIRs. This loads the entire diffuse or compact set starting
|
||||
// counter-clockwise up at the bottom elevation and clockwise at the forward
|
||||
// azimuth.
|
||||
static int LoadMitHrirs (const char * baseName, HrirDataT * hData) {
|
||||
const int EV_ANGLE [MIT_EV_COUNT] = {
|
||||
-90, -80, -70, -60, -50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90
|
||||
};
|
||||
int e, a;
|
||||
char fileName [1024];
|
||||
FILE * fp = NULL;
|
||||
int j0, j1, i;
|
||||
float s;
|
||||
|
||||
for (e = MIT_EV_START; e < MIT_EV_COUNT; e ++) {
|
||||
for (a = 0; a < MIT_AZ_COUNT [e]; a ++) {
|
||||
// The data packs the first 180 degrees in the left channel, and
|
||||
// the last 180 degrees in the right channel.
|
||||
if (round ((360.0f / MIT_AZ_COUNT [e]) * a) > 180.0f)
|
||||
break;
|
||||
// Determine which file to open.
|
||||
snprintf (fileName, 1023, "%s%d/H%de%03da.wav", baseName, EV_ANGLE [e], EV_ANGLE [e], (int) round ((360.0f / MIT_AZ_COUNT [e]) * a));
|
||||
if ((fp = fopen (fileName, "rb")) == NULL) {
|
||||
fprintf (stderr, "Could not open file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
// Assuming they have not changed format, skip the .WAV header.
|
||||
fseek (fp, 44, SEEK_SET);
|
||||
// Map the left and right channels to their appropriate azimuth
|
||||
// offsets.
|
||||
j0 = (MIT_EV_OFFSET [e] + a) * MIT_IR_SIZE;
|
||||
j1 = (MIT_EV_OFFSET [e] + ((MIT_AZ_COUNT [e] - a) % MIT_AZ_COUNT [e])) * MIT_IR_SIZE;
|
||||
// Read in the data, converting it to floating-point.
|
||||
for (i = 0; i < MIT_IR_SIZE; i ++) {
|
||||
if (! ReadInt16LeAsFloat32 (fileName, fp, & s))
|
||||
return (0);
|
||||
hData -> mHrirs [j0 + i] = s;
|
||||
if (! ReadInt16LeAsFloat32 (fileName, fp, & s))
|
||||
return (0);
|
||||
hData -> mHrirs [j1 + i] = s;
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Performs the minimum phase reconstruction for a given HRIR data set. The
|
||||
// cepstrum size should be made configureable at some point in the future.
|
||||
static void ReconstructHrirs (int minIrSize, HrirDataT * hData) {
|
||||
int start, end, step, j;
|
||||
float cep [CEP_SIZE];
|
||||
|
||||
start = hData -> mEvOffset [hData -> mEvStart];
|
||||
end = hData -> mIrCount;
|
||||
step = hData -> mIrSize;
|
||||
for (j = start; j < end; j ++) {
|
||||
RealCepstrum (step, & hData -> mHrirs [j * step], cep);
|
||||
MinimumPhase (cep, minIrSize, & hData -> mHrirs [j * minIrSize]);
|
||||
}
|
||||
hData -> mIrSize = minIrSize;
|
||||
}
|
||||
|
||||
// Renormalize the entire HRIR data set, and attenutate it slightly.
|
||||
static void RenormalizeHrirs (const HrirDataT * hData) {
|
||||
int step, start, end;
|
||||
float norm;
|
||||
int j, i;
|
||||
|
||||
step = hData -> mIrSize;
|
||||
start = hData -> mEvOffset [hData -> mEvStart] * step;
|
||||
end = hData -> mIrCount * step;
|
||||
norm = 0.0f;
|
||||
for (j = start; j < end; j += step) {
|
||||
for (i = 0; i < step; i ++) {
|
||||
if (fabs (hData -> mHrirs [j + i]) > norm)
|
||||
norm = fabs (hData -> mHrirs [j + i]);
|
||||
}
|
||||
}
|
||||
if (norm > 0.000001f)
|
||||
norm = 1.0f / norm;
|
||||
norm *= 0.95f;
|
||||
for (j = start; j < end; j += step) {
|
||||
for (i = 0; i < step; i ++)
|
||||
hData -> mHrirs [j + i] *= norm;
|
||||
}
|
||||
}
|
||||
|
||||
// Given an elevation offset and azimuth, calculates two offsets for
|
||||
// addressing the HRIRs buffer and their interpolation factor.
|
||||
static void CalcAzIndices (const HrirDataT * hData, int oi, float az, int * j0, int * j1, float * jf) {
|
||||
int ai;
|
||||
|
||||
az = fmod ((2.0f * M_PI) + az, 2.0f * M_PI) * hData -> mAzCount [oi] / (2.0f * M_PI);
|
||||
ai = (int) az;
|
||||
az -= ai;
|
||||
(* j0) = hData -> mEvOffset [oi] + ai;
|
||||
(* j1) = hData -> mEvOffset [oi] + ((ai + 1) % hData -> mAzCount [oi]);
|
||||
(* jf) = az;
|
||||
}
|
||||
|
||||
// Perform a linear interpolation.
|
||||
static float Lerp (float a, float b, float f) {
|
||||
return (a + (f * (b - a)));
|
||||
}
|
||||
|
||||
// Attempt to synthesize any missing HRIRs at the bottom elevations. Right
|
||||
// now this just blends the lowest elevation HRIRs together and applies some
|
||||
// attenuates and high frequency damping. It's not a realistic model to use,
|
||||
// but it is simple.
|
||||
static void SynthesizeHrirs (HrirDataT * hData) {
|
||||
int step, oi, i, a, j, e;
|
||||
float of;
|
||||
int j0, j1;
|
||||
float jf;
|
||||
float lp [4], s0, s1;
|
||||
|
||||
if (hData -> mEvStart <= 0)
|
||||
return;
|
||||
step = hData -> mIrSize;
|
||||
oi = hData -> mEvStart;
|
||||
for (i = 0; i < step; i ++)
|
||||
hData -> mHrirs [i] = 0.0f;
|
||||
for (a = 0; a < hData -> mAzCount [oi]; a ++) {
|
||||
j = (hData -> mEvOffset [oi] + a) * step;
|
||||
for (i = 0; i < step; i ++)
|
||||
hData -> mHrirs [i] += hData -> mHrirs [j + i] / hData -> mAzCount [oi];
|
||||
}
|
||||
for (e = 1; e < hData -> mEvStart; e ++) {
|
||||
of = ((float) e) / hData -> mEvStart;
|
||||
for (a = 0; a < hData -> mAzCount [e]; a ++) {
|
||||
j = (hData -> mEvOffset [e] + a) * step;
|
||||
CalcAzIndices (hData, oi, a * 2.0f * M_PI / hData -> mAzCount [e], & j0, & j1, & jf);
|
||||
j0 *= step;
|
||||
j1 *= step;
|
||||
lp [0] = 0.0f;
|
||||
lp [1] = 0.0f;
|
||||
lp [2] = 0.0f;
|
||||
lp [3] = 0.0f;
|
||||
for (i = 0; i < step; i ++) {
|
||||
s0 = hData -> mHrirs [i];
|
||||
s1 = Lerp (hData -> mHrirs [j0 + i], hData -> mHrirs [j1 + i], jf);
|
||||
s0 = Lerp (s0, s1, of);
|
||||
lp [0] = Lerp (s0, lp [0], 0.15f - (0.15f * of));
|
||||
lp [1] = Lerp (lp [0], lp [1], 0.15f - (0.15f * of));
|
||||
lp [2] = Lerp (lp [1], lp [2], 0.15f - (0.15f * of));
|
||||
lp [3] = Lerp (lp [2], lp [3], 0.15f - (0.15f * of));
|
||||
hData -> mHrirs [j + i] = lp [3];
|
||||
}
|
||||
}
|
||||
}
|
||||
lp [0] = 0.0f;
|
||||
lp [1] = 0.0f;
|
||||
lp [2] = 0.0f;
|
||||
lp [3] = 0.0f;
|
||||
for (i = 0; i < step; i ++) {
|
||||
s0 = hData -> mHrirs [i];
|
||||
lp [0] = Lerp (s0, lp [0], 0.15f);
|
||||
lp [1] = Lerp (lp [0], lp [1], 0.15f);
|
||||
lp [2] = Lerp (lp [1], lp [2], 0.15f);
|
||||
lp [3] = Lerp (lp [2], lp [3], 0.15f);
|
||||
hData -> mHrirs [i] = lp [3];
|
||||
}
|
||||
hData -> mEvStart = 0;
|
||||
}
|
||||
|
||||
// Calculate the effective head-related time delays for the each HRIR, now
|
||||
// that they are minimum-phase.
|
||||
static void CalculateHrtds (HrirDataT * hData) {
|
||||
float minHrtd, maxHrtd;
|
||||
int e, a, j;
|
||||
float t;
|
||||
|
||||
minHrtd = 1000.0f;
|
||||
maxHrtd = -1000.0f;
|
||||
for (e = 0; e < hData -> mEvCount; e ++) {
|
||||
for (a = 0; a < hData -> mAzCount [e]; a ++) {
|
||||
j = hData -> mEvOffset [e] + a;
|
||||
t = CalcLTD ((-90.0f + (e * 180.0f / (hData -> mEvCount - 1))) * M_PI / 180.0f,
|
||||
(a * 360.0f / hData -> mAzCount [e]) * M_PI / 180.0f,
|
||||
hData -> mRadius, hData -> mDistance);
|
||||
hData -> mHrtds [j] = t;
|
||||
if (t > maxHrtd)
|
||||
maxHrtd = t;
|
||||
if (t < minHrtd)
|
||||
minHrtd = t;
|
||||
}
|
||||
}
|
||||
maxHrtd -= minHrtd;
|
||||
for (j = 0; j < hData -> mIrCount; j ++)
|
||||
hData -> mHrtds [j] -= minHrtd;
|
||||
hData -> mMaxHrtd = maxHrtd;
|
||||
}
|
||||
|
||||
// Save the OpenAL Soft HRTF data set.
|
||||
static int SaveMhr (const HrirDataT * hData, const char * fileName) {
|
||||
FILE * fp = NULL;
|
||||
int e, step, end, j, i;
|
||||
|
||||
if ((fp = fopen (fileName, "wb")) == NULL) {
|
||||
fprintf (stderr, "Could not create file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
if (! WriteString (MHR_FORMAT, fileName, fp))
|
||||
return (0);
|
||||
if (! WriteUInt32Le ((ALuint) hData -> mIrRate, fileName, fp))
|
||||
return (0);
|
||||
if (! WriteUInt16Le ((ALushort) hData -> mIrCount, fileName, fp))
|
||||
return (0);
|
||||
if (! WriteUInt16Le ((ALushort) hData -> mIrSize, fileName, fp))
|
||||
return (0);
|
||||
if (! WriteUInt8 ((ALubyte) hData -> mEvCount, fileName, fp))
|
||||
return (0);
|
||||
for (e = 0; e < hData -> mEvCount; e ++) {
|
||||
if (! WriteUInt16Le ((ALushort) hData -> mEvOffset [e], fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
step = hData -> mIrSize;
|
||||
end = hData -> mIrCount * step;
|
||||
for (j = 0; j < end; j += step) {
|
||||
for (i = 0; i < step; i ++) {
|
||||
if (! WriteFloat32AsInt16Le (hData -> mHrirs [j + i], fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
for (j = 0; j < hData -> mIrCount; j ++) {
|
||||
i = (int) round (44100.0f * hData -> mHrtds [j]);
|
||||
if (i > 127)
|
||||
i = 127;
|
||||
if (! WriteUInt8 ((ALubyte) i, fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
fclose (fp);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Save the OpenAL Soft built-in table.
|
||||
static int SaveTab (const HrirDataT * hData, const char * fileName) {
|
||||
FILE * fp = NULL;
|
||||
int step, end, j, i;
|
||||
char text [16];
|
||||
|
||||
if ((fp = fopen (fileName, "wb")) == NULL) {
|
||||
fprintf (stderr, "Could not create file, '%s'.\n", fileName);
|
||||
return (0);
|
||||
}
|
||||
if (! WriteString ("/* This data is Copyright 1994 by the MIT Media Laboratory. It is provided free\n"
|
||||
" * with no restrictions on use, provided the authors are cited when the data is\n"
|
||||
" * used in any research or commercial application. */\n"
|
||||
"/* Bill Gardner <billg@media.mit.edu> and Keith Martin <kdm@media.mit.edu> */\n"
|
||||
"\n"
|
||||
" /* HRIR Coefficients */\n"
|
||||
" {\n", fileName, fp))
|
||||
return (0);
|
||||
step = hData -> mIrSize;
|
||||
end = hData -> mIrCount * step;
|
||||
for (j = 0; j < end; j += step) {
|
||||
if (! WriteString (" { ", fileName, fp))
|
||||
return (0);
|
||||
for (i = 0; i < step; i ++) {
|
||||
snprintf (text, 15, "%+d, ", (int) round (32767.0f * hData -> mHrirs [j + i]));
|
||||
if (! WriteString (text, fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
if (! WriteString ("},\n", fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
if (! WriteString (" },\n"
|
||||
"\n"
|
||||
" /* HRIR Delays */\n"
|
||||
" { ", fileName, fp))
|
||||
return (0);
|
||||
for (j = 0; j < hData -> mIrCount; j ++) {
|
||||
snprintf (text, 15, "%d, ", (int) round (44100.0f * hData -> mHrtds [j]));
|
||||
if (! WriteString (text, fileName, fp))
|
||||
return (0);
|
||||
}
|
||||
if (! WriteString ("}\n", fileName, fp))
|
||||
return (0);
|
||||
fclose (fp);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Loads and processes an MIT data set. At present, the HRIR and HRTD data
|
||||
// is loaded and processed in a static buffer. That should change to using
|
||||
// heap allocated memory in the future. A cleanup function will then be
|
||||
// required.
|
||||
static int MakeMit(const char *baseInName, HrirDataT *hData)
|
||||
{
|
||||
static float hrirs[MIT_IR_COUNT * MIT_IR_SIZE];
|
||||
static float hrtds[MIT_IR_COUNT];
|
||||
|
||||
hData->mIrRate = MIT_IR_RATE;
|
||||
hData->mIrCount = MIT_IR_COUNT;
|
||||
hData->mIrSize = MIT_IR_SIZE;
|
||||
hData->mEvCount = MIT_EV_COUNT;
|
||||
hData->mEvStart = MIT_EV_START;
|
||||
hData->mEvOffset = MIT_EV_OFFSET;
|
||||
hData->mAzCount = MIT_AZ_COUNT;
|
||||
hData->mRadius = MIT_RADIUS;
|
||||
hData->mDistance = MIT_DISTANCE;
|
||||
hData->mHrirs = hrirs;
|
||||
hData->mHrtds = hrtds;
|
||||
fprintf(stderr, "Loading base HRIR data...\n");
|
||||
if(!LoadMitHrirs(baseInName, hData))
|
||||
return 0;
|
||||
fprintf(stderr, "Performing minimum phase reconstruction and truncation...\n");
|
||||
ReconstructHrirs(MIN_IR_SIZE, hData);
|
||||
fprintf(stderr, "Renormalizing minimum phase HRIR data...\n");
|
||||
RenormalizeHrirs(hData);
|
||||
fprintf(stderr, "Synthesizing missing elevations...\n");
|
||||
SynthesizeHrirs(hData);
|
||||
fprintf(stderr, "Calculating impulse delays...\n");
|
||||
CalculateHrtds(hData);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Simple dispatch. Provided a command, the path to the MIT set of choice,
|
||||
// and an optional output filename, this will produce an OpenAL Soft
|
||||
// compatible HRTF set in the chosen format.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char baseName[1024];
|
||||
const char *outName = NULL;
|
||||
HrirDataT hData;
|
||||
|
||||
if(argc < 3 || strcmp(argv [1], "-h") == 0 || strcmp (argv [1], "--help") == 0)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <command> <path of MIT set> [ <output file> ]\n\n", argv[0]);
|
||||
fprintf(stderr, "Commands:\n");
|
||||
fprintf(stderr, " -m, --make-mhr Makes an OpenAL Soft compatible HRTF data set.\n");
|
||||
fprintf(stderr, " Defaults output to: ./oal_soft_hrtf_44100.mhr\n");
|
||||
fprintf(stderr, " -t, --make-tab Makes the built-in table used when compiling OpenAL Soft.\n");
|
||||
fprintf(stderr, " Defaults output to: ./hrtf_tables.inc\n");
|
||||
fprintf(stderr, " -h, --help Displays this help information.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(baseName, sizeof(baseName), "%s/elev", argv[2]);
|
||||
if(strcmp(argv[1], "-m") == 0 || strcmp(argv[1], "--make-mhr") == 0)
|
||||
{
|
||||
if(argc > 3)
|
||||
outName = argv[3];
|
||||
else
|
||||
outName = "./oal_soft_hrtf_44100.mhr";
|
||||
if(!MakeMit(baseName, &hData))
|
||||
return -1;
|
||||
fprintf(stderr, "Creating data set file...\n");
|
||||
if(!SaveMhr(&hData, outName))
|
||||
return -1;
|
||||
}
|
||||
else if(strcmp(argv[1], "-t") == 0 || strcmp(argv[1], "--make-tab") == 0)
|
||||
{
|
||||
if(argc > 3)
|
||||
outName = argv[3];
|
||||
else
|
||||
outName = "./hrtf_tables.inc";
|
||||
if(!MakeMit(baseName, &hData))
|
||||
return -1;
|
||||
fprintf(stderr, "Creating table file...\n");
|
||||
if(!SaveTab(&hData, outName))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid command '%s'\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "Done.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -22,8 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -40,39 +38,7 @@
|
||||
#define ALC_EFX_MAJOR_VERSION 0x20001
|
||||
#define ALC_EFX_MINOR_VERSION 0x20002
|
||||
#define ALC_MAX_AUXILIARY_SENDS 0x20003
|
||||
#define AL_FILTER_TYPE 0x8001
|
||||
#define AL_FILTER_NULL 0x0000
|
||||
#define AL_FILTER_LOWPASS 0x0001
|
||||
#define AL_FILTER_HIGHPASS 0x0002
|
||||
#define AL_FILTER_BANDPASS 0x0003
|
||||
#define AL_EFFECT_TYPE 0x8001
|
||||
#define AL_EFFECT_NULL 0x0000
|
||||
#define AL_EFFECT_EAXREVERB 0x8000
|
||||
#define AL_EFFECT_REVERB 0x0001
|
||||
#define AL_EFFECT_CHORUS 0x0002
|
||||
#define AL_EFFECT_DISTORTION 0x0003
|
||||
#define AL_EFFECT_ECHO 0x0004
|
||||
#define AL_EFFECT_FLANGER 0x0005
|
||||
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
|
||||
#define AL_EFFECT_VOCAL_MORPHER 0x0007
|
||||
#define AL_EFFECT_PITCH_SHIFTER 0x0008
|
||||
#define AL_EFFECT_RING_MODULATOR 0x0009
|
||||
#define AL_EFFECT_AUTOWAH 0x000A
|
||||
#define AL_EFFECT_COMPRESSOR 0x000B
|
||||
#define AL_EFFECT_EQUALIZER 0x000C
|
||||
typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint);
|
||||
typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*);
|
||||
typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint);
|
||||
#endif
|
||||
static LPALGENFILTERS palGenFilters;
|
||||
static LPALDELETEFILTERS palDeleteFilters;
|
||||
static LPALFILTERI palFilteri;
|
||||
static LPALGENEFFECTS palGenEffects;
|
||||
static LPALDELETEEFFECTS palDeleteEffects;
|
||||
static LPALEFFECTI palEffecti;
|
||||
|
||||
|
||||
#define MAX_WIDTH 80
|
||||
@@ -184,24 +150,27 @@ static void printALInfo(void)
|
||||
static void printEFXInfo(ALCdevice *device)
|
||||
{
|
||||
ALCint major, minor, sends;
|
||||
ALuint obj;
|
||||
int i;
|
||||
const ALenum filters[] = {
|
||||
AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS,
|
||||
AL_FILTER_NULL
|
||||
static const ALchar filters[][32] = {
|
||||
"AL_FILTER_LOWPASS", "AL_FILTER_HIGHPASS", "AL_FILTER_BANDPASS", ""
|
||||
};
|
||||
char filterNames[] = "Low-pass,High-pass,Band-pass,";
|
||||
const ALenum effects[] = {
|
||||
AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS,
|
||||
AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER,
|
||||
AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER,
|
||||
AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH,
|
||||
AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL
|
||||
static const ALchar effects[][32] = {
|
||||
"AL_EFFECT_EAXREVERB", "AL_EFFECT_REVERB", "AL_EFFECT_CHORUS",
|
||||
"AL_EFFECT_DISTORTION", "AL_EFFECT_ECHO", "AL_EFFECT_FLANGER",
|
||||
"AL_EFFECT_FREQUENCY_SHIFTER", "AL_EFFECT_VOCAL_MORPHER",
|
||||
"AL_EFFECT_PITCH_SHIFTER", "AL_EFFECT_RING_MODULATOR",
|
||||
"AL_EFFECT_AUTOWAH", "AL_EFFECT_COMPRESSOR", "AL_EFFECT_EQUALIZER", ""
|
||||
};
|
||||
static const ALchar dedeffects[][64] = {
|
||||
"AL_EFFECT_DEDICATED_DIALOGUE",
|
||||
"AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", ""
|
||||
};
|
||||
char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
|
||||
"Frequency Shifter,Vocal Morpher,Pitch Shifter,"
|
||||
"Ring Modulator,Autowah,Compressor,Equalizer,";
|
||||
"Ring Modulator,Autowah,Compressor,Equalizer,"
|
||||
"Dedicated Dialog,Dedicated LFE,";
|
||||
char *current;
|
||||
int i;
|
||||
|
||||
if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE)
|
||||
{
|
||||
@@ -217,61 +186,57 @@ static void printEFXInfo(ALCdevice *device)
|
||||
if(checkALCErrors(device) == ALC_NO_ERROR)
|
||||
printf("Max auxiliary sends: %d\n", sends);
|
||||
|
||||
palGenFilters = alGetProcAddress("alGenFilters");
|
||||
palDeleteFilters = alGetProcAddress("alDeleteFilters");
|
||||
palFilteri = alGetProcAddress("alFilteri");
|
||||
palGenEffects = alGetProcAddress("alGenEffects");
|
||||
palDeleteEffects = alGetProcAddress("alDeleteEffects");
|
||||
palEffecti = alGetProcAddress("alEffecti");
|
||||
if(checkALErrors() != AL_NO_ERROR ||
|
||||
!palGenFilters || !palDeleteFilters || !palFilteri ||
|
||||
!palGenEffects || !palDeleteEffects || !palEffecti)
|
||||
current = filterNames;
|
||||
for(i = 0;filters[i][0];i++)
|
||||
{
|
||||
printf("!!! Missing EFX functions !!!\n");
|
||||
return;
|
||||
}
|
||||
char *next = strchr(current, ',');
|
||||
ALenum val;
|
||||
|
||||
palGenFilters(1, &obj);
|
||||
if(checkALErrors() == AL_NO_ERROR)
|
||||
val = alGetEnumValue(filters[i]);
|
||||
if(alGetError() != AL_NO_ERROR || val == 0 || val == -1)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
printf("Supported filters:");
|
||||
printList(filterNames, ',');
|
||||
|
||||
current = effectNames;
|
||||
for(i = 0;effects[i][0];i++)
|
||||
{
|
||||
current = filterNames;
|
||||
for(i = 0;filters[i] != AL_FILTER_NULL;i++)
|
||||
char *next = strchr(current, ',');
|
||||
ALenum val;
|
||||
|
||||
val = alGetEnumValue(effects[i]);
|
||||
if(alGetError() != AL_NO_ERROR || val == 0 || val == -1)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED"))
|
||||
{
|
||||
for(i = 0;dedeffects[i][0];i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
ALenum val;
|
||||
|
||||
palFilteri(obj, AL_FILTER_TYPE, filters[i]);
|
||||
if(alGetError() == AL_NO_ERROR)
|
||||
current = next+1;
|
||||
else
|
||||
val = alGetEnumValue(dedeffects[i]);
|
||||
if(alGetError() != AL_NO_ERROR || val == 0 || val == -1)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
palDeleteFilters(1, &obj);
|
||||
checkALErrors();
|
||||
|
||||
printf("Supported filters:");
|
||||
printList(filterNames, ',');
|
||||
}
|
||||
|
||||
palGenEffects(1, &obj);
|
||||
if(checkALErrors() == AL_NO_ERROR)
|
||||
else
|
||||
{
|
||||
current = effectNames;
|
||||
for(i = 0;effects[i] != AL_EFFECT_NULL;i++)
|
||||
for(i = 0;dedeffects[i][0];i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
|
||||
palEffecti(obj, AL_EFFECT_TYPE, effects[i]);
|
||||
if(alGetError() == AL_NO_ERROR)
|
||||
current = next+1;
|
||||
else
|
||||
memmove(current, next+1, strlen(next));
|
||||
memmove(current, next+1, strlen(next));
|
||||
}
|
||||
palDeleteEffects(1, &obj);
|
||||
checkALErrors();
|
||||
|
||||
printf("Supported effects:");
|
||||
printList(effectNames, ',');
|
||||
}
|
||||
printf("Supported effects:");
|
||||
printList(effectNames, ',');
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -294,8 +259,12 @@ int main(int argc, char *argv[])
|
||||
printf("Available capture devices:\n");
|
||||
printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER));
|
||||
|
||||
printf("Default playback device: %s\n",
|
||||
alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
|
||||
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||
printf("Default playback device: %s\n",
|
||||
alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER));
|
||||
else
|
||||
printf("Default playback device: %s\n",
|
||||
alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
|
||||
printf("Default capture device: %s\n",
|
||||
alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
|
||||
|
||||
@@ -308,7 +277,10 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
|
||||
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);
|
||||
Reference in New Issue
Block a user