├── COPYING ├── Makefile ├── README ├── freeaptx.c ├── freeaptx.h ├── freeaptxdec.c └── freeaptxenc.c /COPYING: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .POSIX: 2 | .SUFFIXES: 3 | .PHONY: default all clean install uninstall 4 | 5 | RM = rm -f 6 | CP = cp -a 7 | LNS = ln -sf 8 | MKDIR = mkdir -p 9 | PRINTF = printf 10 | 11 | CFLAGS = -W -Wall -O3 12 | LDFLAGS = -s 13 | ARFLAGS = -rcs 14 | 15 | PREFIX = /usr/local 16 | BINDIR = bin 17 | LIBDIR = lib 18 | INCDIR = include 19 | PKGDIR = $(LIBDIR)/pkgconfig 20 | 21 | NAME = freeaptx 22 | MAJOR = 0 23 | MINOR = 2 24 | PATCH = 2 25 | 26 | LIBNAME = lib$(NAME).so 27 | SONAME = $(LIBNAME).$(MAJOR) 28 | SOFILENAME = $(SONAME).$(MINOR).$(PATCH) 29 | PCNAME = lib$(NAME).pc 30 | 31 | UTILITIES = $(NAME)enc $(NAME)dec 32 | STATIC_UTILITIES = $(NAME)enc.static $(NAME)dec.static 33 | 34 | HEADERS = $(NAME).h 35 | SOURCES = $(NAME).c 36 | AOBJECTS = $(NAME).o 37 | IOBJECTS = $(NAME)enc.o $(NAME)dec.o 38 | 39 | BUILD = $(SOFILENAME) $(SONAME) $(LIBNAME) $(IOBJECTS) $(UTILITIES) 40 | 41 | default: $(SOFILENAME) $(SONAME) $(LIBNAME) $(UTILITIES) $(HEADERS) 42 | 43 | all: $(BUILD) 44 | 45 | clean: 46 | $(RM) $(BUILD) 47 | 48 | install: default 49 | $(MKDIR) $(DESTDIR)$(PREFIX)/$(LIBDIR) 50 | $(CP) $(SOFILENAME) $(SONAME) $(LIBNAME) $(DESTDIR)$(PREFIX)/$(LIBDIR) 51 | $(MKDIR) $(DESTDIR)$(PREFIX)/$(BINDIR) 52 | $(CP) $(UTILITIES) $(DESTDIR)$(PREFIX)/$(BINDIR) 53 | $(MKDIR) $(DESTDIR)$(PREFIX)/$(INCDIR) 54 | $(CP) $(HEADERS) $(DESTDIR)$(PREFIX)/$(INCDIR) 55 | $(MKDIR) $(DESTDIR)$(PREFIX)/$(PKGDIR) 56 | $(PRINTF) 'prefix=%s\nexec_prefix=$${prefix}\nlibdir=$${exec_prefix}/%s\nincludedir=$${prefix}/%s\n\n' $(PREFIX) $(LIBDIR) $(INCDIR) > $(DESTDIR)$(PREFIX)/$(PKGDIR)/$(PCNAME) 57 | $(PRINTF) 'Name: lib%s\nDescription: Open Source aptX codec library\nVersion: %u.%u.%u\n' $(NAME) $(MAJOR) $(MINOR) $(PATCH) >> $(DESTDIR)$(PREFIX)/$(PKGDIR)/$(PCNAME) 58 | $(PRINTF) 'Libs: -L$${libdir} -l%s\nCflags: -I$${includedir}\n' $(NAME) >> $(DESTDIR)$(PREFIX)/$(PKGDIR)/$(PCNAME) 59 | 60 | uninstall: 61 | for f in $(SOFILENAME) $(SONAME) $(LIBNAME); do $(RM) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$$f; done 62 | for f in $(UTILITIES); do $(RM) $(DESTDIR)$(PREFIX)/$(BINDIR)/$$f; done 63 | for f in $(HEADERS); do $(RM) $(DESTDIR)$(PREFIX)/$(INCDIR)/$$f; done 64 | $(RM) $(DESTDIR)$(PREFIX)/$(PKGDIR)/$(PCNAME) 65 | 66 | $(UTILITIES): $(LIBNAME) 67 | 68 | $(IOBJECTS): $(HEADERS) 69 | 70 | $(LIBNAME): $(SONAME) 71 | $(LNS) $(SONAME) $@ 72 | 73 | $(SONAME): $(SOFILENAME) 74 | $(LNS) $(SOFILENAME) $@ 75 | 76 | $(SOFILENAME): $(SOURCES) $(HEADERS) 77 | $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -I. -shared -fPIC -Wl,-soname,$(SONAME) -o $@ $(SOURCES) 78 | 79 | .SUFFIXES: .o .c .static 80 | 81 | .o: 82 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBNAME) 83 | 84 | .c.o: 85 | $(CC) $(CFLAGS) $(CPPFLAGS) -I. -c -o $@ $< 86 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ### This project is in maintenance mode! 2 | 3 | I forked this from libopenaptx 0.2.0 after a problematic licensing change 4 | upstream in 0.2.1. This project is in maintenance mode. 5 | 6 | ### libfreeaptx 7 | 8 | This is Open Source implementation of Audio Processing Technology codec (aptX) 9 | derived from ffmpeg 4.0 project and licensed under LGPLv2.1+. This codec is 10 | mainly used in Bluetooth A2DP profile. 11 | 12 | It provides dynamic linked shared library libfreeaptx.so and simple command line 13 | utilities freeaptxenc and freeaptxdec for encoding and decoding operations. 14 | Documentation for shared library is provided in C header file freeaptx.h. 15 | 16 | There is support for aptX and aptX HD codec variants. Both variants operates on 17 | a raw 24 bit signed stereo audio samples. aptX provides fixed compress ratio 6:1 18 | and aptX HD fixed compress ratio 4:1. 19 | 20 | For building and installing into system simply run: make install. For building 21 | without installing run: LD_RUN_PATH='$ORIGIN' make. For producing windows builds 22 | run: make SOFILENAME=freeaptx0.dll. 23 | 24 | It is suggested to compile library with -O3 optimizations (enabled by default 25 | when env variable CFLAGS is not set) and -mavx2 switch (not enabled by default, 26 | needs CPU with AVX2: Intel Haswell or AMD Excavator) as it provides significant 27 | boost to the performance. 28 | 29 | Usage of command line utilities together with sox for resampling or playing: 30 | 31 | To convert Wave audio file sample.wav into aptX audio file sample.aptx run: 32 | 33 | $ sox sample.wav -t raw -r 44.1k -L -e s -b 24 -c 2 - | freeaptxenc > sample.aptx 34 | 35 | To convert aptX audio file sample.aptx into Wave audio file sample.wav run: 36 | 37 | $ freeaptxdec < sample.aptx | sox -t raw -r 44.1k -L -e s -b 24 -c 2 - sample.wav 38 | 39 | To convert MP3 audio file sample.mp3 into aptX HD audio file sample.aptxhd run: 40 | 41 | $ sox sample.mp3 -t raw -r 44.1k -L -e s -b 24 -c 2 - | freeaptxenc --hd > sample.aptxhd 42 | 43 | To play aptX HD audio file sample.aptxhd run: 44 | 45 | $ freeaptxdec --hd < sample.aptxhd | play -t raw -r 44.1k -L -e s -b 24 -c 2 - 46 | -------------------------------------------------------------------------------- /freeaptx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Open Source implementation of Audio Processing Technology codec (aptX) 3 | * Copyright (C) 2017 Aurelien Jacobs 4 | * Copyright (C) 2018-2020 Pali Rohár 5 | * Copyright (C) 2025 Hunter Wardlaw 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #if (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) && !defined(inline) 29 | #define inline 30 | #endif 31 | 32 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 33 | #define DIFFSIGN(x,y) (((x)>(y)) - ((x)<(y))) 34 | 35 | /* 36 | * Clip a signed integer into the -(2^p),(2^p-1) range. 37 | * @param a value to clip 38 | * @param p bit position to clip at 39 | * @return clipped value 40 | */ 41 | static inline int32_t clip_intp2(int32_t a, unsigned p) 42 | { 43 | if (((uint32_t)a + ((uint32_t)1 << p)) & ~(((uint32_t)2 << p) - 1)) 44 | return (a >> 31) ^ ((1 << p) - 1); 45 | else 46 | return a; 47 | } 48 | 49 | /* 50 | * Clip a signed integer value into the amin-amax range. 51 | * @param a value to clip 52 | * @param amin minimum value of the clip range 53 | * @param amax maximum value of the clip range 54 | * @return clipped value 55 | */ 56 | static inline int32_t clip(int32_t a, int32_t amin, int32_t amax) 57 | { 58 | if (a < amin) return amin; 59 | else if (a > amax) return amax; 60 | else return a; 61 | } 62 | 63 | static inline int32_t sign_extend(int32_t val, unsigned bits) 64 | { 65 | const unsigned shift = 8 * sizeof(val) - bits; 66 | union { uint32_t u; int32_t s; } v; 67 | v.u = (uint32_t)val << shift; 68 | return v.s >> shift; 69 | } 70 | 71 | enum channels { 72 | LEFT, 73 | RIGHT, 74 | NB_CHANNELS 75 | }; 76 | 77 | #define NB_SUBBANDS 4 78 | #define NB_FILTERS 2 79 | #define FILTER_TAPS 16 80 | #define LATENCY_SAMPLES 90 81 | 82 | struct aptx_filter_signal { 83 | int32_t buffer[2*FILTER_TAPS]; 84 | uint8_t pos; 85 | }; 86 | 87 | struct aptx_QMF_analysis { 88 | struct aptx_filter_signal outer_filter_signal[NB_FILTERS]; 89 | struct aptx_filter_signal inner_filter_signal[NB_FILTERS][NB_FILTERS]; 90 | }; 91 | 92 | struct aptx_quantize { 93 | int32_t quantized_sample; 94 | int32_t quantized_sample_parity_change; 95 | int32_t error; 96 | }; 97 | 98 | struct aptx_invert_quantize { 99 | int32_t quantization_factor; 100 | int32_t factor_select; 101 | int32_t reconstructed_difference; 102 | }; 103 | 104 | struct aptx_prediction { 105 | int32_t prev_sign[2]; 106 | int32_t s_weight[2]; 107 | int32_t d_weight[24]; 108 | int32_t pos; 109 | int32_t reconstructed_differences[48]; 110 | int32_t previous_reconstructed_sample; 111 | int32_t predicted_difference; 112 | int32_t predicted_sample; 113 | }; 114 | 115 | struct aptx_channel { 116 | int32_t codeword_history; 117 | int32_t dither_parity; 118 | int32_t dither[NB_SUBBANDS]; 119 | 120 | struct aptx_QMF_analysis qmf; 121 | struct aptx_quantize quantize[NB_SUBBANDS]; 122 | struct aptx_invert_quantize invert_quantize[NB_SUBBANDS]; 123 | struct aptx_prediction prediction[NB_SUBBANDS]; 124 | }; 125 | 126 | struct aptx_context { 127 | size_t decode_sync_packets; 128 | size_t decode_dropped; 129 | struct aptx_channel channels[NB_CHANNELS]; 130 | uint8_t hd; 131 | uint8_t sync_idx; 132 | uint8_t encode_remaining; 133 | uint8_t decode_skip_leading; 134 | uint8_t decode_sync_buffer_len; 135 | unsigned char decode_sync_buffer[6]; 136 | }; 137 | 138 | 139 | static const int32_t quantize_intervals_LF[65] = { 140 | -9948, 9948, 29860, 49808, 69822, 89926, 110144, 130502, 141 | 151026, 171738, 192666, 213832, 235264, 256982, 279014, 301384, 142 | 324118, 347244, 370790, 394782, 419250, 444226, 469742, 495832, 143 | 522536, 549890, 577936, 606720, 636290, 666700, 698006, 730270, 144 | 763562, 797958, 833538, 870398, 908640, 948376, 989740, 1032874, 145 | 1077948, 1125150, 1174700, 1226850, 1281900, 1340196, 1402156, 1468282, 146 | 1539182, 1615610, 1698514, 1789098, 1888944, 2000168, 2125700, 2269750, 147 | 2438670, 2642660, 2899462, 3243240, 3746078, 4535138, 5664098, 7102424, 148 | 8897462, 149 | }; 150 | static const int32_t invert_quantize_dither_factors_LF[65] = { 151 | 9948, 9948, 9962, 9988, 10026, 10078, 10142, 10218, 152 | 10306, 10408, 10520, 10646, 10784, 10934, 11098, 11274, 153 | 11462, 11664, 11880, 12112, 12358, 12618, 12898, 13194, 154 | 13510, 13844, 14202, 14582, 14988, 15422, 15884, 16380, 155 | 16912, 17484, 18098, 18762, 19480, 20258, 21106, 22030, 156 | 23044, 24158, 25390, 26760, 28290, 30008, 31954, 34172, 157 | 36728, 39700, 43202, 47382, 52462, 58762, 66770, 77280, 158 | 91642, 112348, 144452, 199326, 303512, 485546, 643414, 794914, 159 | 1000124, 160 | }; 161 | static const int32_t quantize_dither_factors_LF[65] = { 162 | 0, 4, 7, 10, 13, 16, 19, 22, 163 | 26, 28, 32, 35, 38, 41, 44, 47, 164 | 51, 54, 58, 62, 65, 70, 74, 79, 165 | 84, 90, 95, 102, 109, 116, 124, 133, 166 | 143, 154, 166, 180, 195, 212, 231, 254, 167 | 279, 308, 343, 383, 430, 487, 555, 639, 168 | 743, 876, 1045, 1270, 1575, 2002, 2628, 3591, 169 | 5177, 8026, 13719, 26047, 45509, 39467, 37875, 51303, 170 | 0, 171 | }; 172 | static const int16_t quantize_factor_select_offset_LF[65] = { 173 | 0, -21, -19, -17, -15, -12, -10, -8, 174 | -6, -4, -1, 1, 3, 6, 8, 10, 175 | 13, 15, 18, 20, 23, 26, 29, 31, 176 | 34, 37, 40, 43, 47, 50, 53, 57, 177 | 60, 64, 68, 72, 76, 80, 85, 89, 178 | 94, 99, 105, 110, 116, 123, 129, 136, 179 | 144, 152, 161, 171, 182, 194, 207, 223, 180 | 241, 263, 291, 328, 382, 467, 522, 522, 181 | 522, 182 | }; 183 | 184 | 185 | static const int32_t quantize_intervals_MLF[9] = { 186 | -89806, 89806, 278502, 494338, 759442, 1113112, 1652322, 2720256, 5190186, 187 | }; 188 | static const int32_t invert_quantize_dither_factors_MLF[9] = { 189 | 89806, 89806, 98890, 116946, 148158, 205512, 333698, 734236, 1735696, 190 | }; 191 | static const int32_t quantize_dither_factors_MLF[9] = { 192 | 0, 2271, 4514, 7803, 14339, 32047, 100135, 250365, 0, 193 | }; 194 | static const int16_t quantize_factor_select_offset_MLF[9] = { 195 | 0, -14, 6, 29, 58, 96, 154, 270, 521, 196 | }; 197 | 198 | 199 | static const int32_t quantize_intervals_MHF[3] = { 200 | -194080, 194080, 890562, 201 | }; 202 | static const int32_t invert_quantize_dither_factors_MHF[3] = { 203 | 194080, 194080, 502402, 204 | }; 205 | static const int32_t quantize_dither_factors_MHF[3] = { 206 | 0, 77081, 0, 207 | }; 208 | static const int16_t quantize_factor_select_offset_MHF[3] = { 209 | 0, -33, 136, 210 | }; 211 | 212 | 213 | static const int32_t quantize_intervals_HF[5] = { 214 | -163006, 163006, 542708, 1120554, 2669238, 215 | }; 216 | static const int32_t invert_quantize_dither_factors_HF[5] = { 217 | 163006, 163006, 216698, 361148, 1187538, 218 | }; 219 | static const int32_t quantize_dither_factors_HF[5] = { 220 | 0, 13423, 36113, 206598, 0, 221 | }; 222 | static const int16_t quantize_factor_select_offset_HF[5] = { 223 | 0, -8, 33, 95, 262, 224 | }; 225 | 226 | 227 | static const int32_t hd_quantize_intervals_LF[257] = { 228 | -2436, 2436, 7308, 12180, 17054, 21930, 26806, 31686, 229 | 36566, 41450, 46338, 51230, 56124, 61024, 65928, 70836, 230 | 75750, 80670, 85598, 90530, 95470, 100418, 105372, 110336, 231 | 115308, 120288, 125278, 130276, 135286, 140304, 145334, 150374, 232 | 155426, 160490, 165566, 170654, 175756, 180870, 185998, 191138, 233 | 196294, 201466, 206650, 211850, 217068, 222300, 227548, 232814, 234 | 238096, 243396, 248714, 254050, 259406, 264778, 270172, 275584, 235 | 281018, 286470, 291944, 297440, 302956, 308496, 314056, 319640, 236 | 325248, 330878, 336532, 342212, 347916, 353644, 359398, 365178, 237 | 370986, 376820, 382680, 388568, 394486, 400430, 406404, 412408, 238 | 418442, 424506, 430600, 436726, 442884, 449074, 455298, 461554, 239 | 467844, 474168, 480528, 486922, 493354, 499820, 506324, 512866, 240 | 519446, 526064, 532722, 539420, 546160, 552940, 559760, 566624, 241 | 573532, 580482, 587478, 594520, 601606, 608740, 615920, 623148, 242 | 630426, 637754, 645132, 652560, 660042, 667576, 675164, 682808, 243 | 690506, 698262, 706074, 713946, 721876, 729868, 737920, 746036, 244 | 754216, 762460, 770770, 779148, 787594, 796108, 804694, 813354, 245 | 822086, 830892, 839774, 848736, 857776, 866896, 876100, 885386, 246 | 894758, 904218, 913766, 923406, 933138, 942964, 952886, 962908, 247 | 973030, 983254, 993582, 1004020, 1014566, 1025224, 1035996, 1046886, 248 | 1057894, 1069026, 1080284, 1091670, 1103186, 1114838, 1126628, 1138558, 249 | 1150634, 1162858, 1175236, 1187768, 1200462, 1213320, 1226346, 1239548, 250 | 1252928, 1266490, 1280242, 1294188, 1308334, 1322688, 1337252, 1352034, 251 | 1367044, 1382284, 1397766, 1413494, 1429478, 1445728, 1462252, 1479058, 252 | 1496158, 1513562, 1531280, 1549326, 1567710, 1586446, 1605550, 1625034, 253 | 1644914, 1665208, 1685932, 1707108, 1728754, 1750890, 1773542, 1796732, 254 | 1820488, 1844840, 1869816, 1895452, 1921780, 1948842, 1976680, 2005338, 255 | 2034868, 2065322, 2096766, 2129260, 2162880, 2197708, 2233832, 2271352, 256 | 2310384, 2351050, 2393498, 2437886, 2484404, 2533262, 2584710, 2639036, 257 | 2696578, 2757738, 2822998, 2892940, 2968278, 3049896, 3138912, 3236760, 258 | 3345312, 3467068, 3605434, 3765154, 3952904, 4177962, 4452178, 4787134, 259 | 5187290, 5647128, 6159120, 6720518, 7332904, 8000032, 8726664, 9518152, 260 | 10380372, 261 | }; 262 | static const int32_t hd_invert_quantize_dither_factors_LF[257] = { 263 | 2436, 2436, 2436, 2436, 2438, 2438, 2438, 2440, 264 | 2442, 2442, 2444, 2446, 2448, 2450, 2454, 2456, 265 | 2458, 2462, 2464, 2468, 2472, 2476, 2480, 2484, 266 | 2488, 2492, 2498, 2502, 2506, 2512, 2518, 2524, 267 | 2528, 2534, 2540, 2548, 2554, 2560, 2568, 2574, 268 | 2582, 2588, 2596, 2604, 2612, 2620, 2628, 2636, 269 | 2646, 2654, 2664, 2672, 2682, 2692, 2702, 2712, 270 | 2722, 2732, 2742, 2752, 2764, 2774, 2786, 2798, 271 | 2810, 2822, 2834, 2846, 2858, 2870, 2884, 2896, 272 | 2910, 2924, 2938, 2952, 2966, 2980, 2994, 3010, 273 | 3024, 3040, 3056, 3070, 3086, 3104, 3120, 3136, 274 | 3154, 3170, 3188, 3206, 3224, 3242, 3262, 3280, 275 | 3300, 3320, 3338, 3360, 3380, 3400, 3422, 3442, 276 | 3464, 3486, 3508, 3532, 3554, 3578, 3602, 3626, 277 | 3652, 3676, 3702, 3728, 3754, 3780, 3808, 3836, 278 | 3864, 3892, 3920, 3950, 3980, 4010, 4042, 4074, 279 | 4106, 4138, 4172, 4206, 4240, 4276, 4312, 4348, 280 | 4384, 4422, 4460, 4500, 4540, 4580, 4622, 4664, 281 | 4708, 4752, 4796, 4842, 4890, 4938, 4986, 5036, 282 | 5086, 5138, 5192, 5246, 5300, 5358, 5416, 5474, 283 | 5534, 5596, 5660, 5726, 5792, 5860, 5930, 6002, 284 | 6074, 6150, 6226, 6306, 6388, 6470, 6556, 6644, 285 | 6736, 6828, 6924, 7022, 7124, 7228, 7336, 7448, 286 | 7562, 7680, 7802, 7928, 8058, 8192, 8332, 8476, 287 | 8624, 8780, 8940, 9106, 9278, 9458, 9644, 9840, 288 | 10042, 10252, 10472, 10702, 10942, 11194, 11458, 11734, 289 | 12024, 12328, 12648, 12986, 13342, 13720, 14118, 14540, 290 | 14990, 15466, 15976, 16520, 17102, 17726, 18398, 19124, 291 | 19908, 20760, 21688, 22702, 23816, 25044, 26404, 27922, 292 | 29622, 31540, 33720, 36222, 39116, 42502, 46514, 51334, 293 | 57218, 64536, 73830, 85890, 101860, 123198, 151020, 183936, 294 | 216220, 243618, 268374, 293022, 319362, 347768, 378864, 412626, 449596, 295 | }; 296 | static const int32_t hd_quantize_dither_factors_LF[256] = { 297 | 0, 0, 0, 1, 0, 0, 1, 1, 298 | 0, 1, 1, 1, 1, 1, 1, 1, 299 | 1, 1, 1, 1, 1, 1, 1, 1, 300 | 1, 2, 1, 1, 2, 2, 2, 1, 301 | 2, 2, 2, 2, 2, 2, 2, 2, 302 | 2, 2, 2, 2, 2, 2, 2, 3, 303 | 2, 3, 2, 3, 3, 3, 3, 3, 304 | 3, 3, 3, 3, 3, 3, 3, 3, 305 | 3, 3, 3, 3, 3, 4, 3, 4, 306 | 4, 4, 4, 4, 4, 4, 4, 4, 307 | 4, 4, 4, 4, 5, 4, 4, 5, 308 | 4, 5, 5, 5, 5, 5, 5, 5, 309 | 5, 5, 6, 5, 5, 6, 5, 6, 310 | 6, 6, 6, 6, 6, 6, 6, 7, 311 | 6, 7, 7, 7, 7, 7, 7, 7, 312 | 7, 7, 8, 8, 8, 8, 8, 8, 313 | 8, 9, 9, 9, 9, 9, 9, 9, 314 | 10, 10, 10, 10, 10, 11, 11, 11, 315 | 11, 11, 12, 12, 12, 12, 13, 13, 316 | 13, 14, 14, 14, 15, 15, 15, 15, 317 | 16, 16, 17, 17, 17, 18, 18, 18, 318 | 19, 19, 20, 21, 21, 22, 22, 23, 319 | 23, 24, 25, 26, 26, 27, 28, 29, 320 | 30, 31, 32, 33, 34, 35, 36, 37, 321 | 39, 40, 42, 43, 45, 47, 49, 51, 322 | 53, 55, 58, 60, 63, 66, 69, 73, 323 | 76, 80, 85, 89, 95, 100, 106, 113, 324 | 119, 128, 136, 146, 156, 168, 182, 196, 325 | 213, 232, 254, 279, 307, 340, 380, 425, 326 | 480, 545, 626, 724, 847, 1003, 1205, 1471, 327 | 1830, 2324, 3015, 3993, 5335, 6956, 8229, 8071, 328 | 6850, 6189, 6162, 6585, 7102, 7774, 8441, 9243, 329 | }; 330 | static const int16_t hd_quantize_factor_select_offset_LF[257] = { 331 | 0, -22, -21, -21, -20, -20, -19, -19, 332 | -18, -18, -17, -17, -16, -16, -15, -14, 333 | -14, -13, -13, -12, -12, -11, -11, -10, 334 | -10, -9, -9, -8, -7, -7, -6, -6, 335 | -5, -5, -4, -4, -3, -3, -2, -1, 336 | -1, 0, 0, 1, 1, 2, 2, 3, 337 | 4, 4, 5, 5, 6, 6, 7, 8, 338 | 8, 9, 9, 10, 11, 11, 12, 12, 339 | 13, 14, 14, 15, 15, 16, 17, 17, 340 | 18, 19, 19, 20, 20, 21, 22, 22, 341 | 23, 24, 24, 25, 26, 26, 27, 28, 342 | 28, 29, 30, 30, 31, 32, 33, 33, 343 | 34, 35, 35, 36, 37, 38, 38, 39, 344 | 40, 41, 41, 42, 43, 44, 44, 45, 345 | 46, 47, 48, 48, 49, 50, 51, 52, 346 | 52, 53, 54, 55, 56, 57, 58, 58, 347 | 59, 60, 61, 62, 63, 64, 65, 66, 348 | 67, 68, 69, 69, 70, 71, 72, 73, 349 | 74, 75, 77, 78, 79, 80, 81, 82, 350 | 83, 84, 85, 86, 87, 89, 90, 91, 351 | 92, 93, 94, 96, 97, 98, 99, 101, 352 | 102, 103, 105, 106, 107, 109, 110, 112, 353 | 113, 115, 116, 118, 119, 121, 122, 124, 354 | 125, 127, 129, 130, 132, 134, 136, 137, 355 | 139, 141, 143, 145, 147, 149, 151, 153, 356 | 155, 158, 160, 162, 164, 167, 169, 172, 357 | 174, 177, 180, 182, 185, 188, 191, 194, 358 | 197, 201, 204, 208, 211, 215, 219, 223, 359 | 227, 232, 236, 241, 246, 251, 257, 263, 360 | 269, 275, 283, 290, 298, 307, 317, 327, 361 | 339, 352, 367, 384, 404, 429, 458, 494, 362 | 522, 522, 522, 522, 522, 522, 522, 522, 522, 363 | }; 364 | 365 | 366 | static const int32_t hd_quantize_intervals_MLF[33] = { 367 | -21236, 21236, 63830, 106798, 150386, 194832, 240376, 287258, 368 | 335726, 386034, 438460, 493308, 550924, 611696, 676082, 744626, 369 | 817986, 896968, 982580, 1076118, 1179278, 1294344, 1424504, 1574386, 370 | 1751090, 1966260, 2240868, 2617662, 3196432, 4176450, 5658260, 7671068, 371 | 10380372, 372 | }; 373 | static const int32_t hd_invert_quantize_dither_factors_MLF[33] = { 374 | 21236, 21236, 21360, 21608, 21978, 22468, 23076, 23806, 375 | 24660, 25648, 26778, 28070, 29544, 31228, 33158, 35386, 376 | 37974, 41008, 44606, 48934, 54226, 60840, 69320, 80564, 377 | 96140, 119032, 155576, 221218, 357552, 622468, 859344, 1153464, 1555840, 378 | }; 379 | static const int32_t hd_quantize_dither_factors_MLF[32] = { 380 | 0, 31, 62, 93, 123, 152, 183, 214, 381 | 247, 283, 323, 369, 421, 483, 557, 647, 382 | 759, 900, 1082, 1323, 1654, 2120, 2811, 3894, 383 | 5723, 9136, 16411, 34084, 66229, 59219, 73530, 100594, 384 | }; 385 | static const int16_t hd_quantize_factor_select_offset_MLF[33] = { 386 | 0, -21, -16, -12, -7, -2, 3, 8, 387 | 13, 19, 24, 30, 36, 43, 50, 57, 388 | 65, 74, 83, 93, 104, 117, 131, 147, 389 | 166, 189, 219, 259, 322, 427, 521, 521, 521, 390 | }; 391 | 392 | 393 | static const int32_t hd_quantize_intervals_MHF[9] = { 394 | -95044, 95044, 295844, 528780, 821332, 1226438, 1890540, 3344850, 6450664, 395 | }; 396 | static const int32_t hd_invert_quantize_dither_factors_MHF[9] = { 397 | 95044, 95044, 105754, 127180, 165372, 39736, 424366, 1029946, 2075866, 398 | }; 399 | static const int32_t hd_quantize_dither_factors_MHF[8] = { 400 | 0, 2678, 5357, 9548, -31409, 96158, 151395, 261480, 401 | }; 402 | static const int16_t hd_quantize_factor_select_offset_MHF[9] = { 403 | 0, -17, 5, 30, 62, 105, 177, 334, 518, 404 | }; 405 | 406 | 407 | static const int32_t hd_quantize_intervals_HF[17] = { 408 | -45754, 45754, 138496, 234896, 337336, 448310, 570738, 708380, 409 | 866534, 1053262, 1281958, 1577438, 1993050, 2665984, 3900982, 5902844, 410 | 8897462, 411 | }; 412 | static const int32_t hd_invert_quantize_dither_factors_HF[17] = { 413 | 45754, 45754, 46988, 49412, 53026, 57950, 64478, 73164, 414 | 84988, 101740, 126958, 168522, 247092, 425842, 809154, 1192708, 1801910, 415 | }; 416 | static const int32_t hd_quantize_dither_factors_HF[16] = { 417 | 0, 309, 606, 904, 1231, 1632, 2172, 2956, 418 | 4188, 6305, 10391, 19643, 44688, 95828, 95889, 152301, 419 | }; 420 | static const int16_t hd_quantize_factor_select_offset_HF[17] = { 421 | 0, -18, -8, 2, 13, 25, 38, 53, 422 | 70, 90, 115, 147, 192, 264, 398, 521, 521, 423 | }; 424 | 425 | struct aptx_tables { 426 | const int32_t *quantize_intervals; 427 | const int32_t *invert_quantize_dither_factors; 428 | const int32_t *quantize_dither_factors; 429 | const int16_t *quantize_factor_select_offset; 430 | int tables_size; 431 | int32_t factor_max; 432 | int prediction_order; 433 | }; 434 | 435 | static const struct aptx_tables all_tables[2][NB_SUBBANDS] = { 436 | { 437 | { 438 | /* Low Frequency (0-5.5 kHz) */ 439 | quantize_intervals_LF, 440 | invert_quantize_dither_factors_LF, 441 | quantize_dither_factors_LF, 442 | quantize_factor_select_offset_LF, 443 | ARRAY_SIZE(quantize_intervals_LF), 444 | 0x11FF, 445 | 24 446 | }, 447 | { 448 | /* Medium-Low Frequency (5.5-11kHz) */ 449 | quantize_intervals_MLF, 450 | invert_quantize_dither_factors_MLF, 451 | quantize_dither_factors_MLF, 452 | quantize_factor_select_offset_MLF, 453 | ARRAY_SIZE(quantize_intervals_MLF), 454 | 0x14FF, 455 | 12 456 | }, 457 | { 458 | /* Medium-High Frequency (11-16.5kHz) */ 459 | quantize_intervals_MHF, 460 | invert_quantize_dither_factors_MHF, 461 | quantize_dither_factors_MHF, 462 | quantize_factor_select_offset_MHF, 463 | ARRAY_SIZE(quantize_intervals_MHF), 464 | 0x16FF, 465 | 6 466 | }, 467 | { 468 | /* High Frequency (16.5-22kHz) */ 469 | quantize_intervals_HF, 470 | invert_quantize_dither_factors_HF, 471 | quantize_dither_factors_HF, 472 | quantize_factor_select_offset_HF, 473 | ARRAY_SIZE(quantize_intervals_HF), 474 | 0x15FF, 475 | 12 476 | }, 477 | }, 478 | { 479 | { 480 | /* Low Frequency (0-5.5 kHz) */ 481 | hd_quantize_intervals_LF, 482 | hd_invert_quantize_dither_factors_LF, 483 | hd_quantize_dither_factors_LF, 484 | hd_quantize_factor_select_offset_LF, 485 | ARRAY_SIZE(hd_quantize_intervals_LF), 486 | 0x11FF, 487 | 24 488 | }, 489 | { 490 | /* Medium-Low Frequency (5.5-11kHz) */ 491 | hd_quantize_intervals_MLF, 492 | hd_invert_quantize_dither_factors_MLF, 493 | hd_quantize_dither_factors_MLF, 494 | hd_quantize_factor_select_offset_MLF, 495 | ARRAY_SIZE(hd_quantize_intervals_MLF), 496 | 0x14FF, 497 | 12 498 | }, 499 | { 500 | /* Medium-High Frequency (11-16.5kHz) */ 501 | hd_quantize_intervals_MHF, 502 | hd_invert_quantize_dither_factors_MHF, 503 | hd_quantize_dither_factors_MHF, 504 | hd_quantize_factor_select_offset_MHF, 505 | ARRAY_SIZE(hd_quantize_intervals_MHF), 506 | 0x16FF, 507 | 6 508 | }, 509 | { 510 | /* High Frequency (16.5-22kHz) */ 511 | hd_quantize_intervals_HF, 512 | hd_invert_quantize_dither_factors_HF, 513 | hd_quantize_dither_factors_HF, 514 | hd_quantize_factor_select_offset_HF, 515 | ARRAY_SIZE(hd_quantize_intervals_HF), 516 | 0x15FF, 517 | 12 518 | }, 519 | } 520 | }; 521 | 522 | static const int16_t quantization_factors[32] = { 523 | 2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383, 524 | 2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834, 525 | 2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371, 526 | 3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008, 527 | }; 528 | 529 | 530 | /* Rounded right shift with optional clipping */ 531 | #define RSHIFT_SIZE(size) \ 532 | static inline int##size##_t rshift##size(int##size##_t value, unsigned shift) \ 533 | { \ 534 | const int##size##_t rounding = (int##size##_t)1 << (shift - 1); \ 535 | const int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \ 536 | return ((value + rounding) >> shift) - ((value & mask) == rounding); \ 537 | } \ 538 | static inline int32_t rshift##size##_clip24(int##size##_t value, unsigned shift) \ 539 | { \ 540 | return clip_intp2((int32_t)rshift##size(value, shift), 23); \ 541 | } 542 | RSHIFT_SIZE(32) 543 | RSHIFT_SIZE(64) 544 | 545 | 546 | static inline void aptx_update_codeword_history(struct aptx_channel *channel) 547 | { 548 | const int32_t cw = ((channel->quantize[0].quantized_sample & 3) << 0) + 549 | ((channel->quantize[1].quantized_sample & 2) << 1) + 550 | ((channel->quantize[2].quantized_sample & 1) << 3); 551 | channel->codeword_history = (cw << 8) + (int32_t)((uint32_t)channel->codeword_history << 4); 552 | } 553 | 554 | static void aptx_generate_dither(struct aptx_channel *channel) 555 | { 556 | unsigned subband; 557 | int64_t m; 558 | int32_t d; 559 | 560 | aptx_update_codeword_history(channel); 561 | 562 | m = (int64_t)5184443 * (channel->codeword_history >> 7); 563 | d = (int32_t)((m * 4) + (m >> 22)); 564 | for (subband = 0; subband < NB_SUBBANDS; subband++) 565 | channel->dither[subband] = (int32_t)((uint32_t)d << (23 - 5*subband)); 566 | channel->dither_parity = (d >> 25) & 1; 567 | } 568 | 569 | /* 570 | * Convolution filter coefficients for the outer QMF of the QMF tree. 571 | * The 2 sets are a mirror of each other. 572 | */ 573 | static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = { 574 | { 575 | 730, -413, -9611, 43626, -121026, 269973, -585547, 2801966, 576 | 697128, -160481, 27611, 8478, -10043, 3511, 688, -897, 577 | }, 578 | { 579 | -897, 688, 3511, -10043, 8478, 27611, -160481, 697128, 580 | 2801966, -585547, 269973, -121026, 43626, -9611, -413, 730, 581 | }, 582 | }; 583 | 584 | /* 585 | * Convolution filter coefficients for the inner QMF of the QMF tree. 586 | * The 2 sets are a mirror of each other. 587 | */ 588 | static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = { 589 | { 590 | 1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579, 591 | 985888, -226954, 39048, 11990, -14203, 4966, 973, -1268, 592 | }, 593 | { 594 | -1268, 973, 4966, -14203, 11990, 39048, -226954, 985888, 595 | 3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033, 596 | }, 597 | }; 598 | 599 | /* 600 | * Push one sample into a circular signal buffer. 601 | */ 602 | static inline void aptx_qmf_filter_signal_push(struct aptx_filter_signal *signal, 603 | int32_t sample) 604 | { 605 | signal->buffer[signal->pos ] = sample; 606 | signal->buffer[signal->pos+FILTER_TAPS] = sample; 607 | signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1); 608 | } 609 | 610 | /* 611 | * Compute the convolution of the signal with the coefficients, and reduce 612 | * to 24 bits by applying the specified right shifting. 613 | */ 614 | static inline int32_t aptx_qmf_convolution(const struct aptx_filter_signal *signal, 615 | const int32_t coeffs[FILTER_TAPS], 616 | unsigned shift) 617 | { 618 | const int32_t *sig = &signal->buffer[signal->pos]; 619 | int64_t e = 0; 620 | unsigned i; 621 | 622 | for (i = 0; i < FILTER_TAPS; i++) 623 | e += (int64_t)sig[i] * (int64_t)coeffs[i]; 624 | 625 | return rshift64_clip24(e, shift); 626 | } 627 | 628 | /* 629 | * Half-band QMF analysis filter realized with a polyphase FIR filter. 630 | * Split into 2 subbands and downsample by 2. 631 | * So for each pair of samples that goes in, one sample goes out, 632 | * split into 2 separate subbands. 633 | */ 634 | static inline void aptx_qmf_polyphase_analysis(struct aptx_filter_signal signal[NB_FILTERS], 635 | const int32_t coeffs[NB_FILTERS][FILTER_TAPS], 636 | unsigned shift, 637 | const int32_t samples[NB_FILTERS], 638 | int32_t *low_subband_output, 639 | int32_t *high_subband_output) 640 | { 641 | int32_t subbands[NB_FILTERS]; 642 | unsigned i; 643 | 644 | for (i = 0; i < NB_FILTERS; i++) { 645 | aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]); 646 | subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); 647 | } 648 | 649 | *low_subband_output = clip_intp2(subbands[0] + subbands[1], 23); 650 | *high_subband_output = clip_intp2(subbands[0] - subbands[1], 23); 651 | } 652 | 653 | /* 654 | * Two stage QMF analysis tree. 655 | * Split 4 input samples into 4 subbands and downsample by 4. 656 | * So for each group of 4 samples that goes in, one sample goes out, 657 | * split into 4 separate subbands. 658 | */ 659 | static void aptx_qmf_tree_analysis(struct aptx_QMF_analysis *qmf, 660 | const int32_t samples[4], 661 | int32_t subband_samples[NB_SUBBANDS]) 662 | { 663 | int32_t intermediate_samples[4]; 664 | unsigned i; 665 | 666 | /* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */ 667 | for (i = 0; i < 2; i++) 668 | aptx_qmf_polyphase_analysis(qmf->outer_filter_signal, 669 | aptx_qmf_outer_coeffs, 23, 670 | &samples[2*i], 671 | &intermediate_samples[0+i], 672 | &intermediate_samples[2+i]); 673 | 674 | /* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */ 675 | for (i = 0; i < 2; i++) 676 | aptx_qmf_polyphase_analysis(qmf->inner_filter_signal[i], 677 | aptx_qmf_inner_coeffs, 23, 678 | &intermediate_samples[2*i], 679 | &subband_samples[2*i+0], 680 | &subband_samples[2*i+1]); 681 | } 682 | 683 | /* 684 | * Half-band QMF synthesis filter realized with a polyphase FIR filter. 685 | * Join 2 subbands and upsample by 2. 686 | * So for each 2 subbands sample that goes in, a pair of samples goes out. 687 | */ 688 | static inline void aptx_qmf_polyphase_synthesis(struct aptx_filter_signal signal[NB_FILTERS], 689 | const int32_t coeffs[NB_FILTERS][FILTER_TAPS], 690 | unsigned shift, 691 | int32_t low_subband_input, 692 | int32_t high_subband_input, 693 | int32_t samples[NB_FILTERS]) 694 | { 695 | int32_t subbands[NB_FILTERS]; 696 | unsigned i; 697 | 698 | subbands[0] = low_subband_input + high_subband_input; 699 | subbands[1] = low_subband_input - high_subband_input; 700 | 701 | for (i = 0; i < NB_FILTERS; i++) { 702 | aptx_qmf_filter_signal_push(&signal[i], subbands[1-i]); 703 | samples[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift); 704 | } 705 | } 706 | 707 | /* 708 | * Two stage QMF synthesis tree. 709 | * Join 4 subbands and upsample by 4. 710 | * So for each 4 subbands sample that goes in, a group of 4 samples goes out. 711 | */ 712 | static void aptx_qmf_tree_synthesis(struct aptx_QMF_analysis *qmf, 713 | const int32_t subband_samples[NB_SUBBANDS], 714 | int32_t samples[4]) 715 | { 716 | int32_t intermediate_samples[4]; 717 | unsigned i; 718 | 719 | /* Join 4 subbands into 2 intermediate subbands upsampled to 2 samples. */ 720 | for (i = 0; i < 2; i++) 721 | aptx_qmf_polyphase_synthesis(qmf->inner_filter_signal[i], 722 | aptx_qmf_inner_coeffs, 22, 723 | subband_samples[2*i+0], 724 | subband_samples[2*i+1], 725 | &intermediate_samples[2*i]); 726 | 727 | /* Join 2 samples from intermediate subbands upsampled to 4 samples. */ 728 | for (i = 0; i < 2; i++) 729 | aptx_qmf_polyphase_synthesis(qmf->outer_filter_signal, 730 | aptx_qmf_outer_coeffs, 21, 731 | intermediate_samples[0+i], 732 | intermediate_samples[2+i], 733 | &samples[2*i]); 734 | } 735 | 736 | 737 | static inline int32_t aptx_bin_search(int32_t value, int32_t factor, 738 | const int32_t *intervals, int nb_intervals) 739 | { 740 | int32_t idx = 0; 741 | int i; 742 | 743 | for (i = nb_intervals >> 1; i > 0; i >>= 1) 744 | if ((int64_t)factor * (int64_t)intervals[idx + i] <= ((int64_t)value << 24)) 745 | idx += i; 746 | 747 | return idx; 748 | } 749 | 750 | static void aptx_quantize_difference(struct aptx_quantize *quantize, 751 | int32_t sample_difference, 752 | int32_t dither, 753 | int32_t quantization_factor, 754 | const struct aptx_tables *tables) 755 | { 756 | const int32_t *intervals = tables->quantize_intervals; 757 | int32_t quantized_sample, dithered_sample, parity_change; 758 | int32_t d, mean, interval, inv, sample_difference_abs; 759 | int64_t error; 760 | 761 | sample_difference_abs = sample_difference; 762 | if (sample_difference_abs < 0) 763 | sample_difference_abs = -sample_difference_abs; 764 | if (sample_difference_abs > ((int32_t)1 << 23) - 1) 765 | sample_difference_abs = ((int32_t)1 << 23) - 1; 766 | 767 | quantized_sample = aptx_bin_search(sample_difference_abs >> 4, 768 | quantization_factor, 769 | intervals, tables->tables_size); 770 | 771 | d = rshift32_clip24((int32_t)(((int64_t)dither * (int64_t)dither) >> 32), 7) - ((int32_t)1 << 23); 772 | d = (int32_t)rshift64((int64_t)d * (int64_t)tables->quantize_dither_factors[quantized_sample], 23); 773 | 774 | intervals += quantized_sample; 775 | mean = (intervals[1] + intervals[0]) / 2; 776 | interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1); 777 | 778 | dithered_sample = rshift64_clip24((int64_t)dither * (int64_t)interval + ((int64_t)clip_intp2(mean + d, 23) << 32), 32); 779 | error = ((int64_t)sample_difference_abs << 20) - (int64_t)dithered_sample * (int64_t)quantization_factor; 780 | quantize->error = (int32_t)rshift64(error, 23); 781 | if (quantize->error < 0) 782 | quantize->error = -quantize->error; 783 | 784 | parity_change = quantized_sample; 785 | if (error < 0) 786 | quantized_sample--; 787 | else 788 | parity_change--; 789 | 790 | inv = -(sample_difference < 0); 791 | quantize->quantized_sample = quantized_sample ^ inv; 792 | quantize->quantized_sample_parity_change = parity_change ^ inv; 793 | } 794 | 795 | static void aptx_encode_channel(struct aptx_channel *channel, const int32_t samples[4], int hd) 796 | { 797 | int32_t subband_samples[NB_SUBBANDS]; 798 | int32_t diff; 799 | unsigned subband; 800 | 801 | aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples); 802 | aptx_generate_dither(channel); 803 | 804 | for (subband = 0; subband < NB_SUBBANDS; subband++) { 805 | diff = clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23); 806 | aptx_quantize_difference(&channel->quantize[subband], diff, 807 | channel->dither[subband], 808 | channel->invert_quantize[subband].quantization_factor, 809 | &all_tables[hd][subband]); 810 | } 811 | } 812 | 813 | static void aptx_decode_channel(struct aptx_channel *channel, int32_t samples[4]) 814 | { 815 | int32_t subband_samples[NB_SUBBANDS]; 816 | unsigned subband; 817 | 818 | for (subband = 0; subband < NB_SUBBANDS; subband++) 819 | subband_samples[subband] = channel->prediction[subband].previous_reconstructed_sample; 820 | aptx_qmf_tree_synthesis(&channel->qmf, subband_samples, samples); 821 | } 822 | 823 | 824 | static void aptx_invert_quantization(struct aptx_invert_quantize *invert_quantize, 825 | int32_t quantized_sample, int32_t dither, 826 | const struct aptx_tables *tables) 827 | { 828 | int32_t qr, idx, shift, factor_select; 829 | 830 | idx = (quantized_sample ^ -(quantized_sample < 0)) + 1; 831 | qr = tables->quantize_intervals[idx] / 2; 832 | if (quantized_sample < 0) 833 | qr = -qr; 834 | 835 | qr = rshift64_clip24(((int64_t)qr * ((int64_t)1<<32)) + (int64_t)dither * (int64_t)tables->invert_quantize_dither_factors[idx], 32); 836 | invert_quantize->reconstructed_difference = (int32_t)(((int64_t)invert_quantize->quantization_factor * (int64_t)qr) >> 19); 837 | 838 | /* update factor_select */ 839 | factor_select = 32620 * invert_quantize->factor_select; 840 | factor_select = rshift32(factor_select + (tables->quantize_factor_select_offset[idx] * (1 << 15)), 15); 841 | invert_quantize->factor_select = clip(factor_select, 0, tables->factor_max); 842 | 843 | /* update quantization factor */ 844 | idx = (invert_quantize->factor_select & 0xFF) >> 3; 845 | shift = (tables->factor_max - invert_quantize->factor_select) >> 8; 846 | invert_quantize->quantization_factor = (quantization_factors[idx] << 11) >> shift; 847 | } 848 | 849 | static int32_t *aptx_reconstructed_differences_update(struct aptx_prediction *prediction, 850 | int32_t reconstructed_difference, 851 | int order) 852 | { 853 | int32_t *rd1 = prediction->reconstructed_differences, *rd2 = rd1 + order; 854 | int p = prediction->pos; 855 | 856 | rd1[p] = rd2[p]; 857 | prediction->pos = p = (p + 1) % order; 858 | rd2[p] = reconstructed_difference; 859 | return &rd2[p]; 860 | } 861 | 862 | static void aptx_prediction_filtering(struct aptx_prediction *prediction, 863 | int32_t reconstructed_difference, 864 | int order) 865 | { 866 | int32_t reconstructed_sample, predictor, srd0, srd; 867 | int32_t *reconstructed_differences; 868 | int64_t predicted_difference = 0; 869 | int i; 870 | 871 | reconstructed_sample = clip_intp2(reconstructed_difference + prediction->predicted_sample, 23); 872 | predictor = clip_intp2((int32_t)(((int64_t)prediction->s_weight[0] * (int64_t)prediction->previous_reconstructed_sample 873 | + (int64_t)prediction->s_weight[1] * (int64_t)reconstructed_sample) >> 22), 23); 874 | prediction->previous_reconstructed_sample = reconstructed_sample; 875 | 876 | reconstructed_differences = aptx_reconstructed_differences_update(prediction, reconstructed_difference, order); 877 | srd0 = (int32_t)DIFFSIGN(reconstructed_difference, 0) * ((int32_t)1 << 23); 878 | for (i = 0; i < order; i++) { 879 | srd = (reconstructed_differences[-i-1] >> 31) | 1; 880 | prediction->d_weight[i] -= rshift32(prediction->d_weight[i] - srd*srd0, 8); 881 | predicted_difference += (int64_t)reconstructed_differences[-i] * (int64_t)prediction->d_weight[i]; 882 | } 883 | 884 | prediction->predicted_difference = clip_intp2((int32_t)(predicted_difference >> 22), 23); 885 | prediction->predicted_sample = clip_intp2(predictor + prediction->predicted_difference, 23); 886 | } 887 | 888 | static void aptx_process_subband(struct aptx_invert_quantize *invert_quantize, 889 | struct aptx_prediction *prediction, 890 | int32_t quantized_sample, int32_t dither, 891 | const struct aptx_tables *tables) 892 | { 893 | int32_t sign, same_sign[2], weight[2], sw1, range; 894 | 895 | aptx_invert_quantization(invert_quantize, quantized_sample, dither, tables); 896 | 897 | sign = DIFFSIGN(invert_quantize->reconstructed_difference, 898 | -prediction->predicted_difference); 899 | same_sign[0] = sign * prediction->prev_sign[0]; 900 | same_sign[1] = sign * prediction->prev_sign[1]; 901 | prediction->prev_sign[0] = prediction->prev_sign[1]; 902 | prediction->prev_sign[1] = sign | 1; 903 | 904 | range = 0x100000; 905 | sw1 = rshift32(-same_sign[1] * prediction->s_weight[1], 1); 906 | sw1 = (clip(sw1, -range, range) & ~0xF) * 16; 907 | 908 | range = 0x300000; 909 | weight[0] = 254 * prediction->s_weight[0] + 0x800000*same_sign[0] + sw1; 910 | prediction->s_weight[0] = clip(rshift32(weight[0], 8), -range, range); 911 | 912 | range = 0x3C0000 - prediction->s_weight[0]; 913 | weight[1] = 255 * prediction->s_weight[1] + 0xC00000*same_sign[1]; 914 | prediction->s_weight[1] = clip(rshift32(weight[1], 8), -range, range); 915 | 916 | aptx_prediction_filtering(prediction, 917 | invert_quantize->reconstructed_difference, 918 | tables->prediction_order); 919 | } 920 | 921 | static void aptx_invert_quantize_and_prediction(struct aptx_channel *channel, int hd) 922 | { 923 | unsigned subband; 924 | for (subband = 0; subband < NB_SUBBANDS; subband++) 925 | aptx_process_subband(&channel->invert_quantize[subband], 926 | &channel->prediction[subband], 927 | channel->quantize[subband].quantized_sample, 928 | channel->dither[subband], 929 | &all_tables[hd][subband]); 930 | } 931 | 932 | static int32_t aptx_quantized_parity(const struct aptx_channel *channel) 933 | { 934 | int32_t parity = channel->dither_parity; 935 | unsigned subband; 936 | 937 | for (subband = 0; subband < NB_SUBBANDS; subband++) 938 | parity ^= channel->quantize[subband].quantized_sample; 939 | 940 | return parity & 1; 941 | } 942 | 943 | /* 944 | * For each sample, ensure that the parity of all subbands of all channels 945 | * is 0 except once every 8 samples where the parity is forced to 1. 946 | */ 947 | static int aptx_check_parity(const struct aptx_channel channels[NB_CHANNELS], uint8_t *sync_idx) 948 | { 949 | const int32_t parity = aptx_quantized_parity(&channels[LEFT]) 950 | ^ aptx_quantized_parity(&channels[RIGHT]); 951 | const int32_t eighth = *sync_idx == 7; 952 | 953 | *sync_idx = (*sync_idx + 1) & 7; 954 | return parity ^ eighth; 955 | } 956 | 957 | static void aptx_insert_sync(struct aptx_channel channels[NB_CHANNELS], uint8_t *sync_idx) 958 | { 959 | unsigned i; 960 | struct aptx_channel *c; 961 | static const unsigned map[] = { 1, 2, 0, 3 }; 962 | struct aptx_quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]]; 963 | 964 | if (aptx_check_parity(channels, sync_idx)) { 965 | for (c = &channels[NB_CHANNELS-1]; c >= channels; c--) 966 | for (i = 0; i < NB_SUBBANDS; i++) 967 | if (c->quantize[map[i]].error < min->error) 968 | min = &c->quantize[map[i]]; 969 | 970 | /* 971 | * Forcing the desired parity is done by offsetting by 1 the quantized 972 | * sample from the subband featuring the smallest quantization error. 973 | */ 974 | min->quantized_sample = min->quantized_sample_parity_change; 975 | } 976 | } 977 | 978 | static uint16_t aptx_pack_codeword(const struct aptx_channel *channel) 979 | { 980 | const int32_t parity = aptx_quantized_parity(channel); 981 | return (uint16_t)((((channel->quantize[3].quantized_sample & 0x06) | parity) << 13) 982 | | (((channel->quantize[2].quantized_sample & 0x03) ) << 11) 983 | | (((channel->quantize[1].quantized_sample & 0x0F) ) << 7) 984 | | (((channel->quantize[0].quantized_sample & 0x7F) ) << 0)); 985 | } 986 | 987 | static uint32_t aptxhd_pack_codeword(const struct aptx_channel *channel) 988 | { 989 | const int32_t parity = aptx_quantized_parity(channel); 990 | return (uint32_t)((((channel->quantize[3].quantized_sample & 0x01E) | parity) << 19) 991 | | (((channel->quantize[2].quantized_sample & 0x00F) ) << 15) 992 | | (((channel->quantize[1].quantized_sample & 0x03F) ) << 9) 993 | | (((channel->quantize[0].quantized_sample & 0x1FF) ) << 0)); 994 | } 995 | 996 | static void aptx_unpack_codeword(struct aptx_channel *channel, uint16_t codeword) 997 | { 998 | channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7); 999 | channel->quantize[1].quantized_sample = sign_extend(codeword >> 7, 4); 1000 | channel->quantize[2].quantized_sample = sign_extend(codeword >> 11, 2); 1001 | channel->quantize[3].quantized_sample = sign_extend(codeword >> 13, 3); 1002 | channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) 1003 | | aptx_quantized_parity(channel); 1004 | } 1005 | 1006 | static void aptxhd_unpack_codeword(struct aptx_channel *channel, uint32_t codeword) 1007 | { 1008 | channel->quantize[0].quantized_sample = sign_extend((int32_t)(codeword >> 0), 9); 1009 | channel->quantize[1].quantized_sample = sign_extend((int32_t)(codeword >> 9), 6); 1010 | channel->quantize[2].quantized_sample = sign_extend((int32_t)(codeword >> 15), 4); 1011 | channel->quantize[3].quantized_sample = sign_extend((int32_t)(codeword >> 19), 5); 1012 | channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1) 1013 | | aptx_quantized_parity(channel); 1014 | } 1015 | 1016 | static void aptx_encode_samples(struct aptx_context *ctx, 1017 | int32_t samples[NB_CHANNELS][4], 1018 | uint8_t *output) 1019 | { 1020 | unsigned channel; 1021 | for (channel = 0; channel < NB_CHANNELS; channel++) 1022 | aptx_encode_channel(&ctx->channels[channel], samples[channel], ctx->hd); 1023 | 1024 | aptx_insert_sync(ctx->channels, &ctx->sync_idx); 1025 | 1026 | for (channel = 0; channel < NB_CHANNELS; channel++) { 1027 | aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); 1028 | if (ctx->hd) { 1029 | uint32_t codeword = aptxhd_pack_codeword(&ctx->channels[channel]); 1030 | output[3*channel+0] = (uint8_t)((codeword >> 16) & 0xFF); 1031 | output[3*channel+1] = (uint8_t)((codeword >> 8) & 0xFF); 1032 | output[3*channel+2] = (uint8_t)((codeword >> 0) & 0xFF); 1033 | } else { 1034 | uint16_t codeword = aptx_pack_codeword(&ctx->channels[channel]); 1035 | output[2*channel+0] = (uint8_t)((codeword >> 8) & 0xFF); 1036 | output[2*channel+1] = (uint8_t)((codeword >> 0) & 0xFF); 1037 | } 1038 | } 1039 | } 1040 | 1041 | static int aptx_decode_samples(struct aptx_context *ctx, 1042 | const uint8_t *input, 1043 | int32_t samples[NB_CHANNELS][4]) 1044 | { 1045 | unsigned channel; 1046 | int ret; 1047 | 1048 | for (channel = 0; channel < NB_CHANNELS; channel++) { 1049 | aptx_generate_dither(&ctx->channels[channel]); 1050 | 1051 | if (ctx->hd) 1052 | aptxhd_unpack_codeword(&ctx->channels[channel], 1053 | ((uint32_t)input[3*channel+0] << 16) | 1054 | ((uint32_t)input[3*channel+1] << 8) | 1055 | ((uint32_t)input[3*channel+2] << 0)); 1056 | else 1057 | aptx_unpack_codeword(&ctx->channels[channel], (uint16_t)( 1058 | ((uint16_t)input[2*channel+0] << 8) | 1059 | ((uint16_t)input[2*channel+1] << 0))); 1060 | aptx_invert_quantize_and_prediction(&ctx->channels[channel], ctx->hd); 1061 | } 1062 | 1063 | ret = aptx_check_parity(ctx->channels, &ctx->sync_idx); 1064 | 1065 | for (channel = 0; channel < NB_CHANNELS; channel++) 1066 | aptx_decode_channel(&ctx->channels[channel], samples[channel]); 1067 | 1068 | return ret; 1069 | } 1070 | 1071 | static void aptx_reset_decode_sync(struct aptx_context *ctx) 1072 | { 1073 | const size_t decode_dropped = ctx->decode_dropped; 1074 | const size_t decode_sync_packets = ctx->decode_sync_packets; 1075 | const uint8_t decode_sync_buffer_len = ctx->decode_sync_buffer_len; 1076 | unsigned char decode_sync_buffer[6]; 1077 | unsigned i; 1078 | 1079 | for (i = 0; i < 6; i++) 1080 | decode_sync_buffer[i] = ctx->decode_sync_buffer[i]; 1081 | 1082 | aptx_reset(ctx); 1083 | 1084 | for (i = 0; i < 6; i++) 1085 | ctx->decode_sync_buffer[i] = decode_sync_buffer[i]; 1086 | 1087 | ctx->decode_sync_buffer_len = decode_sync_buffer_len; 1088 | ctx->decode_sync_packets = decode_sync_packets; 1089 | ctx->decode_dropped = decode_dropped; 1090 | } 1091 | 1092 | 1093 | const int aptx_major = FREEAPTX_MAJOR; 1094 | const int aptx_minor = FREEAPTX_MINOR; 1095 | const int aptx_patch = FREEAPTX_PATCH; 1096 | 1097 | struct aptx_context *aptx_init(int hd) 1098 | { 1099 | struct aptx_context *ctx; 1100 | 1101 | ctx = (struct aptx_context *)malloc(sizeof(*ctx)); 1102 | if (!ctx) 1103 | return NULL; 1104 | 1105 | ctx->hd = hd ? 1 : 0; 1106 | 1107 | aptx_reset(ctx); 1108 | return ctx; 1109 | } 1110 | 1111 | void aptx_reset(struct aptx_context *ctx) 1112 | { 1113 | const uint8_t hd = ctx->hd; 1114 | unsigned i, chan, subband; 1115 | struct aptx_channel *channel; 1116 | struct aptx_prediction *prediction; 1117 | 1118 | for (i = 0; i < sizeof(*ctx); i++) 1119 | ((unsigned char *)ctx)[i] = 0; 1120 | 1121 | ctx->hd = hd; 1122 | ctx->decode_skip_leading = (LATENCY_SAMPLES+3)/4; 1123 | ctx->encode_remaining = (LATENCY_SAMPLES+3)/4; 1124 | 1125 | for (chan = 0; chan < NB_CHANNELS; chan++) { 1126 | channel = &ctx->channels[chan]; 1127 | for (subband = 0; subband < NB_SUBBANDS; subband++) { 1128 | prediction = &channel->prediction[subband]; 1129 | prediction->prev_sign[0] = 1; 1130 | prediction->prev_sign[1] = 1; 1131 | } 1132 | } 1133 | } 1134 | 1135 | void aptx_finish(struct aptx_context *ctx) 1136 | { 1137 | free(ctx); 1138 | } 1139 | 1140 | size_t aptx_encode(struct aptx_context *ctx, const unsigned char *input, size_t input_size, unsigned char *output, size_t output_size, size_t *written) 1141 | { 1142 | const size_t sample_size = ctx->hd ? 6 : 4; 1143 | int32_t samples[NB_CHANNELS][4]; 1144 | unsigned sample, channel; 1145 | size_t ipos, opos; 1146 | 1147 | for (ipos = 0, opos = 0; ipos + 3*NB_CHANNELS*4 <= input_size && opos + sample_size <= output_size; opos += sample_size) { 1148 | for (sample = 0; sample < 4; sample++) { 1149 | for (channel = 0; channel < NB_CHANNELS; channel++, ipos += 3) { 1150 | /* samples need to contain 24bit signed integer stored as 32bit signed integers */ 1151 | /* last int8_t --> uint32_t cast propagates signedness for 32bit integer */ 1152 | samples[channel][sample] = (int32_t)(((uint32_t)input[ipos+0] << 0) | 1153 | ((uint32_t)input[ipos+1] << 8) | 1154 | ((uint32_t)(int8_t)input[ipos+2] << 16)); 1155 | } 1156 | } 1157 | aptx_encode_samples(ctx, samples, output + opos); 1158 | } 1159 | 1160 | *written = opos; 1161 | return ipos; 1162 | } 1163 | 1164 | int aptx_encode_finish(struct aptx_context *ctx, unsigned char *output, size_t output_size, size_t *written) 1165 | { 1166 | const size_t sample_size = ctx->hd ? 6 : 4; 1167 | int32_t samples[NB_CHANNELS][4] = { { 0 } }; 1168 | size_t opos; 1169 | 1170 | if (ctx->encode_remaining == 0) { 1171 | *written = 0; 1172 | return 1; 1173 | } 1174 | 1175 | for (opos = 0; ctx->encode_remaining > 0 && opos + sample_size <= output_size; ctx->encode_remaining--, opos += sample_size) 1176 | aptx_encode_samples(ctx, samples, output + opos); 1177 | 1178 | *written = opos; 1179 | 1180 | if (ctx->encode_remaining > 0) 1181 | return 0; 1182 | 1183 | aptx_reset(ctx); 1184 | return 1; 1185 | } 1186 | 1187 | size_t aptx_decode(struct aptx_context *ctx, const unsigned char *input, size_t input_size, unsigned char *output, size_t output_size, size_t *written) 1188 | { 1189 | const size_t sample_size = ctx->hd ? 6 : 4; 1190 | int32_t samples[NB_CHANNELS][4]; 1191 | unsigned sample, channel; 1192 | size_t ipos, opos; 1193 | 1194 | for (ipos = 0, opos = 0; ipos + sample_size <= input_size && (opos + 3*NB_CHANNELS*4 <= output_size || ctx->decode_skip_leading > 0); ipos += sample_size) { 1195 | if (aptx_decode_samples(ctx, input + ipos, samples)) 1196 | break; 1197 | sample = 0; 1198 | if (ctx->decode_skip_leading > 0) { 1199 | ctx->decode_skip_leading--; 1200 | if (ctx->decode_skip_leading > 0) 1201 | continue; 1202 | sample = LATENCY_SAMPLES%4; 1203 | } 1204 | for (; sample < 4; sample++) { 1205 | for (channel = 0; channel < NB_CHANNELS; channel++, opos += 3) { 1206 | /* samples contain 24bit signed integers stored as 32bit signed integers */ 1207 | /* we do not need to care about negative integers specially as they have 23th bit set */ 1208 | output[opos+0] = (uint8_t)(((uint32_t)samples[channel][sample] >> 0) & 0xFF); 1209 | output[opos+1] = (uint8_t)(((uint32_t)samples[channel][sample] >> 8) & 0xFF); 1210 | output[opos+2] = (uint8_t)(((uint32_t)samples[channel][sample] >> 16) & 0xFF); 1211 | } 1212 | } 1213 | } 1214 | 1215 | *written = opos; 1216 | return ipos; 1217 | } 1218 | 1219 | size_t aptx_decode_sync(struct aptx_context *ctx, const unsigned char *input, size_t input_size, unsigned char *output, size_t output_size, size_t *written, int *synced, size_t *dropped) 1220 | { 1221 | const size_t sample_size = ctx->hd ? 6 : 4; 1222 | size_t input_size_step; 1223 | size_t processed_step; 1224 | size_t written_step; 1225 | size_t ipos = 0; 1226 | size_t opos = 0; 1227 | size_t i; 1228 | 1229 | *synced = 0; 1230 | *dropped = 0; 1231 | 1232 | /* If we have some unprocessed bytes in internal cache, first fill remaining data to internal cache except the final byte */ 1233 | if (ctx->decode_sync_buffer_len > 0 && sample_size-1 - ctx->decode_sync_buffer_len <= input_size) { 1234 | while (ctx->decode_sync_buffer_len < sample_size-1) 1235 | ctx->decode_sync_buffer[ctx->decode_sync_buffer_len++] = input[ipos++]; 1236 | } 1237 | 1238 | /* Internal cache decode loop, use it only when sample is split between internal cache and input buffer */ 1239 | while (ctx->decode_sync_buffer_len == sample_size-1 && ipos < sample_size && ipos < input_size && (opos + 3*NB_CHANNELS*4 <= output_size || ctx->decode_skip_leading > 0 || ctx->decode_dropped > 0)) { 1240 | ctx->decode_sync_buffer[sample_size-1] = input[ipos++]; 1241 | 1242 | processed_step = aptx_decode(ctx, ctx->decode_sync_buffer, sample_size, output + opos, output_size - opos, &written_step); 1243 | 1244 | opos += written_step; 1245 | 1246 | if (ctx->decode_dropped > 0 && processed_step == sample_size) { 1247 | ctx->decode_dropped += processed_step; 1248 | ctx->decode_sync_packets++; 1249 | if (ctx->decode_sync_packets >= (LATENCY_SAMPLES+3)/4) { 1250 | *dropped += ctx->decode_dropped; 1251 | ctx->decode_dropped = 0; 1252 | ctx->decode_sync_packets = 0; 1253 | } 1254 | } 1255 | 1256 | if (processed_step < sample_size) { 1257 | aptx_reset_decode_sync(ctx); 1258 | *synced = 0; 1259 | ctx->decode_dropped++; 1260 | ctx->decode_sync_packets = 0; 1261 | for (i = 0; i < sample_size-1; i++) 1262 | ctx->decode_sync_buffer[i] = ctx->decode_sync_buffer[i+1]; 1263 | } else { 1264 | if (ctx->decode_dropped == 0) 1265 | *synced = 1; 1266 | ctx->decode_sync_buffer_len = 0; 1267 | } 1268 | } 1269 | 1270 | /* If all unprocessed data are now available only in input buffer, do not use internal cache */ 1271 | if (ctx->decode_sync_buffer_len == sample_size-1 && ipos == sample_size) { 1272 | ipos = 0; 1273 | ctx->decode_sync_buffer_len = 0; 1274 | } 1275 | 1276 | /* Main decode loop, decode as much as possible samples, if decoding fails restart it on next byte */ 1277 | while (ipos + sample_size <= input_size && (opos + 3*NB_CHANNELS*4 <= output_size || ctx->decode_skip_leading > 0 || ctx->decode_dropped > 0)) { 1278 | input_size_step = (((output_size - opos) / 3*NB_CHANNELS*4) + ctx->decode_skip_leading) * sample_size; 1279 | if (input_size_step > ((input_size - ipos) / sample_size) * sample_size) 1280 | input_size_step = ((input_size - ipos) / sample_size) * sample_size; 1281 | if (input_size_step > ((LATENCY_SAMPLES+3)/4 - ctx->decode_sync_packets) * sample_size && ctx->decode_dropped > 0) 1282 | input_size_step = ((LATENCY_SAMPLES+3)/4 - ctx->decode_sync_packets) * sample_size; 1283 | 1284 | processed_step = aptx_decode(ctx, input + ipos, input_size_step, output + opos, output_size - opos, &written_step); 1285 | 1286 | ipos += processed_step; 1287 | opos += written_step; 1288 | 1289 | if (ctx->decode_dropped > 0 && processed_step / sample_size > 0) { 1290 | ctx->decode_dropped += processed_step; 1291 | ctx->decode_sync_packets += processed_step / sample_size; 1292 | if (ctx->decode_sync_packets >= (LATENCY_SAMPLES+3)/4) { 1293 | *dropped += ctx->decode_dropped; 1294 | ctx->decode_dropped = 0; 1295 | ctx->decode_sync_packets = 0; 1296 | } 1297 | } 1298 | 1299 | if (processed_step < input_size_step) { 1300 | aptx_reset_decode_sync(ctx); 1301 | *synced = 0; 1302 | ipos++; 1303 | ctx->decode_dropped++; 1304 | ctx->decode_sync_packets = 0; 1305 | } else if (ctx->decode_dropped == 0) { 1306 | *synced = 1; 1307 | } 1308 | } 1309 | 1310 | /* If number of unprocessed bytes is less then sample size store them to internal cache */ 1311 | if (ipos + sample_size > input_size) { 1312 | while (ipos < input_size) 1313 | ctx->decode_sync_buffer[ctx->decode_sync_buffer_len++] = input[ipos++]; 1314 | } 1315 | 1316 | *written = opos; 1317 | return ipos; 1318 | } 1319 | 1320 | size_t aptx_decode_sync_finish(struct aptx_context *ctx) 1321 | { 1322 | const uint8_t dropped = ctx->decode_sync_buffer_len; 1323 | aptx_reset(ctx); 1324 | return dropped; 1325 | } 1326 | -------------------------------------------------------------------------------- /freeaptx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Open Source implementation of Audio Processing Technology codec (aptX) 3 | * Copyright (C) 2018-2020 Pali Rohár 4 | * Copyright (C) 2025 Hunter Wardlaw 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef FREEAPTX_H 22 | #define FREEAPTX_H 23 | 24 | #define FREEAPTX_MAJOR 0 25 | #define FREEAPTX_MINOR 2 26 | #define FREEAPTX_PATCH 2 27 | 28 | #include 29 | 30 | extern const int aptx_major; 31 | extern const int aptx_minor; 32 | extern const int aptx_patch; 33 | 34 | struct aptx_context; 35 | 36 | /* 37 | * Initialize context for aptX codec and reset it. 38 | * hd = 0 process aptX codec 39 | * hd = 1 process aptX HD codec 40 | */ 41 | struct aptx_context *aptx_init(int hd); 42 | 43 | /* 44 | * Reset internal state, predictor and parity sync of aptX context. 45 | * It is needed when going to encode or decode a new stream. 46 | */ 47 | void aptx_reset(struct aptx_context *ctx); 48 | 49 | /* 50 | * Free aptX context initialized by aptx_init(). 51 | */ 52 | void aptx_finish(struct aptx_context *ctx); 53 | 54 | /* 55 | * Encodes sequence of 4 raw 24bit signed stereo samples from input buffer with 56 | * size input_size to aptX audio samples into output buffer with output_size. 57 | * Return value indicates processed length from input buffer and to written 58 | * pointer is stored length of encoded aptX audio samples in output buffer. 59 | * Therefore input buffer must contain sequence of the 24 bytes in format 60 | * LLLRRRLLLRRRLLLRRRLLLRRR (L-left, R-right) and output buffer would contain 61 | * encoded sequence of either four bytes (LLRR) of aptX or six bytes (LLLRRR) 62 | * of aptX HD. 63 | */ 64 | size_t aptx_encode(struct aptx_context *ctx, 65 | const unsigned char *input, 66 | size_t input_size, 67 | unsigned char *output, 68 | size_t output_size, 69 | size_t *written); 70 | 71 | /* 72 | * Finish encoding of current stream and reset internal state to be ready for 73 | * encoding or decoding a new stream. Due to aptX latency, last 90 samples 74 | * (rounded to 92) will be filled by this finish function. When output buffer is 75 | * too small, this function returns zero, fills buffer only partially, does not 76 | * reset internal state and subsequent calls continue filling output buffer. 77 | * When output buffer is large enough, then function returns non-zero value. 78 | * In both cases into written pointer is stored length of encoded samples. 79 | */ 80 | int aptx_encode_finish(struct aptx_context *ctx, 81 | unsigned char *output, 82 | size_t output_size, 83 | size_t *written); 84 | 85 | /* 86 | * Decodes aptX audio samples in input buffer with size input_size to sequence 87 | * of raw 24bit signed stereo samples into output buffer with size output_size. 88 | * Return value indicates processed length from input buffer and to written 89 | * pointer is stored length of decoded output samples in output buffer. 90 | * Input buffer must contain seqeunce of four bytes (LLRR) of aptX or six 91 | * bytes (LLLRRR) of aptX HD samples and output buffer would contain decoded 92 | * sequence of 24 bytes in format LLLRRRLLLRRRLLLRRRLLLRRR (L-left, R-right) 93 | * for one aptX sample. Due to aptX latency, output buffer starts filling 94 | * after 90 samples. When parity check fails then this function stops decoding 95 | * and returns processed length of input buffer. To detect such failure it is 96 | * needed to compare return value and input_size. Note that if you have a 97 | * finite stream then the last two decoded samples from the last decode call 98 | * does not contain any meaningful value. They are present just because aptX 99 | * samples are rounded to the multiple by four and latency is 90 samples so 100 | * last 2 samples are just padding. 101 | */ 102 | size_t aptx_decode(struct aptx_context *ctx, 103 | const unsigned char *input, 104 | size_t input_size, 105 | unsigned char *output, 106 | size_t output_size, 107 | size_t *written); 108 | 109 | /* 110 | * Auto synchronization variant of aptx_decode() function suitable for partially 111 | * corrupted continuous stream in which some bytes are missing. All arguments, 112 | * including return value have same meaning as for aptx_decode() function. The 113 | * only difference is that there is no restriction for size of input buffer, 114 | * output buffer must have space for decoding whole input buffer plus space for 115 | * one additional decoded sample (24 bytes) and the last difference is that this 116 | * function continue to decode even when parity check fails. When decoding fails 117 | * this function starts searching for next bytes from the input buffer which 118 | * have valid parity check (to be synchronized) and then starts decoding again. 119 | * Into synced pointer is stored 1 if at the end of processing is decoder fully 120 | * synchronized (in non-error state, with valid parity check) or is stored 0 if 121 | * decoder is unsynchronized (in error state, without valid parity check). Into 122 | * dropped pointer is stored number of dropped (not decoded) bytes which were 123 | * already processed. Functions aptx_decode() and aptx_decode_sync() should not 124 | * be mixed together. 125 | */ 126 | size_t aptx_decode_sync(struct aptx_context *ctx, 127 | const unsigned char *input, 128 | size_t input_size, 129 | unsigned char *output, 130 | size_t output_size, 131 | size_t *written, 132 | int *synced, 133 | size_t *dropped); 134 | 135 | /* 136 | * Finish decoding of current auto synchronization stream and reset internal 137 | * state to be ready for encoding or decoding a new stream. This function 138 | * returns number of unprocessed cached bytes which would have been processed 139 | * by next aptx_decode_sync() call, therefore in time of calling this function 140 | * it is number of dropped input bytes. 141 | */ 142 | size_t aptx_decode_sync_finish(struct aptx_context *ctx); 143 | 144 | #endif 145 | -------------------------------------------------------------------------------- /freeaptxdec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aptX decoder utility 3 | * Copyright (C) 2018-2020 Pali Rohár 4 | * Copyright (C) 2025 Hunter Wardlaw 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #ifdef _WIN32 25 | #include 26 | #include 27 | #endif 28 | 29 | #include 30 | 31 | static unsigned char input_buffer[512*6]; 32 | static unsigned char output_buffer[512*3*2*6+3*2*4]; 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | int i; 37 | int hd; 38 | int ret; 39 | size_t length; 40 | size_t processed; 41 | size_t written; 42 | size_t dropped; 43 | int synced; 44 | int syncing; 45 | struct aptx_context *ctx; 46 | 47 | #ifdef _WIN32 48 | _setmode(_fileno(stdin), _O_BINARY); 49 | _setmode(_fileno(stdout), _O_BINARY); 50 | #endif 51 | 52 | hd = 0; 53 | 54 | for (i = 1; i < argc; ++i) { 55 | if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { 56 | fprintf(stderr, "aptX decoder utility %d.%d.%d (using libfreeaptx %d.%d.%d)\n", FREEAPTX_MAJOR, FREEAPTX_MINOR, FREEAPTX_PATCH, aptx_major, aptx_minor, aptx_patch); 57 | fprintf(stderr, "\n"); 58 | fprintf(stderr, "This utility decodes aptX or aptX HD audio stream\n"); 59 | fprintf(stderr, "from stdin to a raw 24 bit signed stereo on stdout\n"); 60 | fprintf(stderr, "\n"); 61 | fprintf(stderr, "When input is damaged it tries to synchronize and recover\n"); 62 | fprintf(stderr, "\n"); 63 | fprintf(stderr, "Non-zero return value indicates that input was damaged\n"); 64 | fprintf(stderr, "and some bytes from input aptX audio stream were dropped\n"); 65 | fprintf(stderr, "\n"); 66 | fprintf(stderr, "Usage:\n"); 67 | fprintf(stderr, " %s [options]\n", argv[0]); 68 | fprintf(stderr, "\n"); 69 | fprintf(stderr, "Options:\n"); 70 | fprintf(stderr, " -h, --help Display this help\n"); 71 | fprintf(stderr, " --hd Decode from aptX HD\n"); 72 | fprintf(stderr, "\n"); 73 | fprintf(stderr, "Examples:\n"); 74 | fprintf(stderr, "\n"); 75 | fprintf(stderr, " %s < sample.aptx > sample.s24le\n", argv[0]); 76 | fprintf(stderr, "\n"); 77 | fprintf(stderr, " %s --hd < sample.aptxhd > sample.s24le\n", argv[0]); 78 | fprintf(stderr, "\n"); 79 | fprintf(stderr, " %s < sample.aptx | play -t raw -r 44.1k -L -e s -b 24 -c 2 -\n", argv[0]); 80 | return 1; 81 | } else if (strcmp(argv[i], "--hd") == 0) { 82 | hd = 1; 83 | } else { 84 | fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]); 85 | return 1; 86 | } 87 | } 88 | 89 | ctx = aptx_init(hd); 90 | if (!ctx) { 91 | fprintf(stderr, "%s: Cannot initialize aptX decoder\n", argv[0]); 92 | return 1; 93 | } 94 | 95 | /* 96 | * Try to guess type of input stream based on the first six bytes 97 | * Encoder produces fixed first sample because aptX predictor has fixed values 98 | */ 99 | length = fread(input_buffer, 1, 6, stdin); 100 | if (length >= 4 && memcmp(input_buffer, "\x4b\xbf\x4b\xbf", 4) == 0) { 101 | if (hd) 102 | fprintf(stderr, "%s: Input looks like start of aptX audio stream (not aptX HD), try without --hd\n", argv[0]); 103 | } else if (length >= 6 && memcmp(input_buffer, "\x73\xbe\xff\x73\xbe\xff", 6) == 0) { 104 | if (!hd) 105 | fprintf(stderr, "%s: Input looks like start of aptX HD audio stream, try with --hd\n", argv[0]); 106 | } else { 107 | if (length >= 4 && memcmp(input_buffer, "\x6b\xbf\x6b\xbf", 4) == 0) 108 | fprintf(stderr, "%s: Input looks like start of standard aptX audio stream, which is not supported yet\n", argv[0]); 109 | else 110 | fprintf(stderr, "%s: Input does not look like start of aptX nor aptX HD audio stream\n", argv[0]); 111 | } 112 | 113 | ret = 0; 114 | syncing = 0; 115 | 116 | while (length > 0) { 117 | processed = aptx_decode_sync(ctx, input_buffer, length, output_buffer, sizeof(output_buffer), &written, &synced, &dropped); 118 | 119 | /* Check all possible states of synced, syncing and dropped status */ 120 | if (!synced) { 121 | if (!syncing) { 122 | fprintf(stderr, "%s: aptX decoding failed, synchronizing\n", argv[0]); 123 | syncing = 1; 124 | ret = 1; 125 | } 126 | if (dropped) { 127 | fprintf(stderr, "%s: aptX synchronization successful, dropped %lu byte%s\n", argv[0], (unsigned long)dropped, (dropped != 1) ? "s" : ""); 128 | syncing = 0; 129 | ret = 1; 130 | } 131 | if (!syncing) { 132 | fprintf(stderr, "%s: aptX decoding failed, synchronizing\n", argv[0]); 133 | syncing = 1; 134 | ret = 1; 135 | } 136 | } else { 137 | if (dropped) { 138 | if (!syncing) 139 | fprintf(stderr, "%s: aptX decoding failed, synchronizing\n", argv[0]); 140 | fprintf(stderr, "%s: aptX synchronization successful, dropped %lu byte%s\n", argv[0], (unsigned long)dropped, (dropped != 1) ? "s" : ""); 141 | syncing = 0; 142 | ret = 1; 143 | } else if (syncing) { 144 | fprintf(stderr, "%s: aptX synchronization successful\n", argv[0]); 145 | syncing = 0; 146 | ret = 1; 147 | } 148 | } 149 | 150 | /* If we have not decoded all supplied samples then decoding unrecoverable failed */ 151 | if (processed != length) { 152 | fprintf(stderr, "%s: aptX decoding failed\n", argv[0]); 153 | ret = 1; 154 | break; 155 | } 156 | 157 | if (!feof(stdin)) { 158 | length = fread(input_buffer, 1, sizeof(input_buffer), stdin); 159 | if (ferror(stdin)) { 160 | fprintf(stderr, "%s: aptX decoding failed to read input data\n", argv[0]); 161 | ret = 1; 162 | length = 0; 163 | } 164 | } else { 165 | length = 0; 166 | } 167 | 168 | /* On the end of the input stream last two decoded samples are just padding and not a real data */ 169 | if (length == 0 && !ferror(stdin) && written >= 6*2) 170 | written -= 6*2; 171 | 172 | if (written > 0) { 173 | if (fwrite(output_buffer, 1, written, stdout) != written) { 174 | fprintf(stderr, "%s: aptX decoding failed to write decoded data\n", argv[0]); 175 | ret = 1; 176 | break; 177 | } 178 | } 179 | } 180 | 181 | dropped = aptx_decode_sync_finish(ctx); 182 | if (dropped && !syncing) { 183 | fprintf(stderr, "%s: aptX decoding stopped in the middle of the sample, dropped %lu byte%s\n", argv[0], (unsigned long)dropped, (dropped != 1) ? "s" : ""); 184 | ret = 1; 185 | } else if (syncing) { 186 | fprintf(stderr, "%s: aptX synchronization failed\n", argv[0]); 187 | ret = 1; 188 | } 189 | 190 | aptx_finish(ctx); 191 | return ret; 192 | } 193 | -------------------------------------------------------------------------------- /freeaptxenc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aptX encoder utility 3 | * Copyright (C) 2018-2020 Pali Rohár 4 | * Copyright (C) 2025 Hunter Wardlaw 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #ifdef _WIN32 25 | #include 26 | #include 27 | #endif 28 | 29 | #include 30 | 31 | static unsigned char input_buffer[512*3*2*4]; 32 | static unsigned char output_buffer[512*6]; 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | int i; 37 | int hd; 38 | int ret; 39 | size_t length; 40 | size_t processed; 41 | size_t written; 42 | struct aptx_context *ctx; 43 | 44 | #ifdef _WIN32 45 | _setmode(_fileno(stdin), _O_BINARY); 46 | _setmode(_fileno(stdout), _O_BINARY); 47 | #endif 48 | 49 | hd = 0; 50 | 51 | for (i = 1; i < argc; ++i) { 52 | if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { 53 | fprintf(stderr, "aptX encoder utility %d.%d.%d (using libfreeaptx %d.%d.%d)\n", FREEAPTX_MAJOR, FREEAPTX_MINOR, FREEAPTX_PATCH, aptx_major, aptx_minor, aptx_patch); 54 | fprintf(stderr, "\n"); 55 | fprintf(stderr, "This utility encodes a raw 24 bit signed stereo\n"); 56 | fprintf(stderr, "samples from stdin to aptX or aptX HD on stdout\n"); 57 | fprintf(stderr, "\n"); 58 | fprintf(stderr, "Usage:\n"); 59 | fprintf(stderr, " %s [options]\n", argv[0]); 60 | fprintf(stderr, "\n"); 61 | fprintf(stderr, "Options:\n"); 62 | fprintf(stderr, " -h, --help Display this help\n"); 63 | fprintf(stderr, " --hd Encode to aptX HD\n"); 64 | fprintf(stderr, "\n"); 65 | fprintf(stderr, "Examples:\n"); 66 | fprintf(stderr, "\n"); 67 | fprintf(stderr, " %s < sample.s24le > sample.aptx\n", argv[0]); 68 | fprintf(stderr, "\n"); 69 | fprintf(stderr, " %s --hd < sample.s24le > sample.aptxhd\n", argv[0]); 70 | fprintf(stderr, "\n"); 71 | fprintf(stderr, " sox sample.wav -t raw -r 44.1k -L -e s -b 24 -c 2 - | %s > sample.aptx\n", argv[0]); 72 | return 1; 73 | } else if (strcmp(argv[i], "--hd") == 0) { 74 | hd = 1; 75 | } else { 76 | fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]); 77 | return 1; 78 | } 79 | } 80 | 81 | ctx = aptx_init(hd); 82 | if (!ctx) { 83 | fprintf(stderr, "%s: Cannot initialize aptX encoder\n", argv[0]); 84 | return 1; 85 | } 86 | 87 | ret = 0; 88 | 89 | while (!feof(stdin)) { 90 | length = fread(input_buffer, 1, sizeof(input_buffer), stdin); 91 | if (ferror(stdin)) { 92 | fprintf(stderr, "%s: aptX encoding failed to read input data\n", argv[0]); 93 | ret = 1; 94 | } 95 | if (length == 0) 96 | break; 97 | processed = aptx_encode(ctx, input_buffer, length, output_buffer, sizeof(output_buffer), &written); 98 | if (processed != length) { 99 | fprintf(stderr, "%s: aptX encoding stopped in the middle of the sample, dropped %lu byte%s\n", argv[0], (unsigned long)(length-processed), (length-processed != 1) ? "s" : ""); 100 | ret = 1; 101 | } 102 | if (fwrite(output_buffer, 1, written, stdout) != written) { 103 | fprintf(stderr, "%s: aptX encoding failed to write encoded data\n", argv[0]); 104 | ret = 1; 105 | break; 106 | } 107 | if (processed != length) 108 | break; 109 | } 110 | 111 | if (aptx_encode_finish(ctx, output_buffer, sizeof(output_buffer), &written)) { 112 | if (fwrite(output_buffer, 1, written, stdout) != written) { 113 | fprintf(stderr, "%s: aptX encoding failed to write encoded data\n", argv[0]); 114 | ret = 1; 115 | } 116 | } 117 | 118 | aptx_finish(ctx); 119 | return ret; 120 | } 121 | --------------------------------------------------------------------------------