mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Compare commits
2580 commits
release-11
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e370e06d1 | ||
|
|
35711ec6ad | ||
|
|
0050cc7a08 | ||
|
|
c95e014681 | ||
|
|
41aef1c928 | ||
|
|
0a92dbddc3 | ||
|
|
52db80698c | ||
|
|
dce6a8bef7 | ||
|
|
248ee44e30 | ||
|
|
45cc8468bb | ||
|
|
ef9c1def4e | ||
|
|
a5825d5a67 | ||
|
|
0d5b051820 | ||
|
|
a4cddb74d6 | ||
|
|
9dada484aa | ||
|
|
a731f8bdc0 | ||
|
|
0b912f26de | ||
|
|
cbf8f6b3f4 | ||
|
|
ec72568429 | ||
|
|
ec8bd9acdd | ||
|
|
a81d0ee944 | ||
|
|
c46249178d | ||
|
|
4c5c53ec0b | ||
|
|
689f0408d2 | ||
|
|
9a86e79b5c | ||
|
|
cfe335d124 | ||
|
|
e0fe0301bf | ||
|
|
f6da30da70 | ||
|
|
899030184a | ||
|
|
ab68a1af82 | ||
|
|
11a4dbf0a0 | ||
|
|
b15b6ebf50 | ||
|
|
071799368d | ||
|
|
e232a854a2 | ||
|
|
9b1573e87e | ||
|
|
973c232c21 | ||
|
|
9dc990d5d6 | ||
|
|
804c02743a | ||
|
|
83297bec0e | ||
|
|
62d707b3b9 | ||
|
|
1872832e28 | ||
|
|
7e531ca57b | ||
|
|
bf2f6eb560 | ||
|
|
5403ffa8b0 | ||
|
|
e0899a01d5 | ||
|
|
18d124ab17 | ||
|
|
758e596bf9 | ||
|
|
5893b574a8 | ||
|
|
625aac9294 | ||
|
|
9205fb2303 | ||
|
|
a3492c0cb0 | ||
|
|
750911ce3c | ||
|
|
471ae08219 | ||
|
|
14ade58f34 | ||
|
|
6bcf266118 | ||
|
|
ef2c1d47cc | ||
|
|
3ed8c926a8 | ||
|
|
e2de53ea17 | ||
|
|
622f9d970a | ||
|
|
6408175725 | ||
|
|
1120b9084e | ||
|
|
d4736fe59f | ||
|
|
f6dc52c533 | ||
|
|
3525bcacb2 | ||
|
|
dbd53522be | ||
|
|
eb1b918a77 | ||
|
|
3d9fbdec3c | ||
|
|
79bcc7bc34 | ||
|
|
e8de87dc7b | ||
|
|
98d148e08d | ||
|
|
484b66f28c | ||
|
|
a50f40476d | ||
|
|
79ee96306b | ||
|
|
354e1c7a66 | ||
|
|
bd8886b0f0 | ||
|
|
5950bbe8a1 | ||
|
|
1d8931b334 | ||
|
|
471d11df16 | ||
|
|
4b2a826682 | ||
|
|
e0f4655cc5 | ||
|
|
65eac2fa94 | ||
|
|
befacaa5fe | ||
|
|
28763bb92d | ||
|
|
ef7d582849 | ||
|
|
54958c5b19 | ||
|
|
4c254fe5b4 | ||
|
|
a2548088f6 | ||
|
|
0be58ef45a | ||
|
|
3a62d3417f | ||
|
|
55619c54f9 | ||
|
|
a3131ba4d2 | ||
|
|
aa6314e5c4 | ||
|
|
045ba10386 | ||
|
|
8f4f463265 | ||
|
|
7b11a88231 | ||
|
|
dce321c77a | ||
|
|
a7440dea94 | ||
|
|
9195cfa7ca | ||
|
|
3e6363abf9 | ||
|
|
7ca10eb91e | ||
|
|
366b85f770 | ||
|
|
c13118921d | ||
|
|
1d82735d61 | ||
|
|
0ba45f3b11 | ||
|
|
ddf6999908 | ||
|
|
0be476ff79 | ||
|
|
c3ab3ff218 | ||
|
|
c9a9f8a060 | ||
|
|
21d5b4879b | ||
|
|
93aff4b716 | ||
|
|
4cb80e456b | ||
|
|
0a9f93abd6 | ||
|
|
81e3be1923 | ||
|
|
ebe37cc714 | ||
|
|
6bfb4857b2 | ||
|
|
a91c1d5e8a | ||
|
|
a4b44a4739 | ||
|
|
0682ac9d57 | ||
|
|
64190e2c34 | ||
|
|
81d8ae4c67 | ||
|
|
a250c71991 | ||
|
|
abbd5aef9d | ||
|
|
8b77eb7c81 | ||
|
|
78267e8902 | ||
|
|
64c9e72fad | ||
|
|
675252724f | ||
|
|
a9f8b0d067 | ||
|
|
e1b48665a8 | ||
|
|
348718de5e | ||
|
|
38464954b0 | ||
|
|
8b9f498d53 | ||
|
|
99e4c41b24 | ||
|
|
b48b96ecd9 | ||
|
|
ded413ae74 | ||
|
|
8a62072984 | ||
|
|
3c939d0c87 | ||
|
|
dd9adeeaf2 | ||
|
|
3f09a1f325 | ||
|
|
562de27c30 | ||
|
|
a53ef1f299 | ||
|
|
8dbbf0f715 | ||
|
|
3a22e7c81b | ||
|
|
e2da230af6 | ||
|
|
0a3030deed | ||
|
|
6a0c8d9e07 | ||
|
|
13a153aff2 | ||
|
|
50da64adfa | ||
|
|
c32ef046b7 | ||
|
|
cea2846249 | ||
|
|
e06e154396 | ||
|
|
39d33d998c | ||
|
|
9e3c16cde5 | ||
|
|
b8ee5493d9 | ||
|
|
5fbe230308 | ||
|
|
91eb779ae2 | ||
|
|
c64653ed37 | ||
|
|
4107263747 | ||
|
|
bf01b4c858 | ||
|
|
71ac72d463 | ||
|
|
05fe27d0f7 | ||
|
|
3e9b0742d1 | ||
|
|
05f1f19ab0 | ||
|
|
3051b1f3e4 | ||
|
|
4de5eeccd2 | ||
|
|
aafe6d8dab | ||
|
|
797326d669 | ||
|
|
f7dcf20f69 | ||
|
|
7a7333edab | ||
|
|
e918b353ec | ||
|
|
ea0f6a685c | ||
|
|
ab7fc69e16 | ||
|
|
69bfc65da7 | ||
|
|
631df15f40 | ||
|
|
86d1456552 | ||
|
|
93244da737 | ||
|
|
b1aab0839c | ||
|
|
d1c5d66bd3 | ||
|
|
6e318f314e | ||
|
|
42498cd06c | ||
|
|
5b56675b06 | ||
|
|
5b8e5e0f95 | ||
|
|
a1b37776a8 | ||
|
|
d5823cd5c7 | ||
|
|
da5a92c1be | ||
|
|
ae37006ee4 | ||
|
|
6561adff94 | ||
|
|
972cdf0658 | ||
|
|
fdb2f369ec | ||
|
|
f29af03cd7 | ||
|
|
528807a24b | ||
|
|
d02019f985 | ||
|
|
999aac6eb3 | ||
|
|
f25d0776c7 | ||
|
|
ce5e3f4911 | ||
|
|
c256a9eb17 | ||
|
|
4c3437b575 | ||
|
|
4406fc6239 | ||
|
|
ffd82647ee | ||
|
|
533a179131 | ||
|
|
2481687329 | ||
|
|
2edd2ffea7 | ||
|
|
43b0124790 | ||
|
|
ebe43c72c6 | ||
|
|
c63d2b115c | ||
|
|
8dc06f48ce | ||
|
|
203727d4fb | ||
|
|
5962a563e4 | ||
|
|
6758c94e33 | ||
|
|
9b8abdb5ee | ||
|
|
5b013073bf | ||
|
|
0664197b53 | ||
|
|
4ca7d4231b | ||
|
|
e8baaa5a22 | ||
|
|
9c3cab27e1 | ||
|
|
fce36108da | ||
|
|
5a2d6658e7 | ||
|
|
4e81b79254 | ||
|
|
5588a3996b | ||
|
|
207c971358 | ||
|
|
266b1c5941 | ||
|
|
29ecff3728 | ||
|
|
330fed199d | ||
|
|
15f6811a5f | ||
|
|
b222387923 | ||
|
|
7ef7f16727 | ||
|
|
d6899098a6 | ||
|
|
06d744495c | ||
|
|
e7662a3de5 | ||
|
|
00f87c7b6e | ||
|
|
c74220300f | ||
|
|
f34fdef432 | ||
|
|
f92aabea7e | ||
|
|
1c27b2c426 | ||
|
|
dda6054ef1 | ||
|
|
fd75bdb356 | ||
|
|
5c2cebc7bf | ||
|
|
14bbdca050 | ||
|
|
301be02a89 | ||
|
|
53ed837123 | ||
|
|
06a0031bdd | ||
|
|
fefea439ba | ||
|
|
6eb2014650 | ||
|
|
37d1e2d93e | ||
|
|
3188c793bc | ||
|
|
96089108ca | ||
|
|
d25010c1cb | ||
|
|
5d7edcf36f | ||
|
|
837acfa784 | ||
|
|
7ab4685940 | ||
|
|
8a7daf3662 | ||
|
|
ea090a6858 | ||
|
|
96de278d49 | ||
|
|
fb4f11e54f | ||
|
|
92c350b559 | ||
|
|
d212968040 | ||
|
|
dbcef2ac87 | ||
|
|
bde3418ce5 | ||
|
|
a386e79f59 | ||
|
|
d83734eb46 | ||
|
|
1ae854e2e9 | ||
|
|
bc5c462eea | ||
|
|
027ac77ad7 | ||
|
|
51a7348db6 | ||
|
|
a79447e430 | ||
|
|
511a58e51a | ||
|
|
73d25e7be3 | ||
|
|
1793490519 | ||
|
|
1dba0dbb65 | ||
|
|
bf68a7db3d | ||
|
|
49709e3231 | ||
|
|
55b2b47797 | ||
|
|
12bb7a851c | ||
|
|
d600b7b32e | ||
|
|
d574182374 | ||
|
|
7fdc1ea1d2 | ||
|
|
e97422e333 | ||
|
|
2c002ba3a7 | ||
|
|
12d5336af9 | ||
|
|
c4e1049396 | ||
|
|
1b85d8ccb0 | ||
|
|
40e1a5c7e5 | ||
|
|
5a3a4f5536 | ||
|
|
59e3e714fa | ||
|
|
7ccb382f53 | ||
|
|
0a0ca093f4 | ||
|
|
adc0d5ba6e | ||
|
|
53c2da81fe | ||
|
|
3c6ea30767 | ||
|
|
a04db4a2a6 | ||
|
|
e9d958809a | ||
|
|
2ac8a490b0 | ||
|
|
6b78a35695 | ||
|
|
7ce00a00fa | ||
|
|
d1aa0db537 | ||
|
|
6df5f10973 | ||
|
|
5f7bcb7746 | ||
|
|
9c15b8c27d | ||
|
|
6b7a23867c | ||
|
|
de21dedbe3 | ||
|
|
4e192fda4d | ||
|
|
bd6523bb34 | ||
|
|
c0acc09cb1 | ||
|
|
68a95f53f2 | ||
|
|
6c2f370a8f | ||
|
|
493f3103b3 | ||
|
|
e51fef57d8 | ||
|
|
ce64d84013 | ||
|
|
f5cb1391aa | ||
|
|
97f8c53814 | ||
|
|
8408e0ae19 | ||
|
|
9187fbb6db | ||
|
|
96b1432434 | ||
|
|
f41630083a | ||
|
|
32b2ede5aa | ||
|
|
e3bf0cd30c | ||
|
|
7d3a497db6 | ||
|
|
1fe13a7630 | ||
|
|
11af61f32e | ||
|
|
dbd40fe7d3 | ||
|
|
1dd23f6641 | ||
|
|
f77eafacff | ||
|
|
524c29cbe3 | ||
|
|
59dc46e0f5 | ||
|
|
bf74b055cf | ||
|
|
2dd07ef8cc | ||
|
|
90b2ba0bd4 | ||
|
|
f185b602ea | ||
|
|
3559ee9f1d | ||
|
|
e7956e0e70 | ||
|
|
da1629328f | ||
|
|
4464802051 | ||
|
|
2516f0005d | ||
|
|
57bfe559ea | ||
|
|
803bf23269 | ||
|
|
10054efd81 | ||
|
|
dba8a67bcb | ||
|
|
248c69a6d0 | ||
|
|
bb29084392 | ||
|
|
365d44f03a | ||
|
|
fe6836ab02 | ||
|
|
25ddc21780 | ||
|
|
9ed75ca048 | ||
|
|
afe119a73f | ||
|
|
a7e9375d55 | ||
|
|
615becca7a | ||
|
|
1ef7b9732e | ||
|
|
fa68639b25 | ||
|
|
939873f6f4 | ||
|
|
a0ba3fa29c | ||
|
|
d78fe8e8b8 | ||
|
|
4879d89a92 | ||
|
|
53f023ea52 | ||
|
|
7919556375 | ||
|
|
7c53c9babd | ||
|
|
a86376c25e | ||
|
|
9b06909edd | ||
|
|
8215c057cf | ||
|
|
8e7014a7ed | ||
|
|
a5432e44a8 | ||
|
|
3bb22d503c | ||
|
|
a053909b87 | ||
|
|
46566e7155 | ||
|
|
b20cd3502b | ||
|
|
3716f59e7d | ||
|
|
0fd2765908 | ||
|
|
34c2c8c8a4 | ||
|
|
1a432362a3 | ||
|
|
635d392484 | ||
|
|
b2ba4b5878 | ||
|
|
31012e7cf9 | ||
|
|
8edaa79eda | ||
|
|
7b2b74e79b | ||
|
|
c99adbbe0b | ||
|
|
b989b160c0 | ||
|
|
4ae15b42a7 | ||
|
|
791bb62148 | ||
|
|
684796144c | ||
|
|
d01bbc6529 | ||
|
|
b8e985b939 | ||
|
|
4bd54b9771 | ||
|
|
23c4d94748 | ||
|
|
1670677a92 | ||
|
|
b138b9f549 | ||
|
|
c9b76c9294 | ||
|
|
d88a29b378 | ||
|
|
1fa0c7991c | ||
|
|
bedbc8de6d | ||
|
|
bbfd1ddca0 | ||
|
|
f84e94f507 | ||
|
|
adc275af27 | ||
|
|
75ec477248 | ||
|
|
ef0974de6d | ||
|
|
10e40b974c | ||
|
|
ad85ef6517 | ||
|
|
532a3ae3e1 | ||
|
|
40112d3cff | ||
|
|
ec24ec7dbb | ||
|
|
5d40b8ca33 | ||
|
|
bf21bca206 | ||
|
|
31e3a7dc79 | ||
|
|
8aa421e08b | ||
|
|
8b7e294fc6 | ||
|
|
0df319742a | ||
|
|
efb1110987 | ||
|
|
352d9f24e8 | ||
|
|
701d27c0a9 | ||
|
|
8f1e024aef | ||
|
|
0095bfad39 | ||
|
|
a4e9b0468e | ||
|
|
2de1052c3d | ||
|
|
976c2de599 | ||
|
|
430ea53ed8 | ||
|
|
9fb219645b | ||
|
|
314f02d36d | ||
|
|
64aa306cf9 | ||
|
|
22df2dbdb9 | ||
|
|
41d6f727e0 | ||
|
|
d6d0ab1a7f | ||
|
|
d575824ab4 | ||
|
|
d2293b8e09 | ||
|
|
fc57219d1c | ||
|
|
4504afcde3 | ||
|
|
be6c32ef9c | ||
|
|
0cbbf10eea | ||
|
|
45984d2a12 | ||
|
|
41c6274252 | ||
|
|
80d7198230 | ||
|
|
f89246fd4b | ||
|
|
9d2094fe23 | ||
|
|
5c814c503e | ||
|
|
203047a464 | ||
|
|
bef7b70e55 | ||
|
|
d89a4a79cf | ||
|
|
278f3ca420 | ||
|
|
64c23acd43 | ||
|
|
3d6fabea33 | ||
|
|
9338361543 | ||
|
|
d6d633e296 | ||
|
|
dc20b265d1 | ||
|
|
7052e7e3ea | ||
|
|
095c2940a8 | ||
|
|
e8dc34c11b | ||
|
|
d147c63b68 | ||
|
|
95a03d9931 | ||
|
|
05d64c58b2 | ||
|
|
1b3a547401 | ||
|
|
28608194a9 | ||
|
|
d239564d84 | ||
|
|
e647f733c9 | ||
|
|
9871479b27 | ||
|
|
1c05425261 | ||
|
|
d224a25d07 | ||
|
|
96daaaa794 | ||
|
|
f3e1795b68 | ||
|
|
ae6d05c49d | ||
|
|
86e521c3cb | ||
|
|
498897c227 | ||
|
|
65872a4a59 | ||
|
|
4235d7e9c8 | ||
|
|
823244e49d | ||
|
|
648430e37d | ||
|
|
16c630b946 | ||
|
|
a4d630bf24 | ||
|
|
1a728382c4 | ||
|
|
2bad906e88 | ||
|
|
c81015c003 | ||
|
|
098efc7f20 | ||
|
|
d0d3b064ed | ||
|
|
43c263cb6f | ||
|
|
629f2b1e5d | ||
|
|
e7722d7b29 | ||
|
|
ff95bd97c9 | ||
|
|
43e41b20d9 | ||
|
|
e181533029 | ||
|
|
e8510c1a8a | ||
|
|
5cb164d42e | ||
|
|
796826b0ad | ||
|
|
0fecd9a535 | ||
|
|
3e0c38c3ce | ||
|
|
34477605b1 | ||
|
|
36440d6566 | ||
|
|
c1d8b98fda | ||
|
|
7ea47b8105 | ||
|
|
18abe71dca | ||
|
|
001a5ed5b1 | ||
|
|
c73bceb797 | ||
|
|
b3d4c97da4 | ||
|
|
ca3eacda45 | ||
|
|
8f8dca5795 | ||
|
|
21adc7d061 | ||
|
|
f3c18e1436 | ||
|
|
8d7b84caac | ||
|
|
acc053a628 | ||
|
|
7ac52c685d | ||
|
|
f160fb99d9 | ||
|
|
ceceec2e94 | ||
|
|
6df559ff97 | ||
|
|
53d5425341 | ||
|
|
5532067aa1 | ||
|
|
0fc60571fe | ||
|
|
265b502f76 | ||
|
|
337ffb691e | ||
|
|
14ae9a0bf5 | ||
|
|
6257031092 | ||
|
|
784b43934a | ||
|
|
d0fce97c93 | ||
|
|
e0ec4d9c31 | ||
|
|
5cc27e5d04 | ||
|
|
0b878e4d24 | ||
|
|
9142299387 | ||
|
|
f34db983e0 | ||
|
|
a320fbf36e | ||
|
|
d90092d9f1 | ||
|
|
c1020d12c5 | ||
|
|
3c4af77ad2 | ||
|
|
b5973fed13 | ||
|
|
c9add89043 | ||
|
|
51d1b693d1 | ||
|
|
8dd7b4c8e7 | ||
|
|
d11a967936 | ||
|
|
911ebd07ab | ||
|
|
22e58eb5e4 | ||
|
|
2907ddbe46 | ||
|
|
fd68aed766 | ||
|
|
bc3612587b | ||
|
|
8a523bc1cd | ||
|
|
a1c4e02a06 | ||
|
|
ed55943a44 | ||
|
|
043cdc33d5 | ||
|
|
9dde762a1c | ||
|
|
e6ce004498 | ||
|
|
fe791128d6 | ||
|
|
77cc01f0d9 | ||
|
|
e3eac999c4 | ||
|
|
6b6ba070c7 | ||
|
|
c3181ed97e | ||
|
|
e9f62db2c3 | ||
|
|
50c46d13f3 | ||
|
|
90844063f7 | ||
|
|
583e794a53 | ||
|
|
25762d1133 | ||
|
|
f48617fbec | ||
|
|
93bf472472 | ||
|
|
3920eb1507 | ||
|
|
a0a2f9f6bf | ||
|
|
010945d371 | ||
|
|
84bc40e1f8 | ||
|
|
d4402d371a | ||
|
|
ed6511a79e | ||
|
|
d63f704472 | ||
|
|
67f45ba06d | ||
|
|
9c0e6f6151 | ||
|
|
f437e0bd04 | ||
|
|
c9e07daeda | ||
|
|
1a17e97a7c | ||
|
|
e11c9899e6 | ||
|
|
19da3fa55a | ||
|
|
0aac8d47ac | ||
|
|
87409ead6c | ||
|
|
9a9665ce54 | ||
|
|
7354bea3e6 | ||
|
|
5ed2f0ad1e | ||
|
|
c165cbe434 | ||
|
|
d0e26af8b1 | ||
|
|
61e174fd9e | ||
|
|
6fd65e6d26 | ||
|
|
8098f24f4e | ||
|
|
6aa99e3553 | ||
|
|
91548c5b05 | ||
|
|
66d08c0e1b | ||
|
|
675696da2b | ||
|
|
b2ca658489 | ||
|
|
9110dda4b4 | ||
|
|
e554fa9c6a | ||
|
|
28323206b3 | ||
|
|
30ad6807d4 | ||
|
|
87ca0f78d6 | ||
|
|
ea4bcd9a46 | ||
|
|
40e1e6a116 | ||
|
|
af6e5f258e | ||
|
|
bc7858ad2b | ||
|
|
90f110a311 | ||
|
|
2b5f390262 | ||
|
|
8ac0f3d9e3 | ||
|
|
2a55559f82 | ||
|
|
7811bfa350 | ||
|
|
694c443009 | ||
|
|
f12fb93a3e | ||
|
|
676f46d44d | ||
|
|
34f5b9d4c2 | ||
|
|
e7a334364c | ||
|
|
433237d1e9 | ||
|
|
8919596469 | ||
|
|
bdacdee42f | ||
|
|
d04f1d069f | ||
|
|
5dce76415a | ||
|
|
8d4926bca2 | ||
|
|
2c10093c5e | ||
|
|
a2d5c530a5 | ||
|
|
c32f645f5e | ||
|
|
6519b5c84d | ||
|
|
1a08c3f0d0 | ||
|
|
35346920b9 | ||
|
|
25d601920e | ||
|
|
92ec3558e3 | ||
|
|
2b9d97b944 | ||
|
|
67d43248da | ||
|
|
c2cd6478a8 | ||
|
|
099267a84a | ||
|
|
b1a190f87a | ||
|
|
b64d4a23fe | ||
|
|
3a311f75bd | ||
|
|
6980ca9397 | ||
|
|
a171e30532 | ||
|
|
f38fa578c6 | ||
|
|
72fbe5d7a7 | ||
|
|
950d99eea7 | ||
|
|
cbc5a49507 | ||
|
|
a824d97804 | ||
|
|
bebbd02f30 | ||
|
|
3d3232eedc | ||
|
|
ce1685be40 | ||
|
|
5b04ae1131 | ||
|
|
246b97ce8e | ||
|
|
dce5832d4d | ||
|
|
dca6b5f145 | ||
|
|
bf3ddc99f8 | ||
|
|
968c577488 | ||
|
|
94923cc353 | ||
|
|
a02f811c2a | ||
|
|
0411cfc18c | ||
|
|
b7312f6933 | ||
|
|
2d73c0796d | ||
|
|
0c2bb780d5 | ||
|
|
6c1376169c | ||
|
|
88c60997ca | ||
|
|
e88eb17f1e | ||
|
|
33d598cbe7 | ||
|
|
e4e5142a96 | ||
|
|
efb828e61b | ||
|
|
8605549176 | ||
|
|
18201ca830 | ||
|
|
9a4327116d | ||
|
|
83af56d379 | ||
|
|
68e26d20aa | ||
|
|
8adc7ec9a5 | ||
|
|
249e58fca0 | ||
|
|
ae0d5d4a79 | ||
|
|
713f557e64 | ||
|
|
675b88b316 | ||
|
|
4842beb80d | ||
|
|
c68337ef70 | ||
|
|
ab72475106 | ||
|
|
c84563bd86 | ||
|
|
7ac23627f8 | ||
|
|
1e8abfc3c0 | ||
|
|
ed6643e82c | ||
|
|
e02f0fcc9c | ||
|
|
c06e1b2eb4 | ||
|
|
4fa6aaaf9d | ||
|
|
bb23c6f653 | ||
|
|
e279f224a1 | ||
|
|
d5ccfe2812 | ||
|
|
b2d33d6a57 | ||
|
|
551a74fd61 | ||
|
|
0fdb24253f | ||
|
|
b1aa62e9cc | ||
|
|
3ca012d610 | ||
|
|
ddd336bc8f | ||
|
|
dc6827def2 | ||
|
|
354a4ee92e | ||
|
|
951bc1cec3 | ||
|
|
ad0f639fb5 | ||
|
|
45a9f55b0b | ||
|
|
42085036a2 | ||
|
|
2fb17b827b | ||
|
|
b87a202329 | ||
|
|
5efa8f63c0 | ||
|
|
ad3b5bb0d8 | ||
|
|
ad73bdf08c | ||
|
|
8005514986 | ||
|
|
7504a0f926 | ||
|
|
501416e17a | ||
|
|
e6320bcd91 | ||
|
|
6b2bb6bfe6 | ||
|
|
ba07479aa0 | ||
|
|
b9ba7336bb | ||
|
|
e3c84fce71 | ||
|
|
ddd724a5af | ||
|
|
e12e096919 | ||
|
|
8a60ae2e7f | ||
|
|
22254ad084 | ||
|
|
eac4e0321d | ||
|
|
7facb8b563 | ||
|
|
9d5e4f395d | ||
|
|
687cefb291 | ||
|
|
02f2607dd9 | ||
|
|
dbb8dee236 | ||
|
|
1ab69f4527 | ||
|
|
99b46bd53a | ||
|
|
043e9380d5 | ||
|
|
c05a1dd17c | ||
|
|
7d65064f9b | ||
|
|
d93a33cabb | ||
|
|
9fe004a7ec | ||
|
|
32660b3806 | ||
|
|
654ff9e7e0 | ||
|
|
73dfa5f60d | ||
|
|
4f513faa82 | ||
|
|
622ea906ef | ||
|
|
71b2ff998f | ||
|
|
69c8e2634b | ||
|
|
aec6a54b5d | ||
|
|
ad30eb2bc5 | ||
|
|
e24d411efa | ||
|
|
3ad16682c4 | ||
|
|
bae4591799 | ||
|
|
e36e44ed72 | ||
|
|
d52e4d9b62 | ||
|
|
4f517ed01f | ||
|
|
f852dca2c8 | ||
|
|
c93c70ff84 | ||
|
|
b07a2fbb77 | ||
|
|
e3cbd92a40 | ||
|
|
5d50aa34af | ||
|
|
4203d70414 | ||
|
|
4d4fcdd17f | ||
|
|
45e8661802 | ||
|
|
1d80861e09 | ||
|
|
5018fd7c65 | ||
|
|
83669124c9 | ||
|
|
8def1683b9 | ||
|
|
2c4c9a9d9b | ||
|
|
0999c097b4 | ||
|
|
02aab7476e | ||
|
|
670c547aad | ||
|
|
0aae6101a3 | ||
|
|
3b5707fe0f | ||
|
|
d9d1210c1d | ||
|
|
a2413e4aa8 | ||
|
|
2e2b278e85 | ||
|
|
589e46f52d | ||
|
|
9c16af25c0 | ||
|
|
26cc304ca0 | ||
|
|
7171441b96 | ||
|
|
4f6ba2c2d0 | ||
|
|
dec912f2db | ||
|
|
038a6e928c | ||
|
|
9988158f83 | ||
|
|
4864bb1ae4 | ||
|
|
c79716dfbe | ||
|
|
f4064a5dd9 | ||
|
|
631d5e1b2f | ||
|
|
6c37615dbd | ||
|
|
a8a308d7a6 | ||
|
|
9d33962c01 | ||
|
|
466de70edd | ||
|
|
09d3f7386b | ||
|
|
fe8d847408 | ||
|
|
ddf5ac7275 | ||
|
|
8b56eb602e | ||
|
|
157a7a978d | ||
|
|
04f6c60c0c | ||
|
|
9616ea2ad9 | ||
|
|
2a317d87d2 | ||
|
|
955d69472c | ||
|
|
41566cede0 | ||
|
|
761701caa1 | ||
|
|
82f930a993 | ||
|
|
c0f7cda4eb | ||
|
|
6240a14697 | ||
|
|
37a744a26c | ||
|
|
45b3705f1f | ||
|
|
bb30f5c1ea | ||
|
|
dde740bfe8 | ||
|
|
72b0007ac0 | ||
|
|
72ed83c99a | ||
|
|
189d25c32e | ||
|
|
e294569f5d | ||
|
|
692fbd9742 | ||
|
|
73d7587a06 | ||
|
|
102afdeaf6 | ||
|
|
cd6092d15a | ||
|
|
45952b7c18 | ||
|
|
6ed54e991b | ||
|
|
a329f55dce | ||
|
|
0afb17091b | ||
|
|
4b9b95cbc5 | ||
|
|
8babb95d7e | ||
|
|
b47660b22c | ||
|
|
7606a5a0fe | ||
|
|
a1c3b7a588 | ||
|
|
c313a43456 | ||
|
|
2057b724cd | ||
|
|
002df956d2 | ||
|
|
a3b4b085ae | ||
|
|
45b1306274 | ||
|
|
c9ea813970 | ||
|
|
d4a3523fb1 | ||
|
|
25952cfef6 | ||
|
|
96bb624b2d | ||
|
|
e81e7c6897 | ||
|
|
aa21a14c7d | ||
|
|
44fab3078a | ||
|
|
e17c7d9859 | ||
|
|
5aeb390d8c | ||
|
|
8005726b3d | ||
|
|
63a37c5bec | ||
|
|
5ebc55af73 | ||
|
|
c0f8f7deec | ||
|
|
e6b0d669e3 | ||
|
|
29678db680 | ||
|
|
c5a0ad267c | ||
|
|
8e9cd79855 | ||
|
|
2bed5fab18 | ||
|
|
cb802c524e | ||
|
|
d40e803719 | ||
|
|
8c54db62f3 | ||
|
|
b3aef93435 | ||
|
|
ef5a5d22ab | ||
|
|
ceca805df7 | ||
|
|
07bddcd6f4 | ||
|
|
510dadd5a5 | ||
|
|
14be0239af | ||
|
|
facd51e0f5 | ||
|
|
5a92faa94b | ||
|
|
370bcdfe04 | ||
|
|
0b112aea95 | ||
|
|
1bb139ff32 | ||
|
|
0e58f827b6 | ||
|
|
2ba1f6183e | ||
|
|
93b10b7e11 | ||
|
|
bc9d6d8368 | ||
|
|
83c1563c44 | ||
|
|
bbad57434f | ||
|
|
a49fea01ac | ||
|
|
bc3523d4e0 | ||
|
|
226200c8c9 | ||
|
|
6ed562a052 | ||
|
|
3ea99e6eee | ||
|
|
b7f206c486 | ||
|
|
cbe98a3fc6 | ||
|
|
c9074f65ba | ||
|
|
2c601506ae | ||
|
|
c509a6e1a2 | ||
|
|
f58bf2e724 | ||
|
|
4da24b44dc | ||
|
|
dca57f143d | ||
|
|
ff7f75c946 | ||
|
|
ad731bf237 | ||
|
|
eb20fdbc60 | ||
|
|
b91e78fbea | ||
|
|
37ffcf76e9 | ||
|
|
5b27ca9d4c | ||
|
|
0448473ab6 | ||
|
|
7f75219a03 | ||
|
|
8af5f74cf7 | ||
|
|
75627b036a | ||
|
|
47cef684ba | ||
|
|
58aab15546 | ||
|
|
962a9ae83a | ||
|
|
15d0267e72 | ||
|
|
87e914d1d2 | ||
|
|
9c4e390f0d | ||
|
|
609c22582a | ||
|
|
4d99e3ad01 | ||
|
|
90a4dbe855 | ||
|
|
f0c0f806e6 | ||
|
|
d07d38df25 | ||
|
|
422e3e4e24 | ||
|
|
5389f949d9 | ||
|
|
4e43b0cbb2 | ||
|
|
b459de93b6 | ||
|
|
4d64ba28a5 | ||
|
|
1d59f24bd8 | ||
|
|
809958df3b | ||
|
|
a1aa4d9094 | ||
|
|
52a22d8cef | ||
|
|
15ca7254fb | ||
|
|
142d59cf8f | ||
|
|
efe000e9e3 | ||
|
|
42bf37bbc8 | ||
|
|
ba1068a5ea | ||
|
|
0f025f0c55 | ||
|
|
80c7b7c3f3 | ||
|
|
13e9940230 | ||
|
|
9af8018ac6 | ||
|
|
8422b48216 | ||
|
|
6f3f664f82 | ||
|
|
c1659b34e8 | ||
|
|
8be8491b84 | ||
|
|
0d12dd29ad | ||
|
|
7f59789ffc | ||
|
|
ea82a68859 | ||
|
|
ca6fdc1629 | ||
|
|
0431273d7f | ||
|
|
6ad2622b30 | ||
|
|
4832fe8234 | ||
|
|
206bb40479 | ||
|
|
20b00b51b2 | ||
|
|
5ac365a601 | ||
|
|
bc6b472960 | ||
|
|
0638c08b75 | ||
|
|
4f04dc0bb7 | ||
|
|
589168318a | ||
|
|
823cd9993f | ||
|
|
7f2eb05339 | ||
|
|
ea9d8db1d3 | ||
|
|
f444587197 | ||
|
|
50c5cc9616 | ||
|
|
bb7e1ae300 | ||
|
|
64d8fe6ba0 | ||
|
|
6746305b4b | ||
|
|
b1f723fbe8 | ||
|
|
5e4cbec07a | ||
|
|
1f4b520b1b | ||
|
|
81e17da3fb | ||
|
|
b5dc0b2fd9 | ||
|
|
5e27a39d80 | ||
|
|
55c53717af | ||
|
|
9b71eb0f8f | ||
|
|
8a99f76f93 | ||
|
|
859f5acea5 | ||
|
|
5712f3061f | ||
|
|
42b89bbb90 | ||
|
|
07313cbb84 | ||
|
|
90737abf6d | ||
|
|
c6b0ef5da3 | ||
|
|
a3d66c99f0 | ||
|
|
3e5775b48e | ||
|
|
94b53b190a | ||
|
|
61983a113a | ||
|
|
d2cf720e0a | ||
|
|
7013cd9fee | ||
|
|
59ace446a5 | ||
|
|
dc29571075 | ||
|
|
e0367409f2 | ||
|
|
1b52877d0b | ||
|
|
2fdec84b46 | ||
|
|
6558d2e265 | ||
|
|
db93244583 | ||
|
|
a1f6f80888 | ||
|
|
8696bb0c2a | ||
|
|
e68bdc05ca | ||
|
|
33a0d9e62c | ||
|
|
6b2c0f9c53 | ||
|
|
ac019b15c5 | ||
|
|
a78b2c0db2 | ||
|
|
02167b9b86 | ||
|
|
df3b1cddcf | ||
|
|
dc3d2dc789 | ||
|
|
68d60d34dc | ||
|
|
9f757cbf74 | ||
|
|
375c1bc3e0 | ||
|
|
a526aee73e | ||
|
|
94cb9d3228 | ||
|
|
138cc9f51e | ||
|
|
a14a8ecf00 | ||
|
|
e02a39331c | ||
|
|
9b68f361e4 | ||
|
|
6c0f54a688 | ||
|
|
2db08cde89 | ||
|
|
3773777141 | ||
|
|
76c3cb47c3 | ||
|
|
0f5a019f04 | ||
|
|
4e2c4631dd | ||
|
|
e68756a7d5 | ||
|
|
e89a069016 | ||
|
|
584af12c27 | ||
|
|
4463c7f26c | ||
|
|
d70b31f8bc | ||
|
|
dfbab14a67 | ||
|
|
dbd5dd9912 | ||
|
|
f3090d3b91 | ||
|
|
fc78790b24 | ||
|
|
b2972e3f59 | ||
|
|
35cfd6d0d2 | ||
|
|
93bb85b3b6 | ||
|
|
21995065d6 | ||
|
|
6b82d49945 | ||
|
|
f89ad5cd72 | ||
|
|
937eae7081 | ||
|
|
ec53c5d115 | ||
|
|
1425fd8973 | ||
|
|
3e5547ef28 | ||
|
|
a200a427e6 | ||
|
|
abc135f257 | ||
|
|
9cfcc5d8ba | ||
|
|
62a431b12c | ||
|
|
3a1d85784e | ||
|
|
2a5b83429a | ||
|
|
bceed091d8 | ||
|
|
179be956d0 | ||
|
|
c654227b83 | ||
|
|
a9cf09a673 | ||
|
|
cb7d6f8593 | ||
|
|
26d845520b | ||
|
|
9300ec2db0 | ||
|
|
87187bd414 | ||
|
|
c93e02a58e | ||
|
|
b80fb9acc9 | ||
|
|
da23f7798d | ||
|
|
abb6abdf94 | ||
|
|
80f4410f42 | ||
|
|
b04fd532da | ||
|
|
3defa0121e | ||
|
|
7cd159bda4 | ||
|
|
5e0f332efb | ||
|
|
0b2f7bbe61 | ||
|
|
e4bb16bd53 | ||
|
|
79142834fb | ||
|
|
38053570c9 | ||
|
|
4e45d5f27c | ||
|
|
1c91b37b6f | ||
|
|
8a406c86a5 | ||
|
|
eba3c17f69 | ||
|
|
839efdd5cf | ||
|
|
fd27c39a9a | ||
|
|
fdc66446ce | ||
|
|
45e10e98a3 | ||
|
|
b6fcc88f67 | ||
|
|
bae3a1234b | ||
|
|
c9863f26f1 | ||
|
|
844da497fb | ||
|
|
a906dc0bb4 | ||
|
|
af7f91163b | ||
|
|
efda15d41b | ||
|
|
49398ef9e0 | ||
|
|
0d82876099 | ||
|
|
61108c162b | ||
|
|
150dfa934d | ||
|
|
966182bd2f | ||
|
|
f2cbf6b609 | ||
|
|
c75df9501e | ||
|
|
c3c82f4e9b | ||
|
|
d2456c2a6b | ||
|
|
05b667797d | ||
|
|
2e95fa0a08 | ||
|
|
54ec998186 | ||
|
|
9d6518a738 | ||
|
|
3f87ee8321 | ||
|
|
f4f3ed1d54 | ||
|
|
602708649d | ||
|
|
d12103c553 | ||
|
|
816632ae38 | ||
|
|
216a49c71e | ||
|
|
9dbfa24ad5 | ||
|
|
586f5039f1 | ||
|
|
40361ce6a6 | ||
|
|
4a13c3830a | ||
|
|
7ed08c0141 | ||
|
|
974a2f6caa | ||
|
|
0f53130216 | ||
|
|
57cdc60862 | ||
|
|
f7f3b92fa7 | ||
|
|
2bba31bcdf | ||
|
|
59f2f7389a | ||
|
|
2edce5ebf2 | ||
|
|
25d13682ba | ||
|
|
3bce334dc1 | ||
|
|
77ad4b15a5 | ||
|
|
b40513ac37 | ||
|
|
4c6b273fe1 | ||
|
|
3486393f99 | ||
|
|
ef5b8537e0 | ||
|
|
c367c8eb8a | ||
|
|
1a1f08de64 | ||
|
|
28abb4cd3d | ||
|
|
28d4e1e171 | ||
|
|
0ccec4b6b6 | ||
|
|
f781dbd25f | ||
|
|
fbebd03f88 | ||
|
|
6b63a53322 | ||
|
|
c49fe34c43 | ||
|
|
b2af252d11 | ||
|
|
b90e17064e | ||
|
|
903ecdc8f6 | ||
|
|
5561667d04 | ||
|
|
6d42458fe7 | ||
|
|
b0f2d0220e | ||
|
|
a63c90aa00 | ||
|
|
fdf8fef76c | ||
|
|
e7a4815ec3 | ||
|
|
8a8b04978d | ||
|
|
d476b2ecf8 | ||
|
|
9793dc8718 | ||
|
|
2ce14895bf | ||
|
|
aeb2e35d42 | ||
|
|
245dacbaa6 | ||
|
|
6a6714baef | ||
|
|
3982aa3f9e | ||
|
|
a62aec40fe | ||
|
|
0c3530d8a8 | ||
|
|
10a429b944 | ||
|
|
95b074de14 | ||
|
|
03afc1343c | ||
|
|
f7dc38b52e | ||
|
|
ce5e83b53b | ||
|
|
68a75ff7fc | ||
|
|
7621e2f8de | ||
|
|
13a2fdf5c8 | ||
|
|
a3b1dd5c9b | ||
|
|
3b1b668fe4 | ||
|
|
595eeb73cf | ||
|
|
4c085af0bc | ||
|
|
7facd8aaf0 | ||
|
|
e84fc33aa9 | ||
|
|
dca1f06e91 | ||
|
|
1ee7268488 | ||
|
|
06cb1ece50 | ||
|
|
1969b1b280 | ||
|
|
6db5077642 | ||
|
|
f97eca0172 | ||
|
|
2cb0c7f147 | ||
|
|
4660f67271 | ||
|
|
52e7a175c4 | ||
|
|
f21f9b0421 | ||
|
|
6a09d2e4e6 | ||
|
|
6a0763f8fc | ||
|
|
55a5745149 | ||
|
|
a90b1e865f | ||
|
|
f6ba92766b | ||
|
|
0044bde566 | ||
|
|
5d9d21e0dc | ||
|
|
ecb12a784e | ||
|
|
3b02aeae9d | ||
|
|
bd2819e749 | ||
|
|
62d29ee551 | ||
|
|
2e279e8fd3 | ||
|
|
b1a1d932a8 | ||
|
|
e2b49cc712 | ||
|
|
52adb303f1 | ||
|
|
0ac2602f7f | ||
|
|
653ee1b299 | ||
|
|
42f10b4fed | ||
|
|
8047d0fa2a | ||
|
|
6dba110767 | ||
|
|
cf5584e02f | ||
|
|
231b2d320b | ||
|
|
b308f42396 | ||
|
|
50fe471cb6 | ||
|
|
765aa49f41 | ||
|
|
4a571de626 | ||
|
|
5046aab8ff | ||
|
|
ac2ba992ff | ||
|
|
2967648b2b | ||
|
|
8f1c9019be | ||
|
|
95526c1c4d | ||
|
|
6bc1fe1939 | ||
|
|
d8b0878046 | ||
|
|
89f96e28b3 | ||
|
|
cd436e8210 | ||
|
|
557af859bb | ||
|
|
31d1b0ac63 | ||
|
|
b04eee8289 | ||
|
|
2caa983785 | ||
|
|
a9511e7c57 | ||
|
|
0055396d4d | ||
|
|
ddcea95734 | ||
|
|
6e6b5b571e | ||
|
|
9c609350aa | ||
|
|
5761556de6 | ||
|
|
1496c81082 | ||
|
|
cfd7a5242a | ||
|
|
d86362c6e7 | ||
|
|
5e26b246bd | ||
|
|
dd8040f00c | ||
|
|
0f994c4f62 | ||
|
|
d5a952172a | ||
|
|
b53b2545fa | ||
|
|
9f5efde107 | ||
|
|
b83250ac63 | ||
|
|
8dafa7003f | ||
|
|
af04c63038 | ||
|
|
887d1063e1 | ||
|
|
f0de386e91 | ||
|
|
7463fb9eda | ||
|
|
326fe35598 | ||
|
|
c67ed1a009 | ||
|
|
95ecb88025 | ||
|
|
0371407380 | ||
|
|
abc6997985 | ||
|
|
8dc582ac0f | ||
|
|
183bc34f79 | ||
|
|
d6cb84e878 | ||
|
|
8a46bdffce | ||
|
|
5a2d74d53d | ||
|
|
49ae84062b | ||
|
|
8f33585114 | ||
|
|
c813a76e9a | ||
|
|
a2f71562f6 | ||
|
|
00858ee5f4 | ||
|
|
0859e8594c | ||
|
|
74b761c53f | ||
|
|
eb7f575bda | ||
|
|
3a4031b5c5 | ||
|
|
d8efc7c865 | ||
|
|
e52134993a | ||
|
|
c7556cedf9 | ||
|
|
da08c69da2 | ||
|
|
53966b99a8 | ||
|
|
49a060585f | ||
|
|
1f841d4c43 | ||
|
|
0a5c043896 | ||
|
|
5390369691 | ||
|
|
29fb65d33d | ||
|
|
a443df81dd | ||
|
|
82addaa434 | ||
|
|
d33fd57200 | ||
|
|
c57aa07d7d | ||
|
|
1c3b749ede | ||
|
|
48e873c840 | ||
|
|
a39987a8cd | ||
|
|
e3bf4697b7 | ||
|
|
888b12405b | ||
|
|
09ca26be9b | ||
|
|
35235b8e3a | ||
|
|
a8c6314d48 | ||
|
|
ac65d7f443 | ||
|
|
72eaf9f83b | ||
|
|
6a030345d0 | ||
|
|
63055d7ba8 | ||
|
|
a8f09233ba | ||
|
|
38eaa9085a | ||
|
|
807fa893c5 | ||
|
|
493e91f60d | ||
|
|
90b6f2427f | ||
|
|
09bbf8df9c | ||
|
|
95b0889361 | ||
|
|
4de499b88a | ||
|
|
5f1eafa0ce | ||
|
|
4d184eb9fa | ||
|
|
c0ae0f8a42 | ||
|
|
7e2d79adfc | ||
|
|
cbab90d49c | ||
|
|
989e1b4368 | ||
|
|
a05e19e745 | ||
|
|
e56c3451c0 | ||
|
|
0e1b60be24 | ||
|
|
f91fbff773 | ||
|
|
441b4ccc9f | ||
|
|
507ff0555b | ||
|
|
c2f2744401 | ||
|
|
2a35678e2b | ||
|
|
a8d4de1224 | ||
|
|
9d34773d1c | ||
|
|
cbf23d0df5 | ||
|
|
1d351a0547 | ||
|
|
301f04fd27 | ||
|
|
4c89870f2d | ||
|
|
1ef464086b | ||
|
|
70a0f01951 | ||
|
|
87035b30ea | ||
|
|
7f696814ff | ||
|
|
e5a004f67a | ||
|
|
08ac8fa27f | ||
|
|
cce8161001 | ||
|
|
22e764278a | ||
|
|
14c56127fa | ||
|
|
008a1a09a7 | ||
|
|
ee50fdcd14 | ||
|
|
a16f71d336 | ||
|
|
c37c6fd005 | ||
|
|
09c12f964b | ||
|
|
5e17b321f8 | ||
|
|
cebadbbf3d | ||
|
|
74e1d22de4 | ||
|
|
0995e5ebcb | ||
|
|
d574fb7a11 | ||
|
|
62157e92ae | ||
|
|
e9a3e599a1 | ||
|
|
22ba19029e | ||
|
|
ab3d486026 | ||
|
|
87baa1b655 | ||
|
|
2f66d9931c | ||
|
|
3886b847ae | ||
|
|
9527b2d8be | ||
|
|
29b24d9d57 | ||
|
|
c6acd92aed | ||
|
|
1712a00910 | ||
|
|
cd3942882d | ||
|
|
e680691988 | ||
|
|
e8fe2b0042 | ||
|
|
789f9e29c9 | ||
|
|
1be0aaef7c | ||
|
|
b0f4ca9ad9 | ||
|
|
bdcc80e649 | ||
|
|
ac28ed9d74 | ||
|
|
99840de8d7 | ||
|
|
412e02ef00 | ||
|
|
f2f1f0db35 | ||
|
|
9fce079880 | ||
|
|
dff6e560d2 | ||
|
|
858e00c991 | ||
|
|
7acf2b0b41 | ||
|
|
89ce010de2 | ||
|
|
9eddffb694 | ||
|
|
9f9a6365f1 | ||
|
|
bd8d1d055f | ||
|
|
5c572fd8fe | ||
|
|
3d51d83e89 | ||
|
|
938669e1fa | ||
|
|
430994d341 | ||
|
|
99cb9d4832 | ||
|
|
3097309db5 | ||
|
|
aba2704dcb | ||
|
|
ea8dc07b23 | ||
|
|
d05425794c | ||
|
|
9ad4321d00 | ||
|
|
4b13bd5c04 | ||
|
|
cd6a593be7 | ||
|
|
dab0ea96d4 | ||
|
|
fbf7473892 | ||
|
|
b76c6c9b3c | ||
|
|
64ab80da02 | ||
|
|
4853623813 | ||
|
|
7b5f9a89b2 | ||
|
|
62e92134e0 | ||
|
|
6ea1d44e94 | ||
|
|
c3fdcbde88 | ||
|
|
a3b7e1acab | ||
|
|
42e4d4add6 | ||
|
|
22945ebb31 | ||
|
|
4616f0833c | ||
|
|
a05ef5e022 | ||
|
|
99430812c1 | ||
|
|
51ad5a5efa | ||
|
|
b559663d6a | ||
|
|
6b330351e1 | ||
|
|
481419ced0 | ||
|
|
feba38c28b | ||
|
|
5783d24652 | ||
|
|
9580e43846 | ||
|
|
4e9f09e2a1 | ||
|
|
8ff8bd766b | ||
|
|
fad96534ce | ||
|
|
5d46a9c219 | ||
|
|
4ebbbfe71b | ||
|
|
a165eab477 | ||
|
|
11ed074079 | ||
|
|
bda836f032 | ||
|
|
16cd9b3c29 | ||
|
|
23a0b30de0 | ||
|
|
07a3a5a2aa | ||
|
|
354bde5af1 | ||
|
|
e7bd31137a | ||
|
|
b427a8d4ca | ||
|
|
be8227eba5 | ||
|
|
2b2937a2eb | ||
|
|
d11fe92d67 | ||
|
|
029654c14a | ||
|
|
0284687897 | ||
|
|
6f5cd84019 | ||
|
|
ff32f34405 | ||
|
|
3ab4850306 | ||
|
|
7cf87859a8 | ||
|
|
8897deff91 | ||
|
|
e09b241a9b | ||
|
|
bc5a577994 | ||
|
|
5bc61d614c | ||
|
|
2f3cf25666 | ||
|
|
a1c33e1884 | ||
|
|
9397ece5a8 | ||
|
|
0dfcdbeb9c | ||
|
|
4432581c77 | ||
|
|
5145b9e605 | ||
|
|
0e5337636d | ||
|
|
7be3a0ce81 | ||
|
|
e839427846 | ||
|
|
76757b5f3d | ||
|
|
25b82cf7f4 | ||
|
|
21446a5ba0 | ||
|
|
547b2c285f | ||
|
|
8bcbfd7166 | ||
|
|
1d139d11bf | ||
|
|
7a0c3503a9 | ||
|
|
5ac77b9f31 | ||
|
|
5877f2c20d | ||
|
|
1bb50a3b36 | ||
|
|
8dc3fcb2ec | ||
|
|
d4d032a47d | ||
|
|
70702914b4 | ||
|
|
aa59524a09 | ||
|
|
aa637d96d7 | ||
|
|
284d963b07 | ||
|
|
348a176393 | ||
|
|
84171b89f4 | ||
|
|
d3d1b0ee39 | ||
|
|
fedc43fec8 | ||
|
|
24260d3652 | ||
|
|
c880397eca | ||
|
|
bc1598bb92 | ||
|
|
3e50a2dd56 | ||
|
|
fcdfd8e00f | ||
|
|
5633833085 | ||
|
|
1967e1e273 | ||
|
|
eebfe1acae | ||
|
|
7e473a3872 | ||
|
|
35a285752f | ||
|
|
471822007c | ||
|
|
c014d0b333 | ||
|
|
39db75b4ea | ||
|
|
fad4203892 | ||
|
|
118d475e16 | ||
|
|
e44bd4d858 | ||
|
|
ee059515d0 | ||
|
|
78c9cc422e | ||
|
|
2cb5122bb3 | ||
|
|
ffa620b62b | ||
|
|
2751cf54d8 | ||
|
|
35c9a5d279 | ||
|
|
bcc1213db2 | ||
|
|
1e87e776ed | ||
|
|
abe3a01668 | ||
|
|
0619f73819 | ||
|
|
280e0b09c8 | ||
|
|
216d03f95d | ||
|
|
7e3abe798f | ||
|
|
3b4297ad7d | ||
|
|
d676001557 | ||
|
|
85092482f3 | ||
|
|
d58757ca3c | ||
|
|
473b00c2e7 | ||
|
|
0915a42e64 | ||
|
|
babf5cc9d7 | ||
|
|
f468cea13c | ||
|
|
5c68a90cb0 | ||
|
|
6af750e586 | ||
|
|
73d5152aec | ||
|
|
751f4801d6 | ||
|
|
6758fa57cc | ||
|
|
9353cc0ff1 | ||
|
|
b9b38e5fbf | ||
|
|
62d881d25b | ||
|
|
e3ee0126b2 | ||
|
|
ddf68a0729 | ||
|
|
90c88e4122 | ||
|
|
3fd1ef362c | ||
|
|
5d143f5e75 | ||
|
|
72848d83da | ||
|
|
04bf598060 | ||
|
|
bff39b3f39 | ||
|
|
74d46c2bcb | ||
|
|
7a2df7750c | ||
|
|
c281db9100 | ||
|
|
6ecec86ef8 | ||
|
|
07ab14f625 | ||
|
|
4b04a6c69e | ||
|
|
1ff56084fe | ||
|
|
a2797c4b49 | ||
|
|
35d6c16fc5 | ||
|
|
891a5c1186 | ||
|
|
9c0f5c0921 | ||
|
|
8e93744c73 | ||
|
|
67ada2a1bd | ||
|
|
3ed35f973b | ||
|
|
5ec68c7a5b | ||
|
|
6816609a99 | ||
|
|
06936fa06c | ||
|
|
2725154111 | ||
|
|
c962e6f56a | ||
|
|
70be4f840f | ||
|
|
c02ef75c55 | ||
|
|
27159968f4 | ||
|
|
08fae7b3c3 | ||
|
|
ba58f0c694 | ||
|
|
6de357d643 | ||
|
|
948a99a143 | ||
|
|
5efc685585 | ||
|
|
c2c99edf89 | ||
|
|
282b9ccd7e | ||
|
|
09b104fe11 | ||
|
|
5b65b52c61 | ||
|
|
54d2b58eb3 | ||
|
|
bdca60c3d0 | ||
|
|
4746b8d486 | ||
|
|
3bca9ed158 | ||
|
|
a7385ad068 | ||
|
|
b5e8c8960d | ||
|
|
7364be9057 | ||
|
|
0570dbb774 | ||
|
|
02181ead9e | ||
|
|
6e48514c3b | ||
|
|
ecd495e1d4 | ||
|
|
8c3bfe9890 | ||
|
|
4f2bfb5d0d | ||
|
|
5bbc75fc7c | ||
|
|
724b4ccbdf | ||
|
|
b0b4381f01 | ||
|
|
850bd3b84b | ||
|
|
29edd18309 | ||
|
|
a3200c23a5 | ||
|
|
56ea340e8a | ||
|
|
aa15e6c5fe | ||
|
|
d126717ec1 | ||
|
|
88068f3ccc | ||
|
|
6af4878504 | ||
|
|
81a02e46af | ||
|
|
3fe6791076 | ||
|
|
cfbd75f03d | ||
|
|
c39b34d430 | ||
|
|
c7f607865a | ||
|
|
a7ef03e321 | ||
|
|
786c0b03ae | ||
|
|
5728de8df8 | ||
|
|
107436d78c | ||
|
|
9cd5b06592 | ||
|
|
6d59a6394a | ||
|
|
2aa0a8b4a9 | ||
|
|
92a7157a70 | ||
|
|
4657ac752d | ||
|
|
f5ca87fb23 | ||
|
|
ecfe436a24 | ||
|
|
75722ecbde | ||
|
|
c49713e4d1 | ||
|
|
d2f471bd35 | ||
|
|
aa890a14f5 | ||
|
|
282a538372 | ||
|
|
d140a5098b | ||
|
|
e3f7405fae | ||
|
|
8c89dccf39 | ||
|
|
0f9e64818a | ||
|
|
d5d4bad649 | ||
|
|
b8bf673c5f | ||
|
|
deb549bd95 | ||
|
|
7dfd3b1d87 | ||
|
|
85f8bde398 | ||
|
|
596e04468e | ||
|
|
ecfaa33807 | ||
|
|
737f84bb13 | ||
|
|
73b67e9a4e | ||
|
|
87630b6e74 | ||
|
|
98fb98a86e | ||
|
|
a91658373b | ||
|
|
6976839bfc | ||
|
|
934ed73331 | ||
|
|
700c915495 | ||
|
|
678e059b22 | ||
|
|
9dd6d95be6 | ||
|
|
c99a642669 | ||
|
|
59d351da90 | ||
|
|
61ac2e9c21 | ||
|
|
672aff4eb5 | ||
|
|
9e7b0efc8b | ||
|
|
c32d05fdb2 | ||
|
|
7ed1261193 | ||
|
|
b62fd285d6 | ||
|
|
0ebc5dac3a | ||
|
|
3684c6ca15 | ||
|
|
5d43f14ccb | ||
|
|
a29a30530d | ||
|
|
e61870dd0d | ||
|
|
400a67e240 | ||
|
|
8921375934 | ||
|
|
d63b0ce392 | ||
|
|
fb7b93fbdc | ||
|
|
a80a706379 | ||
|
|
efe304afe6 | ||
|
|
173cba16bd | ||
|
|
b65a684431 | ||
|
|
bf3ec930bc | ||
|
|
80a7f9fcd2 | ||
|
|
16b981651a | ||
|
|
14782c1d33 | ||
|
|
d4a4305f5b | ||
|
|
1d5de1be39 | ||
|
|
526ad333f0 | ||
|
|
a0e96582dd | ||
|
|
98d28d32f3 | ||
|
|
905de7ee78 | ||
|
|
b8400f435f | ||
|
|
4f0b8a8bb4 | ||
|
|
d3a3ea008d | ||
|
|
eab382611c | ||
|
|
be92ffd8ea | ||
|
|
96f2740607 | ||
|
|
4b8d87b05f | ||
|
|
b6507b6cfb | ||
|
|
cb523192d5 | ||
|
|
202274073f | ||
|
|
04765e0c36 | ||
|
|
0678d0ded0 | ||
|
|
5a8bd1d98d | ||
|
|
0f648157fa | ||
|
|
3e6c432511 | ||
|
|
e0d511165c | ||
|
|
a257009780 | ||
|
|
18e40eafe3 | ||
|
|
842711de04 | ||
|
|
ebcd0557e5 | ||
|
|
6b0b4975b9 | ||
|
|
3e71e2428b | ||
|
|
f7901af416 | ||
|
|
2c3a49780f | ||
|
|
9d97a62195 | ||
|
|
94ee23649d | ||
|
|
3e483aad40 | ||
|
|
4fc3ba70fc | ||
|
|
141e7c1f49 | ||
|
|
5c0796b536 | ||
|
|
c28ca9ec16 | ||
|
|
f2c2b9ae8c | ||
|
|
33fe6eb476 | ||
|
|
76e8d79f9f | ||
|
|
6ee1edc8b0 | ||
|
|
4f4fc92345 | ||
|
|
dbcc62ee40 | ||
|
|
1d06c3f058 | ||
|
|
63e2a1c417 | ||
|
|
b9e5a3f3de | ||
|
|
ef3512668c | ||
|
|
59239ca2df | ||
|
|
762f99c0df | ||
|
|
29b266d5ad | ||
|
|
3c61b4a1e4 | ||
|
|
3f9820f2ef | ||
|
|
5de7e74180 | ||
|
|
e60cd2d4d4 | ||
|
|
5497a40f0e | ||
|
|
871072ba95 | ||
|
|
e2cd4a5f8f | ||
|
|
ad25a91a2f | ||
|
|
e69f383a40 | ||
|
|
629f8703ec | ||
|
|
980ced37a8 | ||
|
|
4337026fba | ||
|
|
8e7e5fefb1 | ||
|
|
fde974e51d | ||
|
|
12d72565ae | ||
|
|
5fe77d8fd6 | ||
|
|
b1bcf52a09 | ||
|
|
27ec161e39 | ||
|
|
7b3cf92720 | ||
|
|
70aa29c46b | ||
|
|
b41ec12024 | ||
|
|
46d71cdeb9 | ||
|
|
d156e55233 | ||
|
|
3532aad036 | ||
|
|
4dc1134688 | ||
|
|
975430aa85 | ||
|
|
388868a3ce | ||
|
|
4dfbf55937 | ||
|
|
9e099d6612 | ||
|
|
be54adbfa7 | ||
|
|
c54e9fbedf | ||
|
|
da7fae6566 | ||
|
|
eac655f572 | ||
|
|
a4ed31da74 | ||
|
|
1e800125d5 | ||
|
|
34ff4d1f16 | ||
|
|
1802a28686 | ||
|
|
20630b499e | ||
|
|
a7924e7b6f | ||
|
|
2713bcee1d | ||
|
|
6405f365a9 | ||
|
|
effaa875a6 | ||
|
|
eb8464f687 | ||
|
|
276743d0f9 | ||
|
|
24e01cc8d4 | ||
|
|
bd915704fa | ||
|
|
f17f7041cf | ||
|
|
4a5e7ebed4 | ||
|
|
6ec1569536 | ||
|
|
23dd2695b8 | ||
|
|
11a5e97304 | ||
|
|
bbef11084a | ||
|
|
144516eae5 | ||
|
|
03fce1ed09 | ||
|
|
4e1b9943a4 | ||
|
|
f56f138aec | ||
|
|
800cfaf6c5 | ||
|
|
f77609e6fa | ||
|
|
73ffed012f | ||
|
|
bdc6b8f628 | ||
|
|
618859a050 | ||
|
|
f6e28fc44e | ||
|
|
cb1f5058a7 | ||
|
|
1d20927877 | ||
|
|
ea2c1e24af | ||
|
|
498ce24a09 | ||
|
|
5749548ac8 | ||
|
|
83ef360953 | ||
|
|
780909673a | ||
|
|
e7c698d5f1 | ||
|
|
6e3c3940c2 | ||
|
|
c8230eb2e0 | ||
|
|
b1ebdab0dc | ||
|
|
a60a437206 | ||
|
|
290d955b59 | ||
|
|
114401f62b | ||
|
|
75c773e694 | ||
|
|
8dac4b39c1 | ||
|
|
2c07764a31 | ||
|
|
ee0b13bfda | ||
|
|
64ccf14ba2 | ||
|
|
8abcfbd895 | ||
|
|
6b65571ca1 | ||
|
|
fc535df5d2 | ||
|
|
ed2b41a1a1 | ||
|
|
0bac271cdb | ||
|
|
66a614a9a4 | ||
|
|
adf218345a | ||
|
|
ee749050f0 | ||
|
|
dc4b8cf999 | ||
|
|
927d6ad0a8 | ||
|
|
8ba3fe6d4b | ||
|
|
bdaf5f5a02 | ||
|
|
ea63abbc8a | ||
|
|
f828becdb2 | ||
|
|
ba5b9295a3 | ||
|
|
ded7e9695e | ||
|
|
2d04763fae | ||
|
|
826c48a4dc | ||
|
|
92e193e584 | ||
|
|
92156ffec0 | ||
|
|
4c42c4d5a4 | ||
|
|
b4a0e8809c | ||
|
|
8843fbe5cb | ||
|
|
1439c8c7b0 | ||
|
|
6dc3045ccd | ||
|
|
261e95cb8c | ||
|
|
3d2d9a7654 | ||
|
|
91036bcdc2 | ||
|
|
68c08c67b3 | ||
|
|
8f70aa3957 | ||
|
|
cc7fc32ab1 | ||
|
|
8405cd5a19 | ||
|
|
b83e7d81ee | ||
|
|
19c72085dd | ||
|
|
1b9b272b8a | ||
|
|
b9e104bf2d | ||
|
|
c3fd609929 | ||
|
|
313ccd7831 | ||
|
|
624914b2c0 | ||
|
|
899e4cd5d1 | ||
|
|
403a163692 | ||
|
|
905a46e6cc | ||
|
|
9146a42cfa | ||
|
|
5c1952162b | ||
|
|
a03dbbc365 | ||
|
|
709d474929 | ||
|
|
1e4357c94e | ||
|
|
17111efc7c | ||
|
|
b328b84321 | ||
|
|
18a491fa48 | ||
|
|
a3f9ba1fe0 | ||
|
|
567ca066cf | ||
|
|
62a02ec197 | ||
|
|
e16f2ff47f | ||
|
|
a25bedd36b | ||
|
|
bbb65862b9 | ||
|
|
5da006c4ea | ||
|
|
72c58813a8 | ||
|
|
c9f9bf7daa | ||
|
|
179c1341be | ||
|
|
cefc76d4fc | ||
|
|
60c907e1a9 | ||
|
|
61b3025654 | ||
|
|
0280cdbaec | ||
|
|
375c2a6b6e | ||
|
|
c7949efcc2 | ||
|
|
ddb09c821d | ||
|
|
02097cc6da | ||
|
|
5dd0a03d9a | ||
|
|
711f8f7b46 | ||
|
|
e23a02eb44 | ||
|
|
edd33a0103 | ||
|
|
9e5b9d42c6 | ||
|
|
e574e2def7 | ||
|
|
7a99577093 | ||
|
|
3c87b308f8 | ||
|
|
b625243040 | ||
|
|
c6946cc014 | ||
|
|
e91809a683 | ||
|
|
7377b811e1 | ||
|
|
bc1d03cebd | ||
|
|
c7bc6dc223 | ||
|
|
f273c81d33 | ||
|
|
74cdd1816f | ||
|
|
14ee4b56b5 | ||
|
|
1da6943b7d | ||
|
|
f671952424 | ||
|
|
2d49ebf714 | ||
|
|
ef01d24f02 | ||
|
|
f32c9f52d5 | ||
|
|
6f32d88a4e | ||
|
|
fd05480710 | ||
|
|
83f60686c8 | ||
|
|
bd797798e1 | ||
|
|
e3ed629d8f | ||
|
|
200b86a384 | ||
|
|
865cebe0e7 | ||
|
|
17140bf961 | ||
|
|
aa244fbcce | ||
|
|
6ff5012e18 | ||
|
|
633b44843a | ||
|
|
87a4a0df9c | ||
|
|
cf3bc1edbd | ||
|
|
7a93320a5c | ||
|
|
2c72d060c9 | ||
|
|
82543312c7 | ||
|
|
43e0f92aa2 | ||
|
|
e315e6da6e | ||
|
|
f3a27124d7 | ||
|
|
5a5892b3a7 | ||
|
|
380e6c4210 | ||
|
|
37e74f402e | ||
|
|
b8ac955792 | ||
|
|
b20652120e | ||
|
|
46dad2eddc | ||
|
|
0d2cffb033 | ||
|
|
0699602bbc | ||
|
|
7fe2c54488 | ||
|
|
ee67dcb981 | ||
|
|
8d5dc7ff60 | ||
|
|
6617a0c45f | ||
|
|
1cebd4ac6d | ||
|
|
24aea17132 | ||
|
|
5c2d7a642b | ||
|
|
3178a7472a | ||
|
|
ef0669ab91 | ||
|
|
0055ca09cb | ||
|
|
8777f5da8f | ||
|
|
55e96a5a30 | ||
|
|
b9a2af1e97 | ||
|
|
da930a44ad | ||
|
|
9fbd857506 | ||
|
|
cb1961ff72 | ||
|
|
0c9b15b181 | ||
|
|
9c47496253 | ||
|
|
bc49c5e788 | ||
|
|
edf2cfefc9 | ||
|
|
a5ad030123 | ||
|
|
2af0b2a8b7 | ||
|
|
79c2f40d0b | ||
|
|
cf3dbeee29 | ||
|
|
32f0f1a07f | ||
|
|
fd714756d2 | ||
|
|
209325ca3d | ||
|
|
89c03bc96a | ||
|
|
9dcbc81923 | ||
|
|
e843a69542 | ||
|
|
6ced6dacd6 | ||
|
|
28b0334952 | ||
|
|
c9e8fe831a | ||
|
|
9d703f5b60 | ||
|
|
afaba07b76 | ||
|
|
c825438b72 | ||
|
|
43bb746776 | ||
|
|
0817e0a943 | ||
|
|
2aace71289 | ||
|
|
72270d288e | ||
|
|
66f78a352a | ||
|
|
e7e2fa1e83 | ||
|
|
f97c2b9924 | ||
|
|
3ea7da244f | ||
|
|
5a1ea16354 | ||
|
|
db09966499 | ||
|
|
fd9b25b527 | ||
|
|
eeaf5d4ac9 | ||
|
|
dff0a61d19 | ||
|
|
a6544e5d57 | ||
|
|
817308f13e | ||
|
|
4a527f3ac9 | ||
|
|
1df896f59a | ||
|
|
5ad4331eeb | ||
|
|
fb43b34a2e | ||
|
|
555518a41d | ||
|
|
9bb46769a3 | ||
|
|
709e3376a4 | ||
|
|
66a889c636 | ||
|
|
ef2d93c5a0 | ||
|
|
3547bb0f2a | ||
|
|
3945acbe01 | ||
|
|
dc0cf1d459 | ||
|
|
01d90f55b1 | ||
|
|
b4832ff856 | ||
|
|
7a1b0d3364 | ||
|
|
8c5f0072bb | ||
|
|
2ed6f9616b | ||
|
|
30ccc8017f | ||
|
|
8d2b9255a6 | ||
|
|
5b15e139fd | ||
|
|
636508fc97 | ||
|
|
20a85a4ff7 | ||
|
|
735b497a23 | ||
|
|
681ab8248e | ||
|
|
68a003be20 | ||
|
|
0ae39dca5a | ||
|
|
01f8a7e769 | ||
|
|
6d2757eb91 | ||
|
|
4902b5fa36 | ||
|
|
7d5185ed4d | ||
|
|
7d3e4ece26 | ||
|
|
7e240c7064 | ||
|
|
b335bb83df | ||
|
|
a16a3c3936 | ||
|
|
2b5b56a5bb | ||
|
|
3e31d12db6 | ||
|
|
72c466ca13 | ||
|
|
0880e7864a | ||
|
|
82768efe11 | ||
|
|
9a414b9f09 | ||
|
|
37cea84896 | ||
|
|
a6ad87dc63 | ||
|
|
800f7d3ac2 | ||
|
|
21e8bc02ca | ||
|
|
7b18685825 | ||
|
|
c5f2953e90 | ||
|
|
af3d7ada55 | ||
|
|
adbc7bad61 | ||
|
|
d696a53dcb | ||
|
|
d3f42e6cb0 | ||
|
|
f610e8b3b3 | ||
|
|
deed7905b6 | ||
|
|
1b066a3c8e | ||
|
|
1507e99c1d | ||
|
|
7076cc93a5 | ||
|
|
be6890d189 | ||
|
|
bdfcc56613 | ||
|
|
9af928467b | ||
|
|
43091b01d2 | ||
|
|
8b5d475378 | ||
|
|
4fe928574f | ||
|
|
9072cef8c4 | ||
|
|
e79e1b2cf9 | ||
|
|
73062c70e6 | ||
|
|
3ed857bfc3 | ||
|
|
4c962e6a6d | ||
|
|
12e85b67b8 | ||
|
|
4016ae8a25 | ||
|
|
b2909a3241 | ||
|
|
ea9f53acb8 | ||
|
|
0849431ca9 | ||
|
|
c2a10931b6 | ||
|
|
a05b846703 | ||
|
|
30c2bbc94b | ||
|
|
09b7e77e88 | ||
|
|
2ce6d8c66c | ||
|
|
529951f1ba | ||
|
|
dee385f501 | ||
|
|
73218834ff | ||
|
|
df3eab0a74 | ||
|
|
15c9af3ab2 | ||
|
|
496c43fcf9 | ||
|
|
efd0f35509 | ||
|
|
a23deded22 | ||
|
|
cbb4a890b2 | ||
|
|
8862492480 | ||
|
|
7512f7f017 | ||
|
|
8b2bcc462c | ||
|
|
b1b5b348b3 | ||
|
|
e15f0982cb | ||
|
|
f79a244bf2 | ||
|
|
10c28d982e | ||
|
|
fd324106e3 | ||
|
|
a78224b965 | ||
|
|
5f207b4231 | ||
|
|
3e40713aad | ||
|
|
d7dbeed5d6 | ||
|
|
8818ef04ad | ||
|
|
abfdf04e9f | ||
|
|
3b46e1d3d0 | ||
|
|
dbda23b1e1 | ||
|
|
9a43e49289 | ||
|
|
98c3b67f96 | ||
|
|
cae2388f95 | ||
|
|
484c350538 | ||
|
|
183db2a8e4 | ||
|
|
119db20d25 | ||
|
|
4513f7d2e4 | ||
|
|
f2e96efdb5 | ||
|
|
6ca38476a4 | ||
|
|
d27741e5d9 | ||
|
|
adae44e26f | ||
|
|
b56a0143f3 | ||
|
|
34372148fb | ||
|
|
212164b072 | ||
|
|
0da5f08f22 | ||
|
|
d166e32b3e | ||
|
|
51a16c7110 | ||
|
|
9a14b076c6 | ||
|
|
2180826318 | ||
|
|
3c31a513e1 | ||
|
|
e57538b321 | ||
|
|
d1e2951849 | ||
|
|
472bf7d3b1 | ||
|
|
c22e60092f | ||
|
|
618306b65e | ||
|
|
3ec622d2ee | ||
|
|
88d91ee774 | ||
|
|
4d0d62075a | ||
|
|
484de3829d | ||
|
|
df3e2db84c | ||
|
|
14eaec4cdd | ||
|
|
6e4660dbc0 | ||
|
|
0a56b5bfa7 | ||
|
|
7dd7386068 | ||
|
|
10c87a2057 | ||
|
|
5b5586e2e8 | ||
|
|
ad0e48ac21 | ||
|
|
2f440b5453 | ||
|
|
546f6ca7c2 | ||
|
|
c5223959b2 | ||
|
|
07dc55194b | ||
|
|
1b2cdb9a9b | ||
|
|
8d40ccce0f | ||
|
|
d5a6cb86d2 | ||
|
|
504cb1d596 | ||
|
|
d1ad1668c4 | ||
|
|
6dc45113d2 | ||
|
|
55c7b6551f | ||
|
|
ab470b6be7 | ||
|
|
da225fd4d8 | ||
|
|
06eaf81fa9 | ||
|
|
1b888befa1 | ||
|
|
8ed9cb99e6 | ||
|
|
88405d99ec | ||
|
|
f1efac862b | ||
|
|
0a30a0ee56 | ||
|
|
f1b98f6dd8 | ||
|
|
76a24167d9 | ||
|
|
f7ecaef3eb | ||
|
|
2c53fd2273 | ||
|
|
a835c0a6f5 | ||
|
|
91eb2ac8bd | ||
|
|
d0e130ec8b | ||
|
|
3bb622782e | ||
|
|
e03895329f | ||
|
|
f11ebd9559 | ||
|
|
c7a2fe5d3e | ||
|
|
5200c378c6 | ||
|
|
c42b2bd9c0 | ||
|
|
f59abe1689 | ||
|
|
400de1ef11 | ||
|
|
8d2639f940 | ||
|
|
46f8362501 | ||
|
|
9f4b35211c | ||
|
|
2d1e99affe | ||
|
|
d7634beb50 | ||
|
|
9edf52ed36 | ||
|
|
3fd4154ddd | ||
|
|
41ae916106 | ||
|
|
bc04d3c8e9 | ||
|
|
cf8fe78769 | ||
|
|
d486f529a3 | ||
|
|
562c621ec4 | ||
|
|
8709581d6a | ||
|
|
cd3c27fcc2 | ||
|
|
1dd07df394 | ||
|
|
e53af6f87d | ||
|
|
74eb315215 | ||
|
|
b0c824d79f | ||
|
|
a173850d41 | ||
|
|
e3afecd82c | ||
|
|
2ca01d18eb | ||
|
|
b1371bf1ee | ||
|
|
b5c3d6f34f | ||
|
|
8dadd30702 | ||
|
|
40b770dde8 | ||
|
|
8afaf50d59 | ||
|
|
1cbc239dc0 | ||
|
|
99e09e0d5a | ||
|
|
69feac4d97 | ||
|
|
5b2a54163b | ||
|
|
cf112917d6 | ||
|
|
a8ee490b16 | ||
|
|
c2f0633161 | ||
|
|
973dc12985 | ||
|
|
d9a2d06270 | ||
|
|
4fdbe44825 | ||
|
|
997bcf7edf | ||
|
|
0a1be88185 | ||
|
|
a1ce5e5726 | ||
|
|
92065b2861 | ||
|
|
2e53aa417f | ||
|
|
2fd6f40884 | ||
|
|
eb3f95ea63 | ||
|
|
98dc32fe4c | ||
|
|
7b72c1a034 | ||
|
|
0077a070f2 | ||
|
|
34cef80179 | ||
|
|
31926980e7 | ||
|
|
7fe9ce7321 | ||
|
|
82d38a8403 | ||
|
|
da477ec84e | ||
|
|
db34a7c175 | ||
|
|
78edb66f86 | ||
|
|
8d65fb3495 | ||
|
|
66ce61e756 | ||
|
|
df088af209 | ||
|
|
545140337b | ||
|
|
3b275b5e98 | ||
|
|
cf97d7bb3b | ||
|
|
3cad999c75 | ||
|
|
8f7006281c | ||
|
|
ecaae4c29a | ||
|
|
e2bc739c7f | ||
|
|
0d56fcc294 | ||
|
|
d2d16117f2 | ||
|
|
5d2b252850 | ||
|
|
c984cb956b | ||
|
|
60f2b98ee8 | ||
|
|
cf5223ab46 | ||
|
|
40e26fc25c | ||
|
|
ade92569c1 | ||
|
|
3985c538a8 | ||
|
|
e27ff72830 | ||
|
|
4e804bf9d9 | ||
|
|
7b5883c115 | ||
|
|
ce3af41ebe | ||
|
|
bf15144237 | ||
|
|
76246efb5d | ||
|
|
870488c183 | ||
|
|
64e772f0b1 | ||
|
|
a464698638 | ||
|
|
5cdce4b21a | ||
|
|
c4c05851a7 | ||
|
|
ff29e58d4b | ||
|
|
0542113ace | ||
|
|
2a3e3ad4ba | ||
|
|
3910ecdca2 | ||
|
|
3f2533ae68 | ||
|
|
4c423437a3 | ||
|
|
77e21b4047 | ||
|
|
b0c6afdcee | ||
|
|
c353a04323 | ||
|
|
e94c979900 | ||
|
|
23e52bc1f7 | ||
|
|
9633013275 | ||
|
|
d1e1fffed9 | ||
|
|
40780242fe | ||
|
|
e6f4910254 | ||
|
|
cfbee4943d | ||
|
|
855efe40a6 | ||
|
|
d574855c17 | ||
|
|
c264378b6a | ||
|
|
e7772bb581 | ||
|
|
23834d139b | ||
|
|
c2052b559a | ||
|
|
e2660e38e7 | ||
|
|
56532e3ab8 | ||
|
|
902e913b93 | ||
|
|
e43307d945 | ||
|
|
880fd391c4 | ||
|
|
4180b348f1 | ||
|
|
f4074a4d01 | ||
|
|
30acac1660 | ||
|
|
902346bd0d | ||
|
|
c7c8beba5b | ||
|
|
417908a179 | ||
|
|
4c3ad04015 | ||
|
|
cd3ffe902e | ||
|
|
432ef8f8c8 | ||
|
|
6c337b0f84 | ||
|
|
81e11d6d36 | ||
|
|
ba931407b3 | ||
|
|
a0e92f1f38 | ||
|
|
f1d0f694f5 | ||
|
|
c94e050e58 | ||
|
|
62f156440f | ||
|
|
f0ceabd6f7 | ||
|
|
88e2d839d7 | ||
|
|
5841e96301 | ||
|
|
109fa6b537 | ||
|
|
f7db73db40 | ||
|
|
92eb80265e | ||
|
|
7afac7e0e9 | ||
|
|
3a47dab24e | ||
|
|
4b47c48685 | ||
|
|
00cd571c9b | ||
|
|
e5762bd9c8 | ||
|
|
02a86faa7c | ||
|
|
b8a4748388 | ||
|
|
7bf76198bf | ||
|
|
1853144218 | ||
|
|
b394d7a958 | ||
|
|
3c59dcef70 | ||
|
|
f681453bd0 | ||
|
|
830c38f4bb | ||
|
|
6a7cc64883 | ||
|
|
98b05bfbc6 | ||
|
|
be6fda9404 | ||
|
|
280762c7c1 | ||
|
|
3ff51a5ef8 | ||
|
|
09c49d47d9 | ||
|
|
5f9e166f8b | ||
|
|
245ad761be | ||
|
|
58986c0a4f | ||
|
|
1a56afcb48 | ||
|
|
b6db0715d0 | ||
|
|
65eb853b56 | ||
|
|
fa52568dde | ||
|
|
b752a49432 | ||
|
|
03f2d0d9b9 | ||
|
|
3b7ddc33ee | ||
|
|
0401bc8ef1 | ||
|
|
4882a3b9b2 | ||
|
|
3fe4720668 | ||
|
|
a47dd6ff9e | ||
|
|
96be5f6410 | ||
|
|
e39a3dbdd6 | ||
|
|
25a3ae793b | ||
|
|
15b769a274 | ||
|
|
f90402102b | ||
|
|
ada73e1e20 | ||
|
|
fb0479facd | ||
|
|
9927abd73a | ||
|
|
0b448bf68f | ||
|
|
9e18743b1b | ||
|
|
c3222c046f | ||
|
|
a775b2c62c | ||
|
|
c4b0444e53 | ||
|
|
78f382a8f1 | ||
|
|
9d2aa61ea0 | ||
|
|
610c051e38 | ||
|
|
140efd6cfd | ||
|
|
2ba773373c | ||
|
|
0e119dd6f1 | ||
|
|
2bd66ced8c | ||
|
|
01e5d87002 | ||
|
|
0ae2f9b53a | ||
|
|
aa357d463c | ||
|
|
064ab69058 | ||
|
|
4e9d624877 | ||
|
|
4fb90392b0 | ||
|
|
a39313a4bb | ||
|
|
a523f70a14 | ||
|
|
641310f4a8 | ||
|
|
2fc5a19f50 | ||
|
|
064024514c | ||
|
|
6e00be4796 | ||
|
|
60168420dc | ||
|
|
80a901704c | ||
|
|
e8cf06d3be | ||
|
|
59f69bea05 | ||
|
|
28f246749f | ||
|
|
fe49c78134 | ||
|
|
ad5b0c3a6a | ||
|
|
e788bb7801 | ||
|
|
ecb1711970 | ||
|
|
b9aa229182 | ||
|
|
b7f84a97b5 | ||
|
|
7afa30f3d8 | ||
|
|
9fcc3248fa | ||
|
|
3865e253ff | ||
|
|
9db5eb726d | ||
|
|
995fea2943 | ||
|
|
631f942a7f | ||
|
|
17df575f54 | ||
|
|
c37c825333 | ||
|
|
22ea05b3aa | ||
|
|
3db26de77b | ||
|
|
79eb359587 | ||
|
|
984d22009b | ||
|
|
a77e9fd905 | ||
|
|
241c3832fa | ||
|
|
4b90fffb69 | ||
|
|
cbb09e4780 | ||
|
|
65a0b41071 | ||
|
|
ef20f4229c | ||
|
|
ee38ee55d4 | ||
|
|
fa46338010 | ||
|
|
c04e8f3c11 | ||
|
|
60aef02fa5 | ||
|
|
fe2cc49a55 | ||
|
|
6334e86721 | ||
|
|
da164c2332 | ||
|
|
751e20043f | ||
|
|
c9c4d78e30 | ||
|
|
874fac0c63 | ||
|
|
1f43a83c5c | ||
|
|
f8c872db55 | ||
|
|
d09a563200 | ||
|
|
058a5297ea | ||
|
|
e060b91947 | ||
|
|
fb853d50b9 | ||
|
|
e341c0f028 | ||
|
|
d4443f9682 | ||
|
|
9a2aff5b1e | ||
|
|
254aea276b | ||
|
|
dd2227223d | ||
|
|
4a9258cc65 | ||
|
|
313833b7d9 | ||
|
|
46d9465841 | ||
|
|
c5081979f0 | ||
|
|
10d5fdcac3 | ||
|
|
b92293efe9 | ||
|
|
89bcbcf4e5 | ||
|
|
1f869f309f | ||
|
|
e77402d7b3 | ||
|
|
084bb5bcd5 | ||
|
|
9e0600edfa | ||
|
|
1ed853e255 | ||
|
|
d6334b9748 | ||
|
|
e8dc1e4d93 | ||
|
|
6ff961d250 | ||
|
|
c4731d8b8d | ||
|
|
9483448aa3 | ||
|
|
9f6c3a920f | ||
|
|
d5139b6363 | ||
|
|
7482abfd3c | ||
|
|
a6a807ffcb | ||
|
|
999f8c8032 | ||
|
|
9b062fd5b8 | ||
|
|
9b0bcee0a7 | ||
|
|
da2849dfcf | ||
|
|
603d5754db | ||
|
|
96a5df0b68 | ||
|
|
f344b46dea | ||
|
|
2962851527 | ||
|
|
14064f94eb | ||
|
|
a8c7b217a4 | ||
|
|
8d1c8f43ec | ||
|
|
3fa887367c | ||
|
|
4bbea1f0d0 | ||
|
|
f696cfb915 | ||
|
|
037890cfa5 | ||
|
|
0d4b8ee2c0 | ||
|
|
7fd14c1427 | ||
|
|
7a261aec95 | ||
|
|
d8dd96e39e | ||
|
|
0bde0019f1 | ||
|
|
587ac7bf00 | ||
|
|
0c7c73a3e9 | ||
|
|
239862cae2 | ||
|
|
99c05b67c4 | ||
|
|
b484d03de6 | ||
|
|
caeef02be3 | ||
|
|
a18ff6a0a1 | ||
|
|
d49d2271cf | ||
|
|
ebdd7b37ed | ||
|
|
c3c4e17b13 | ||
|
|
56058e73f0 | ||
|
|
c1f9068c11 | ||
|
|
746239cf69 | ||
|
|
02711f268d | ||
|
|
ffed4a5e32 | ||
|
|
86930f1a7e | ||
|
|
acb25b0a16 | ||
|
|
27a2f38ff6 | ||
|
|
a43e5fc16b | ||
|
|
1c44d7a36f | ||
|
|
fc14d83988 | ||
|
|
844ab9ae15 | ||
|
|
16489db78e | ||
|
|
ffc6589fa1 | ||
|
|
cc285ef23c | ||
|
|
9a2215de29 | ||
|
|
62a3b0d6ae | ||
|
|
c7269fa310 | ||
|
|
54625af501 | ||
|
|
62e53f8960 | ||
|
|
77bfc86c6f | ||
|
|
75d6745372 | ||
|
|
4a97994bff | ||
|
|
7593cc2724 | ||
|
|
facbd5492c | ||
|
|
1f051f737a | ||
|
|
1ab31f1b44 | ||
|
|
c3051cbf90 | ||
|
|
73b8c2d3c4 | ||
|
|
cc06ddf3b1 | ||
|
|
672d5ddbd1 | ||
|
|
5f01a83214 | ||
|
|
e5f37ee6a9 | ||
|
|
66e8f140c1 | ||
|
|
b7a0e9e2d7 | ||
|
|
522576cb37 | ||
|
|
b130511450 | ||
|
|
15e138e492 | ||
|
|
07037a82e7 | ||
|
|
c6ff9717d4 | ||
|
|
6ee705e786 | ||
|
|
dcde323740 | ||
|
|
22b4c30774 | ||
|
|
a1631b421a | ||
|
|
da86483d66 | ||
|
|
fd0c7918ff | ||
|
|
de7104e48f | ||
|
|
84ad1344c7 | ||
|
|
0c524a3e8b | ||
|
|
829ccedc80 | ||
|
|
1d67c6f8dc | ||
|
|
d92ac9275f | ||
|
|
fec3db13d5 | ||
|
|
8b0030ca9b | ||
|
|
700a71f393 | ||
|
|
5134cc2ff2 | ||
|
|
cd30285d87 | ||
|
|
56b383d9db | ||
|
|
8fece7c49a | ||
|
|
00c4a89add | ||
|
|
7b1c4595b8 | ||
|
|
105b8fd8bd | ||
|
|
bebb448ffb | ||
|
|
51512ad436 | ||
|
|
3cc5231185 | ||
|
|
85fba82266 | ||
|
|
2387dbd1ad | ||
|
|
a2234e9271 | ||
|
|
55953feeb1 | ||
|
|
732a430119 | ||
|
|
9ea3a38ebb | ||
|
|
654b258d97 | ||
|
|
2ab4af656b | ||
|
|
cb83bc1b67 | ||
|
|
6de900e87a | ||
|
|
b0defe9ce6 | ||
|
|
5af756488a | ||
|
|
c78095e2d3 | ||
|
|
81ae40bcde | ||
|
|
51a657c41c | ||
|
|
dd359090fd | ||
|
|
9e165ca150 | ||
|
|
4830be32b3 | ||
|
|
5b2a41fdae | ||
|
|
c64c8ab240 | ||
|
|
f9191aba6b | ||
|
|
2242097992 | ||
|
|
6ae44df975 | ||
|
|
88e5ff8f6b | ||
|
|
e6fc58d797 | ||
|
|
f0bb504b6c | ||
|
|
157692bc48 | ||
|
|
ed20a51ed2 | ||
|
|
b0c637bfff | ||
|
|
5f6f1de1d3 | ||
|
|
0a499f4e2b | ||
|
|
e8b7f53c84 | ||
|
|
9052f0d32e | ||
|
|
e03a9d818e | ||
|
|
9367fa95d7 | ||
|
|
a2c624c3b3 | ||
|
|
d49a85b35a | ||
|
|
0cf707f2c7 | ||
|
|
077fdb4d82 | ||
|
|
5fa86c6a33 | ||
|
|
13669eee96 | ||
|
|
c5168b8905 | ||
|
|
a72b61423a | ||
|
|
b78817526e | ||
|
|
1a31d83699 | ||
|
|
5deca3fac7 | ||
|
|
6112405c9f | ||
|
|
86e311ec44 | ||
|
|
5076c948d8 | ||
|
|
f546a7ab20 | ||
|
|
0a67b254f8 | ||
|
|
518e04cab7 | ||
|
|
61f247235a | ||
|
|
2393424bde | ||
|
|
dd863d3948 | ||
|
|
b90065451b | ||
|
|
54c5314462 | ||
|
|
7e550200aa | ||
|
|
81d23edd72 | ||
|
|
09c940bfe2 | ||
|
|
0186f12972 | ||
|
|
c3c092967f | ||
|
|
2c32a62f6a | ||
|
|
7c73b91129 | ||
|
|
36e564e53d | ||
|
|
895e16710b | ||
|
|
dd471503ba | ||
|
|
aaf52d4282 | ||
|
|
66c244f540 | ||
|
|
747f4b9d20 | ||
|
|
cebe18e6d6 | ||
|
|
7d8920db82 | ||
|
|
03a604d543 | ||
|
|
d423ebeac0 | ||
|
|
19e37d149b | ||
|
|
b19e056a37 | ||
|
|
97eea98f11 | ||
|
|
2739a839ed | ||
|
|
6ae4aa2b73 | ||
|
|
bf620b4703 | ||
|
|
e26a2c3e21 | ||
|
|
a8b02015ce | ||
|
|
a651bb589d | ||
|
|
f720277d29 | ||
|
|
fa93715135 | ||
|
|
9a103ddbcf | ||
|
|
5956d5142f | ||
|
|
a4b39e6fd0 | ||
|
|
b7f6ed2107 | ||
|
|
2e0597ffe0 | ||
|
|
fb68e14a24 | ||
|
|
7c700f9f80 | ||
|
|
7d02650616 | ||
|
|
c8fe12cb8e | ||
|
|
2b66b91f3a | ||
|
|
454b77da4e | ||
|
|
66d1aedcb0 | ||
|
|
93b421cd73 | ||
|
|
7e2c6da812 | ||
|
|
b732a6c578 | ||
|
|
26f7d180a7 | ||
|
|
006b14bda7 | ||
|
|
17dd059f13 | ||
|
|
40b19cfef2 | ||
|
|
20ec0b6e05 | ||
|
|
5e79ec4b32 | ||
|
|
ef3eb05d69 | ||
|
|
344bbb4fcd | ||
|
|
d6eecb7844 | ||
|
|
730f03dcd8 | ||
|
|
39dd9110f5 | ||
|
|
82ed854341 | ||
|
|
52bdb13bdc | ||
|
|
8a8ff6fddc | ||
|
|
fd20831e92 | ||
|
|
e6f9f2e2e6 | ||
|
|
2454a7a876 | ||
|
|
4c626fdd13 | ||
|
|
f7b7fc151a | ||
|
|
4291cd6279 | ||
|
|
8563fa6abd | ||
|
|
7e4195a6eb | ||
|
|
371ec63cc7 | ||
|
|
52b44764f4 | ||
|
|
a78cd98a3e | ||
|
|
e4c5b85739 | ||
|
|
765bca915e | ||
|
|
04a6fa02e2 | ||
|
|
c529ba1c87 | ||
|
|
5473a8d25d | ||
|
|
c00d75ca5b | ||
|
|
91da8e11ff | ||
|
|
47fad1f11a | ||
|
|
90f0bcbc8a | ||
|
|
0b38b11ce6 | ||
|
|
5546558197 | ||
|
|
f0d2f4d225 | ||
|
|
1cd1c1e0b3 | ||
|
|
13488b2eaa | ||
|
|
1304f0f098 | ||
|
|
97c02dd5b5 | ||
|
|
daaa6a7e2e | ||
|
|
2effcb42b7 | ||
|
|
fed338985d | ||
|
|
ff34190f92 | ||
|
|
e9ef89be5e | ||
|
|
c6718b3a5e | ||
|
|
6d1732d830 | ||
|
|
f9f58e1ca7 | ||
|
|
6faefd876a | ||
|
|
bb015f2bfa | ||
|
|
950c3d9f1e | ||
|
|
46e71cd7c7 | ||
|
|
399933bc5e | ||
|
|
c5ed3139b7 | ||
|
|
eabf0985ef | ||
|
|
369116767a | ||
|
|
a67c0b41af | ||
|
|
5ee53ad996 | ||
|
|
bafbe20063 | ||
|
|
80cd8f7b32 | ||
|
|
ebfa8f08a1 | ||
|
|
2ecbaf4507 | ||
|
|
509de0f5e9 | ||
|
|
21c9965750 | ||
|
|
588f5cb8c0 | ||
|
|
b864b88935 | ||
|
|
0f8def4348 | ||
|
|
f619e628f1 | ||
|
|
15c181bc52 | ||
|
|
8ddd793a36 | ||
|
|
a6708979ba | ||
|
|
9bba73a8ff | ||
|
|
a9ce88255d | ||
|
|
c39ba69250 | ||
|
|
1483207919 | ||
|
|
cdd987e627 | ||
|
|
d7a8f0dcc3 | ||
|
|
383ab9e479 | ||
|
|
05c05c62ec | ||
|
|
a63a3074bd | ||
|
|
0d4a8403fc |
18288 changed files with 1874657 additions and 293634 deletions
60
.bazelrc
60
.bazelrc
|
|
@ -1,39 +1,41 @@
|
|||
build --action_env=ZERO_AR_DATE=1
|
||||
|
||||
build --apple_platform_type=ios
|
||||
build --enable_platform_specific_config
|
||||
build --apple_crosstool_top=@local_config_apple_cc//:toolchain
|
||||
build --crosstool_top=@local_config_apple_cc//:toolchain
|
||||
build --host_crosstool_top=@local_config_apple_cc//:toolchain
|
||||
|
||||
build --cxxopt='-std=c++17'
|
||||
build --per_file_copt="third-party/webrtc/.*\.cpp$","@-std=c++17"
|
||||
build --per_file_copt="third-party/webrtc/.*\.cc$","@-std=c++17"
|
||||
build --per_file_copt="third-party/webrtc/.*\.mm$","@-std=c++17"
|
||||
build --per_file_copt="submodules/LottieMeshSwift/LottieMeshBinding/Sources/.*\.mm$","@-std=c++17"
|
||||
build --per_file_copt="submodules/LottieCpp/lottiecpp/Sources/.*\.mm$","@-std=c++17"
|
||||
build --per_file_copt="submodules/LottieCpp/lottiecpp/Sources/.*\.cpp$","@-std=c++17"
|
||||
build --per_file_copt="submodules/LottieCpp/lottiecpp/PlatformSpecific/Darwin/Sources/.*\.mm$","@-std=c++17"
|
||||
build --per_file_copt="submodules/LottieCpp/lottiecpp/PlatformSpecific/Darwin/Sources/.*\.cpp$","@-std=c++17"
|
||||
build --per_file_copt="Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/.*\.cpp$","@-std=c++17"
|
||||
build --per_file_copt="Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/.*\.mm$","@-std=c++17"
|
||||
# macOS-specific settings (auto-applied on macOS via --enable_platform_specific_config)
|
||||
build:macos --apple_platform_type=ios
|
||||
build:macos --apple_crosstool_top=@local_config_apple_cc//:toolchain
|
||||
build:macos --crosstool_top=@local_config_apple_cc//:toolchain
|
||||
build:macos --host_crosstool_top=@local_config_apple_cc//:toolchain
|
||||
build:macos --per_file_copt=".*\.m$","@-fno-objc-msgsend-selector-stubs"
|
||||
build:macos --per_file_copt=".*\.mm$","@-fno-objc-msgsend-selector-stubs"
|
||||
build:macos --features=debug_prefix_map_pwd_is_dot
|
||||
build:macos --features=swift.cacheable_swiftmodules
|
||||
build:macos --features=swift.debug_prefix_map
|
||||
build:macos --features=swift.enable_vfsoverlays
|
||||
build:dbg --features=swift.emit_swiftsourceinfo
|
||||
|
||||
build --swiftcopt=-whole-module-optimization
|
||||
|
||||
build --per_file_copt=".*\.m$","@-fno-objc-msgsend-selector-stubs"
|
||||
build --per_file_copt=".*\.mm$","@-fno-objc-msgsend-selector-stubs"
|
||||
|
||||
#build --linkopt="-ld_classic"
|
||||
|
||||
build --features=debug_prefix_map_pwd_is_dot
|
||||
build --features=swift.cacheable_swiftmodules
|
||||
build --features=swift.debug_prefix_map
|
||||
build --features=swift.enable_vfsoverlays
|
||||
# Linux-specific settings (auto-applied on Linux via --enable_platform_specific_config)
|
||||
build:linux --action_env=CC
|
||||
build:linux --action_env=CXX
|
||||
|
||||
build --strategy=Genrule=standalone
|
||||
build --spawn_strategy=standalone
|
||||
|
||||
build --strategy=SwiftCompile=standalone
|
||||
build --define RULES_SWIFT_BUILD_DUMMY_WORKER=1
|
||||
build:macos --strategy=SwiftCompile=worker
|
||||
|
||||
build --noenable_bzlmod
|
||||
# SourceKit BSP: Swift indexing features (macOS only)
|
||||
common:macos --features=swift.index_while_building
|
||||
common:macos --features=swift.use_global_index_store
|
||||
common:macos --features=swift.use_global_module_cache
|
||||
common:macos --features=oso_prefix_is_pwd
|
||||
|
||||
# SourceKit BSP: Index build config (used for background indexing)
|
||||
common:index_build --experimental_convenience_symlinks=ignore
|
||||
common:index_build --show_result=0
|
||||
common:index_build --noshow_loading_progress
|
||||
common:index_build --noshow_progress
|
||||
common:index_build --noannounce_rc
|
||||
common:index_build --noshow_timestamps
|
||||
common:index_build --curses=no
|
||||
common:index_build --color=no
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
||||
spm-files
|
||||
15
.gitignore
vendored
15
.gitignore
vendored
|
|
@ -69,4 +69,17 @@ submodules/OpusBinding/SharedHeaders/*
|
|||
submodules/FFMpegBinding/SharedHeaders/*
|
||||
submodules/OpenSSLEncryptionProvider/SharedHeaders/*
|
||||
submodules/TelegramCore/FlatSerialization/Sources/*
|
||||
buildServer.json
|
||||
buildServer.json
|
||||
.build/**
|
||||
Telegram.LSP.json
|
||||
**/.build/**
|
||||
spm-files
|
||||
xcode-files
|
||||
.bsp/**
|
||||
.sourcekit-lsp/**
|
||||
/.claude/
|
||||
**/.claude/settings.local.json
|
||||
**/.vscode/launch.json
|
||||
/buildbox/*
|
||||
**/node_modules/
|
||||
tools/sim-watcher/dist/
|
||||
|
|
|
|||
|
|
@ -21,15 +21,14 @@ internal:
|
|||
script:
|
||||
- export PATH=/opt/homebrew/opt/ruby/bin:$PATH
|
||||
- export PATH=`gem environment gemdir`/bin:$PATH
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appcenter-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=adhoc --configuration=release_arm64
|
||||
- python3 -u build-system/Make/DeployToAppCenter.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/appcenter-configurations/appcenter-internal.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appcenter-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=adhoc --configuration=release_arm64 --embedWatchApp --watchApiId="$TELEGRAM_WATCHOS_APP_ID" --watchApiHash="$TELEGRAM_WATCHOS_APP_HASH"
|
||||
- python3 -u build-system/Make/DeployBuild.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/deploy-configurations/internal-configuration.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
- rm -rf build-input/configuration-repository-workdir
|
||||
- rm -rf build-input/configuration-repository
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="$TELEGRAM_PRIVATE_DATA_PATH/build-configurations/enterprise-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=enterprise --configuration=release_arm64 --embedWatchApp --watchApiId="$TELEGRAM_WATCHOS_APP_ID" --watchApiHash="$TELEGRAM_WATCHOS_APP_HASH"
|
||||
- python3 -u build-system/Make/DeployBuild.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/deploy-configurations/enterprise-configuration.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
environment:
|
||||
name: internal
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build/artifacts
|
||||
expire_in: 1 week
|
||||
|
||||
internal_testflight:
|
||||
tags:
|
||||
|
|
@ -40,10 +39,15 @@ internal_testflight:
|
|||
except:
|
||||
- tags
|
||||
script:
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_arm64
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_arm64 --embedWatchApp --watchApiId="$TELEGRAM_WATCHOS_APP_ID" --watchApiHash="$TELEGRAM_WATCHOS_APP_HASH"
|
||||
- python3 -u build-system/Make/Make.py remote-deploy-testflight --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
environment:
|
||||
name: testflight_llc
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build/artifacts
|
||||
expire_in: 1 week
|
||||
|
||||
appstore_development:
|
||||
tags:
|
||||
|
|
@ -55,7 +59,6 @@ appstore_development:
|
|||
- tags
|
||||
script:
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="$TELEGRAM_PRIVATE_DATA_PATH/build-configurations/enterprise-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=enterprise --configuration=release_arm64
|
||||
- python3 -u build-system/Make/DeployToAppCenter.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/appcenter-configurations/appstore-development.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
environment:
|
||||
name: appstore-development
|
||||
artifacts:
|
||||
|
|
@ -74,8 +77,8 @@ experimental_i:
|
|||
script:
|
||||
- export PATH=/opt/homebrew/opt/ruby/bin:$PATH
|
||||
- export PATH=`gem environment gemdir`/bin:$PATH
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=adhoc --configuration=release_arm64
|
||||
- python3 -u build-system/Make/DeployToAppCenter.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/appcenter-configurations/appcenter-experimental.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appcenter-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=adhoc --configuration=release_arm64
|
||||
- python3 -u build-system/Make/Make.py remote-deploy-testflight --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
environment:
|
||||
name: experimental
|
||||
artifacts:
|
||||
|
|
@ -93,7 +96,6 @@ experimental:
|
|||
- tags
|
||||
script:
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="$TELEGRAM_PRIVATE_DATA_PATH/build-configurations/enterprise-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=enterprise --configuration=release_arm64
|
||||
- python3 -u build-system/Make/DeployToAppCenter.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/appcenter-configurations/appcenter-experimental2.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip"
|
||||
environment:
|
||||
name: experimental-2
|
||||
artifacts:
|
||||
|
|
@ -113,7 +115,7 @@ beta_testflight:
|
|||
script:
|
||||
- export PATH=/opt/homebrew/opt/ruby/bin:$PATH
|
||||
- export PATH=`gem environment gemdir`/bin:$PATH
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_arm64
|
||||
- python3 -u build-system/Make/Make.py remote-build --darwinContainers="$DARWIN_CONTAINERS" --darwinContainersHost="$DARWIN_CONTAINERS_HOST" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_arm64 --embedWatchApp --watchApiId="$TELEGRAM_WATCHOS_APP_ID" --watchApiHash="$TELEGRAM_WATCHOS_APP_HASH"
|
||||
environment:
|
||||
name: testflight_llc
|
||||
artifacts:
|
||||
|
|
|
|||
9
.gitmodules
vendored
9
.gitmodules
vendored
|
|
@ -29,3 +29,12 @@ url=../tgcalls.git
|
|||
[submodule "third-party/dav1d/dav1d"]
|
||||
path = third-party/dav1d/dav1d
|
||||
url = https://github.com/ali-fareed/dav1d.git
|
||||
[submodule "third-party/td/td"]
|
||||
path = third-party/td/td
|
||||
url = https://github.com/tdlib/td
|
||||
[submodule "third-party/XcodeGen"]
|
||||
path = third-party/XcodeGen
|
||||
url = https://github.com/yonaskolb/XcodeGen.git
|
||||
[submodule "build-system/bazel-rules/sourcekit-bazel-bsp"]
|
||||
path = build-system/bazel-rules/sourcekit-bazel-bsp
|
||||
url = https://github.com/spotify/sourcekit-bazel-bsp.git
|
||||
|
|
|
|||
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "sweetpad-lldb",
|
||||
"request": "attach",
|
||||
"name": "Attach to running app (SweetPad)",
|
||||
"preLaunchTask": "sweetpad: launch",
|
||||
"codelldbAttributes": {
|
||||
"initCommands": [
|
||||
"command source ~/.lldbinit-Xcode"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
32
.vscode/settings.json
vendored
32
.vscode/settings.json
vendored
|
|
@ -1,5 +1,29 @@
|
|||
{
|
||||
"sweetpad.build.xcodeWorkspacePath": "Telegram/Telegram.xcodeproj/project.xcworkspace",
|
||||
"lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB",
|
||||
"lldb.launch.expressions": "native"
|
||||
}
|
||||
"swift.disableSwiftPackageManagerIntegration": true,
|
||||
"swift.autoGenerateLaunchConfigurations": false,
|
||||
"swift.disableAutoResolve": true,
|
||||
"search.followSymlinks": false,
|
||||
"files.exclude": {
|
||||
".git/**": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
".git/**": true
|
||||
},
|
||||
"search.exclude": {
|
||||
".git/**": true
|
||||
},
|
||||
"swift.sourcekit-lsp.backgroundIndexing": "on",
|
||||
"swift.sourcekit-lsp.trace.server": "messages",
|
||||
"terminal.integrated.profiles.osx": {
|
||||
"zsh": {
|
||||
"path": "/bin/zsh",
|
||||
"args": [
|
||||
"-l",
|
||||
"-i"
|
||||
]
|
||||
}
|
||||
},
|
||||
"swift.sourcekit-lsp.serverPath": "${workspaceFolder}/build-input/sourcekit-lsp",
|
||||
"sourcekit-bazel-bsp.rulesAppleName": "build_bazel_rules_apple",
|
||||
"cmake.sourceDirectory": "/Users/ali/build/telegram/telegram-ios/submodules/rlottie/rlottie/test"
|
||||
}
|
||||
|
|
|
|||
19
.vscode/tasks.json
vendored
19
.vscode/tasks.json
vendored
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "sweetpad",
|
||||
"action": "launch",
|
||||
"problemMatcher": [
|
||||
"$sweetpad-watch", // ! Required for debugging
|
||||
"$sweetpad-xcodebuild-default",
|
||||
"$sweetpad-xcbeautify-errors",
|
||||
"$sweetpad-xcbeautify-warnings"
|
||||
],
|
||||
"label": "sweetpad: launch",
|
||||
"detail": "Build and Launch the app",
|
||||
"isBackground": true // ! Required for debugging
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
2
.xcodebuildmcp/config.yaml
Normal file
2
.xcodebuildmcp/config.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
schemaVersion: 1
|
||||
enabledWorkflows: ["simulator", "debugging", "ui-automation"]
|
||||
31
BUILD.bazel
Normal file
31
BUILD.bazel
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
load("@sourcekit_bazel_bsp//rules:setup_sourcekit_bsp.bzl", "setup_sourcekit_bsp")
|
||||
|
||||
exports_files(["versions.json"])
|
||||
|
||||
setup_sourcekit_bsp(
|
||||
name = "setup_sourcekit_bsp",
|
||||
bazel_wrapper = "./build-input/bazel-8.4.2-darwin-arm64",
|
||||
files_to_watch = [
|
||||
"Telegram/**/*.swift",
|
||||
"Telegram/**/*.h",
|
||||
"Telegram/**/*.m",
|
||||
"Telegram/**/*.mm",
|
||||
"Telegram/**/*.c",
|
||||
"Telegram/**/*.cpp",
|
||||
"submodules/**/*.swift",
|
||||
"submodules/**/*.h",
|
||||
"submodules/**/*.m",
|
||||
"submodules/**/*.mm",
|
||||
"submodules/**/*.c",
|
||||
"submodules/**/*.cpp",
|
||||
],
|
||||
aquery_flags = [
|
||||
],
|
||||
index_flags = [
|
||||
"config=index_build",
|
||||
],
|
||||
index_build_batch_size = 10,
|
||||
targets = [
|
||||
"//Telegram:Telegram",
|
||||
],
|
||||
)
|
||||
161
CLAUDE.md
Normal file
161
CLAUDE.md
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to AI assistants when working with code in this repository.
|
||||
|
||||
## Build
|
||||
|
||||
The app is built using Bazel via the `Make.py` wrapper. There is no selective per-module build — the only supported invocation builds the full `Telegram/Telegram` target.
|
||||
|
||||
**Command:**
|
||||
|
||||
```sh
|
||||
python3 build-system/Make/Make.py --overrideXcodeVersion \
|
||||
--cacheDir ~/telegram-bazel-cache \
|
||||
build \
|
||||
--configurationPath build-system/appstore-configuration.json \
|
||||
--gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git \
|
||||
--gitCodesigningType development --gitCodesigningUseCurrent --buildNumber=1 --configuration=debug_sim_arm64
|
||||
```
|
||||
|
||||
Add `--continueOnError` after `build` (forwards to bazel's `--keep_going`) when verifying changes that may surface errors in many files at once — it lets the full set of errors land in one pass instead of stopping at the first failing target.
|
||||
|
||||
The build needs `TELEGRAM_CODESIGNING_GIT_PASSWORD` in the environment. It is set in `~/.zshrc` but Claude Code's bash tool does NOT source shell config by default. Prefix build commands with `source ~/.zshrc 2>/dev/null;` to pick it up.
|
||||
|
||||
## Code Style Guidelines
|
||||
- **Naming**: PascalCase for types, camelCase for variables/methods
|
||||
- **Imports**: Group and sort imports at the top of files
|
||||
- **Error Handling**: Properly handle errors with appropriate redaction of sensitive data
|
||||
- **Formatting**: Use standard Swift/Objective-C formatting and spacing
|
||||
- **Types**: Prefer strong typing and explicit type annotations where needed
|
||||
- **Documentation**: Document public APIs with comments
|
||||
|
||||
## Project Structure
|
||||
- Core launch and application extensions code is in `Telegram/` directory
|
||||
- Most code is organized into libraries in `submodules/`
|
||||
- External code is located in `third-party/`
|
||||
- No tests are used at the moment
|
||||
|
||||
## Embedded watch app (`Telegram/WatchApp`)
|
||||
|
||||
A standalone watchOS Telegram client (developed in the separate `~/build/tgwatch` repo) is vendored into this repo at `Telegram/WatchApp/` and can be embedded into the **device** IPA under `Telegram.app/Watch/`. It is built by `xcodebuild` (not Bazel) and codesigned by the Bazel build.
|
||||
|
||||
**Build it:** add `--embedWatchApp` to a Make.py **device** build (`--configuration=debug_arm64` or `release_arm64`) together with `--watchApiId`, `--watchApiHash`, `--watchSigningIdentity`, `--watchProvisioningProfile`. Off by default (it adds a ~4-min xcodebuild step); simulator builds never embed, and the default `debug_sim_arm64` build is unaffected.
|
||||
|
||||
**`Telegram/WatchApp/` is a synced snapshot — do not hand-edit it.** The source of truth and dev tooling live in the `tgwatch` repo. To change the watch app, edit it there, then re-sync with `tgwatch/tools/export-sources.sh /abs/path/to/telegram-ios/Telegram/WatchApp` and commit the result. The committed `tgwatch.xcodeproj` is generated (kept via a `!tgwatch.xcodeproj` negation in `Telegram/WatchApp/.gitignore`, since the root `.gitignore` ignores `*.xcodeproj`); `.build`/`.swiftpm`/`xcuserdata` are excluded.
|
||||
|
||||
**How it's wired:** `//Telegram:TelegramWatchApp` (rule in `Telegram/prebuilt_watchos.bzl`) runs in **two actions**: `PrebuiltWatchosCompile` (`Telegram/prebuilt_watchos_compile.sh`) runs xcodebuild on the snapshot in a writable temp copy with PLACEHOLDER version/api values (the bundle ids are baked from the snapshot's pbxproj/Info.plist — `ph.telegra.Telegraph.watchkitapp` / `ph.telegra.Telegraph`), emitting an unsigned `.app`; `PrebuiltWatchosPatchSign` (`Telegram/prebuilt_watchos_patch.sh`) then rewrites **six** per-build Info.plist keys (`CFBundleShortVersionString`, `CFBundleVersion`, `TG_API_ID`, `TG_API_HASH`, `CFBundleIdentifier`, `WKCompanionAppBundleIdentifier`) and codesigns the `.app` + nested `TDLibFramework.framework` (identity + the watchkitapp profile from `--define`s). The result feeds the `Telegram` `ios_application`'s `watch_application` slot (gated by the `//Telegram:embedWatchApp` flag). The rule takes `bundle_id` (set to `"{telegram_bundle_id}.watchkitapp"` in `Telegram/BUILD`) and derives the host bundle id by stripping the `.watchkitapp` suffix; both are passed to the patch worker as args (not action inputs), so the patch action re-runs when the host bundle id changes but the (expensive) compile stays cached. **The compile action's only inputs are the snapshot (+ its worker)** — so changing the version, build number, api id/hash, host bundle id, or signing identity re-runs only the cheap patch+sign action, not xcodebuild; xcodebuild re-runs only when the snapshot changes. This is correct because none of those values reach the compiled binary: each lands only in the Info.plist (via `$(...)` substitution and a runtime `Bundle.main.object(forInfoDictionaryKey:)` lookup in `Secrets.swift`, except for the bundle-id keys which only Info.plist consumers read).
|
||||
|
||||
**Non-obvious invariants** (also in the `.bzl` comments): `AppleBundleInfo`'s public init is banned — use the internal `new_applebundleinfo`; `watch_application` requires BOTH `AppleBundleInfo` (with a non-None `infoplist` File) AND `WatchosApplicationBundleInfo`; the embedded watch app's `CFBundleShortVersionString`/`CFBundleVersion` must exactly equal the host's (sourced from `versions.json['app']` + `--define=buildNumber`); the host does NOT re-sign the embedded watch app, so the worker must sign it; the watch bundle id `ph.telegra.Telegraph.watchkitapp` must track the host `telegram_bundle_id`.
|
||||
|
||||
**Status:** verified with **development** signing on `debug_arm64` only. Open follow-ups before App Store shipping: secure timestamp (drop `codesign --timestamp=none`), distribution profile (`get-task-allow=false`), `release_arm64` + `altool --validate-app`, and committing a `Package.resolved` for hermetic remote-SwiftPM resolution.
|
||||
|
||||
## View frame ownership
|
||||
|
||||
A view does not control its own `frame`. The parent (or a layout system) sets the frame; the view positions its own subviews against `self.bounds` in response.
|
||||
|
||||
This matters in two places specifically:
|
||||
|
||||
- **Reusable components (`UIView`/`ASDisplayNode` subclasses).** Public methods like `update(...)` / `apply(...)` rebuild internal state, mutate child frames, and read `self.bounds` to lay them out — but they do not write `self.frame`. The caller has already chosen the frame; mutating it from inside the component overrides that choice and fights the parent's next layout pass.
|
||||
- **`asyncLayout`-style content nodes.** The measure pass runs off-main and returns a size; the apply step runs on main and the chat layout system positions the node. A child view that writes `self.frame` from `update()` corrupts the size the parent just measured.
|
||||
|
||||
Rare exceptions: top-level view-controller views integrating with the system's first-responder/inset model. If you find yourself wanting `self.frame = …` from inside a child view, refactor so the parent positions it instead.
|
||||
|
||||
## InstantPage V2 & rich-text messages
|
||||
|
||||
Typed markdown with structure the regular message-entity set can't represent (headings, lists, tables, formulas, nested blockquotes) is sent as a **rich message** — a `RichTextMessageAttribute` carrying an `InstantPage`, drawn by `ChatMessageRichDataBubbleContentNode` via the **InstantPage V2** renderer (with AI-streaming progressive reveal, inline custom emoji, and entity cases). The detailed architecture and non-obvious invariants — streaming reveal, V2 table/text-box layout, custom-emoji & entity round-trips, task-list checkboxes, nested blockquotes, thinking blocks, the markdown send / edit / copy / paste paths, and surfacing rich-message media through the shared-media/gallery/preview pipelines via `Message.effectiveMedia` — live in [`docs/instantpage-richtext.md`](docs/instantpage-richtext.md).
|
||||
|
||||
## Postbox → TelegramEngine refactor (in progress)
|
||||
|
||||
A gradual migration is underway to eliminate direct `import Postbox` from consumer submodules in favor of `TelegramEngine`.
|
||||
|
||||
**Historical record:** Wave-by-wave outcomes, the running tally of Postbox-free modules, the full wave-selection guidance, and the `TelegramEngine.Resources` facade inventory (also authoritatively defined in `submodules/TelegramCore/Sources/TelegramEngine/Resources/TelegramEngineResources.swift`) live in [`docs/superpowers/postbox-refactor-log.md`](docs/superpowers/postbox-refactor-log.md). Read that file when you need wave-specific context, a full worked example of a pattern, or the history of a particular module's migration.
|
||||
|
||||
See the log for per-wave detail; the current wave count and the list of still-open migration opportunities live in the `project_postbox_refactor_next_wave.md` memory file.
|
||||
|
||||
### Rules that apply to every wave
|
||||
|
||||
1. `TelegramCore` does **not** `@_exported import Postbox`. Once a consumer drops `import Postbox`, every remaining Postbox-type reference must use an engine-typealiased equivalent.
|
||||
2. **Never typealias `Postbox`, `Account`, or `MediaBox`.** These umbrella types rename without encapsulating. Narrow utility typealiases (`MemoryBuffer`, `PostboxDecoder`, `PostboxEncoder`, `AdaptedPostboxDecoder`, `MediaResource`, …) remain allowed and expected.
|
||||
3. No new engine wrapper **structs** unless the wave's spec explicitly allows — only typealiases and thin forwarding methods.
|
||||
4. **Discovery first:** before adding any new engine wrapper/typealias, grep `submodules/TelegramCore/Sources/TelegramEngine/` for existing equivalents. Record the search result in the commit message.
|
||||
5. **Abandonment protocol:** if a module can only be refactored by violating rule 2 or by editing a module outside the current wave's list, mark the task Abandoned with a recorded reason. Do NOT substitute a new module mid-wave.
|
||||
6. Full project build per module. No unit tests exist in this project.
|
||||
7. **TelegramCore never imports UIKit/Display.** `TelegramCore` is shared with the Telegram-Mac codebase; its Bazel `deps` and source files must not reference UIKit, Display, or any Apple-UI framework. UIKit-needing helpers (image scaling, rendering, etc.) stay in consumer-side submodules.
|
||||
8. **Never substitute Postbox protocols (`Media`, `Peer`, `Message`) with `Any` / `AnyObject`** in code that previously used them. Type erasure throws away the domain semantics that the next reader expects. Use the matching engine wrapper (`EngineMedia`, `EnginePeer`, `EngineMessage`) — extending it as needed (e.g. add a missing case-init or convenience). If neither typealias nor wrapper covers the use site, restore the original Postbox import + type for now and flag the case for a future facade. Existing `Any`/`AnyObject` parameters predating the refactor are not in scope for this rule.
|
||||
|
||||
### Engine typealias cheat sheet (existing aliases)
|
||||
|
||||
```
|
||||
PeerId → EnginePeer.Id
|
||||
MessageId → EngineMessage.Id
|
||||
MessageIndex → EngineMessage.Index
|
||||
MessageTags → EngineMessage.Tags
|
||||
MessageAttribute → EngineMessage.Attribute
|
||||
MessageFlags → EngineMessage.Flags
|
||||
MessageForwardInfo → EngineMessage.ForwardInfo
|
||||
MediaId → EngineMedia.Id
|
||||
PreferencesEntry → EnginePreferencesEntry
|
||||
TempBox → EngineTempBox
|
||||
PinnedItemId → EngineChatList.PinnedItem.Id
|
||||
MemoryBuffer → EngineMemoryBuffer (added 2026-04)
|
||||
PostboxDecoder → EnginePostboxDecoder (added 2026-04)
|
||||
PostboxEncoder → EnginePostboxEncoder (added 2026-04)
|
||||
AdaptedPostboxDecoder → EngineAdaptedPostboxDecoder (added 2026-04)
|
||||
ItemCollectionId → EngineItemCollectionId (added 2026-04-20)
|
||||
FetchResourceSourceType → EngineFetchResourceSourceType (added 2026-04-20)
|
||||
FetchResourceError → EngineFetchResourceError (added 2026-04-20)
|
||||
StoryId → EngineStoryId (added 2026-05-02)
|
||||
ChatListIndex → EngineChatListIndex (added 2026-05-03)
|
||||
TempBoxFile → EngineTempBoxFile (added 2026-05-03)
|
||||
ItemCollectionItemIndex → EngineItemCollectionItemIndex (added 2026-05-03)
|
||||
ItemCollectionViewEntryIndex → EngineItemCollectionViewEntryIndex (added 2026-05-03)
|
||||
ValueBoxEncryptionParameters → EngineValueBoxEncryptionParameters (added 2026-05-03)
|
||||
MessageAndThreadId → EngineMessageAndThreadId (added 2026-05-03)
|
||||
PeerStoryStats → EnginePeerStoryStats (added 2026-05-03)
|
||||
MessageHistoryAnchorIndex → EngineMessageHistoryAnchorIndex (added 2026-05-03)
|
||||
ChatListTotalUnreadStateCategory → EngineChatListTotalUnreadStateCategory (added 2026-05-03)
|
||||
ChatListTotalUnreadStateStats → EngineChatListTotalUnreadStateStats (added 2026-05-03)
|
||||
PeerSummaryCounterTags → EnginePeerSummaryCounterTags (added 2026-05-03)
|
||||
ChatListTotalUnreadState → EngineChatListTotalUnreadState (added 2026-05-04)
|
||||
ItemCacheEntryId → EngineItemCacheEntryId (added 2026-05-04)
|
||||
HashFunctions → EngineHashFunctions (added 2026-05-04 wave 251)
|
||||
CachedMediaResourceRepresentationResult → EngineCachedMediaResourceRepresentationResult (added 2026-05-04 wave 265)
|
||||
MediaResourceDataFetchResult → EngineMediaResourceDataFetchResult (added 2026-05-04 wave 266)
|
||||
MediaResourceDataFetchError → EngineMediaResourceDataFetchError (added 2026-05-04 wave 266)
|
||||
MediaResourceStatus → EngineMediaResourceStatus (added 2026-05-04 wave 272)
|
||||
```
|
||||
|
||||
**Free-function thin forwarders in TelegramCore** (rule 3 allows):
|
||||
- `engineFileSize(_ path:, useTotalFileAllocatedSize: Bool = false)` — forwards to Postbox's `fileSize(...)` (added 2026-05-04 wave 268)
|
||||
|
||||
**TelegramEngineUnauthorized.resources facade**: `UnauthorizedResources.storeResourceData(id: EngineMediaResource.Id, data:, synchronous:)` — bridges to `account.postbox.mediaBox.storeResourceData` (added 2026-05-04 wave 271)
|
||||
|
||||
For the `MediaResource` Postbox protocol, prefer the TelegramCore subtype `TelegramMediaResource` when the consumer's usage allows (note: `EngineMediaResource` is a wrapper **class**, not a typealias, so it is not interchangeable with the protocol).
|
||||
|
||||
### MediaResource → EngineMediaResource consumer migration
|
||||
|
||||
`EngineMediaResource` is a `final class` in `TelegramCore` wrapping a `MediaResource` value. Unlike the typealiases above it is **not** interchangeable with the protocol, but it does provide wrap/unwrap helpers:
|
||||
|
||||
- `EngineMediaResource(rawResource)` — wrap a raw `MediaResource`.
|
||||
- `engineResource._asResource()` — unwrap to the raw `MediaResource`.
|
||||
- `EngineMediaResource.ResourceData(rawResourceData)` — wrap `MediaResourceData`.
|
||||
- `EngineMediaResource.Id(rawMediaResourceId)` — wrap `MediaResourceId`.
|
||||
|
||||
**Pattern for facade functions:** when a `TelegramEngine.<Area>` method leaks raw `MediaResource` in its public signature, **change the facade signature in place** to `EngineMediaResource` (and change any closure parameter types the same way). Bridge inside the facade body by calling the existing `_internal_*` function with `engineResource._asResource()` / wrapping raw inputs from inner closures with `EngineMediaResource(rawResource)`. Update all call sites in the same commit. The `_internal_*` function stays on raw `MediaResource` — it is the Postbox-facing layer.
|
||||
|
||||
Do **not** add opt-in `EngineMediaResource` overloads alongside raw-`MediaResource` overloads. Duplicate signatures fragment the public API and leave the leak in place forever.
|
||||
|
||||
For consumer modules, prefer `EngineMediaResource` as the type in properties, locals, generic arguments and function parameters when the usage is a pure type reference. Do **not** try to use `EngineMediaResource` where a class must conform to `TelegramMediaResource` (Postbox protocol) or override `isEqual(to: MediaResource)` — those remain `import Postbox`.
|
||||
|
||||
## tgcalls Testbench
|
||||
|
||||
This repo includes a tgcalls testbench (CLI tool, Go/Pion SFU, Docker build) layered on top of the iOS source. All testbench code, build instructions, and architecture docs live inside the tgcalls submodule:
|
||||
|
||||
- `submodules/TgVoipWebrtc/tgcalls/CLAUDE.md` — top-level testbench overview, build/run commands
|
||||
- `submodules/TgVoipWebrtc/tgcalls/tools/cli/CLAUDE.md` — CLI test tool architecture
|
||||
- `submodules/TgVoipWebrtc/tgcalls/tools/go_sfu/CLAUDE.md` — Go SFU internals
|
||||
- `submodules/TgVoipWebrtc/CLAUDE.md` — tgcalls library internals + macOS/Linux build patches
|
||||
|
||||
Build the test binary from this directory with:
|
||||
|
||||
`./build-input/bazel-8.4.2 build //submodules/TgVoipWebrtc/tgcalls/tools/cli:tgcalls_cli`
|
||||
95
MODULE.bazel
95
MODULE.bazel
|
|
@ -1,6 +1,89 @@
|
|||
###############################################################################
|
||||
# Bazel now uses Bzlmod by default to manage external dependencies.
|
||||
# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
|
||||
#
|
||||
# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
|
||||
###############################################################################
|
||||
http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
|
||||
|
||||
bazel_dep(name = "bazel_features", version = "1.33.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.11")
|
||||
bazel_dep(name = "rules_go", version = "0.60.0", repo_name = "io_bazel_rules_go")
|
||||
|
||||
go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.24.2")
|
||||
|
||||
bazel_dep(name = "gazelle", version = "0.43.0", repo_name = "bazel_gazelle")
|
||||
|
||||
go_deps = use_extension("@bazel_gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//submodules/TgVoipWebrtc/tgcalls/tools/go_sfu:go.mod")
|
||||
use_repo(
|
||||
go_deps,
|
||||
"com_github_pion_datachannel",
|
||||
"com_github_pion_dtls_v3",
|
||||
"com_github_pion_ice_v4",
|
||||
"com_github_pion_logging",
|
||||
"com_github_pion_rtcp",
|
||||
"com_github_pion_sctp",
|
||||
"com_github_pion_srtp_v3",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_xcodeproj")
|
||||
local_path_override(
|
||||
module_name = "rules_xcodeproj",
|
||||
path = "./build-system/bazel-rules/rules_xcodeproj",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_apple", repo_name = "build_bazel_rules_apple")
|
||||
local_path_override(
|
||||
module_name = "rules_apple",
|
||||
path = "./build-system/bazel-rules/rules_apple",
|
||||
)
|
||||
|
||||
bazel_dep(name = "rules_swift", repo_name = "build_bazel_rules_swift")
|
||||
local_path_override(
|
||||
module_name = "rules_swift",
|
||||
path = "./build-system/bazel-rules/rules_swift",
|
||||
)
|
||||
|
||||
bazel_dep(name = "apple_support", repo_name = "build_bazel_apple_support")
|
||||
local_path_override(
|
||||
module_name = "apple_support",
|
||||
path = "./build-system/bazel-rules/apple_support",
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "cmake_tar_gz",
|
||||
sha256 = "3be85f5b999e327b1ac7d804cbc9acd767059e9f603c42ec2765f6ab68fbd367",
|
||||
urls = ["https://github.com/Kitware/CMake/releases/download/v4.1.2/cmake-4.1.2-macos-universal.tar.gz"],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "meson_tar_gz",
|
||||
sha256 = "999b65f21c03541cf11365489c1fad22e2418bb0c3d50ca61139f2eec09d5496",
|
||||
urls = ["https://github.com/mesonbuild/meson/releases/download/1.6.0/meson-1.6.0.tar.gz"],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "ninja-mac_zip",
|
||||
sha256 = "89a287444b5b3e98f88a945afa50ce937b8ffd1dcc59c555ad9b1baf855298c9",
|
||||
urls = ["https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-mac.zip"],
|
||||
)
|
||||
|
||||
http_file(
|
||||
name = "flatbuffers_zip",
|
||||
sha256 = "c5cd6a605ff20350c7faa19d8eeb599df6117ea4aabd16ac58a7eb5ba82df4e7",
|
||||
urls = ["https://github.com/google/flatbuffers/archive/refs/tags/v24.12.23.zip"],
|
||||
)
|
||||
|
||||
provisioning_profile_repository = use_extension("@build_bazel_rules_apple//apple:apple.bzl", "provisioning_profile_repository_extension")
|
||||
#provisioning_profile_repository.setup(
|
||||
# fallback_profiles = "//path/to/some:filegroup", # Profiles to use if one isn't found locally
|
||||
#)
|
||||
|
||||
bazel_dep(name = "build_configuration")
|
||||
local_path_override(
|
||||
module_name = "build_configuration",
|
||||
path = "./build-input/configuration-repository",
|
||||
)
|
||||
|
||||
bazel_dep(name = "sourcekit_bazel_bsp", version = "0.7.1")
|
||||
local_path_override(
|
||||
module_name = "sourcekit_bazel_bsp",
|
||||
path = "build-system/bazel-rules/sourcekit-bazel-bsp",
|
||||
)
|
||||
|
|
|
|||
1136
MODULE.bazel.lock
generated
1136
MODULE.bazel.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1 +1 @@
|
|||
9677ed109bd94f16fece4cf5e4ca033f
|
||||
c27f02cf6e413fdc
|
||||
|
|
|
|||
527
Telegram/BUILD
527
Telegram/BUILD
|
|
@ -8,33 +8,37 @@ load("@build_bazel_rules_apple//apple:ios.bzl",
|
|||
"ios_application",
|
||||
"ios_extension",
|
||||
"ios_framework",
|
||||
"ios_unit_test",
|
||||
"ios_ui_test",
|
||||
"ios_ui_test_suite",
|
||||
)
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl",
|
||||
"ios_test_runner",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:resources.bzl",
|
||||
"swift_intent_library",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:watchos.bzl",
|
||||
"watchos_application",
|
||||
"watchos_extension",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl",
|
||||
"swift_library",
|
||||
)
|
||||
|
||||
load(
|
||||
"@rules_xcodeproj//xcodeproj:defs.bzl",
|
||||
"top_level_target",
|
||||
"top_level_targets",
|
||||
"top_level_target",
|
||||
"xcodeproj",
|
||||
"xcode_provisioning_profile",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:apple.bzl", "local_provisioning_profile")
|
||||
|
||||
load("//Telegram:prebuilt_watchos.bzl",
|
||||
"apple_prebuilt_watchos_application",
|
||||
)
|
||||
|
||||
load("//build-system/bazel-utils:plist_fragment.bzl",
|
||||
"plist_fragment",
|
||||
)
|
||||
|
|
@ -48,13 +52,16 @@ load(
|
|||
"telegram_team_id",
|
||||
"telegram_enable_icloud",
|
||||
"telegram_enable_siri",
|
||||
"telegram_enable_watch",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:resources.bzl",
|
||||
"swift_intent_library",
|
||||
)
|
||||
|
||||
load("//build-system/bazel-utils:spm.bzl",
|
||||
"generate_spm",
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "debug",
|
||||
values = {
|
||||
|
|
@ -94,6 +101,19 @@ config_setting(
|
|||
},
|
||||
)
|
||||
|
||||
bool_flag(
|
||||
name = "embedWatchApp",
|
||||
build_setting_default = False,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "embedWatchAppSetting",
|
||||
flag_values = {
|
||||
":embedWatchApp": "True",
|
||||
},
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "projectIncludeReleaseSetting",
|
||||
flag_values = {
|
||||
|
|
@ -140,8 +160,7 @@ genrule(
|
|||
],
|
||||
)
|
||||
|
||||
minimum_os_version = "12.0"
|
||||
minimum_watchos_version="9.0"
|
||||
minimum_os_version = "13.0"
|
||||
|
||||
notificationServiceExtensionVersion = "v1"
|
||||
|
||||
|
|
@ -255,13 +274,6 @@ filegroup(
|
|||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "WatchAppStringResources",
|
||||
srcs = glob([
|
||||
"Telegram-iOS/*.lproj/Localizable.strings",
|
||||
], exclude = ["Telegram-iOS/*.lproj/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "AppIntentVocabularyResources",
|
||||
srcs = glob([
|
||||
|
|
@ -297,13 +309,6 @@ filegroup(
|
|||
], exclude = ["Telegram-iOS/DefaultAppIcon.xcassets/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "BlackAppIcon",
|
||||
srcs = glob([
|
||||
"Telegram-iOS/BlackIcon.xcassets/**/*",
|
||||
], exclude = ["Telegram-iOS/BlackIcon.xcassets/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "DefaultIcon",
|
||||
srcs = glob([
|
||||
|
|
@ -311,13 +316,6 @@ filegroup(
|
|||
]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "AdditionalIcons",
|
||||
srcs = glob([
|
||||
"Telegram-iOS/*.png",
|
||||
]),
|
||||
)
|
||||
|
||||
alternate_icon_folders = [
|
||||
"BlackIcon",
|
||||
"BlackClassicIcon",
|
||||
|
|
@ -333,6 +331,8 @@ alternate_icon_folders = [
|
|||
"PremiumTurbo",
|
||||
]
|
||||
|
||||
composer_icon_folders = ["Telegram"]
|
||||
|
||||
[
|
||||
filegroup(
|
||||
name = "{}".format(name),
|
||||
|
|
@ -342,6 +342,15 @@ alternate_icon_folders = [
|
|||
) for name in alternate_icon_folders
|
||||
]
|
||||
|
||||
[
|
||||
filegroup(
|
||||
name = "{}_icon".format(name),
|
||||
srcs = glob([
|
||||
"Telegram-iOS/{}.icon/**/*".format(name),
|
||||
]),
|
||||
) for name in composer_icon_folders
|
||||
]
|
||||
|
||||
filegroup(
|
||||
name = "LaunchScreen",
|
||||
srcs = glob([
|
||||
|
|
@ -351,6 +360,7 @@ filegroup(
|
|||
|
||||
objc_library(
|
||||
name = "Main",
|
||||
module_name = "Main",
|
||||
srcs = [
|
||||
"Telegram-iOS/main.m"
|
||||
],
|
||||
|
|
@ -358,6 +368,7 @@ objc_library(
|
|||
|
||||
swift_library(
|
||||
name = "Lib",
|
||||
module_name = "Lib",
|
||||
srcs = glob([
|
||||
"Telegram-iOS/Application.swift",
|
||||
]),
|
||||
|
|
@ -391,7 +402,8 @@ plist_fragment(
|
|||
"""
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{buildNumber}</string>
|
||||
"""
|
||||
""",
|
||||
defaults = {"buildNumber": "1"},
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
|
|
@ -493,7 +505,7 @@ icloud_fragment = "" if not telegram_enable_icloud else """
|
|||
<string>iCloud.{telegram_bundle_id}</string>
|
||||
</array>
|
||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
||||
<string>{telegram_team_id}.*</string>
|
||||
<string>{telegram_team_id}.{telegram_bundle_id}</string>
|
||||
<key>com.apple.developer.icloud-container-environment</key>
|
||||
<string>{telegram_icloud_environment}</string>
|
||||
""".format(
|
||||
|
|
@ -508,6 +520,8 @@ associated_domains_fragment = "" if telegram_bundle_id not in official_bundle_id
|
|||
<string>applinks:telegram.me</string>
|
||||
<string>applinks:t.me</string>
|
||||
<string>applinks:*.t.me</string>
|
||||
<string>webcredentials:t.me</string>
|
||||
<string>webcredentials:telegram.org</string>
|
||||
</array>
|
||||
"""
|
||||
|
||||
|
|
@ -539,6 +553,12 @@ official_communication_notifications_fragment = """
|
|||
"""
|
||||
communication_notifications_fragment = official_communication_notifications_fragment if telegram_bundle_id in official_bundle_ids else ""
|
||||
|
||||
official_notification_filtering_fragment = """
|
||||
<key>com.apple.developer.usernotifications.filtering</key>
|
||||
<true/>
|
||||
"""
|
||||
notification_filtering_fragment = official_notification_filtering_fragment if telegram_bundle_id == "ph.telegra.Telegraph" else ""
|
||||
|
||||
store_signin_fragment = """
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
|
|
@ -547,6 +567,12 @@ store_signin_fragment = """
|
|||
"""
|
||||
signin_fragment = store_signin_fragment if telegram_bundle_id in store_bundle_ids else ""
|
||||
|
||||
official_background_gpu_fragment = """
|
||||
<key>com.apple.developer.background-tasks.continued-processing.gpu</key>
|
||||
<true/>
|
||||
"""
|
||||
background_gpu_fragment = official_background_gpu_fragment if telegram_bundle_id == "ph.telegra.Telegraph" else ""
|
||||
|
||||
plist_fragment(
|
||||
name = "TelegramEntitlements",
|
||||
extension = "entitlements",
|
||||
|
|
@ -560,74 +586,29 @@ plist_fragment(
|
|||
unrestricted_voip_fragment,
|
||||
carplay_fragment,
|
||||
communication_notifications_fragment,
|
||||
notification_filtering_fragment,
|
||||
signin_fragment,
|
||||
background_gpu_fragment,
|
||||
])
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "TelegramWatchExtensionResources",
|
||||
srcs = glob([
|
||||
"Watch/Extension/Resources/**/*",
|
||||
], exclude = ["Watch/Extension/Resources/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "TelegramWatchAppResources",
|
||||
srcs = glob([
|
||||
"Watch/Extension/Resources/**/*.png",
|
||||
], exclude = ["Watch/Extension/Resources/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "TelegramWatchAppAssets",
|
||||
srcs = glob([
|
||||
"Watch/App/Assets.xcassets/**/*",
|
||||
], exclude = ["Watch/App/Assets.xcassets/**/.*"]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "TelegramWatchAppInterface",
|
||||
srcs = glob([
|
||||
"Watch/App/Base.lproj/Interface.storyboard",
|
||||
]),
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "TelegramWatchLib",
|
||||
srcs = glob([
|
||||
"Watch/Extension/**/*.m",
|
||||
"Watch/SSignalKit/**/*.m",
|
||||
"Watch/Bridge/**/*.m",
|
||||
"Watch/WatchCommonWatch/**/*.m",
|
||||
"Watch/Extension/**/*.h",
|
||||
"Watch/SSignalKit/**/*.h",
|
||||
"Watch/Bridge/**/*.h",
|
||||
"Watch/WatchCommonWatch/**/*.h",
|
||||
]),
|
||||
copts = [
|
||||
"-DTARGET_OS_WATCH=1",
|
||||
"-ITelegram/Watch",
|
||||
"-ITelegram/Watch/Extension",
|
||||
"-ITelegram/Watch/Bridge",
|
||||
],
|
||||
sdk_frameworks = [
|
||||
"WatchKit",
|
||||
"WatchConnectivity",
|
||||
"ClockKit",
|
||||
"UserNotifications",
|
||||
"CoreLocation",
|
||||
"CoreGraphics",
|
||||
],
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
genrule(
|
||||
name = "VersionInfoPlist",
|
||||
extension = "plist",
|
||||
template =
|
||||
"""
|
||||
srcs = ["//:versions.json"],
|
||||
outs = ["VersionInfoPlist.plist"],
|
||||
cmd = """
|
||||
version=$$(python3 -c "import json; print(json.load(open('$(location //:versions.json)'))['app'])")
|
||||
cat > $@ <<PLIST
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>{telegramVersion}</string>
|
||||
"""
|
||||
<string>$$version</string>
|
||||
</dict>
|
||||
</plist>
|
||||
PLIST
|
||||
""",
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
|
|
@ -652,162 +633,6 @@ plist_fragment(
|
|||
"""
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "WatchExtensionNSExtensionInfoPlist",
|
||||
extension = "plist",
|
||||
template =
|
||||
"""
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>WKAppBundleIdentifier</key>
|
||||
<string>{telegram_bundle_id}.watchkitapp</string>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.watchkit</string>
|
||||
</dict>
|
||||
""".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
)
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "WatchAppCompanionInfoPlist",
|
||||
extension = "plist",
|
||||
template =
|
||||
"""
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
<string>{telegram_bundle_id}</string>
|
||||
""".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
)
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "WatchExtensionInfoPlist",
|
||||
extension = "plist",
|
||||
template =
|
||||
"""
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>{telegram_bundle_id}.watchkitapp.watchkitextension</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Telegram</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>WKExtensionDelegateClassName</key>
|
||||
<string>TGExtensionDelegate</string>
|
||||
""".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
)
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "WatchAppInfoPlist",
|
||||
extension = "plist",
|
||||
template =
|
||||
"""
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>{telegram_bundle_id}.watchkitapp</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Telegram</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>WKWatchKitApp</key>
|
||||
<true/>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
""".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
)
|
||||
)
|
||||
|
||||
watchos_extension(
|
||||
name = "TelegramWatchExtension",
|
||||
bundle_id = "{telegram_bundle_id}.watchkitapp.watchkitextension".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
bundle_name = "TelegramWatchExtension",
|
||||
infoplists = [
|
||||
":WatchExtensionInfoPlist",
|
||||
":VersionInfoPlist",
|
||||
":BuildNumberInfoPlist",
|
||||
":AppNameInfoPlist",
|
||||
":WatchExtensionNSExtensionInfoPlist",
|
||||
],
|
||||
minimum_os_version = minimum_watchos_version,
|
||||
provisioning_profile = select({
|
||||
":disableProvisioningProfilesSetting": None,
|
||||
"//conditions:default": "@build_configuration//provisioning:WatchExtension.mobileprovision",
|
||||
}),
|
||||
resources = [
|
||||
":TelegramWatchExtensionResources",
|
||||
],
|
||||
strings = [
|
||||
":WatchAppStringResources",
|
||||
],
|
||||
deps = [
|
||||
":TelegramWatchLib",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
genrule(
|
||||
name = "StripWatchosStubBinary",
|
||||
cmd_bash =
|
||||
"""
|
||||
echo 'lipo -remove armv7k -remove arm64 -remove arm64e $$1/TelegramWatch.app/_WatchKitStub/WK -output $$1/TelegramWatch.app/_WatchKitStub/WK' > $(location StripWatchosStubBinary.sh)
|
||||
echo '' >> $(location StripWatchosStubBinary.sh)
|
||||
""",
|
||||
outs = [
|
||||
"StripWatchosStubBinary.sh",
|
||||
],
|
||||
executable = True,
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
]
|
||||
)
|
||||
|
||||
watchos_application(
|
||||
name = "TelegramWatchApp",
|
||||
bundle_id = "{telegram_bundle_id}.watchkitapp".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
bundle_name = "TelegramWatch",
|
||||
extension = ":TelegramWatchExtension",
|
||||
infoplists = [
|
||||
":WatchAppInfoPlist",
|
||||
":VersionInfoPlist",
|
||||
":BuildNumberInfoPlist",
|
||||
":AppNameInfoPlist",
|
||||
":WatchAppCompanionInfoPlist",
|
||||
],
|
||||
minimum_os_version = minimum_watchos_version,
|
||||
provisioning_profile = select({
|
||||
":disableProvisioningProfilesSetting": None,
|
||||
"//conditions:default": "@build_configuration//provisioning:WatchApp.mobileprovision",
|
||||
}),
|
||||
ipa_post_processor = ":StripWatchosStubBinary",
|
||||
resources = [
|
||||
":TelegramWatchAppResources",
|
||||
":TelegramWatchAppAssets",
|
||||
],
|
||||
storyboards = [
|
||||
":TelegramWatchAppInterface",
|
||||
],
|
||||
strings = [
|
||||
],
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "MtProtoKitInfoPlist",
|
||||
extension = "plist",
|
||||
|
|
@ -952,29 +777,6 @@ plist_fragment(
|
|||
)
|
||||
)
|
||||
|
||||
ios_framework(
|
||||
name = "TelegramApiFramework",
|
||||
bundle_id = "{telegram_bundle_id}.TelegramApi".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
families = [
|
||||
"iphone",
|
||||
"ipad",
|
||||
],
|
||||
infoplists = [
|
||||
":TelegramApiInfoPlist",
|
||||
":BuildNumberInfoPlist",
|
||||
":VersionInfoPlist",
|
||||
":RequiredDeviceCapabilitiesPlist",
|
||||
],
|
||||
minimum_os_version = minimum_os_version,
|
||||
extension_safe = True,
|
||||
ipa_post_processor = strip_framework,
|
||||
deps = [
|
||||
"//submodules/TelegramApi:TelegramApi",
|
||||
],
|
||||
)
|
||||
|
||||
plist_fragment(
|
||||
name = "TelegramCoreInfoPlist",
|
||||
extension = "plist",
|
||||
|
|
@ -1759,6 +1561,7 @@ plist_fragment(
|
|||
<array>
|
||||
<string>{telegram_bundle_id}.refresh</string>
|
||||
<string>{telegram_bundle_id}.cleanup</string>
|
||||
<string>{telegram_bundle_id}.upload.*</string>
|
||||
</array>
|
||||
<key>CFBundleAllowMixedLocalizations</key>
|
||||
<true/>
|
||||
|
|
@ -1784,6 +1587,8 @@ plist_fragment(
|
|||
<string>here-location</string>
|
||||
<string>yandexmaps</string>
|
||||
<string>yandexnavi</string>
|
||||
<string>yandextaxi</string>
|
||||
<string>yangoride</string>
|
||||
<string>comgooglemaps</string>
|
||||
<string>youtube</string>
|
||||
<string>twitter</string>
|
||||
|
|
@ -1811,6 +1616,8 @@ plist_fragment(
|
|||
<string>ucbrowser</string>
|
||||
<string>dolphin</string>
|
||||
<string>instagram-stories</string>
|
||||
<string>yangomaps</string>
|
||||
<string>vivaldi</string>
|
||||
</array>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
|
|
@ -1848,7 +1655,6 @@ plist_fragment(
|
|||
</array>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>SFCompactRounded-Semibold.otf</string>
|
||||
<string>AremacFS-Regular.otf</string>
|
||||
<string>AremacFS-Semibold.otf</string>
|
||||
</array>
|
||||
|
|
@ -1888,7 +1694,7 @@ plist_fragment(
|
|||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<true/>
|
||||
<key>UIViewEdgeAntialiasing</key>
|
||||
<false/>
|
||||
<key>UIViewGroupOpacity</key>
|
||||
|
|
@ -1938,6 +1744,19 @@ xcode_provisioning_profile(
|
|||
provisioning_profile = ":Telegram_local_profile",
|
||||
)
|
||||
|
||||
apple_prebuilt_watchos_application(
|
||||
name = "TelegramWatchApp",
|
||||
# Watch bundle id tracks the host config ("<host>.watchkitapp"). The rule passes it
|
||||
# to xcodebuild as PRODUCT_BUNDLE_IDENTIFIER (baked + signed); the watch Info.plist
|
||||
# derives WKCompanionAppBundleIdentifier from it via $(PRODUCT_BUNDLE_IDENTIFIER:base),
|
||||
# so the embedded watch app is correct for any host (ph.telegra.Telegraph,
|
||||
# org.telegram.TelegramInternal, ...) with no post-build plist patching.
|
||||
bundle_id = "{telegram_bundle_id}.watchkitapp".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
ios_application(
|
||||
name = "Telegram",
|
||||
bundle_id = "{telegram_bundle_id}".format(
|
||||
|
|
@ -1957,14 +1776,13 @@ ios_application(
|
|||
":RequiredDeviceCapabilitiesPlist",
|
||||
":UrlTypesInfoPlist",
|
||||
],
|
||||
app_icons = [ ":{}_icon".format(name) for name in composer_icon_folders ],
|
||||
alternate_icons = [
|
||||
":{}".format(name) for name in alternate_icon_folders
|
||||
],
|
||||
#ipa_post_processor = ":AddAlternateIcons",
|
||||
resources = [
|
||||
":LaunchScreen",
|
||||
":DefaultAppIcon",
|
||||
#":AdditionalIcons",
|
||||
#":DefaultAppIcon",
|
||||
],
|
||||
frameworks = [
|
||||
":MtProtoKitFramework",
|
||||
|
|
@ -1987,10 +1805,13 @@ ios_application(
|
|||
":BroadcastUploadExtension",
|
||||
],
|
||||
}),
|
||||
# Embed the in-repo tgwatch watch app (Telegram/WatchApp) under Watch/ only when
|
||||
# --//Telegram:embedWatchApp is set (Make.py sets it for device configs when
|
||||
# --embedWatchApp is passed). Off by default, so simulator/dev builds are unaffected.
|
||||
watch_application = select({
|
||||
":disableExtensionsSetting": None,
|
||||
"//conditions:default": None#":TelegramWatchApp",
|
||||
}) if telegram_enable_watch else None,
|
||||
":embedWatchAppSetting": ":TelegramWatchApp",
|
||||
"//conditions:default": None,
|
||||
}),
|
||||
deps = [
|
||||
":Main",
|
||||
":Lib",
|
||||
|
|
@ -2000,16 +1821,13 @@ ios_application(
|
|||
|
||||
xcodeproj(
|
||||
name = "Telegram_xcodeproj",
|
||||
build_mode = "bazel",
|
||||
bazel_path = telegram_bazel_path,
|
||||
project_name = "Telegram",
|
||||
tags = ["manual"],
|
||||
top_level_targets = top_level_targets(
|
||||
labels = [
|
||||
":Telegram",
|
||||
],
|
||||
target_environments = ["device", "simulator"],
|
||||
),
|
||||
top_level_targets = [
|
||||
top_level_target(":Telegram", target_environments = ["device", "simulator"]),
|
||||
":iOSAppUITestSuite",
|
||||
],
|
||||
xcode_configurations = {
|
||||
"Debug": {
|
||||
"//command_line_option:compilation_mode": "dbg",
|
||||
|
|
@ -2021,7 +1839,83 @@ xcodeproj(
|
|||
default_xcode_configuration = "Debug"
|
||||
)
|
||||
|
||||
# Temporary targets used to simplify webrtc build tests
|
||||
filegroup(
|
||||
name = "TestSources",
|
||||
srcs = glob(["Tests/Sources/**/*.swift"]),
|
||||
)
|
||||
|
||||
ios_test_runner(
|
||||
name = "iPhone-17__26.2",
|
||||
device_type = "iPhone 17",
|
||||
os_version = "26.2",
|
||||
)
|
||||
|
||||
|
||||
swift_library(
|
||||
name = "iOSAppUITestSuite.library",
|
||||
testonly = True,
|
||||
srcs = [":TestSources"],
|
||||
module_name = "iOSAppUITestSuite",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
ios_ui_test_suite(
|
||||
name = "iOSAppUITestSuite",
|
||||
bundle_id = "org.telegram.Telegram-iOS-uitests",
|
||||
minimum_os_version = minimum_os_version,
|
||||
runners = [
|
||||
":iPhone-17__26.2",
|
||||
],
|
||||
tags = ["manual"],
|
||||
test_host = "//Telegram",
|
||||
visibility = ["@rules_xcodeproj//xcodeproj:generated"],
|
||||
deps = [":iOSAppUITestSuite.library"],
|
||||
)
|
||||
|
||||
# Temporary targets used to simplify build tests
|
||||
|
||||
ios_application(
|
||||
name = "spm_build_app",
|
||||
bundle_id = "{telegram_bundle_id}".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
families = ["iphone", "ipad"],
|
||||
minimum_os_version = minimum_os_version,
|
||||
provisioning_profile = select({
|
||||
":disableProvisioningProfilesSetting": None,
|
||||
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
||||
}),
|
||||
entitlements = ":TelegramEntitlements.entitlements",
|
||||
infoplists = [
|
||||
":TelegramInfoPlist",
|
||||
":BuildNumberInfoPlist",
|
||||
":VersionInfoPlist",
|
||||
":RequiredDeviceCapabilitiesPlist",
|
||||
":UrlTypesInfoPlist",
|
||||
],
|
||||
deps = [
|
||||
#"//submodules/Display",
|
||||
#"//submodules/TelegramCore",
|
||||
#"//submodules/FFMpegBinding",
|
||||
#"//third-party/webrtc",
|
||||
#"//third-party/webrtc:webrtc_objc",
|
||||
#"//submodules/AsyncDisplayKit",
|
||||
#"//submodules/ObjCRuntimeUtils",
|
||||
#"//submodules/OpusBinding",
|
||||
#"//third-party/boringssl:ssl",
|
||||
#"//third-party/boringssl:crypto",
|
||||
#"//submodules/TelegramVoip",
|
||||
#"//third-party/recaptcha:RecaptchaEnterprise",
|
||||
"//submodules/TelegramUI",
|
||||
],
|
||||
)
|
||||
|
||||
generate_spm(
|
||||
name = "spm_build_root",
|
||||
deps = [
|
||||
":spm_build_app",
|
||||
]
|
||||
)
|
||||
|
||||
ios_application(
|
||||
name = "webrtc_build_test",
|
||||
|
|
@ -2043,7 +1937,8 @@ ios_application(
|
|||
":UrlTypesInfoPlist",
|
||||
],
|
||||
deps = [
|
||||
"//third-party/webrtc:webrtc_lib",
|
||||
"//third-party/webrtc",
|
||||
"//third-party/webrtc:webrtc_objc",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -2070,53 +1965,3 @@ ios_application(
|
|||
"//third-party/libvpx:vpx",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "TelegramCoreBuildTestLib",
|
||||
module_name = "TelegramCoreBuildTestLib",
|
||||
srcs = glob([
|
||||
"Tests/TelegramCoreBuildTest/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
data = [
|
||||
":WidgetAssets",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/BuildConfig:BuildConfig",
|
||||
"//submodules/WidgetItems:WidgetItems_iOS14",
|
||||
"//submodules/WidgetItemsUtils:WidgetItemsUtils",
|
||||
"//submodules/AppLockState:AppLockState",
|
||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||
"//submodules/Postbox:Postbox",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider",
|
||||
"//Telegram:GeneratedSources",
|
||||
],
|
||||
)
|
||||
|
||||
ios_application(
|
||||
name = "TelegramCoreBuildTest",
|
||||
bundle_id = "{telegram_bundle_id}".format(
|
||||
telegram_bundle_id = telegram_bundle_id,
|
||||
),
|
||||
families = ["iphone", "ipad"],
|
||||
minimum_os_version = minimum_os_version,
|
||||
provisioning_profile = select({
|
||||
":disableProvisioningProfilesSetting": None,
|
||||
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
||||
}),
|
||||
entitlements = ":TelegramEntitlements.entitlements",
|
||||
infoplists = [
|
||||
":TelegramInfoPlist",
|
||||
":BuildNumberInfoPlist",
|
||||
":VersionInfoPlist",
|
||||
":RequiredDeviceCapabilitiesPlist",
|
||||
":UrlTypesInfoPlist",
|
||||
],
|
||||
frameworks = [
|
||||
":TelegramCoreFramework",
|
||||
],
|
||||
deps = [":TelegramCoreBuildTestLib"],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import SwiftSignalKit
|
|||
import BuildConfig
|
||||
import BroadcastUploadHelpers
|
||||
import AudioToolbox
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import CoreMedia
|
||||
import AVFoundation
|
||||
|
||||
|
|
@ -163,13 +163,15 @@ private final class EmbeddedBroadcastUploadImpl: BroadcastUploadImpl {
|
|||
enableNoiseSuppression: false,
|
||||
disableAudioInput: true,
|
||||
enableSystemMute: false,
|
||||
preferX264: false,
|
||||
useReferenceImpl: false,
|
||||
prioritizeVP8: false,
|
||||
logPath: "",
|
||||
onMutedSpeechActivityDetected: { _ in },
|
||||
encryptionKey: nil,
|
||||
isConference: false,
|
||||
audioIsActiveByDefault: true,
|
||||
isStream: false,
|
||||
sharedAudioDevice: nil
|
||||
sharedAudioDevice: nil,
|
||||
encryptionContext: nil
|
||||
)
|
||||
self.callContext = callContext
|
||||
self.joinPayloadDisposable = (callContext.joinPayload
|
||||
|
|
@ -330,12 +332,12 @@ private final class EmbeddedBroadcastUploadImpl: BroadcastUploadImpl {
|
|||
|
||||
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||
|
||||
TempBox.initializeShared(basePath: rootPath, processType: "share", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||
EngineTempBox.initializeShared(basePath: rootPath, processType: "share", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||
|
||||
let logsPath = rootPath + "/logs/broadcast-logs"
|
||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
let embeddedBroadcastImplementationTypePath = rootPath + "/broadcast-coordination-type"
|
||||
let embeddedBroadcastImplementationTypePath = rootPath + "/broadcast-coordination-type-v2"
|
||||
|
||||
var useIPCContext = false
|
||||
if let typeData = try? Data(contentsOf: URL(fileURLWithPath: embeddedBroadcastImplementationTypePath)), let type = String(data: typeData, encoding: .utf8) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ swift_library(
|
|||
"//submodules/PersistentStringHash:PersistentStringHash",
|
||||
"//submodules/Utils/RangeSet",
|
||||
"//submodules/Media/ConvertOpusToAAC",
|
||||
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ import AppLockState
|
|||
import NotificationsPresentationData
|
||||
import RangeSet
|
||||
import ConvertOpusToAAC
|
||||
import CoreServices
|
||||
import ImageIO
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
private let queue = Queue()
|
||||
|
||||
|
|
@ -275,13 +278,18 @@ private extension CGSize {
|
|||
}
|
||||
}
|
||||
|
||||
private func convertLottieImage(data: Data) -> UIImage? {
|
||||
private func convertLottieImage(data: Data, size: CGSize, forceSquare: Bool) -> UIImage? {
|
||||
let decompressedData = TGGUnzipData(data, 512 * 1024) ?? data
|
||||
guard let animation = LottieInstance(data: decompressedData, fitzModifier: .none, colorReplacements: nil, cacheKey: "") else {
|
||||
return nil
|
||||
}
|
||||
let size = animation.dimensions.fitted(CGSize(width: 200.0, height: 200.0))
|
||||
let context = DrawingContext(size: size, scale: 1.0, opaque: false, clear: true)
|
||||
let actualSize: CGSize
|
||||
if forceSquare {
|
||||
actualSize = animation.dimensions.fitted(size)
|
||||
} else {
|
||||
actualSize = size
|
||||
}
|
||||
let context = DrawingContext(size: actualSize, scale: 1.0, opaque: false, clear: true)
|
||||
animation.renderFrame(with: 0, into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(context.scaledSize.width), height: Int32(context.scaledSize.height), bytesPerRow: Int32(context.bytesPerRow))
|
||||
return context.generateImage()
|
||||
}
|
||||
|
|
@ -486,9 +494,21 @@ private func peerAvatar(mediaBox: MediaBox, accountPeerId: PeerId, peer: Peer, i
|
|||
|
||||
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
||||
private struct NotificationContent: CustomStringConvertible {
|
||||
struct CustomEmoji {
|
||||
var range: Range<Int>
|
||||
var fileId: Int64
|
||||
|
||||
init(range: Range<Int>, fileId: Int64) {
|
||||
self.range = range
|
||||
self.fileId = fileId
|
||||
}
|
||||
}
|
||||
|
||||
var title: String?
|
||||
var subtitle: String?
|
||||
var body: String?
|
||||
var customEmoji: [CustomEmoji] = []
|
||||
var resolvedEmojiFiles: [Int64: String] = [:]
|
||||
var threadId: String?
|
||||
var sound: String?
|
||||
var badge: Int?
|
||||
|
|
@ -519,6 +539,7 @@ private struct NotificationContent: CustomStringConvertible {
|
|||
string += " senderImage: \(self.senderImage != nil ? "non-empty" : "empty"),\n"
|
||||
string += " isLockedMessage: \(String(describing: self.isLockedMessage)),\n"
|
||||
string += " attachments: \(self.attachments),\n"
|
||||
string += " resolvedEmojiFiles: \(self.resolvedEmojiFiles.count) files,\n"
|
||||
string += "}"
|
||||
return string
|
||||
}
|
||||
|
|
@ -565,11 +586,51 @@ private struct NotificationContent: CustomStringConvertible {
|
|||
content.title = title
|
||||
}
|
||||
}
|
||||
|
||||
if let subtitle = self.subtitle {
|
||||
content.subtitle = subtitle
|
||||
}
|
||||
if let body = self.body {
|
||||
content.body = body
|
||||
if #available(iOS 18.0, *) {
|
||||
if !self.resolvedEmojiFiles.isEmpty {
|
||||
let attributedString = NSMutableAttributedString(string: body)
|
||||
|
||||
let sortedEmoji = self.customEmoji.sorted(by: { $0.range.lowerBound < $1.range.lowerBound })
|
||||
|
||||
for emoji in sortedEmoji.reversed() {
|
||||
if emoji.range.lowerBound < 0 || emoji.range.upperBound > attributedString.length {
|
||||
continue
|
||||
}
|
||||
guard let filePath = self.resolvedEmojiFiles[emoji.fileId] else {
|
||||
continue
|
||||
}
|
||||
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
||||
continue
|
||||
}
|
||||
let image: UIImage
|
||||
if let lottieImage = convertLottieImage(data: fileData, size: CGSize(width: 40.0, height: 40.0), forceSquare: false) {
|
||||
image = lottieImage
|
||||
} else if let webpImage = WebP.convert(fromWebP: fileData) {
|
||||
image = webpImage
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
let emojiRange = NSRange(location: emoji.range.lowerBound, length: emoji.range.upperBound - emoji.range.lowerBound)
|
||||
let substring = attributedString.attributedSubstring(from: emojiRange)
|
||||
|
||||
let glyph = try! Customoji.makeGlyph(from: image, description: substring.string, tileSizes: [40], cropToSquare: false)
|
||||
let imageString = NSAttributedString(adaptiveImageGlyph: glyph, attributes: [:])
|
||||
attributedString.replaceCharacters(in: emojiRange, with: "")
|
||||
attributedString.insert(imageString, at: emojiRange.lowerBound)
|
||||
}
|
||||
content.setValue(attributedString, forKey: "attributedBody")
|
||||
} else {
|
||||
content.body = body
|
||||
}
|
||||
} else {
|
||||
content.body = body
|
||||
}
|
||||
}
|
||||
|
||||
if !content.title.isEmpty || !content.subtitle.isEmpty || !content.body.isEmpty {
|
||||
|
|
@ -925,8 +986,19 @@ private final class NotificationServiceHandler {
|
|||
var peer: EnginePeer?
|
||||
var localContactId: String?
|
||||
}
|
||||
|
||||
struct GroupCallData {
|
||||
var id: Int64
|
||||
var fromId: PeerId
|
||||
var fromTitle: String
|
||||
var memberCount: Int
|
||||
var isVideo: Bool
|
||||
var messageId: Int32
|
||||
var accountId: Int64
|
||||
}
|
||||
|
||||
var callData: CallData?
|
||||
var groupCallData: GroupCallData?
|
||||
|
||||
if let messageIdString = payloadJson["msg_id"] as? String {
|
||||
messageId = Int32(messageIdString)
|
||||
|
|
@ -952,8 +1024,33 @@ private final class NotificationServiceHandler {
|
|||
peerId = PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(encryptionIdValue))
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if let locKey = payloadJson["loc-key"] as? String, locKey == "CONF_CALL_REQUEST" {
|
||||
}
|
||||
#endif
|
||||
|
||||
if let callIdString = payloadJson["call_id"] as? String, let callAccessHashString = payloadJson["call_ah"] as? String, let peerId = peerId, let updates = payloadJson["updates"] as? String {
|
||||
if let peerId, let locKey = payloadJson["loc-key"] as? String, (locKey == "CONF_CALL_REQUEST" || locKey == "CONF_VIDEOCALL_REQUEST"), let callIdString = payloadJson["call_id"] as? String, let messageIdString = payloadJson["msg_id"] as? String {
|
||||
if let callId = Int64(callIdString), let messageId = Int32(messageIdString) {
|
||||
if let fromTitle = payloadJson["call_conference_from"] as? String {
|
||||
let isVideo = locKey == "CONF_VIDEOCALL_REQUEST"
|
||||
var memberCount = 0
|
||||
if let callParticipantsCountString = payloadJson["call_participants_cnt"] as? String, let callParticipantsCount = Int(callParticipantsCountString) {
|
||||
memberCount = callParticipantsCount
|
||||
}
|
||||
|
||||
groupCallData = GroupCallData(
|
||||
id: callId,
|
||||
fromId: peerId,
|
||||
fromTitle: fromTitle,
|
||||
memberCount: memberCount,
|
||||
isVideo: isVideo,
|
||||
messageId: messageId,
|
||||
accountId: recordId.int64
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if let callIdString = payloadJson["call_id"] as? String, let callAccessHashString = payloadJson["call_ah"] as? String, let peerId = peerId, let updates = payloadJson["updates"] as? String {
|
||||
if let callId = Int64(callIdString), let callAccessHash = Int64(callAccessHashString) {
|
||||
var peer: EnginePeer?
|
||||
|
||||
|
|
@ -982,26 +1079,29 @@ private final class NotificationServiceHandler {
|
|||
|
||||
enum Action {
|
||||
case logout
|
||||
case poll(peerId: PeerId, content: NotificationContent, messageId: MessageId?, reportDelivery: Bool)
|
||||
case poll(peerId: PeerId, content: NotificationContent, messageId: MessageId?, reportDelivery: Bool, enableInlineEmoji: Bool)
|
||||
case pollStories(peerId: PeerId, content: NotificationContent, storyId: Int32, isReaction: Bool)
|
||||
case deleteMessage([MessageId])
|
||||
case readReactions([MessageId])
|
||||
case readMessage(MessageId)
|
||||
case readStories(peerId: PeerId, maxId: Int32)
|
||||
case call(CallData)
|
||||
case groupCall(GroupCallData)
|
||||
}
|
||||
|
||||
var action: Action?
|
||||
|
||||
if let callData = callData {
|
||||
action = .call(callData)
|
||||
} else if let groupCallData {
|
||||
action = .groupCall(groupCallData)
|
||||
} else if let locKey = payloadJson["loc-key"] as? String {
|
||||
switch locKey {
|
||||
case "SESSION_REVOKE":
|
||||
action = .logout
|
||||
case "MESSAGE_MUTED":
|
||||
if let peerId = peerId {
|
||||
action = .poll(peerId: peerId, content: NotificationContent(isLockedMessage: nil), messageId: nil, reportDelivery: false)
|
||||
action = .poll(peerId: peerId, content: NotificationContent(isLockedMessage: nil), messageId: nil, reportDelivery: false, enableInlineEmoji: false)
|
||||
}
|
||||
case "MESSAGE_DELETED":
|
||||
if let peerId = peerId {
|
||||
|
|
@ -1122,7 +1222,7 @@ private final class NotificationServiceHandler {
|
|||
|
||||
content.userInfo["peerId"] = "\(peerId.toInt64())"
|
||||
content.userInfo["accountId"] = "\(recordId.int64)"
|
||||
|
||||
|
||||
if let silentString = payloadJson["silent"] as? String {
|
||||
if let silentValue = Int(silentString), silentValue != 0 {
|
||||
content.silent = true
|
||||
|
|
@ -1186,16 +1286,49 @@ private final class NotificationServiceHandler {
|
|||
action = .pollStories(peerId: peerId, content: content, storyId: storyId, isReaction: isReaction)
|
||||
} else {
|
||||
var reportDelivery = false
|
||||
if let reportDeliveryUntilDate = aps["report_delivery_until_date"] as? Int32 {
|
||||
if let reportDeliveryUntilDate = aps["report_delivery_until_date"] as? String, let reportDeliveryUntilDateValue = Int32(reportDeliveryUntilDate) {
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
if reportDeliveryUntilDate > currentTime {
|
||||
if reportDeliveryUntilDateValue > currentTime {
|
||||
reportDelivery = true
|
||||
}
|
||||
}
|
||||
action = .poll(peerId: peerId, content: content, messageId: messageIdValue, reportDelivery: reportDelivery)
|
||||
var enableInlineEmoji = true
|
||||
if let _ = aps["_ddie"] {
|
||||
enableInlineEmoji = false
|
||||
}
|
||||
action = .poll(peerId: peerId, content: content, messageId: messageIdValue, reportDelivery: reportDelivery, enableInlineEmoji: enableInlineEmoji)
|
||||
}
|
||||
|
||||
updateCurrentContent(content)
|
||||
} else if let aps = payloadJson["aps"] as? [String: Any], let url = payloadJson["url"] as? String {
|
||||
var content: NotificationContent = NotificationContent(isLockedMessage: nil)
|
||||
content.userInfo["url"] = url
|
||||
content.userInfo["peerId"] = "777000"
|
||||
content.userInfo["accountId"] = "\(recordId.int64)"
|
||||
if let sound = aps["sound"] as? String {
|
||||
content.sound = sound
|
||||
}
|
||||
if let alert = aps["alert"] as? [String: Any] {
|
||||
if let topicTitleValue = payloadJson["topic_title"] as? String {
|
||||
topicTitle = topicTitleValue
|
||||
if let title = alert["title"] as? String {
|
||||
content.title = "\(topicTitleValue) (\(title))"
|
||||
} else {
|
||||
content.title = topicTitleValue
|
||||
}
|
||||
} else {
|
||||
content.title = alert["title"] as? String
|
||||
}
|
||||
content.subtitle = alert["subtitle"] as? String
|
||||
content.body = alert["body"] as? String
|
||||
} else if let alert = aps["alert"] as? String {
|
||||
content.body = alert
|
||||
} else {
|
||||
content.body = "You have a new message"
|
||||
}
|
||||
updateCurrentContent(content)
|
||||
completed()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1243,6 +1376,51 @@ private final class NotificationServiceHandler {
|
|||
content.body = "Incoming Call"
|
||||
}
|
||||
|
||||
updateCurrentContent(content)
|
||||
completed()
|
||||
}
|
||||
})
|
||||
}
|
||||
case let .groupCall(groupCallData):
|
||||
if let stateManager = strongSelf.stateManager {
|
||||
let content = NotificationContent(isLockedMessage: nil)
|
||||
updateCurrentContent(content)
|
||||
|
||||
let _ = (stateManager.postbox.transaction { transaction -> TelegramUser? in
|
||||
return transaction.getPeer(groupCallData.fromId) as? TelegramUser
|
||||
}).start(next: { fromPeer in
|
||||
var voipPayload: [AnyHashable: Any] = [
|
||||
"group_call_id": "\(groupCallData.id)",
|
||||
"msg_id": "\(groupCallData.messageId)",
|
||||
"video": "\(groupCallData.isVideo ? 1 : 0)",
|
||||
"member_count": "\(groupCallData.memberCount)",
|
||||
"from_id": "\(groupCallData.fromId.id._internalGetInt64Value())",
|
||||
"from_title": groupCallData.fromTitle,
|
||||
"accountId": "\(groupCallData.accountId)"
|
||||
]
|
||||
if let phoneNumber = fromPeer?.phone {
|
||||
voipPayload["phoneNumber"] = phoneNumber
|
||||
}
|
||||
|
||||
if #available(iOS 14.5, *), voiceCallSettings.enableSystemIntegration {
|
||||
Logger.shared.log("NotificationService \(episode)", "Will report voip notification")
|
||||
let content = NotificationContent(isLockedMessage: nil)
|
||||
updateCurrentContent(content)
|
||||
|
||||
CXProvider.reportNewIncomingVoIPPushPayload(voipPayload, completion: { error in
|
||||
Logger.shared.log("NotificationService \(episode)", "Did report voip notification, error: \(String(describing: error))")
|
||||
|
||||
completed()
|
||||
})
|
||||
} else {
|
||||
var content = NotificationContent(isLockedMessage: nil)
|
||||
if let peer = fromPeer {
|
||||
content.title = peer.debugDisplayTitle
|
||||
content.body = incomingCallMessage
|
||||
} else {
|
||||
content.body = "Incoming Call"
|
||||
}
|
||||
|
||||
updateCurrentContent(content)
|
||||
completed()
|
||||
}
|
||||
|
|
@ -1254,7 +1432,7 @@ private final class NotificationServiceHandler {
|
|||
let content = NotificationContent(isLockedMessage: nil)
|
||||
updateCurrentContent(content)
|
||||
completed()
|
||||
case let .poll(peerId, initialContent, messageId, reportDelivery):
|
||||
case let .poll(peerId, initialContent, messageId, reportDelivery, enableInlineEmoji):
|
||||
Logger.shared.log("NotificationService \(episode)", "Will poll")
|
||||
if let stateManager = strongSelf.stateManager {
|
||||
let shouldKeepConnection = stateManager.network.shouldKeepConnection
|
||||
|
|
@ -1273,7 +1451,7 @@ private final class NotificationServiceHandler {
|
|||
let mediaAttachment = mediaAttachment ?? customMedia
|
||||
|
||||
var fetchMediaSignal: Signal<Data?, NoError> = .single(nil)
|
||||
if let mediaAttachment = mediaAttachment {
|
||||
if let mediaAttachment {
|
||||
var contentType: MediaResourceUserContentType = .other
|
||||
var fetchResource: TelegramMultipartFetchableResource?
|
||||
if let image = mediaAttachment as? TelegramMediaImage, let representation = largestImageRepresentation(image.representations), let resource = representation.resource as? TelegramMultipartFetchableResource {
|
||||
|
|
@ -1440,10 +1618,146 @@ private final class NotificationServiceHandler {
|
|||
}
|
||||
|
||||
let wasDisplayed = stateManager.postbox.transaction { transaction -> Bool in
|
||||
var wasDisplayed = false
|
||||
if let messageId {
|
||||
return _internal_getMessageNotificationWasDisplayed(transaction: transaction, id: messageId)
|
||||
} else {
|
||||
return false
|
||||
wasDisplayed = _internal_getMessageNotificationWasDisplayed(transaction: transaction, id: messageId)
|
||||
}
|
||||
|
||||
return wasDisplayed
|
||||
}
|
||||
|
||||
let maxEmojiCount: Int = 10
|
||||
var uniqueEmojiIds: [Int64] = []
|
||||
for emoji in content.customEmoji {
|
||||
if !uniqueEmojiIds.contains(emoji.fileId) {
|
||||
uniqueEmojiIds.append(emoji.fileId)
|
||||
if uniqueEmojiIds.count >= maxEmojiCount {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedEmojiFiles: Signal<[Int64: String], NoError> = _internal_resolveInlineStickers(postbox: stateManager.postbox, network: stateManager.network, fileIds: uniqueEmojiIds)
|
||||
|> mapToSignal { files -> Signal<[Int64: String], NoError> in
|
||||
var fetchSignals: [Signal<(Int64, String?), NoError>] = []
|
||||
|
||||
for (_, file) in files {
|
||||
if let resource = file.resource as? TelegramMultipartFetchableResource {
|
||||
let fetchSignal: Signal<(Int64, String?), NoError>
|
||||
if let path = stateManager.postbox.mediaBox.completedResourcePath(resource) {
|
||||
fetchSignal = .single((file.fileId.id, path))
|
||||
} else {
|
||||
let intervals: Signal<[(Range<Int64>, MediaBoxFetchPriority)], NoError> = .single([(0 ..< Int64.max, MediaBoxFetchPriority.maximum)])
|
||||
let fetchDataSignal: Signal<Data?, NoError> = Signal { subscriber in
|
||||
final class DataValue {
|
||||
var data = Data()
|
||||
var missingRanges = RangeSet<Int64>(0 ..< Int64.max)
|
||||
}
|
||||
|
||||
let collectedData = Atomic<DataValue>(value: DataValue())
|
||||
|
||||
return standaloneMultipartFetch(
|
||||
accountPeerId: stateManager.accountPeerId,
|
||||
postbox: stateManager.postbox,
|
||||
network: stateManager.network,
|
||||
resource: resource,
|
||||
datacenterId: resource.datacenterId,
|
||||
size: nil,
|
||||
intervals: intervals,
|
||||
parameters: MediaResourceFetchParameters(
|
||||
tag: nil,
|
||||
info: resourceFetchInfo(resource: resource),
|
||||
location: messageId.flatMap { messageId in
|
||||
return MediaResourceStorageLocation(
|
||||
peerId: peerId,
|
||||
messageId: messageId
|
||||
)
|
||||
},
|
||||
contentType: .sticker,
|
||||
isRandomAccessAllowed: true
|
||||
),
|
||||
encryptionKey: nil,
|
||||
decryptedSize: nil,
|
||||
continueInBackground: false,
|
||||
useMainConnection: true
|
||||
).start(next: { result in
|
||||
switch result {
|
||||
case let .dataPart(offset, data, dataRange, _):
|
||||
var isCompleted = false
|
||||
let _ = collectedData.modify { current in
|
||||
let current = current
|
||||
|
||||
let fillRange = Int(offset) ..< (Int(offset) + data.count)
|
||||
if current.data.count < fillRange.upperBound {
|
||||
current.data.count = fillRange.upperBound
|
||||
}
|
||||
current.data.withUnsafeMutableBytes { buffer -> Void in
|
||||
let bytes = buffer.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
data.copyBytes(to: bytes.advanced(by: Int(offset)), from: Int(dataRange.lowerBound) ..< Int(dataRange.upperBound))
|
||||
}
|
||||
current.missingRanges.remove(contentsOf: Int64(fillRange.lowerBound) ..< Int64(fillRange.upperBound))
|
||||
|
||||
if current.missingRanges.isEmpty {
|
||||
isCompleted = true
|
||||
}
|
||||
return current
|
||||
}
|
||||
if isCompleted {
|
||||
let data = collectedData.with({ $0.data })
|
||||
subscriber.putNext( data)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
case let .resourceSizeUpdated(size):
|
||||
var isCompleted = false
|
||||
let _ = collectedData.modify { current in
|
||||
let current = current
|
||||
current.missingRanges.remove(contentsOf: size ..< Int64.max)
|
||||
if current.missingRanges.isEmpty {
|
||||
isCompleted = true
|
||||
}
|
||||
return current
|
||||
}
|
||||
if isCompleted {
|
||||
let data = collectedData.with({ $0.data })
|
||||
subscriber.putNext(data)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}, error: { _ in
|
||||
subscriber.putNext(nil)
|
||||
subscriber.putCompletion()
|
||||
}, completed: {
|
||||
let data = collectedData.with({ $0.data })
|
||||
subscriber.putNext(data)
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
fetchSignal = fetchDataSignal |> map { data -> (Int64, String?) in
|
||||
guard let data else {
|
||||
return (file.fileId.id, nil)
|
||||
}
|
||||
stateManager.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
if let path = stateManager.postbox.mediaBox.completedResourcePath(resource) {
|
||||
return (file.fileId.id, path)
|
||||
} else {
|
||||
return (file.fileId.id, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
fetchSignals.append(fetchSignal)
|
||||
}
|
||||
}
|
||||
return combineLatest(fetchSignals)
|
||||
|> map { results -> [Int64: String] in
|
||||
var result: [Int64: String] = [:]
|
||||
for (id, path) in results {
|
||||
if let path {
|
||||
result[id] = path
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1453,9 +1767,11 @@ private final class NotificationServiceHandler {
|
|||
|> timeout(10.0, queue: queue, alternate: .single(nil)),
|
||||
fetchNotificationSoundSignal
|
||||
|> timeout(10.0, queue: queue, alternate: .single(nil)),
|
||||
wasDisplayed
|
||||
wasDisplayed,
|
||||
resolvedEmojiFiles
|
||||
|> timeout(10.0, queue: queue, alternate: .single([:])),
|
||||
)
|
||||
|> deliverOn(queue)).start(next: { mediaData, notificationSoundData, wasDisplayed in
|
||||
|> deliverOn(queue)).start(next: { mediaData, notificationSoundData, wasDisplayed, resolvedEmojiFiles in
|
||||
guard let strongSelf = self, let stateManager = strongSelf.stateManager else {
|
||||
completed()
|
||||
return
|
||||
|
|
@ -1527,7 +1843,7 @@ private final class NotificationServiceHandler {
|
|||
stateManager.postbox.mediaBox.storeResourceData(resource.id, data: mediaData, synchronous: true)
|
||||
}
|
||||
if let storedPath = stateManager.postbox.mediaBox.completedResourcePath(resource) {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: storedPath)), let image = convertLottieImage(data: data) {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: storedPath)), let image = convertLottieImage(data: data, size: CGSize(width: 200.0, height: 200.0), forceSquare: false) {
|
||||
let tempFile = TempBox.shared.tempFile(fileName: "image.png")
|
||||
let _ = try? image.pngData()?.write(to: URL(fileURLWithPath: tempFile.path))
|
||||
if let attachment = try? UNNotificationAttachment(identifier: "image", url: URL(fileURLWithPath: tempFile.path), options: nil) {
|
||||
|
|
@ -1566,6 +1882,8 @@ private final class NotificationServiceHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
content.resolvedEmojiFiles = resolvedEmojiFiles
|
||||
|
||||
Logger.shared.log("NotificationService \(episode)", "Updating content to \(content)")
|
||||
|
||||
|
|
@ -1628,7 +1946,11 @@ private final class NotificationServiceHandler {
|
|||
var content = initialContent
|
||||
|
||||
if let interactionAuthorId = interactionAuthorId {
|
||||
if inAppNotificationSettings.displayNameOnLockscreen, let peer = transaction.getPeer(interactionAuthorId) {
|
||||
if inAppNotificationSettings.displayNameOnLockscreen, var peer = transaction.getPeer(interactionAuthorId) {
|
||||
if let channel = peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = transaction.getPeer(linkedMonoforumId) {
|
||||
peer = mainChannel
|
||||
}
|
||||
|
||||
var foundLocalId: String?
|
||||
transaction.enumerateDeviceContactImportInfoItems({ _, value in
|
||||
if let value = value as? TelegramDeviceContactImportedData {
|
||||
|
|
@ -1678,11 +2000,34 @@ private final class NotificationServiceHandler {
|
|||
|> takeLast
|
||||
|> mapToSignal { content, _ -> Signal<(NotificationContent, Media?), NoError> in
|
||||
return stateManager.postbox.transaction { transaction -> (NotificationContent, Media?) in
|
||||
var content = content
|
||||
|
||||
var parsedMedia: Media?
|
||||
if let messageId, let message = transaction.getMessage(messageId), !message.containsSecretMedia {
|
||||
if let messageId, let message = transaction.getMessage(messageId), !message.containsSecretMedia, !message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute }) {
|
||||
if let media = message.media.first {
|
||||
parsedMedia = media
|
||||
}
|
||||
if enableInlineEmoji, let textEntitiesAttribute = message.textEntitiesAttribute, let author = message.author {
|
||||
let authorTitle = author.debugDisplayTitle
|
||||
var needsPrefix = false
|
||||
if message.id.peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
needsPrefix = true
|
||||
} else if let channel = message.peers[message.id.peerId] as? TelegramChannel {
|
||||
if case .group = channel.info {
|
||||
needsPrefix = true
|
||||
}
|
||||
}
|
||||
let messagePrefix = needsPrefix ? "\(authorTitle): " : ""
|
||||
let messagePrefixLength = (messagePrefix as NSString).length
|
||||
for entity in textEntitiesAttribute.entities {
|
||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||
content.customEmoji.append(NotificationContent.CustomEmoji(range: (entity.range.lowerBound + messagePrefixLength) ..< (entity.range.upperBound + messagePrefixLength), fileId: fileId))
|
||||
}
|
||||
}
|
||||
if !content.customEmoji.isEmpty {
|
||||
content.body = messagePrefix + message.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (content, parsedMedia)
|
||||
|
|
@ -1942,7 +2287,11 @@ private final class NotificationServiceHandler {
|
|||
var content = initialContent
|
||||
|
||||
if let interactionAuthorId = interactionAuthorId {
|
||||
if inAppNotificationSettings.displayNameOnLockscreen, let peer = transaction.getPeer(interactionAuthorId) {
|
||||
if inAppNotificationSettings.displayNameOnLockscreen, var peer = transaction.getPeer(interactionAuthorId) {
|
||||
if let channel = peer as? TelegramChannel, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = transaction.getPeer(linkedMonoforumId) {
|
||||
peer = mainChannel
|
||||
}
|
||||
|
||||
var foundLocalId: String?
|
||||
transaction.enumerateDeviceContactImportInfoItems({ _, value in
|
||||
if let value = value as? TelegramDeviceContactImportedData {
|
||||
|
|
@ -2258,3 +2607,430 @@ final class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias CMJImage = UIImage
|
||||
|
||||
// MARK: - Public Namespace
|
||||
|
||||
/// A lightweight utility for turning ordinary bitmap images into ``NSAdaptiveImageGlyph`` (Apple “Genmoji”) objects.
|
||||
///
|
||||
/// ## Overview
|
||||
/// The public API is minimal — a single call to generate a glyph and helper utilities for
|
||||
/// de/serialising attributed strings.
|
||||
///
|
||||
/// ```swift
|
||||
/// // Synchronous usage
|
||||
/// let glyph = try Customoji.makeGlyph(
|
||||
/// from: image,
|
||||
/// description: "alt text",
|
||||
/// cropToSquare: true
|
||||
/// )
|
||||
/// let attr = NSAttributedString(adaptiveImageGlyph: glyph, attributes: [:])
|
||||
/// ```
|
||||
///
|
||||
/// ## Requirements
|
||||
/// * iOS 18 / macOS 15
|
||||
/// * Swift 5.10+
|
||||
///
|
||||
/// ## Topics
|
||||
/// - Generating glyphs: ``makeGlyph(from:description:identifier:tileSizes:cropToSquare:heicQuality:)``
|
||||
/// - Generating glyphs asynchronously: ``makeGlyphAsync(from:description:identifier:tileSizes:cropToSquare:heicQuality:)``
|
||||
/// - Serialising: ``decompose(_:)`` / ``recompose(plain:ranges:blobs:)``
|
||||
///
|
||||
public struct Customoji {
|
||||
|
||||
// MARK: Library-scoped Errors
|
||||
/// Errors that can be thrown by ``Customoji``.
|
||||
public enum Error: Swift.Error, LocalizedError {
|
||||
/// The input image is not square and ``makeGlyph(from:description:identifier:tileSizes:cropToSquare:heicQuality:)`` was called with `cropToSquare == false`.
|
||||
case nonSquare
|
||||
/// The longest side of the input image exceeds ``maxSide`` pixels (defaults to 4096).
|
||||
case imageTooLarge
|
||||
/// Failed to create an in-memory HEIC container via *Image I/O*.
|
||||
case heicDestinationCreationFailed
|
||||
/// Failed to finalise the HEIC container after writing all tiles.
|
||||
case heicFinalizeFailed
|
||||
/// Internal resize operation failed when generating a tile.
|
||||
case imageScaleFailed
|
||||
/// A `CGImage` representation could not be extracted from the source image.
|
||||
case cgImageUnavailable
|
||||
/// The `tileSizes` parameter was empty, not strictly ascending, contained duplicates, or exceeded the source size.
|
||||
case invalidTileSizes
|
||||
/// No tiles were generated — normally unreachable unless all requested sizes were invalid.
|
||||
case noTilesGenerated
|
||||
/// The current platform is neither UIKit- nor AppKit-based (unlikely in practice).
|
||||
case unsupportedPlatform
|
||||
/// The `heicQuality` parameter was outside the 0.0 … 1.0 range.
|
||||
case invalidHeicQuality
|
||||
/// Cropping or scaling to a square failed.
|
||||
case squareCropFailed
|
||||
|
||||
/// Textual description suitable for presenting to users.
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .nonSquare: return "Input image must be square."
|
||||
case .imageTooLarge:
|
||||
return "Source image is too large to process safely."
|
||||
case .heicDestinationCreationFailed:
|
||||
return
|
||||
"Failed to create an in-memory HEIC destination container."
|
||||
case .heicFinalizeFailed: return "Failed to finalize HEIC encoding."
|
||||
case .imageScaleFailed: return "Failed to rescale CGImage tile."
|
||||
case .cgImageUnavailable:
|
||||
return "Unable to obtain CGImage from the source image."
|
||||
case .invalidTileSizes:
|
||||
return
|
||||
"Tile sizes must be unique, strictly ascending, and not exceed the source size."
|
||||
case .noTilesGenerated:
|
||||
return "No tiles were generated from the source image."
|
||||
case .unsupportedPlatform:
|
||||
return
|
||||
"Unsupported platform when attempting to extract CGImage."
|
||||
case .invalidHeicQuality:
|
||||
return "HEIC quality must be between 0.0 and 1.0."
|
||||
case .squareCropFailed:
|
||||
return "Failed to create a square crop of the input image."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Default tile sizes (in pixels) officially used by Apple for Genmoji.
|
||||
public static let defaultTileSizes = [40, 64, 96, 160, 320]
|
||||
|
||||
/// Maximum allowed side length (in pixels) to guard against excessive memory consumption.
|
||||
private static let maxSide = 4_096
|
||||
|
||||
// MARK: - Synchronous Builder
|
||||
#if swift(>=5.10)
|
||||
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, *)
|
||||
/// Generates an ``NSAdaptiveImageGlyph`` synchronously on the **current** thread.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - image: Source image. Can be rectangular; see `cropToSquare`.
|
||||
/// - description: A human-readable accessibility description (VoiceOver/Narrator).
|
||||
/// - identifier: A globally unique content identifier. Defaults to a fresh UUID.
|
||||
/// - tileSizes: Desired tile sizes, in pixels. Must be strictly ascending. Defaults to ``defaultTileSizes``.
|
||||
/// - cropToSquare: When `true`, the central square area is cropped if the input image is not square.
|
||||
/// - heicQuality: Lossy compression quality between `0.0` and `1.0`. Defaults to `0.8`.
|
||||
/// - Throws: ``Customoji/Error`` if validation or encoding fails.
|
||||
/// - Returns: A fully-formed glyph ready for attribution.
|
||||
static func makeGlyph(
|
||||
from image: CMJImage,
|
||||
description: String,
|
||||
identifier: String = UUID().uuidString,
|
||||
tileSizes: [Int] = defaultTileSizes,
|
||||
cropToSquare: Bool = false,
|
||||
heicQuality: CGFloat = 0.8
|
||||
) throws -> NSAdaptiveImageGlyph {
|
||||
try validatePixelSide(of: image)
|
||||
let cg = try extractCGImage(from: image)
|
||||
|
||||
return try coreMakeGlyph(
|
||||
from: cg,
|
||||
description: description,
|
||||
identifier: identifier,
|
||||
tileSizes: tileSizes,
|
||||
cropToSquare: cropToSquare,
|
||||
heicQuality: heicQuality
|
||||
)
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - AttributedString Utilities
|
||||
#if swift(>=5.10)
|
||||
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, *)
|
||||
/// Breaks an ``NSAttributedString`` that may contain adaptive-image glyphs into three parts.
|
||||
///
|
||||
/// This is handy when you need to **serialise** rich text for network transport or persistent
|
||||
/// storage, because `NSAdaptiveImageGlyph` itself is not `Codable`.
|
||||
///
|
||||
/// ```swift
|
||||
/// let (plain, ranges, blobs) = Customoji.decompose(attrString)
|
||||
/// ```
|
||||
///
|
||||
/// - Returns: A tuple where:
|
||||
/// - plain: UTF-16 plain text.
|
||||
/// - ranges: An array mapping text ranges to glyph identifiers.
|
||||
/// - blobs: A dictionary mapping identifier → raw HEIC data.
|
||||
@inlinable
|
||||
public static func decompose(_ attr: NSAttributedString) -> (
|
||||
plain: String, ranges: [(NSRange, String)], blobs: [String: Data]
|
||||
) {
|
||||
var ranges = [(NSRange, String)]()
|
||||
var blobs = [String: Data]()
|
||||
|
||||
attr.enumerateAttribute(
|
||||
.adaptiveImageGlyph,
|
||||
in: NSRange(location: 0, length: attr.length)
|
||||
) { value, range, _ in
|
||||
guard let g = value as? NSAdaptiveImageGlyph else { return }
|
||||
let id = g.contentIdentifier
|
||||
ranges.append((range, id))
|
||||
blobs[id] = blobs[id] ?? g.imageContent
|
||||
}
|
||||
|
||||
return (attr.string, ranges, blobs)
|
||||
}
|
||||
|
||||
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, *)
|
||||
/// Reassembles an attributed string previously produced by ``decompose(_:)``.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - plain: The plain UTF-16 text.
|
||||
/// - ranges: An array of `(NSRange, identifier)` pairs.
|
||||
/// - blobs: A dictionary of identifier → HEIC data. *Must* contain every identifier referenced by `ranges`.
|
||||
/// - Returns: A fully restored `NSAttributedString` with adaptive-image glyphs reinstated.
|
||||
public static func recompose(
|
||||
plain: String,
|
||||
ranges: [(NSRange, String)],
|
||||
blobs: [String: Data]
|
||||
) -> NSAttributedString {
|
||||
let out = NSMutableAttributedString(string: plain)
|
||||
var cache = [String: NSAdaptiveImageGlyph]()
|
||||
|
||||
ranges.forEach { (range, id) in
|
||||
if cache[id] == nil, let data = blobs[id] {
|
||||
cache[id] = NSAdaptiveImageGlyph(imageContent: data)
|
||||
}
|
||||
if let glyph = cache[id] {
|
||||
out.addAttribute(
|
||||
.adaptiveImageGlyph,
|
||||
value: glyph,
|
||||
range: range
|
||||
)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
#endif
|
||||
|
||||
// MARK: - Helper: Pixel-Side Validation
|
||||
/// Ensures that the image’s **longer edge** does not exceed ``maxSide`` pixels, guarding against
|
||||
/// excessive memory usage during HEIC encoding.
|
||||
private static func validatePixelSide(of image: CMJImage) throws {
|
||||
#if canImport(UIKit)
|
||||
let scale = image.scale == 0 ? 1 : image.scale
|
||||
let px = Int(max(image.size.width, image.size.height) * scale)
|
||||
#elseif canImport(AppKit)
|
||||
let px = Int(
|
||||
max(image.size.width, image.size.height)
|
||||
* CGFloat(NSScreen.main?.backingScaleFactor ?? 1)
|
||||
)
|
||||
#endif
|
||||
guard px <= maxSide else { throw Error.imageTooLarge }
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================
|
||||
// Below this line lies the internal implementation.
|
||||
// Public-facing symbols have already been documented above.
|
||||
// =============================================================
|
||||
|
||||
// MARK: - Core Builder
|
||||
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, *)
|
||||
extension Customoji {
|
||||
@Sendable fileprivate static func coreMakeGlyph(
|
||||
from original: CGImage,
|
||||
description: String,
|
||||
identifier: String,
|
||||
tileSizes: [Int],
|
||||
cropToSquare: Bool,
|
||||
heicQuality: CGFloat
|
||||
) throws -> NSAdaptiveImageGlyph {
|
||||
let cg = try ensureSquare(original, cropIfNeeded: cropToSquare)
|
||||
guard cg.width <= maxSide else { throw Error.imageTooLarge }
|
||||
|
||||
let validSizes = try validatedTileSizes(tileSizes, max: cg.width)
|
||||
let data = try heicData(
|
||||
from: cg,
|
||||
id: identifier,
|
||||
description: description,
|
||||
tileSizes: validSizes,
|
||||
quality: heicQuality
|
||||
)
|
||||
return NSAdaptiveImageGlyph(imageContent: data)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - HEIC Encoder
|
||||
@available(iOS 18.0, macCatalyst 18.0, macOS 15.0, *)
|
||||
extension Customoji {
|
||||
fileprivate static func heicData(
|
||||
from cg: CGImage,
|
||||
id: String,
|
||||
description: String,
|
||||
tileSizes: [Int],
|
||||
quality: CGFloat
|
||||
) throws -> Data {
|
||||
guard (0...1).contains(quality) else { throw Error.invalidHeicQuality }
|
||||
|
||||
let destData = NSMutableData()
|
||||
guard
|
||||
let dest = CGImageDestinationCreateWithData(
|
||||
destData,
|
||||
UTType.heic.identifier as CFString,
|
||||
tileSizes.count,
|
||||
nil
|
||||
)
|
||||
else {
|
||||
throw Error.heicDestinationCreationFailed
|
||||
}
|
||||
|
||||
// Attach Genmoji metadata
|
||||
let meta = CGImageMetadataCreateMutable()
|
||||
CGImageMetadataSetValueWithPath(
|
||||
meta,
|
||||
nil,
|
||||
"tiff:\(kCGImagePropertyTIFFDocumentName)" as CFString,
|
||||
id as CFString
|
||||
)
|
||||
CGImageMetadataSetValueWithPath(
|
||||
meta,
|
||||
nil,
|
||||
"dc:description" as CFString,
|
||||
description as CFString
|
||||
)
|
||||
|
||||
for (idx, side) in tileSizes.enumerated() {
|
||||
if Task.isCancelled { throw CancellationError() }
|
||||
guard let img = cg.scaled(to: side) else {
|
||||
throw Error.imageScaleFailed
|
||||
}
|
||||
let opts =
|
||||
[kCGImageDestinationLossyCompressionQuality: quality]
|
||||
as CFDictionary
|
||||
if idx == 0 {
|
||||
CGImageDestinationAddImageAndMetadata(dest, img, meta, opts)
|
||||
} else {
|
||||
CGImageDestinationAddImage(dest, img, opts)
|
||||
}
|
||||
}
|
||||
|
||||
guard CGImageDestinationFinalize(dest) else {
|
||||
throw Error.heicFinalizeFailed
|
||||
}
|
||||
return destData as Data
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CGImage Helpers
|
||||
extension CGImage {
|
||||
/// Returns a copy whose longer edge equals `side` pixels. *Assumes the input is already square.*
|
||||
fileprivate func scaled(to side: Int) -> CGImage? {
|
||||
guard width != side else { return self }
|
||||
guard let cs = CGColorSpace(name: CGColorSpace.sRGB) else { return nil }
|
||||
|
||||
let hasAlpha: Bool = {
|
||||
switch alphaInfo {
|
||||
case .none, .noneSkipFirst, .noneSkipLast: return false
|
||||
default: return true
|
||||
}
|
||||
}()
|
||||
let bitmapInfo: UInt32 =
|
||||
hasAlpha
|
||||
? CGImageAlphaInfo.premultipliedLast.rawValue
|
||||
: CGImageAlphaInfo.noneSkipLast.rawValue
|
||||
|
||||
guard
|
||||
let ctx = CGContext(
|
||||
data: nil,
|
||||
width: side,
|
||||
height: side,
|
||||
bitsPerComponent: 8,
|
||||
bytesPerRow: 0,
|
||||
space: cs,
|
||||
bitmapInfo: bitmapInfo
|
||||
)
|
||||
else { return nil }
|
||||
|
||||
ctx.interpolationQuality = .high
|
||||
ctx.draw(self, in: CGRect(x: 0, y: 0, width: side, height: side))
|
||||
return ctx.makeImage()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Image Extraction Helpers
|
||||
extension Customoji {
|
||||
fileprivate static func extractCGImage(from image: CMJImage) throws
|
||||
-> CGImage
|
||||
{
|
||||
#if canImport(UIKit)
|
||||
if let cg = (image as UIImage).cgImage { return cg }
|
||||
|
||||
var rendered: CGImage?
|
||||
let work = { rendered = renderCGImage(image) }
|
||||
if Thread.isMainThread {
|
||||
work()
|
||||
} else {
|
||||
DispatchQueue.main.sync(execute: work)
|
||||
}
|
||||
if let cg = rendered { return cg }
|
||||
#elseif canImport(AppKit)
|
||||
var rect = CGRect(origin: .zero, size: image.size)
|
||||
if let cg = (image as NSImage).cgImage(
|
||||
forProposedRect: &rect,
|
||||
context: nil,
|
||||
hints: nil
|
||||
) {
|
||||
return cg
|
||||
}
|
||||
if let tiff = (image as NSImage).tiffRepresentation,
|
||||
let rep = NSBitmapImageRep(data: tiff), let cg = rep.cgImage
|
||||
{
|
||||
return cg
|
||||
}
|
||||
#endif
|
||||
throw Error.cgImageUnavailable
|
||||
}
|
||||
|
||||
#if canImport(UIKit)
|
||||
private static func renderCGImage(_ image: UIImage) -> CGImage? {
|
||||
precondition(Thread.isMainThread, "Must be on main thread")
|
||||
let fmt = UIGraphicsImageRendererFormat()
|
||||
fmt.scale = image.scale == 0 ? 1 : image.scale
|
||||
fmt.opaque = false
|
||||
return UIGraphicsImageRenderer(size: image.size, format: fmt).image
|
||||
{ _ in image.draw(at: .zero) }.cgImage
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Square Enforcement
|
||||
extension Customoji {
|
||||
fileprivate static func ensureSquare(_ cg: CGImage, cropIfNeeded: Bool)
|
||||
throws -> CGImage
|
||||
{
|
||||
guard cg.width == cg.height else {
|
||||
guard cropIfNeeded else { throw Error.nonSquare }
|
||||
|
||||
let side = min(cg.width, cg.height)
|
||||
let rect = CGRect(
|
||||
x: (cg.width - side) / 2,
|
||||
y: (cg.height - side) / 2,
|
||||
width: side,
|
||||
height: side
|
||||
)
|
||||
|
||||
if let cropped = cg.cropping(to: rect) { return cropped }
|
||||
if let scaled = cg.scaled(to: side) { return scaled }
|
||||
throw Error.squareCropFailed
|
||||
}
|
||||
return cg
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tile Size Validation
|
||||
extension Customoji {
|
||||
fileprivate static func validatedTileSizes(_ sizes: [Int], max: Int) throws
|
||||
-> [Int]
|
||||
{
|
||||
guard !sizes.isEmpty else { throw Error.invalidTileSizes }
|
||||
for (prev, curr) in zip(sizes, sizes.dropFirst()) where curr <= prev {
|
||||
throw Error.invalidTileSizes
|
||||
}
|
||||
guard sizes.allSatisfy({ $0 > 0 && $0 <= max }) else {
|
||||
throw Error.invalidTileSizes
|
||||
}
|
||||
return sizes
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import TelegramUI
|
|||
import BuildConfig
|
||||
import ShareExtensionContext
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
@objc(ShareRootController)
|
||||
|
|
@ -56,10 +55,10 @@ class ShareRootController: UIViewController {
|
|||
appGroupPath: appGroupUrl.path,
|
||||
accountManager: accountManager,
|
||||
appLockContext: appLockContext,
|
||||
encryptionParameters: ValueBoxEncryptionParameters(
|
||||
encryptionParameters: EngineValueBoxEncryptionParameters(
|
||||
forceEncryptionIfNoSet: false,
|
||||
key: ValueBoxEncryptionParameters.Key(data: encryptionParameters.0)!,
|
||||
salt: ValueBoxEncryptionParameters.Salt(data: encryptionParameters.1)!
|
||||
key: EngineValueBoxEncryptionParameters.Key(data: encryptionParameters.0)!,
|
||||
salt: EngineValueBoxEncryptionParameters.Salt(data: encryptionParameters.1)!
|
||||
),
|
||||
applicationBindings: applicationBindings,
|
||||
initialPresentationDataAndSettings: InitialPresentationDataAndSettings,
|
||||
|
|
@ -69,6 +68,13 @@ class ShareRootController: UIViewController {
|
|||
}), getExtensionContext: { [weak self] in
|
||||
return self?.extensionContext
|
||||
})
|
||||
|
||||
self.impl?.openUrl = { [weak self] url in
|
||||
guard let self, let url = URL(string: url) else {
|
||||
return
|
||||
}
|
||||
let _ = self.openURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
self.impl?.loadView()
|
||||
|
|
@ -93,4 +99,20 @@ class ShareRootController: UIViewController {
|
|||
super.viewDidLayoutSubviews()
|
||||
self.impl?.viewDidLayoutSubviews(view: self.view, traitCollection: self.traitCollection)
|
||||
}
|
||||
|
||||
@objc func openURL(_ url: URL) -> Bool {
|
||||
var responder: UIResponder? = self
|
||||
while responder != nil {
|
||||
if let application = responder as? UIApplication {
|
||||
if #available(iOS 18.0, *) {
|
||||
application.open(url, options: [:], completionHandler: nil)
|
||||
return true
|
||||
} else {
|
||||
return application.perform(#selector(openURL(_:)), with: url) != nil
|
||||
}
|
||||
}
|
||||
responder = responder?.next
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,16 +96,23 @@ private func matchPhoneNumbers(_ lhs: String, _ rhs: String) -> Bool {
|
|||
func matchingCloudContacts(postbox: Postbox, contacts: [MatchingDeviceContact]) -> Signal<[(String, TelegramUser)], NoError> {
|
||||
return postbox.transaction { transaction -> [(String, TelegramUser)] in
|
||||
var result: [(String, TelegramUser)] = []
|
||||
var matchingIds = Set<EnginePeer.Id>()
|
||||
outer: for peerId in transaction.getContactPeerIds() {
|
||||
if let peer = transaction.getPeer(peerId) as? TelegramUser {
|
||||
for contact in contacts {
|
||||
if let contactPeerId = contact.peerId, contactPeerId == peerId {
|
||||
result.append((contact.stableId, peer))
|
||||
if !matchingIds.contains(peer.id) {
|
||||
matchingIds.insert(peer.id)
|
||||
result.append((contact.stableId, peer))
|
||||
}
|
||||
continue outer
|
||||
} else if let peerPhoneNumber = peer.phone {
|
||||
for contactPhoneNumber in contact.phoneNumbers {
|
||||
if matchPhoneNumbers(contactPhoneNumber, peerPhoneNumber) {
|
||||
result.append((contact.stableId, peer))
|
||||
if !matchingIds.contains(peer.id) {
|
||||
matchingIds.insert(peer.id)
|
||||
result.append((contact.stableId, peer))
|
||||
}
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
|
@ -113,6 +120,15 @@ func matchingCloudContacts(postbox: Postbox, contacts: [MatchingDeviceContact])
|
|||
}
|
||||
}
|
||||
}
|
||||
for contact in contacts {
|
||||
if let peerId = contact.peerId, let peer = transaction.getPeer(peerId) as? TelegramUser {
|
||||
if !matchingIds.contains(peer.id) {
|
||||
matchingIds.insert(peer.id)
|
||||
result.append((contact.stableId, peer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,9 +70,8 @@ class IntentHandler: INExtension {
|
|||
}
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension 10.0, iOS 10.0, *)
|
||||
@objc(IntentHandler)
|
||||
class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartAudioCallIntentHandling, INSearchCallHistoryIntentHandling {
|
||||
class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling, INStartCallIntentHandling, INSearchCallHistoryIntentHandling {
|
||||
private let accountPromise = Promise<Account?>()
|
||||
private let allAccounts = Promise<[(AccountRecordId, PeerId, Bool)]>()
|
||||
|
||||
|
|
@ -234,16 +233,31 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
|||
|
||||
var personResolutionResult: INPersonResolutionResult {
|
||||
switch self {
|
||||
case let .success(person):
|
||||
return .success(with: person)
|
||||
case let .disambiguation(persons):
|
||||
return .disambiguation(with: persons)
|
||||
case .needsValue:
|
||||
return .needsValue()
|
||||
case .noResult:
|
||||
return .unsupported()
|
||||
case .skip:
|
||||
return .notRequired()
|
||||
case let .success(person):
|
||||
return .success(with: person)
|
||||
case let .disambiguation(persons):
|
||||
return .disambiguation(with: persons)
|
||||
case .needsValue:
|
||||
return .needsValue()
|
||||
case .noResult:
|
||||
return .unsupported()
|
||||
case .skip:
|
||||
return .notRequired()
|
||||
}
|
||||
}
|
||||
|
||||
var contactResolutionResult: INStartCallContactResolutionResult {
|
||||
switch self {
|
||||
case let .success(person):
|
||||
return .success(with: person)
|
||||
case let .disambiguation(persons):
|
||||
return .disambiguation(with: persons)
|
||||
case .needsValue:
|
||||
return .needsValue()
|
||||
case .noResult:
|
||||
return .unsupported()
|
||||
case .skip:
|
||||
return .notRequired()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -644,36 +658,34 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
|||
}
|
||||
|
||||
// MARK: - INStartAudioCallIntentHandling
|
||||
|
||||
public func resolveContacts(for intent: INStartAudioCallIntent, with completion: @escaping ([INPersonResolutionResult]) -> Void) {
|
||||
public func resolveContacts(for intent: INStartCallIntent, with completion: @escaping ([INStartCallContactResolutionResult]) -> Void) {
|
||||
if let appGroupUrl = self.appGroupUrl {
|
||||
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
|
||||
completion([INPersonResolutionResult.notRequired()])
|
||||
completion([INStartCallContactResolutionResult.notRequired()])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else {
|
||||
completion([INPersonResolutionResult.notRequired()])
|
||||
completion([INStartCallContactResolutionResult.notRequired()])
|
||||
return
|
||||
}
|
||||
self.resolve(persons: intent.contacts, with: { result in
|
||||
completion(result.map { $0.personResolutionResult })
|
||||
completion(result.map { $0.contactResolutionResult })
|
||||
})
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension 11.0, iOS 11.0, *)
|
||||
public func resolveDestinationType(for intent: INStartAudioCallIntent, with completion: @escaping (INCallDestinationTypeResolutionResult) -> Void) {
|
||||
public func resolveDestinationType(for intent: INStartCallIntent, with completion: @escaping (INCallDestinationTypeResolutionResult) -> Void) {
|
||||
completion(.success(with: .normal))
|
||||
}
|
||||
|
||||
public func handle(intent: INStartAudioCallIntent, completion: @escaping (INStartAudioCallIntentResponse) -> Void) {
|
||||
public func handle(intent: INStartCallIntent, completion: @escaping (INStartCallIntentResponse) -> Void) {
|
||||
if let appGroupUrl = self.appGroupUrl {
|
||||
let rootPath = rootPathForBasePath(appGroupUrl.path)
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) {
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartAudioCallIntent.self))
|
||||
let response = INStartAudioCallIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartCallIntent.self))
|
||||
let response = INStartCallIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
completion(response)
|
||||
return
|
||||
}
|
||||
|
|
@ -699,13 +711,13 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
|||
return .single(peerId)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartAudioCallIntent.self))
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartCallIntent.self))
|
||||
userActivity.userInfo = ["handle": "TGCA\(peerId.toInt64())"]
|
||||
let response = INStartAudioCallIntentResponse(code: .continueInApp, userActivity: userActivity)
|
||||
let response = INStartCallIntentResponse(code: .continueInApp, userActivity: userActivity)
|
||||
completion(response)
|
||||
}, error: { _ in
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartAudioCallIntent.self))
|
||||
let response = INStartAudioCallIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
let userActivity = NSUserActivity(activityType: NSStringFromClass(INStartCallIntent.self))
|
||||
let response = INStartCallIntentResponse(code: .failureRequiringAppLaunch, userActivity: userActivity)
|
||||
completion(response)
|
||||
}))
|
||||
}
|
||||
|
|
@ -803,7 +815,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
|||
|
||||
if let searchTerm = searchTerm {
|
||||
if !searchTerm.isEmpty {
|
||||
for renderedPeer in transaction.searchPeers(query: searchTerm) {
|
||||
for renderedPeer in transaction.searchPeers(query: searchTerm, predicate: nil) {
|
||||
if let peer = renderedPeer.peer, !(peer is TelegramSecretChat), !peer.isDeleted {
|
||||
peers.append(peer)
|
||||
}
|
||||
|
|
@ -976,7 +988,7 @@ private final class WidgetIntentHandler {
|
|||
|
||||
if let searchTerm = searchTerm {
|
||||
if !searchTerm.isEmpty {
|
||||
for renderedPeer in transaction.searchPeers(query: searchTerm) {
|
||||
for renderedPeer in transaction.searchPeers(query: searchTerm, predicate: nil) {
|
||||
if let peer = renderedPeer.peer, !(peer is TelegramSecretChat), !peer.isDeleted {
|
||||
peers.append(peer)
|
||||
}
|
||||
|
|
@ -1309,7 +1321,7 @@ private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId
|
|||
var profileImage: INImage?
|
||||
|
||||
var isForum = false
|
||||
if let peer = peer as? TelegramChannel, peer.flags.contains(.isForum) {
|
||||
if let peer = peer as? TelegramChannel, peer.isForumOrMonoForum {
|
||||
isForum = true
|
||||
}
|
||||
|
||||
|
|
|
|||
BIN
Telegram/Telegram-iOS/Resources/Anvil.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/Anvil.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/Cake.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/Cake.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/Cocoon.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/Cocoon.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/CraftFail.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/CraftFail.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond1.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond2.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/GiftDiamond3.tgs
Normal file
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/HandRestrict.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/HandRestrict.tgs
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 712 B |
Binary file not shown.
|
Before Width: | Height: | Size: 455 B |
Binary file not shown.
|
Before Width: | Height: | Size: 788 B |
Binary file not shown.
7
Telegram/Telegram-iOS/Telegram.icon/Assets/Oval.svg
Normal file
7
Telegram/Telegram-iOS/Telegram.icon/Assets/Oval.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Oval</title>
|
||||
<g id="Oval" stroke="none" fill="none" fill-rule="nonzero">
|
||||
<circle fill="#000000" cx="512" cy="512" r="410.5"></circle>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 364 B |
7
Telegram/Telegram-iOS/Telegram.icon/Assets/Plane.svg
Normal file
7
Telegram/Telegram-iOS/Telegram.icon/Assets/Plane.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Plane</title>
|
||||
<g id="Plane" stroke="none" fill="none" fill-rule="nonzero">
|
||||
<path d="M287.315632,507.666819 C406.984718,455.528898 486.782853,421.15639 526.710034,404.549294 C640.710251,357.13266 664.39852,348.895883 679.838202,348.621 C683.234017,348.56408 690.826804,349.405665 695.745092,353.396516 C699.897998,356.766313 701.040629,361.31843 701.587414,364.513367 C702.1342,367.708304 702.815079,374.986453 702.273832,380.673387 C696.09612,445.583141 669.36526,603.101997 655.766116,675.802034 C650.011808,706.564145 638.681397,716.878524 627.712247,717.887922 C603.873746,720.081578 585.77187,702.133777 562.683116,686.998808 C526.553773,663.315568 506.142993,648.572678 471.073211,625.462211 C430.544009,598.754068 456.817404,584.074808 479.914878,560.08479 C485.959597,553.806488 590.992581,458.270869 593.025497,449.604291 C593.279747,448.520391 593.515704,444.480123 591.115452,442.346714 C588.715199,440.213304 585.172634,440.942847 582.61622,441.52306 C578.99258,442.345492 521.275488,480.49435 409.464943,555.969631 C393.082138,567.219329 378.243103,572.700559 364.947836,572.413323 C350.290871,572.096667 322.096751,564.126052 301.137321,557.312967 C275.429726,548.956441 254.997841,544.538286 256.777,530.34632 C257.703696,522.954266 267.883239,515.394432 287.315632,507.666819 Z" id="Path-3" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
122
Telegram/Telegram-iOS/Telegram.icon/icon.json
Normal file
122
Telegram/Telegram-iOS/Telegram.icon/icon.json
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"fill" : "system-light",
|
||||
"groups" : [
|
||||
{
|
||||
"blend-mode" : "normal",
|
||||
"blur-material" : 1,
|
||||
"layers" : [
|
||||
{
|
||||
"blend-mode-specializations" : [
|
||||
{
|
||||
"value" : "normal"
|
||||
},
|
||||
{
|
||||
"appearance" : "dark",
|
||||
"value" : "normal"
|
||||
}
|
||||
],
|
||||
"fill-specializations" : [
|
||||
{
|
||||
"appearance" : "dark",
|
||||
"value" : "automatic"
|
||||
}
|
||||
],
|
||||
"glass" : true,
|
||||
"image-name" : "Plane.svg",
|
||||
"name" : "Plane",
|
||||
"position-specializations" : [
|
||||
{
|
||||
"idiom" : "watchOS",
|
||||
"value" : {
|
||||
"scale" : 1.35,
|
||||
"translation-in-points" : [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"blend-mode-specializations" : [
|
||||
{
|
||||
"value" : "normal"
|
||||
},
|
||||
{
|
||||
"appearance" : "dark",
|
||||
"value" : "normal"
|
||||
}
|
||||
],
|
||||
"fill-specializations" : [
|
||||
{
|
||||
"value" : {
|
||||
"linear-gradient" : [
|
||||
"display-p3:0.21569,0.68627,0.89020,1.00000",
|
||||
"srgb:0.11373,0.57647,0.82353,1.00000"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"appearance" : "dark",
|
||||
"value" : {
|
||||
"automatic-gradient" : "srgb:0.00000,0.47843,1.00000,1.00000"
|
||||
}
|
||||
}
|
||||
],
|
||||
"glass" : true,
|
||||
"hidden-specializations" : [
|
||||
{
|
||||
"value" : false
|
||||
},
|
||||
{
|
||||
"idiom" : "watchOS",
|
||||
"value" : false
|
||||
}
|
||||
],
|
||||
"image-name" : "Oval.svg",
|
||||
"name" : "Oval",
|
||||
"position-specializations" : [
|
||||
{
|
||||
"idiom" : "watchOS",
|
||||
"value" : {
|
||||
"scale" : 2,
|
||||
"translation-in-points" : [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"lighting" : "combined",
|
||||
"position-specializations" : [
|
||||
{
|
||||
"idiom" : "watchOS",
|
||||
"value" : {
|
||||
"scale" : 1,
|
||||
"translation-in-points" : [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"shadow" : {
|
||||
"kind" : "layer-color",
|
||||
"opacity" : 1
|
||||
},
|
||||
"specular" : true,
|
||||
"translucency" : {
|
||||
"enabled" : false,
|
||||
"value" : 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"supported-platforms" : {
|
||||
"circles" : [
|
||||
"watchOS"
|
||||
],
|
||||
"squares" : "shared"
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
"NSLocationAlwaysAndWhenInUseUsageDescription" = "When you choose to share your Live Location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing.";
|
||||
"NSLocationAlwaysUsageDescription" = "When you choose to share your live location with friends in a chat, Telegram needs background access to your location to keep them updated for the duration of the live sharing. You also need this to send locations from an Apple Watch.";
|
||||
"NSCameraUsageDescription" = "We need this so that you can take and share photos and videos, as well as make video calls.";
|
||||
"NSPhotoLibraryUsageDescription" = "We need this so that you can share photos and videos from your photo library.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "We need this so that you can save photos and videos to your photo library.";
|
||||
"NSPhotoLibraryUsageDescription" = "We need this so that you can share photos and videos from your photo library and save the ones you capture.";
|
||||
"NSPhotoLibraryAddUsageDescription" = "We need this so that you can save photos and videos to your photo library and save the ones you capture.";
|
||||
"NSMicrophoneUsageDescription" = "We need this so that you can record and share voice messages and videos with sound.";
|
||||
"NSSiriUsageDescription" = "You can use Siri to send messages.";
|
||||
"NSFaceIDUsageDescription" = "You can use Face ID to unlock the app.";
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,16 +1,6 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
#import <dlfcn.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/*NSString *basePath = [[NSString stringWithUTF8String:argv[0]] stringByDeletingLastPathComponent];
|
||||
void *Share = dlopen([[basePath stringByAppendingPathComponent:@"PlugIns/Share.appex/Share"] UTF8String], RTLD_LAZY);
|
||||
void *NotificationContent = dlopen([[basePath stringByAppendingPathComponent:@"PlugIns/NotificationContent.appex/NotificationContent"] UTF8String], RTLD_LAZY);
|
||||
sleep(1000);
|
||||
void *NotificationService = dlopen([[basePath stringByAppendingPathComponent:@"PlugIns/NotificationService.appex/NotificationService"] UTF8String], RTLD_LAZY);
|
||||
void *SiriIntents = dlopen([[basePath stringByAppendingPathComponent:@"PlugIns/SiriIntents.appex/SiriIntents"] UTF8String], RTLD_LAZY);
|
||||
void *Widget = dlopen([[basePath stringByAppendingPathComponent:@"PlugIns/Widget.appex/Widget"] UTF8String], RTLD_LAZY);
|
||||
1*/
|
||||
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, @"Application", @"AppDelegate");
|
||||
}
|
||||
|
|
|
|||
92
Telegram/Tests/Sources/UITests.swift
Normal file
92
Telegram/Tests/Sources/UITests.swift
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import XCTest
|
||||
import Foundation
|
||||
|
||||
class UITests: XCTestCase {
|
||||
private var app: XCUIApplication!
|
||||
|
||||
override func setUpWithError() throws {
|
||||
continueAfterFailure = false
|
||||
app = XCUIApplication()
|
||||
app.launchArguments.append("--ui-test")
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
app = nil
|
||||
}
|
||||
|
||||
/// Deletes a test account so the sign-up flow can be exercised again.
|
||||
/// Launches the app with `--delete-test-account` which logs in and deletes the account.
|
||||
private func deleteTestAccount(phone: String) {
|
||||
let cleanupApp = XCUIApplication()
|
||||
cleanupApp.launchArguments += ["--ui-test", "--delete-test-account", phone]
|
||||
cleanupApp.launch()
|
||||
let success = cleanupApp.windows["DeleteAccount.Success"]
|
||||
XCTAssert(success.waitForExistence(timeout: 30), "test account cleanup did not complete in 30s")
|
||||
cleanupApp.terminate()
|
||||
}
|
||||
|
||||
func testLaunch() throws {
|
||||
app.launch()
|
||||
XCTAssert(app.wait(for: .runningForeground, timeout: 10.0))
|
||||
}
|
||||
|
||||
func testSignUp() throws {
|
||||
deleteTestAccount(phone: "9996625296")
|
||||
app.launch()
|
||||
|
||||
// Welcome screen — tap Start Messaging
|
||||
let startButton = app.buttons["Auth.Welcome.StartButton"]
|
||||
XCTAssert(startButton.waitForExistence(timeout: 5.0))
|
||||
startButton.tap()
|
||||
|
||||
// Phone entry screen — enter test phone number
|
||||
let countryCodeField = app.textFields["Auth.PhoneEntry.CountryCodeField"]
|
||||
XCTAssert(countryCodeField.waitForExistence(timeout: 10.0))
|
||||
countryCodeField.tap()
|
||||
for _ in 0..<10 {
|
||||
countryCodeField.typeText(XCUIKeyboardKey.delete.rawValue)
|
||||
}
|
||||
countryCodeField.typeText("999")
|
||||
|
||||
let phoneNumberField = app.textFields["Auth.PhoneEntry.PhoneNumberField"]
|
||||
phoneNumberField.tap()
|
||||
phoneNumberField.typeText("6629999")
|
||||
|
||||
let continueButton = app.buttons["Auth.PhoneEntry.ContinueButton"]
|
||||
XCTAssert(continueButton.waitForExistence(timeout: 3.0))
|
||||
XCTAssert(continueButton.isEnabled)
|
||||
continueButton.tap()
|
||||
|
||||
// Confirmation dialog — tap Continue
|
||||
let confirmButton = app.buttons["Auth.PhoneConfirm.ContinueButton"]
|
||||
XCTAssert(confirmButton.waitForExistence(timeout: 5.0))
|
||||
confirmButton.tap()
|
||||
|
||||
// Code entry screen — enter verification code
|
||||
let codeEntryTitle = app.staticTexts["Auth.CodeEntry.Title"]
|
||||
XCTAssert(codeEntryTitle.waitForExistence(timeout: 15.0))
|
||||
|
||||
let codeField = app.textFields["Auth.CodeEntry.CodeField"]
|
||||
XCTAssert(codeField.waitForExistence(timeout: 3.0))
|
||||
codeField.typeText("22222")
|
||||
|
||||
// Set name screen — enter name and submit
|
||||
let firstNameField = app.textFields["Auth.SetName.FirstNameField"]
|
||||
XCTAssert(firstNameField.waitForExistence(timeout: 15.0))
|
||||
firstNameField.tap()
|
||||
firstNameField.typeText("Test")
|
||||
|
||||
let lastNameField = app.textFields["Auth.SetName.LastNameField"]
|
||||
lastNameField.tap()
|
||||
lastNameField.typeText("User")
|
||||
|
||||
let signUpButton = app.buttons["Auth.SetName.ContinueButton"]
|
||||
XCTAssert(signUpButton.waitForExistence(timeout: 3.0))
|
||||
signUpButton.tap()
|
||||
|
||||
// Wait for post-signup UI to appear
|
||||
sleep(10)
|
||||
let description = app.debugDescription
|
||||
XCTFail("UI DUMP:\n\(description)")
|
||||
}
|
||||
}
|
||||
8
Telegram/WatchApp/.gitignore
vendored
Normal file
8
Telegram/WatchApp/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
**/.build/
|
||||
**/DerivedData/
|
||||
.DS_Store
|
||||
**/xcuserdata/
|
||||
# The repo root .gitignore ignores *.xcodeproj, but this committed snapshot needs its
|
||||
# generated project (the Bazel embed build uses it directly). Re-include the project
|
||||
# directory; xcuserdata inside stays excluded via the rule above.
|
||||
!tgwatch.xcodeproj
|
||||
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_lottie.tgs
Normal file
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_lottie.tgs
Normal file
Binary file not shown.
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_raster.webp
Normal file
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_raster.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_vp9.webm
Normal file
BIN
Telegram/WatchApp/Assets/SampleStickers/sticker_vp9.webm
Normal file
Binary file not shown.
19
Telegram/WatchApp/BUILD
Normal file
19
Telegram/WatchApp/BUILD
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Committed snapshot of the tgwatch watch app (synced from the standalone tgwatch repo
|
||||
# via tools/export-sources.sh). Built by //Telegram:TelegramWatchApp
|
||||
# (apple_prebuilt_watchos_application) via xcodebuild. These files are the rule's tracked
|
||||
# inputs, so the watch build re-runs only when the snapshot changes.
|
||||
filegroup(
|
||||
name = "sources",
|
||||
srcs = glob(
|
||||
["**"],
|
||||
exclude = [
|
||||
"**/.build/**",
|
||||
"**/.swiftpm/**",
|
||||
"**/xcuserdata/**",
|
||||
"**/DerivedData/**",
|
||||
"BUILD",
|
||||
".gitignore",
|
||||
],
|
||||
),
|
||||
visibility = ["//Telegram:__pkg__"],
|
||||
)
|
||||
113
Telegram/WatchApp/Packages/OpusKit/Package.swift
Normal file
113
Telegram/WatchApp/Packages/OpusKit/Package.swift
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// swift-tools-version:5.9
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "OpusKit",
|
||||
platforms: [
|
||||
.watchOS(.v10),
|
||||
.macOS(.v14)
|
||||
],
|
||||
products: [
|
||||
.library(name: "OpusKit", targets: ["OpusKit"]),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "COgg",
|
||||
path: "Sources/COgg",
|
||||
sources: ["libogg/src"],
|
||||
publicHeadersPath: "include",
|
||||
cSettings: [
|
||||
.headerSearchPath("libogg/include"),
|
||||
]
|
||||
),
|
||||
// Vendored: libopus 1.5.2 (https://opus-codec.org).
|
||||
// Exclude list is version-specific — verify on upgrade.
|
||||
// arm_celt_map.c and armcpu.c are intentionally kept; both are fully
|
||||
// wrapped in `#ifdef OPUS_HAVE_RTCD` (never defined here) and compile
|
||||
// to empty TUs. arm_silk_map.c is excluded because it unconditionally
|
||||
// includes main_FIX.h from the (excluded) silk/fixed tree.
|
||||
.target(
|
||||
name: "COpus",
|
||||
path: "Sources/COpus",
|
||||
exclude: [
|
||||
// NEON (ARM) SIMD variants — disabled via -U__ARM_NEON__
|
||||
"libopus/celt/arm/celt_neon_intr.c",
|
||||
"libopus/celt/arm/pitch_neon_intr.c",
|
||||
"libopus/silk/arm/biquad_alt_neon_intr.c",
|
||||
"libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c",
|
||||
"libopus/silk/arm/NSQ_del_dec_neon_intr.c",
|
||||
"libopus/silk/arm/NSQ_neon.c",
|
||||
// ARM dispatcher — unconditionally includes silk/fixed headers (excluded)
|
||||
"libopus/silk/arm/arm_silk_map.c",
|
||||
// (silk/fixed/arm files already covered by the silk/fixed directory exclude below)
|
||||
// ARM .s assembly (GAS/RVCT)
|
||||
"libopus/celt/arm/celt_pitch_xcorr_arm.s",
|
||||
"libopus/celt/arm/celt_pitch_xcorr_arm-gnu.S",
|
||||
// ARM NE10 FFT (external dep) — not used
|
||||
"libopus/celt/arm/celt_mdct_ne10.c",
|
||||
"libopus/celt/arm/celt_fft_ne10.c",
|
||||
// x86 (SSE/AVX) intrinsic variants
|
||||
"libopus/celt/x86/celt_lpc_sse4_1.c",
|
||||
"libopus/celt/x86/pitch_sse.c",
|
||||
"libopus/celt/x86/pitch_sse2.c",
|
||||
"libopus/celt/x86/pitch_sse4_1.c",
|
||||
"libopus/celt/x86/pitch_avx.c",
|
||||
"libopus/celt/x86/vq_sse2.c",
|
||||
"libopus/celt/x86/x86_celt_map.c",
|
||||
"libopus/celt/x86/x86cpu.c",
|
||||
"libopus/silk/x86/NSQ_del_dec_sse4_1.c",
|
||||
"libopus/silk/x86/NSQ_del_dec_avx2.c",
|
||||
"libopus/silk/x86/NSQ_sse4_1.c",
|
||||
"libopus/silk/x86/VAD_sse4_1.c",
|
||||
"libopus/silk/x86/VQ_WMat_EC_sse4_1.c",
|
||||
"libopus/silk/x86/x86_silk_map.c",
|
||||
"libopus/silk/fixed/x86/burg_modified_FIX_sse4_1.c",
|
||||
"libopus/silk/fixed/x86/vector_ops_FIX_sse4_1.c",
|
||||
"libopus/silk/float/x86/inner_product_FLP_avx2.c",
|
||||
// libopus example / test programs
|
||||
"libopus/src/opus_compare.c",
|
||||
"libopus/src/opus_demo.c",
|
||||
"libopus/src/repacketizer_demo.c",
|
||||
"libopus/celt/opus_custom_demo.c",
|
||||
"libopus/celt/tests",
|
||||
"libopus/silk/tests",
|
||||
// Fixed-point silk — we're a float build (FIXED_POINT undefined)
|
||||
"libopus/silk/fixed",
|
||||
],
|
||||
publicHeadersPath: "include",
|
||||
cSettings: [
|
||||
.headerSearchPath("libopus"),
|
||||
.headerSearchPath("libopus/include"),
|
||||
.headerSearchPath("libopus/celt"),
|
||||
.headerSearchPath("libopus/silk"),
|
||||
.headerSearchPath("libopus/silk/float"),
|
||||
.headerSearchPath("libopus/src"),
|
||||
.define("HAVE_CONFIG_H"),
|
||||
.unsafeFlags(["-U__ARM_NEON__", "-U__SSE2__", "-U__SSE4_1__", "-U__AVX2__"]),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "COpusHelpers",
|
||||
dependencies: ["COpus"],
|
||||
path: "Sources/COpusHelpers",
|
||||
publicHeadersPath: "include",
|
||||
cSettings: [
|
||||
.headerSearchPath("../COpus/include"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "OpusKit",
|
||||
dependencies: ["COgg", "COpus", "COpusHelpers"],
|
||||
path: "Sources/OpusKit"
|
||||
),
|
||||
.testTarget(
|
||||
name: "OpusKitTests",
|
||||
dependencies: ["OpusKit"],
|
||||
path: "Tests/OpusKitTests",
|
||||
resources: [
|
||||
.copy("Resources/voice_note.ogg"),
|
||||
]
|
||||
),
|
||||
],
|
||||
cLanguageStandard: .c11
|
||||
)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef COgg_h
|
||||
#define COgg_h
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module COgg {
|
||||
header "ogg/ogg.h"
|
||||
header "ogg/os_types.h"
|
||||
export *
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
#define _OGG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
typedef struct {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
} ogg_iovec_t;
|
||||
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
|
||||
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||
extern int oggpack_writecheck(oggpack_buffer *b);
|
||||
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpack_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||
|
||||
extern void oggpackB_writeinit(oggpack_buffer *b);
|
||||
extern int oggpackB_writecheck(oggpack_buffer *b);
|
||||
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpackB_writealign(oggpack_buffer *b);
|
||||
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpackB_reset(oggpack_buffer *b);
|
||||
extern void oggpackB_writeclear(oggpack_buffer *b);
|
||||
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpackB_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_look1(oggpack_buffer *b);
|
||||
extern void oggpackB_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpackB_adv1(oggpack_buffer *b);
|
||||
extern long oggpackB_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_read1(oggpack_buffer *b);
|
||||
extern long oggpackB_bytes(oggpack_buffer *b);
|
||||
extern long oggpackB_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
|
||||
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
|
||||
int count, long e_o_s, ogg_int64_t granulepos);
|
||||
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
extern int ogg_sync_check(ogg_sync_state *oy);
|
||||
|
||||
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_check(ogg_stream_state *os);
|
||||
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||
|
||||
extern void ogg_page_checksum_set(ogg_page *og);
|
||||
|
||||
extern int ogg_page_version(const ogg_page *og);
|
||||
extern int ogg_page_continued(const ogg_page *og);
|
||||
extern int ogg_page_bos(const ogg_page *og);
|
||||
extern int ogg_page_eos(const ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
|
||||
extern int ogg_page_serialno(const ogg_page *og);
|
||||
extern long ogg_page_pageno(const ogg_page *og);
|
||||
extern int ogg_page_packets(const ogg_page *og);
|
||||
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OGG_H */
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef OGG_OS_TYPES_H
|
||||
#define OGG_OS_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#define _ogg_malloc malloc
|
||||
#define _ogg_calloc calloc
|
||||
#define _ogg_realloc realloc
|
||||
#define _ogg_free free
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: toplevel libogg include
|
||||
|
||||
********************************************************************/
|
||||
#ifndef _OGG_H
|
||||
#define _OGG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
typedef struct {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
} ogg_iovec_t;
|
||||
|
||||
typedef struct {
|
||||
long endbyte;
|
||||
int endbit;
|
||||
|
||||
unsigned char *buffer;
|
||||
unsigned char *ptr;
|
||||
long storage;
|
||||
} oggpack_buffer;
|
||||
|
||||
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *header;
|
||||
long header_len;
|
||||
unsigned char *body;
|
||||
long body_len;
|
||||
} ogg_page;
|
||||
|
||||
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||
Ogg bitstream **********************************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *body_data; /* bytes from packet bodies */
|
||||
long body_storage; /* storage elements allocated */
|
||||
long body_fill; /* elements stored; fill mark */
|
||||
long body_returned; /* elements of fill returned */
|
||||
|
||||
|
||||
int *lacing_vals; /* The values that will go to the segment table */
|
||||
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||
this way, but it is simple coupled to the
|
||||
lacing fifo */
|
||||
long lacing_storage;
|
||||
long lacing_fill;
|
||||
long lacing_packet;
|
||||
long lacing_returned;
|
||||
|
||||
unsigned char header[282]; /* working space for header encode */
|
||||
int header_fill;
|
||||
|
||||
int e_o_s; /* set when we have buffered the last packet in the
|
||||
logical bitstream */
|
||||
int b_o_s; /* set after we've written the initial page
|
||||
of a logical bitstream */
|
||||
long serialno;
|
||||
long pageno;
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
} ogg_stream_state;
|
||||
|
||||
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||
to a single raw Ogg/Vorbis packet *************************************/
|
||||
|
||||
typedef struct {
|
||||
unsigned char *packet;
|
||||
long bytes;
|
||||
long b_o_s;
|
||||
long e_o_s;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
|
||||
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||
knows where there's a hole in the data,
|
||||
but we need coupling so that the codec
|
||||
(which is in a separate abstraction
|
||||
layer) also knows about the gap */
|
||||
} ogg_packet;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
int storage;
|
||||
int fill;
|
||||
int returned;
|
||||
|
||||
int unsynced;
|
||||
int headerbytes;
|
||||
int bodybytes;
|
||||
} ogg_sync_state;
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||
|
||||
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||
extern int oggpack_writecheck(oggpack_buffer *b);
|
||||
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpack_writealign(oggpack_buffer *b);
|
||||
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpack_reset(oggpack_buffer *b);
|
||||
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_look1(oggpack_buffer *b);
|
||||
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpack_adv1(oggpack_buffer *b);
|
||||
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpack_read1(oggpack_buffer *b);
|
||||
extern long oggpack_bytes(oggpack_buffer *b);
|
||||
extern long oggpack_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||
|
||||
extern void oggpackB_writeinit(oggpack_buffer *b);
|
||||
extern int oggpackB_writecheck(oggpack_buffer *b);
|
||||
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
|
||||
extern void oggpackB_writealign(oggpack_buffer *b);
|
||||
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||
extern void oggpackB_reset(oggpack_buffer *b);
|
||||
extern void oggpackB_writeclear(oggpack_buffer *b);
|
||||
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||
extern long oggpackB_look(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_look1(oggpack_buffer *b);
|
||||
extern void oggpackB_adv(oggpack_buffer *b,int bits);
|
||||
extern void oggpackB_adv1(oggpack_buffer *b);
|
||||
extern long oggpackB_read(oggpack_buffer *b,int bits);
|
||||
extern long oggpackB_read1(oggpack_buffer *b);
|
||||
extern long oggpackB_bytes(oggpack_buffer *b);
|
||||
extern long oggpackB_bits(oggpack_buffer *b);
|
||||
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||
|
||||
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
|
||||
int count, long e_o_s, ogg_int64_t granulepos);
|
||||
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||
|
||||
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||
extern int ogg_sync_check(ogg_sync_state *oy);
|
||||
|
||||
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||
|
||||
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||
|
||||
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||
extern int ogg_stream_check(ogg_stream_state *os);
|
||||
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||
|
||||
extern void ogg_page_checksum_set(ogg_page *og);
|
||||
|
||||
extern int ogg_page_version(const ogg_page *og);
|
||||
extern int ogg_page_continued(const ogg_page *og);
|
||||
extern int ogg_page_bos(const ogg_page *og);
|
||||
extern int ogg_page_eos(const ogg_page *og);
|
||||
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
|
||||
extern int ogg_page_serialno(const ogg_page *og);
|
||||
extern long ogg_page_pageno(const ogg_page *og);
|
||||
extern int ogg_page_packets(const ogg_page *og);
|
||||
|
||||
extern void ogg_packet_clear(ogg_packet *op);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OGG_H */
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef OGG_OS_TYPES_H
|
||||
#define OGG_OS_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef uint16_t ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef uint32_t ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
typedef uint64_t ogg_uint64_t;
|
||||
|
||||
#define _ogg_malloc malloc
|
||||
#define _ogg_calloc calloc
|
||||
#define _ogg_realloc realloc
|
||||
#define _ogg_free free
|
||||
|
||||
#endif
|
||||
1087
Telegram/WatchApp/Packages/OpusKit/Sources/COgg/libogg/src/bitwise.c
Normal file
1087
Telegram/WatchApp/Packages/OpusKit/Sources/COgg/libogg/src/bitwise.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,19 @@
|
|||
/* Hand-written config.h for Apple/SPM build (replaces autoconf-generated file). */
|
||||
#ifndef OGG_CONFIG_H
|
||||
#define OGG_CONFIG_H
|
||||
|
||||
/* Standard headers are available on all Apple platforms */
|
||||
#define HAVE_DLFCN_H 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Keep CRC enabled (do not define DISABLE_CRC) */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
static const ogg_uint32_t crc_lookup[8][256]={
|
||||
{0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
|
||||
0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
|
||||
0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
|
||||
0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
|
||||
0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
|
||||
0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
|
||||
0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
|
||||
0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
|
||||
0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
|
||||
0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
|
||||
0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
|
||||
0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
|
||||
0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
|
||||
0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
|
||||
0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
|
||||
0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
|
||||
0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
|
||||
0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
|
||||
0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
|
||||
0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
|
||||
0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
|
||||
0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
|
||||
0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
|
||||
0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
|
||||
0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
|
||||
0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
|
||||
0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
|
||||
0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
|
||||
0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
|
||||
0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
|
||||
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
|
||||
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4},
|
||||
|
||||
{0x00000000,0xd219c1dc,0xa0f29e0f,0x72eb5fd3,0x452421a9,0x973de075,0xe5d6bfa6,0x37cf7e7a,
|
||||
0x8a484352,0x5851828e,0x2abadd5d,0xf8a31c81,0xcf6c62fb,0x1d75a327,0x6f9efcf4,0xbd873d28,
|
||||
0x10519b13,0xc2485acf,0xb0a3051c,0x62bac4c0,0x5575baba,0x876c7b66,0xf58724b5,0x279ee569,
|
||||
0x9a19d841,0x4800199d,0x3aeb464e,0xe8f28792,0xdf3df9e8,0x0d243834,0x7fcf67e7,0xadd6a63b,
|
||||
0x20a33626,0xf2baf7fa,0x8051a829,0x524869f5,0x6587178f,0xb79ed653,0xc5758980,0x176c485c,
|
||||
0xaaeb7574,0x78f2b4a8,0x0a19eb7b,0xd8002aa7,0xefcf54dd,0x3dd69501,0x4f3dcad2,0x9d240b0e,
|
||||
0x30f2ad35,0xe2eb6ce9,0x9000333a,0x4219f2e6,0x75d68c9c,0xa7cf4d40,0xd5241293,0x073dd34f,
|
||||
0xbabaee67,0x68a32fbb,0x1a487068,0xc851b1b4,0xff9ecfce,0x2d870e12,0x5f6c51c1,0x8d75901d,
|
||||
0x41466c4c,0x935fad90,0xe1b4f243,0x33ad339f,0x04624de5,0xd67b8c39,0xa490d3ea,0x76891236,
|
||||
0xcb0e2f1e,0x1917eec2,0x6bfcb111,0xb9e570cd,0x8e2a0eb7,0x5c33cf6b,0x2ed890b8,0xfcc15164,
|
||||
0x5117f75f,0x830e3683,0xf1e56950,0x23fca88c,0x1433d6f6,0xc62a172a,0xb4c148f9,0x66d88925,
|
||||
0xdb5fb40d,0x094675d1,0x7bad2a02,0xa9b4ebde,0x9e7b95a4,0x4c625478,0x3e890bab,0xec90ca77,
|
||||
0x61e55a6a,0xb3fc9bb6,0xc117c465,0x130e05b9,0x24c17bc3,0xf6d8ba1f,0x8433e5cc,0x562a2410,
|
||||
0xebad1938,0x39b4d8e4,0x4b5f8737,0x994646eb,0xae893891,0x7c90f94d,0x0e7ba69e,0xdc626742,
|
||||
0x71b4c179,0xa3ad00a5,0xd1465f76,0x035f9eaa,0x3490e0d0,0xe689210c,0x94627edf,0x467bbf03,
|
||||
0xfbfc822b,0x29e543f7,0x5b0e1c24,0x8917ddf8,0xbed8a382,0x6cc1625e,0x1e2a3d8d,0xcc33fc51,
|
||||
0x828cd898,0x50951944,0x227e4697,0xf067874b,0xc7a8f931,0x15b138ed,0x675a673e,0xb543a6e2,
|
||||
0x08c49bca,0xdadd5a16,0xa83605c5,0x7a2fc419,0x4de0ba63,0x9ff97bbf,0xed12246c,0x3f0be5b0,
|
||||
0x92dd438b,0x40c48257,0x322fdd84,0xe0361c58,0xd7f96222,0x05e0a3fe,0x770bfc2d,0xa5123df1,
|
||||
0x189500d9,0xca8cc105,0xb8679ed6,0x6a7e5f0a,0x5db12170,0x8fa8e0ac,0xfd43bf7f,0x2f5a7ea3,
|
||||
0xa22feebe,0x70362f62,0x02dd70b1,0xd0c4b16d,0xe70bcf17,0x35120ecb,0x47f95118,0x95e090c4,
|
||||
0x2867adec,0xfa7e6c30,0x889533e3,0x5a8cf23f,0x6d438c45,0xbf5a4d99,0xcdb1124a,0x1fa8d396,
|
||||
0xb27e75ad,0x6067b471,0x128ceba2,0xc0952a7e,0xf75a5404,0x254395d8,0x57a8ca0b,0x85b10bd7,
|
||||
0x383636ff,0xea2ff723,0x98c4a8f0,0x4add692c,0x7d121756,0xaf0bd68a,0xdde08959,0x0ff94885,
|
||||
0xc3cab4d4,0x11d37508,0x63382adb,0xb121eb07,0x86ee957d,0x54f754a1,0x261c0b72,0xf405caae,
|
||||
0x4982f786,0x9b9b365a,0xe9706989,0x3b69a855,0x0ca6d62f,0xdebf17f3,0xac544820,0x7e4d89fc,
|
||||
0xd39b2fc7,0x0182ee1b,0x7369b1c8,0xa1707014,0x96bf0e6e,0x44a6cfb2,0x364d9061,0xe45451bd,
|
||||
0x59d36c95,0x8bcaad49,0xf921f29a,0x2b383346,0x1cf74d3c,0xceee8ce0,0xbc05d333,0x6e1c12ef,
|
||||
0xe36982f2,0x3170432e,0x439b1cfd,0x9182dd21,0xa64da35b,0x74546287,0x06bf3d54,0xd4a6fc88,
|
||||
0x6921c1a0,0xbb38007c,0xc9d35faf,0x1bca9e73,0x2c05e009,0xfe1c21d5,0x8cf77e06,0x5eeebfda,
|
||||
0xf33819e1,0x2121d83d,0x53ca87ee,0x81d34632,0xb61c3848,0x6405f994,0x16eea647,0xc4f7679b,
|
||||
0x79705ab3,0xab699b6f,0xd982c4bc,0x0b9b0560,0x3c547b1a,0xee4dbac6,0x9ca6e515,0x4ebf24c9},
|
||||
|
||||
{0x00000000,0x01d8ac87,0x03b1590e,0x0269f589,0x0762b21c,0x06ba1e9b,0x04d3eb12,0x050b4795,
|
||||
0x0ec56438,0x0f1dc8bf,0x0d743d36,0x0cac91b1,0x09a7d624,0x087f7aa3,0x0a168f2a,0x0bce23ad,
|
||||
0x1d8ac870,0x1c5264f7,0x1e3b917e,0x1fe33df9,0x1ae87a6c,0x1b30d6eb,0x19592362,0x18818fe5,
|
||||
0x134fac48,0x129700cf,0x10fef546,0x112659c1,0x142d1e54,0x15f5b2d3,0x179c475a,0x1644ebdd,
|
||||
0x3b1590e0,0x3acd3c67,0x38a4c9ee,0x397c6569,0x3c7722fc,0x3daf8e7b,0x3fc67bf2,0x3e1ed775,
|
||||
0x35d0f4d8,0x3408585f,0x3661add6,0x37b90151,0x32b246c4,0x336aea43,0x31031fca,0x30dbb34d,
|
||||
0x269f5890,0x2747f417,0x252e019e,0x24f6ad19,0x21fdea8c,0x2025460b,0x224cb382,0x23941f05,
|
||||
0x285a3ca8,0x2982902f,0x2beb65a6,0x2a33c921,0x2f388eb4,0x2ee02233,0x2c89d7ba,0x2d517b3d,
|
||||
0x762b21c0,0x77f38d47,0x759a78ce,0x7442d449,0x714993dc,0x70913f5b,0x72f8cad2,0x73206655,
|
||||
0x78ee45f8,0x7936e97f,0x7b5f1cf6,0x7a87b071,0x7f8cf7e4,0x7e545b63,0x7c3daeea,0x7de5026d,
|
||||
0x6ba1e9b0,0x6a794537,0x6810b0be,0x69c81c39,0x6cc35bac,0x6d1bf72b,0x6f7202a2,0x6eaaae25,
|
||||
0x65648d88,0x64bc210f,0x66d5d486,0x670d7801,0x62063f94,0x63de9313,0x61b7669a,0x606fca1d,
|
||||
0x4d3eb120,0x4ce61da7,0x4e8fe82e,0x4f5744a9,0x4a5c033c,0x4b84afbb,0x49ed5a32,0x4835f6b5,
|
||||
0x43fbd518,0x4223799f,0x404a8c16,0x41922091,0x44996704,0x4541cb83,0x47283e0a,0x46f0928d,
|
||||
0x50b47950,0x516cd5d7,0x5305205e,0x52dd8cd9,0x57d6cb4c,0x560e67cb,0x54679242,0x55bf3ec5,
|
||||
0x5e711d68,0x5fa9b1ef,0x5dc04466,0x5c18e8e1,0x5913af74,0x58cb03f3,0x5aa2f67a,0x5b7a5afd,
|
||||
0xec564380,0xed8eef07,0xefe71a8e,0xee3fb609,0xeb34f19c,0xeaec5d1b,0xe885a892,0xe95d0415,
|
||||
0xe29327b8,0xe34b8b3f,0xe1227eb6,0xe0fad231,0xe5f195a4,0xe4293923,0xe640ccaa,0xe798602d,
|
||||
0xf1dc8bf0,0xf0042777,0xf26dd2fe,0xf3b57e79,0xf6be39ec,0xf766956b,0xf50f60e2,0xf4d7cc65,
|
||||
0xff19efc8,0xfec1434f,0xfca8b6c6,0xfd701a41,0xf87b5dd4,0xf9a3f153,0xfbca04da,0xfa12a85d,
|
||||
0xd743d360,0xd69b7fe7,0xd4f28a6e,0xd52a26e9,0xd021617c,0xd1f9cdfb,0xd3903872,0xd24894f5,
|
||||
0xd986b758,0xd85e1bdf,0xda37ee56,0xdbef42d1,0xdee40544,0xdf3ca9c3,0xdd555c4a,0xdc8df0cd,
|
||||
0xcac91b10,0xcb11b797,0xc978421e,0xc8a0ee99,0xcdaba90c,0xcc73058b,0xce1af002,0xcfc25c85,
|
||||
0xc40c7f28,0xc5d4d3af,0xc7bd2626,0xc6658aa1,0xc36ecd34,0xc2b661b3,0xc0df943a,0xc10738bd,
|
||||
0x9a7d6240,0x9ba5cec7,0x99cc3b4e,0x981497c9,0x9d1fd05c,0x9cc77cdb,0x9eae8952,0x9f7625d5,
|
||||
0x94b80678,0x9560aaff,0x97095f76,0x96d1f3f1,0x93dab464,0x920218e3,0x906bed6a,0x91b341ed,
|
||||
0x87f7aa30,0x862f06b7,0x8446f33e,0x859e5fb9,0x8095182c,0x814db4ab,0x83244122,0x82fceda5,
|
||||
0x8932ce08,0x88ea628f,0x8a839706,0x8b5b3b81,0x8e507c14,0x8f88d093,0x8de1251a,0x8c39899d,
|
||||
0xa168f2a0,0xa0b05e27,0xa2d9abae,0xa3010729,0xa60a40bc,0xa7d2ec3b,0xa5bb19b2,0xa463b535,
|
||||
0xafad9698,0xae753a1f,0xac1ccf96,0xadc46311,0xa8cf2484,0xa9178803,0xab7e7d8a,0xaaa6d10d,
|
||||
0xbce23ad0,0xbd3a9657,0xbf5363de,0xbe8bcf59,0xbb8088cc,0xba58244b,0xb831d1c2,0xb9e97d45,
|
||||
0xb2275ee8,0xb3fff26f,0xb19607e6,0xb04eab61,0xb545ecf4,0xb49d4073,0xb6f4b5fa,0xb72c197d},
|
||||
|
||||
{0x00000000,0xdc6d9ab7,0xbc1a28d9,0x6077b26e,0x7cf54c05,0xa098d6b2,0xc0ef64dc,0x1c82fe6b,
|
||||
0xf9ea980a,0x258702bd,0x45f0b0d3,0x999d2a64,0x851fd40f,0x59724eb8,0x3905fcd6,0xe5686661,
|
||||
0xf7142da3,0x2b79b714,0x4b0e057a,0x97639fcd,0x8be161a6,0x578cfb11,0x37fb497f,0xeb96d3c8,
|
||||
0x0efeb5a9,0xd2932f1e,0xb2e49d70,0x6e8907c7,0x720bf9ac,0xae66631b,0xce11d175,0x127c4bc2,
|
||||
0xeae946f1,0x3684dc46,0x56f36e28,0x8a9ef49f,0x961c0af4,0x4a719043,0x2a06222d,0xf66bb89a,
|
||||
0x1303defb,0xcf6e444c,0xaf19f622,0x73746c95,0x6ff692fe,0xb39b0849,0xd3ecba27,0x0f812090,
|
||||
0x1dfd6b52,0xc190f1e5,0xa1e7438b,0x7d8ad93c,0x61082757,0xbd65bde0,0xdd120f8e,0x017f9539,
|
||||
0xe417f358,0x387a69ef,0x580ddb81,0x84604136,0x98e2bf5d,0x448f25ea,0x24f89784,0xf8950d33,
|
||||
0xd1139055,0x0d7e0ae2,0x6d09b88c,0xb164223b,0xade6dc50,0x718b46e7,0x11fcf489,0xcd916e3e,
|
||||
0x28f9085f,0xf49492e8,0x94e32086,0x488eba31,0x540c445a,0x8861deed,0xe8166c83,0x347bf634,
|
||||
0x2607bdf6,0xfa6a2741,0x9a1d952f,0x46700f98,0x5af2f1f3,0x869f6b44,0xe6e8d92a,0x3a85439d,
|
||||
0xdfed25fc,0x0380bf4b,0x63f70d25,0xbf9a9792,0xa31869f9,0x7f75f34e,0x1f024120,0xc36fdb97,
|
||||
0x3bfad6a4,0xe7974c13,0x87e0fe7d,0x5b8d64ca,0x470f9aa1,0x9b620016,0xfb15b278,0x277828cf,
|
||||
0xc2104eae,0x1e7dd419,0x7e0a6677,0xa267fcc0,0xbee502ab,0x6288981c,0x02ff2a72,0xde92b0c5,
|
||||
0xcceefb07,0x108361b0,0x70f4d3de,0xac994969,0xb01bb702,0x6c762db5,0x0c019fdb,0xd06c056c,
|
||||
0x3504630d,0xe969f9ba,0x891e4bd4,0x5573d163,0x49f12f08,0x959cb5bf,0xf5eb07d1,0x29869d66,
|
||||
0xa6e63d1d,0x7a8ba7aa,0x1afc15c4,0xc6918f73,0xda137118,0x067eebaf,0x660959c1,0xba64c376,
|
||||
0x5f0ca517,0x83613fa0,0xe3168dce,0x3f7b1779,0x23f9e912,0xff9473a5,0x9fe3c1cb,0x438e5b7c,
|
||||
0x51f210be,0x8d9f8a09,0xede83867,0x3185a2d0,0x2d075cbb,0xf16ac60c,0x911d7462,0x4d70eed5,
|
||||
0xa81888b4,0x74751203,0x1402a06d,0xc86f3ada,0xd4edc4b1,0x08805e06,0x68f7ec68,0xb49a76df,
|
||||
0x4c0f7bec,0x9062e15b,0xf0155335,0x2c78c982,0x30fa37e9,0xec97ad5e,0x8ce01f30,0x508d8587,
|
||||
0xb5e5e3e6,0x69887951,0x09ffcb3f,0xd5925188,0xc910afe3,0x157d3554,0x750a873a,0xa9671d8d,
|
||||
0xbb1b564f,0x6776ccf8,0x07017e96,0xdb6ce421,0xc7ee1a4a,0x1b8380fd,0x7bf43293,0xa799a824,
|
||||
0x42f1ce45,0x9e9c54f2,0xfeebe69c,0x22867c2b,0x3e048240,0xe26918f7,0x821eaa99,0x5e73302e,
|
||||
0x77f5ad48,0xab9837ff,0xcbef8591,0x17821f26,0x0b00e14d,0xd76d7bfa,0xb71ac994,0x6b775323,
|
||||
0x8e1f3542,0x5272aff5,0x32051d9b,0xee68872c,0xf2ea7947,0x2e87e3f0,0x4ef0519e,0x929dcb29,
|
||||
0x80e180eb,0x5c8c1a5c,0x3cfba832,0xe0963285,0xfc14ccee,0x20795659,0x400ee437,0x9c637e80,
|
||||
0x790b18e1,0xa5668256,0xc5113038,0x197caa8f,0x05fe54e4,0xd993ce53,0xb9e47c3d,0x6589e68a,
|
||||
0x9d1cebb9,0x4171710e,0x2106c360,0xfd6b59d7,0xe1e9a7bc,0x3d843d0b,0x5df38f65,0x819e15d2,
|
||||
0x64f673b3,0xb89be904,0xd8ec5b6a,0x0481c1dd,0x18033fb6,0xc46ea501,0xa419176f,0x78748dd8,
|
||||
0x6a08c61a,0xb6655cad,0xd612eec3,0x0a7f7474,0x16fd8a1f,0xca9010a8,0xaae7a2c6,0x768a3871,
|
||||
0x93e25e10,0x4f8fc4a7,0x2ff876c9,0xf395ec7e,0xef171215,0x337a88a2,0x530d3acc,0x8f60a07b},
|
||||
|
||||
{0x00000000,0x490d678d,0x921acf1a,0xdb17a897,0x20f48383,0x69f9e40e,0xb2ee4c99,0xfbe32b14,
|
||||
0x41e90706,0x08e4608b,0xd3f3c81c,0x9afeaf91,0x611d8485,0x2810e308,0xf3074b9f,0xba0a2c12,
|
||||
0x83d20e0c,0xcadf6981,0x11c8c116,0x58c5a69b,0xa3268d8f,0xea2bea02,0x313c4295,0x78312518,
|
||||
0xc23b090a,0x8b366e87,0x5021c610,0x192ca19d,0xe2cf8a89,0xabc2ed04,0x70d54593,0x39d8221e,
|
||||
0x036501af,0x4a686622,0x917fceb5,0xd872a938,0x2391822c,0x6a9ce5a1,0xb18b4d36,0xf8862abb,
|
||||
0x428c06a9,0x0b816124,0xd096c9b3,0x999bae3e,0x6278852a,0x2b75e2a7,0xf0624a30,0xb96f2dbd,
|
||||
0x80b70fa3,0xc9ba682e,0x12adc0b9,0x5ba0a734,0xa0438c20,0xe94eebad,0x3259433a,0x7b5424b7,
|
||||
0xc15e08a5,0x88536f28,0x5344c7bf,0x1a49a032,0xe1aa8b26,0xa8a7ecab,0x73b0443c,0x3abd23b1,
|
||||
0x06ca035e,0x4fc764d3,0x94d0cc44,0xddddabc9,0x263e80dd,0x6f33e750,0xb4244fc7,0xfd29284a,
|
||||
0x47230458,0x0e2e63d5,0xd539cb42,0x9c34accf,0x67d787db,0x2edae056,0xf5cd48c1,0xbcc02f4c,
|
||||
0x85180d52,0xcc156adf,0x1702c248,0x5e0fa5c5,0xa5ec8ed1,0xece1e95c,0x37f641cb,0x7efb2646,
|
||||
0xc4f10a54,0x8dfc6dd9,0x56ebc54e,0x1fe6a2c3,0xe40589d7,0xad08ee5a,0x761f46cd,0x3f122140,
|
||||
0x05af02f1,0x4ca2657c,0x97b5cdeb,0xdeb8aa66,0x255b8172,0x6c56e6ff,0xb7414e68,0xfe4c29e5,
|
||||
0x444605f7,0x0d4b627a,0xd65ccaed,0x9f51ad60,0x64b28674,0x2dbfe1f9,0xf6a8496e,0xbfa52ee3,
|
||||
0x867d0cfd,0xcf706b70,0x1467c3e7,0x5d6aa46a,0xa6898f7e,0xef84e8f3,0x34934064,0x7d9e27e9,
|
||||
0xc7940bfb,0x8e996c76,0x558ec4e1,0x1c83a36c,0xe7608878,0xae6deff5,0x757a4762,0x3c7720ef,
|
||||
0x0d9406bc,0x44996131,0x9f8ec9a6,0xd683ae2b,0x2d60853f,0x646de2b2,0xbf7a4a25,0xf6772da8,
|
||||
0x4c7d01ba,0x05706637,0xde67cea0,0x976aa92d,0x6c898239,0x2584e5b4,0xfe934d23,0xb79e2aae,
|
||||
0x8e4608b0,0xc74b6f3d,0x1c5cc7aa,0x5551a027,0xaeb28b33,0xe7bfecbe,0x3ca84429,0x75a523a4,
|
||||
0xcfaf0fb6,0x86a2683b,0x5db5c0ac,0x14b8a721,0xef5b8c35,0xa656ebb8,0x7d41432f,0x344c24a2,
|
||||
0x0ef10713,0x47fc609e,0x9cebc809,0xd5e6af84,0x2e058490,0x6708e31d,0xbc1f4b8a,0xf5122c07,
|
||||
0x4f180015,0x06156798,0xdd02cf0f,0x940fa882,0x6fec8396,0x26e1e41b,0xfdf64c8c,0xb4fb2b01,
|
||||
0x8d23091f,0xc42e6e92,0x1f39c605,0x5634a188,0xadd78a9c,0xe4daed11,0x3fcd4586,0x76c0220b,
|
||||
0xccca0e19,0x85c76994,0x5ed0c103,0x17dda68e,0xec3e8d9a,0xa533ea17,0x7e244280,0x3729250d,
|
||||
0x0b5e05e2,0x4253626f,0x9944caf8,0xd049ad75,0x2baa8661,0x62a7e1ec,0xb9b0497b,0xf0bd2ef6,
|
||||
0x4ab702e4,0x03ba6569,0xd8adcdfe,0x91a0aa73,0x6a438167,0x234ee6ea,0xf8594e7d,0xb15429f0,
|
||||
0x888c0bee,0xc1816c63,0x1a96c4f4,0x539ba379,0xa878886d,0xe175efe0,0x3a624777,0x736f20fa,
|
||||
0xc9650ce8,0x80686b65,0x5b7fc3f2,0x1272a47f,0xe9918f6b,0xa09ce8e6,0x7b8b4071,0x328627fc,
|
||||
0x083b044d,0x413663c0,0x9a21cb57,0xd32cacda,0x28cf87ce,0x61c2e043,0xbad548d4,0xf3d82f59,
|
||||
0x49d2034b,0x00df64c6,0xdbc8cc51,0x92c5abdc,0x692680c8,0x202be745,0xfb3c4fd2,0xb231285f,
|
||||
0x8be90a41,0xc2e46dcc,0x19f3c55b,0x50fea2d6,0xab1d89c2,0xe210ee4f,0x390746d8,0x700a2155,
|
||||
0xca000d47,0x830d6aca,0x581ac25d,0x1117a5d0,0xeaf48ec4,0xa3f9e949,0x78ee41de,0x31e32653},
|
||||
|
||||
{0x00000000,0x1b280d78,0x36501af0,0x2d781788,0x6ca035e0,0x77883898,0x5af02f10,0x41d82268,
|
||||
0xd9406bc0,0xc26866b8,0xef107130,0xf4387c48,0xb5e05e20,0xaec85358,0x83b044d0,0x989849a8,
|
||||
0xb641ca37,0xad69c74f,0x8011d0c7,0x9b39ddbf,0xdae1ffd7,0xc1c9f2af,0xecb1e527,0xf799e85f,
|
||||
0x6f01a1f7,0x7429ac8f,0x5951bb07,0x4279b67f,0x03a19417,0x1889996f,0x35f18ee7,0x2ed9839f,
|
||||
0x684289d9,0x736a84a1,0x5e129329,0x453a9e51,0x04e2bc39,0x1fcab141,0x32b2a6c9,0x299aabb1,
|
||||
0xb102e219,0xaa2aef61,0x8752f8e9,0x9c7af591,0xdda2d7f9,0xc68ada81,0xebf2cd09,0xf0dac071,
|
||||
0xde0343ee,0xc52b4e96,0xe853591e,0xf37b5466,0xb2a3760e,0xa98b7b76,0x84f36cfe,0x9fdb6186,
|
||||
0x0743282e,0x1c6b2556,0x311332de,0x2a3b3fa6,0x6be31dce,0x70cb10b6,0x5db3073e,0x469b0a46,
|
||||
0xd08513b2,0xcbad1eca,0xe6d50942,0xfdfd043a,0xbc252652,0xa70d2b2a,0x8a753ca2,0x915d31da,
|
||||
0x09c57872,0x12ed750a,0x3f956282,0x24bd6ffa,0x65654d92,0x7e4d40ea,0x53355762,0x481d5a1a,
|
||||
0x66c4d985,0x7decd4fd,0x5094c375,0x4bbcce0d,0x0a64ec65,0x114ce11d,0x3c34f695,0x271cfbed,
|
||||
0xbf84b245,0xa4acbf3d,0x89d4a8b5,0x92fca5cd,0xd32487a5,0xc80c8add,0xe5749d55,0xfe5c902d,
|
||||
0xb8c79a6b,0xa3ef9713,0x8e97809b,0x95bf8de3,0xd467af8b,0xcf4fa2f3,0xe237b57b,0xf91fb803,
|
||||
0x6187f1ab,0x7aaffcd3,0x57d7eb5b,0x4cffe623,0x0d27c44b,0x160fc933,0x3b77debb,0x205fd3c3,
|
||||
0x0e86505c,0x15ae5d24,0x38d64aac,0x23fe47d4,0x622665bc,0x790e68c4,0x54767f4c,0x4f5e7234,
|
||||
0xd7c63b9c,0xccee36e4,0xe196216c,0xfabe2c14,0xbb660e7c,0xa04e0304,0x8d36148c,0x961e19f4,
|
||||
0xa5cb3ad3,0xbee337ab,0x939b2023,0x88b32d5b,0xc96b0f33,0xd243024b,0xff3b15c3,0xe41318bb,
|
||||
0x7c8b5113,0x67a35c6b,0x4adb4be3,0x51f3469b,0x102b64f3,0x0b03698b,0x267b7e03,0x3d53737b,
|
||||
0x138af0e4,0x08a2fd9c,0x25daea14,0x3ef2e76c,0x7f2ac504,0x6402c87c,0x497adff4,0x5252d28c,
|
||||
0xcaca9b24,0xd1e2965c,0xfc9a81d4,0xe7b28cac,0xa66aaec4,0xbd42a3bc,0x903ab434,0x8b12b94c,
|
||||
0xcd89b30a,0xd6a1be72,0xfbd9a9fa,0xe0f1a482,0xa12986ea,0xba018b92,0x97799c1a,0x8c519162,
|
||||
0x14c9d8ca,0x0fe1d5b2,0x2299c23a,0x39b1cf42,0x7869ed2a,0x6341e052,0x4e39f7da,0x5511faa2,
|
||||
0x7bc8793d,0x60e07445,0x4d9863cd,0x56b06eb5,0x17684cdd,0x0c4041a5,0x2138562d,0x3a105b55,
|
||||
0xa28812fd,0xb9a01f85,0x94d8080d,0x8ff00575,0xce28271d,0xd5002a65,0xf8783ded,0xe3503095,
|
||||
0x754e2961,0x6e662419,0x431e3391,0x58363ee9,0x19ee1c81,0x02c611f9,0x2fbe0671,0x34960b09,
|
||||
0xac0e42a1,0xb7264fd9,0x9a5e5851,0x81765529,0xc0ae7741,0xdb867a39,0xf6fe6db1,0xedd660c9,
|
||||
0xc30fe356,0xd827ee2e,0xf55ff9a6,0xee77f4de,0xafafd6b6,0xb487dbce,0x99ffcc46,0x82d7c13e,
|
||||
0x1a4f8896,0x016785ee,0x2c1f9266,0x37379f1e,0x76efbd76,0x6dc7b00e,0x40bfa786,0x5b97aafe,
|
||||
0x1d0ca0b8,0x0624adc0,0x2b5cba48,0x3074b730,0x71ac9558,0x6a849820,0x47fc8fa8,0x5cd482d0,
|
||||
0xc44ccb78,0xdf64c600,0xf21cd188,0xe934dcf0,0xa8ecfe98,0xb3c4f3e0,0x9ebce468,0x8594e910,
|
||||
0xab4d6a8f,0xb06567f7,0x9d1d707f,0x86357d07,0xc7ed5f6f,0xdcc55217,0xf1bd459f,0xea9548e7,
|
||||
0x720d014f,0x69250c37,0x445d1bbf,0x5f7516c7,0x1ead34af,0x058539d7,0x28fd2e5f,0x33d52327},
|
||||
|
||||
{0x00000000,0x4f576811,0x9eaed022,0xd1f9b833,0x399cbdf3,0x76cbd5e2,0xa7326dd1,0xe86505c0,
|
||||
0x73397be6,0x3c6e13f7,0xed97abc4,0xa2c0c3d5,0x4aa5c615,0x05f2ae04,0xd40b1637,0x9b5c7e26,
|
||||
0xe672f7cc,0xa9259fdd,0x78dc27ee,0x378b4fff,0xdfee4a3f,0x90b9222e,0x41409a1d,0x0e17f20c,
|
||||
0x954b8c2a,0xda1ce43b,0x0be55c08,0x44b23419,0xacd731d9,0xe38059c8,0x3279e1fb,0x7d2e89ea,
|
||||
0xc824f22f,0x87739a3e,0x568a220d,0x19dd4a1c,0xf1b84fdc,0xbeef27cd,0x6f169ffe,0x2041f7ef,
|
||||
0xbb1d89c9,0xf44ae1d8,0x25b359eb,0x6ae431fa,0x8281343a,0xcdd65c2b,0x1c2fe418,0x53788c09,
|
||||
0x2e5605e3,0x61016df2,0xb0f8d5c1,0xffafbdd0,0x17cab810,0x589dd001,0x89646832,0xc6330023,
|
||||
0x5d6f7e05,0x12381614,0xc3c1ae27,0x8c96c636,0x64f3c3f6,0x2ba4abe7,0xfa5d13d4,0xb50a7bc5,
|
||||
0x9488f9e9,0xdbdf91f8,0x0a2629cb,0x457141da,0xad14441a,0xe2432c0b,0x33ba9438,0x7cedfc29,
|
||||
0xe7b1820f,0xa8e6ea1e,0x791f522d,0x36483a3c,0xde2d3ffc,0x917a57ed,0x4083efde,0x0fd487cf,
|
||||
0x72fa0e25,0x3dad6634,0xec54de07,0xa303b616,0x4b66b3d6,0x0431dbc7,0xd5c863f4,0x9a9f0be5,
|
||||
0x01c375c3,0x4e941dd2,0x9f6da5e1,0xd03acdf0,0x385fc830,0x7708a021,0xa6f11812,0xe9a67003,
|
||||
0x5cac0bc6,0x13fb63d7,0xc202dbe4,0x8d55b3f5,0x6530b635,0x2a67de24,0xfb9e6617,0xb4c90e06,
|
||||
0x2f957020,0x60c21831,0xb13ba002,0xfe6cc813,0x1609cdd3,0x595ea5c2,0x88a71df1,0xc7f075e0,
|
||||
0xbadefc0a,0xf589941b,0x24702c28,0x6b274439,0x834241f9,0xcc1529e8,0x1dec91db,0x52bbf9ca,
|
||||
0xc9e787ec,0x86b0effd,0x574957ce,0x181e3fdf,0xf07b3a1f,0xbf2c520e,0x6ed5ea3d,0x2182822c,
|
||||
0x2dd0ee65,0x62878674,0xb37e3e47,0xfc295656,0x144c5396,0x5b1b3b87,0x8ae283b4,0xc5b5eba5,
|
||||
0x5ee99583,0x11befd92,0xc04745a1,0x8f102db0,0x67752870,0x28224061,0xf9dbf852,0xb68c9043,
|
||||
0xcba219a9,0x84f571b8,0x550cc98b,0x1a5ba19a,0xf23ea45a,0xbd69cc4b,0x6c907478,0x23c71c69,
|
||||
0xb89b624f,0xf7cc0a5e,0x2635b26d,0x6962da7c,0x8107dfbc,0xce50b7ad,0x1fa90f9e,0x50fe678f,
|
||||
0xe5f41c4a,0xaaa3745b,0x7b5acc68,0x340da479,0xdc68a1b9,0x933fc9a8,0x42c6719b,0x0d91198a,
|
||||
0x96cd67ac,0xd99a0fbd,0x0863b78e,0x4734df9f,0xaf51da5f,0xe006b24e,0x31ff0a7d,0x7ea8626c,
|
||||
0x0386eb86,0x4cd18397,0x9d283ba4,0xd27f53b5,0x3a1a5675,0x754d3e64,0xa4b48657,0xebe3ee46,
|
||||
0x70bf9060,0x3fe8f871,0xee114042,0xa1462853,0x49232d93,0x06744582,0xd78dfdb1,0x98da95a0,
|
||||
0xb958178c,0xf60f7f9d,0x27f6c7ae,0x68a1afbf,0x80c4aa7f,0xcf93c26e,0x1e6a7a5d,0x513d124c,
|
||||
0xca616c6a,0x8536047b,0x54cfbc48,0x1b98d459,0xf3fdd199,0xbcaab988,0x6d5301bb,0x220469aa,
|
||||
0x5f2ae040,0x107d8851,0xc1843062,0x8ed35873,0x66b65db3,0x29e135a2,0xf8188d91,0xb74fe580,
|
||||
0x2c139ba6,0x6344f3b7,0xb2bd4b84,0xfdea2395,0x158f2655,0x5ad84e44,0x8b21f677,0xc4769e66,
|
||||
0x717ce5a3,0x3e2b8db2,0xefd23581,0xa0855d90,0x48e05850,0x07b73041,0xd64e8872,0x9919e063,
|
||||
0x02459e45,0x4d12f654,0x9ceb4e67,0xd3bc2676,0x3bd923b6,0x748e4ba7,0xa577f394,0xea209b85,
|
||||
0x970e126f,0xd8597a7e,0x09a0c24d,0x46f7aa5c,0xae92af9c,0xe1c5c78d,0x303c7fbe,0x7f6b17af,
|
||||
0xe4376989,0xab600198,0x7a99b9ab,0x35ced1ba,0xddabd47a,0x92fcbc6b,0x43050458,0x0c526c49},
|
||||
|
||||
{0x00000000,0x5ba1dcca,0xb743b994,0xece2655e,0x6a466e9f,0x31e7b255,0xdd05d70b,0x86a40bc1,
|
||||
0xd48cdd3e,0x8f2d01f4,0x63cf64aa,0x386eb860,0xbecab3a1,0xe56b6f6b,0x09890a35,0x5228d6ff,
|
||||
0xadd8a7cb,0xf6797b01,0x1a9b1e5f,0x413ac295,0xc79ec954,0x9c3f159e,0x70dd70c0,0x2b7cac0a,
|
||||
0x79547af5,0x22f5a63f,0xce17c361,0x95b61fab,0x1312146a,0x48b3c8a0,0xa451adfe,0xfff07134,
|
||||
0x5f705221,0x04d18eeb,0xe833ebb5,0xb392377f,0x35363cbe,0x6e97e074,0x8275852a,0xd9d459e0,
|
||||
0x8bfc8f1f,0xd05d53d5,0x3cbf368b,0x671eea41,0xe1bae180,0xba1b3d4a,0x56f95814,0x0d5884de,
|
||||
0xf2a8f5ea,0xa9092920,0x45eb4c7e,0x1e4a90b4,0x98ee9b75,0xc34f47bf,0x2fad22e1,0x740cfe2b,
|
||||
0x262428d4,0x7d85f41e,0x91679140,0xcac64d8a,0x4c62464b,0x17c39a81,0xfb21ffdf,0xa0802315,
|
||||
0xbee0a442,0xe5417888,0x09a31dd6,0x5202c11c,0xd4a6cadd,0x8f071617,0x63e57349,0x3844af83,
|
||||
0x6a6c797c,0x31cda5b6,0xdd2fc0e8,0x868e1c22,0x002a17e3,0x5b8bcb29,0xb769ae77,0xecc872bd,
|
||||
0x13380389,0x4899df43,0xa47bba1d,0xffda66d7,0x797e6d16,0x22dfb1dc,0xce3dd482,0x959c0848,
|
||||
0xc7b4deb7,0x9c15027d,0x70f76723,0x2b56bbe9,0xadf2b028,0xf6536ce2,0x1ab109bc,0x4110d576,
|
||||
0xe190f663,0xba312aa9,0x56d34ff7,0x0d72933d,0x8bd698fc,0xd0774436,0x3c952168,0x6734fda2,
|
||||
0x351c2b5d,0x6ebdf797,0x825f92c9,0xd9fe4e03,0x5f5a45c2,0x04fb9908,0xe819fc56,0xb3b8209c,
|
||||
0x4c4851a8,0x17e98d62,0xfb0be83c,0xa0aa34f6,0x260e3f37,0x7dafe3fd,0x914d86a3,0xcaec5a69,
|
||||
0x98c48c96,0xc365505c,0x2f873502,0x7426e9c8,0xf282e209,0xa9233ec3,0x45c15b9d,0x1e608757,
|
||||
0x79005533,0x22a189f9,0xce43eca7,0x95e2306d,0x13463bac,0x48e7e766,0xa4058238,0xffa45ef2,
|
||||
0xad8c880d,0xf62d54c7,0x1acf3199,0x416eed53,0xc7cae692,0x9c6b3a58,0x70895f06,0x2b2883cc,
|
||||
0xd4d8f2f8,0x8f792e32,0x639b4b6c,0x383a97a6,0xbe9e9c67,0xe53f40ad,0x09dd25f3,0x527cf939,
|
||||
0x00542fc6,0x5bf5f30c,0xb7179652,0xecb64a98,0x6a124159,0x31b39d93,0xdd51f8cd,0x86f02407,
|
||||
0x26700712,0x7dd1dbd8,0x9133be86,0xca92624c,0x4c36698d,0x1797b547,0xfb75d019,0xa0d40cd3,
|
||||
0xf2fcda2c,0xa95d06e6,0x45bf63b8,0x1e1ebf72,0x98bab4b3,0xc31b6879,0x2ff90d27,0x7458d1ed,
|
||||
0x8ba8a0d9,0xd0097c13,0x3ceb194d,0x674ac587,0xe1eece46,0xba4f128c,0x56ad77d2,0x0d0cab18,
|
||||
0x5f247de7,0x0485a12d,0xe867c473,0xb3c618b9,0x35621378,0x6ec3cfb2,0x8221aaec,0xd9807626,
|
||||
0xc7e0f171,0x9c412dbb,0x70a348e5,0x2b02942f,0xada69fee,0xf6074324,0x1ae5267a,0x4144fab0,
|
||||
0x136c2c4f,0x48cdf085,0xa42f95db,0xff8e4911,0x792a42d0,0x228b9e1a,0xce69fb44,0x95c8278e,
|
||||
0x6a3856ba,0x31998a70,0xdd7bef2e,0x86da33e4,0x007e3825,0x5bdfe4ef,0xb73d81b1,0xec9c5d7b,
|
||||
0xbeb48b84,0xe515574e,0x09f73210,0x5256eeda,0xd4f2e51b,0x8f5339d1,0x63b15c8f,0x38108045,
|
||||
0x9890a350,0xc3317f9a,0x2fd31ac4,0x7472c60e,0xf2d6cdcf,0xa9771105,0x4595745b,0x1e34a891,
|
||||
0x4c1c7e6e,0x17bda2a4,0xfb5fc7fa,0xa0fe1b30,0x265a10f1,0x7dfbcc3b,0x9119a965,0xcab875af,
|
||||
0x3548049b,0x6ee9d851,0x820bbd0f,0xd9aa61c5,0x5f0e6a04,0x04afb6ce,0xe84dd390,0xb3ec0f5a,
|
||||
0xe1c4d9a5,0xba65056f,0x56876031,0x0d26bcfb,0x8b82b73a,0xd0236bf0,0x3cc10eae,0x6760d264}};
|
||||
2114
Telegram/WatchApp/Packages/OpusKit/Sources/COgg/libogg/src/framing.c
Normal file
2114
Telegram/WatchApp/Packages/OpusKit/Sources/COgg/libogg/src/framing.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef COpus_h
|
||||
#define COpus_h
|
||||
|
||||
#include <opus.h>
|
||||
#include <opus_multistream.h>
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module COpus {
|
||||
header "opus.h"
|
||||
header "opus_defines.h"
|
||||
header "opus_multistream.h"
|
||||
header "opus_types.h"
|
||||
export *
|
||||
}
|
||||
1099
Telegram/WatchApp/Packages/OpusKit/Sources/COpus/include/opus.h
Normal file
1099
Telegram/WatchApp/Packages/OpusKit/Sources/COpus/include/opus.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,830 @@
|
|||
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
|
||||
Written by Jean-Marc Valin and Koen Vos */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_defines.h
|
||||
* @brief Opus reference implementation constants
|
||||
*/
|
||||
|
||||
#ifndef OPUS_DEFINES_H
|
||||
#define OPUS_DEFINES_H
|
||||
|
||||
#include "opus_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup opus_errorcodes Error codes
|
||||
* @{
|
||||
*/
|
||||
/** No error @hideinitializer*/
|
||||
#define OPUS_OK 0
|
||||
/** One or more invalid/out of range arguments @hideinitializer*/
|
||||
#define OPUS_BAD_ARG -1
|
||||
/** Not enough bytes allocated in the buffer @hideinitializer*/
|
||||
#define OPUS_BUFFER_TOO_SMALL -2
|
||||
/** An internal error was detected @hideinitializer*/
|
||||
#define OPUS_INTERNAL_ERROR -3
|
||||
/** The compressed data passed is corrupted @hideinitializer*/
|
||||
#define OPUS_INVALID_PACKET -4
|
||||
/** Invalid/unsupported request number @hideinitializer*/
|
||||
#define OPUS_UNIMPLEMENTED -5
|
||||
/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
|
||||
#define OPUS_INVALID_STATE -6
|
||||
/** Memory allocation has failed @hideinitializer*/
|
||||
#define OPUS_ALLOC_FAIL -7
|
||||
/**@}*/
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
/**Export control for opus functions */
|
||||
|
||||
#ifndef OPUS_EXPORT
|
||||
# if defined(_WIN32)
|
||||
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
|
||||
# define OPUS_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
# elif defined(__GNUC__) && defined(OPUS_BUILD)
|
||||
# define OPUS_EXPORT __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define OPUS_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
# if !defined(OPUS_GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define OPUS_GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if OPUS_GNUC_PREREQ(3,0)
|
||||
# define OPUS_RESTRICT __restrict__
|
||||
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
|
||||
# define OPUS_RESTRICT __restrict
|
||||
# else
|
||||
# define OPUS_RESTRICT
|
||||
# endif
|
||||
#else
|
||||
# define OPUS_RESTRICT restrict
|
||||
#endif
|
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
|
||||
# if OPUS_GNUC_PREREQ(2,7)
|
||||
# define OPUS_INLINE __inline__
|
||||
# elif (defined(_MSC_VER))
|
||||
# define OPUS_INLINE __inline
|
||||
# else
|
||||
# define OPUS_INLINE
|
||||
# endif
|
||||
#else
|
||||
# define OPUS_INLINE inline
|
||||
#endif
|
||||
|
||||
/**Warning attributes for opus functions
|
||||
* NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
|
||||
* some paranoid null checks. */
|
||||
#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
|
||||
#else
|
||||
# define OPUS_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
|
||||
# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
|
||||
#else
|
||||
# define OPUS_ARG_NONNULL(_x)
|
||||
#endif
|
||||
|
||||
/** These are the actual Encoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
#define OPUS_SET_APPLICATION_REQUEST 4000
|
||||
#define OPUS_GET_APPLICATION_REQUEST 4001
|
||||
#define OPUS_SET_BITRATE_REQUEST 4002
|
||||
#define OPUS_GET_BITRATE_REQUEST 4003
|
||||
#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
|
||||
#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
|
||||
#define OPUS_SET_VBR_REQUEST 4006
|
||||
#define OPUS_GET_VBR_REQUEST 4007
|
||||
#define OPUS_SET_BANDWIDTH_REQUEST 4008
|
||||
#define OPUS_GET_BANDWIDTH_REQUEST 4009
|
||||
#define OPUS_SET_COMPLEXITY_REQUEST 4010
|
||||
#define OPUS_GET_COMPLEXITY_REQUEST 4011
|
||||
#define OPUS_SET_INBAND_FEC_REQUEST 4012
|
||||
#define OPUS_GET_INBAND_FEC_REQUEST 4013
|
||||
#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
|
||||
#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
|
||||
#define OPUS_SET_DTX_REQUEST 4016
|
||||
#define OPUS_GET_DTX_REQUEST 4017
|
||||
#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
|
||||
#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
|
||||
#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
|
||||
#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
|
||||
#define OPUS_SET_SIGNAL_REQUEST 4024
|
||||
#define OPUS_GET_SIGNAL_REQUEST 4025
|
||||
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
|
||||
/* #define OPUS_RESET_STATE 4028 */
|
||||
#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
|
||||
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
|
||||
#define OPUS_GET_PITCH_REQUEST 4033
|
||||
#define OPUS_SET_GAIN_REQUEST 4034
|
||||
#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
|
||||
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
|
||||
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
|
||||
#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
|
||||
#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
|
||||
#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
|
||||
#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
|
||||
#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
|
||||
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
|
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
|
||||
#define OPUS_GET_IN_DTX_REQUEST 4049
|
||||
#define OPUS_SET_DRED_DURATION_REQUEST 4050
|
||||
#define OPUS_GET_DRED_DURATION_REQUEST 4051
|
||||
#define OPUS_SET_DNN_BLOB_REQUEST 4052
|
||||
/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */
|
||||
|
||||
/** Defines for the presence of extended APIs. */
|
||||
#define OPUS_HAVE_OPUS_PROJECTION_H
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
|
||||
#ifdef DISABLE_PTR_CHECK
|
||||
/* Disable checks to prevent ubsan from complaining about NULL checks
|
||||
in test_opus_api. */
|
||||
#define __opus_check_int_ptr(ptr) (ptr)
|
||||
#define __opus_check_uint_ptr(ptr) (ptr)
|
||||
#define __opus_check_uint8_ptr(ptr) (ptr)
|
||||
#define __opus_check_val16_ptr(ptr) (ptr)
|
||||
#define __opus_check_void_ptr(ptr) (ptr)
|
||||
#else
|
||||
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
|
||||
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
|
||||
#define __opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr)))
|
||||
#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
|
||||
#define __opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x))
|
||||
#endif
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
|
||||
* @see opus_genericctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
/* Values for the various encoder CTLs */
|
||||
#define OPUS_AUTO -1000 /**<Auto/default setting @hideinitializer*/
|
||||
#define OPUS_BITRATE_MAX -1 /**<Maximum bitrate @hideinitializer*/
|
||||
|
||||
/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_VOIP 2048
|
||||
/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_AUDIO 2049
|
||||
/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
|
||||
* @hideinitializer */
|
||||
#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
|
||||
|
||||
#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
|
||||
#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
|
||||
#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
|
||||
#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
|
||||
|
||||
#define OPUS_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */
|
||||
#define OPUS_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */
|
||||
#define OPUS_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */
|
||||
#define OPUS_FRAMESIZE_10_MS 5003 /**< Use 10 ms frames */
|
||||
#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */
|
||||
#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
|
||||
#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
|
||||
#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
|
||||
#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
|
||||
#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @defgroup opus_encoderctls Encoder related CTLs
|
||||
*
|
||||
* These are convenience macros for use with the \c opus_encode_ctl
|
||||
* interface. They are used to generate the appropriate series of
|
||||
* arguments for that call, passing the correct type, size and so
|
||||
* on as expected for each particular request.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
|
||||
* if (ret != OPUS_OK) return ret;
|
||||
*
|
||||
* opus_int32 rate;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_genericctls, opus_encoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures the encoder's computational complexity.
|
||||
* The supported range is 0-10 inclusive with 10 representing the highest complexity.
|
||||
* @see OPUS_GET_COMPLEXITY
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's complexity configuration.
|
||||
* @see OPUS_SET_COMPLEXITY
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
|
||||
* inclusive.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the bitrate in the encoder.
|
||||
* Rates from 500 to 512000 bits per second are meaningful, as well as the
|
||||
* special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
|
||||
* The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
|
||||
* rate as it can, which is useful for controlling the rate by adjusting the
|
||||
* output buffer size.
|
||||
* @see OPUS_GET_BITRATE
|
||||
* @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
|
||||
* is determined based on the number of
|
||||
* channels and the input sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's bitrate configuration.
|
||||
* @see OPUS_SET_BITRATE
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
|
||||
* The default is determined based on the
|
||||
* number of channels and the input
|
||||
* sampling rate.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables variable bitrate (VBR) in the encoder.
|
||||
* The configured bitrate may not be met exactly because frames must
|
||||
* be an integer number of bytes in length.
|
||||
* @see OPUS_GET_VBR
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
|
||||
* cause noticeable quality degradation.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
|
||||
* #OPUS_SET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
|
||||
/** Determine if variable bitrate (VBR) is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Hard CBR.</dd>
|
||||
* <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
|
||||
* #OPUS_GET_VBR_CONSTRAINT.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Enables or disables constrained VBR in the encoder.
|
||||
* This setting is ignored when the encoder is in CBR mode.
|
||||
* @warning Only the MDCT mode of Opus currently heeds the constraint.
|
||||
* Speech mode ignores it completely, hybrid mode may fail to obey it
|
||||
* if the LPC layer uses more bitrate than the constraint would have
|
||||
* permitted.
|
||||
* @see OPUS_GET_VBR_CONSTRAINT
|
||||
* @see OPUS_SET_VBR
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
|
||||
* frame of buffering delay assuming a transport with a
|
||||
* serialization speed of the nominal bitrate.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
|
||||
/** Determine if constrained VBR is enabled in the encoder.
|
||||
* @see OPUS_SET_VBR_CONSTRAINT
|
||||
* @see OPUS_GET_VBR
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Unconstrained VBR.</dd>
|
||||
* <dt>1</dt><dd>Constrained VBR (default).</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures mono/stereo forcing in the encoder.
|
||||
* This can force the encoder to produce packets encoded as either mono or
|
||||
* stereo, regardless of the format of the input audio. This is useful when
|
||||
* the caller knows that the input signal is currently a mono source embedded
|
||||
* in a stereo stream.
|
||||
* @see OPUS_GET_FORCE_CHANNELS
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's forced channel configuration.
|
||||
* @see OPUS_SET_FORCE_CHANNELS
|
||||
* @param[out] x <tt>opus_int32 *</tt>:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
|
||||
* <dt>1</dt> <dd>Forced mono</dd>
|
||||
* <dt>2</dt> <dd>Forced stereo</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the maximum bandpass that the encoder will select automatically.
|
||||
* Applications should normally use this instead of #OPUS_SET_BANDWIDTH
|
||||
* (leaving that set to the default, #OPUS_AUTO). This allows the
|
||||
* application to set an upper bound based on the type of input it is
|
||||
* providing, but still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_MAX_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Gets the encoder's configured maximum allowed bandpass.
|
||||
* @see OPUS_SET_MAX_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Sets the encoder's bandpass to a specific value.
|
||||
* This prevents the encoder from automatically selecting the bandpass based
|
||||
* on the available bitrate. If an application knows the bandpass of the input
|
||||
* audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
|
||||
* instead, which still gives the encoder the freedom to reduce the bandpass
|
||||
* when the bitrate becomes too low, for better overall quality.
|
||||
* @see OPUS_GET_BANDWIDTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
|
||||
|
||||
/** Configures the type of signal being encoded.
|
||||
* This is a hint which helps the encoder's mode selection.
|
||||
* @see OPUS_GET_SIGNAL
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal type.
|
||||
* @see OPUS_SET_SIGNAL
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
|
||||
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
|
||||
/** Configures the encoder's intended application.
|
||||
* The initial value is a mandatory argument to the encoder_create function.
|
||||
* @see OPUS_GET_APPLICATION
|
||||
* @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured application.
|
||||
* @see OPUS_SET_APPLICATION
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the total samples of delay added by the entire codec.
|
||||
* This can be queried by the encoder and then the provided number of samples can be
|
||||
* skipped on from the start of the decoder's output to provide time aligned input
|
||||
* and output. From the perspective of a decoding application the real data begins this many
|
||||
* samples late.
|
||||
*
|
||||
* The decoder contribution to this delay is identical for all decoders, but the
|
||||
* encoder portion of the delay may vary from implementation to implementation,
|
||||
* version to version, or even depend on the encoder's initial configuration.
|
||||
* Applications needing delay compensation should call this CTL rather than
|
||||
* hard-coding a value.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of inband forward error correction (FEC).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_INBAND_FEC
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of inband forward error correction.
|
||||
* @see OPUS_SET_INBAND_FEC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
|
||||
* <dt>1</dt><dd>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd>
|
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's expected packet loss percentage.
|
||||
* Higher values trigger progressively more loss resistant behavior in the encoder
|
||||
* at the expense of quality at a given bitrate in the absence of packet loss, but
|
||||
* greater quality under loss.
|
||||
* @see OPUS_GET_PACKET_LOSS_PERC
|
||||
* @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured packet loss percentage.
|
||||
* @see OPUS_SET_PACKET_LOSS_PERC
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
|
||||
* in the range 0-100, inclusive (default: 0).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of discontinuous transmission (DTX).
|
||||
* @note This is only applicable to the LPC layer
|
||||
* @see OPUS_GET_DTX
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Disable DTX (default).</dd>
|
||||
* <dt>1</dt><dd>Enabled DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
|
||||
/** Gets encoder's configured use of discontinuous transmission.
|
||||
* @see OPUS_SET_DTX
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>DTX disabled (default).</dd>
|
||||
* <dt>1</dt><dd>DTX enabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Configures the depth of signal being encoded.
|
||||
*
|
||||
* This is a hint which helps the encoder identify silence and near-silence.
|
||||
* It represents the number of significant bits of linear intensity below
|
||||
* which the signal contains ignorable quantization or other noise.
|
||||
*
|
||||
* For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
|
||||
* for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
|
||||
* for 16-bit linear pcm input with opus_encode_float().
|
||||
*
|
||||
* When using opus_encode() instead of opus_encode_float(), or when libopus
|
||||
* is compiled for fixed-point, the encoder uses the minimum of the value
|
||||
* set here and the value 16.
|
||||
*
|
||||
* @see OPUS_GET_LSB_DEPTH
|
||||
* @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
|
||||
* (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured signal depth.
|
||||
* @see OPUS_SET_LSB_DEPTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
|
||||
* 24 (default: 24).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Configures the encoder's use of variable duration frames.
|
||||
* When variable duration is enabled, the encoder is free to use a shorter frame
|
||||
* size than the one requested in the opus_encode*() call.
|
||||
* It is then the user's responsibility
|
||||
* to verify how much audio was encoded by checking the ToC byte of the encoded
|
||||
* packet. The part of the audio that was not encoded needs to be resent to the
|
||||
* encoder for the next call. Do not use this option unless you <b>really</b>
|
||||
* know what you are doing.
|
||||
* @see OPUS_GET_EXPERT_FRAME_DURATION
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
|
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured use of variable duration frames.
|
||||
* @see OPUS_SET_EXPERT_FRAME_DURATION
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
|
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
|
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If set to 1, disables almost all use of prediction, making frames almost
|
||||
* completely independent. This reduces quality.
|
||||
* @see OPUS_GET_PREDICTION_DISABLED
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Enable prediction (default).</dd>
|
||||
* <dt>1</dt><dd>Disable prediction.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured prediction status.
|
||||
* @see OPUS_SET_PREDICTION_DISABLED
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Prediction enabled (default).</dd>
|
||||
* <dt>1</dt><dd>Prediction disabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Provide external DNN weights from binary object (only when explicitly built without the weights)
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, __opus_check_void_ptr(data), __opus_check_int(len)
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_genericctls Generic CTLs
|
||||
*
|
||||
* These macros are used with the \c opus_decoder_ctl and
|
||||
* \c opus_encoder_ctl calls to generate a particular
|
||||
* request.
|
||||
*
|
||||
* When called on an \c OpusDecoder they apply to that
|
||||
* particular decoder instance. When called on an
|
||||
* \c OpusEncoder they apply to the corresponding setting
|
||||
* on that encoder instance, if present.
|
||||
*
|
||||
* Some usage examples:
|
||||
*
|
||||
* @code
|
||||
* int ret;
|
||||
* opus_int32 pitch;
|
||||
* ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
|
||||
* if (ret == OPUS_OK) return ret;
|
||||
*
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
|
||||
*
|
||||
* opus_int32 enc_bw, dec_bw;
|
||||
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
|
||||
* opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
|
||||
* if (enc_bw != dec_bw) {
|
||||
* printf("packet bandwidth mismatch!\n");
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Resets the codec state to be equivalent to a freshly initialized state.
|
||||
* This should be called when switching streams in order to prevent
|
||||
* the back to back decoding from giving different results from
|
||||
* one at a time decoding.
|
||||
* @hideinitializer */
|
||||
#define OPUS_RESET_STATE 4028
|
||||
|
||||
/** Gets the final state of the codec's entropy coder.
|
||||
* This is used for testing purposes,
|
||||
* The encoder and decoder state should be identical after coding a payload
|
||||
* (assuming no data corruption or software bugs)
|
||||
*
|
||||
* @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
|
||||
|
||||
/** Gets the encoder's configured bandpass or the decoder's last bandpass.
|
||||
* @see OPUS_SET_BANDWIDTH
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
|
||||
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the sampling rate the encoder or decoder was initialized with.
|
||||
* This simply returns the <code>Fs</code> value passed to opus_encoder_init()
|
||||
* or opus_decoder_init().
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** If set to 1, disables the use of phase inversion for intensity stereo,
|
||||
* improving the quality of mono downmixes, but slightly reducing normal
|
||||
* stereo quality. Disabling phase inversion in the decoder does not comply
|
||||
* with RFC 6716, although it does not cause any interoperability issue and
|
||||
* is expected to become part of the Opus standard once RFC 6716 is updated
|
||||
* by draft-ietf-codec-opus-update.
|
||||
* @see OPUS_GET_PHASE_INVERSION_DISABLED
|
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Enable phase inversion (default).</dd>
|
||||
* <dt>1</dt><dd>Disable phase inversion.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
|
||||
/** Gets the encoder's configured phase inversion status.
|
||||
* @see OPUS_SET_PHASE_INVERSION_DISABLED
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
|
||||
* <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
|
||||
/** Gets the DTX state of the encoder.
|
||||
* Returns whether the last encoded frame was either a comfort noise update
|
||||
* during DTX or not encoded because of DTX.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
|
||||
* <dl>
|
||||
* <dt>0</dt><dd>The encoder is not in DTX.</dd>
|
||||
* <dt>1</dt><dd>The encoder is in DTX.</dd>
|
||||
* </dl>
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_decoderctls Decoder related CTLs
|
||||
* @see opus_genericctls, opus_encoderctls, opus_decoder
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Configures decoder gain adjustment.
|
||||
* Scales the decoded output by a factor specified in Q8 dB units.
|
||||
* This has a maximum range of -32768 to 32767 inclusive, and returns
|
||||
* OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
|
||||
* This setting survives decoder reset.
|
||||
*
|
||||
* gain = pow(10, x/(20.0*256))
|
||||
*
|
||||
* @param[in] x <tt>opus_int32</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
|
||||
/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/** Gets the pitch of the last decoded frame, if available.
|
||||
* This can be used for any post-processing algorithm requiring the use of pitch,
|
||||
* e.g. time stretching/shortening. If the last frame was not voiced, or if the
|
||||
* pitch was not coded in the frame, then zero is returned.
|
||||
*
|
||||
* This CTL is only implemented for decoder instances.
|
||||
*
|
||||
* @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
|
||||
*
|
||||
* @hideinitializer */
|
||||
#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_libinfo Opus library information functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Converts an opus error code into a human readable string.
|
||||
*
|
||||
* @param[in] error <tt>int</tt>: Error number
|
||||
* @returns Error string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_strerror(int error);
|
||||
|
||||
/** Gets the libopus version string.
|
||||
*
|
||||
* Applications may look for the substring "-fixed" in the version string to
|
||||
* determine whether they have a fixed-point or floating-point build at
|
||||
* runtime.
|
||||
*
|
||||
* @returns Version string
|
||||
*/
|
||||
OPUS_EXPORT const char *opus_get_version_string(void);
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_DEFINES_H */
|
||||
|
|
@ -0,0 +1,660 @@
|
|||
/* Copyright (c) 2011 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file opus_multistream.h
|
||||
* @brief Opus reference implementation multistream API
|
||||
*/
|
||||
|
||||
#ifndef OPUS_MULTISTREAM_H
|
||||
#define OPUS_MULTISTREAM_H
|
||||
|
||||
#include "opus.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */
|
||||
|
||||
/** Macros to trigger compilation errors when the wrong types are provided to a
|
||||
* CTL. */
|
||||
/**@{*/
|
||||
#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
|
||||
#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
|
||||
/**@}*/
|
||||
|
||||
/** These are the actual encoder and decoder CTL ID numbers.
|
||||
* They should not be used directly by applications.
|
||||
* In general, SETs should be even and GETs should be odd.*/
|
||||
/**@{*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
|
||||
/**@}*/
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
|
||||
*
|
||||
* These are convenience macros that are specific to the
|
||||
* opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
|
||||
* interface.
|
||||
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
|
||||
* @ref opus_decoderctls may be applied to a multistream encoder or decoder as
|
||||
* well.
|
||||
* In addition, you may retrieve the encoder or decoder state for an specific
|
||||
* stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
|
||||
* #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/** Gets the encoder state for an individual stream of a multistream encoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the encoder.
|
||||
* @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
|
||||
* encoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
|
||||
|
||||
/** Gets the decoder state for an individual stream of a multistream decoder.
|
||||
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
|
||||
* wish to retrieve.
|
||||
* This must be non-negative and less than
|
||||
* the <code>streams</code> parameter used
|
||||
* to initialize the decoder.
|
||||
* @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
|
||||
* decoder state.
|
||||
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
|
||||
* @hideinitializer
|
||||
*/
|
||||
#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup opus_multistream Opus Multistream API
|
||||
* @{
|
||||
*
|
||||
* The multistream API allows individual Opus streams to be combined into a
|
||||
* single packet, enabling support for up to 255 channels. Unlike an
|
||||
* elementary Opus stream, the encoder and decoder must negotiate the channel
|
||||
* configuration before the decoder can successfully interpret the data in the
|
||||
* packets produced by the encoder. Some basic information, such as packet
|
||||
* duration, can be computed without any special negotiation.
|
||||
*
|
||||
* The format for multistream Opus packets is defined in
|
||||
* <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
|
||||
* and is based on the self-delimited Opus framing described in Appendix B of
|
||||
* <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
|
||||
* Normal Opus packets are just a degenerate case of multistream Opus packets,
|
||||
* and can be encoded or decoded with the multistream API by setting
|
||||
* <code>streams</code> to <code>1</code> when initializing the encoder or
|
||||
* decoder.
|
||||
*
|
||||
* Multistream Opus streams can contain up to 255 elementary Opus streams.
|
||||
* These may be either "uncoupled" or "coupled", indicating that the decoder
|
||||
* is configured to decode them to either 1 or 2 channels, respectively.
|
||||
* The streams are ordered so that all coupled streams appear at the
|
||||
* beginning.
|
||||
*
|
||||
* A <code>mapping</code> table defines which decoded channel <code>i</code>
|
||||
* should be used for each input/output (I/O) channel <code>j</code>. This table is
|
||||
* typically provided as an unsigned char array.
|
||||
* Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
|
||||
* If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
|
||||
* encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
|
||||
* is even, or as the right channel of stream <code>(i/2)</code> if
|
||||
* <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
|
||||
* mono in stream <code>(i - coupled_streams)</code>, unless it has the special
|
||||
* value 255, in which case it is omitted from the encoding entirely (the
|
||||
* decoder will reproduce it as silence). Each value <code>i</code> must either
|
||||
* be the special value 255 or be less than <code>streams + coupled_streams</code>.
|
||||
*
|
||||
* The output channels specified by the encoder
|
||||
* should use the
|
||||
* <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
|
||||
* channel ordering</a>. A decoder may wish to apply an additional permutation
|
||||
* to the mapping the encoder used to achieve a different output channel
|
||||
* order (e.g. for outputting in WAV order).
|
||||
*
|
||||
* Each multistream packet contains an Opus packet for each stream, and all of
|
||||
* the Opus packets in a single multistream packet must have the same
|
||||
* duration. Therefore the duration of a multistream packet can be extracted
|
||||
* from the TOC sequence of the first stream, which is located at the
|
||||
* beginning of the packet, just like an elementary Opus stream:
|
||||
*
|
||||
* @code
|
||||
* int nb_samples;
|
||||
* int nb_frames;
|
||||
* nb_frames = opus_packet_get_nb_frames(data, len);
|
||||
* if (nb_frames < 1)
|
||||
* return nb_frames;
|
||||
* nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
|
||||
* @endcode
|
||||
*
|
||||
* The general encoding and decoding process proceeds exactly the same as in
|
||||
* the normal @ref opus_encoder and @ref opus_decoder APIs.
|
||||
* See their documentation for an overview of how to use the corresponding
|
||||
* multistream functions.
|
||||
*/
|
||||
|
||||
/** Opus multistream encoder state.
|
||||
* This contains the complete state of a multistream Opus encoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_init
|
||||
*/
|
||||
typedef struct OpusMSEncoder OpusMSEncoder;
|
||||
|
||||
/** Opus multistream decoder state.
|
||||
* This contains the complete state of a multistream Opus decoder.
|
||||
* It is position independent and can be freely copied.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_decoder_init
|
||||
*/
|
||||
typedef struct OpusMSDecoder OpusMSDecoder;
|
||||
|
||||
/**\name Multistream encoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an OpusMSEncoder structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
|
||||
int channels,
|
||||
int mapping_family
|
||||
);
|
||||
|
||||
|
||||
/** Allocates and initializes a multistream encoder state.
|
||||
* Call opus_multistream_encoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
unsigned char *mapping,
|
||||
int application,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Initialize a previously allocated multistream encoder state.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_encoder_create
|
||||
* @see opus_multistream_encoder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels in the input signal.
|
||||
* This must be at most 255.
|
||||
* It may be greater than the number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams to encode from the
|
||||
* input.
|
||||
* This must be no more than the number of channels.
|
||||
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
|
||||
* to encode.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* encoded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than the number of input channels.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* encoded channels to input channels, as described in
|
||||
* @ref opus_multistream. As an extra constraint, the
|
||||
* multistream encoder does not allow encoding coupled
|
||||
* streams for which one channel is unused since this
|
||||
* is never a good idea.
|
||||
* @param application <tt>int</tt>: The target encoder application.
|
||||
* This must be one of the following:
|
||||
* <dl>
|
||||
* <dt>#OPUS_APPLICATION_VOIP</dt>
|
||||
* <dd>Process signal for improved speech intelligibility.</dd>
|
||||
* <dt>#OPUS_APPLICATION_AUDIO</dt>
|
||||
* <dd>Favor faithfulness to the original input.</dd>
|
||||
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
|
||||
* <dd>Configure the minimum possible coding delay by disabling certain modes
|
||||
* of operation.</dd>
|
||||
* </dl>
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_init(
|
||||
OpusMSEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
OPUS_EXPORT int opus_multistream_surround_encoder_init(
|
||||
OpusMSEncoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int mapping_family,
|
||||
int *streams,
|
||||
int *coupled_streams,
|
||||
unsigned char *mapping,
|
||||
int application
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
|
||||
|
||||
/** Encodes a multistream Opus frame.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
|
||||
* samples.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
|
||||
OpusMSEncoder *st,
|
||||
const opus_int16 *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Encodes a multistream Opus frame from floating point input.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
|
||||
* samples with a normal range of
|
||||
* +/-1.0.
|
||||
* Samples with a range beyond +/-1.0
|
||||
* are supported but will be clipped by
|
||||
* decoders using the integer API and
|
||||
* should only be used if it is known
|
||||
* that the far end supports extended
|
||||
* dynamic range.
|
||||
* This must contain
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
|
||||
* signal.
|
||||
* This must be an Opus frame size for the
|
||||
* encoder's sampling rate.
|
||||
* For example, at 48 kHz the permitted values
|
||||
* are 120, 240, 480, 960, 1920, and 2880.
|
||||
* Passing in a duration of less than 10 ms
|
||||
* (480 samples at 48 kHz) will prevent the
|
||||
* encoder from using the LPC or hybrid modes.
|
||||
* @param[out] data <tt>unsigned char*</tt>: Output payload.
|
||||
* This must contain storage for at
|
||||
* least \a max_data_bytes.
|
||||
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
|
||||
* memory for the output
|
||||
* payload. This may be
|
||||
* used to impose an upper limit on
|
||||
* the instant bitrate, but should
|
||||
* not be used as the only bitrate
|
||||
* control. Use #OPUS_SET_BITRATE to
|
||||
* control the bitrate.
|
||||
* @returns The length of the encoded packet (in bytes) on success or a
|
||||
* negative error code (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
|
||||
OpusMSEncoder *st,
|
||||
const float *pcm,
|
||||
int frame_size,
|
||||
unsigned char *data,
|
||||
opus_int32 max_data_bytes
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Frees an <code>OpusMSEncoder</code> allocated by
|
||||
* opus_multistream_encoder_create().
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus encoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_encoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_encoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**\name Multistream decoder functions */
|
||||
/**@{*/
|
||||
|
||||
/** Gets the size of an <code>OpusMSDecoder</code> structure.
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @returns The size in bytes on success, or a negative error code
|
||||
* (see @ref opus_errorcodes) on error.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
|
||||
int streams,
|
||||
int coupled_streams
|
||||
);
|
||||
|
||||
/** Allocates and initializes a multistream decoder state.
|
||||
* Call opus_multistream_decoder_destroy() to release
|
||||
* this object when finished.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
|
||||
* code (see @ref opus_errorcodes) on
|
||||
* failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping,
|
||||
int *error
|
||||
) OPUS_ARG_NONNULL(5);
|
||||
|
||||
/** Intialize a previously allocated decoder state object.
|
||||
* The memory pointed to by \a st must be at least the size returned by
|
||||
* opus_multistream_encoder_get_size().
|
||||
* This is intended for applications which use their own allocator instead of
|
||||
* malloc.
|
||||
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
|
||||
* @see opus_multistream_decoder_create
|
||||
* @see opus_multistream_deocder_get_size
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
|
||||
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
|
||||
* This must be one of 8000, 12000, 16000,
|
||||
* 24000, or 48000.
|
||||
* @param channels <tt>int</tt>: Number of channels to output.
|
||||
* This must be at most 255.
|
||||
* It may be different from the number of coded
|
||||
* channels (<code>streams +
|
||||
* coupled_streams</code>).
|
||||
* @param streams <tt>int</tt>: The total number of streams coded in the
|
||||
* input.
|
||||
* This must be no more than 255.
|
||||
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
|
||||
* (2 channel) streams.
|
||||
* This must be no larger than the total
|
||||
* number of streams.
|
||||
* Additionally, The total number of
|
||||
* coded channels (<code>streams +
|
||||
* coupled_streams</code>) must be no
|
||||
* more than 255.
|
||||
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
|
||||
* coded channels to output channels, as described in
|
||||
* @ref opus_multistream.
|
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
|
||||
* on failure.
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_init(
|
||||
OpusMSDecoder *st,
|
||||
opus_int32 Fs,
|
||||
int channels,
|
||||
int streams,
|
||||
int coupled_streams,
|
||||
const unsigned char *mapping
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
|
||||
|
||||
/** Decode a multistream Opus packet.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
opus_int16 *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Decode a multistream Opus packet with floating point output.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
|
||||
* Use a <code>NULL</code>
|
||||
* pointer to indicate packet
|
||||
* loss.
|
||||
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
|
||||
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
|
||||
* samples.
|
||||
* This must contain room for
|
||||
* <code>frame_size*channels</code>
|
||||
* samples.
|
||||
* @param frame_size <tt>int</tt>: The number of samples per channel of
|
||||
* available space in \a pcm.
|
||||
* If this is less than the maximum packet duration
|
||||
* (120 ms; 5760 for 48kHz), this function will not be capable
|
||||
* of decoding some packets. In the case of PLC (data==NULL)
|
||||
* or FEC (decode_fec=1), then frame_size needs to be exactly
|
||||
* the duration of audio that is missing, otherwise the
|
||||
* decoder will not be in the optimal state to decode the
|
||||
* next incoming packet. For the PLC and FEC cases, frame_size
|
||||
* <b>must</b> be a multiple of 2.5 ms.
|
||||
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
|
||||
* forward error correction data be decoded.
|
||||
* If no such data is available, the frame is
|
||||
* decoded as if it were lost.
|
||||
* @returns Number of samples decoded on success or a negative error code
|
||||
* (see @ref opus_errorcodes) on failure.
|
||||
*/
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
|
||||
OpusMSDecoder *st,
|
||||
const unsigned char *data,
|
||||
opus_int32 len,
|
||||
float *pcm,
|
||||
int frame_size,
|
||||
int decode_fec
|
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
|
||||
|
||||
/** Perform a CTL function on a multistream Opus decoder.
|
||||
*
|
||||
* Generally the request and subsequent arguments are generated by a
|
||||
* convenience macro.
|
||||
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
|
||||
* @param request This and all remaining parameters should be replaced by one
|
||||
* of the convenience macros in @ref opus_genericctls,
|
||||
* @ref opus_decoderctls, or @ref opus_multistream_ctls.
|
||||
* @see opus_genericctls
|
||||
* @see opus_decoderctls
|
||||
* @see opus_multistream_ctls
|
||||
*/
|
||||
OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
|
||||
|
||||
/** Frees an <code>OpusMSDecoder</code> allocated by
|
||||
* opus_multistream_decoder_create().
|
||||
* @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
|
||||
*/
|
||||
OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_MULTISTREAM_H */
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
|
||||
/* Modified by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* opus_types.h based on ogg_types.h from libogg */
|
||||
|
||||
/**
|
||||
@file opus_types.h
|
||||
@brief Opus reference implementation types
|
||||
*/
|
||||
#ifndef OPUS_TYPES_H
|
||||
#define OPUS_TYPES_H
|
||||
|
||||
#define opus_int int /* used for counters etc; at least 16 bits */
|
||||
#define opus_int64 long long
|
||||
#define opus_int8 signed char
|
||||
|
||||
#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
|
||||
#define opus_uint64 unsigned long long
|
||||
#define opus_uint8 unsigned char
|
||||
|
||||
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
|
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
|
||||
#include <stdint.h>
|
||||
# undef opus_int64
|
||||
# undef opus_int8
|
||||
# undef opus_uint64
|
||||
# undef opus_uint8
|
||||
typedef int8_t opus_int8;
|
||||
typedef uint8_t opus_uint8;
|
||||
typedef int16_t opus_int16;
|
||||
typedef uint16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef uint32_t opus_uint32;
|
||||
typedef int64_t opus_int64;
|
||||
typedef uint64_t opus_uint64;
|
||||
#elif defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <_G_config.h>
|
||||
typedef _G_int32_t opus_int32;
|
||||
typedef _G_uint32_t opus_uint32;
|
||||
typedef _G_int16 opus_int16;
|
||||
typedef _G_uint16 opus_uint16;
|
||||
# elif defined(__MINGW32__)
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int32 opus_int32;
|
||||
typedef unsigned __int32 opus_uint32;
|
||||
typedef __int16 opus_int16;
|
||||
typedef unsigned __int16 opus_uint16;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 opus_int16;
|
||||
typedef UInt16 opus_uint16;
|
||||
typedef SInt32 opus_int32;
|
||||
typedef UInt32 opus_uint32;
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t opus_int16;
|
||||
typedef u_int16_t opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16 opus_int16;
|
||||
typedef u_int16 opus_uint16;
|
||||
typedef int32_t opus_int32;
|
||||
typedef u_int32_t opus_uint32;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef int opus_int32;
|
||||
typedef unsigned opus_uint32;
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef signed int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef long opus_int32;
|
||||
typedef unsigned long opus_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C6X)
|
||||
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#else
|
||||
|
||||
/* Give up, take a reasonable guess */
|
||||
typedef short opus_int16;
|
||||
typedef unsigned short opus_uint16;
|
||||
typedef int opus_int32;
|
||||
typedef unsigned int opus_uint32;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* OPUS_TYPES_H */
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/*Copyright (c) 2003-2004, Mark Borgerding
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
#ifndef KISS_FFT_GUTS_H
|
||||
#define KISS_FFT_GUTS_H
|
||||
|
||||
#define MIN(a,b) ((a)<(b) ? (a):(b))
|
||||
#define MAX(a,b) ((a)>(b) ? (a):(b))
|
||||
|
||||
/* kiss_fft.h
|
||||
defines kiss_fft_scalar as either short or a float type
|
||||
and defines
|
||||
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||
#include "kiss_fft.h"
|
||||
|
||||
/*
|
||||
Explanation of macros dealing with complex math:
|
||||
|
||||
C_MUL(m,a,b) : m = a*b
|
||||
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||
C_SUB( res, a,b) : res = a - b
|
||||
C_SUBFROM( res , a) : res -= a
|
||||
C_ADDTO( res , a) : res += a
|
||||
* */
|
||||
#ifdef FIXED_POINT
|
||||
#include "arch.h"
|
||||
|
||||
|
||||
#define SAMP_MAX 2147483647
|
||||
#define TWID_MAX 32767
|
||||
#define TRIG_UPSCALE 1
|
||||
|
||||
#define SAMP_MIN -SAMP_MAX
|
||||
|
||||
|
||||
# define S_MUL(a,b) MULT16_32_Q15(b, a)
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
|
||||
|
||||
# define C_MULC(m,a,b) \
|
||||
do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
|
||||
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r = S_MUL( (c).r , s ) ;\
|
||||
(c).i = S_MUL( (c).i , s ) ; }while(0)
|
||||
|
||||
# define DIVSCALAR(x,k) \
|
||||
(x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 )
|
||||
|
||||
# define C_FIXDIV(c,div) \
|
||||
do { DIVSCALAR( (c).r , div); \
|
||||
DIVSCALAR( (c).i , div); }while (0)
|
||||
|
||||
#define C_ADD( res, a,b)\
|
||||
do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
|
||||
}while(0)
|
||||
|
||||
#if defined(OPUS_ARM_INLINE_ASM)
|
||||
#include "arm/kiss_fft_armv4.h"
|
||||
#endif
|
||||
|
||||
#if defined(OPUS_ARM_INLINE_EDSP)
|
||||
#include "arm/kiss_fft_armv5e.h"
|
||||
#endif
|
||||
#if defined(MIPSr1_ASM)
|
||||
#include "mips/kiss_fft_mipsr1.h"
|
||||
#endif
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) )
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||
#define C_MULC(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
|
||||
(m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
|
||||
|
||||
#define C_MUL4(m,a,b) C_MUL(m,a,b)
|
||||
|
||||
# define C_FIXDIV(c,div) /* NOOP */
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r *= (s);\
|
||||
(c).i *= (s); }while(0)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK_OVERFLOW_OP
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||
#endif
|
||||
|
||||
#ifndef C_ADD
|
||||
#define C_ADD( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||
(res).r += (a).r; (res).i += (a).i;\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {\
|
||||
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||
(res).r -= (a).r; (res).i -= (a).i; \
|
||||
}while(0)
|
||||
#endif /* C_ADD defined */
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
/*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
|
||||
# define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
|
||||
# define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase))
|
||||
# define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase))
|
||||
# define HALF_OF(x) ((x)>>1)
|
||||
#elif defined(USE_SIMD)
|
||||
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
|
||||
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
|
||||
# define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
|
||||
#else
|
||||
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
|
||||
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
|
||||
# define HALF_OF(x) ((x)*.5f)
|
||||
#endif
|
||||
|
||||
#define kf_cexp(x,phase) \
|
||||
do{ \
|
||||
(x)->r = KISS_FFT_COS(phase);\
|
||||
(x)->i = KISS_FFT_SIN(phase);\
|
||||
}while(0)
|
||||
|
||||
#define kf_cexp2(x,phase) \
|
||||
do{ \
|
||||
(x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
|
||||
(x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
|
||||
}while(0)
|
||||
|
||||
#endif /* KISS_FFT_GUTS_H */
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
/* Copyright (c) 2003-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/**
|
||||
@file arch.h
|
||||
@brief Various architecture definitions for CELT
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
|
||||
# if !defined(__GNUC_PREREQ)
|
||||
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
|
||||
# define __GNUC_PREREQ(_maj,_min) \
|
||||
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
|
||||
# else
|
||||
# define __GNUC_PREREQ(_maj,_min) 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if OPUS_GNUC_PREREQ(3, 0)
|
||||
#define opus_likely(x) (__builtin_expect(!!(x), 1))
|
||||
#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
|
||||
#else
|
||||
#define opus_likely(x) (!!(x))
|
||||
#define opus_unlikely(x) (!!(x))
|
||||
#endif
|
||||
|
||||
#define CELT_SIG_SCALE 32768.f
|
||||
|
||||
#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__);
|
||||
|
||||
#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
void celt_fatal(const char *str, const char *file, int line);
|
||||
|
||||
#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn))
|
||||
#endif
|
||||
void celt_fatal(const char *str, const char *file, int line)
|
||||
{
|
||||
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
|
||||
#if defined(_MSC_VER)
|
||||
_set_abort_behavior( 0, _WRITE_ABORT_MSG);
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
|
||||
#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
|
||||
#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
|
||||
#else
|
||||
#define celt_assert(cond)
|
||||
#define celt_assert2(cond, message)
|
||||
#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_ASSERTIONS)
|
||||
#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
|
||||
#else
|
||||
#define celt_sig_assert(cond)
|
||||
#endif
|
||||
|
||||
#define IMUL32(a,b) ((a)*(b))
|
||||
|
||||
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */
|
||||
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
|
||||
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */
|
||||
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
|
||||
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
|
||||
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
|
||||
#define UADD32(a,b) ((a)+(b))
|
||||
#define USUB32(a,b) ((a)-(b))
|
||||
|
||||
/* Set this if opus_int64 is a native type of the CPU. */
|
||||
/* Assume that all LP64 architectures have fast 64-bit types; also x86_64
|
||||
(which can be ILP32 for x32) and Win64 (which is LLP64). */
|
||||
#if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64)
|
||||
#define OPUS_FAST_INT64 1
|
||||
#else
|
||||
#define OPUS_FAST_INT64 0
|
||||
#endif
|
||||
|
||||
#define PRINT_MIPS(file)
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
typedef opus_int16 opus_val16;
|
||||
typedef opus_int32 opus_val32;
|
||||
typedef opus_int64 opus_val64;
|
||||
|
||||
typedef opus_val32 celt_sig;
|
||||
typedef opus_val16 celt_norm;
|
||||
typedef opus_val32 celt_ener;
|
||||
|
||||
#define celt_isnan(x) 0
|
||||
|
||||
#define Q15ONE 32767
|
||||
|
||||
#define SIG_SHIFT 12
|
||||
/* Safe saturation value for 32-bit signals. Should be less than
|
||||
2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
|
||||
#define SIG_SAT (300000000)
|
||||
|
||||
#define NORM_SCALING 16384
|
||||
|
||||
#define DB_SHIFT 10
|
||||
|
||||
#define EPSILON 1
|
||||
#define VERY_SMALL 0
|
||||
#define VERY_LARGE16 ((opus_val16)32767)
|
||||
#define Q15_ONE ((opus_val16)32767)
|
||||
|
||||
#define SCALEIN(a) (a)
|
||||
#define SCALEOUT(a) (a)
|
||||
|
||||
#define ABS16(x) ((x) < 0 ? (-(x)) : (x))
|
||||
#define ABS32(x) ((x) < 0 ? (-(x)) : (x))
|
||||
|
||||
static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
|
||||
return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x;
|
||||
}
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
#include "fixed_debug.h"
|
||||
#else
|
||||
|
||||
#include "fixed_generic.h"
|
||||
|
||||
#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
|
||||
#include "arm/fixed_arm64.h"
|
||||
#elif defined (OPUS_ARM_INLINE_EDSP)
|
||||
#include "arm/fixed_armv5e.h"
|
||||
#elif defined (OPUS_ARM_INLINE_ASM)
|
||||
#include "arm/fixed_armv4.h"
|
||||
#elif defined (BFIN_ASM)
|
||||
#include "fixed_bfin.h"
|
||||
#elif defined (TI_C5X_ASM)
|
||||
#include "fixed_c5x.h"
|
||||
#elif defined (TI_C6X_ASM)
|
||||
#include "fixed_c6x.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#else /* FIXED_POINT */
|
||||
|
||||
typedef float opus_val16;
|
||||
typedef float opus_val32;
|
||||
typedef float opus_val64;
|
||||
|
||||
typedef float celt_sig;
|
||||
typedef float celt_norm;
|
||||
typedef float celt_ener;
|
||||
|
||||
#ifdef FLOAT_APPROX
|
||||
/* This code should reliably detect NaN/inf even when -ffast-math is used.
|
||||
Assumes IEEE 754 format. */
|
||||
static OPUS_INLINE int celt_isnan(float x)
|
||||
{
|
||||
union {float f; opus_uint32 i;} in;
|
||||
in.f = x;
|
||||
return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0;
|
||||
}
|
||||
#else
|
||||
#ifdef __FAST_MATH__
|
||||
#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input
|
||||
#endif
|
||||
#define celt_isnan(x) ((x)!=(x))
|
||||
#endif
|
||||
|
||||
#define Q15ONE 1.0f
|
||||
|
||||
#define NORM_SCALING 1.f
|
||||
|
||||
#define EPSILON 1e-15f
|
||||
#define VERY_SMALL 1e-30f
|
||||
#define VERY_LARGE16 1e15f
|
||||
#define Q15_ONE ((opus_val16)1.f)
|
||||
|
||||
/* This appears to be the same speed as C99's fabsf() but it's more portable. */
|
||||
#define ABS16(x) ((float)fabs(x))
|
||||
#define ABS32(x) ((float)fabs(x))
|
||||
|
||||
#define QCONST16(x,bits) (x)
|
||||
#define QCONST32(x,bits) (x)
|
||||
|
||||
#define NEG16(x) (-(x))
|
||||
#define NEG32(x) (-(x))
|
||||
#define NEG32_ovflw(x) (-(x))
|
||||
#define EXTRACT16(x) (x)
|
||||
#define EXTEND32(x) (x)
|
||||
#define SHR16(a,shift) (a)
|
||||
#define SHL16(a,shift) (a)
|
||||
#define SHR32(a,shift) (a)
|
||||
#define SHL32(a,shift) (a)
|
||||
#define PSHR32(a,shift) (a)
|
||||
#define VSHR32(a,shift) (a)
|
||||
|
||||
#define PSHR(a,shift) (a)
|
||||
#define SHR(a,shift) (a)
|
||||
#define SHL(a,shift) (a)
|
||||
#define SATURATE(x,a) (x)
|
||||
#define SATURATE16(x) (x)
|
||||
|
||||
#define ROUND16(a,shift) (a)
|
||||
#define SROUND16(a,shift) (a)
|
||||
#define HALF16(x) (.5f*(x))
|
||||
#define HALF32(x) (.5f*(x))
|
||||
|
||||
#define ADD16(a,b) ((a)+(b))
|
||||
#define SUB16(a,b) ((a)-(b))
|
||||
#define ADD32(a,b) ((a)+(b))
|
||||
#define SUB32(a,b) ((a)-(b))
|
||||
#define ADD32_ovflw(a,b) ((a)+(b))
|
||||
#define SUB32_ovflw(a,b) ((a)-(b))
|
||||
#define MULT16_16_16(a,b) ((a)*(b))
|
||||
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
|
||||
#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
|
||||
|
||||
#define MULT16_32_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q16(a,b) ((a)*(b))
|
||||
|
||||
#define MULT32_32_Q31(a,b) ((a)*(b))
|
||||
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_32_Q16(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MULT16_16_Q11_32(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q11(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q13(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q14(a,b) ((a)*(b))
|
||||
#define MULT16_16_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_16_P15(a,b) ((a)*(b))
|
||||
#define MULT16_16_P13(a,b) ((a)*(b))
|
||||
#define MULT16_16_P14(a,b) ((a)*(b))
|
||||
#define MULT16_32_P16(a,b) ((a)*(b))
|
||||
|
||||
#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b))
|
||||
#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b))
|
||||
|
||||
#define SCALEIN(a) ((a)*CELT_SIG_SCALE)
|
||||
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE))
|
||||
|
||||
#define SIG2WORD16(x) (x)
|
||||
|
||||
#endif /* !FIXED_POINT */
|
||||
|
||||
#ifndef GLOBAL_STACK_SIZE
|
||||
#ifdef FIXED_POINT
|
||||
#define GLOBAL_STACK_SIZE 120000
|
||||
#else
|
||||
#define GLOBAL_STACK_SIZE 120000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_H */
|
||||
353
Telegram/WatchApp/Packages/OpusKit/Sources/COpus/libopus/celt/arm/arm2gnu.pl
Executable file
353
Telegram/WatchApp/Packages/OpusKit/Sources/COpus/libopus/celt/arm/arm2gnu.pl
Executable file
|
|
@ -0,0 +1,353 @@
|
|||
#!/usr/bin/perl
|
||||
# Copyright (C) 2002-2013 Xiph.org Foundation
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
my $bigend; # little/big endian
|
||||
my $nxstack;
|
||||
my $apple = 0;
|
||||
my $symprefix = "";
|
||||
|
||||
$nxstack = 0;
|
||||
|
||||
eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
|
||||
if $running_under_some_shell;
|
||||
|
||||
while ($ARGV[0] =~ /^-/) {
|
||||
$_ = shift;
|
||||
last if /^--$/;
|
||||
if (/^-n$/) {
|
||||
$nflag++;
|
||||
next;
|
||||
}
|
||||
if (/^--apple$/) {
|
||||
$apple = 1;
|
||||
$symprefix = "_";
|
||||
next;
|
||||
}
|
||||
die "I don't recognize this switch: $_\\n";
|
||||
}
|
||||
$printit++ unless $nflag;
|
||||
|
||||
$\ = "\n"; # automatically add newline on print
|
||||
$n=0;
|
||||
|
||||
$thumb = 0; # ARM mode by default, not Thumb.
|
||||
@proc_stack = ();
|
||||
|
||||
printf (" .syntax unified\n");
|
||||
|
||||
LINE:
|
||||
while (<>) {
|
||||
|
||||
# For ADRLs we need to add a new line after the substituted one.
|
||||
$addPadding = 0;
|
||||
|
||||
# First, we do not dare to touch *anything* inside double quotes, do we?
|
||||
# Second, if you want a dollar character in the string,
|
||||
# insert two of them -- that's how ARM C and assembler treat strings.
|
||||
s/^([A-Za-z_]\w*)[ \t]+DCB[ \t]*\"/$1: .ascii \"/ && do { s/\$\$/\$/g; next };
|
||||
s/\bDCB\b[ \t]*\"/.ascii \"/ && do { s/\$\$/\$/g; next };
|
||||
s/^(\S+)\s+RN\s+(\S+)/$1 .req r$2/ && do { s/\$\$/\$/g; next };
|
||||
# If there's nothing on a line but a comment, don't try to apply any further
|
||||
# substitutions (this is a cheap hack to avoid mucking up the license header)
|
||||
s/^([ \t]*);/$1@/ && do { s/\$\$/\$/g; next };
|
||||
# If substituted -- leave immediately !
|
||||
|
||||
s/@/,:/;
|
||||
s/;/@/;
|
||||
while ( /@.*'/ ) {
|
||||
s/(@.*)'/$1/g;
|
||||
}
|
||||
s/\{FALSE\}/0/g;
|
||||
s/\{TRUE\}/1/g;
|
||||
s/\{(\w\w\w\w+)\}/$1/g;
|
||||
s/\bINCLUDE[ \t]*([^ \t\n]+)/.include \"$1\"/;
|
||||
s/\bGET[ \t]*([^ \t\n]+)/.include \"${ my $x=$1; $x =~ s|\.s|-gnu.S|; \$x }\"/;
|
||||
s/\bIMPORT\b/.extern/;
|
||||
s/\bEXPORT\b\s*/.global $symprefix/;
|
||||
s/^(\s+)\[/$1IF/;
|
||||
s/^(\s+)\|/$1ELSE/;
|
||||
s/^(\s+)\]/$1ENDIF/;
|
||||
s/IF *:DEF:/ .ifdef/;
|
||||
s/IF *:LNOT: *:DEF:/ .ifndef/;
|
||||
s/ELSE/ .else/;
|
||||
s/ENDIF/ .endif/;
|
||||
|
||||
if( /\bIF\b/ ) {
|
||||
s/\bIF\b/ .if/;
|
||||
s/=/==/;
|
||||
}
|
||||
if ( $n == 2) {
|
||||
s/\$/\\/g;
|
||||
}
|
||||
if ($n == 1) {
|
||||
s/\$//g;
|
||||
s/label//g;
|
||||
$n = 2;
|
||||
}
|
||||
if ( /MACRO/ ) {
|
||||
s/MACRO *\n/.macro/;
|
||||
$n=1;
|
||||
}
|
||||
if ( /\bMEND\b/ ) {
|
||||
s/\bMEND\b/.endm/;
|
||||
$n=0;
|
||||
}
|
||||
|
||||
# ".rdata" doesn't work in 'as' version 2.13.2, as it is ".rodata" there.
|
||||
#
|
||||
if ( /\bAREA\b/ ) {
|
||||
my $align;
|
||||
$align = "2";
|
||||
if ( /ALIGN=(\d+)/ ) {
|
||||
$align = $1;
|
||||
}
|
||||
if ( /CODE/ ) {
|
||||
$nxstack = 1;
|
||||
}
|
||||
s/^(.+)CODE(.+)READONLY(.*)/ .text/;
|
||||
s/^(.+)DATA(.+)READONLY(.*)/ .section .rdata/;
|
||||
s/^(.+)\|\|\.data\|\|(.+)/ .data/;
|
||||
s/^(.+)\|\|\.bss\|\|(.+)/ .bss/;
|
||||
s/$/; .p2align $align/;
|
||||
# Enable NEON instructions but don't produce a binary that requires
|
||||
# ARMv7. RVCT does not have equivalent directives, so we just do this
|
||||
# for all CODE areas.
|
||||
if ( /.text/ ) {
|
||||
# Separating .arch, .fpu, etc., by semicolons does not work (gas
|
||||
# thinks the semicolon is part of the arch name, even when there's
|
||||
# whitespace separating them). Sadly this means our line numbers
|
||||
# won't match the original source file (we could use the .line
|
||||
# directive, which is documented to be obsolete, but then gdb will
|
||||
# show the wrong line in the translated source file).
|
||||
s/$/; .arch armv7-a\n .fpu neon\n .object_arch armv4t/ unless ($apple);
|
||||
}
|
||||
}
|
||||
|
||||
s/\|\|\.constdata\$(\d+)\|\|/.L_CONST$1/; # ||.constdata$3||
|
||||
s/\|\|\.bss\$(\d+)\|\|/.L_BSS$1/; # ||.bss$2||
|
||||
s/\|\|\.data\$(\d+)\|\|/.L_DATA$1/; # ||.data$2||
|
||||
s/\|\|([a-zA-Z0-9_]+)\@([a-zA-Z0-9_]+)\|\|/@ $&/;
|
||||
s/^(\s+)\%(\s)/ .space $1/;
|
||||
|
||||
s/\|(.+)\.(\d+)\|/\.$1_$2/; # |L80.123| -> .L80_123
|
||||
s/\bCODE32\b/.code 32/ && do {$thumb = 0};
|
||||
s/\bCODE16\b/.code 16/ && do {$thumb = 1};
|
||||
if (/\bPROC\b/)
|
||||
{
|
||||
my $prefix;
|
||||
my $proc;
|
||||
/^([A-Za-z_\.]\w+)\b/;
|
||||
$proc = $1;
|
||||
$prefix = "";
|
||||
if ($proc)
|
||||
{
|
||||
$prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple);
|
||||
# Make sure we $prefix isn't empty here (for the $apple case).
|
||||
# We handle mangling the label here, make sure it doesn't match
|
||||
# the label handling below (if $prefix would be empty).
|
||||
$prefix = $prefix."; ";
|
||||
push(@proc_stack, $proc);
|
||||
s/^[A-Za-z_\.]\w+/$symprefix$&:/;
|
||||
}
|
||||
$prefix = $prefix."\t.thumb_func; " if ($thumb);
|
||||
s/\bPROC\b/@ $&/;
|
||||
$_ = $prefix.$_;
|
||||
}
|
||||
s/^(\s*)(S|Q|SH|U|UQ|UH)ASX\b/$1$2ADDSUBX/;
|
||||
s/^(\s*)(S|Q|SH|U|UQ|UH)SAX\b/$1$2SUBADDX/;
|
||||
if (/\bENDP\b/)
|
||||
{
|
||||
my $proc;
|
||||
s/\bENDP\b/@ $&/;
|
||||
$proc = pop(@proc_stack);
|
||||
$_ = "\t.size $proc, .-$proc".$_ if ($proc && !$apple);
|
||||
}
|
||||
s/\bSUBT\b/@ $&/;
|
||||
s/\bDATA\b/@ $&/; # DATA directive is deprecated -- Asm guide, p.7-25
|
||||
s/\bKEEP\b/@ $&/;
|
||||
s/\bEXPORTAS\b/@ $&/;
|
||||
s/\|\|(.)+\bEQU\b/@ $&/;
|
||||
s/\|\|([\w\$]+)\|\|/$1/;
|
||||
s/\bENTRY\b/@ $&/;
|
||||
s/\bASSERT\b/@ $&/;
|
||||
s/\bGBLL\b/@ $&/;
|
||||
s/\bGBLA\b/@ $&/;
|
||||
s/^\W+OPT\b/@ $&/;
|
||||
s/:OR:/|/g;
|
||||
s/:SHL:/<</g;
|
||||
s/:SHR:/>>/g;
|
||||
s/:AND:/&/g;
|
||||
s/:LAND:/&&/g;
|
||||
s/CPSR/cpsr/;
|
||||
s/SPSR/spsr/;
|
||||
s/ALIGN$/.balign 4/;
|
||||
s/ALIGN\s+([0-9x]+)$/.balign $1/;
|
||||
s/psr_cxsf/psr_all/;
|
||||
s/LTORG/.ltorg/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+EQU/ .set $1,/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+SETL/ .set $1,/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+SETA/ .set $1,/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+\*/ .set $1,/;
|
||||
|
||||
# {PC} + 0xdeadfeed --> . + 0xdeadfeed
|
||||
s/\{PC\} \+/ \. +/;
|
||||
|
||||
# Single hex constant on the line !
|
||||
#
|
||||
# >>> NOTE <<<
|
||||
# Double-precision floats in gcc are always mixed-endian, which means
|
||||
# bytes in two words are little-endian, but words are big-endian.
|
||||
# So, 0x0000deadfeed0000 would be stored as 0x0000dead at low address
|
||||
# and 0xfeed0000 at high address.
|
||||
#
|
||||
s/\bDCFD\b[ \t]+0x([a-fA-F0-9]{8})([a-fA-F0-9]{8})/.long 0x$1, 0x$2/;
|
||||
# Only decimal constants on the line, no hex !
|
||||
s/\bDCFD\b[ \t]+([0-9\.\-]+)/.double $1/;
|
||||
|
||||
# Single hex constant on the line !
|
||||
# s/\bDCFS\b[ \t]+0x([a-f0-9]{8})([a-f0-9]{8})/.long 0x$1, 0x$2/;
|
||||
# Only decimal constants on the line, no hex !
|
||||
# s/\bDCFS\b[ \t]+([0-9\.\-]+)/.double $1/;
|
||||
s/\bDCFS[ \t]+0x/.word 0x/;
|
||||
s/\bDCFS\b/.float/;
|
||||
|
||||
s/^([A-Za-z_]\w*)[ \t]+DCD/$1 .word/;
|
||||
s/\bDCD\b/.word/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+DCW/$1 .short/;
|
||||
s/\bDCW\b/.short/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+DCB/$1 .byte/;
|
||||
s/\bDCB\b/.byte/;
|
||||
s/^([A-Za-z_]\w*)[ \t]+\%/.comm $1,/;
|
||||
s/^[A-Za-z_\.]\w+/$&:/;
|
||||
s/^(\d+)/$1:/;
|
||||
s/\%(\d+)/$1b_or_f/;
|
||||
s/\%[Bb](\d+)/$1b/;
|
||||
s/\%[Ff](\d+)/$1f/;
|
||||
s/\%[Ff][Tt](\d+)/$1f/;
|
||||
s/&([\dA-Fa-f]+)/0x$1/;
|
||||
if ( /\b2_[01]+\b/ ) {
|
||||
s/\b2_([01]+)\b/conv$1&&&&/g;
|
||||
while ( /[01][01][01][01]&&&&/ ) {
|
||||
s/0000&&&&/&&&&0/g;
|
||||
s/0001&&&&/&&&&1/g;
|
||||
s/0010&&&&/&&&&2/g;
|
||||
s/0011&&&&/&&&&3/g;
|
||||
s/0100&&&&/&&&&4/g;
|
||||
s/0101&&&&/&&&&5/g;
|
||||
s/0110&&&&/&&&&6/g;
|
||||
s/0111&&&&/&&&&7/g;
|
||||
s/1000&&&&/&&&&8/g;
|
||||
s/1001&&&&/&&&&9/g;
|
||||
s/1010&&&&/&&&&A/g;
|
||||
s/1011&&&&/&&&&B/g;
|
||||
s/1100&&&&/&&&&C/g;
|
||||
s/1101&&&&/&&&&D/g;
|
||||
s/1110&&&&/&&&&E/g;
|
||||
s/1111&&&&/&&&&F/g;
|
||||
}
|
||||
s/000&&&&/&&&&0/g;
|
||||
s/001&&&&/&&&&1/g;
|
||||
s/010&&&&/&&&&2/g;
|
||||
s/011&&&&/&&&&3/g;
|
||||
s/100&&&&/&&&&4/g;
|
||||
s/101&&&&/&&&&5/g;
|
||||
s/110&&&&/&&&&6/g;
|
||||
s/111&&&&/&&&&7/g;
|
||||
s/00&&&&/&&&&0/g;
|
||||
s/01&&&&/&&&&1/g;
|
||||
s/10&&&&/&&&&2/g;
|
||||
s/11&&&&/&&&&3/g;
|
||||
s/0&&&&/&&&&0/g;
|
||||
s/1&&&&/&&&&1/g;
|
||||
s/conv&&&&/0x/g;
|
||||
}
|
||||
|
||||
if ( /commandline/)
|
||||
{
|
||||
if( /-bigend/)
|
||||
{
|
||||
$bigend=1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( /\bDCDU\b/ )
|
||||
{
|
||||
my $cmd=$_;
|
||||
my $value;
|
||||
my $prefix;
|
||||
my $w1;
|
||||
my $w2;
|
||||
my $w3;
|
||||
my $w4;
|
||||
|
||||
s/\s+DCDU\b/@ $&/;
|
||||
|
||||
$cmd =~ /\bDCDU\b\s+0x(\d+)/;
|
||||
$value = $1;
|
||||
$value =~ /(\w\w)(\w\w)(\w\w)(\w\w)/;
|
||||
$w1 = $1;
|
||||
$w2 = $2;
|
||||
$w3 = $3;
|
||||
$w4 = $4;
|
||||
|
||||
if( $bigend ne "")
|
||||
{
|
||||
# big endian
|
||||
$prefix = "\t.byte\t0x".$w1.";".
|
||||
"\t.byte\t0x".$w2.";".
|
||||
"\t.byte\t0x".$w3.";".
|
||||
"\t.byte\t0x".$w4."; ";
|
||||
}
|
||||
else
|
||||
{
|
||||
# little endian
|
||||
$prefix = "\t.byte\t0x".$w4.";".
|
||||
"\t.byte\t0x".$w3.";".
|
||||
"\t.byte\t0x".$w2.";".
|
||||
"\t.byte\t0x".$w1."; ";
|
||||
}
|
||||
$_=$prefix.$_;
|
||||
}
|
||||
|
||||
if ( /\badrl\b/i )
|
||||
{
|
||||
s/\badrl\s+(\w+)\s*,\s*(\w+)/ldr $1,=$2/i;
|
||||
$addPadding = 1;
|
||||
}
|
||||
s/\bEND\b/@ END/;
|
||||
} continue {
|
||||
printf ("%s", $_) if $printit;
|
||||
if ($addPadding != 0)
|
||||
{
|
||||
printf (" mov r0,r0\n");
|
||||
$addPadding = 0;
|
||||
}
|
||||
}
|
||||
#If we had a code section, mark that this object doesn't need an executable
|
||||
# stack.
|
||||
if ($nxstack && !$apple) {
|
||||
printf (" .section\t.note.GNU-stack,\"\",\%\%progbits\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pitch.h"
|
||||
#include "kiss_fft.h"
|
||||
#include "mdct.h"
|
||||
|
||||
#if defined(OPUS_HAVE_RTCD)
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = {
|
||||
celt_inner_prod_c, /* ARMv4 */
|
||||
celt_inner_prod_c, /* EDSP */
|
||||
celt_inner_prod_c, /* Media */
|
||||
celt_inner_prod_neon,/* NEON */
|
||||
celt_inner_prod_neon /* DOTPROD */
|
||||
};
|
||||
|
||||
void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
|
||||
int N, opus_val32 *xy1, opus_val32 *xy2) = {
|
||||
dual_inner_prod_c, /* ARMv4 */
|
||||
dual_inner_prod_c, /* EDSP */
|
||||
dual_inner_prod_c, /* Media */
|
||||
dual_inner_prod_neon,/* NEON */
|
||||
dual_inner_prod_neon /* DOTPROD */
|
||||
};
|
||||
# endif
|
||||
|
||||
# if defined(FIXED_POINT)
|
||||
# if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
|
||||
(defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
|
||||
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
|
||||
opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
|
||||
const opus_val16 *, opus_val32 *, int, int, int) = {
|
||||
celt_pitch_xcorr_c, /* ARMv4 */
|
||||
MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */
|
||||
MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */
|
||||
MAY_HAVE_NEON(celt_pitch_xcorr), /* NEON */
|
||||
MAY_HAVE_NEON(celt_pitch_xcorr) /* DOTPROD */
|
||||
};
|
||||
|
||||
# endif
|
||||
# else /* !FIXED_POINT */
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
|
||||
const opus_val16 *, opus_val32 *, int, int, int) = {
|
||||
celt_pitch_xcorr_c, /* ARMv4 */
|
||||
celt_pitch_xcorr_c, /* EDSP */
|
||||
celt_pitch_xcorr_c, /* Media */
|
||||
celt_pitch_xcorr_float_neon, /* Neon */
|
||||
celt_pitch_xcorr_float_neon /* DOTPROD */
|
||||
};
|
||||
# endif
|
||||
# endif /* FIXED_POINT */
|
||||
|
||||
#if defined(FIXED_POINT) && defined(OPUS_HAVE_RTCD) && \
|
||||
defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
|
||||
void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
|
||||
const opus_val16 *x,
|
||||
const opus_val16 *y,
|
||||
opus_val32 sum[4],
|
||||
int len
|
||||
) = {
|
||||
xcorr_kernel_c, /* ARMv4 */
|
||||
xcorr_kernel_c, /* EDSP */
|
||||
xcorr_kernel_c, /* Media */
|
||||
xcorr_kernel_neon_fixed, /* Neon */
|
||||
xcorr_kernel_neon_fixed /* DOTPROD */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
# if defined(HAVE_ARM_NE10)
|
||||
# if defined(CUSTOM_MODES)
|
||||
int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = {
|
||||
opus_fft_alloc_arch_c, /* ARMv4 */
|
||||
opus_fft_alloc_arch_c, /* EDSP */
|
||||
opus_fft_alloc_arch_c, /* Media */
|
||||
opus_fft_alloc_arm_neon, /* Neon with NE10 library support */
|
||||
opus_fft_alloc_arm_neon /* DOTPROD with NE10 library support */
|
||||
};
|
||||
|
||||
void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = {
|
||||
opus_fft_free_arch_c, /* ARMv4 */
|
||||
opus_fft_free_arch_c, /* EDSP */
|
||||
opus_fft_free_arch_c, /* Media */
|
||||
opus_fft_free_arm_neon, /* Neon with NE10 */
|
||||
opus_fft_free_arm_neon /* DOTPROD with NE10 */
|
||||
};
|
||||
# endif /* CUSTOM_MODES */
|
||||
|
||||
void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout) = {
|
||||
opus_fft_c, /* ARMv4 */
|
||||
opus_fft_c, /* EDSP */
|
||||
opus_fft_c, /* Media */
|
||||
opus_fft_neon, /* Neon with NE10 */
|
||||
opus_fft_neon /* DOTPROD with NE10 */
|
||||
};
|
||||
|
||||
void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout) = {
|
||||
opus_ifft_c, /* ARMv4 */
|
||||
opus_ifft_c, /* EDSP */
|
||||
opus_ifft_c, /* Media */
|
||||
opus_ifft_neon, /* Neon with NE10 */
|
||||
opus_ifft_neon /* DOTPROD with NE10 */
|
||||
};
|
||||
|
||||
void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l,
|
||||
kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window,
|
||||
int overlap, int shift,
|
||||
int stride, int arch) = {
|
||||
clt_mdct_forward_c, /* ARMv4 */
|
||||
clt_mdct_forward_c, /* EDSP */
|
||||
clt_mdct_forward_c, /* Media */
|
||||
clt_mdct_forward_neon, /* Neon with NE10 */
|
||||
clt_mdct_forward_neon /* DOTPROD with NE10 */
|
||||
};
|
||||
|
||||
void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l,
|
||||
kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window,
|
||||
int overlap, int shift,
|
||||
int stride, int arch) = {
|
||||
clt_mdct_backward_c, /* ARMv4 */
|
||||
clt_mdct_backward_c, /* EDSP */
|
||||
clt_mdct_backward_c, /* Media */
|
||||
clt_mdct_backward_neon, /* Neon with NE10 */
|
||||
clt_mdct_backward_neon /* DOTPROD with NE10 */
|
||||
};
|
||||
|
||||
# endif /* HAVE_ARM_NE10 */
|
||||
# endif /* OPUS_ARM_MAY_HAVE_NEON_INTR */
|
||||
|
||||
#endif /* OPUS_HAVE_RTCD */
|
||||
|
|
@ -0,0 +1,291 @@
|
|||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Original code from libtheora modified to suit to Opus */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef OPUS_HAVE_RTCD
|
||||
|
||||
#include "armcpu.h"
|
||||
#include "cpu_support.h"
|
||||
#include "os_support.h"
|
||||
#include "opus_types.h"
|
||||
#include "arch.h"
|
||||
|
||||
#define OPUS_CPU_ARM_V4_FLAG (1<<OPUS_ARCH_ARM_V4)
|
||||
#define OPUS_CPU_ARM_EDSP_FLAG (1<<OPUS_ARCH_ARM_EDSP)
|
||||
#define OPUS_CPU_ARM_MEDIA_FLAG (1<<OPUS_ARCH_ARM_MEDIA)
|
||||
#define OPUS_CPU_ARM_NEON_FLAG (1<<OPUS_ARCH_ARM_NEON)
|
||||
#define OPUS_CPU_ARM_DOTPROD_FLAG (1<<OPUS_ARCH_ARM_DOTPROD)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_EXTRA_LEAN
|
||||
# include <windows.h>
|
||||
|
||||
static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){
|
||||
opus_uint32 flags;
|
||||
flags=0;
|
||||
/* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit
|
||||
* instructions via their assembled hex code.
|
||||
* All of these instructions should be essentially nops. */
|
||||
# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
__try{
|
||||
/*PLD [r13]*/
|
||||
__emit(0xF5DDF000);
|
||||
flags|=OPUS_CPU_ARM_EDSP_FLAG;
|
||||
}
|
||||
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
|
||||
/*Ignore exception.*/
|
||||
}
|
||||
# if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
__try{
|
||||
/*SHADD8 r3,r3,r3*/
|
||||
__emit(0xE6333F93);
|
||||
flags|=OPUS_CPU_ARM_MEDIA_FLAG;
|
||||
}
|
||||
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
|
||||
/*Ignore exception.*/
|
||||
}
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
__try{
|
||||
/*VORR q0,q0,q0*/
|
||||
__emit(0xF2200150);
|
||||
flags|=OPUS_CPU_ARM_NEON_FLAG;
|
||||
}
|
||||
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
|
||||
/*Ignore exception.*/
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
/* Linux based */
|
||||
#include <stdio.h>
|
||||
|
||||
static opus_uint32 opus_cpu_capabilities(void)
|
||||
{
|
||||
opus_uint32 flags = 0;
|
||||
FILE *cpuinfo;
|
||||
|
||||
/* Reading /proc/self/auxv would be easier, but that doesn't work reliably on
|
||||
* Android */
|
||||
cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
|
||||
if(cpuinfo != NULL)
|
||||
{
|
||||
/* 512 should be enough for anybody (it's even enough for all the flags that
|
||||
* x86 has accumulated... so far). */
|
||||
char buf[512];
|
||||
|
||||
while(fgets(buf, 512, cpuinfo) != NULL)
|
||||
{
|
||||
# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
/* Search for edsp and neon flag */
|
||||
if(memcmp(buf, "Features", 8) == 0)
|
||||
{
|
||||
char *p;
|
||||
p = strstr(buf, " edsp");
|
||||
if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
|
||||
flags |= OPUS_CPU_ARM_EDSP_FLAG;
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
p = strstr(buf, " neon");
|
||||
if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
|
||||
flags |= OPUS_CPU_ARM_NEON_FLAG;
|
||||
p = strstr(buf, " asimd");
|
||||
if(p != NULL && (p[6] == ' ' || p[6] == '\n'))
|
||||
flags |= OPUS_CPU_ARM_NEON_FLAG | OPUS_CPU_ARM_MEDIA_FLAG | OPUS_CPU_ARM_EDSP_FLAG;
|
||||
# endif
|
||||
# if defined(OPUS_ARM_MAY_HAVE_DOTPROD)
|
||||
p = strstr(buf, " asimddp");
|
||||
if(p != NULL && (p[8] == ' ' || p[8] == '\n'))
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
# endif
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
/* Search for media capabilities (>= ARMv6) */
|
||||
if(memcmp(buf, "CPU architecture:", 17) == 0)
|
||||
{
|
||||
int version;
|
||||
version = atoi(buf+17);
|
||||
|
||||
if(version >= 6)
|
||||
flags |= OPUS_CPU_ARM_MEDIA_FLAG;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
#if defined(OPUS_ARM_PRESUME_AARCH64_NEON_INTR)
|
||||
flags |= OPUS_CPU_ARM_EDSP_FLAG | OPUS_CPU_ARM_MEDIA_FLAG | OPUS_CPU_ARM_NEON_FLAG;
|
||||
# if defined(OPUS_ARM_PRESUME_DOTPROD)
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
fclose(cpuinfo);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
static opus_uint32 opus_cpu_capabilities(void)
|
||||
{
|
||||
opus_uint32 flags = 0;
|
||||
|
||||
#if defined(OPUS_ARM_MAY_HAVE_DOTPROD)
|
||||
size_t size = sizeof(uint32_t);
|
||||
uint32_t value = 0;
|
||||
if (!sysctlbyname("hw.optional.arm.FEAT_DotProd", &value, &size, NULL, 0) && value)
|
||||
{
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OPUS_ARM_PRESUME_AARCH64_NEON_INTR)
|
||||
flags |= OPUS_CPU_ARM_EDSP_FLAG | OPUS_CPU_ARM_MEDIA_FLAG | OPUS_CPU_ARM_NEON_FLAG;
|
||||
# if defined(OPUS_ARM_PRESUME_DOTPROD)
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/auxv.h>
|
||||
|
||||
static opus_uint32 opus_cpu_capabilities(void)
|
||||
{
|
||||
long hwcap = 0;
|
||||
opus_uint32 flags = 0;
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
/* FreeBSD requires armv6+, which always supports media instructions */
|
||||
flags |= OPUS_CPU_ARM_MEDIA_FLAG;
|
||||
# endif
|
||||
|
||||
elf_aux_info(AT_HWCAP, &hwcap, sizeof hwcap);
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|
||||
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
# ifdef HWCAP_EDSP
|
||||
if (hwcap & HWCAP_EDSP)
|
||||
flags |= OPUS_CPU_ARM_EDSP_FLAG;
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
# ifdef HWCAP_NEON
|
||||
if (hwcap & HWCAP_NEON)
|
||||
flags |= OPUS_CPU_ARM_NEON_FLAG;
|
||||
# elif defined(HWCAP_ASIMD)
|
||||
if (hwcap & HWCAP_ASIMD)
|
||||
flags |= OPUS_CPU_ARM_NEON_FLAG | OPUS_CPU_ARM_MEDIA_FLAG | OPUS_CPU_ARM_EDSP_FLAG;
|
||||
# endif
|
||||
# endif
|
||||
# if defined(OPUS_ARM_MAY_HAVE_DOTPROD) && defined(HWCAP_ASIMDDP)
|
||||
if (hwcap & HWCAP_ASIMDDP)
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#if defined(OPUS_ARM_PRESUME_AARCH64_NEON_INTR)
|
||||
flags |= OPUS_CPU_ARM_EDSP_FLAG | OPUS_CPU_ARM_MEDIA_FLAG | OPUS_CPU_ARM_NEON_FLAG;
|
||||
# if defined(OPUS_ARM_PRESUME_DOTPROD)
|
||||
flags |= OPUS_CPU_ARM_DOTPROD_FLAG;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
return (flags);
|
||||
}
|
||||
|
||||
#else
|
||||
/* The feature registers which can tell us what the processor supports are
|
||||
* accessible in priveleged modes only, so we can't have a general user-space
|
||||
* detection method like on x86.*/
|
||||
# error "Configured to use ARM asm but no CPU detection method available for " \
|
||||
"your platform. Reconfigure with --disable-rtcd (or send patches)."
|
||||
#endif
|
||||
|
||||
static int opus_select_arch_impl(void)
|
||||
{
|
||||
opus_uint32 flags = opus_cpu_capabilities();
|
||||
int arch = 0;
|
||||
|
||||
if(!(flags & OPUS_CPU_ARM_EDSP_FLAG)) {
|
||||
/* Asserts ensure arch values are sequential */
|
||||
celt_assert(arch == OPUS_ARCH_ARM_V4);
|
||||
return arch;
|
||||
}
|
||||
arch++;
|
||||
|
||||
if(!(flags & OPUS_CPU_ARM_MEDIA_FLAG)) {
|
||||
celt_assert(arch == OPUS_ARCH_ARM_EDSP);
|
||||
return arch;
|
||||
}
|
||||
arch++;
|
||||
|
||||
if(!(flags & OPUS_CPU_ARM_NEON_FLAG)) {
|
||||
celt_assert(arch == OPUS_ARCH_ARM_MEDIA);
|
||||
return arch;
|
||||
}
|
||||
arch++;
|
||||
|
||||
if(!(flags & OPUS_CPU_ARM_DOTPROD_FLAG)) {
|
||||
celt_assert(arch == OPUS_ARCH_ARM_NEON);
|
||||
return arch;
|
||||
}
|
||||
arch++;
|
||||
|
||||
celt_assert(arch == OPUS_ARCH_ARM_DOTPROD);
|
||||
return arch;
|
||||
}
|
||||
|
||||
int opus_select_arch(void) {
|
||||
int arch = opus_select_arch_impl();
|
||||
#ifdef FUZZING
|
||||
arch = rand()%(arch+1);
|
||||
#endif
|
||||
return arch;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(ARMCPU_H)
|
||||
# define ARMCPU_H
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_EDSP)
|
||||
# define MAY_HAVE_EDSP(name) name ## _edsp
|
||||
# else
|
||||
# define MAY_HAVE_EDSP(name) name ## _c
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_MEDIA)
|
||||
# define MAY_HAVE_MEDIA(name) name ## _media
|
||||
# else
|
||||
# define MAY_HAVE_MEDIA(name) MAY_HAVE_EDSP(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON)
|
||||
# define MAY_HAVE_NEON(name) name ## _neon
|
||||
# else
|
||||
# define MAY_HAVE_NEON(name) MAY_HAVE_MEDIA(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_DOTPROD)
|
||||
# define MAY_HAVE_DOTPROD(name) name ## _dotprod
|
||||
# else
|
||||
# define MAY_HAVE_DOTPROD(name) MAY_HAVE_NEON(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_PRESUME_EDSP)
|
||||
# define PRESUME_EDSP(name) name ## _edsp
|
||||
# else
|
||||
# define PRESUME_EDSP(name) name ## _c
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_PRESUME_MEDIA)
|
||||
# define PRESUME_MEDIA(name) name ## _media
|
||||
# else
|
||||
# define PRESUME_MEDIA(name) PRESUME_EDSP(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define PRESUME_NEON(name) name ## _neon
|
||||
# else
|
||||
# define PRESUME_NEON(name) PRESUME_MEDIA(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_PRESUME_DOTPROD)
|
||||
# define PRESUME_DOTPROD(name) name ## _dotprod
|
||||
# else
|
||||
# define PRESUME_DOTPROD(name) PRESUME_NEON(name)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_HAVE_RTCD)
|
||||
int opus_select_arch(void);
|
||||
|
||||
#define OPUS_ARCH_ARM_V4 (0)
|
||||
#define OPUS_ARCH_ARM_EDSP (1)
|
||||
#define OPUS_ARCH_ARM_MEDIA (2)
|
||||
#define OPUS_ARCH_ARM_NEON (3)
|
||||
#define OPUS_ARCH_ARM_DOTPROD (4)
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* Copyright (C) 2013 Mozilla Corporation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
; Set the following to 1 if we have EDSP instructions
|
||||
; (LDRD/STRD, etc., ARMv5E and later).
|
||||
OPUS_ARM_MAY_HAVE_EDSP * @OPUS_ARM_MAY_HAVE_EDSP@
|
||||
|
||||
; Set the following to 1 if we have ARMv6 media instructions.
|
||||
OPUS_ARM_MAY_HAVE_MEDIA * @OPUS_ARM_MAY_HAVE_MEDIA@
|
||||
|
||||
; Set the following to 1 if we have NEON (some ARMv7)
|
||||
OPUS_ARM_MAY_HAVE_NEON * @OPUS_ARM_MAY_HAVE_NEON@
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/* Copyright (c) 2015 Xiph.Org Foundation
|
||||
Written by Viswanath Puttagunta */
|
||||
/**
|
||||
@file celt_fft_ne10.c
|
||||
@brief ARM Neon optimizations for fft using NE10 library
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SKIP_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <NE10_dsp.h>
|
||||
#include "os_support.h"
|
||||
#include "kiss_fft.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
#if !defined(FIXED_POINT)
|
||||
# define NE10_FFT_ALLOC_C2C_TYPE_NEON ne10_fft_alloc_c2c_float32_neon
|
||||
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t
|
||||
# define NE10_FFT_STATE_TYPE_T ne10_fft_state_float32_t
|
||||
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_float32
|
||||
# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_float32_t
|
||||
# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_float32_neon
|
||||
#else
|
||||
# define NE10_FFT_ALLOC_C2C_TYPE_NEON(nfft) ne10_fft_alloc_c2c_int32_neon(nfft)
|
||||
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_int32_t
|
||||
# define NE10_FFT_STATE_TYPE_T ne10_fft_state_int32_t
|
||||
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32
|
||||
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32
|
||||
# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_int32_t
|
||||
# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_int32_neon
|
||||
#endif
|
||||
|
||||
#if defined(CUSTOM_MODES)
|
||||
|
||||
/* nfft lengths in NE10 that support scaled fft */
|
||||
# define NE10_FFTSCALED_SUPPORT_MAX 4
|
||||
static const int ne10_fft_scaled_support[NE10_FFTSCALED_SUPPORT_MAX] = {
|
||||
480, 240, 120, 60
|
||||
};
|
||||
|
||||
int opus_fft_alloc_arm_neon(kiss_fft_state *st)
|
||||
{
|
||||
int i;
|
||||
size_t memneeded = sizeof(struct arch_fft_state);
|
||||
|
||||
st->arch_fft = (arch_fft_state *)opus_alloc(memneeded);
|
||||
if (!st->arch_fft)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < NE10_FFTSCALED_SUPPORT_MAX; i++) {
|
||||
if(st->nfft == ne10_fft_scaled_support[i])
|
||||
break;
|
||||
}
|
||||
if (i == NE10_FFTSCALED_SUPPORT_MAX) {
|
||||
/* This nfft length (scaled fft) is not supported in NE10 */
|
||||
st->arch_fft->is_supported = 0;
|
||||
st->arch_fft->priv = NULL;
|
||||
}
|
||||
else {
|
||||
st->arch_fft->is_supported = 1;
|
||||
st->arch_fft->priv = (void *)NE10_FFT_ALLOC_C2C_TYPE_NEON(st->nfft);
|
||||
if (st->arch_fft->priv == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void opus_fft_free_arm_neon(kiss_fft_state *st)
|
||||
{
|
||||
NE10_FFT_CFG_TYPE_T cfg;
|
||||
|
||||
if (!st->arch_fft)
|
||||
return;
|
||||
|
||||
cfg = (NE10_FFT_CFG_TYPE_T)st->arch_fft->priv;
|
||||
if (cfg)
|
||||
NE10_FFT_DESTROY_C2C_TYPE(cfg);
|
||||
opus_free(st->arch_fft);
|
||||
}
|
||||
#endif
|
||||
|
||||
void opus_fft_neon(const kiss_fft_state *st,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout)
|
||||
{
|
||||
NE10_FFT_STATE_TYPE_T state;
|
||||
NE10_FFT_CFG_TYPE_T cfg = &state;
|
||||
VARDECL(NE10_FFT_CPX_TYPE_T, buffer);
|
||||
SAVE_STACK;
|
||||
ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T);
|
||||
|
||||
if (!st->arch_fft->is_supported) {
|
||||
/* This nfft length (scaled fft) not supported in NE10 */
|
||||
opus_fft_c(st, fin, fout);
|
||||
}
|
||||
else {
|
||||
memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T));
|
||||
state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0];
|
||||
#if !defined(FIXED_POINT)
|
||||
state.is_forward_scaled = 1;
|
||||
|
||||
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
|
||||
(NE10_FFT_CPX_TYPE_T *)fin,
|
||||
cfg, 0);
|
||||
#else
|
||||
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
|
||||
(NE10_FFT_CPX_TYPE_T *)fin,
|
||||
cfg, 0, 1);
|
||||
#endif
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
void opus_ifft_neon(const kiss_fft_state *st,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout)
|
||||
{
|
||||
NE10_FFT_STATE_TYPE_T state;
|
||||
NE10_FFT_CFG_TYPE_T cfg = &state;
|
||||
VARDECL(NE10_FFT_CPX_TYPE_T, buffer);
|
||||
SAVE_STACK;
|
||||
ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T);
|
||||
|
||||
if (!st->arch_fft->is_supported) {
|
||||
/* This nfft length (scaled fft) not supported in NE10 */
|
||||
opus_ifft_c(st, fin, fout);
|
||||
}
|
||||
else {
|
||||
memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T));
|
||||
state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0];
|
||||
#if !defined(FIXED_POINT)
|
||||
state.is_backward_scaled = 0;
|
||||
|
||||
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
|
||||
(NE10_FFT_CPX_TYPE_T *)fin,
|
||||
cfg, 1);
|
||||
#else
|
||||
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
|
||||
(NE10_FFT_CPX_TYPE_T *)fin,
|
||||
cfg, 1, 0);
|
||||
#endif
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
/* Copyright (c) 2015 Xiph.Org Foundation
|
||||
Written by Viswanath Puttagunta */
|
||||
/**
|
||||
@file celt_mdct_ne10.c
|
||||
@brief ARM Neon optimizations for mdct using NE10 library
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SKIP_CONFIG_H
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
#include "mdct.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
void clt_mdct_forward_neon(const mdct_lookup *l,
|
||||
kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window,
|
||||
int overlap, int shift, int stride, int arch)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
VARDECL(kiss_fft_cpx, f2);
|
||||
const kiss_fft_state *st = l->kfft[shift];
|
||||
const kiss_twiddle_scalar *trig;
|
||||
|
||||
SAVE_STACK;
|
||||
|
||||
N = l->n;
|
||||
trig = l->trig;
|
||||
for (i=0;i<shift;i++)
|
||||
{
|
||||
N >>= 1;
|
||||
trig += N;
|
||||
}
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
ALLOC(f2, N4, kiss_fft_cpx);
|
||||
|
||||
/* Consider the input to be composed of four blocks: [a, b, c, d] */
|
||||
/* Window, shuffle, fold */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f;
|
||||
const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
|
||||
const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
|
||||
for(i=0;i<((overlap+3)>>2);i++)
|
||||
{
|
||||
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
|
||||
*yp++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2);
|
||||
*yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]);
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
wp1+=2;
|
||||
wp2-=2;
|
||||
}
|
||||
wp1 = window;
|
||||
wp2 = window+overlap-1;
|
||||
for(;i<N4-((overlap+3)>>2);i++)
|
||||
{
|
||||
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
|
||||
*yp++ = *xp2;
|
||||
*yp++ = *xp1;
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
}
|
||||
for(;i<N4;i++)
|
||||
{
|
||||
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
|
||||
*yp++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2);
|
||||
*yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]);
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
wp1+=2;
|
||||
wp2-=2;
|
||||
}
|
||||
}
|
||||
/* Pre-rotation */
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f;
|
||||
const kiss_twiddle_scalar *t = &trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_cpx yc;
|
||||
kiss_twiddle_scalar t0, t1;
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
t0 = t[i];
|
||||
t1 = t[N4+i];
|
||||
re = *yp++;
|
||||
im = *yp++;
|
||||
yr = S_MUL(re,t0) - S_MUL(im,t1);
|
||||
yi = S_MUL(im,t0) + S_MUL(re,t1);
|
||||
yc.r = yr;
|
||||
yc.i = yi;
|
||||
f2[i] = yc;
|
||||
}
|
||||
}
|
||||
|
||||
opus_fft(st, f2, (kiss_fft_cpx *)f, arch);
|
||||
|
||||
/* Post-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_cpx * OPUS_RESTRICT fp = (kiss_fft_cpx *)f;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
|
||||
const kiss_twiddle_scalar *t = &trig[0];
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar yr, yi;
|
||||
yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]);
|
||||
yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]);
|
||||
*yp1 = yr;
|
||||
*yp2 = yi;
|
||||
fp++;
|
||||
yp1 += 2*stride;
|
||||
yp2 -= 2*stride;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
void clt_mdct_backward_neon(const mdct_lookup *l,
|
||||
kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 * OPUS_RESTRICT window,
|
||||
int overlap, int shift, int stride, int arch)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
const kiss_twiddle_scalar *trig;
|
||||
const kiss_fft_state *st = l->kfft[shift];
|
||||
|
||||
N = l->n;
|
||||
trig = l->trig;
|
||||
for (i=0;i<shift;i++)
|
||||
{
|
||||
N >>= 1;
|
||||
trig += N;
|
||||
}
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
|
||||
/* Pre-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
|
||||
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f;
|
||||
const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar yr, yi;
|
||||
yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]);
|
||||
yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]);
|
||||
yp[2*i] = yr;
|
||||
yp[2*i+1] = yi;
|
||||
xp1+=2*stride;
|
||||
xp2-=2*stride;
|
||||
}
|
||||
}
|
||||
|
||||
opus_ifft(st, (kiss_fft_cpx *)f, (kiss_fft_cpx*)(out+(overlap>>1)), arch);
|
||||
|
||||
/* Post-rotate and de-shuffle from both ends of the buffer at once to make
|
||||
it in-place. */
|
||||
{
|
||||
kiss_fft_scalar * yp0 = out+(overlap>>1);
|
||||
kiss_fft_scalar * yp1 = out+(overlap>>1)+N2-2;
|
||||
const kiss_twiddle_scalar *t = &trig[0];
|
||||
/* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the
|
||||
middle pair will be computed twice. */
|
||||
for(i=0;i<(N4+1)>>1;i++)
|
||||
{
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
kiss_twiddle_scalar t0, t1;
|
||||
re = yp0[0];
|
||||
im = yp0[1];
|
||||
t0 = t[i];
|
||||
t1 = t[N4+i];
|
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
|
||||
yr = S_MUL(re,t0) + S_MUL(im,t1);
|
||||
yi = S_MUL(re,t1) - S_MUL(im,t0);
|
||||
re = yp1[0];
|
||||
im = yp1[1];
|
||||
yp0[0] = yr;
|
||||
yp1[1] = yi;
|
||||
|
||||
t0 = t[(N4-i-1)];
|
||||
t1 = t[(N2-i-1)];
|
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
|
||||
yr = S_MUL(re,t0) + S_MUL(im,t1);
|
||||
yi = S_MUL(re,t1) - S_MUL(im,t0);
|
||||
yp1[0] = yr;
|
||||
yp0[1] = yi;
|
||||
yp0 += 2;
|
||||
yp1 -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mirror on both sides for TDAC */
|
||||
{
|
||||
kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1;
|
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
|
||||
const opus_val16 * OPUS_RESTRICT wp1 = window;
|
||||
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
|
||||
|
||||
for(i = 0; i < overlap/2; i++)
|
||||
{
|
||||
kiss_fft_scalar x1, x2;
|
||||
x1 = *xp1;
|
||||
x2 = *yp1;
|
||||
*yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
|
||||
*xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
|
||||
wp1++;
|
||||
wp2--;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
/* Copyright (c) 2014-2015 Xiph.Org Foundation
|
||||
Written by Viswanath Puttagunta */
|
||||
/**
|
||||
@file celt_neon_intr.c
|
||||
@brief ARM Neon Intrinsic optimizations for celt
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include "../pitch.h"
|
||||
|
||||
#if defined(FIXED_POINT)
|
||||
#include <string.h>
|
||||
|
||||
void xcorr_kernel_neon_fixed(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
|
||||
{
|
||||
int j;
|
||||
int32x4_t a = vld1q_s32(sum);
|
||||
/* Load y[0...3] */
|
||||
/* This requires len>0 to always be valid (which we assert in the C code). */
|
||||
int16x4_t y0 = vld1_s16(y);
|
||||
y += 4;
|
||||
|
||||
/* This loop loads one y value more than we actually need.
|
||||
Therefore we have to stop as soon as there are 8 or fewer samples left
|
||||
(instead of 7), to avoid reading past the end of the array. */
|
||||
for (j = 0; j + 8 < len; j += 8)
|
||||
{
|
||||
/* Load x[0...7] */
|
||||
int16x8_t xx = vld1q_s16(x);
|
||||
int16x4_t x0 = vget_low_s16(xx);
|
||||
int16x4_t x4 = vget_high_s16(xx);
|
||||
/* Load y[4...11] */
|
||||
int16x8_t yy = vld1q_s16(y);
|
||||
int16x4_t y4 = vget_low_s16(yy);
|
||||
int16x4_t y8 = vget_high_s16(yy);
|
||||
int32x4_t a0 = vmlal_lane_s16(a, y0, x0, 0);
|
||||
int32x4_t a1 = vmlal_lane_s16(a0, y4, x4, 0);
|
||||
|
||||
int16x4_t y1 = vext_s16(y0, y4, 1);
|
||||
int16x4_t y5 = vext_s16(y4, y8, 1);
|
||||
int32x4_t a2 = vmlal_lane_s16(a1, y1, x0, 1);
|
||||
int32x4_t a3 = vmlal_lane_s16(a2, y5, x4, 1);
|
||||
|
||||
int16x4_t y2 = vext_s16(y0, y4, 2);
|
||||
int16x4_t y6 = vext_s16(y4, y8, 2);
|
||||
int32x4_t a4 = vmlal_lane_s16(a3, y2, x0, 2);
|
||||
int32x4_t a5 = vmlal_lane_s16(a4, y6, x4, 2);
|
||||
|
||||
int16x4_t y3 = vext_s16(y0, y4, 3);
|
||||
int16x4_t y7 = vext_s16(y4, y8, 3);
|
||||
int32x4_t a6 = vmlal_lane_s16(a5, y3, x0, 3);
|
||||
int32x4_t a7 = vmlal_lane_s16(a6, y7, x4, 3);
|
||||
|
||||
y0 = y8;
|
||||
a = a7;
|
||||
x += 8;
|
||||
y += 8;
|
||||
}
|
||||
if (j + 4 < len) {
|
||||
/* Load x[0...3] */
|
||||
int16x4_t x0 = vld1_s16(x);
|
||||
/* Load y[4...7] */
|
||||
int16x4_t y4 = vld1_s16(y);
|
||||
int32x4_t a0 = vmlal_lane_s16(a, y0, x0, 0);
|
||||
int16x4_t y1 = vext_s16(y0, y4, 1);
|
||||
int32x4_t a1 = vmlal_lane_s16(a0, y1, x0, 1);
|
||||
int16x4_t y2 = vext_s16(y0, y4, 2);
|
||||
int32x4_t a2 = vmlal_lane_s16(a1, y2, x0, 2);
|
||||
int16x4_t y3 = vext_s16(y0, y4, 3);
|
||||
int32x4_t a3 = vmlal_lane_s16(a2, y3, x0, 3);
|
||||
y0 = y4;
|
||||
a = a3;
|
||||
x += 4;
|
||||
y += 4;
|
||||
j += 4;
|
||||
}
|
||||
if (j + 2 < len) {
|
||||
/* Load x[0...1] */
|
||||
int16x4x2_t xx = vld2_dup_s16(x);
|
||||
int16x4_t x0 = xx.val[0];
|
||||
int16x4_t x1 = xx.val[1];
|
||||
/* Load y[4...5].
|
||||
We would like to use vld1_dup_s32(), but casting the pointer would
|
||||
break strict aliasing rules and potentially have alignment issues.
|
||||
Fortunately the compiler seems capable of translating this memcpy()
|
||||
and vdup_n_s32() into the equivalent vld1_dup_s32().*/
|
||||
int32_t yy;
|
||||
memcpy(&yy, y, sizeof(yy));
|
||||
int16x4_t y4 = vreinterpret_s16_s32(vdup_n_s32(yy));
|
||||
int32x4_t a0 = vmlal_s16(a, y0, x0);
|
||||
int16x4_t y1 = vext_s16(y0, y4, 1);
|
||||
/* Replace bottom copy of {y[5], y[4]} in y4 with {y[3], y[2]} from y0,
|
||||
using VSRI instead of VEXT, since it's a data-processing
|
||||
instruction. */
|
||||
y0 = vreinterpret_s16_s64(vsri_n_s64(vreinterpret_s64_s16(y4),
|
||||
vreinterpret_s64_s16(y0), 32));
|
||||
int32x4_t a1 = vmlal_s16(a0, y1, x1);
|
||||
a = a1;
|
||||
x += 2;
|
||||
y += 2;
|
||||
j += 2;
|
||||
}
|
||||
if (j + 1 < len) {
|
||||
/* Load next x. */
|
||||
int16x4_t x0 = vld1_dup_s16(x);
|
||||
int32x4_t a0 = vmlal_s16(a, y0, x0);
|
||||
/* Load last y. */
|
||||
int16x4_t y4 = vld1_dup_s16(y);
|
||||
y0 = vreinterpret_s16_s64(vsri_n_s64(vreinterpret_s64_s16(y4),
|
||||
vreinterpret_s64_s16(y0), 16));
|
||||
a = a0;
|
||||
x++;
|
||||
}
|
||||
/* Load last x. */
|
||||
int16x4_t x0 = vld1_dup_s16(x);
|
||||
int32x4_t a0 = vmlal_s16(a, y0, x0);
|
||||
vst1q_s32(sum, a0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__ARM_FEATURE_FMA) && defined(__ARM_ARCH_ISA_A64)
|
||||
/* If we can, force the compiler to use an FMA instruction rather than break
|
||||
* vmlaq_f32() into fmul/fadd. */
|
||||
#ifdef vmlaq_lane_f32
|
||||
#undef vmlaq_lane_f32
|
||||
#endif
|
||||
#define vmlaq_lane_f32(a,b,c,lane) vfmaq_lane_f32(a,b,c,lane)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Function: xcorr_kernel_neon_float
|
||||
* ---------------------------------
|
||||
* Computes 4 correlation values and stores them in sum[4]
|
||||
*/
|
||||
static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y,
|
||||
float32_t sum[4], int len) {
|
||||
float32x4_t YY[3];
|
||||
float32x4_t YEXT[3];
|
||||
float32x4_t XX[2];
|
||||
float32x2_t XX_2;
|
||||
float32x4_t SUMM;
|
||||
const float32_t *xi = x;
|
||||
const float32_t *yi = y;
|
||||
|
||||
celt_assert(len>0);
|
||||
|
||||
YY[0] = vld1q_f32(yi);
|
||||
SUMM = vdupq_n_f32(0);
|
||||
|
||||
/* Consume 8 elements in x vector and 12 elements in y
|
||||
* vector. However, the 12'th element never really gets
|
||||
* touched in this loop. So, if len == 8, then we only
|
||||
* must access y[0] to y[10]. y[11] must not be accessed
|
||||
* hence make sure len > 8 and not len >= 8
|
||||
*/
|
||||
while (len > 8) {
|
||||
yi += 4;
|
||||
YY[1] = vld1q_f32(yi);
|
||||
yi += 4;
|
||||
YY[2] = vld1q_f32(yi);
|
||||
|
||||
XX[0] = vld1q_f32(xi);
|
||||
xi += 4;
|
||||
XX[1] = vld1q_f32(xi);
|
||||
xi += 4;
|
||||
|
||||
SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0);
|
||||
YEXT[0] = vextq_f32(YY[0], YY[1], 1);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1);
|
||||
YEXT[1] = vextq_f32(YY[0], YY[1], 2);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0);
|
||||
YEXT[2] = vextq_f32(YY[0], YY[1], 3);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1);
|
||||
|
||||
SUMM = vmlaq_lane_f32(SUMM, YY[1], vget_low_f32(XX[1]), 0);
|
||||
YEXT[0] = vextq_f32(YY[1], YY[2], 1);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[1]), 1);
|
||||
YEXT[1] = vextq_f32(YY[1], YY[2], 2);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[1]), 0);
|
||||
YEXT[2] = vextq_f32(YY[1], YY[2], 3);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[1]), 1);
|
||||
|
||||
YY[0] = YY[2];
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* Consume 4 elements in x vector and 8 elements in y
|
||||
* vector. However, the 8'th element in y never really gets
|
||||
* touched in this loop. So, if len == 4, then we only
|
||||
* must access y[0] to y[6]. y[7] must not be accessed
|
||||
* hence make sure len>4 and not len>=4
|
||||
*/
|
||||
if (len > 4) {
|
||||
yi += 4;
|
||||
YY[1] = vld1q_f32(yi);
|
||||
|
||||
XX[0] = vld1q_f32(xi);
|
||||
xi += 4;
|
||||
|
||||
SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0);
|
||||
YEXT[0] = vextq_f32(YY[0], YY[1], 1);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1);
|
||||
YEXT[1] = vextq_f32(YY[0], YY[1], 2);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0);
|
||||
YEXT[2] = vextq_f32(YY[0], YY[1], 3);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1);
|
||||
|
||||
YY[0] = YY[1];
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
while (--len > 0) {
|
||||
XX_2 = vld1_dup_f32(xi++);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0);
|
||||
YY[0]= vld1q_f32(++yi);
|
||||
}
|
||||
|
||||
XX_2 = vld1_dup_f32(xi);
|
||||
SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0);
|
||||
|
||||
vst1q_f32(sum, SUMM);
|
||||
}
|
||||
|
||||
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
|
||||
opus_val32 *xcorr, int len, int max_pitch, int arch) {
|
||||
int i;
|
||||
(void)arch;
|
||||
celt_assert(max_pitch > 0);
|
||||
celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
|
||||
|
||||
for (i = 0; i < (max_pitch-3); i += 4) {
|
||||
xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i,
|
||||
(float32_t *)xcorr+i, len);
|
||||
}
|
||||
|
||||
/* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
|
||||
for (; i < max_pitch; i++) {
|
||||
xcorr[i] = celt_inner_prod_neon(_x, _y+i, len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,555 @@
|
|||
.syntax unified
|
||||
@ Copyright (c) 2007-2008 CSIRO
|
||||
@ Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
@ Copyright (c) 2013 Parrot
|
||||
@ Written by Aurélien Zanelli
|
||||
@
|
||||
@ Redistribution and use in source and binary forms, with or without
|
||||
@ modification, are permitted provided that the following conditions
|
||||
@ are met:
|
||||
@
|
||||
@ - Redistributions of source code must retain the above copyright
|
||||
@ notice, this list of conditions and the following disclaimer.
|
||||
@
|
||||
@ - Redistributions in binary form must reproduce the above copyright
|
||||
@ notice, this list of conditions and the following disclaimer in the
|
||||
@ documentation and/or other materials provided with the distribution.
|
||||
@
|
||||
@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
@ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
@ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
@ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
@ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
.text; .p2align 2; .arch armv7-a
|
||||
.fpu neon
|
||||
.object_arch armv4t
|
||||
|
||||
.include "celt/arm/armopts-gnu.S"
|
||||
|
||||
.if OPUS_ARM_MAY_HAVE_EDSP
|
||||
.global celt_pitch_xcorr_edsp
|
||||
.endif
|
||||
|
||||
.if OPUS_ARM_MAY_HAVE_NEON
|
||||
.global celt_pitch_xcorr_neon
|
||||
.endif
|
||||
|
||||
.if OPUS_ARM_MAY_HAVE_NEON
|
||||
|
||||
@ Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3
|
||||
.type xcorr_kernel_neon, %function; xcorr_kernel_neon: @ PROC
|
||||
xcorr_kernel_neon_start:
|
||||
@ input:
|
||||
@ r3 = int len
|
||||
@ r4 = opus_val16 *x
|
||||
@ r5 = opus_val16 *y
|
||||
@ q0 = opus_val32 sum[4]
|
||||
@ output:
|
||||
@ q0 = opus_val32 sum[4]
|
||||
@ preserved: r0-r3, r6-r11, d2, q4-q7, q9-q15
|
||||
@ internal usage:
|
||||
@ r12 = int j
|
||||
@ d3 = y_3|y_2|y_1|y_0
|
||||
@ q2 = y_B|y_A|y_9|y_8|y_7|y_6|y_5|y_4
|
||||
@ q3 = x_7|x_6|x_5|x_4|x_3|x_2|x_1|x_0
|
||||
@ q8 = scratch
|
||||
@
|
||||
@ Load y[0...3]
|
||||
@ This requires len>0 to always be valid (which we assert in the C code).
|
||||
VLD1.16 {d5}, [r5]!
|
||||
SUBS r12, r3, #8
|
||||
BLE xcorr_kernel_neon_process4
|
||||
@ Process 8 samples at a time.
|
||||
@ This loop loads one y value more than we actually need. Therefore we have to
|
||||
@ stop as soon as there are 8 or fewer samples left (instead of 7), to avoid
|
||||
@ reading past the end of the array.
|
||||
xcorr_kernel_neon_process8:
|
||||
@ This loop has 19 total instructions (10 cycles to issue, minimum), with
|
||||
@ - 2 cycles of ARM insrtuctions,
|
||||
@ - 10 cycles of load/store/byte permute instructions, and
|
||||
@ - 9 cycles of data processing instructions.
|
||||
@ On a Cortex A8, we dual-issue the maximum amount (9 cycles) between the
|
||||
@ latter two categories, meaning the whole loop should run in 10 cycles per
|
||||
@ iteration, barring cache misses.
|
||||
@
|
||||
@ Load x[0...7]
|
||||
VLD1.16 {d6, d7}, [r4]!
|
||||
@ Unlike VMOV, VAND is a data processsing instruction (and doesn't get
|
||||
@ assembled to VMOV, like VORR would), so it dual-issues with the prior VLD1.
|
||||
VAND d3, d5, d5
|
||||
SUBS r12, r12, #8
|
||||
@ Load y[4...11]
|
||||
VLD1.16 {d4, d5}, [r5]!
|
||||
VMLAL.S16 q0, d3, d6[0]
|
||||
VEXT.16 d16, d3, d4, #1
|
||||
VMLAL.S16 q0, d4, d7[0]
|
||||
VEXT.16 d17, d4, d5, #1
|
||||
VMLAL.S16 q0, d16, d6[1]
|
||||
VEXT.16 d16, d3, d4, #2
|
||||
VMLAL.S16 q0, d17, d7[1]
|
||||
VEXT.16 d17, d4, d5, #2
|
||||
VMLAL.S16 q0, d16, d6[2]
|
||||
VEXT.16 d16, d3, d4, #3
|
||||
VMLAL.S16 q0, d17, d7[2]
|
||||
VEXT.16 d17, d4, d5, #3
|
||||
VMLAL.S16 q0, d16, d6[3]
|
||||
VMLAL.S16 q0, d17, d7[3]
|
||||
BGT xcorr_kernel_neon_process8
|
||||
@ Process 4 samples here if we have > 4 left (still reading one extra y value).
|
||||
xcorr_kernel_neon_process4:
|
||||
ADDS r12, r12, #4
|
||||
BLE xcorr_kernel_neon_process2
|
||||
@ Load x[0...3]
|
||||
VLD1.16 d6, [r4]!
|
||||
@ Use VAND since it's a data processing instruction again.
|
||||
VAND d4, d5, d5
|
||||
SUB r12, r12, #4
|
||||
@ Load y[4...7]
|
||||
VLD1.16 d5, [r5]!
|
||||
VMLAL.S16 q0, d4, d6[0]
|
||||
VEXT.16 d16, d4, d5, #1
|
||||
VMLAL.S16 q0, d16, d6[1]
|
||||
VEXT.16 d16, d4, d5, #2
|
||||
VMLAL.S16 q0, d16, d6[2]
|
||||
VEXT.16 d16, d4, d5, #3
|
||||
VMLAL.S16 q0, d16, d6[3]
|
||||
@ Process 2 samples here if we have > 2 left (still reading one extra y value).
|
||||
xcorr_kernel_neon_process2:
|
||||
ADDS r12, r12, #2
|
||||
BLE xcorr_kernel_neon_process1
|
||||
@ Load x[0...1]
|
||||
VLD2.16 {d6[],d7[]}, [r4]!
|
||||
@ Use VAND since it's a data processing instruction again.
|
||||
VAND d4, d5, d5
|
||||
SUB r12, r12, #2
|
||||
@ Load y[4...5]
|
||||
VLD1.32 {d5[]}, [r5]!
|
||||
VMLAL.S16 q0, d4, d6
|
||||
VEXT.16 d16, d4, d5, #1
|
||||
@ Replace bottom copy of {y5,y4} in d5 with {y3,y2} from d4, using VSRI
|
||||
@ instead of VEXT, since it's a data-processing instruction.
|
||||
VSRI.64 d5, d4, #32
|
||||
VMLAL.S16 q0, d16, d7
|
||||
@ Process 1 sample using the extra y value we loaded above.
|
||||
xcorr_kernel_neon_process1:
|
||||
@ Load next *x
|
||||
VLD1.16 {d6[]}, [r4]!
|
||||
ADDS r12, r12, #1
|
||||
@ y[0...3] are left in d5 from prior iteration(s) (if any)
|
||||
VMLAL.S16 q0, d5, d6
|
||||
MOVLE pc, lr
|
||||
@ Now process 1 last sample, not reading ahead.
|
||||
@ Load last *y
|
||||
VLD1.16 {d4[]}, [r5]!
|
||||
VSRI.64 d4, d5, #16
|
||||
@ Load last *x
|
||||
VLD1.16 {d6[]}, [r4]!
|
||||
VMLAL.S16 q0, d4, d6
|
||||
MOV pc, lr
|
||||
.size xcorr_kernel_neon, .-xcorr_kernel_neon @ ENDP
|
||||
|
||||
@ opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
|
||||
@ opus_val32 *xcorr, int len, int max_pitch, int arch)
|
||||
.type celt_pitch_xcorr_neon, %function; celt_pitch_xcorr_neon: @ PROC
|
||||
@ input:
|
||||
@ r0 = opus_val16 *_x
|
||||
@ r1 = opus_val16 *_y
|
||||
@ r2 = opus_val32 *xcorr
|
||||
@ r3 = int len
|
||||
@ output:
|
||||
@ r0 = int maxcorr
|
||||
@ internal usage:
|
||||
@ r4 = opus_val16 *x (for xcorr_kernel_neon())
|
||||
@ r5 = opus_val16 *y (for xcorr_kernel_neon())
|
||||
@ r6 = int max_pitch
|
||||
@ r12 = int j
|
||||
@ q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon())
|
||||
@ ignored:
|
||||
@ int arch
|
||||
STMFD sp!, {r4-r6, lr}
|
||||
LDR r6, [sp, #16]
|
||||
VMOV.S32 q15, #1
|
||||
@ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
|
||||
SUBS r6, r6, #4
|
||||
BLT celt_pitch_xcorr_neon_process4_done
|
||||
celt_pitch_xcorr_neon_process4:
|
||||
@ xcorr_kernel_neon parameters:
|
||||
@ r3 = len, r4 = _x, r5 = _y, q0 = {0, 0, 0, 0}
|
||||
MOV r4, r0
|
||||
MOV r5, r1
|
||||
VEOR q0, q0, q0
|
||||
@ xcorr_kernel_neon only modifies r4, r5, r12, and q0...q3.
|
||||
@ So we don't save/restore any other registers.
|
||||
BL xcorr_kernel_neon_start
|
||||
SUBS r6, r6, #4
|
||||
VST1.32 {q0}, [r2]!
|
||||
@ _y += 4
|
||||
ADD r1, r1, #8
|
||||
VMAX.S32 q15, q15, q0
|
||||
@ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
|
||||
BGE celt_pitch_xcorr_neon_process4
|
||||
@ We have less than 4 sums left to compute.
|
||||
celt_pitch_xcorr_neon_process4_done:
|
||||
ADDS r6, r6, #4
|
||||
@ Reduce maxcorr to a single value
|
||||
VMAX.S32 d30, d30, d31
|
||||
VPMAX.S32 d30, d30, d30
|
||||
@ if (max_pitch <= 0) goto celt_pitch_xcorr_neon_done
|
||||
BLE celt_pitch_xcorr_neon_done
|
||||
@ Now compute each remaining sum one at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining:
|
||||
MOV r4, r0
|
||||
MOV r5, r1
|
||||
VMOV.I32 q0, #0
|
||||
SUBS r12, r3, #8
|
||||
BLT celt_pitch_xcorr_neon_process_remaining4
|
||||
@ Sum terms 8 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining_loop8:
|
||||
@ Load x[0...7]
|
||||
VLD1.16 {q1}, [r4]!
|
||||
@ Load y[0...7]
|
||||
VLD1.16 {q2}, [r5]!
|
||||
SUBS r12, r12, #8
|
||||
VMLAL.S16 q0, d4, d2
|
||||
VMLAL.S16 q0, d5, d3
|
||||
BGE celt_pitch_xcorr_neon_process_remaining_loop8
|
||||
@ Sum terms 4 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining4:
|
||||
ADDS r12, r12, #4
|
||||
BLT celt_pitch_xcorr_neon_process_remaining4_done
|
||||
@ Load x[0...3]
|
||||
VLD1.16 {d2}, [r4]!
|
||||
@ Load y[0...3]
|
||||
VLD1.16 {d3}, [r5]!
|
||||
SUB r12, r12, #4
|
||||
VMLAL.S16 q0, d3, d2
|
||||
celt_pitch_xcorr_neon_process_remaining4_done:
|
||||
@ Reduce the sum to a single value.
|
||||
VADD.S32 d0, d0, d1
|
||||
VPADDL.S32 d0, d0
|
||||
ADDS r12, r12, #4
|
||||
BLE celt_pitch_xcorr_neon_process_remaining_loop_done
|
||||
@ Sum terms 1 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining_loop1:
|
||||
VLD1.16 {d2[]}, [r4]!
|
||||
VLD1.16 {d3[]}, [r5]!
|
||||
SUBS r12, r12, #1
|
||||
VMLAL.S16 q0, d2, d3
|
||||
BGT celt_pitch_xcorr_neon_process_remaining_loop1
|
||||
celt_pitch_xcorr_neon_process_remaining_loop_done:
|
||||
VST1.32 {d0[0]}, [r2]!
|
||||
VMAX.S32 d30, d30, d0
|
||||
SUBS r6, r6, #1
|
||||
@ _y++
|
||||
ADD r1, r1, #2
|
||||
@ if (--max_pitch > 0) goto celt_pitch_xcorr_neon_process_remaining
|
||||
BGT celt_pitch_xcorr_neon_process_remaining
|
||||
celt_pitch_xcorr_neon_done:
|
||||
VMOV.32 r0, d30[0]
|
||||
LDMFD sp!, {r4-r6, pc}
|
||||
.size celt_pitch_xcorr_neon, .-celt_pitch_xcorr_neon @ ENDP
|
||||
|
||||
.endif
|
||||
|
||||
.if OPUS_ARM_MAY_HAVE_EDSP
|
||||
|
||||
@ This will get used on ARMv7 devices without NEON, so it has been optimized
|
||||
@ to take advantage of dual-issuing where possible.
|
||||
.type xcorr_kernel_edsp, %function; xcorr_kernel_edsp: @ PROC
|
||||
xcorr_kernel_edsp_start:
|
||||
@ input:
|
||||
@ r3 = int len
|
||||
@ r4 = opus_val16 *_x (must be 32-bit aligned)
|
||||
@ r5 = opus_val16 *_y (must be 32-bit aligned)
|
||||
@ r6...r9 = opus_val32 sum[4]
|
||||
@ output:
|
||||
@ r6...r9 = opus_val32 sum[4]
|
||||
@ preserved: r0-r5
|
||||
@ internal usage
|
||||
@ r2 = int j
|
||||
@ r12,r14 = opus_val16 x[4]
|
||||
@ r10,r11 = opus_val16 y[4]
|
||||
STMFD sp!, {r2,r4,r5,lr}
|
||||
LDR r10, [r5], #4 @ Load y[0...1]
|
||||
SUBS r2, r3, #4 @ j = len-4
|
||||
LDR r11, [r5], #4 @ Load y[2...3]
|
||||
BLE xcorr_kernel_edsp_process4_done
|
||||
LDR r12, [r4], #4 @ Load x[0...1]
|
||||
@ Stall
|
||||
xcorr_kernel_edsp_process4:
|
||||
@ The multiplies must issue from pipeline 0, and can't dual-issue with each
|
||||
@ other. Every other instruction here dual-issues with a multiply, and is
|
||||
@ thus "free". There should be no stalls in the body of the loop.
|
||||
SMLABB r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x_0,y_0)
|
||||
LDR r14, [r4], #4 @ Load x[2...3]
|
||||
SMLABT r7, r12, r10, r7 @ sum[1] = MAC16_16(sum[1],x_0,y_1)
|
||||
SUBS r2, r2, #4 @ j-=4
|
||||
SMLABB r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x_0,y_2)
|
||||
SMLABT r9, r12, r11, r9 @ sum[3] = MAC16_16(sum[3],x_0,y_3)
|
||||
SMLATT r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x_1,y_1)
|
||||
LDR r10, [r5], #4 @ Load y[4...5]
|
||||
SMLATB r7, r12, r11, r7 @ sum[1] = MAC16_16(sum[1],x_1,y_2)
|
||||
SMLATT r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x_1,y_3)
|
||||
SMLATB r9, r12, r10, r9 @ sum[3] = MAC16_16(sum[3],x_1,y_4)
|
||||
LDRGT r12, [r4], #4 @ Load x[0...1]
|
||||
SMLABB r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],x_2,y_2)
|
||||
SMLABT r7, r14, r11, r7 @ sum[1] = MAC16_16(sum[1],x_2,y_3)
|
||||
SMLABB r8, r14, r10, r8 @ sum[2] = MAC16_16(sum[2],x_2,y_4)
|
||||
SMLABT r9, r14, r10, r9 @ sum[3] = MAC16_16(sum[3],x_2,y_5)
|
||||
SMLATT r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],x_3,y_3)
|
||||
LDR r11, [r5], #4 @ Load y[6...7]
|
||||
SMLATB r7, r14, r10, r7 @ sum[1] = MAC16_16(sum[1],x_3,y_4)
|
||||
SMLATT r8, r14, r10, r8 @ sum[2] = MAC16_16(sum[2],x_3,y_5)
|
||||
SMLATB r9, r14, r11, r9 @ sum[3] = MAC16_16(sum[3],x_3,y_6)
|
||||
BGT xcorr_kernel_edsp_process4
|
||||
xcorr_kernel_edsp_process4_done:
|
||||
ADDS r2, r2, #4
|
||||
BLE xcorr_kernel_edsp_done
|
||||
LDRH r12, [r4], #2 @ r12 = *x++
|
||||
SUBS r2, r2, #1 @ j--
|
||||
@ Stall
|
||||
SMLABB r6, r12, r10, r6 @ sum[0] = MAC16_16(sum[0],x,y_0)
|
||||
LDRHGT r14, [r4], #2 @ r14 = *x++
|
||||
SMLABT r7, r12, r10, r7 @ sum[1] = MAC16_16(sum[1],x,y_1)
|
||||
SMLABB r8, r12, r11, r8 @ sum[2] = MAC16_16(sum[2],x,y_2)
|
||||
SMLABT r9, r12, r11, r9 @ sum[3] = MAC16_16(sum[3],x,y_3)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABT r6, r14, r10, r6 @ sum[0] = MAC16_16(sum[0],x,y_1)
|
||||
SUBS r2, r2, #1 @ j--
|
||||
SMLABB r7, r14, r11, r7 @ sum[1] = MAC16_16(sum[1],x,y_2)
|
||||
LDRH r10, [r5], #2 @ r10 = y_4 = *y++
|
||||
SMLABT r8, r14, r11, r8 @ sum[2] = MAC16_16(sum[2],x,y_3)
|
||||
LDRHGT r12, [r4], #2 @ r12 = *x++
|
||||
SMLABB r9, r14, r10, r9 @ sum[3] = MAC16_16(sum[3],x,y_4)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABB r6, r12, r11, r6 @ sum[0] = MAC16_16(sum[0],tmp,y_2)
|
||||
CMP r2, #1 @ j--
|
||||
SMLABT r7, r12, r11, r7 @ sum[1] = MAC16_16(sum[1],tmp,y_3)
|
||||
LDRH r2, [r5], #2 @ r2 = y_5 = *y++
|
||||
SMLABB r8, r12, r10, r8 @ sum[2] = MAC16_16(sum[2],tmp,y_4)
|
||||
LDRHGT r14, [r4] @ r14 = *x
|
||||
SMLABB r9, r12, r2, r9 @ sum[3] = MAC16_16(sum[3],tmp,y_5)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABT r6, r14, r11, r6 @ sum[0] = MAC16_16(sum[0],tmp,y_3)
|
||||
LDRH r11, [r5] @ r11 = y_6 = *y
|
||||
SMLABB r7, r14, r10, r7 @ sum[1] = MAC16_16(sum[1],tmp,y_4)
|
||||
SMLABB r8, r14, r2, r8 @ sum[2] = MAC16_16(sum[2],tmp,y_5)
|
||||
SMLABB r9, r14, r11, r9 @ sum[3] = MAC16_16(sum[3],tmp,y_6)
|
||||
xcorr_kernel_edsp_done:
|
||||
LDMFD sp!, {r2,r4,r5,pc}
|
||||
.size xcorr_kernel_edsp, .-xcorr_kernel_edsp @ ENDP
|
||||
|
||||
.type celt_pitch_xcorr_edsp, %function; celt_pitch_xcorr_edsp: @ PROC
|
||||
@ input:
|
||||
@ r0 = opus_val16 *_x (must be 32-bit aligned)
|
||||
@ r1 = opus_val16 *_y (only needs to be 16-bit aligned)
|
||||
@ r2 = opus_val32 *xcorr
|
||||
@ r3 = int len
|
||||
@ output:
|
||||
@ r0 = maxcorr
|
||||
@ internal usage
|
||||
@ r4 = opus_val16 *x
|
||||
@ r5 = opus_val16 *y
|
||||
@ r6 = opus_val32 sum0
|
||||
@ r7 = opus_val32 sum1
|
||||
@ r8 = opus_val32 sum2
|
||||
@ r9 = opus_val32 sum3
|
||||
@ r1 = int max_pitch
|
||||
@ r12 = int j
|
||||
@ ignored:
|
||||
@ int arch
|
||||
STMFD sp!, {r4-r11, lr}
|
||||
MOV r5, r1
|
||||
LDR r1, [sp, #36]
|
||||
MOV r4, r0
|
||||
TST r5, #3
|
||||
@ maxcorr = 1
|
||||
MOV r0, #1
|
||||
BEQ celt_pitch_xcorr_edsp_process1u_done
|
||||
@ Compute one sum at the start to make y 32-bit aligned.
|
||||
SUBS r12, r3, #4
|
||||
@ r14 = sum = 0
|
||||
MOV r14, #0
|
||||
LDRH r8, [r5], #2
|
||||
BLE celt_pitch_xcorr_edsp_process1u_loop4_done
|
||||
LDR r6, [r4], #4
|
||||
MOV r8, r8, LSL #16
|
||||
celt_pitch_xcorr_edsp_process1u_loop4:
|
||||
LDR r9, [r5], #4
|
||||
SMLABT r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0)
|
||||
LDR r7, [r4], #4
|
||||
SMLATB r14, r6, r9, r14 @ sum = MAC16_16(sum, x_1, y_1)
|
||||
LDR r8, [r5], #4
|
||||
SMLABT r14, r7, r9, r14 @ sum = MAC16_16(sum, x_2, y_2)
|
||||
SUBS r12, r12, #4 @ j-=4
|
||||
SMLATB r14, r7, r8, r14 @ sum = MAC16_16(sum, x_3, y_3)
|
||||
LDRGT r6, [r4], #4
|
||||
BGT celt_pitch_xcorr_edsp_process1u_loop4
|
||||
MOV r8, r8, LSR #16
|
||||
celt_pitch_xcorr_edsp_process1u_loop4_done:
|
||||
ADDS r12, r12, #4
|
||||
celt_pitch_xcorr_edsp_process1u_loop1:
|
||||
LDRHGE r6, [r4], #2
|
||||
@ Stall
|
||||
SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, *x, *y)
|
||||
SUBSGE r12, r12, #1
|
||||
LDRHGT r8, [r5], #2
|
||||
BGT celt_pitch_xcorr_edsp_process1u_loop1
|
||||
@ Restore _x
|
||||
SUB r4, r4, r3, LSL #1
|
||||
@ Restore and advance _y
|
||||
SUB r5, r5, r3, LSL #1
|
||||
@ maxcorr = max(maxcorr, sum)
|
||||
CMP r0, r14
|
||||
ADD r5, r5, #2
|
||||
MOVLT r0, r14
|
||||
SUBS r1, r1, #1
|
||||
@ xcorr[i] = sum
|
||||
STR r14, [r2], #4
|
||||
BLE celt_pitch_xcorr_edsp_done
|
||||
celt_pitch_xcorr_edsp_process1u_done:
|
||||
@ if (max_pitch < 4) goto celt_pitch_xcorr_edsp_process2
|
||||
SUBS r1, r1, #4
|
||||
BLT celt_pitch_xcorr_edsp_process2
|
||||
celt_pitch_xcorr_edsp_process4:
|
||||
@ xcorr_kernel_edsp parameters:
|
||||
@ r3 = len, r4 = _x, r5 = _y, r6...r9 = sum[4] = {0, 0, 0, 0}
|
||||
MOV r6, #0
|
||||
MOV r7, #0
|
||||
MOV r8, #0
|
||||
MOV r9, #0
|
||||
BL xcorr_kernel_edsp_start @ xcorr_kernel_edsp(_x, _y+i, xcorr+i, len)
|
||||
@ maxcorr = max(maxcorr, sum0, sum1, sum2, sum3)
|
||||
CMP r0, r6
|
||||
@ _y+=4
|
||||
ADD r5, r5, #8
|
||||
MOVLT r0, r6
|
||||
CMP r0, r7
|
||||
MOVLT r0, r7
|
||||
CMP r0, r8
|
||||
MOVLT r0, r8
|
||||
CMP r0, r9
|
||||
MOVLT r0, r9
|
||||
STMIA r2!, {r6-r9}
|
||||
SUBS r1, r1, #4
|
||||
BGE celt_pitch_xcorr_edsp_process4
|
||||
celt_pitch_xcorr_edsp_process2:
|
||||
ADDS r1, r1, #2
|
||||
BLT celt_pitch_xcorr_edsp_process1a
|
||||
SUBS r12, r3, #4
|
||||
@ {r10, r11} = {sum0, sum1} = {0, 0}
|
||||
MOV r10, #0
|
||||
MOV r11, #0
|
||||
LDR r8, [r5], #4
|
||||
BLE celt_pitch_xcorr_edsp_process2_loop_done
|
||||
LDR r6, [r4], #4
|
||||
LDR r9, [r5], #4
|
||||
celt_pitch_xcorr_edsp_process2_loop4:
|
||||
SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDR r7, [r4], #4
|
||||
SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
SUBS r12, r12, #4 @ j-=4
|
||||
SMLATT r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_1, y_1)
|
||||
LDR r8, [r5], #4
|
||||
SMLATB r11, r6, r9, r11 @ sum1 = MAC16_16(sum1, x_1, y_2)
|
||||
LDRGT r6, [r4], #4
|
||||
SMLABB r10, r7, r9, r10 @ sum0 = MAC16_16(sum0, x_2, y_2)
|
||||
SMLABT r11, r7, r9, r11 @ sum1 = MAC16_16(sum1, x_2, y_3)
|
||||
SMLATT r10, r7, r9, r10 @ sum0 = MAC16_16(sum0, x_3, y_3)
|
||||
LDRGT r9, [r5], #4
|
||||
SMLATB r11, r7, r8, r11 @ sum1 = MAC16_16(sum1, x_3, y_4)
|
||||
BGT celt_pitch_xcorr_edsp_process2_loop4
|
||||
celt_pitch_xcorr_edsp_process2_loop_done:
|
||||
ADDS r12, r12, #2
|
||||
BLE celt_pitch_xcorr_edsp_process2_1
|
||||
LDR r6, [r4], #4
|
||||
@ Stall
|
||||
SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDR r9, [r5], #4
|
||||
SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
SUB r12, r12, #2
|
||||
SMLATT r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_1, y_1)
|
||||
MOV r8, r9
|
||||
SMLATB r11, r6, r9, r11 @ sum1 = MAC16_16(sum1, x_1, y_2)
|
||||
celt_pitch_xcorr_edsp_process2_1:
|
||||
LDRH r6, [r4], #2
|
||||
ADDS r12, r12, #1
|
||||
@ Stall
|
||||
SMLABB r10, r6, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDRHGT r7, [r4], #2
|
||||
SMLABT r11, r6, r8, r11 @ sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
BLE celt_pitch_xcorr_edsp_process2_done
|
||||
LDRH r9, [r5], #2
|
||||
SMLABT r10, r7, r8, r10 @ sum0 = MAC16_16(sum0, x_0, y_1)
|
||||
SMLABB r11, r7, r9, r11 @ sum1 = MAC16_16(sum1, x_0, y_2)
|
||||
celt_pitch_xcorr_edsp_process2_done:
|
||||
@ Restore _x
|
||||
SUB r4, r4, r3, LSL #1
|
||||
@ Restore and advance _y
|
||||
SUB r5, r5, r3, LSL #1
|
||||
@ maxcorr = max(maxcorr, sum0)
|
||||
CMP r0, r10
|
||||
ADD r5, r5, #2
|
||||
MOVLT r0, r10
|
||||
SUB r1, r1, #2
|
||||
@ maxcorr = max(maxcorr, sum1)
|
||||
CMP r0, r11
|
||||
@ xcorr[i] = sum
|
||||
STR r10, [r2], #4
|
||||
MOVLT r0, r11
|
||||
STR r11, [r2], #4
|
||||
celt_pitch_xcorr_edsp_process1a:
|
||||
ADDS r1, r1, #1
|
||||
BLT celt_pitch_xcorr_edsp_done
|
||||
SUBS r12, r3, #4
|
||||
@ r14 = sum = 0
|
||||
MOV r14, #0
|
||||
BLT celt_pitch_xcorr_edsp_process1a_loop_done
|
||||
LDR r6, [r4], #4
|
||||
LDR r8, [r5], #4
|
||||
LDR r7, [r4], #4
|
||||
LDR r9, [r5], #4
|
||||
celt_pitch_xcorr_edsp_process1a_loop4:
|
||||
SMLABB r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0)
|
||||
SUBS r12, r12, #4 @ j-=4
|
||||
SMLATT r14, r6, r8, r14 @ sum = MAC16_16(sum, x_1, y_1)
|
||||
LDRGE r6, [r4], #4
|
||||
SMLABB r14, r7, r9, r14 @ sum = MAC16_16(sum, x_2, y_2)
|
||||
LDRGE r8, [r5], #4
|
||||
SMLATT r14, r7, r9, r14 @ sum = MAC16_16(sum, x_3, y_3)
|
||||
LDRGE r7, [r4], #4
|
||||
LDRGE r9, [r5], #4
|
||||
BGE celt_pitch_xcorr_edsp_process1a_loop4
|
||||
celt_pitch_xcorr_edsp_process1a_loop_done:
|
||||
ADDS r12, r12, #2
|
||||
LDRGE r6, [r4], #4
|
||||
LDRGE r8, [r5], #4
|
||||
@ Stall
|
||||
SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, x_0, y_0)
|
||||
SUBGE r12, r12, #2
|
||||
SMLATTGE r14, r6, r8, r14 @ sum = MAC16_16(sum, x_1, y_1)
|
||||
ADDS r12, r12, #1
|
||||
LDRHGE r6, [r4], #2
|
||||
LDRHGE r8, [r5], #2
|
||||
@ Stall
|
||||
SMLABBGE r14, r6, r8, r14 @ sum = MAC16_16(sum, *x, *y)
|
||||
@ maxcorr = max(maxcorr, sum)
|
||||
CMP r0, r14
|
||||
@ xcorr[i] = sum
|
||||
STR r14, [r2], #4
|
||||
MOVLT r0, r14
|
||||
celt_pitch_xcorr_edsp_done:
|
||||
LDMFD sp!, {r4-r11, pc}
|
||||
.size celt_pitch_xcorr_edsp, .-celt_pitch_xcorr_edsp @ ENDP
|
||||
|
||||
.endif
|
||||
|
||||
@ END:
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
|
|
@ -0,0 +1,551 @@
|
|||
; Copyright (c) 2007-2008 CSIRO
|
||||
; Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
; Copyright (c) 2013 Parrot
|
||||
; Written by Aurélien Zanelli
|
||||
;
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions
|
||||
; are met:
|
||||
;
|
||||
; - Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
;
|
||||
; - Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
;
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
; ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
; OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
GET celt/arm/armopts.s
|
||||
|
||||
IF OPUS_ARM_MAY_HAVE_EDSP
|
||||
EXPORT celt_pitch_xcorr_edsp
|
||||
ENDIF
|
||||
|
||||
IF OPUS_ARM_MAY_HAVE_NEON
|
||||
EXPORT celt_pitch_xcorr_neon
|
||||
ENDIF
|
||||
|
||||
IF OPUS_ARM_MAY_HAVE_NEON
|
||||
|
||||
; Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3
|
||||
xcorr_kernel_neon PROC
|
||||
xcorr_kernel_neon_start
|
||||
; input:
|
||||
; r3 = int len
|
||||
; r4 = opus_val16 *x
|
||||
; r5 = opus_val16 *y
|
||||
; q0 = opus_val32 sum[4]
|
||||
; output:
|
||||
; q0 = opus_val32 sum[4]
|
||||
; preserved: r0-r3, r6-r11, d2, q4-q7, q9-q15
|
||||
; internal usage:
|
||||
; r12 = int j
|
||||
; d3 = y_3|y_2|y_1|y_0
|
||||
; q2 = y_B|y_A|y_9|y_8|y_7|y_6|y_5|y_4
|
||||
; q3 = x_7|x_6|x_5|x_4|x_3|x_2|x_1|x_0
|
||||
; q8 = scratch
|
||||
;
|
||||
; Load y[0...3]
|
||||
; This requires len>0 to always be valid (which we assert in the C code).
|
||||
VLD1.16 {d5}, [r5]!
|
||||
SUBS r12, r3, #8
|
||||
BLE xcorr_kernel_neon_process4
|
||||
; Process 8 samples at a time.
|
||||
; This loop loads one y value more than we actually need. Therefore we have to
|
||||
; stop as soon as there are 8 or fewer samples left (instead of 7), to avoid
|
||||
; reading past the end of the array.
|
||||
xcorr_kernel_neon_process8
|
||||
; This loop has 19 total instructions (10 cycles to issue, minimum), with
|
||||
; - 2 cycles of ARM insrtuctions,
|
||||
; - 10 cycles of load/store/byte permute instructions, and
|
||||
; - 9 cycles of data processing instructions.
|
||||
; On a Cortex A8, we dual-issue the maximum amount (9 cycles) between the
|
||||
; latter two categories, meaning the whole loop should run in 10 cycles per
|
||||
; iteration, barring cache misses.
|
||||
;
|
||||
; Load x[0...7]
|
||||
VLD1.16 {d6, d7}, [r4]!
|
||||
; Unlike VMOV, VAND is a data processsing instruction (and doesn't get
|
||||
; assembled to VMOV, like VORR would), so it dual-issues with the prior VLD1.
|
||||
VAND d3, d5, d5
|
||||
SUBS r12, r12, #8
|
||||
; Load y[4...11]
|
||||
VLD1.16 {d4, d5}, [r5]!
|
||||
VMLAL.S16 q0, d3, d6[0]
|
||||
VEXT.16 d16, d3, d4, #1
|
||||
VMLAL.S16 q0, d4, d7[0]
|
||||
VEXT.16 d17, d4, d5, #1
|
||||
VMLAL.S16 q0, d16, d6[1]
|
||||
VEXT.16 d16, d3, d4, #2
|
||||
VMLAL.S16 q0, d17, d7[1]
|
||||
VEXT.16 d17, d4, d5, #2
|
||||
VMLAL.S16 q0, d16, d6[2]
|
||||
VEXT.16 d16, d3, d4, #3
|
||||
VMLAL.S16 q0, d17, d7[2]
|
||||
VEXT.16 d17, d4, d5, #3
|
||||
VMLAL.S16 q0, d16, d6[3]
|
||||
VMLAL.S16 q0, d17, d7[3]
|
||||
BGT xcorr_kernel_neon_process8
|
||||
; Process 4 samples here if we have > 4 left (still reading one extra y value).
|
||||
xcorr_kernel_neon_process4
|
||||
ADDS r12, r12, #4
|
||||
BLE xcorr_kernel_neon_process2
|
||||
; Load x[0...3]
|
||||
VLD1.16 d6, [r4]!
|
||||
; Use VAND since it's a data processing instruction again.
|
||||
VAND d4, d5, d5
|
||||
SUB r12, r12, #4
|
||||
; Load y[4...7]
|
||||
VLD1.16 d5, [r5]!
|
||||
VMLAL.S16 q0, d4, d6[0]
|
||||
VEXT.16 d16, d4, d5, #1
|
||||
VMLAL.S16 q0, d16, d6[1]
|
||||
VEXT.16 d16, d4, d5, #2
|
||||
VMLAL.S16 q0, d16, d6[2]
|
||||
VEXT.16 d16, d4, d5, #3
|
||||
VMLAL.S16 q0, d16, d6[3]
|
||||
; Process 2 samples here if we have > 2 left (still reading one extra y value).
|
||||
xcorr_kernel_neon_process2
|
||||
ADDS r12, r12, #2
|
||||
BLE xcorr_kernel_neon_process1
|
||||
; Load x[0...1]
|
||||
VLD2.16 {d6[],d7[]}, [r4]!
|
||||
; Use VAND since it's a data processing instruction again.
|
||||
VAND d4, d5, d5
|
||||
SUB r12, r12, #2
|
||||
; Load y[4...5]
|
||||
VLD1.32 {d5[]}, [r5]!
|
||||
VMLAL.S16 q0, d4, d6
|
||||
VEXT.16 d16, d4, d5, #1
|
||||
; Replace bottom copy of {y5,y4} in d5 with {y3,y2} from d4, using VSRI
|
||||
; instead of VEXT, since it's a data-processing instruction.
|
||||
VSRI.64 d5, d4, #32
|
||||
VMLAL.S16 q0, d16, d7
|
||||
; Process 1 sample using the extra y value we loaded above.
|
||||
xcorr_kernel_neon_process1
|
||||
; Load next *x
|
||||
VLD1.16 {d6[]}, [r4]!
|
||||
ADDS r12, r12, #1
|
||||
; y[0...3] are left in d5 from prior iteration(s) (if any)
|
||||
VMLAL.S16 q0, d5, d6
|
||||
MOVLE pc, lr
|
||||
; Now process 1 last sample, not reading ahead.
|
||||
; Load last *y
|
||||
VLD1.16 {d4[]}, [r5]!
|
||||
VSRI.64 d4, d5, #16
|
||||
; Load last *x
|
||||
VLD1.16 {d6[]}, [r4]!
|
||||
VMLAL.S16 q0, d4, d6
|
||||
MOV pc, lr
|
||||
ENDP
|
||||
|
||||
; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
|
||||
; opus_val32 *xcorr, int len, int max_pitch, int arch)
|
||||
celt_pitch_xcorr_neon PROC
|
||||
; input:
|
||||
; r0 = opus_val16 *_x
|
||||
; r1 = opus_val16 *_y
|
||||
; r2 = opus_val32 *xcorr
|
||||
; r3 = int len
|
||||
; output:
|
||||
; r0 = int maxcorr
|
||||
; internal usage:
|
||||
; r4 = opus_val16 *x (for xcorr_kernel_neon())
|
||||
; r5 = opus_val16 *y (for xcorr_kernel_neon())
|
||||
; r6 = int max_pitch
|
||||
; r12 = int j
|
||||
; q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon())
|
||||
; ignored:
|
||||
; int arch
|
||||
STMFD sp!, {r4-r6, lr}
|
||||
LDR r6, [sp, #16]
|
||||
VMOV.S32 q15, #1
|
||||
; if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
|
||||
SUBS r6, r6, #4
|
||||
BLT celt_pitch_xcorr_neon_process4_done
|
||||
celt_pitch_xcorr_neon_process4
|
||||
; xcorr_kernel_neon parameters:
|
||||
; r3 = len, r4 = _x, r5 = _y, q0 = {0, 0, 0, 0}
|
||||
MOV r4, r0
|
||||
MOV r5, r1
|
||||
VEOR q0, q0, q0
|
||||
; xcorr_kernel_neon only modifies r4, r5, r12, and q0...q3.
|
||||
; So we don't save/restore any other registers.
|
||||
BL xcorr_kernel_neon_start
|
||||
SUBS r6, r6, #4
|
||||
VST1.32 {q0}, [r2]!
|
||||
; _y += 4
|
||||
ADD r1, r1, #8
|
||||
VMAX.S32 q15, q15, q0
|
||||
; if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
|
||||
BGE celt_pitch_xcorr_neon_process4
|
||||
; We have less than 4 sums left to compute.
|
||||
celt_pitch_xcorr_neon_process4_done
|
||||
ADDS r6, r6, #4
|
||||
; Reduce maxcorr to a single value
|
||||
VMAX.S32 d30, d30, d31
|
||||
VPMAX.S32 d30, d30, d30
|
||||
; if (max_pitch <= 0) goto celt_pitch_xcorr_neon_done
|
||||
BLE celt_pitch_xcorr_neon_done
|
||||
; Now compute each remaining sum one at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining
|
||||
MOV r4, r0
|
||||
MOV r5, r1
|
||||
VMOV.I32 q0, #0
|
||||
SUBS r12, r3, #8
|
||||
BLT celt_pitch_xcorr_neon_process_remaining4
|
||||
; Sum terms 8 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining_loop8
|
||||
; Load x[0...7]
|
||||
VLD1.16 {q1}, [r4]!
|
||||
; Load y[0...7]
|
||||
VLD1.16 {q2}, [r5]!
|
||||
SUBS r12, r12, #8
|
||||
VMLAL.S16 q0, d4, d2
|
||||
VMLAL.S16 q0, d5, d3
|
||||
BGE celt_pitch_xcorr_neon_process_remaining_loop8
|
||||
; Sum terms 4 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining4
|
||||
ADDS r12, r12, #4
|
||||
BLT celt_pitch_xcorr_neon_process_remaining4_done
|
||||
; Load x[0...3]
|
||||
VLD1.16 {d2}, [r4]!
|
||||
; Load y[0...3]
|
||||
VLD1.16 {d3}, [r5]!
|
||||
SUB r12, r12, #4
|
||||
VMLAL.S16 q0, d3, d2
|
||||
celt_pitch_xcorr_neon_process_remaining4_done
|
||||
; Reduce the sum to a single value.
|
||||
VADD.S32 d0, d0, d1
|
||||
VPADDL.S32 d0, d0
|
||||
ADDS r12, r12, #4
|
||||
BLE celt_pitch_xcorr_neon_process_remaining_loop_done
|
||||
; Sum terms 1 at a time.
|
||||
celt_pitch_xcorr_neon_process_remaining_loop1
|
||||
VLD1.16 {d2[]}, [r4]!
|
||||
VLD1.16 {d3[]}, [r5]!
|
||||
SUBS r12, r12, #1
|
||||
VMLAL.S16 q0, d2, d3
|
||||
BGT celt_pitch_xcorr_neon_process_remaining_loop1
|
||||
celt_pitch_xcorr_neon_process_remaining_loop_done
|
||||
VST1.32 {d0[0]}, [r2]!
|
||||
VMAX.S32 d30, d30, d0
|
||||
SUBS r6, r6, #1
|
||||
; _y++
|
||||
ADD r1, r1, #2
|
||||
; if (--max_pitch > 0) goto celt_pitch_xcorr_neon_process_remaining
|
||||
BGT celt_pitch_xcorr_neon_process_remaining
|
||||
celt_pitch_xcorr_neon_done
|
||||
VMOV.32 r0, d30[0]
|
||||
LDMFD sp!, {r4-r6, pc}
|
||||
ENDP
|
||||
|
||||
ENDIF
|
||||
|
||||
IF OPUS_ARM_MAY_HAVE_EDSP
|
||||
|
||||
; This will get used on ARMv7 devices without NEON, so it has been optimized
|
||||
; to take advantage of dual-issuing where possible.
|
||||
xcorr_kernel_edsp PROC
|
||||
xcorr_kernel_edsp_start
|
||||
; input:
|
||||
; r3 = int len
|
||||
; r4 = opus_val16 *_x (must be 32-bit aligned)
|
||||
; r5 = opus_val16 *_y (must be 32-bit aligned)
|
||||
; r6...r9 = opus_val32 sum[4]
|
||||
; output:
|
||||
; r6...r9 = opus_val32 sum[4]
|
||||
; preserved: r0-r5
|
||||
; internal usage
|
||||
; r2 = int j
|
||||
; r12,r14 = opus_val16 x[4]
|
||||
; r10,r11 = opus_val16 y[4]
|
||||
STMFD sp!, {r2,r4,r5,lr}
|
||||
LDR r10, [r5], #4 ; Load y[0...1]
|
||||
SUBS r2, r3, #4 ; j = len-4
|
||||
LDR r11, [r5], #4 ; Load y[2...3]
|
||||
BLE xcorr_kernel_edsp_process4_done
|
||||
LDR r12, [r4], #4 ; Load x[0...1]
|
||||
; Stall
|
||||
xcorr_kernel_edsp_process4
|
||||
; The multiplies must issue from pipeline 0, and can't dual-issue with each
|
||||
; other. Every other instruction here dual-issues with a multiply, and is
|
||||
; thus "free". There should be no stalls in the body of the loop.
|
||||
SMLABB r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x_0,y_0)
|
||||
LDR r14, [r4], #4 ; Load x[2...3]
|
||||
SMLABT r7, r12, r10, r7 ; sum[1] = MAC16_16(sum[1],x_0,y_1)
|
||||
SUBS r2, r2, #4 ; j-=4
|
||||
SMLABB r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x_0,y_2)
|
||||
SMLABT r9, r12, r11, r9 ; sum[3] = MAC16_16(sum[3],x_0,y_3)
|
||||
SMLATT r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x_1,y_1)
|
||||
LDR r10, [r5], #4 ; Load y[4...5]
|
||||
SMLATB r7, r12, r11, r7 ; sum[1] = MAC16_16(sum[1],x_1,y_2)
|
||||
SMLATT r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x_1,y_3)
|
||||
SMLATB r9, r12, r10, r9 ; sum[3] = MAC16_16(sum[3],x_1,y_4)
|
||||
LDRGT r12, [r4], #4 ; Load x[0...1]
|
||||
SMLABB r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],x_2,y_2)
|
||||
SMLABT r7, r14, r11, r7 ; sum[1] = MAC16_16(sum[1],x_2,y_3)
|
||||
SMLABB r8, r14, r10, r8 ; sum[2] = MAC16_16(sum[2],x_2,y_4)
|
||||
SMLABT r9, r14, r10, r9 ; sum[3] = MAC16_16(sum[3],x_2,y_5)
|
||||
SMLATT r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],x_3,y_3)
|
||||
LDR r11, [r5], #4 ; Load y[6...7]
|
||||
SMLATB r7, r14, r10, r7 ; sum[1] = MAC16_16(sum[1],x_3,y_4)
|
||||
SMLATT r8, r14, r10, r8 ; sum[2] = MAC16_16(sum[2],x_3,y_5)
|
||||
SMLATB r9, r14, r11, r9 ; sum[3] = MAC16_16(sum[3],x_3,y_6)
|
||||
BGT xcorr_kernel_edsp_process4
|
||||
xcorr_kernel_edsp_process4_done
|
||||
ADDS r2, r2, #4
|
||||
BLE xcorr_kernel_edsp_done
|
||||
LDRH r12, [r4], #2 ; r12 = *x++
|
||||
SUBS r2, r2, #1 ; j--
|
||||
; Stall
|
||||
SMLABB r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x,y_0)
|
||||
LDRHGT r14, [r4], #2 ; r14 = *x++
|
||||
SMLABT r7, r12, r10, r7 ; sum[1] = MAC16_16(sum[1],x,y_1)
|
||||
SMLABB r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x,y_2)
|
||||
SMLABT r9, r12, r11, r9 ; sum[3] = MAC16_16(sum[3],x,y_3)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABT r6, r14, r10, r6 ; sum[0] = MAC16_16(sum[0],x,y_1)
|
||||
SUBS r2, r2, #1 ; j--
|
||||
SMLABB r7, r14, r11, r7 ; sum[1] = MAC16_16(sum[1],x,y_2)
|
||||
LDRH r10, [r5], #2 ; r10 = y_4 = *y++
|
||||
SMLABT r8, r14, r11, r8 ; sum[2] = MAC16_16(sum[2],x,y_3)
|
||||
LDRHGT r12, [r4], #2 ; r12 = *x++
|
||||
SMLABB r9, r14, r10, r9 ; sum[3] = MAC16_16(sum[3],x,y_4)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABB r6, r12, r11, r6 ; sum[0] = MAC16_16(sum[0],tmp,y_2)
|
||||
CMP r2, #1 ; j--
|
||||
SMLABT r7, r12, r11, r7 ; sum[1] = MAC16_16(sum[1],tmp,y_3)
|
||||
LDRH r2, [r5], #2 ; r2 = y_5 = *y++
|
||||
SMLABB r8, r12, r10, r8 ; sum[2] = MAC16_16(sum[2],tmp,y_4)
|
||||
LDRHGT r14, [r4] ; r14 = *x
|
||||
SMLABB r9, r12, r2, r9 ; sum[3] = MAC16_16(sum[3],tmp,y_5)
|
||||
BLE xcorr_kernel_edsp_done
|
||||
SMLABT r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],tmp,y_3)
|
||||
LDRH r11, [r5] ; r11 = y_6 = *y
|
||||
SMLABB r7, r14, r10, r7 ; sum[1] = MAC16_16(sum[1],tmp,y_4)
|
||||
SMLABB r8, r14, r2, r8 ; sum[2] = MAC16_16(sum[2],tmp,y_5)
|
||||
SMLABB r9, r14, r11, r9 ; sum[3] = MAC16_16(sum[3],tmp,y_6)
|
||||
xcorr_kernel_edsp_done
|
||||
LDMFD sp!, {r2,r4,r5,pc}
|
||||
ENDP
|
||||
|
||||
celt_pitch_xcorr_edsp PROC
|
||||
; input:
|
||||
; r0 = opus_val16 *_x (must be 32-bit aligned)
|
||||
; r1 = opus_val16 *_y (only needs to be 16-bit aligned)
|
||||
; r2 = opus_val32 *xcorr
|
||||
; r3 = int len
|
||||
; output:
|
||||
; r0 = maxcorr
|
||||
; internal usage
|
||||
; r4 = opus_val16 *x
|
||||
; r5 = opus_val16 *y
|
||||
; r6 = opus_val32 sum0
|
||||
; r7 = opus_val32 sum1
|
||||
; r8 = opus_val32 sum2
|
||||
; r9 = opus_val32 sum3
|
||||
; r1 = int max_pitch
|
||||
; r12 = int j
|
||||
; ignored:
|
||||
; int arch
|
||||
STMFD sp!, {r4-r11, lr}
|
||||
MOV r5, r1
|
||||
LDR r1, [sp, #36]
|
||||
MOV r4, r0
|
||||
TST r5, #3
|
||||
; maxcorr = 1
|
||||
MOV r0, #1
|
||||
BEQ celt_pitch_xcorr_edsp_process1u_done
|
||||
; Compute one sum at the start to make y 32-bit aligned.
|
||||
SUBS r12, r3, #4
|
||||
; r14 = sum = 0
|
||||
MOV r14, #0
|
||||
LDRH r8, [r5], #2
|
||||
BLE celt_pitch_xcorr_edsp_process1u_loop4_done
|
||||
LDR r6, [r4], #4
|
||||
MOV r8, r8, LSL #16
|
||||
celt_pitch_xcorr_edsp_process1u_loop4
|
||||
LDR r9, [r5], #4
|
||||
SMLABT r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
|
||||
LDR r7, [r4], #4
|
||||
SMLATB r14, r6, r9, r14 ; sum = MAC16_16(sum, x_1, y_1)
|
||||
LDR r8, [r5], #4
|
||||
SMLABT r14, r7, r9, r14 ; sum = MAC16_16(sum, x_2, y_2)
|
||||
SUBS r12, r12, #4 ; j-=4
|
||||
SMLATB r14, r7, r8, r14 ; sum = MAC16_16(sum, x_3, y_3)
|
||||
LDRGT r6, [r4], #4
|
||||
BGT celt_pitch_xcorr_edsp_process1u_loop4
|
||||
MOV r8, r8, LSR #16
|
||||
celt_pitch_xcorr_edsp_process1u_loop4_done
|
||||
ADDS r12, r12, #4
|
||||
celt_pitch_xcorr_edsp_process1u_loop1
|
||||
LDRHGE r6, [r4], #2
|
||||
; Stall
|
||||
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, *x, *y)
|
||||
SUBSGE r12, r12, #1
|
||||
LDRHGT r8, [r5], #2
|
||||
BGT celt_pitch_xcorr_edsp_process1u_loop1
|
||||
; Restore _x
|
||||
SUB r4, r4, r3, LSL #1
|
||||
; Restore and advance _y
|
||||
SUB r5, r5, r3, LSL #1
|
||||
; maxcorr = max(maxcorr, sum)
|
||||
CMP r0, r14
|
||||
ADD r5, r5, #2
|
||||
MOVLT r0, r14
|
||||
SUBS r1, r1, #1
|
||||
; xcorr[i] = sum
|
||||
STR r14, [r2], #4
|
||||
BLE celt_pitch_xcorr_edsp_done
|
||||
celt_pitch_xcorr_edsp_process1u_done
|
||||
; if (max_pitch < 4) goto celt_pitch_xcorr_edsp_process2
|
||||
SUBS r1, r1, #4
|
||||
BLT celt_pitch_xcorr_edsp_process2
|
||||
celt_pitch_xcorr_edsp_process4
|
||||
; xcorr_kernel_edsp parameters:
|
||||
; r3 = len, r4 = _x, r5 = _y, r6...r9 = sum[4] = {0, 0, 0, 0}
|
||||
MOV r6, #0
|
||||
MOV r7, #0
|
||||
MOV r8, #0
|
||||
MOV r9, #0
|
||||
BL xcorr_kernel_edsp_start ; xcorr_kernel_edsp(_x, _y+i, xcorr+i, len)
|
||||
; maxcorr = max(maxcorr, sum0, sum1, sum2, sum3)
|
||||
CMP r0, r6
|
||||
; _y+=4
|
||||
ADD r5, r5, #8
|
||||
MOVLT r0, r6
|
||||
CMP r0, r7
|
||||
MOVLT r0, r7
|
||||
CMP r0, r8
|
||||
MOVLT r0, r8
|
||||
CMP r0, r9
|
||||
MOVLT r0, r9
|
||||
STMIA r2!, {r6-r9}
|
||||
SUBS r1, r1, #4
|
||||
BGE celt_pitch_xcorr_edsp_process4
|
||||
celt_pitch_xcorr_edsp_process2
|
||||
ADDS r1, r1, #2
|
||||
BLT celt_pitch_xcorr_edsp_process1a
|
||||
SUBS r12, r3, #4
|
||||
; {r10, r11} = {sum0, sum1} = {0, 0}
|
||||
MOV r10, #0
|
||||
MOV r11, #0
|
||||
LDR r8, [r5], #4
|
||||
BLE celt_pitch_xcorr_edsp_process2_loop_done
|
||||
LDR r6, [r4], #4
|
||||
LDR r9, [r5], #4
|
||||
celt_pitch_xcorr_edsp_process2_loop4
|
||||
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDR r7, [r4], #4
|
||||
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
SUBS r12, r12, #4 ; j-=4
|
||||
SMLATT r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_1, y_1)
|
||||
LDR r8, [r5], #4
|
||||
SMLATB r11, r6, r9, r11 ; sum1 = MAC16_16(sum1, x_1, y_2)
|
||||
LDRGT r6, [r4], #4
|
||||
SMLABB r10, r7, r9, r10 ; sum0 = MAC16_16(sum0, x_2, y_2)
|
||||
SMLABT r11, r7, r9, r11 ; sum1 = MAC16_16(sum1, x_2, y_3)
|
||||
SMLATT r10, r7, r9, r10 ; sum0 = MAC16_16(sum0, x_3, y_3)
|
||||
LDRGT r9, [r5], #4
|
||||
SMLATB r11, r7, r8, r11 ; sum1 = MAC16_16(sum1, x_3, y_4)
|
||||
BGT celt_pitch_xcorr_edsp_process2_loop4
|
||||
celt_pitch_xcorr_edsp_process2_loop_done
|
||||
ADDS r12, r12, #2
|
||||
BLE celt_pitch_xcorr_edsp_process2_1
|
||||
LDR r6, [r4], #4
|
||||
; Stall
|
||||
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDR r9, [r5], #4
|
||||
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
SUB r12, r12, #2
|
||||
SMLATT r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_1, y_1)
|
||||
MOV r8, r9
|
||||
SMLATB r11, r6, r9, r11 ; sum1 = MAC16_16(sum1, x_1, y_2)
|
||||
celt_pitch_xcorr_edsp_process2_1
|
||||
LDRH r6, [r4], #2
|
||||
ADDS r12, r12, #1
|
||||
; Stall
|
||||
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
|
||||
LDRHGT r7, [r4], #2
|
||||
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
|
||||
BLE celt_pitch_xcorr_edsp_process2_done
|
||||
LDRH r9, [r5], #2
|
||||
SMLABT r10, r7, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_1)
|
||||
SMLABB r11, r7, r9, r11 ; sum1 = MAC16_16(sum1, x_0, y_2)
|
||||
celt_pitch_xcorr_edsp_process2_done
|
||||
; Restore _x
|
||||
SUB r4, r4, r3, LSL #1
|
||||
; Restore and advance _y
|
||||
SUB r5, r5, r3, LSL #1
|
||||
; maxcorr = max(maxcorr, sum0)
|
||||
CMP r0, r10
|
||||
ADD r5, r5, #2
|
||||
MOVLT r0, r10
|
||||
SUB r1, r1, #2
|
||||
; maxcorr = max(maxcorr, sum1)
|
||||
CMP r0, r11
|
||||
; xcorr[i] = sum
|
||||
STR r10, [r2], #4
|
||||
MOVLT r0, r11
|
||||
STR r11, [r2], #4
|
||||
celt_pitch_xcorr_edsp_process1a
|
||||
ADDS r1, r1, #1
|
||||
BLT celt_pitch_xcorr_edsp_done
|
||||
SUBS r12, r3, #4
|
||||
; r14 = sum = 0
|
||||
MOV r14, #0
|
||||
BLT celt_pitch_xcorr_edsp_process1a_loop_done
|
||||
LDR r6, [r4], #4
|
||||
LDR r8, [r5], #4
|
||||
LDR r7, [r4], #4
|
||||
LDR r9, [r5], #4
|
||||
celt_pitch_xcorr_edsp_process1a_loop4
|
||||
SMLABB r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
|
||||
SUBS r12, r12, #4 ; j-=4
|
||||
SMLATT r14, r6, r8, r14 ; sum = MAC16_16(sum, x_1, y_1)
|
||||
LDRGE r6, [r4], #4
|
||||
SMLABB r14, r7, r9, r14 ; sum = MAC16_16(sum, x_2, y_2)
|
||||
LDRGE r8, [r5], #4
|
||||
SMLATT r14, r7, r9, r14 ; sum = MAC16_16(sum, x_3, y_3)
|
||||
LDRGE r7, [r4], #4
|
||||
LDRGE r9, [r5], #4
|
||||
BGE celt_pitch_xcorr_edsp_process1a_loop4
|
||||
celt_pitch_xcorr_edsp_process1a_loop_done
|
||||
ADDS r12, r12, #2
|
||||
LDRGE r6, [r4], #4
|
||||
LDRGE r8, [r5], #4
|
||||
; Stall
|
||||
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
|
||||
SUBGE r12, r12, #2
|
||||
SMLATTGE r14, r6, r8, r14 ; sum = MAC16_16(sum, x_1, y_1)
|
||||
ADDS r12, r12, #1
|
||||
LDRHGE r6, [r4], #2
|
||||
LDRHGE r8, [r5], #2
|
||||
; Stall
|
||||
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, *x, *y)
|
||||
; maxcorr = max(maxcorr, sum)
|
||||
CMP r0, r14
|
||||
; xcorr[i] = sum
|
||||
STR r14, [r2], #4
|
||||
MOVLT r0, r14
|
||||
celt_pitch_xcorr_edsp_done
|
||||
LDMFD sp!, {r4-r11, pc}
|
||||
ENDP
|
||||
|
||||
ENDIF
|
||||
|
||||
END
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* Copyright (c) 2015 Xiph.Org Foundation
|
||||
Written by Viswanath Puttagunta */
|
||||
/**
|
||||
@file fft_arm.h
|
||||
@brief ARM Neon Intrinsic optimizations for fft using NE10 library
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(FFT_ARM_H)
|
||||
#define FFT_ARM_H
|
||||
|
||||
#include "kiss_fft.h"
|
||||
|
||||
#if defined(HAVE_ARM_NE10)
|
||||
|
||||
int opus_fft_alloc_arm_neon(kiss_fft_state *st);
|
||||
void opus_fft_free_arm_neon(kiss_fft_state *st);
|
||||
|
||||
void opus_fft_neon(const kiss_fft_state *st,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout);
|
||||
|
||||
void opus_ifft_neon(const kiss_fft_state *st,
|
||||
const kiss_fft_cpx *fin,
|
||||
kiss_fft_cpx *fout);
|
||||
|
||||
#if !defined(OPUS_HAVE_RTCD)
|
||||
#define OVERRIDE_OPUS_FFT (1)
|
||||
|
||||
#define opus_fft_alloc_arch(_st, arch) \
|
||||
((void)(arch), opus_fft_alloc_arm_neon(_st))
|
||||
|
||||
#define opus_fft_free_arch(_st, arch) \
|
||||
((void)(arch), opus_fft_free_arm_neon(_st))
|
||||
|
||||
#define opus_fft(_st, _fin, _fout, arch) \
|
||||
((void)(arch), opus_fft_neon(_st, _fin, _fout))
|
||||
|
||||
#define opus_ifft(_st, _fin, _fout, arch) \
|
||||
((void)(arch), opus_ifft_neon(_st, _fin, _fout))
|
||||
|
||||
#endif /* OPUS_HAVE_RTCD */
|
||||
|
||||
#endif /* HAVE_ARM_NE10 */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* Copyright (C) 2015 Vidyo */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_ARM64_H
|
||||
#define FIXED_ARM64_H
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#undef SIG2WORD16
|
||||
#define SIG2WORD16(x) (vqmovns_s32(PSHR32((x), SIG_SHIFT)))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/* Copyright (C) 2013 Xiph.Org Foundation and contributors */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_ARMv4_H
|
||||
#define FIXED_ARMv4_H
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
|
||||
#undef MULT16_32_Q16
|
||||
static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b)
|
||||
{
|
||||
unsigned rd_lo;
|
||||
int rd_hi;
|
||||
__asm__(
|
||||
"#MULT16_32_Q16\n\t"
|
||||
"smull %0, %1, %2, %3\n\t"
|
||||
: "=&r"(rd_lo), "=&r"(rd_hi)
|
||||
: "%r"(b),"r"(SHL32(a,16))
|
||||
);
|
||||
return rd_hi;
|
||||
}
|
||||
#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv4(a, b))
|
||||
|
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
|
||||
#undef MULT16_32_Q15
|
||||
static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b)
|
||||
{
|
||||
unsigned rd_lo;
|
||||
int rd_hi;
|
||||
__asm__(
|
||||
"#MULT16_32_Q15\n\t"
|
||||
"smull %0, %1, %2, %3\n\t"
|
||||
: "=&r"(rd_lo), "=&r"(rd_hi)
|
||||
: "%r"(b), "r"(SHL32(a,16))
|
||||
);
|
||||
/*We intentionally don't OR in the high bit of rd_lo for speed.*/
|
||||
return SHL32(rd_hi,1);
|
||||
}
|
||||
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b))
|
||||
|
||||
|
||||
/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
|
||||
b must fit in 31 bits.
|
||||
Result fits in 32 bits. */
|
||||
#undef MAC16_32_Q15
|
||||
#define MAC16_32_Q15(c, a, b) ADD32(c, MULT16_32_Q15(a, b))
|
||||
|
||||
/** 16x32 multiply, followed by a 16-bit shift right and 32-bit add.
|
||||
Result fits in 32 bits. */
|
||||
#undef MAC16_32_Q16
|
||||
#define MAC16_32_Q16(c, a, b) ADD32(c, MULT16_32_Q16(a, b))
|
||||
|
||||
/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
|
||||
#undef MULT32_32_Q31
|
||||
#define MULT32_32_Q31(a,b) (opus_val32)((((opus_int64)(a)) * ((opus_int64)(b)))>>31)
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/* Copyright (C) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (C) 2003-2008 Jean-Marc Valin
|
||||
Copyright (C) 2007-2008 CSIRO
|
||||
Copyright (C) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_ARMv5E_H
|
||||
#define FIXED_ARMv5E_H
|
||||
|
||||
#include "fixed_armv4.h"
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
|
||||
#undef MULT16_32_Q16
|
||||
static OPUS_INLINE opus_val32 MULT16_32_Q16_armv5e(opus_val16 a, opus_val32 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MULT16_32_Q16\n\t"
|
||||
"smulwb %0, %1, %2\n\t"
|
||||
: "=r"(res)
|
||||
: "r"(b),"r"(a)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv5e(a, b))
|
||||
|
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
|
||||
#undef MULT16_32_Q15
|
||||
static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MULT16_32_Q15\n\t"
|
||||
"smulwb %0, %1, %2\n\t"
|
||||
: "=r"(res)
|
||||
: "r"(b), "r"(a)
|
||||
);
|
||||
return SHL32(res,1);
|
||||
}
|
||||
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b))
|
||||
|
||||
|
||||
/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
|
||||
b must fit in 31 bits.
|
||||
Result fits in 32 bits. */
|
||||
#undef MAC16_32_Q15
|
||||
static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a,
|
||||
opus_val32 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MAC16_32_Q15\n\t"
|
||||
"smlawb %0, %1, %2, %3;\n"
|
||||
: "=r"(res)
|
||||
: "r"(SHL32(b,1)), "r"(a), "r"(c)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#define MAC16_32_Q15(c, a, b) (MAC16_32_Q15_armv5e(c, a, b))
|
||||
|
||||
/** 16x32 multiply, followed by a 16-bit shift right and 32-bit add.
|
||||
Result fits in 32 bits. */
|
||||
#undef MAC16_32_Q16
|
||||
static OPUS_INLINE opus_val32 MAC16_32_Q16_armv5e(opus_val32 c, opus_val16 a,
|
||||
opus_val32 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MAC16_32_Q16\n\t"
|
||||
"smlawb %0, %1, %2, %3;\n"
|
||||
: "=r"(res)
|
||||
: "r"(b), "r"(a), "r"(c)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#define MAC16_32_Q16(c, a, b) (MAC16_32_Q16_armv5e(c, a, b))
|
||||
|
||||
/** 16x16 multiply-add where the result fits in 32 bits */
|
||||
#undef MAC16_16
|
||||
static OPUS_INLINE opus_val32 MAC16_16_armv5e(opus_val32 c, opus_val16 a,
|
||||
opus_val16 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MAC16_16\n\t"
|
||||
"smlabb %0, %1, %2, %3;\n"
|
||||
: "=r"(res)
|
||||
: "r"(a), "r"(b), "r"(c)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#define MAC16_16(c, a, b) (MAC16_16_armv5e(c, a, b))
|
||||
|
||||
/** 16x16 multiplication where the result fits in 32 bits */
|
||||
#undef MULT16_16
|
||||
static OPUS_INLINE opus_val32 MULT16_16_armv5e(opus_val16 a, opus_val16 b)
|
||||
{
|
||||
int res;
|
||||
__asm__(
|
||||
"#MULT16_16\n\t"
|
||||
"smulbb %0, %1, %2;\n"
|
||||
: "=r"(res)
|
||||
: "r"(a), "r"(b)
|
||||
);
|
||||
return res;
|
||||
}
|
||||
#define MULT16_16(a, b) (MULT16_16_armv5e(a, b))
|
||||
|
||||
#ifdef OPUS_ARM_INLINE_MEDIA
|
||||
|
||||
#undef SIG2WORD16
|
||||
static OPUS_INLINE opus_val16 SIG2WORD16_armv6(opus_val32 x)
|
||||
{
|
||||
celt_sig res;
|
||||
__asm__(
|
||||
"#SIG2WORD16\n\t"
|
||||
"ssat %0, #16, %1, ASR #12\n\t"
|
||||
: "=r"(res)
|
||||
: "r"(x+2048)
|
||||
);
|
||||
return EXTRACT16(res);
|
||||
}
|
||||
#define SIG2WORD16(x) (SIG2WORD16_armv6(x))
|
||||
|
||||
#endif /* OPUS_ARM_INLINE_MEDIA */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*Copyright (c) 2013, Xiph.Org Foundation and contributors.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
#ifndef KISS_FFT_ARMv4_H
|
||||
#define KISS_FFT_ARMv4_H
|
||||
|
||||
#if !defined(KISS_FFT_GUTS_H)
|
||||
#error "This file should only be included from _kiss_fft_guts.h"
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
#undef C_MUL
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ \
|
||||
int br__; \
|
||||
int bi__; \
|
||||
int tt__; \
|
||||
__asm__ __volatile__( \
|
||||
"#C_MUL\n\t" \
|
||||
"ldrsh %[br], [%[bp], #0]\n\t" \
|
||||
"ldm %[ap], {r0,r1}\n\t" \
|
||||
"ldrsh %[bi], [%[bp], #2]\n\t" \
|
||||
"smull %[tt], %[mi], r1, %[br]\n\t" \
|
||||
"smlal %[tt], %[mi], r0, %[bi]\n\t" \
|
||||
"rsb %[bi], %[bi], #0\n\t" \
|
||||
"smull %[br], %[mr], r0, %[br]\n\t" \
|
||||
"mov %[tt], %[tt], lsr #15\n\t" \
|
||||
"smlal %[br], %[mr], r1, %[bi]\n\t" \
|
||||
"orr %[mi], %[tt], %[mi], lsl #17\n\t" \
|
||||
"mov %[br], %[br], lsr #15\n\t" \
|
||||
"orr %[mr], %[br], %[mr], lsl #17\n\t" \
|
||||
: [mr]"=r"((m).r), [mi]"=r"((m).i), \
|
||||
[br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \
|
||||
: [ap]"r"(&(a)), [bp]"r"(&(b)) \
|
||||
: "r0", "r1" \
|
||||
); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#undef C_MUL4
|
||||
#define C_MUL4(m,a,b) \
|
||||
do{ \
|
||||
int br__; \
|
||||
int bi__; \
|
||||
int tt__; \
|
||||
__asm__ __volatile__( \
|
||||
"#C_MUL4\n\t" \
|
||||
"ldrsh %[br], [%[bp], #0]\n\t" \
|
||||
"ldm %[ap], {r0,r1}\n\t" \
|
||||
"ldrsh %[bi], [%[bp], #2]\n\t" \
|
||||
"smull %[tt], %[mi], r1, %[br]\n\t" \
|
||||
"smlal %[tt], %[mi], r0, %[bi]\n\t" \
|
||||
"rsb %[bi], %[bi], #0\n\t" \
|
||||
"smull %[br], %[mr], r0, %[br]\n\t" \
|
||||
"mov %[tt], %[tt], lsr #17\n\t" \
|
||||
"smlal %[br], %[mr], r1, %[bi]\n\t" \
|
||||
"orr %[mi], %[tt], %[mi], lsl #15\n\t" \
|
||||
"mov %[br], %[br], lsr #17\n\t" \
|
||||
"orr %[mr], %[br], %[mr], lsl #15\n\t" \
|
||||
: [mr]"=r"((m).r), [mi]"=r"((m).i), \
|
||||
[br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \
|
||||
: [ap]"r"(&(a)), [bp]"r"(&(b)) \
|
||||
: "r0", "r1" \
|
||||
); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#undef C_MULC
|
||||
#define C_MULC(m,a,b) \
|
||||
do{ \
|
||||
int br__; \
|
||||
int bi__; \
|
||||
int tt__; \
|
||||
__asm__ __volatile__( \
|
||||
"#C_MULC\n\t" \
|
||||
"ldrsh %[br], [%[bp], #0]\n\t" \
|
||||
"ldm %[ap], {r0,r1}\n\t" \
|
||||
"ldrsh %[bi], [%[bp], #2]\n\t" \
|
||||
"smull %[tt], %[mr], r0, %[br]\n\t" \
|
||||
"smlal %[tt], %[mr], r1, %[bi]\n\t" \
|
||||
"rsb %[bi], %[bi], #0\n\t" \
|
||||
"smull %[br], %[mi], r1, %[br]\n\t" \
|
||||
"mov %[tt], %[tt], lsr #15\n\t" \
|
||||
"smlal %[br], %[mi], r0, %[bi]\n\t" \
|
||||
"orr %[mr], %[tt], %[mr], lsl #17\n\t" \
|
||||
"mov %[br], %[br], lsr #15\n\t" \
|
||||
"orr %[mi], %[br], %[mi], lsl #17\n\t" \
|
||||
: [mr]"=r"((m).r), [mi]"=r"((m).i), \
|
||||
[br]"=&r"(br__), [bi]"=r"(bi__), [tt]"=r"(tt__) \
|
||||
: [ap]"r"(&(a)), [bp]"r"(&(b)) \
|
||||
: "r0", "r1" \
|
||||
); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#endif /* FIXED_POINT */
|
||||
|
||||
#endif /* KISS_FFT_ARMv4_H */
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*Copyright (c) 2013, Xiph.Org Foundation and contributors.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
#ifndef KISS_FFT_ARMv5E_H
|
||||
#define KISS_FFT_ARMv5E_H
|
||||
|
||||
#if !defined(KISS_FFT_GUTS_H)
|
||||
#error "This file should only be included from _kiss_fft_guts.h"
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
#if defined(__thumb__)||defined(__thumb2__)
|
||||
#define LDRD_CONS "Q"
|
||||
#else
|
||||
#define LDRD_CONS "Uq"
|
||||
#endif
|
||||
|
||||
#undef C_MUL
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ \
|
||||
int mr1__; \
|
||||
int mr2__; \
|
||||
int mi__; \
|
||||
long long aval__; \
|
||||
int bval__; \
|
||||
__asm__( \
|
||||
"#C_MUL\n\t" \
|
||||
"ldrd %[aval], %H[aval], %[ap]\n\t" \
|
||||
"ldr %[bval], %[bp]\n\t" \
|
||||
"smulwb %[mi], %H[aval], %[bval]\n\t" \
|
||||
"smulwb %[mr1], %[aval], %[bval]\n\t" \
|
||||
"smulwt %[mr2], %H[aval], %[bval]\n\t" \
|
||||
"smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \
|
||||
: [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \
|
||||
[aval]"=&r"(aval__), [bval]"=r"(bval__) \
|
||||
: [ap]LDRD_CONS(a), [bp]"m"(b) \
|
||||
); \
|
||||
(m).r = SHL32(SUB32(mr1__, mr2__), 1); \
|
||||
(m).i = SHL32(mi__, 1); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#undef C_MUL4
|
||||
#define C_MUL4(m,a,b) \
|
||||
do{ \
|
||||
int mr1__; \
|
||||
int mr2__; \
|
||||
int mi__; \
|
||||
long long aval__; \
|
||||
int bval__; \
|
||||
__asm__( \
|
||||
"#C_MUL4\n\t" \
|
||||
"ldrd %[aval], %H[aval], %[ap]\n\t" \
|
||||
"ldr %[bval], %[bp]\n\t" \
|
||||
"smulwb %[mi], %H[aval], %[bval]\n\t" \
|
||||
"smulwb %[mr1], %[aval], %[bval]\n\t" \
|
||||
"smulwt %[mr2], %H[aval], %[bval]\n\t" \
|
||||
"smlawt %[mi], %[aval], %[bval], %[mi]\n\t" \
|
||||
: [mr1]"=r"(mr1__), [mr2]"=r"(mr2__), [mi]"=r"(mi__), \
|
||||
[aval]"=&r"(aval__), [bval]"=r"(bval__) \
|
||||
: [ap]LDRD_CONS(a), [bp]"m"(b) \
|
||||
); \
|
||||
(m).r = SHR32(SUB32(mr1__, mr2__), 1); \
|
||||
(m).i = SHR32(mi__, 1); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#undef C_MULC
|
||||
#define C_MULC(m,a,b) \
|
||||
do{ \
|
||||
int mr__; \
|
||||
int mi1__; \
|
||||
int mi2__; \
|
||||
long long aval__; \
|
||||
int bval__; \
|
||||
__asm__( \
|
||||
"#C_MULC\n\t" \
|
||||
"ldrd %[aval], %H[aval], %[ap]\n\t" \
|
||||
"ldr %[bval], %[bp]\n\t" \
|
||||
"smulwb %[mr], %[aval], %[bval]\n\t" \
|
||||
"smulwb %[mi1], %H[aval], %[bval]\n\t" \
|
||||
"smulwt %[mi2], %[aval], %[bval]\n\t" \
|
||||
"smlawt %[mr], %H[aval], %[bval], %[mr]\n\t" \
|
||||
: [mr]"=r"(mr__), [mi1]"=r"(mi1__), [mi2]"=r"(mi2__), \
|
||||
[aval]"=&r"(aval__), [bval]"=r"(bval__) \
|
||||
: [ap]LDRD_CONS(a), [bp]"m"(b) \
|
||||
); \
|
||||
(m).r = SHL32(mr__, 1); \
|
||||
(m).i = SHL32(SUB32(mi1__, mi2__), 1); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#endif /* FIXED_POINT */
|
||||
|
||||
#endif /* KISS_FFT_GUTS_H */
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (c) 2015 Xiph.Org Foundation
|
||||
Written by Viswanath Puttagunta */
|
||||
/**
|
||||
@file arm_mdct.h
|
||||
@brief ARM Neon Intrinsic optimizations for mdct using NE10 library
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(MDCT_ARM_H)
|
||||
#define MDCT_ARM_H
|
||||
|
||||
#include "mdct.h"
|
||||
|
||||
#if defined(HAVE_ARM_NE10)
|
||||
/** Compute a forward MDCT and scale by 4/N, trashes the input array */
|
||||
void clt_mdct_forward_neon(const mdct_lookup *l, kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window, int overlap,
|
||||
int shift, int stride, int arch);
|
||||
|
||||
void clt_mdct_backward_neon(const mdct_lookup *l, kiss_fft_scalar *in,
|
||||
kiss_fft_scalar * OPUS_RESTRICT out,
|
||||
const opus_val16 *window, int overlap,
|
||||
int shift, int stride, int arch);
|
||||
|
||||
#if !defined(OPUS_HAVE_RTCD)
|
||||
#define OVERRIDE_OPUS_MDCT (1)
|
||||
#define clt_mdct_forward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \
|
||||
clt_mdct_forward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch)
|
||||
#define clt_mdct_backward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \
|
||||
clt_mdct_backward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch)
|
||||
#endif /* OPUS_HAVE_RTCD */
|
||||
#endif /* HAVE_ARM_NE10 */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(PITCH_ARM_H)
|
||||
# define PITCH_ARM_H
|
||||
|
||||
# include "armcpu.h"
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N);
|
||||
void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01,
|
||||
const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
|
||||
|
||||
# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define OVERRIDE_CELT_INNER_PROD (1)
|
||||
# define OVERRIDE_DUAL_INNER_PROD (1)
|
||||
# define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N))
|
||||
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OVERRIDE_CELT_INNER_PROD)
|
||||
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N);
|
||||
# define OVERRIDE_CELT_INNER_PROD (1)
|
||||
# define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N))
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_CELT_INNER_PROD (1)
|
||||
# define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(OVERRIDE_DUAL_INNER_PROD)
|
||||
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x,
|
||||
const opus_val16 *y01, const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
|
||||
# define OVERRIDE_DUAL_INNER_PROD (1)
|
||||
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_DUAL_INNER_PROD (1)
|
||||
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(FIXED_POINT)
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON)
|
||||
opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
|
||||
opus_val32 *xcorr, int len, int max_pitch, int arch);
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_MEDIA)
|
||||
# define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr)
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_EDSP)
|
||||
opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
|
||||
opus_val32 *xcorr, int len, int max_pitch, int arch);
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_HAVE_RTCD) && \
|
||||
((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
|
||||
(defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
|
||||
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
|
||||
extern opus_val32
|
||||
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
|
||||
const opus_val16 *, opus_val32 *, int, int, int);
|
||||
# define OVERRIDE_PITCH_XCORR (1)
|
||||
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
|
||||
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
|
||||
xcorr, len, max_pitch, arch))
|
||||
|
||||
# elif defined(OPUS_ARM_PRESUME_EDSP) || \
|
||||
defined(OPUS_ARM_PRESUME_MEDIA) || \
|
||||
defined(OPUS_ARM_PRESUME_NEON)
|
||||
# define OVERRIDE_PITCH_XCORR (1)
|
||||
# define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr))
|
||||
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
void xcorr_kernel_neon_fixed(
|
||||
const opus_val16 *x,
|
||||
const opus_val16 *y,
|
||||
opus_val32 sum[4],
|
||||
int len);
|
||||
# endif
|
||||
|
||||
# if defined(OPUS_HAVE_RTCD) && \
|
||||
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
|
||||
extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
|
||||
const opus_val16 *x,
|
||||
const opus_val16 *y,
|
||||
opus_val32 sum[4],
|
||||
int len);
|
||||
|
||||
# define OVERRIDE_XCORR_KERNEL (1)
|
||||
# define xcorr_kernel(x, y, sum, len, arch) \
|
||||
((*XCORR_KERNEL_IMPL[(arch) & OPUS_ARCHMASK])(x, y, sum, len))
|
||||
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
# define OVERRIDE_XCORR_KERNEL (1)
|
||||
# define xcorr_kernel(x, y, sum, len, arch) \
|
||||
((void)arch, xcorr_kernel_neon_fixed(x, y, sum, len))
|
||||
|
||||
# endif
|
||||
|
||||
#else /* Start !FIXED_POINT */
|
||||
/* Float case */
|
||||
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
|
||||
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
|
||||
opus_val32 *xcorr, int len, int max_pitch, int arch);
|
||||
#endif
|
||||
|
||||
# if defined(OPUS_HAVE_RTCD) && \
|
||||
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
|
||||
extern void
|
||||
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
|
||||
const opus_val16 *, opus_val32 *, int, int, int);
|
||||
|
||||
# define OVERRIDE_PITCH_XCORR (1)
|
||||
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
|
||||
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
|
||||
xcorr, len, max_pitch, arch))
|
||||
|
||||
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
|
||||
|
||||
# define OVERRIDE_PITCH_XCORR (1)
|
||||
# define celt_pitch_xcorr celt_pitch_xcorr_float_neon
|
||||
|
||||
# endif
|
||||
|
||||
#endif /* end !FIXED_POINT */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/***********************************************************************
|
||||
Copyright (c) 2017 Google Inc.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Internet Society, IETF or IETF Trust, nor the
|
||||
names of specific contributors, may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include "pitch.h"
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
|
||||
{
|
||||
int i;
|
||||
opus_val32 xy;
|
||||
int16x8_t x_s16x8, y_s16x8;
|
||||
int32x4_t xy_s32x4 = vdupq_n_s32(0);
|
||||
int64x2_t xy_s64x2;
|
||||
int64x1_t xy_s64x1;
|
||||
|
||||
for (i = 0; i < N - 7; i += 8) {
|
||||
x_s16x8 = vld1q_s16(&x[i]);
|
||||
y_s16x8 = vld1q_s16(&y[i]);
|
||||
xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8));
|
||||
xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8));
|
||||
}
|
||||
|
||||
if (N - i >= 4) {
|
||||
const int16x4_t x_s16x4 = vld1_s16(&x[i]);
|
||||
const int16x4_t y_s16x4 = vld1_s16(&y[i]);
|
||||
xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
xy_s64x2 = vpaddlq_s32(xy_s32x4);
|
||||
xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2));
|
||||
xy = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0);
|
||||
|
||||
for (; i < N; i++) {
|
||||
xy = MAC16_16(xy, x[i], y[i]);
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
celt_assert(celt_inner_prod_c(x, y, N) == xy);
|
||||
#endif
|
||||
|
||||
return xy;
|
||||
}
|
||||
|
||||
void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
|
||||
int N, opus_val32 *xy1, opus_val32 *xy2)
|
||||
{
|
||||
int i;
|
||||
opus_val32 xy01, xy02;
|
||||
int16x8_t x_s16x8, y01_s16x8, y02_s16x8;
|
||||
int32x4_t xy01_s32x4 = vdupq_n_s32(0);
|
||||
int32x4_t xy02_s32x4 = vdupq_n_s32(0);
|
||||
int64x2_t xy01_s64x2, xy02_s64x2;
|
||||
int64x1_t xy01_s64x1, xy02_s64x1;
|
||||
|
||||
for (i = 0; i < N - 7; i += 8) {
|
||||
x_s16x8 = vld1q_s16(&x[i]);
|
||||
y01_s16x8 = vld1q_s16(&y01[i]);
|
||||
y02_s16x8 = vld1q_s16(&y02[i]);
|
||||
xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8));
|
||||
xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8));
|
||||
xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8));
|
||||
xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8));
|
||||
}
|
||||
|
||||
if (N - i >= 4) {
|
||||
const int16x4_t x_s16x4 = vld1_s16(&x[i]);
|
||||
const int16x4_t y01_s16x4 = vld1_s16(&y01[i]);
|
||||
const int16x4_t y02_s16x4 = vld1_s16(&y02[i]);
|
||||
xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4);
|
||||
xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
xy01_s64x2 = vpaddlq_s32(xy01_s32x4);
|
||||
xy02_s64x2 = vpaddlq_s32(xy02_s32x4);
|
||||
xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2));
|
||||
xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2));
|
||||
xy01 = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0);
|
||||
xy02 = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0);
|
||||
|
||||
for (; i < N; i++) {
|
||||
xy01 = MAC16_16(xy01, x[i], y01[i]);
|
||||
xy02 = MAC16_16(xy02, x[i], y02[i]);
|
||||
}
|
||||
*xy1 = xy01;
|
||||
*xy2 = xy02;
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
opus_val32 xy1_c, xy2_c;
|
||||
dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c);
|
||||
celt_assert(xy1_c == *xy1);
|
||||
celt_assert(xy2_c == *xy2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* !FIXED_POINT */
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
#ifdef __ARM_FEATURE_FMA
|
||||
/* If we can, force the compiler to use an FMA instruction rather than break
|
||||
vmlaq_f32() into fmul/fadd. */
|
||||
#define vmlaq_f32(a,b,c) vfmaq_f32(a,b,c)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
|
||||
/* This part of code simulates floating-point NEON operations. */
|
||||
|
||||
/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point */
|
||||
/* operations of celt_inner_prod_neon(), and both functions should have bit */
|
||||
/* exact output. */
|
||||
static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, float *err, int N)
|
||||
{
|
||||
int i;
|
||||
*err = 0;
|
||||
opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0;
|
||||
for (i = 0; i < N - 3; i += 4) {
|
||||
xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]);
|
||||
xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]);
|
||||
xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]);
|
||||
xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]);
|
||||
*err += ABS32(xy0)+ABS32(xy1)+ABS32(xy2)+ABS32(xy3);
|
||||
}
|
||||
xy0 += xy2;
|
||||
xy1 += xy3;
|
||||
xy = xy0 + xy1;
|
||||
*err += ABS32(xy1)+ABS32(xy0)+ABS32(xy);
|
||||
for (; i < N; i++) {
|
||||
xy = MAC16_16(xy, x[i], y[i]);
|
||||
*err += ABS32(xy);
|
||||
}
|
||||
*err = *err*2e-7 + N*1e-37;
|
||||
return xy;
|
||||
}
|
||||
|
||||
/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point */
|
||||
/* operations of dual_inner_prod_neon(), and both functions should have bit */
|
||||
/* exact output. */
|
||||
static void dual_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
|
||||
int N, opus_val32 *xy1, opus_val32 *xy2, float *err)
|
||||
{
|
||||
*xy1 = celt_inner_prod_neon_float_c_simulation(x, y01, &err[0], N);
|
||||
*xy2 = celt_inner_prod_neon_float_c_simulation(x, y02, &err[1], N);
|
||||
}
|
||||
|
||||
#endif /* OPUS_CHECK_ASM */
|
||||
|
||||
/* ========================================================================== */
|
||||
|
||||
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
|
||||
{
|
||||
int i;
|
||||
opus_val32 xy;
|
||||
float32x4_t xy_f32x4 = vdupq_n_f32(0);
|
||||
float32x2_t xy_f32x2;
|
||||
|
||||
for (i = 0; i < N - 7; i += 8) {
|
||||
float32x4_t x_f32x4, y_f32x4;
|
||||
x_f32x4 = vld1q_f32(&x[i]);
|
||||
y_f32x4 = vld1q_f32(&y[i]);
|
||||
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
|
||||
x_f32x4 = vld1q_f32(&x[i + 4]);
|
||||
y_f32x4 = vld1q_f32(&y[i + 4]);
|
||||
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
|
||||
}
|
||||
|
||||
if (N - i >= 4) {
|
||||
const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
|
||||
const float32x4_t y_f32x4 = vld1q_f32(&y[i]);
|
||||
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4));
|
||||
xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2);
|
||||
xy = vget_lane_f32(xy_f32x2, 0);
|
||||
|
||||
for (; i < N; i++) {
|
||||
xy = MAC16_16(xy, x[i], y[i]);
|
||||
}
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
float err, res;
|
||||
res = celt_inner_prod_neon_float_c_simulation(x, y, &err, N);
|
||||
/*if (ABS32(res - xy) > err) fprintf(stderr, "%g %g %g\n", res, xy, err);*/
|
||||
celt_assert(ABS32(res - xy) <= err);
|
||||
}
|
||||
#endif
|
||||
|
||||
return xy;
|
||||
}
|
||||
|
||||
void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
|
||||
int N, opus_val32 *xy1, opus_val32 *xy2)
|
||||
{
|
||||
int i;
|
||||
opus_val32 xy01, xy02;
|
||||
float32x4_t xy01_f32x4 = vdupq_n_f32(0);
|
||||
float32x4_t xy02_f32x4 = vdupq_n_f32(0);
|
||||
float32x2_t xy01_f32x2, xy02_f32x2;
|
||||
|
||||
for (i = 0; i < N - 7; i += 8) {
|
||||
float32x4_t x_f32x4, y01_f32x4, y02_f32x4;
|
||||
x_f32x4 = vld1q_f32(&x[i]);
|
||||
y01_f32x4 = vld1q_f32(&y01[i]);
|
||||
y02_f32x4 = vld1q_f32(&y02[i]);
|
||||
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
|
||||
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
|
||||
x_f32x4 = vld1q_f32(&x[i + 4]);
|
||||
y01_f32x4 = vld1q_f32(&y01[i + 4]);
|
||||
y02_f32x4 = vld1q_f32(&y02[i + 4]);
|
||||
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
|
||||
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
|
||||
}
|
||||
|
||||
if (N - i >= 4) {
|
||||
const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
|
||||
const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]);
|
||||
const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]);
|
||||
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
|
||||
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4));
|
||||
xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4));
|
||||
xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2);
|
||||
xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2);
|
||||
xy01 = vget_lane_f32(xy01_f32x2, 0);
|
||||
xy02 = vget_lane_f32(xy02_f32x2, 0);
|
||||
|
||||
for (; i < N; i++) {
|
||||
xy01 = MAC16_16(xy01, x[i], y01[i]);
|
||||
xy02 = MAC16_16(xy02, x[i], y02[i]);
|
||||
}
|
||||
*xy1 = xy01;
|
||||
*xy2 = xy02;
|
||||
|
||||
#ifdef OPUS_CHECK_ASM
|
||||
{
|
||||
opus_val32 xy1_c, xy2_c;
|
||||
float err[2];
|
||||
dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c, err);
|
||||
/*if (ABS32(xy1_c - *xy1) > err[0]) fprintf(stderr, "dual1 fail: %g %g %g\n", xy1_c, *xy1, err[0]);
|
||||
if (ABS32(xy2_c - *xy2) > err[1]) fprintf(stderr, "dual2 fail: %g %g %g\n", xy2_c, *xy2, err[1]);*/
|
||||
celt_assert(ABS32(xy1_c - *xy1) <= err[0]);
|
||||
celt_assert(ABS32(xy2_c - *xy2) <= err[1]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,123 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008-2009 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef BANDS_H
|
||||
#define BANDS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "modes.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "rate.h"
|
||||
|
||||
opus_int16 bitexact_cos(opus_int16 x);
|
||||
int bitexact_log2tan(int isin,int icos);
|
||||
|
||||
/** Compute the amplitude (sqrt energy) in each of the bands
|
||||
* @param m Mode data
|
||||
* @param X Spectrum
|
||||
* @param bandE Square root of the energy for each band (returned)
|
||||
*/
|
||||
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
|
||||
|
||||
/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
|
||||
|
||||
/** Normalise each band of X such that the energy in each band is
|
||||
equal to 1
|
||||
* @param m Mode data
|
||||
* @param X Spectrum (returned normalised)
|
||||
* @param bandE Square root of the energy for each band
|
||||
*/
|
||||
void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
|
||||
|
||||
/** Denormalise each band of X to restore full amplitude
|
||||
* @param m Mode data
|
||||
* @param X Spectrum (returned de-normalised)
|
||||
* @param bandE Square root of the energy for each band
|
||||
*/
|
||||
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
|
||||
celt_sig * OPUS_RESTRICT freq, const opus_val16 *bandE, int start,
|
||||
int end, int M, int downsample, int silence);
|
||||
|
||||
#define SPREAD_NONE (0)
|
||||
#define SPREAD_LIGHT (1)
|
||||
#define SPREAD_NORMAL (2)
|
||||
#define SPREAD_AGGRESSIVE (3)
|
||||
|
||||
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
|
||||
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
|
||||
int end, int C, int M, const int *spread_weight);
|
||||
|
||||
#ifdef MEASURE_NORM_MSE
|
||||
void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
|
||||
#endif
|
||||
|
||||
void haar1(celt_norm *X, int N0, int stride);
|
||||
|
||||
/** Quantisation/encoding of the residual spectrum
|
||||
* @param encode flag that indicates whether we're encoding (1) or decoding (0)
|
||||
* @param m Mode data
|
||||
* @param start First band to process
|
||||
* @param end Last band to process + 1
|
||||
* @param X Residual (normalised)
|
||||
* @param Y Residual (normalised) for second channel (or NULL for mono)
|
||||
* @param collapse_masks Anti-collapse tracking mask
|
||||
* @param bandE Square root of the energy for each band
|
||||
* @param pulses Bit allocation (per band) for PVQ
|
||||
* @param shortBlocks Zero for long blocks, non-zero for short blocks
|
||||
* @param spread Amount of spreading to use
|
||||
* @param dual_stereo Zero for MS stereo, non-zero for dual stereo
|
||||
* @param intensity First band to use intensity stereo
|
||||
* @param tf_res Time-frequency resolution change
|
||||
* @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
|
||||
* @param balance Number of unallocated bits
|
||||
* @param en Entropy coder state
|
||||
* @param LM log2() of the number of 2.5 subframes in the frame
|
||||
* @param codedBands Last band to receive bits + 1
|
||||
* @param seed Random generator seed
|
||||
* @param arch Run-time architecture (see opus_select_arch())
|
||||
*/
|
||||
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
|
||||
celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
|
||||
const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
|
||||
int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
|
||||
opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
|
||||
int complexity, int arch, int disable_inv);
|
||||
|
||||
void anti_collapse(const CELTMode *m, celt_norm *X_,
|
||||
unsigned char *collapse_masks, int LM, int C, int size, int start,
|
||||
int end, const opus_val16 *logE, const opus_val16 *prev1logE,
|
||||
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed,
|
||||
int arch);
|
||||
|
||||
opus_uint32 celt_lcg_rand(opus_uint32 seed);
|
||||
|
||||
int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev);
|
||||
|
||||
#endif /* BANDS_H */
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2010 Xiph.Org Foundation
|
||||
Copyright (c) 2008 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define CELT_C
|
||||
|
||||
#include "os_support.h"
|
||||
#include "mdct.h"
|
||||
#include <math.h>
|
||||
#include "celt.h"
|
||||
#include "pitch.h"
|
||||
#include "bands.h"
|
||||
#include "modes.h"
|
||||
#include "entcode.h"
|
||||
#include "quant_bands.h"
|
||||
#include "rate.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
#include "float_cast.h"
|
||||
#include <stdarg.h>
|
||||
#include "celt_lpc.h"
|
||||
#include "vq.h"
|
||||
|
||||
#ifndef PACKAGE_VERSION
|
||||
#define PACKAGE_VERSION "unknown"
|
||||
#endif
|
||||
|
||||
#if defined(MIPSr1_ASM)
|
||||
#include "mips/celt_mipsr1.h"
|
||||
#endif
|
||||
|
||||
|
||||
int resampling_factor(opus_int32 rate)
|
||||
{
|
||||
int ret;
|
||||
switch (rate)
|
||||
{
|
||||
case 48000:
|
||||
ret = 1;
|
||||
break;
|
||||
case 24000:
|
||||
ret = 2;
|
||||
break;
|
||||
case 16000:
|
||||
ret = 3;
|
||||
break;
|
||||
case 12000:
|
||||
ret = 4;
|
||||
break;
|
||||
case 8000:
|
||||
ret = 6;
|
||||
break;
|
||||
default:
|
||||
#ifndef CUSTOM_MODES
|
||||
celt_assert(0);
|
||||
#endif
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
|
||||
/* This version should be faster on ARM */
|
||||
#ifdef OPUS_ARM_ASM
|
||||
#ifndef NON_STATIC_COMB_FILTER_CONST_C
|
||||
static
|
||||
#endif
|
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
|
||||
opus_val16 g10, opus_val16 g11, opus_val16 g12)
|
||||
{
|
||||
opus_val32 x0, x1, x2, x3, x4;
|
||||
int i;
|
||||
x4 = SHL32(x[-T-2], 1);
|
||||
x3 = SHL32(x[-T-1], 1);
|
||||
x2 = SHL32(x[-T], 1);
|
||||
x1 = SHL32(x[-T+1], 1);
|
||||
for (i=0;i<N-4;i+=5)
|
||||
{
|
||||
opus_val32 t;
|
||||
x0=SHL32(x[i-T+2],1);
|
||||
t = MAC16_32_Q16(x[i], g10, x2);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i] = t;
|
||||
x4=SHL32(x[i-T+3],1);
|
||||
t = MAC16_32_Q16(x[i+1], g10, x1);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i+1] = t;
|
||||
x3=SHL32(x[i-T+4],1);
|
||||
t = MAC16_32_Q16(x[i+2], g10, x0);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i+2] = t;
|
||||
x2=SHL32(x[i-T+5],1);
|
||||
t = MAC16_32_Q16(x[i+3], g10, x4);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i+3] = t;
|
||||
x1=SHL32(x[i-T+6],1);
|
||||
t = MAC16_32_Q16(x[i+4], g10, x3);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i+4] = t;
|
||||
}
|
||||
#ifdef CUSTOM_MODES
|
||||
for (;i<N;i++)
|
||||
{
|
||||
opus_val32 t;
|
||||
x0=SHL32(x[i-T+2],1);
|
||||
t = MAC16_32_Q16(x[i], g10, x2);
|
||||
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
|
||||
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
|
||||
t = SATURATE(t, SIG_SAT);
|
||||
y[i] = t;
|
||||
x4=x3;
|
||||
x3=x2;
|
||||
x2=x1;
|
||||
x1=x0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifndef NON_STATIC_COMB_FILTER_CONST_C
|
||||
static
|
||||
#endif
|
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
|
||||
opus_val16 g10, opus_val16 g11, opus_val16 g12)
|
||||
{
|
||||
opus_val32 x0, x1, x2, x3, x4;
|
||||
int i;
|
||||
x4 = x[-T-2];
|
||||
x3 = x[-T-1];
|
||||
x2 = x[-T];
|
||||
x1 = x[-T+1];
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
x0=x[i-T+2];
|
||||
y[i] = x[i]
|
||||
+ MULT16_32_Q15(g10,x2)
|
||||
+ MULT16_32_Q15(g11,ADD32(x1,x3))
|
||||
+ MULT16_32_Q15(g12,ADD32(x0,x4));
|
||||
y[i] = SATURATE(y[i], SIG_SAT);
|
||||
x4=x3;
|
||||
x3=x2;
|
||||
x2=x1;
|
||||
x1=x0;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef OVERRIDE_comb_filter
|
||||
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
|
||||
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
|
||||
const opus_val16 *window, int overlap, int arch)
|
||||
{
|
||||
int i;
|
||||
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
|
||||
opus_val16 g00, g01, g02, g10, g11, g12;
|
||||
opus_val32 x0, x1, x2, x3, x4;
|
||||
static const opus_val16 gains[3][3] = {
|
||||
{QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
|
||||
{QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
|
||||
{QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
|
||||
|
||||
if (g0==0 && g1==0)
|
||||
{
|
||||
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
|
||||
if (x!=y)
|
||||
OPUS_MOVE(y, x, N);
|
||||
return;
|
||||
}
|
||||
/* When the gain is zero, T0 and/or T1 is set to zero. We need
|
||||
to have then be at least 2 to avoid processing garbage data. */
|
||||
T0 = IMAX(T0, COMBFILTER_MINPERIOD);
|
||||
T1 = IMAX(T1, COMBFILTER_MINPERIOD);
|
||||
g00 = MULT16_16_P15(g0, gains[tapset0][0]);
|
||||
g01 = MULT16_16_P15(g0, gains[tapset0][1]);
|
||||
g02 = MULT16_16_P15(g0, gains[tapset0][2]);
|
||||
g10 = MULT16_16_P15(g1, gains[tapset1][0]);
|
||||
g11 = MULT16_16_P15(g1, gains[tapset1][1]);
|
||||
g12 = MULT16_16_P15(g1, gains[tapset1][2]);
|
||||
x1 = x[-T1+1];
|
||||
x2 = x[-T1 ];
|
||||
x3 = x[-T1-1];
|
||||
x4 = x[-T1-2];
|
||||
/* If the filter didn't change, we don't need the overlap */
|
||||
if (g0==g1 && T0==T1 && tapset0==tapset1)
|
||||
overlap=0;
|
||||
for (i=0;i<overlap;i++)
|
||||
{
|
||||
opus_val16 f;
|
||||
x0=x[i-T1+2];
|
||||
f = MULT16_16_Q15(window[i],window[i]);
|
||||
y[i] = x[i]
|
||||
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0])
|
||||
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
|
||||
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
|
||||
+ MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
|
||||
+ MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
|
||||
+ MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
|
||||
y[i] = SATURATE(y[i], SIG_SAT);
|
||||
x4=x3;
|
||||
x3=x2;
|
||||
x2=x1;
|
||||
x1=x0;
|
||||
|
||||
}
|
||||
if (g1==0)
|
||||
{
|
||||
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
|
||||
if (x!=y)
|
||||
OPUS_MOVE(y+overlap, x+overlap, N-overlap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the part with the constant filter. */
|
||||
comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
|
||||
}
|
||||
#endif /* OVERRIDE_comb_filter */
|
||||
|
||||
/* TF change table. Positive values mean better frequency resolution (longer
|
||||
effective window), whereas negative values mean better time resolution
|
||||
(shorter effective window). The second index is computed as:
|
||||
4*isTransient + 2*tf_select + per_band_flag */
|
||||
const signed char tf_select_table[4][8] = {
|
||||
/*isTransient=0 isTransient=1 */
|
||||
{0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */
|
||||
{0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */
|
||||
{0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */
|
||||
{0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */
|
||||
};
|
||||
|
||||
|
||||
void init_caps(const CELTMode *m,int *cap,int LM,int C)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<m->nbEBands;i++)
|
||||
{
|
||||
int N;
|
||||
N=(m->eBands[i+1]-m->eBands[i])<<LM;
|
||||
cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *opus_strerror(int error)
|
||||
{
|
||||
static const char * const error_strings[8] = {
|
||||
"success",
|
||||
"invalid argument",
|
||||
"buffer too small",
|
||||
"internal error",
|
||||
"corrupted stream",
|
||||
"request not implemented",
|
||||
"invalid state",
|
||||
"memory allocation failed"
|
||||
};
|
||||
if (error > 0 || error < -7)
|
||||
return "unknown error";
|
||||
else
|
||||
return error_strings[-error];
|
||||
}
|
||||
|
||||
const char *opus_get_version_string(void)
|
||||
{
|
||||
return "libopus " PACKAGE_VERSION
|
||||
/* Applications may rely on the presence of this substring in the version
|
||||
string to determine if they have a fixed-point or floating-point build
|
||||
at runtime. */
|
||||
#ifdef FIXED_POINT
|
||||
"-fixed"
|
||||
#endif
|
||||
#ifdef FUZZING
|
||||
"-fuzzing"
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2008 Gregory Maxwell
|
||||
Written by Jean-Marc Valin and Gregory Maxwell */
|
||||
/**
|
||||
@file celt.h
|
||||
@brief Contains all the functions for encoding and decoding audio
|
||||
*/
|
||||
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CELT_H
|
||||
#define CELT_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
#include "opus_custom.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "arch.h"
|
||||
|
||||
#ifdef ENABLE_DEEP_PLC
|
||||
#include "lpcnet.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CELTEncoder OpusCustomEncoder
|
||||
#define CELTDecoder OpusCustomDecoder
|
||||
#define CELTMode OpusCustomMode
|
||||
|
||||
#define LEAK_BANDS 19
|
||||
|
||||
typedef struct {
|
||||
int valid;
|
||||
float tonality;
|
||||
float tonality_slope;
|
||||
float noisiness;
|
||||
float activity;
|
||||
float music_prob;
|
||||
float music_prob_min;
|
||||
float music_prob_max;
|
||||
int bandwidth;
|
||||
float activity_probability;
|
||||
float max_pitch_ratio;
|
||||
/* Store as Q6 char to save space. */
|
||||
unsigned char leak_boost[LEAK_BANDS];
|
||||
} AnalysisInfo;
|
||||
|
||||
typedef struct {
|
||||
int signalType;
|
||||
int offset;
|
||||
} SILKInfo;
|
||||
|
||||
#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
|
||||
|
||||
#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
|
||||
|
||||
#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
|
||||
|
||||
/* Encoder/decoder Requests */
|
||||
|
||||
|
||||
#define CELT_SET_PREDICTION_REQUEST 10002
|
||||
/** Controls the use of interframe prediction.
|
||||
0=Independent frames
|
||||
1=Short term interframe prediction allowed
|
||||
2=Long term prediction allowed
|
||||
*/
|
||||
#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_INPUT_CLIPPING_REQUEST 10004
|
||||
#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_GET_AND_CLEAR_ERROR_REQUEST 10007
|
||||
#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, __opus_check_int_ptr(x)
|
||||
|
||||
#define CELT_SET_CHANNELS_REQUEST 10008
|
||||
#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, __opus_check_int(x)
|
||||
|
||||
|
||||
/* Internal */
|
||||
#define CELT_SET_START_BAND_REQUEST 10010
|
||||
#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_END_BAND_REQUEST 10012
|
||||
#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_GET_MODE_REQUEST 10015
|
||||
/** Get the CELTMode used by an encoder or decoder */
|
||||
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, __celt_check_mode_ptr_ptr(x)
|
||||
|
||||
#define CELT_SET_SIGNALLING_REQUEST 10016
|
||||
#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_TONALITY_REQUEST 10018
|
||||
#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, __opus_check_int(x)
|
||||
#define CELT_SET_TONALITY_SLOPE_REQUEST 10020
|
||||
#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define CELT_SET_ANALYSIS_REQUEST 10022
|
||||
#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, __celt_check_analysis_ptr(x)
|
||||
|
||||
#define OPUS_SET_LFE_REQUEST 10024
|
||||
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
|
||||
|
||||
#define OPUS_SET_ENERGY_MASK_REQUEST 10026
|
||||
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
|
||||
|
||||
#define CELT_SET_SILK_INFO_REQUEST 10028
|
||||
#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
|
||||
|
||||
/* Encoder stuff */
|
||||
|
||||
int celt_encoder_get_size(int channels);
|
||||
|
||||
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
|
||||
|
||||
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
|
||||
int arch);
|
||||
|
||||
|
||||
|
||||
/* Decoder stuff */
|
||||
|
||||
int celt_decoder_get_size(int channels);
|
||||
|
||||
|
||||
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
|
||||
|
||||
int celt_decode_with_ec_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
|
||||
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum
|
||||
#ifdef ENABLE_DEEP_PLC
|
||||
,LPCNetPLCState *lpcnet
|
||||
#endif
|
||||
);
|
||||
|
||||
int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data,
|
||||
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum);
|
||||
|
||||
#define celt_encoder_ctl opus_custom_encoder_ctl
|
||||
#define celt_decoder_ctl opus_custom_decoder_ctl
|
||||
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
#define OPUS_CUSTOM_NOSTATIC
|
||||
#else
|
||||
#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE
|
||||
#endif
|
||||
|
||||
static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
|
||||
/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
|
||||
static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
|
||||
|
||||
static const unsigned char tapset_icdf[3]={2,1,0};
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
static const unsigned char toOpusTable[20] = {
|
||||
0xE0, 0xE8, 0xF0, 0xF8,
|
||||
0xC0, 0xC8, 0xD0, 0xD8,
|
||||
0xA0, 0xA8, 0xB0, 0xB8,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x80, 0x88, 0x90, 0x98,
|
||||
};
|
||||
|
||||
static const unsigned char fromOpusTable[16] = {
|
||||
0x80, 0x88, 0x90, 0x98,
|
||||
0x40, 0x48, 0x50, 0x58,
|
||||
0x20, 0x28, 0x30, 0x38,
|
||||
0x00, 0x08, 0x10, 0x18
|
||||
};
|
||||
|
||||
static OPUS_INLINE int toOpus(unsigned char c)
|
||||
{
|
||||
int ret=0;
|
||||
if (c<0xA0)
|
||||
ret = toOpusTable[c>>3];
|
||||
if (ret == 0)
|
||||
return -1;
|
||||
else
|
||||
return ret|(c&0x7);
|
||||
}
|
||||
|
||||
static OPUS_INLINE int fromOpus(unsigned char c)
|
||||
{
|
||||
if (c<0x80)
|
||||
return -1;
|
||||
else
|
||||
return fromOpusTable[(c>>3)-16] | (c&0x7);
|
||||
}
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
#define COMBFILTER_MAXPERIOD 1024
|
||||
#define COMBFILTER_MINPERIOD 15
|
||||
|
||||
extern const signed char tf_select_table[4][8];
|
||||
|
||||
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
|
||||
void validate_celt_decoder(CELTDecoder *st);
|
||||
#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
|
||||
#else
|
||||
#define VALIDATE_CELT_DECODER(st)
|
||||
#endif
|
||||
|
||||
int resampling_factor(opus_int32 rate);
|
||||
|
||||
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
|
||||
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
|
||||
|
||||
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
|
||||
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
|
||||
const opus_val16 *window, int overlap, int arch);
|
||||
|
||||
void init_caps(const CELTMode *m,int *cap,int LM,int C);
|
||||
|
||||
#ifdef RESYNTH
|
||||
void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum);
|
||||
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
|
||||
opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient,
|
||||
int LM, int downsample, int silence, int arch);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CELT_H */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,363 @@
|
|||
/* Copyright (c) 2009-2010 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt_lpc.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
#include "pitch.h"
|
||||
|
||||
void _celt_lpc(
|
||||
opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
|
||||
const opus_val32 *ac, /* in: [0...p] autocorrelation values */
|
||||
int p
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
opus_val32 r;
|
||||
opus_val32 error = ac[0];
|
||||
#ifdef FIXED_POINT
|
||||
opus_val32 lpc[CELT_LPC_ORDER];
|
||||
#else
|
||||
float *lpc = _lpc;
|
||||
#endif
|
||||
|
||||
OPUS_CLEAR(lpc, p);
|
||||
#ifdef FIXED_POINT
|
||||
if (ac[0] != 0)
|
||||
#else
|
||||
if (ac[0] > 1e-10f)
|
||||
#endif
|
||||
{
|
||||
for (i = 0; i < p; i++) {
|
||||
/* Sum up this iteration's reflection coefficient */
|
||||
opus_val32 rr = 0;
|
||||
for (j = 0; j < i; j++)
|
||||
rr += MULT32_32_Q31(lpc[j],ac[i - j]);
|
||||
rr += SHR32(ac[i + 1],6);
|
||||
r = -frac_div32(SHL32(rr,6), error);
|
||||
/* Update LPC coefficients and total error */
|
||||
lpc[i] = SHR32(r,6);
|
||||
for (j = 0; j < (i+1)>>1; j++)
|
||||
{
|
||||
opus_val32 tmp1, tmp2;
|
||||
tmp1 = lpc[j];
|
||||
tmp2 = lpc[i-1-j];
|
||||
lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
|
||||
lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
|
||||
}
|
||||
|
||||
error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
|
||||
/* Bail out once we get 30 dB gain */
|
||||
#ifdef FIXED_POINT
|
||||
if (error<=SHR32(ac[0],10))
|
||||
break;
|
||||
#else
|
||||
if (error<=.001f*ac[0])
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
/* Convert the int32 lpcs to int16 and ensure there are no wrap-arounds.
|
||||
This reuses the logic in silk_LPC_fit() and silk_bwexpander_32(). Any bug
|
||||
fixes should also be applied there. */
|
||||
int iter, idx = 0;
|
||||
opus_val32 maxabs, absval, chirp_Q16, chirp_minus_one_Q16;
|
||||
|
||||
for (iter = 0; iter < 10; iter++) {
|
||||
maxabs = 0;
|
||||
for (i = 0; i < p; i++) {
|
||||
absval = ABS32(lpc[i]);
|
||||
if (absval > maxabs) {
|
||||
maxabs = absval;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
maxabs = PSHR32(maxabs, 13); /* Q25->Q12 */
|
||||
|
||||
if (maxabs > 32767) {
|
||||
maxabs = MIN32(maxabs, 163838);
|
||||
chirp_Q16 = QCONST32(0.999, 16) - DIV32(SHL32(maxabs - 32767, 14),
|
||||
SHR32(MULT32_32_32(maxabs, idx + 1), 2));
|
||||
chirp_minus_one_Q16 = chirp_Q16 - 65536;
|
||||
|
||||
/* Apply bandwidth expansion. */
|
||||
for (i = 0; i < p - 1; i++) {
|
||||
lpc[i] = MULT32_32_Q16(chirp_Q16, lpc[i]);
|
||||
chirp_Q16 += PSHR32(MULT32_32_32(chirp_Q16, chirp_minus_one_Q16), 16);
|
||||
}
|
||||
lpc[p - 1] = MULT32_32_Q16(chirp_Q16, lpc[p - 1]);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter == 10) {
|
||||
/* If the coeffs still do not fit into the 16 bit range after 10 iterations,
|
||||
fall back to the A(z)=1 filter. */
|
||||
OPUS_CLEAR(lpc, p);
|
||||
_lpc[0] = 4096; /* Q12 */
|
||||
} else {
|
||||
for (i = 0; i < p; i++) {
|
||||
_lpc[i] = EXTRACT16(PSHR32(lpc[i], 13)); /* Q25->Q12 */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void celt_fir_c(
|
||||
const opus_val16 *x,
|
||||
const opus_val16 *num,
|
||||
opus_val16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
int arch)
|
||||
{
|
||||
int i,j;
|
||||
VARDECL(opus_val16, rnum);
|
||||
SAVE_STACK;
|
||||
celt_assert(x != y);
|
||||
ALLOC(rnum, ord, opus_val16);
|
||||
for(i=0;i<ord;i++)
|
||||
rnum[i] = num[ord-i-1];
|
||||
for (i=0;i<N-3;i+=4)
|
||||
{
|
||||
opus_val32 sum[4];
|
||||
sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
|
||||
sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
|
||||
sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
|
||||
sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
|
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
|
||||
{
|
||||
opus_val32 sum_c[4];
|
||||
memcpy(sum_c, sum, sizeof(sum_c));
|
||||
xcorr_kernel_c(rnum, x+i-ord, sum_c, ord);
|
||||
#endif
|
||||
xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
|
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
|
||||
celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
|
||||
}
|
||||
#endif
|
||||
y[i ] = SROUND16(sum[0], SIG_SHIFT);
|
||||
y[i+1] = SROUND16(sum[1], SIG_SHIFT);
|
||||
y[i+2] = SROUND16(sum[2], SIG_SHIFT);
|
||||
y[i+3] = SROUND16(sum[3], SIG_SHIFT);
|
||||
}
|
||||
for (;i<N;i++)
|
||||
{
|
||||
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
|
||||
for (j=0;j<ord;j++)
|
||||
sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
|
||||
y[i] = SROUND16(sum, SIG_SHIFT);
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
void celt_iir(const opus_val32 *_x,
|
||||
const opus_val16 *den,
|
||||
opus_val32 *_y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem,
|
||||
int arch)
|
||||
{
|
||||
#ifdef SMALL_FOOTPRINT
|
||||
int i,j;
|
||||
(void)arch;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
opus_val32 sum = _x[i];
|
||||
for (j=0;j<ord;j++)
|
||||
{
|
||||
sum -= MULT16_16(den[j],mem[j]);
|
||||
}
|
||||
for (j=ord-1;j>=1;j--)
|
||||
{
|
||||
mem[j]=mem[j-1];
|
||||
}
|
||||
mem[0] = SROUND16(sum, SIG_SHIFT);
|
||||
_y[i] = sum;
|
||||
}
|
||||
#else
|
||||
int i,j;
|
||||
VARDECL(opus_val16, rden);
|
||||
VARDECL(opus_val16, y);
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert((ord&3)==0);
|
||||
ALLOC(rden, ord, opus_val16);
|
||||
ALLOC(y, N+ord, opus_val16);
|
||||
for(i=0;i<ord;i++)
|
||||
rden[i] = den[ord-i-1];
|
||||
for(i=0;i<ord;i++)
|
||||
y[i] = -mem[ord-i-1];
|
||||
for(;i<N+ord;i++)
|
||||
y[i]=0;
|
||||
for (i=0;i<N-3;i+=4)
|
||||
{
|
||||
/* Unroll by 4 as if it were an FIR filter */
|
||||
opus_val32 sum[4];
|
||||
sum[0]=_x[i];
|
||||
sum[1]=_x[i+1];
|
||||
sum[2]=_x[i+2];
|
||||
sum[3]=_x[i+3];
|
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
|
||||
{
|
||||
opus_val32 sum_c[4];
|
||||
memcpy(sum_c, sum, sizeof(sum_c));
|
||||
xcorr_kernel_c(rden, y+i, sum_c, ord);
|
||||
#endif
|
||||
xcorr_kernel(rden, y+i, sum, ord, arch);
|
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT)
|
||||
celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0);
|
||||
}
|
||||
#endif
|
||||
/* Patch up the result to compensate for the fact that this is an IIR */
|
||||
y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT);
|
||||
_y[i ] = sum[0];
|
||||
sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
|
||||
y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
|
||||
_y[i+1] = sum[1];
|
||||
sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
|
||||
sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
|
||||
y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
|
||||
_y[i+2] = sum[2];
|
||||
|
||||
sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
|
||||
sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
|
||||
sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
|
||||
y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
|
||||
_y[i+3] = sum[3];
|
||||
}
|
||||
for (;i<N;i++)
|
||||
{
|
||||
opus_val32 sum = _x[i];
|
||||
for (j=0;j<ord;j++)
|
||||
sum -= MULT16_16(rden[j],y[i+j]);
|
||||
y[i+ord] = SROUND16(sum,SIG_SHIFT);
|
||||
_y[i] = sum;
|
||||
}
|
||||
for(i=0;i<ord;i++)
|
||||
mem[i] = _y[N-i-1];
|
||||
RESTORE_STACK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int _celt_autocorr(
|
||||
const opus_val16 *x, /* in: [0...n-1] samples x */
|
||||
opus_val32 *ac, /* out: [0...lag-1] ac values */
|
||||
const opus_val16 *window,
|
||||
int overlap,
|
||||
int lag,
|
||||
int n,
|
||||
int arch
|
||||
)
|
||||
{
|
||||
opus_val32 d;
|
||||
int i, k;
|
||||
int fastN=n-lag;
|
||||
int shift;
|
||||
const opus_val16 *xptr;
|
||||
VARDECL(opus_val16, xx);
|
||||
SAVE_STACK;
|
||||
ALLOC(xx, n, opus_val16);
|
||||
celt_assert(n>0);
|
||||
celt_assert(overlap>=0);
|
||||
if (overlap == 0)
|
||||
{
|
||||
xptr = x;
|
||||
} else {
|
||||
for (i=0;i<n;i++)
|
||||
xx[i] = x[i];
|
||||
for (i=0;i<overlap;i++)
|
||||
{
|
||||
xx[i] = MULT16_16_Q15(x[i],window[i]);
|
||||
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
|
||||
}
|
||||
xptr = xx;
|
||||
}
|
||||
shift=0;
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
opus_val32 ac0;
|
||||
ac0 = 1+(n<<7);
|
||||
if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
|
||||
for(i=(n&1);i<n;i+=2)
|
||||
{
|
||||
ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
|
||||
ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
|
||||
}
|
||||
|
||||
shift = celt_ilog2(ac0)-30+10;
|
||||
shift = (shift)/2;
|
||||
if (shift>0)
|
||||
{
|
||||
for(i=0;i<n;i++)
|
||||
xx[i] = PSHR32(xptr[i], shift);
|
||||
xptr = xx;
|
||||
} else
|
||||
shift = 0;
|
||||
}
|
||||
#endif
|
||||
celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
|
||||
for (k=0;k<=lag;k++)
|
||||
{
|
||||
for (i = k+fastN, d = 0; i < n; i++)
|
||||
d = MAC16_16(d, xptr[i], xptr[i-k]);
|
||||
ac[k] += d;
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
shift = 2*shift;
|
||||
if (shift<=0)
|
||||
ac[0] += SHL32((opus_int32)1, -shift);
|
||||
if (ac[0] < 268435456)
|
||||
{
|
||||
int shift2 = 29 - EC_ILOG(ac[0]);
|
||||
for (i=0;i<=lag;i++)
|
||||
ac[i] = SHL32(ac[i], shift2);
|
||||
shift -= shift2;
|
||||
} else if (ac[0] >= 536870912)
|
||||
{
|
||||
int shift2=1;
|
||||
if (ac[0] >= 1073741824)
|
||||
shift2++;
|
||||
for (i=0;i<=lag;i++)
|
||||
ac[i] = SHR32(ac[i], shift2);
|
||||
shift += shift2;
|
||||
}
|
||||
#endif
|
||||
|
||||
RESTORE_STACK;
|
||||
return shift;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* Copyright (c) 2009-2010 Xiph.Org Foundation
|
||||
Written by Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLC_H
|
||||
#define PLC_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "cpu_support.h"
|
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
|
||||
#include "x86/celt_lpc_sse.h"
|
||||
#endif
|
||||
|
||||
#define CELT_LPC_ORDER 24
|
||||
|
||||
void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
|
||||
|
||||
void celt_fir_c(
|
||||
const opus_val16 *x,
|
||||
const opus_val16 *num,
|
||||
opus_val16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
int arch);
|
||||
|
||||
#if !defined(OVERRIDE_CELT_FIR)
|
||||
#define celt_fir(x, num, y, N, ord, arch) \
|
||||
(celt_fir_c(x, num, y, N, ord, arch))
|
||||
#endif
|
||||
|
||||
void celt_iir(const opus_val32 *x,
|
||||
const opus_val16 *den,
|
||||
opus_val32 *y,
|
||||
int N,
|
||||
int ord,
|
||||
opus_val16 *mem,
|
||||
int arch);
|
||||
|
||||
int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
|
||||
const opus_val16 *window, int overlap, int lag, int n, int arch);
|
||||
|
||||
#endif /* PLC_H */
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_SUPPORT_H
|
||||
#define CPU_SUPPORT_H
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
|
||||
#if defined(OPUS_HAVE_RTCD) && \
|
||||
(defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
|
||||
#include "arm/armcpu.h"
|
||||
|
||||
/* We currently support 5 ARM variants:
|
||||
* arch[0] -> ARMv4
|
||||
* arch[1] -> ARMv5E
|
||||
* arch[2] -> ARMv6
|
||||
* arch[3] -> NEON
|
||||
* arch[4] -> NEON+DOTPROD
|
||||
*/
|
||||
#define OPUS_ARCHMASK 7
|
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) && \
|
||||
((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2)))
|
||||
|
||||
#include "x86/x86cpu.h"
|
||||
/* We currently support 5 x86 variants:
|
||||
* arch[0] -> non-sse
|
||||
* arch[1] -> sse
|
||||
* arch[2] -> sse2
|
||||
* arch[3] -> sse4.1
|
||||
* arch[4] -> avx
|
||||
*/
|
||||
#define OPUS_ARCHMASK 7
|
||||
int opus_select_arch(void);
|
||||
|
||||
#else
|
||||
#define OPUS_ARCHMASK 0
|
||||
|
||||
static OPUS_INLINE int opus_select_arch(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,715 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2007-2009 Timothy B. Terriberry
|
||||
Written by Timothy B. Terriberry and Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "os_support.h"
|
||||
#include "cwrs.h"
|
||||
#include "mathops.h"
|
||||
#include "arch.h"
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
/*Guaranteed to return a conservatively large estimate of the binary logarithm
|
||||
with frac bits of fractional precision.
|
||||
Tested for all possible 32-bit inputs with frac=4, where the maximum
|
||||
overestimation is 0.06254243 bits.*/
|
||||
int log2_frac(opus_uint32 val, int frac)
|
||||
{
|
||||
int l;
|
||||
l=EC_ILOG(val);
|
||||
if(val&(val-1)){
|
||||
/*This is (val>>l-16), but guaranteed to round up, even if adding a bias
|
||||
before the shift would cause overflow (e.g., for 0xFFFFxxxx).
|
||||
Doesn't work for val=0, but that case fails the test above.*/
|
||||
if(l>16)val=((val-1)>>(l-16))+1;
|
||||
else val<<=16-l;
|
||||
l=(l-1)<<frac;
|
||||
/*Note that we always need one iteration, since the rounding up above means
|
||||
that we might need to adjust the integer part of the logarithm.*/
|
||||
do{
|
||||
int b;
|
||||
b=(int)(val>>16);
|
||||
l+=b<<frac;
|
||||
val=(val+b)>>b;
|
||||
val=(val*val+0x7FFF)>>15;
|
||||
}
|
||||
while(frac-->0);
|
||||
/*If val is not exactly 0x8000, then we have to round up the remainder.*/
|
||||
return l+(val>0x8000);
|
||||
}
|
||||
/*Exact powers of two require no rounding.*/
|
||||
else return (l-1)<<frac;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Although derived separately, the pulse vector coding scheme is equivalent to
|
||||
a Pyramid Vector Quantizer \cite{Fis86}.
|
||||
Some additional notes about an early version appear at
|
||||
https://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
|
||||
and the definitions of some terms have evolved since that was written.
|
||||
|
||||
The conversion from a pulse vector to an integer index (encoding) and back
|
||||
(decoding) is governed by two related functions, V(N,K) and U(N,K).
|
||||
|
||||
V(N,K) = the number of combinations, with replacement, of N items, taken K
|
||||
at a time, when a sign bit is added to each item taken at least once (i.e.,
|
||||
the number of N-dimensional unit pulse vectors with K pulses).
|
||||
One way to compute this is via
|
||||
V(N,K) = K>0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1,
|
||||
where choose() is the binomial function.
|
||||
A table of values for N<10 and K<10 looks like:
|
||||
V[10][10] = {
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{1, 2, 2, 2, 2, 2, 2, 2, 2, 2},
|
||||
{1, 4, 8, 12, 16, 20, 24, 28, 32, 36},
|
||||
{1, 6, 18, 38, 66, 102, 146, 198, 258, 326},
|
||||
{1, 8, 32, 88, 192, 360, 608, 952, 1408, 1992},
|
||||
{1, 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290},
|
||||
{1, 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436},
|
||||
{1, 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598},
|
||||
{1, 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688},
|
||||
{1, 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146}
|
||||
};
|
||||
|
||||
U(N,K) = the number of such combinations wherein N-1 objects are taken at
|
||||
most K-1 at a time.
|
||||
This is given by
|
||||
U(N,K) = sum(k=0...K-1,V(N-1,k))
|
||||
= K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0.
|
||||
The latter expression also makes clear that U(N,K) is half the number of such
|
||||
combinations wherein the first object is taken at least once.
|
||||
Although it may not be clear from either of these definitions, U(N,K) is the
|
||||
natural function to work with when enumerating the pulse vector codebooks,
|
||||
not V(N,K).
|
||||
U(N,K) is not well-defined for N=0, but with the extension
|
||||
U(0,K) = K>0 ? 0 : 1,
|
||||
the function becomes symmetric: U(N,K) = U(K,N), with a similar table:
|
||||
U[10][10] = {
|
||||
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
|
||||
{0, 1, 3, 5, 7, 9, 11, 13, 15, 17},
|
||||
{0, 1, 5, 13, 25, 41, 61, 85, 113, 145},
|
||||
{0, 1, 7, 25, 63, 129, 231, 377, 575, 833},
|
||||
{0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649},
|
||||
{0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073},
|
||||
{0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081},
|
||||
{0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545},
|
||||
{0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729}
|
||||
};
|
||||
|
||||
With this extension, V(N,K) may be written in terms of U(N,K):
|
||||
V(N,K) = U(N,K) + U(N,K+1)
|
||||
for all N>=0, K>=0.
|
||||
Thus U(N,K+1) represents the number of combinations where the first element
|
||||
is positive or zero, and U(N,K) represents the number of combinations where
|
||||
it is negative.
|
||||
With a large enough table of U(N,K) values, we could write O(N) encoding
|
||||
and O(min(N*log(K),N+K)) decoding routines, but such a table would be
|
||||
prohibitively large for small embedded devices (K may be as large as 32767
|
||||
for small N, and N may be as large as 200).
|
||||
|
||||
Both functions obey the same recurrence relation:
|
||||
V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1),
|
||||
U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1),
|
||||
for all N>0, K>0, with different initial conditions at N=0 or K=0.
|
||||
This allows us to construct a row of one of the tables above given the
|
||||
previous row or the next row.
|
||||
Thus we can derive O(NK) encoding and decoding routines with O(K) memory
|
||||
using only addition and subtraction.
|
||||
|
||||
When encoding, we build up from the U(2,K) row and work our way forwards.
|
||||
When decoding, we need to start at the U(N,K) row and work our way backwards,
|
||||
which requires a means of computing U(N,K).
|
||||
U(N,K) may be computed from two previous values with the same N:
|
||||
U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2)
|
||||
for all N>1, and since U(N,K) is symmetric, a similar relation holds for two
|
||||
previous values with the same K:
|
||||
U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K)
|
||||
for all K>1.
|
||||
This allows us to construct an arbitrary row of the U(N,K) table by starting
|
||||
with the first two values, which are constants.
|
||||
This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K)
|
||||
multiplications.
|
||||
Similar relations can be derived for V(N,K), but are not used here.
|
||||
|
||||
For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree
|
||||
polynomial for fixed N.
|
||||
The first few are
|
||||
U(1,K) = 1,
|
||||
U(2,K) = 2*K-1,
|
||||
U(3,K) = (2*K-2)*K+1,
|
||||
U(4,K) = (((4*K-6)*K+8)*K-3)/3,
|
||||
U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3,
|
||||
and
|
||||
V(1,K) = 2,
|
||||
V(2,K) = 4*K,
|
||||
V(3,K) = 4*K*K+2,
|
||||
V(4,K) = 8*(K*K+2)*K/3,
|
||||
V(5,K) = ((4*K*K+20)*K*K+6)/3,
|
||||
for all K>0.
|
||||
This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for
|
||||
small N (and indeed decoding is also O(N) for N<3).
|
||||
|
||||
@ARTICLE{Fis86,
|
||||
author="Thomas R. Fischer",
|
||||
title="A Pyramid Vector Quantizer",
|
||||
journal="IEEE Transactions on Information Theory",
|
||||
volume="IT-32",
|
||||
number=4,
|
||||
pages="568--583",
|
||||
month=Jul,
|
||||
year=1986
|
||||
}*/
|
||||
|
||||
#if !defined(SMALL_FOOTPRINT)
|
||||
|
||||
/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/
|
||||
# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)])
|
||||
/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N
|
||||
with K pulses allocated to it.*/
|
||||
# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1))
|
||||
|
||||
/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)).
|
||||
Thus, the number of entries in row I is the larger of the maximum number of
|
||||
pulses we will ever allocate for a given N=I (K=128, or however many fit in
|
||||
32 bits, whichever is smaller), plus one, and the maximum N for which
|
||||
K=I-1 pulses fit in 32 bits.
|
||||
The largest band size in an Opus Custom mode is 208.
|
||||
Otherwise, we can limit things to the set of N which can be achieved by
|
||||
splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48,
|
||||
44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/
|
||||
#if defined(CUSTOM_MODES)
|
||||
static const opus_uint32 CELT_PVQ_U_DATA[1488]={
|
||||
#else
|
||||
static const opus_uint32 CELT_PVQ_U_DATA[1272]={
|
||||
#endif
|
||||
/*N=0, K=0...176:*/
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
#endif
|
||||
/*N=1, K=1...176:*/
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1,
|
||||
#endif
|
||||
/*N=2, K=2...176:*/
|
||||
3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
|
||||
43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79,
|
||||
81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113,
|
||||
115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143,
|
||||
145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
|
||||
175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203,
|
||||
205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233,
|
||||
235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263,
|
||||
265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293,
|
||||
295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323,
|
||||
325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381,
|
||||
383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411,
|
||||
413, 415,
|
||||
#endif
|
||||
/*N=3, K=3...176:*/
|
||||
13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613,
|
||||
685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861,
|
||||
1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785,
|
||||
3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385,
|
||||
6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661,
|
||||
9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961,
|
||||
13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745,
|
||||
17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013,
|
||||
21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765,
|
||||
26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001,
|
||||
31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721,
|
||||
37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925,
|
||||
43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613,
|
||||
50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785,
|
||||
57461, 58141, 58825, 59513, 60205, 60901, 61601,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565,
|
||||
70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013,
|
||||
78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113,
|
||||
#endif
|
||||
/*N=4, K=4...176:*/
|
||||
63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017,
|
||||
7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775,
|
||||
30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153,
|
||||
82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193,
|
||||
161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575,
|
||||
267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217,
|
||||
410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951,
|
||||
597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609,
|
||||
833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023,
|
||||
1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407,
|
||||
1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759,
|
||||
1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175,
|
||||
2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751,
|
||||
2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583,
|
||||
3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767,
|
||||
3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399,
|
||||
4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575,
|
||||
5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391,
|
||||
6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943,
|
||||
7085049, 7207551,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783,
|
||||
8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967,
|
||||
9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199,
|
||||
10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177,
|
||||
11912575,
|
||||
#endif
|
||||
/*N=5, K=5...176:*/
|
||||
321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041,
|
||||
50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401,
|
||||
330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241,
|
||||
1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241,
|
||||
2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801,
|
||||
4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849,
|
||||
8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849,
|
||||
13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809,
|
||||
20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881,
|
||||
29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641,
|
||||
40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081,
|
||||
55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609,
|
||||
73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049,
|
||||
95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641,
|
||||
122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041,
|
||||
155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321,
|
||||
193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969,
|
||||
238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889,
|
||||
290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401,
|
||||
351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241,
|
||||
420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561,
|
||||
500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929,
|
||||
590359041, 604167209, 618216201, 632508801,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...208:*/
|
||||
647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241,
|
||||
755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161,
|
||||
878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329,
|
||||
1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041,
|
||||
1143412929, 1166053121, 1189027881, 1212340489, 1235994241,
|
||||
#endif
|
||||
/*N=6, K=6...96:*/
|
||||
1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047,
|
||||
335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409,
|
||||
2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793,
|
||||
11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455,
|
||||
29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189,
|
||||
64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651,
|
||||
128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185,
|
||||
235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647,
|
||||
402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229,
|
||||
655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283,
|
||||
1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135,
|
||||
1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187,
|
||||
2011371957, 2120032959,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...109:*/
|
||||
2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U,
|
||||
3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U,
|
||||
4012305913U,
|
||||
#endif
|
||||
/*N=7, K=7...54*/
|
||||
8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777,
|
||||
1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233,
|
||||
19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013,
|
||||
88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805,
|
||||
292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433,
|
||||
793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821,
|
||||
1667010073, 1870535785, 2094367717,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...60:*/
|
||||
2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U,
|
||||
#endif
|
||||
/*N=8, K=8...37*/
|
||||
48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767,
|
||||
9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017,
|
||||
104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351,
|
||||
638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615,
|
||||
2229491905U,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...40:*/
|
||||
2691463695U, 3233240945U, 3866006015U,
|
||||
#endif
|
||||
/*N=9, K=9...28:*/
|
||||
265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777,
|
||||
39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145,
|
||||
628496897, 872893441, 1196924561, 1621925137, 2173806145U,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...29:*/
|
||||
2883810113U,
|
||||
#endif
|
||||
/*N=10, K=10...24:*/
|
||||
1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073,
|
||||
254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U,
|
||||
3375210671U,
|
||||
/*N=11, K=11...19:*/
|
||||
8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585,
|
||||
948062325, 1616336765,
|
||||
#if defined(CUSTOM_MODES)
|
||||
/*...20:*/
|
||||
2684641785U,
|
||||
#endif
|
||||
/*N=12, K=12...18:*/
|
||||
45046719, 103274625, 224298231, 464387817, 921406335, 1759885185,
|
||||
3248227095U,
|
||||
/*N=13, K=13...16:*/
|
||||
251595969, 579168825, 1267854873, 2653649025U,
|
||||
/*N=14, K=14:*/
|
||||
1409933619
|
||||
};
|
||||
|
||||
#if defined(CUSTOM_MODES)
|
||||
static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
|
||||
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415,
|
||||
CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030,
|
||||
CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389,
|
||||
CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455,
|
||||
CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473
|
||||
};
|
||||
#else
|
||||
static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
|
||||
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351,
|
||||
CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870,
|
||||
CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178,
|
||||
CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240,
|
||||
CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CUSTOM_MODES)
|
||||
void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
|
||||
int k;
|
||||
/*_maxk==0 => there's nothing to do.*/
|
||||
celt_assert(_maxk>0);
|
||||
_bits[0]=0;
|
||||
for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac);
|
||||
}
|
||||
#endif
|
||||
|
||||
static opus_uint32 icwrs(int _n,const int *_y){
|
||||
opus_uint32 i;
|
||||
int j;
|
||||
int k;
|
||||
celt_assert(_n>=2);
|
||||
j=_n-1;
|
||||
i=_y[j]<0;
|
||||
k=abs(_y[j]);
|
||||
do{
|
||||
j--;
|
||||
i+=CELT_PVQ_U(_n-j,k);
|
||||
k+=abs(_y[j]);
|
||||
if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1);
|
||||
}
|
||||
while(j>0);
|
||||
return i;
|
||||
}
|
||||
|
||||
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
|
||||
celt_assert(_k>0);
|
||||
ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k));
|
||||
}
|
||||
|
||||
static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int k0;
|
||||
opus_int16 val;
|
||||
opus_val32 yy=0;
|
||||
celt_assert(_k>0);
|
||||
celt_assert(_n>1);
|
||||
while(_n>2){
|
||||
opus_uint32 q;
|
||||
/*Lots of pulses case:*/
|
||||
if(_k>=_n){
|
||||
const opus_uint32 *row;
|
||||
row=CELT_PVQ_U_ROW[_n];
|
||||
/*Are the pulses in this dimension negative?*/
|
||||
p=row[_k+1];
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
/*Count how many pulses were placed in this dimension.*/
|
||||
k0=_k;
|
||||
q=row[_n];
|
||||
if(q>_i){
|
||||
celt_sig_assert(p>q);
|
||||
_k=_n;
|
||||
do p=CELT_PVQ_U_ROW[--_k][_n];
|
||||
while(p>_i);
|
||||
}
|
||||
else for(p=row[_k];p>_i;p=row[_k])_k--;
|
||||
_i-=p;
|
||||
val=(k0-_k+s)^s;
|
||||
*_y++=val;
|
||||
yy=MAC16_16(yy,val,val);
|
||||
}
|
||||
/*Lots of dimensions case:*/
|
||||
else{
|
||||
/*Are there any pulses in this dimension at all?*/
|
||||
p=CELT_PVQ_U_ROW[_k][_n];
|
||||
q=CELT_PVQ_U_ROW[_k+1][_n];
|
||||
if(p<=_i&&_i<q){
|
||||
_i-=p;
|
||||
*_y++=0;
|
||||
}
|
||||
else{
|
||||
/*Are the pulses in this dimension negative?*/
|
||||
s=-(_i>=q);
|
||||
_i-=q&s;
|
||||
/*Count how many pulses were placed in this dimension.*/
|
||||
k0=_k;
|
||||
do p=CELT_PVQ_U_ROW[--_k][_n];
|
||||
while(p>_i);
|
||||
_i-=p;
|
||||
val=(k0-_k+s)^s;
|
||||
*_y++=val;
|
||||
yy=MAC16_16(yy,val,val);
|
||||
}
|
||||
}
|
||||
_n--;
|
||||
}
|
||||
/*_n==2*/
|
||||
p=2*_k+1;
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
k0=_k;
|
||||
_k=(_i+1)>>1;
|
||||
if(_k)_i-=2*_k-1;
|
||||
val=(k0-_k+s)^s;
|
||||
*_y++=val;
|
||||
yy=MAC16_16(yy,val,val);
|
||||
/*_n==1*/
|
||||
s=-(int)_i;
|
||||
val=(_k+s)^s;
|
||||
*_y=val;
|
||||
yy=MAC16_16(yy,val,val);
|
||||
return yy;
|
||||
}
|
||||
|
||||
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
|
||||
return cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y);
|
||||
}
|
||||
|
||||
#else /* SMALL_FOOTPRINT */
|
||||
|
||||
/*Computes the next row/column of any recurrence that obeys the relation
|
||||
u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
|
||||
_ui0 is the base case for the new row/column.*/
|
||||
static OPUS_INLINE void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){
|
||||
opus_uint32 ui1;
|
||||
unsigned j;
|
||||
/*This do-while will overrun the array if we don't have storage for at least
|
||||
2 values.*/
|
||||
j=1; do {
|
||||
ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
|
||||
_ui[j-1]=_ui0;
|
||||
_ui0=ui1;
|
||||
} while (++j<_len);
|
||||
_ui[j-1]=_ui0;
|
||||
}
|
||||
|
||||
/*Computes the previous row/column of any recurrence that obeys the relation
|
||||
u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
|
||||
_ui0 is the base case for the new row/column.*/
|
||||
static OPUS_INLINE void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){
|
||||
opus_uint32 ui1;
|
||||
unsigned j;
|
||||
/*This do-while will overrun the array if we don't have storage for at least
|
||||
2 values.*/
|
||||
j=1; do {
|
||||
ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
|
||||
_ui[j-1]=_ui0;
|
||||
_ui0=ui1;
|
||||
} while (++j<_n);
|
||||
_ui[j-1]=_ui0;
|
||||
}
|
||||
|
||||
/*Compute V(_n,_k), as well as U(_n,0..._k+1).
|
||||
_u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/
|
||||
static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){
|
||||
opus_uint32 um2;
|
||||
unsigned len;
|
||||
unsigned k;
|
||||
len=_k+2;
|
||||
/*We require storage at least 3 values (e.g., _k>0).*/
|
||||
celt_assert(len>=3);
|
||||
_u[0]=0;
|
||||
_u[1]=um2=1;
|
||||
/*If _n==0, _u[0] should be 1 and the rest should be 0.*/
|
||||
/*If _n==1, _u[i] should be 1 for i>1.*/
|
||||
celt_assert(_n>=2);
|
||||
/*If _k==0, the following do-while loop will overflow the buffer.*/
|
||||
celt_assert(_k>0);
|
||||
k=2;
|
||||
do _u[k]=(k<<1)-1;
|
||||
while(++k<len);
|
||||
for(k=2;k<_n;k++)unext(_u+1,_k+1,1);
|
||||
return _u[_k]+_u[_k+1];
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements chosen from a set of size _n
|
||||
with associated sign bits.
|
||||
_y: Returns the vector of pulses.
|
||||
_u: Must contain entries [0..._k+1] of row _n of U() on input.
|
||||
Its contents will be destructively modified.*/
|
||||
static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){
|
||||
int j;
|
||||
opus_int16 val;
|
||||
opus_val32 yy=0;
|
||||
celt_assert(_n>0);
|
||||
j=0;
|
||||
do{
|
||||
opus_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=_u[_k+1];
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
p=_u[_k];
|
||||
while(p>_i)p=_u[--_k];
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
val=(yj+s)^s;
|
||||
_y[j]=val;
|
||||
yy=MAC16_16(yy,val,val);
|
||||
uprev(_u,_k+2,0);
|
||||
}
|
||||
while(++j<_n);
|
||||
return yy;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 1 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){
|
||||
*_k=abs(_y[0]);
|
||||
return _y[0]<0;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size _n with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values must be _k.
|
||||
_nc: Returns V(_n,_k).*/
|
||||
static OPUS_INLINE opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y,
|
||||
opus_uint32 *_u){
|
||||
opus_uint32 i;
|
||||
int j;
|
||||
int k;
|
||||
/*We can't unroll the first two iterations of the loop unless _n>=2.*/
|
||||
celt_assert(_n>=2);
|
||||
_u[0]=0;
|
||||
for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1;
|
||||
i=icwrs1(_y+_n-1,&k);
|
||||
j=_n-2;
|
||||
i+=_u[k];
|
||||
k+=abs(_y[j]);
|
||||
if(_y[j]<0)i+=_u[k+1];
|
||||
while(j-->0){
|
||||
unext(_u,_k+2,0);
|
||||
i+=_u[k];
|
||||
k+=abs(_y[j]);
|
||||
if(_y[j]<0)i+=_u[k+1];
|
||||
}
|
||||
*_nc=_u[k]+_u[k+1];
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
|
||||
int k;
|
||||
/*_maxk==0 => there's nothing to do.*/
|
||||
celt_assert(_maxk>0);
|
||||
_bits[0]=0;
|
||||
if (_n==1)
|
||||
{
|
||||
for (k=1;k<=_maxk;k++)
|
||||
_bits[k] = 1<<_frac;
|
||||
}
|
||||
else {
|
||||
VARDECL(opus_uint32,u);
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_maxk+2U,opus_uint32);
|
||||
ncwrs_urow(_n,_maxk,u);
|
||||
for(k=1;k<=_maxk;k++)
|
||||
_bits[k]=log2_frac(u[k]+u[k+1],_frac);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
|
||||
opus_uint32 i;
|
||||
VARDECL(opus_uint32,u);
|
||||
opus_uint32 nc;
|
||||
SAVE_STACK;
|
||||
celt_assert(_k>0);
|
||||
ALLOC(u,_k+2U,opus_uint32);
|
||||
i=icwrs(_n,_k,&nc,_y,u);
|
||||
ec_enc_uint(_enc,i,nc);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
|
||||
VARDECL(opus_uint32,u);
|
||||
int ret;
|
||||
SAVE_STACK;
|
||||
celt_assert(_k>0);
|
||||
ALLOC(u,_k+2U,opus_uint32);
|
||||
ret = cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation
|
||||
Copyright (c) 2007-2009 Timothy B. Terriberry
|
||||
Written by Timothy B. Terriberry and Jean-Marc Valin */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CWRS_H
|
||||
#define CWRS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
int log2_frac(opus_uint32 val, int frac);
|
||||
#endif
|
||||
|
||||
void get_required_bits(opus_int16 *bits, int N, int K, int frac);
|
||||
|
||||
void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
|
||||
|
||||
opus_val32 decode_pulses(int *_y, int N, int K, ec_dec *dec);
|
||||
|
||||
#endif /* CWRS_H */
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/* Copyright (c) 2003-2008 Timothy B. Terriberry
|
||||
Copyright (c) 2008 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*Some common macros for potential platform-specific optimization.*/
|
||||
#include "opus_types.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include "arch.h"
|
||||
#if !defined(_ecintrin_H)
|
||||
# define _ecintrin_H (1)
|
||||
|
||||
/*Some specific platforms may have optimized intrinsic or OPUS_INLINE assembly
|
||||
versions of these functions which can substantially improve performance.
|
||||
We define macros for them to allow easy incorporation of these non-ANSI
|
||||
features.*/
|
||||
|
||||
/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
|
||||
given an appropriate architecture, but the branchless bit-twiddling versions
|
||||
are just as fast, and do not require any special target architecture.
|
||||
Earlier gcc versions (3.x) compiled both code to the same assembly
|
||||
instructions, because of the way they represented ((_b)>(_a)) internally.*/
|
||||
# define EC_MINI(_a,_b) ((_a)+(((_b)-(_a))&-((_b)<(_a))))
|
||||
|
||||
/*Count leading zeros.
|
||||
This macro should only be used for implementing ec_ilog(), if it is defined.
|
||||
All other code should use EC_ILOG() instead.*/
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1910)
|
||||
# include <intrin0.h> /* Improve compiler throughput. */
|
||||
#else
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
/*In _DEBUG mode this is not an intrinsic by default.*/
|
||||
# pragma intrinsic(_BitScanReverse)
|
||||
|
||||
static __inline int ec_bsr(unsigned long _x){
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret,_x);
|
||||
return (int)ret;
|
||||
}
|
||||
# define EC_CLZ0 (1)
|
||||
# define EC_CLZ(_x) (-ec_bsr(_x))
|
||||
#elif defined(ENABLE_TI_DSPLIB)
|
||||
# include "dsplib.h"
|
||||
# define EC_CLZ0 (31)
|
||||
# define EC_CLZ(_x) (_lnorm(_x))
|
||||
#elif __GNUC_PREREQ(3,4)
|
||||
# if INT_MAX>=2147483647
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clz(_x))
|
||||
# elif LONG_MAX>=2147483647L
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clzl(_x))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(EC_CLZ)
|
||||
/*Note that __builtin_clz is not defined when _x==0, according to the gcc
|
||||
documentation (and that of the BSR instruction that implements it on x86).
|
||||
The majority of the time we can never pass it zero.
|
||||
When we need to, it can be special cased.*/
|
||||
# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
|
||||
#else
|
||||
int ec_ilog(opus_uint32 _v);
|
||||
# define EC_ILOG(_x) (ec_ilog(_x))
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
*/
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "entcode.h"
|
||||
#include "arch.h"
|
||||
|
||||
#if !defined(EC_CLZ)
|
||||
/*This is a fallback for systems where we don't know how to access
|
||||
a BSR or CLZ instruction (see ecintrin.h).
|
||||
If you are optimizing Opus on a new platform and it has a native CLZ or
|
||||
BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be
|
||||
an easy performance win.*/
|
||||
int ec_ilog(opus_uint32 _v){
|
||||
/*On a Pentium M, this branchless version tested as the fastest on
|
||||
1,000,000,000 random 32-bit integers, edging out a similar version with
|
||||
branches, and a 256-entry LUT version.*/
|
||||
int ret;
|
||||
int m;
|
||||
ret=!!_v;
|
||||
m=!!(_v&0xFFFF0000)<<4;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xFF00)<<3;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xF0)<<2;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xC)<<1;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
ret+=!!(_v&0x2);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* This is a faster version of ec_tell_frac() that takes advantage
|
||||
of the low (1/8 bit) resolution to use just a linear function
|
||||
followed by a lookup to determine the exact transition thresholds. */
|
||||
opus_uint32 ec_tell_frac(ec_ctx *_this){
|
||||
static const unsigned correction[8] =
|
||||
{35733, 38967, 42495, 46340,
|
||||
50535, 55109, 60097, 65535};
|
||||
opus_uint32 nbits;
|
||||
opus_uint32 r;
|
||||
int l;
|
||||
unsigned b;
|
||||
nbits=_this->nbits_total<<BITRES;
|
||||
l=EC_ILOG(_this->rng);
|
||||
r=_this->rng>>(l-16);
|
||||
b = (r>>12)-8;
|
||||
b += r>correction[b];
|
||||
l = (l<<3)+b;
|
||||
return nbits-l;
|
||||
}
|
||||
#else
|
||||
opus_uint32 ec_tell_frac(ec_ctx *_this){
|
||||
opus_uint32 nbits;
|
||||
opus_uint32 r;
|
||||
int l;
|
||||
int i;
|
||||
/*To handle the non-integral number of bits still left in the encoder/decoder
|
||||
state, we compute the worst-case number of bits of val that must be
|
||||
encoded to ensure that the value is inside the range for any possible
|
||||
subsequent bits.
|
||||
The computation here is independent of val itself (the decoder does not
|
||||
even track that value), even though the real number of bits used after
|
||||
ec_enc_done() may be 1 smaller if rng is a power of two and the
|
||||
corresponding trailing bits of val are all zeros.
|
||||
If we did try to track that special case, then coding a value with a
|
||||
probability of 1/(1<<n) might sometimes appear to use more than n bits.
|
||||
This may help explain the surprising result that a newly initialized
|
||||
encoder or decoder claims to have used 1 bit.*/
|
||||
nbits=_this->nbits_total<<BITRES;
|
||||
l=EC_ILOG(_this->rng);
|
||||
r=_this->rng>>(l-16);
|
||||
for(i=BITRES;i-->0;){
|
||||
int b;
|
||||
r=r*r>>15;
|
||||
b=(int)(r>>16);
|
||||
l=l<<1|b;
|
||||
r>>=b;
|
||||
}
|
||||
return nbits-l;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SMALL_DIV_TABLE
|
||||
/* Result of 2^32/(2*i+1), except for i=0. */
|
||||
const opus_uint32 SMALL_DIV_TABLE[129] = {
|
||||
0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924,
|
||||
0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111,
|
||||
0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C,
|
||||
0x0A3D70A3, 0x097B425E, 0x08D3DCB0, 0x08421084,
|
||||
0x07C1F07C, 0x07507507, 0x06EB3E45, 0x06906906,
|
||||
0x063E7063, 0x05F417D0, 0x05B05B05, 0x0572620A,
|
||||
0x05397829, 0x05050505, 0x04D4873E, 0x04A7904A,
|
||||
0x047DC11F, 0x0456C797, 0x04325C53, 0x04104104,
|
||||
0x03F03F03, 0x03D22635, 0x03B5CC0E, 0x039B0AD1,
|
||||
0x0381C0E0, 0x0369D036, 0x03531DEC, 0x033D91D2,
|
||||
0x0329161F, 0x03159721, 0x03030303, 0x02F14990,
|
||||
0x02E05C0B, 0x02D02D02, 0x02C0B02C, 0x02B1DA46,
|
||||
0x02A3A0FD, 0x0295FAD4, 0x0288DF0C, 0x027C4597,
|
||||
0x02702702, 0x02647C69, 0x02593F69, 0x024E6A17,
|
||||
0x0243F6F0, 0x0239E0D5, 0x02302302, 0x0226B902,
|
||||
0x021D9EAD, 0x0214D021, 0x020C49BA, 0x02040810,
|
||||
0x01FC07F0, 0x01F44659, 0x01ECC07B, 0x01E573AC,
|
||||
0x01DE5D6E, 0x01D77B65, 0x01D0CB58, 0x01CA4B30,
|
||||
0x01C3F8F0, 0x01BDD2B8, 0x01B7D6C3, 0x01B20364,
|
||||
0x01AC5701, 0x01A6D01A, 0x01A16D3F, 0x019C2D14,
|
||||
0x01970E4F, 0x01920FB4, 0x018D3018, 0x01886E5F,
|
||||
0x0183C977, 0x017F405F, 0x017AD220, 0x01767DCE,
|
||||
0x01724287, 0x016E1F76, 0x016A13CD, 0x01661EC6,
|
||||
0x01623FA7, 0x015E75BB, 0x015AC056, 0x01571ED3,
|
||||
0x01539094, 0x01501501, 0x014CAB88, 0x0149539E,
|
||||
0x01460CBC, 0x0142D662, 0x013FB013, 0x013C995A,
|
||||
0x013991C2, 0x013698DF, 0x0133AE45, 0x0130D190,
|
||||
0x012E025C, 0x012B404A, 0x01288B01, 0x0125E227,
|
||||
0x01234567, 0x0120B470, 0x011E2EF3, 0x011BB4A4,
|
||||
0x01194538, 0x0116E068, 0x011485F0, 0x0112358E,
|
||||
0x010FEF01, 0x010DB20A, 0x010B7E6E, 0x010953F3,
|
||||
0x01073260, 0x0105197F, 0x0103091B, 0x01010101
|
||||
};
|
||||
#endif
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opus_types.h"
|
||||
#include "opus_defines.h"
|
||||
|
||||
#if !defined(_entcode_H)
|
||||
# define _entcode_H (1)
|
||||
# include <limits.h>
|
||||
# include <stddef.h>
|
||||
# include "ecintrin.h"
|
||||
|
||||
extern const opus_uint32 SMALL_DIV_TABLE[129];
|
||||
|
||||
#ifdef OPUS_ARM_ASM
|
||||
#define USE_SMALL_DIV_TABLE
|
||||
#endif
|
||||
|
||||
/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a
|
||||
larger type, you can speed up the decoder by using it here.*/
|
||||
typedef opus_uint32 ec_window;
|
||||
typedef struct ec_ctx ec_ctx;
|
||||
typedef struct ec_ctx ec_enc;
|
||||
typedef struct ec_ctx ec_dec;
|
||||
|
||||
# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
|
||||
|
||||
/*The number of bits to use for the range-coded part of unsigned integers.*/
|
||||
# define EC_UINT_BITS (8)
|
||||
|
||||
/*The resolution of fractional-precision bit usage measurements, i.e.,
|
||||
3 => 1/8th bits.*/
|
||||
# define BITRES 3
|
||||
|
||||
/*The entropy encoder/decoder context.
|
||||
We use the same structure for both, so that common functions like ec_tell()
|
||||
can be used on either one.*/
|
||||
struct ec_ctx{
|
||||
/*Buffered input/output.*/
|
||||
unsigned char *buf;
|
||||
/*The size of the buffer.*/
|
||||
opus_uint32 storage;
|
||||
/*The offset at which the last byte containing raw bits was read/written.*/
|
||||
opus_uint32 end_offs;
|
||||
/*Bits that will be read from/written at the end.*/
|
||||
ec_window end_window;
|
||||
/*Number of valid bits in end_window.*/
|
||||
int nend_bits;
|
||||
/*The total number of whole bits read/written.
|
||||
This does not include partial bits currently in the range coder.*/
|
||||
int nbits_total;
|
||||
/*The offset at which the next range coder byte will be read/written.*/
|
||||
opus_uint32 offs;
|
||||
/*The number of values in the current range.*/
|
||||
opus_uint32 rng;
|
||||
/*In the decoder: the difference between the top of the current range and
|
||||
the input value, minus one.
|
||||
In the encoder: the low end of the current range.*/
|
||||
opus_uint32 val;
|
||||
/*In the decoder: the saved normalization factor from ec_decode().
|
||||
In the encoder: the number of oustanding carry propagating symbols.*/
|
||||
opus_uint32 ext;
|
||||
/*A buffered input/output symbol, awaiting carry propagation.*/
|
||||
int rem;
|
||||
/*Nonzero if an error occurred.*/
|
||||
int error;
|
||||
};
|
||||
|
||||
static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){
|
||||
return _this->offs;
|
||||
}
|
||||
|
||||
static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){
|
||||
return _this->buf;
|
||||
}
|
||||
|
||||
static OPUS_INLINE int ec_get_error(ec_ctx *_this){
|
||||
return _this->error;
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
static OPUS_INLINE int ec_tell(ec_ctx *_this){
|
||||
return _this->nbits_total-EC_ILOG(_this->rng);
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits scaled by 2**BITRES.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
opus_uint32 ec_tell_frac(ec_ctx *_this);
|
||||
|
||||
/* Tested exhaustively for all n and for 1<=d<=256 */
|
||||
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
|
||||
celt_sig_assert(d>0);
|
||||
#ifdef USE_SMALL_DIV_TABLE
|
||||
if (d>256)
|
||||
return n/d;
|
||||
else {
|
||||
opus_uint32 t, q;
|
||||
t = EC_ILOG(d&-d);
|
||||
q = (opus_uint64)SMALL_DIV_TABLE[d>>t]*(n>>(t-1))>>32;
|
||||
return q+(n-q*d >= d);
|
||||
}
|
||||
#else
|
||||
return n/d;
|
||||
#endif
|
||||
}
|
||||
|
||||
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
|
||||
celt_sig_assert(d>0);
|
||||
#ifdef USE_SMALL_DIV_TABLE
|
||||
if (n<0)
|
||||
return -(opus_int32)celt_udiv(-n, d);
|
||||
else
|
||||
return celt_udiv(n, d);
|
||||
#else
|
||||
return n/d;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "os_support.h"
|
||||
#include "arch.h"
|
||||
#include "entdec.h"
|
||||
#include "mfrngcod.h"
|
||||
|
||||
/*A range decoder.
|
||||
This is an entropy decoder based upon \cite{Mar79}, which is itself a
|
||||
rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
|
||||
It is very similar to arithmetic encoding, except that encoding is done with
|
||||
digits in any base, instead of with bits, and so it is faster when using
|
||||
larger bases (i.e.: a byte).
|
||||
The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
|
||||
is the base, longer than the theoretical optimum, but to my knowledge there
|
||||
is no published justification for this claim.
|
||||
This only seems true when using near-infinite precision arithmetic so that
|
||||
the process is carried out with no rounding errors.
|
||||
|
||||
An excellent description of implementation details is available at
|
||||
http://www.arturocampos.com/ac_range.html
|
||||
A recent work \cite{MNW98} which proposes several changes to arithmetic
|
||||
encoding for efficiency actually re-discovers many of the principles
|
||||
behind range encoding, and presents a good theoretical analysis of them.
|
||||
|
||||
End of stream is handled by writing out the smallest number of bits that
|
||||
ensures that the stream will be correctly decoded regardless of the value of
|
||||
any subsequent bits.
|
||||
ec_tell() can be used to determine how many bits were needed to decode
|
||||
all the symbols thus far; other data can be packed in the remaining bits of
|
||||
the input buffer.
|
||||
@PHDTHESIS{Pas76,
|
||||
author="Richard Clark Pasco",
|
||||
title="Source coding algorithms for fast data compression",
|
||||
school="Dept. of Electrical Engineering, Stanford University",
|
||||
address="Stanford, CA",
|
||||
month=May,
|
||||
year=1976
|
||||
}
|
||||
@INPROCEEDINGS{Mar79,
|
||||
author="Martin, G.N.N.",
|
||||
title="Range encoding: an algorithm for removing redundancy from a digitised
|
||||
message",
|
||||
booktitle="Video & Data Recording Conference",
|
||||
year=1979,
|
||||
address="Southampton",
|
||||
month=Jul
|
||||
}
|
||||
@ARTICLE{MNW98,
|
||||
author="Alistair Moffat and Radford Neal and Ian H. Witten",
|
||||
title="Arithmetic Coding Revisited",
|
||||
journal="{ACM} Transactions on Information Systems",
|
||||
year=1998,
|
||||
volume=16,
|
||||
number=3,
|
||||
pages="256--294",
|
||||
month=Jul,
|
||||
URL="http://www.stanford.edu/class/ee398a/handouts/papers/Moffat98ArithmCoding.pdf"
|
||||
}*/
|
||||
|
||||
static int ec_read_byte(ec_dec *_this){
|
||||
return _this->offs<_this->storage?_this->buf[_this->offs++]:0;
|
||||
}
|
||||
|
||||
static int ec_read_byte_from_end(ec_dec *_this){
|
||||
return _this->end_offs<_this->storage?
|
||||
_this->buf[_this->storage-++(_this->end_offs)]:0;
|
||||
}
|
||||
|
||||
/*Normalizes the contents of val and rng so that rng lies entirely in the
|
||||
high-order symbol.*/
|
||||
static void ec_dec_normalize(ec_dec *_this){
|
||||
/*If the range is too small, rescale it and input some bits.*/
|
||||
while(_this->rng<=EC_CODE_BOT){
|
||||
int sym;
|
||||
_this->nbits_total+=EC_SYM_BITS;
|
||||
_this->rng<<=EC_SYM_BITS;
|
||||
/*Use up the remaining bits from our last symbol.*/
|
||||
sym=_this->rem;
|
||||
/*Read the next value from the input.*/
|
||||
_this->rem=ec_read_byte(_this);
|
||||
/*Take the rest of the bits we need from this new symbol.*/
|
||||
sym=(sym<<EC_SYM_BITS|_this->rem)>>(EC_SYM_BITS-EC_CODE_EXTRA);
|
||||
/*And subtract them from val, capped to be less than EC_CODE_TOP.*/
|
||||
_this->val=((_this->val<<EC_SYM_BITS)+(EC_SYM_MAX&~sym))&(EC_CODE_TOP-1);
|
||||
}
|
||||
}
|
||||
|
||||
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage){
|
||||
_this->buf=_buf;
|
||||
_this->storage=_storage;
|
||||
_this->end_offs=0;
|
||||
_this->end_window=0;
|
||||
_this->nend_bits=0;
|
||||
/*This is the offset from which ec_tell() will subtract partial bits.
|
||||
The final value after the ec_dec_normalize() call will be the same as in
|
||||
the encoder, but we have to compensate for the bits that are added there.*/
|
||||
_this->nbits_total=EC_CODE_BITS+1
|
||||
-((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS;
|
||||
_this->offs=0;
|
||||
_this->rng=1U<<EC_CODE_EXTRA;
|
||||
_this->rem=ec_read_byte(_this);
|
||||
_this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA));
|
||||
_this->error=0;
|
||||
/*Normalize the interval.*/
|
||||
ec_dec_normalize(_this);
|
||||
}
|
||||
|
||||
unsigned ec_decode(ec_dec *_this,unsigned _ft){
|
||||
unsigned s;
|
||||
_this->ext=celt_udiv(_this->rng,_ft);
|
||||
s=(unsigned)(_this->val/_this->ext);
|
||||
return _ft-EC_MINI(s+1,_ft);
|
||||
}
|
||||
|
||||
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){
|
||||
unsigned s;
|
||||
_this->ext=_this->rng>>_bits;
|
||||
s=(unsigned)(_this->val/_this->ext);
|
||||
return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits);
|
||||
}
|
||||
|
||||
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||
opus_uint32 s;
|
||||
s=IMUL32(_this->ext,_ft-_fh);
|
||||
_this->val-=s;
|
||||
_this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s;
|
||||
ec_dec_normalize(_this);
|
||||
}
|
||||
|
||||
/*The probability of having a "one" is 1/(1<<_logp).*/
|
||||
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
int ret;
|
||||
r=_this->rng;
|
||||
d=_this->val;
|
||||
s=r>>_logp;
|
||||
ret=d<s;
|
||||
if(!ret)_this->val=d-s;
|
||||
_this->rng=ret?s:r-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
opus_uint32 t;
|
||||
int ret;
|
||||
s=_this->rng;
|
||||
d=_this->val;
|
||||
r=s>>_ftb;
|
||||
ret=-1;
|
||||
do{
|
||||
t=s;
|
||||
s=IMUL32(r,_icdf[++ret]);
|
||||
}
|
||||
while(d<s);
|
||||
_this->val=d-s;
|
||||
_this->rng=t-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb){
|
||||
opus_uint32 r;
|
||||
opus_uint32 d;
|
||||
opus_uint32 s;
|
||||
opus_uint32 t;
|
||||
int ret;
|
||||
s=_this->rng;
|
||||
d=_this->val;
|
||||
r=s>>_ftb;
|
||||
ret=-1;
|
||||
do{
|
||||
t=s;
|
||||
s=IMUL32(r,_icdf[++ret]);
|
||||
}
|
||||
while(d<s);
|
||||
_this->val=d-s;
|
||||
_this->rng=t-s;
|
||||
ec_dec_normalize(_this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
|
||||
unsigned ft;
|
||||
unsigned s;
|
||||
int ftb;
|
||||
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
|
||||
celt_assert(_ft>1);
|
||||
_ft--;
|
||||
ftb=EC_ILOG(_ft);
|
||||
if(ftb>EC_UINT_BITS){
|
||||
opus_uint32 t;
|
||||
ftb-=EC_UINT_BITS;
|
||||
ft=(unsigned)(_ft>>ftb)+1;
|
||||
s=ec_decode(_this,ft);
|
||||
ec_dec_update(_this,s,s+1,ft);
|
||||
t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb);
|
||||
if(t<=_ft)return t;
|
||||
_this->error=1;
|
||||
return _ft;
|
||||
}
|
||||
else{
|
||||
_ft++;
|
||||
s=ec_decode(_this,(unsigned)_ft);
|
||||
ec_dec_update(_this,s,s+1,(unsigned)_ft);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
|
||||
ec_window window;
|
||||
int available;
|
||||
opus_uint32 ret;
|
||||
window=_this->end_window;
|
||||
available=_this->nend_bits;
|
||||
if((unsigned)available<_bits){
|
||||
do{
|
||||
window|=(ec_window)ec_read_byte_from_end(_this)<<available;
|
||||
available+=EC_SYM_BITS;
|
||||
}
|
||||
while(available<=EC_WINDOW_SIZE-EC_SYM_BITS);
|
||||
}
|
||||
ret=(opus_uint32)window&(((opus_uint32)1<<_bits)-1U);
|
||||
window>>=_bits;
|
||||
available-=_bits;
|
||||
_this->end_window=window;
|
||||
_this->nend_bits=available;
|
||||
_this->nbits_total+=_bits;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/* Copyright (c) 2001-2011 Timothy B. Terriberry
|
||||
Copyright (c) 2008-2009 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_entdec_H)
|
||||
# define _entdec_H (1)
|
||||
# include <limits.h>
|
||||
# include "entcode.h"
|
||||
|
||||
/*Initializes the decoder.
|
||||
_buf: The input buffer to use.
|
||||
Return: 0 on success, or a negative value on error.*/
|
||||
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage);
|
||||
|
||||
/*Calculates the cumulative frequency for the next symbol.
|
||||
This can then be fed into the probability model to determine what that
|
||||
symbol is, and the additional frequency information required to advance to
|
||||
the next symbol.
|
||||
This function cannot be called more than once without a corresponding call to
|
||||
ec_dec_update(), or decoding will not proceed correctly.
|
||||
_ft: The total frequency of the symbols in the alphabet the next symbol was
|
||||
encoded with.
|
||||
Return: A cumulative frequency representing the encoded symbol.
|
||||
If the cumulative frequency of all the symbols before the one that
|
||||
was encoded was fl, and the cumulative frequency of all the symbols
|
||||
up to and including the one encoded is fh, then the returned value
|
||||
will fall in the range [fl,fh).*/
|
||||
unsigned ec_decode(ec_dec *_this,unsigned _ft);
|
||||
|
||||
/*Equivalent to ec_decode() with _ft==1<<_bits.*/
|
||||
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits);
|
||||
|
||||
/*Advance the decoder past the next symbol using the frequency information the
|
||||
symbol was encoded with.
|
||||
Exactly one call to ec_decode() must have been made so that all necessary
|
||||
intermediate calculations are performed.
|
||||
_fl: The cumulative frequency of all symbols that come before the symbol
|
||||
decoded.
|
||||
_fh: The cumulative frequency of all symbols up to and including the symbol
|
||||
decoded.
|
||||
Together with _fl, this defines the range [_fl,_fh) in which the value
|
||||
returned above must fall.
|
||||
_ft: The total frequency of the symbols in the alphabet the symbol decoded
|
||||
was encoded in.
|
||||
This must be the same as passed to the preceding call to ec_decode().*/
|
||||
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft);
|
||||
|
||||
/* Decode a bit that has a 1/(1<<_logp) probability of being a one */
|
||||
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
|
||||
|
||||
/*Decodes a symbol given an "inverse" CDF table.
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_icdf: The "inverse" CDF, such that symbol s falls in the range
|
||||
[s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.
|
||||
Return: The decoded symbol s.*/
|
||||
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
|
||||
|
||||
/*Decodes a symbol given an "inverse" CDF table.
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_icdf: The "inverse" CDF, such that symbol s falls in the range
|
||||
[s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
|
||||
The values must be monotonically non-increasing, and the last value
|
||||
must be 0.
|
||||
_ftb: The number of bits of precision in the cumulative distribution.
|
||||
Return: The decoded symbol s.*/
|
||||
int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_icdf,unsigned _ftb);
|
||||
|
||||
/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
|
||||
The bits must have been encoded with ec_enc_uint().
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_ft: The number of integers that can be decoded (one more than the max).
|
||||
This must be at least 2, and no more than 2**32-1.
|
||||
Return: The decoded bits.*/
|
||||
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
|
||||
|
||||
/*Extracts a sequence of raw bits from the stream.
|
||||
The bits must have been encoded with ec_enc_bits().
|
||||
No call to ec_dec_update() is necessary after this call.
|
||||
_ftb: The number of bits to extract.
|
||||
This must be between 0 and 25, inclusive.
|
||||
Return: The decoded bits.*/
|
||||
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue