| @ -0,0 +1,19 @@ | |||
| .deps/ | |||
| INSTALL | |||
| Makefile | |||
| Makefile.in | |||
| aclocal.m4 | |||
| autom4te.cache/ | |||
| build-aux/ | |||
| config.log | |||
| config.status | |||
| configure | |||
| libtool | |||
| *.o | |||
| *.lo | |||
| *.la | |||
| libbcg729.pc | |||
| test/src/decoderTest | |||
| test/src/encoderTest | |||
| .libs | |||
| @ -0,0 +1,4 @@ | |||
| Copyright 2012 Belledonne Communications SARL. | |||
| Johan Pascal | |||
| Jehan Monnier | |||
| @ -0,0 +1,340 @@ | |||
| GNU GENERAL PUBLIC LICENSE | |||
| Version 2, June 1991 | |||
| Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |||
| 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| Everyone is permitted to copy and distribute verbatim copies | |||
| of this license document, but changing it is not allowed. | |||
| Preamble | |||
| The licenses for most software are designed to take away your | |||
| freedom to share and change it. By contrast, the GNU General Public | |||
| License is intended to guarantee your freedom to share and change free | |||
| software--to make sure the software is free for all its users. This | |||
| General Public License applies to most of the Free Software | |||
| Foundation's software and to any other program whose authors commit to | |||
| using it. (Some other Free Software Foundation software is covered by | |||
| the GNU Library General Public License instead.) You can apply it to | |||
| your programs, too. | |||
| When we speak of free software, we are referring to freedom, not | |||
| price. Our General Public Licenses are designed to make sure that you | |||
| have the freedom to distribute copies of free software (and charge for | |||
| this service if you wish), that you receive source code or can get it | |||
| if you want it, that you can change the software or use pieces of it | |||
| in new free programs; and that you know you can do these things. | |||
| To protect your rights, we need to make restrictions that forbid | |||
| anyone to deny you these rights or to ask you to surrender the rights. | |||
| These restrictions translate to certain responsibilities for you if you | |||
| distribute copies of the software, or if you modify it. | |||
| For example, if you distribute copies of such a program, whether | |||
| gratis or for a fee, you must give the recipients all the rights that | |||
| you have. You must make sure that they, too, receive or can get the | |||
| source code. And you must show them these terms so they know their | |||
| rights. | |||
| We protect your rights with two steps: (1) copyright the software, and | |||
| (2) offer you this license which gives you legal permission to copy, | |||
| distribute and/or modify the software. | |||
| Also, for each author's protection and ours, we want to make certain | |||
| that everyone understands that there is no warranty for this free | |||
| software. If the software is modified by someone else and passed on, we | |||
| want its recipients to know that what they have is not the original, so | |||
| that any problems introduced by others will not reflect on the original | |||
| authors' reputations. | |||
| Finally, any free program is threatened constantly by software | |||
| patents. We wish to avoid the danger that redistributors of a free | |||
| program will individually obtain patent licenses, in effect making the | |||
| program proprietary. To prevent this, we have made it clear that any | |||
| patent must be licensed for everyone's free use or not licensed at all. | |||
| The precise terms and conditions for copying, distribution and | |||
| modification follow. | |||
| GNU GENERAL PUBLIC LICENSE | |||
| TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||
| 0. This License applies to any program or other work which contains | |||
| a notice placed by the copyright holder saying it may be distributed | |||
| under the terms of this General Public License. The "Program", below, | |||
| refers to any such program or work, and a "work based on the Program" | |||
| means either the Program or any derivative work under copyright law: | |||
| that is to say, a work containing the Program or a portion of it, | |||
| either verbatim or with modifications and/or translated into another | |||
| language. (Hereinafter, translation is included without limitation in | |||
| the term "modification".) Each licensee is addressed as "you". | |||
| Activities other than copying, distribution and modification are not | |||
| covered by this License; they are outside its scope. The act of | |||
| running the Program is not restricted, and the output from the Program | |||
| is covered only if its contents constitute a work based on the | |||
| Program (independent of having been made by running the Program). | |||
| Whether that is true depends on what the Program does. | |||
| 1. You may copy and distribute verbatim copies of the Program's | |||
| source code as you receive it, in any medium, provided that you | |||
| conspicuously and appropriately publish on each copy an appropriate | |||
| copyright notice and disclaimer of warranty; keep intact all the | |||
| notices that refer to this License and to the absence of any warranty; | |||
| and give any other recipients of the Program a copy of this License | |||
| along with the Program. | |||
| You may charge a fee for the physical act of transferring a copy, and | |||
| you may at your option offer warranty protection in exchange for a fee. | |||
| 2. You may modify your copy or copies of the Program or any portion | |||
| of it, thus forming a work based on the Program, and copy and | |||
| distribute such modifications or work under the terms of Section 1 | |||
| above, provided that you also meet all of these conditions: | |||
| a) You must cause the modified files to carry prominent notices | |||
| stating that you changed the files and the date of any change. | |||
| b) You must cause any work that you distribute or publish, that in | |||
| whole or in part contains or is derived from the Program or any | |||
| part thereof, to be licensed as a whole at no charge to all third | |||
| parties under the terms of this License. | |||
| c) If the modified program normally reads commands interactively | |||
| when run, you must cause it, when started running for such | |||
| interactive use in the most ordinary way, to print or display an | |||
| announcement including an appropriate copyright notice and a | |||
| notice that there is no warranty (or else, saying that you provide | |||
| a warranty) and that users may redistribute the program under | |||
| these conditions, and telling the user how to view a copy of this | |||
| License. (Exception: if the Program itself is interactive but | |||
| does not normally print such an announcement, your work based on | |||
| the Program is not required to print an announcement.) | |||
| These requirements apply to the modified work as a whole. If | |||
| identifiable sections of that work are not derived from the Program, | |||
| and can be reasonably considered independent and separate works in | |||
| themselves, then this License, and its terms, do not apply to those | |||
| sections when you distribute them as separate works. But when you | |||
| distribute the same sections as part of a whole which is a work based | |||
| on the Program, the distribution of the whole must be on the terms of | |||
| this License, whose permissions for other licensees extend to the | |||
| entire whole, and thus to each and every part regardless of who wrote it. | |||
| Thus, it is not the intent of this section to claim rights or contest | |||
| your rights to work written entirely by you; rather, the intent is to | |||
| exercise the right to control the distribution of derivative or | |||
| collective works based on the Program. | |||
| In addition, mere aggregation of another work not based on the Program | |||
| with the Program (or with a work based on the Program) on a volume of | |||
| a storage or distribution medium does not bring the other work under | |||
| the scope of this License. | |||
| 3. You may copy and distribute the Program (or a work based on it, | |||
| under Section 2) in object code or executable form under the terms of | |||
| Sections 1 and 2 above provided that you also do one of the following: | |||
| a) Accompany it with the complete corresponding machine-readable | |||
| source code, which must be distributed under the terms of Sections | |||
| 1 and 2 above on a medium customarily used for software interchange; or, | |||
| b) Accompany it with a written offer, valid for at least three | |||
| years, to give any third party, for a charge no more than your | |||
| cost of physically performing source distribution, a complete | |||
| machine-readable copy of the corresponding source code, to be | |||
| distributed under the terms of Sections 1 and 2 above on a medium | |||
| customarily used for software interchange; or, | |||
| c) Accompany it with the information you received as to the offer | |||
| to distribute corresponding source code. (This alternative is | |||
| allowed only for noncommercial distribution and only if you | |||
| received the program in object code or executable form with such | |||
| an offer, in accord with Subsection b above.) | |||
| The source code for a work means the preferred form of the work for | |||
| making modifications to it. For an executable work, complete source | |||
| code means all the source code for all modules it contains, plus any | |||
| associated interface definition files, plus the scripts used to | |||
| control compilation and installation of the executable. However, as a | |||
| special exception, the source code distributed need not include | |||
| anything that is normally distributed (in either source or binary | |||
| form) with the major components (compiler, kernel, and so on) of the | |||
| operating system on which the executable runs, unless that component | |||
| itself accompanies the executable. | |||
| If distribution of executable or object code is made by offering | |||
| access to copy from a designated place, then offering equivalent | |||
| access to copy the source code from the same place counts as | |||
| distribution of the source code, even though third parties are not | |||
| compelled to copy the source along with the object code. | |||
| 4. You may not copy, modify, sublicense, or distribute the Program | |||
| except as expressly provided under this License. Any attempt | |||
| otherwise to copy, modify, sublicense or distribute the Program is | |||
| void, and will automatically terminate your rights under this License. | |||
| However, parties who have received copies, or rights, from you under | |||
| this License will not have their licenses terminated so long as such | |||
| parties remain in full compliance. | |||
| 5. You are not required to accept this License, since you have not | |||
| signed it. However, nothing else grants you permission to modify or | |||
| distribute the Program or its derivative works. These actions are | |||
| prohibited by law if you do not accept this License. Therefore, by | |||
| modifying or distributing the Program (or any work based on the | |||
| Program), you indicate your acceptance of this License to do so, and | |||
| all its terms and conditions for copying, distributing or modifying | |||
| the Program or works based on it. | |||
| 6. Each time you redistribute the Program (or any work based on the | |||
| Program), the recipient automatically receives a license from the | |||
| original licensor to copy, distribute or modify the Program subject to | |||
| these terms and conditions. You may not impose any further | |||
| restrictions on the recipients' exercise of the rights granted herein. | |||
| You are not responsible for enforcing compliance by third parties to | |||
| this License. | |||
| 7. If, as a consequence of a court judgment or allegation of patent | |||
| infringement or for any other reason (not limited to patent issues), | |||
| conditions are imposed on you (whether by court order, agreement or | |||
| otherwise) that contradict the conditions of this License, they do not | |||
| excuse you from the conditions of this License. If you cannot | |||
| distribute so as to satisfy simultaneously your obligations under this | |||
| License and any other pertinent obligations, then as a consequence you | |||
| may not distribute the Program at all. For example, if a patent | |||
| license would not permit royalty-free redistribution of the Program by | |||
| all those who receive copies directly or indirectly through you, then | |||
| the only way you could satisfy both it and this License would be to | |||
| refrain entirely from distribution of the Program. | |||
| If any portion of this section is held invalid or unenforceable under | |||
| any particular circumstance, the balance of the section is intended to | |||
| apply and the section as a whole is intended to apply in other | |||
| circumstances. | |||
| It is not the purpose of this section to induce you to infringe any | |||
| patents or other property right claims or to contest validity of any | |||
| such claims; this section has the sole purpose of protecting the | |||
| integrity of the free software distribution system, which is | |||
| implemented by public license practices. Many people have made | |||
| generous contributions to the wide range of software distributed | |||
| through that system in reliance on consistent application of that | |||
| system; it is up to the author/donor to decide if he or she is willing | |||
| to distribute software through any other system and a licensee cannot | |||
| impose that choice. | |||
| This section is intended to make thoroughly clear what is believed to | |||
| be a consequence of the rest of this License. | |||
| 8. If the distribution and/or use of the Program is restricted in | |||
| certain countries either by patents or by copyrighted interfaces, the | |||
| original copyright holder who places the Program under this License | |||
| may add an explicit geographical distribution limitation excluding | |||
| those countries, so that distribution is permitted only in or among | |||
| countries not thus excluded. In such case, this License incorporates | |||
| the limitation as if written in the body of this License. | |||
| 9. The Free Software Foundation may publish revised and/or new versions | |||
| of the General Public License from time to time. Such new versions will | |||
| be similar in spirit to the present version, but may differ in detail to | |||
| address new problems or concerns. | |||
| Each version is given a distinguishing version number. If the Program | |||
| specifies a version number of this License which applies to it and "any | |||
| later version", you have the option of following the terms and conditions | |||
| either of that version or of any later version published by the Free | |||
| Software Foundation. If the Program does not specify a version number of | |||
| this License, you may choose any version ever published by the Free Software | |||
| Foundation. | |||
| 10. If you wish to incorporate parts of the Program into other free | |||
| programs whose distribution conditions are different, write to the author | |||
| to ask for permission. For software which is copyrighted by the Free | |||
| Software Foundation, write to the Free Software Foundation; we sometimes | |||
| make exceptions for this. Our decision will be guided by the two goals | |||
| of preserving the free status of all derivatives of our free software and | |||
| of promoting the sharing and reuse of software generally. | |||
| NO WARRANTY | |||
| 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |||
| FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |||
| OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||
| PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |||
| OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
| MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |||
| TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |||
| PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |||
| REPAIR OR CORRECTION. | |||
| 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
| WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||
| REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |||
| INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |||
| OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |||
| TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |||
| YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |||
| PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||
| POSSIBILITY OF SUCH DAMAGES. | |||
| END OF TERMS AND CONDITIONS | |||
| How to Apply These Terms to Your New Programs | |||
| If you develop a new program, and you want it to be of the greatest | |||
| possible use to the public, the best way to achieve this is to make it | |||
| free software which everyone can redistribute and change under these terms. | |||
| To do so, attach the following notices to the program. It is safest | |||
| to attach them to the start of each source file to most effectively | |||
| convey the exclusion of warranty; and each file should have at least | |||
| the "copyright" line and a pointer to where the full notice is found. | |||
| <one line to give the program's name and a brief idea of what it does.> | |||
| Copyright (C) <year> <name of author> | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
| Also add information on how to contact you by electronic and paper mail. | |||
| If the program is interactive, make it output a short notice like this | |||
| when it starts in an interactive mode: | |||
| Gnomovision version 69, Copyright (C) year name of author | |||
| Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
| This is free software, and you are welcome to redistribute it | |||
| under certain conditions; type `show c' for details. | |||
| The hypothetical commands `show w' and `show c' should show the appropriate | |||
| parts of the General Public License. Of course, the commands you use may | |||
| be called something other than `show w' and `show c'; they could even be | |||
| mouse-clicks or menu items--whatever suits your program. | |||
| You should also get your employer (if you work as a programmer) or your | |||
| school, if any, to sign a "copyright disclaimer" for the program, if | |||
| necessary. Here is a sample; alter the names: | |||
| Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||
| `Gnomovision' (which makes passes at compilers) written by James Hacker. | |||
| <signature of Ty Coon>, 1 April 1989 | |||
| Ty Coon, President of Vice | |||
| This General Public License does not permit incorporating your program into | |||
| proprietary programs. If your program is a subroutine library, you may | |||
| consider it more useful to permit linking proprietary applications with the | |||
| library. If this is what you want to do, use the GNU Library General | |||
| Public License instead of this License. | |||
| @ -0,0 +1,13 @@ | |||
| ACLOCAL_AMFLAGS = -I m4 | |||
| SUBDIRS = src include | |||
| if BUILD_MSBCG729 | |||
| SUBDIRS += msbcg729 | |||
| endif | |||
| SUBDIRS += test | |||
| pkgconfigdir = $(libdir)/pkgconfig | |||
| pkgconfig_DATA = libbcg729.pc | |||
| @ -0,0 +1,21 @@ | |||
| bcg729 - g729 encoder and decoder implementation, and mediastreamer2 plugin interface. | |||
| By default, the upstream package installs into /usr/local. Please use | |||
| './configure --prefix' to change it | |||
| # Tests suite: | |||
| - Tests are defined for each functional bloc (more or less matching a source file) | |||
| and for global encoding/decoding | |||
| - Use 'make check' to compile and run all tests available in the test directory. | |||
| - Input tests pattern have been generated by ITU code using ITU tests patterns. | |||
| The test patterns are not part of this repository but can be downloaded here: | |||
| http://www.belledonne-communications.com/downloads/bcg729-patterns.zip | |||
| However, the first run of 'make check' will get them for you. | |||
| - To run partial test, use perl executable 'testCampaign' in the test directory. | |||
| './testCampaign <functional bloc name>' | |||
| You must first download the tests patterns using 'make check' or manually | |||
| @ -0,0 +1,29 @@ | |||
| #!/bin/sh | |||
| #AM_VERSION="1.11" | |||
| if ! type aclocal-$AM_VERSION 1>/dev/null 2>&1; then | |||
| AUTOMAKE=automake | |||
| ACLOCAL=aclocal | |||
| else | |||
| ACLOCAL=aclocal-${AM_VERSION} | |||
| AUTOMAKE=automake-${AM_VERSION} | |||
| fi | |||
| if test -f /opt/local/bin/glibtoolize ; then | |||
| # darwin | |||
| LIBTOOLIZE=/opt/local/bin/glibtoolize | |||
| else | |||
| LIBTOOLIZE=libtoolize | |||
| fi | |||
| if test -d /opt/local/share/aclocal ; then | |||
| ACLOCAL_ARGS="-I /opt/local/share/aclocal" | |||
| fi | |||
| echo "Generating build scripts for G729 codec..." | |||
| set -x | |||
| $LIBTOOLIZE --copy --force | |||
| $ACLOCAL $ACLOCAL_ARGS | |||
| #autoheader | |||
| $AUTOMAKE --force-missing --add-missing --copy | |||
| autoconf | |||
| @ -0,0 +1,45 @@ | |||
| # -*- Autoconf -*- | |||
| # Process this file with autoconf to produce a configure script. | |||
| AC_INIT([bcg729],[0.1]) | |||
| AC_PREREQ(2.63) | |||
| AC_CONFIG_SRCDIR([src/encoder.c]) | |||
| AC_CONFIG_AUX_DIR([build-aux]) | |||
| AC_CONFIG_MACRO_DIR([m4]) | |||
| AM_INIT_AUTOMAKE([tar-ustar --warnings=no-portability]) | |||
| AC_PROG_LIBTOOL | |||
| AC_PROG_CC | |||
| m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) | |||
| AC_ARG_ENABLE(strict, | |||
| [ --enable-strict Enable error on compilation warning [default=yes]], | |||
| [wall_werror=$enableval], | |||
| [wall_werror=yes] | |||
| ) | |||
| CFLAGS="$CFLAGS -Wall" | |||
| if test $GCC = yes && test $wall_werror = yes; then | |||
| CFLAGS="$CFLAGS -Werror " | |||
| fi | |||
| # check for libraries that have pkg-config files installed | |||
| PKG_CHECK_MODULES(ORTP, ortp >= 0.16.0,[found_ortp=true],foo=bar) | |||
| PKG_CHECK_MODULES(MEDIASTREAMER, mediastreamer >= 2.0.0,[found_ms2=true],foo=bar) | |||
| AM_CONDITIONAL(BUILD_MSBCG729, test x$found_ms2 = xtrue && test x$found_ortp = xtrue) | |||
| # Create the following files from their .in counterparts | |||
| AC_CONFIG_FILES([ | |||
| Makefile | |||
| src/Makefile | |||
| include/Makefile | |||
| include/bcg729/Makefile | |||
| msbcg729/Makefile | |||
| test/Makefile | |||
| test/bin/Makefile | |||
| libbcg729.pc | |||
| ]) | |||
| AC_OUTPUT | |||
| @ -0,0 +1,34 @@ | |||
| /* | |||
| LP2LSPConversion.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef LP2LSPCONVERSION_H | |||
| #define LP2LSPCONVERSION_H | |||
| /*****************************************************************************/ | |||
| /* LP2LSPConversion : Compute polynomials, find their roots as in spec A3.2.3*/ | |||
| /* parameters: */ | |||
| /* -(i) LPCoefficients[] : 10 coefficients in Q12 */ | |||
| /* -(o) LSPCoefficients[] : 10 coefficients in Q15 */ | |||
| /* */ | |||
| /* return value : */ | |||
| /* - boolean: 1 if all roots found, 0 if unable to compute 10 roots */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[]); | |||
| #endif /* ifndef LP2LSPCONVERSION_H */ | |||
| @ -0,0 +1,34 @@ | |||
| /* | |||
| LPSynthesisFilter.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef LPSYNTHESISFILTER_H | |||
| #define LPSYNTHESISFILTER_H | |||
| /*****************************************************************************/ | |||
| /* LPSynthesisFilter : as decribed in spec 4.1.6 eq77 */ | |||
| /* parameters: */ | |||
| /* -(i) excitationVector: u(n), the excitation, 40 values in Q0 */ | |||
| /* -(i) LPCoefficients: 10 LP coefficients in Q12 */ | |||
| /* -(i/o) recontructedSpeech: 50 values in Q0 */ | |||
| /* [-NB_LSP_COEFF, -1] of previous values as input */ | |||
| /* [0, L_SUBFRAME[ as output */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void LPSynthesisFilter (word16_t *excitationVector, word16_t *LPCoefficients, word16_t *reconstructedSpeech); | |||
| #endif /* ifndef LPSYNTHESISFILTER_H */ | |||
| @ -0,0 +1,36 @@ | |||
| /* | |||
| LSPQuantization.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef LSPQUANTIZATION_H | |||
| #define LSPQUANTIZATION_H | |||
| void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* LSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */ | |||
| /* qLSF->qLSP as described in spec A3.2.4 */ | |||
| /* parameters: */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */ | |||
| /* -(i) qLSPCoefficients : 10 qLSP coefficients in Q15 */ | |||
| /* -(o) parameters : 4 parameters L0, L1, L2, L3 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[]); | |||
| #endif /* LSPQUANTIZATION_H */ | |||
| @ -0,0 +1,4 @@ | |||
| SUBDIRS = bcg729 | |||
| @ -0,0 +1,49 @@ | |||
| /* | |||
| adaptativeCodebookSearch.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef ADAPTATIVECODEBOOKSEARCH_H | |||
| #define ADAPTATIVECODEBOOKSEARCH_H | |||
| /*****************************************************************************/ | |||
| /* adaptativeCodebookSearch: compute parameter P1 and P2 as in spec A.3.7 */ | |||
| /* compute also adaptative codebook vector as in spec 3.7.1 */ | |||
| /* parameters: */ | |||
| /* -(i/o) excitationVector: [-154,0[ previous excitation as input */ | |||
| /* Range [0,39[ */ | |||
| /* 40 words of LPResidualSignal as substitute for current */ | |||
| /* excitation (spec A.3.7) as input */ | |||
| /* 40 words of adaptative codebook vector in Q0 as output */ | |||
| /* Buffer in Q0 accessed in range [-154, 39] */ | |||
| /* -(i/o) intPitchDelayMin: low boundary for pitch delay search */ | |||
| /* -(i/o) intPitchDelayMax: low boundary for pitch delay search */ | |||
| /* Boundaries are updated during first subframe search */ | |||
| /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ | |||
| /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ | |||
| /* */ | |||
| /* -(o) intPitchDelay: the integer pitch delay */ | |||
| /* -(o) fracPitchDelay: the fractionnal part of pitch delay */ | |||
| /* -(o) pitchDelayCodeword: P1 or P2 codeword as in spec 3.7.2 */ | |||
| /* -(o) adaptativeCodebookVector: 40 words of adaptative codebook vector*/ | |||
| /* as described in spec 3.7.1, in Q0. */ | |||
| /* -(i) subFrameIndex: 0 for the first subframe, 40 for the second */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDelayMin, int16_t *intPitchDelayMax, word16_t impulseResponse[], word16_t targetSignal[], | |||
| int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex); | |||
| #endif /* ifndef ADAPTATIVECODEBOOKSEARCH_H */ | |||
| @ -0,0 +1,26 @@ | |||
| /* | |||
| basicOperationsMacros.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef BASICOPERATIONSMACROS_H | |||
| #define BASICOPERATIONSMACROS__H | |||
| #include "fixedPointMacros.h" | |||
| #endif /* ifndef BASICOPERATIONSMACROS_H */ | |||
| @ -0,0 +1,5 @@ | |||
| bcg729_includedir=$(includedir)/bcg729 | |||
| bcg729_include_HEADERS= encoder.h decoder.h | |||
| EXTRA_DIST=$(bcg729_include_HEADERS) | |||
| @ -0,0 +1,52 @@ | |||
| /* | |||
| decoder.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef DECODER_H | |||
| #define DECODER_H | |||
| typedef struct bcg729DecoderChannelContextStruct_struct bcg729DecoderChannelContextStruct; | |||
| #include <stdint.h> | |||
| /*****************************************************************************/ | |||
| /* initBcg729DecoderChannel : create context structure and initialise it */ | |||
| /* return value : */ | |||
| /* - the decoder channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) bcg729DecoderChannelContextStruct *initBcg729DecoderChannel(); | |||
| /*****************************************************************************/ | |||
| /* closeBcg729DecoderChannel : free memory of context structure */ | |||
| /* parameters: */ | |||
| /* -(i) decoderChannelContext : the channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* bcg729Decoder : */ | |||
| /* parameters: */ | |||
| /* -(i) decoderChannelContext : the channel context data */ | |||
| /* -(i) bitStream : 15 parameters on 80 bits */ | |||
| /* -(i) frameErased: flag: true, frame has been erased */ | |||
| /* -(o) signal : a decoded frame 80 samples (16 bits PCM) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, int16_t signal[]); | |||
| #endif /* ifndef DECODER_H */ | |||
| @ -0,0 +1,52 @@ | |||
| /* | |||
| encoder.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef ENCODER_H | |||
| #define ENCODER_H | |||
| #include <stdint.h> | |||
| typedef struct bcg729EncoderChannelContextStruct_struct bcg729EncoderChannelContextStruct; | |||
| /*****************************************************************************/ | |||
| /* initBcg729EncoderChannel : create context structure and initialise it */ | |||
| /* return value : */ | |||
| /* - the encoder channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) bcg729EncoderChannelContextStruct *initBcg729EncoderChannel(); | |||
| /*****************************************************************************/ | |||
| /* closeBcg729EncoderChannel : free memory of context structure */ | |||
| /* parameters: */ | |||
| /* -(i) encoderChannelContext : the channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* bcg729Encoder : */ | |||
| /* parameters: */ | |||
| /* -(i) encoderChannelContext : context for this encoder channel */ | |||
| /* -(i) inputFrame : 80 samples (16 bits PCM) */ | |||
| /* -(o) bitStream : The 15 parameters for a frame on 80 bits */ | |||
| /* on 80 bits (5 16bits words) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| __attribute__ ((visibility ("default"))) void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[]); | |||
| #endif /* ifndef ENCODER_H */ | |||
| @ -0,0 +1,50 @@ | |||
| /* | |||
| codebooks.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef CODEBOOKS_H | |||
| #define CODEBOOKS_H | |||
| #include "codecParameters.h" | |||
| /* this codebooks are defined in codebook.c */ | |||
| /*** codebooks for quantization of the LSP coefficient - doc: 3.2.4 ***/ | |||
| extern word16_t L1[L1_RANGE][NB_LSP_COEFF]; /* The first stage is a 10-dimensional VQ using codebook L1 with 128 entries (7 bits). in Q2.13 */ | |||
| extern word16_t L2L3[L2_RANGE][NB_LSP_COEFF]; /* Doc : The second stage is a 10-bit VQ splitted in L2(first 5 values of a vector) and L3(last five value in each vector) containing 32 entries (5 bits). in Q0.13 but max value < 0.5 so fits in 13 bits. */ | |||
| extern word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF]; /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */ | |||
| extern word16_t MAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1 - Sum(MAPredictor) in Q0.15 */ | |||
| extern word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1/(1 - Sum(MAPredictor)) in Q3.12 */ | |||
| /* codebook for adaptative code vector */ | |||
| extern word16_t b30[30]; | |||
| /* codebook for gains */ | |||
| extern uint16_t reverseIndexMappingGA[8]; | |||
| extern uint16_t reverseIndexMappingGB[16]; | |||
| extern uint16_t indexMappingGA[8]; | |||
| extern uint16_t indexMappingGB[16]; | |||
| extern word16_t GACodebook[8][2]; | |||
| extern word16_t GBCodebook[16][2]; | |||
| extern word16_t MAPredictionCoefficients[4]; | |||
| /* codebook for LP Analysis */ | |||
| extern word16_t wlp[L_LP_ANALYSIS_WINDOW]; | |||
| extern word16_t wlag[NB_LSP_COEFF+1]; | |||
| #endif /* ifndef CODEBOOKS_H */ | |||
| @ -0,0 +1,113 @@ | |||
| /* | |||
| codecParameters.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef CODECPARAMETERS_H | |||
| #define CODECPARAMETERS_H | |||
| #define L_FRAME 80 /* Frame size. */ | |||
| #define L_SUBFRAME 40 /* subFrame size. */ | |||
| #define L_LP_ANALYSIS_WINDOW 240 /* Size of the window used in the LP Analysis */ | |||
| /******************************************************************************/ | |||
| /*** LSP coefficients ***/ | |||
| /******************************************************************************/ | |||
| /* define each coefficient bit number and range */ | |||
| #define L0_LENGTH 1 | |||
| #define L1_LENGTH 7 | |||
| #define L2_LENGTH 5 | |||
| #define L3_LENGTH 5 | |||
| #define L0_RANGE (1<<L0_LENGTH) | |||
| #define L1_RANGE (1<<L1_LENGTH) | |||
| #define L2_RANGE (1<<L2_LENGTH) | |||
| #define L3_RANGE (1<<L3_LENGTH) | |||
| /* MA Prediction history length: maximum number of previous LSP used */ | |||
| #define MA_MAX_K 4 | |||
| /* Linear Prediction filters order: 10th order filters gives 10 (quantized) LP coefficients */ | |||
| /* NB_LSP_COEFF is the number of LSP coefficient */ | |||
| #define NB_LSP_COEFF 10 | |||
| /* Maximum value of integer part of pitch delay */ | |||
| #define MAXIMUM_INT_PITCH_DELAY 143 | |||
| /* past excitation vector length: Maximum Pitch Delay (143 + 1(fractionnal part)) + Interpolation Windows Length (10) */ | |||
| #define L_PAST_EXCITATION 154 | |||
| /* rearrange coefficient gap in Q13 */ | |||
| /* GAP1 is 0.0012, GAP2 is 0.0006 */ | |||
| #define GAP1 10 | |||
| #define GAP2 5 | |||
| /* qLSF stability in Q13*/ | |||
| /* Limits for quantized LSF */ | |||
| /* in Q2.13, Max is 3.135 and Min is 0.005 */ | |||
| #define qLSF_MIN 40 | |||
| #define qLSF_MAX 25681 | |||
| /* min distance between 2 consecutive qLSF is 0.0391 */ | |||
| #define MIN_qLSF_DISTANCE 321 | |||
| /* pitch gain boundaries in Q14 */ | |||
| #define BOUNDED_PITCH_GAIN_MIN 3277 | |||
| #define BOUNDED_PITCH_GAIN_MAX 13107 | |||
| /* post filters values defined in 4.2.2 in Q15 pow 1 to 10 */ | |||
| #define GAMMA_N1 18022 | |||
| #define GAMMA_N2 9912 | |||
| #define GAMMA_N3 5452 | |||
| #define GAMMA_N4 2998 | |||
| #define GAMMA_N5 1649 | |||
| #define GAMMA_N6 907 | |||
| #define GAMMA_N7 499 | |||
| #define GAMMA_N8 274 | |||
| #define GAMMA_N9 151 | |||
| #define GAMMA_N10 83 | |||
| #define GAMMA_D1 22938 | |||
| #define GAMMA_D2 16056 | |||
| #define GAMMA_D3 11239 | |||
| #define GAMMA_D4 7868 | |||
| #define GAMMA_D5 5507 | |||
| #define GAMMA_D6 3855 | |||
| #define GAMMA_D7 2699 | |||
| #define GAMMA_D8 1889 | |||
| #define GAMMA_D9 1322 | |||
| #define GAMMA_D10 926 | |||
| /* post filter value GAMMA_T 0.8 in Q15 (spec A.4.2.3)*/ | |||
| #define GAMMA_T 26214 | |||
| /* weighted speech for open-loop pitch delay (spec A3.3.3) in Q15 0.75^(1..10)*/ | |||
| #define GAMMA_E1 24756 | |||
| #define GAMMA_E2 18432 | |||
| #define GAMMA_E3 13824 | |||
| #define GAMMA_E4 10368 | |||
| #define GAMMA_E5 7776 | |||
| #define GAMMA_E6 5832 | |||
| #define GAMMA_E7 4374 | |||
| #define GAMMA_E8 3280 | |||
| #define GAMMA_E9 2460 | |||
| #define GAMMA_E10 1845 | |||
| /*** Number of parameters in the encoded signal ***/ | |||
| #define NB_PARAMETERS 15 | |||
| /*** LP to LSP conversion ***/ | |||
| #define NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL 51 | |||
| #endif /* ifndef CODECPARAMETERS_H */ | |||
| @ -0,0 +1,37 @@ | |||
| /* | |||
| computeAdaptativeCodebookGain.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef COMPUTEADAPTATIVECODEBOOKGAIN_H | |||
| #define COMPUTEADAPTATIVECODEBOOKGAIN_H | |||
| /*****************************************************************************/ | |||
| /* computeAdaptativeCodebookGain: compute gain, return result in Q14 */ | |||
| /* in range [0,1.2]. Spec 3.7.3 */ | |||
| /* parameters: */ | |||
| /* -(i) targetSignal: 40 values in Q0 */ | |||
| /* -(i) filteredAdaptativeCodebookVector: 40 values in Q0 */ | |||
| /* -(o) gainQuantizationXy in Q0 on 64 bits used for gain quantization */ | |||
| /* -(o) gainQuantizationYy in Q0 on 64 bits used for gain quantization */ | |||
| /* return value: */ | |||
| /* - the adaptative codebook gain on 16 bits in Q14 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word64_t *gainQuantizationXy, word64_t *gainQuantizationYy); | |||
| #endif /* ifndef COMPUTEADAPTATIVECODEBOOKGAIN_H */ | |||
| @ -0,0 +1,32 @@ | |||
| /* | |||
| computeLP.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef COMPUTELP_H | |||
| #define COMPUTELP_H | |||
| /*****************************************************************************/ | |||
| /* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */ | |||
| /* Autocorrelation and Levinson-Durbin algorithm */ | |||
| /* parameters: */ | |||
| /* -(i) signal: 240 samples in Q0, the last 40 are from next frame */ | |||
| /* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[]); | |||
| #endif /* ifndef COMPUTELP_H */ | |||
| @ -0,0 +1,37 @@ | |||
| /* | |||
| computeWeightedSpeech.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef COMPUTEWEIGHTEDSPEECH | |||
| #define COMPUTEWEIGHTEDSPEECH | |||
| /*****************************************************************************/ | |||
| /* computeWeightedSpeech: compute wieghted speech according to spec A3.3.3 */ | |||
| /* parameters: */ | |||
| /* -(i) inputSignal : 90 values buffer accessed in range [-10, 79] in Q0*/ | |||
| /* -(i) qLPCoefficients: 20 coefficients(10 for each subframe) in Q12 */ | |||
| /* -(i) weightedqLPCoefficients: 20 coefficients(10 for each subframe) */ | |||
| /* in Q12 */ | |||
| /* -(i/o) weightedInputSignal: 90 values in Q0: [-10, -1] as input */ | |||
| /* [0,79] as output in Q0 */ | |||
| /* -(o) LPResidualSignal: 80 values of residual signal in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], word16_t weightedqLPCoefficients[], word16_t weightedInputSignal[], word16_t LPResidualSignal[]); | |||
| #endif /* ifndef COMPUTEWEIGHTEDSPEECH */ | |||
| @ -0,0 +1,45 @@ | |||
| /* | |||
| decodeAdaptativeCodeVector.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef DECODEADAPTATIVECODEVECTOR_H | |||
| #define DECODEADAPTATIVECODEVECTOR_H | |||
| /* init function */ | |||
| void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* decodeAdaptativeCodeVector : as in spec 4.1.3 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) subFrameIndex : 0 or 40 for subframe 1 or subframe 2 */ | |||
| /* -(i) adaptativeCodebookIndex : parameter P1 or P2 */ | |||
| /* -(i) parityFlag : based on P1 parity flag : set if parity error */ | |||
| /* -(i) frameErasureFlag : set in case of frame erasure */ | |||
| /* -(i/o) intPitchDelay : the integer part of Pitch Delay. Computed from*/ | |||
| /* P1 on subframe 1. On Subframe 2, contains the intPitchDelay */ | |||
| /* computed on Subframe 1. */ | |||
| /* -(i/o) excitationVector : in Q0 excitation accessed from */ | |||
| /* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */ | |||
| /* and [0, L_SUBFRAME[ as output to store the adaptative */ | |||
| /* codebook vector */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext, int subFrameIndex, uint16_t adaptativeCodebookIndex, uint8_t parityFlag, uint8_t frameErasureFlag, | |||
| int16_t *intPitchDelay, word16_t *excitationVector); | |||
| #endif /* ifndef DECODEADAPTATIVECODEVECTOR_H */ | |||
| @ -0,0 +1,35 @@ | |||
| /* | |||
| decodeFixedCodeVector.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef DECODEFIXEDCODEVECTOR_H | |||
| #define DECODEFIXEDCODEVECTOR_H | |||
| /*****************************************************************************/ | |||
| /* decodeFixedCodeVector : compute the fixed codebook vector as in spec 4.1.4*/ | |||
| /* parameters: */ | |||
| /* -(i) signs: parameter S(4 signs bit) eq61 */ | |||
| /* -(i) positions: parameter C(4 3bits position and jx bit) eq62 */ | |||
| /* -(i) intPitchDelay: integer part of pitch Delay (T) */ | |||
| /* -(i) boundedPitchGain: Beta in eq47 and eq48, in Q14 */ | |||
| /* -(o) fixedCodebookVector: 40 values in Q13, range: [-1.8,+1.8] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchDelay, word16_t boundedPitchGain, | |||
| word16_t *fixedCodebookVector); | |||
| #endif /* ifndef DECODEFIXEDCODEVECTOR_H */ | |||
| @ -0,0 +1,43 @@ | |||
| /* | |||
| decodeGains.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef DECODEGAINS_H | |||
| #define DECODEGAINS_H | |||
| /* init function */ | |||
| void initDecodeGains(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* decodeGains : decode adaptive and fixed codebooks gains as in spec 4.1.5 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) GA : parameter GA: Gain Codebook Stage 1 (3 bits) */ | |||
| /* -(i) GB : paremeter GB: Gain Codebook Stage 2 (4 bits) */ | |||
| /* -(i) fixedCodebookVector: 40 values current fixed Codebook vector */ | |||
| /* in Q1.13. */ | |||
| /* -(i) frameErasureFlag : set in case of frame erasure */ | |||
| /* -(i/o) adaptativeCodebookGain : input previous/output current */ | |||
| /* subframe Pitch Gain in Q14 */ | |||
| /* -(i/o) fixedCodebookGain : input previous/output current Fixed */ | |||
| /* Codebook Gain in Q1 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t GA, uint16_t GB, word16_t *fixedCodebookVector, uint8_t frameErasureFlag, | |||
| word16_t *adaptativeCodebookGain, word16_t *fixedCodebookGain); | |||
| #endif /* ifndef DECODEGAINS_H */ | |||
| @ -0,0 +1,43 @@ | |||
| /* | |||
| decodeLSP.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef DECODELSP_H | |||
| #define DECODELSP_H | |||
| /*****************************************************************************/ | |||
| /* initDecodeLSP : */ | |||
| /* Initialise the decodeLSP previousqLSP buffer */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void initDecodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* decodeLSP : decode LSP coefficients as in spec 4.1.1/3.2.4 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) L: 4 elements array containing L[0-3] the first and */ | |||
| /* second stage vector of LSP quantizer */ | |||
| /* -(i) frameErased : a boolean, when true, frame has been erased */ | |||
| /* -(o) qLSP: 10 quantized LSP coefficients in Q15 in range [-1,+1[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t L[], word16_t qLSP[], uint8_t frameErased); | |||
| #endif /* ifndef DECODELSP_H */ | |||
| @ -0,0 +1,33 @@ | |||
| /* | |||
| findOpenLoopPitchDelay.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef FINDOPENLOOPPITCHDELAY_H | |||
| #define FINDOPENLOOPPITCHDELAY_H | |||
| /*****************************************************************************/ | |||
| /* findOpenLoopPitchDelay : as specified in specA3.4 */ | |||
| /* paremeters: */ | |||
| /* -(i) weightedInputSignal: 223 values in Q0, buffer */ | |||
| /* accessed in range [-MAXIMUM_INT_PITCH_DELAY(143), L_FRAME(80)[ */ | |||
| /* return value: */ | |||
| /* - the openLoopIntegerPitchDelay in Q0 range [20, 143] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[]); | |||
| #endif /* ifndef FINDOPENLOOPPITCHDELAY_H */ | |||
| @ -0,0 +1,43 @@ | |||
| /* | |||
| fixedCodebookSearch.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef FIXEDCODEBOOKSEARCH_H | |||
| #define FIXEDCODEBOOKSEARCH_H | |||
| /*****************************************************************************/ | |||
| /* fixedCodebookSearch: compute fixed codebook parameters (codeword and sign)*/ | |||
| /* compute also fixed codebook vector as in spec 3.8.1 */ | |||
| /* parameters: */ | |||
| /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ | |||
| /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ | |||
| /* -(i) intPitchDelay: current integer pitch delay */ | |||
| /* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */ | |||
| /* gain quantized in Q14 */ | |||
| /* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */ | |||
| /* -(i) adaptativeCodebookGain : in Q14 */ | |||
| /* -(o) fixedCodebookParameter */ | |||
| /* -(o) fixedCodebookPulsesSigns */ | |||
| /* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q13 */ | |||
| /* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */ | |||
| /* in Q12. */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], int16_t intPitchDelay, word16_t lastQuantizedAdaptativeCodebookGain, word16_t filteredAdaptativeCodebookVector[], word16_t adaptativeCodebookGain, | |||
| uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[]); | |||
| #endif /* ifndef FIXEDCODEBOOKSEARCH_H */ | |||
| @ -0,0 +1,111 @@ | |||
| /* | |||
| fixedPointMacros.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef FIXEDPOINTMACROS_H | |||
| #define FIXEDPOINTMACROS_H | |||
| #define EXTEND32(x) ((word32_t)(x)) | |||
| #define NEG16(x) (-(x)) | |||
| #define NEG32(x) (-(x)) | |||
| /*** shifts ***/ | |||
| #define SHR(a,shift) ((a) >> (shift)) | |||
| #define SHL(a,shift) ((word32_t)(a) << (shift)) | |||
| /* shift right with rounding: used to extract the integer value of a Qa number */ | |||
| #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) | |||
| /* shift right with checking on sign of shift value */ | |||
| #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) | |||
| #define SHR16(a,shift) ((a) >> (shift)) | |||
| #define SHL16(a,shift) ((a) << (shift)) | |||
| #define SHR32(a,shift) ((a) >> (shift)) | |||
| #define SHL32(a,shift) ((a) << (shift)) | |||
| #define SHR64(a,shift) ((a) >> (shift)) | |||
| #define SHL64(a,shift) ((a) << (shift)) | |||
| /* avoid overflows: a+1 is used to check on negative value because range of a 2n signed bits int is -2pow(n) - 2pow(n)-1 */ | |||
| /* SATURATE Macro shall be called with MAXINT(nbits). Ex: SATURATE(x,MAXINT16) with MAXINT16 defined to 2pow(16) - 1 */ | |||
| #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a+1) ? -(a+1) : (x))) | |||
| /*** add and sub ***/ | |||
| #define ADD16(a,b) ((word16_t)((word16_t)(a)+(word16_t)(b))) | |||
| #define SUB16(a,b) ((word16_t)(a)-(word16_t)(b)) | |||
| #define ADD32(a,b) ((word32_t)(a)+(word32_t)(b)) | |||
| #define SUB32(a,b) ((word32_t)(a)-(word32_t)(b)) | |||
| /*** Multiplications/Accumulations ***/ | |||
| /* WARNING: MULT16_32_QX use MULT16_16 macro but the first multiplication must actually be a 16bits * 32bits with result on 32 bits and not a 16*16 */ | |||
| /* MULT16_16 is then implemented here as a 32*32 bits giving result on 32 bits */ | |||
| #define MULT16_16(a,b) ((word32_t)((word32_t)(a))*((word32_t)(b))) | |||
| #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) | |||
| #define MSU16_16(c,a,b) (SUB32((c),MULT16_16((a),(b)))) | |||
| #define DIV32(a,b) (((word32_t)(a))/((word32_t)(b))) | |||
| /* Q4 operations */ | |||
| #define MULT16_16_Q4(a,b) (SHR(MULT16_16((a),(b)),4)) | |||
| #define MAC16_16_Q4(c,a,b) ADD32(c,MULT16_16_Q4(a,b)) | |||
| /* Q11 operations */ | |||
| #define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11)) | |||
| #define MULT16_16_P11(a,b) (SHR(ADD32(1024,MULT16_16((a),(b))),11)) | |||
| /* Q12 operations */ | |||
| #define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) | |||
| #define MAC16_32_Q12(c,a,b) ADD32(c,MULT16_32_Q12(a,b)) | |||
| #define MULT16_16_Q12(a,b) (SHR(MULT16_16((a),(b)),12)) | |||
| #define MAC16_16_Q12(c,a,b) ADD32(c,MULT16_16_Q12(a,b)) | |||
| #define MSU16_16_Q12(c,a,b) SUB32(c,MULT16_16_Q12(a,b)) | |||
| /* Q13 operations */ | |||
| #define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) | |||
| #define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) | |||
| #define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) | |||
| #define MAC16_32_Q13(c,a,b) ADD32(c,MULT16_32_Q13(a,b)) | |||
| /* Q14 operations */ | |||
| #define MULT16_32_P14(a,b) ADD32(MULT16_16((a),SHR((b),14)), PSHR(MULT16_16((a),((b)&0x00003fff)),14)) | |||
| #define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) | |||
| #define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) | |||
| #define MAC16_16_Q14(c,a,b) ADD32(c,MULT16_16_Q14(a,b)) | |||
| #define MSU16_16_Q14(c,a,b) SUB32(c,MULT16_16_Q14(a,b)) | |||
| /* Q15 operations */ | |||
| #define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) | |||
| #define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) | |||
| #define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) | |||
| #define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) | |||
| #define MAC16_32_P15(c,a,b) ADD32(c,MULT16_32_P15(a,b)) | |||
| /* 64 bits operations */ | |||
| #define ADD64_32(a,b) ((word64_t)(a)+(word32_t)(b)) | |||
| #define MULT32_32(a,b) ((word64_t)((word64_t)(a)*((word64_t)(b)))) | |||
| #define DIV64(a,b) ((word64_t)(a)/(word64_t)(b)) | |||
| #define MAC64(c,a,b) ((word64_t)c+(word64_t)((word64_t)a*(word64_t)b)) | |||
| /* Divisions: input numbers with similar scale(Q) output according to operation. Warning: Make use of 64 bits variables */ | |||
| #define DIV32_32_Q24(a,b) (((word64_t)(a)<<24)/((word32_t)(b))) | |||
| #define DIV32_32_Q27(a,b) (((word64_t)(a)<<27)/((word32_t)(b))) | |||
| #define DIV32_32_Q31(a,b) (((word64_t)(a)<<31)/((word32_t)(b))) | |||
| #define MULT32_32_Q23(a,b) ((word32_t)(SHR64(((word64_t)a*(word64_t)b),23))) | |||
| #define MULT32_32_Q31(a,b) ((word32_t)(SHR64(((word64_t)a*(word64_t)b),31))) | |||
| #define MAC32_32_Q31(c,a,b) ADD32(c,MULT32_32_Q31(a,b)) | |||
| #endif /* ifndef FIXEDPOINTMACROS_H */ | |||
| @ -0,0 +1,52 @@ | |||
| /* | |||
| floatingPointMacros.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef FLOATINGPOINTMACROS_H | |||
| #define FLOATINGPOINTMACROS_H | |||
| #define EXTEND32(x) (x) | |||
| /* shifts */ | |||
| #define SHR(a,shift) (a) | |||
| #define SHL(a,shift) (a) | |||
| #define PSHR(a,shift) (a) | |||
| /* avoid overflows: nothing to do for floats */ | |||
| #define SATURATE(x,a) (x) | |||
| /* add and sub */ | |||
| #define ADD16(a,b) ((a)+(b)) | |||
| #define SUB16(a,b) ((a)-(b)) | |||
| #define ADD32(a,b) ((a)+(b)) | |||
| #define SUB32(a,b) ((a)-(b)) | |||
| /* Multiplications/Accumulations */ | |||
| #define MULT16_16(a,b) ((word32_t)(a)*(word32_t)(b)) | |||
| #define MAC16_16(c,a,b) ((c)+MULT16_16((a),(b))) | |||
| #define MULT16_32(a,b) ((a)*(b)) | |||
| #define MAC16_32(c,a,b) ((c)+(a)*(b)) | |||
| /* Q12 operations */ | |||
| #define MULT16_32_Q12(a,b) MULT16_32(a,b) | |||
| #define MAC16_32_Q12(c,a,b) MAC16_32(c,a,b) | |||
| #endif /* ifndef FLOATINGPOINTMACROS_H */ | |||
| @ -0,0 +1,316 @@ | |||
| /* | |||
| g729FixedPointMath.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef G729FIXEDPOINTMATH_H | |||
| #define G729FIXEDPOINTMATH_H | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* This library provides the following functions */ | |||
| /* */ | |||
| /* g729Log2_Q0Q16 : Logarithm base 2 */ | |||
| /* g729Exp2_Q11Q16 : Exponentiel base 2 */ | |||
| /* g729Sqrt_Q0Q7 : Square Root */ | |||
| /* g729Cos_Q13Q15 : Cosine */ | |||
| /* g729Atan_Q15Q13 : Arc Tangent */ | |||
| /* g729Asin_Q15Q13 : Arc Sine */ | |||
| /* g729Acos_Q15Q13 : Arc Cosine */ | |||
| /* */ | |||
| /* Extention QxxQyy stands for input in Qxx output in Qyy */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include "typedef.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| /* constants defined in Q16: actual values: | |||
| KL0 = -2.059978 | |||
| KL1 = 5.770780 | |||
| KL2 = -3.847187 | |||
| KL3 = 1.139907 | |||
| */ | |||
| #define KL0 -135003 | |||
| #define KL1 378194 | |||
| #define KL2 -252129 | |||
| #define KL3 74705 | |||
| /*****************************************************************************/ | |||
| /* g729Log2_Q0Q16 : logarithm base 2, frac part computed from Taylor serie */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 32 bits integer in Q0, expected to be>0(not checked here) */ | |||
| /* return value: */ | |||
| /* - the log2(x) in Q16 on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word32_t g729Log2_Q0Q16(word32_t x) | |||
| { | |||
| /* first get the integer part and put it in the 16 MSB of return value (in Q16) */ | |||
| uint16_t leadingZeros = countLeadingZeros(x); /* note: MSB is excluded as considered as sign bit */ | |||
| word32_t retValue = SHL32(SUB16(30,leadingZeros), 16); | |||
| /* now shift the number to have it on this form 01XX XXXX XXXX XXXX, and keep only 16 bits -> consider it as a number in range [0.5, 1[ in Q0.15 */ | |||
| word16_t acc = (word16_t)VSHR32(x, 16-leadingZeros); | |||
| /* So calling int the integer part of the log2, we have: */ | |||
| /* int = 30 - leadingZeros */ | |||
| /* acc = x*2^(leadingZeros - 16) */ | |||
| /* acc = x*2^(14 - int) */ | |||
| /* considering the content of acc as a Q15 number eq *2^-15*/ | |||
| /* acc = x*2^(14 -int)*2^-15 */ | |||
| /* acc = x*2^(-1 -int) */ | |||
| /* log2(acc) = log2(x) -1 - int */ | |||
| /* log2(x) ~= -3.059978 + 5.770780*x - 3.847187*x^2 + 1.139907*x^3 (for .5 < x < 1) Taylor Serie log2(x) at x near 0.75 */ | |||
| /* log2(x) + 1 = -2.059978 + x*(5.770780 +x(-3.847187 + 1.139907*x)) */ | |||
| /* with coeff in Q16 : */ | |||
| /* log2(acc) +1 = log2(x) - int = */ | |||
| /* log2(acc) +1 = -135003 +acc*(378194 +acc*(-252129 + acc*74705)) acc in Q15 and constants in Q16 -> final result will be log2(x) -int in Q16(on 32 bits) */ | |||
| word32_t acc32 = ADD32(KL0, MULT16_32_Q15(acc, ADD32(KL1, MULT16_32_Q15(acc, ADD32(KL2, MULT16_32_Q15(acc, KL3)))))); | |||
| return ADD32(retValue,acc32); | |||
| } | |||
| /* constants defined in Q15: actual values: | |||
| E0 = 1 | |||
| E1 = log(2) | |||
| E2 = 3-4*log(2) | |||
| E3 = 3*log(2) - 2 | |||
| */ | |||
| #define E0 16384 | |||
| #define E1 11356 | |||
| #define E2 3726 | |||
| #define E3 1301 | |||
| /*****************************************************************************/ | |||
| /* g729Exp2_Q11Q16 : Exponentielle base 2 */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 16 bits integer in Q11 */ | |||
| /* return value: */ | |||
| /* - exp2(x) in Q16 on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word32_t g729Exp2_Q11Q16(word16_t x) | |||
| { | |||
| int integer; | |||
| word16_t frac; | |||
| integer = SHR16(x,11); | |||
| if (integer>14) { | |||
| return 0x7fffffff; | |||
| } else { | |||
| if (integer < -15) { | |||
| return 0; | |||
| } | |||
| } | |||
| frac = SHL16(x-SHL16(integer,11),3); | |||
| frac = ADD16(E0, MULT16_16_Q14(frac, ADD16(E1, MULT16_16_Q14(frac, ADD16(E2 , MULT16_16_Q14(E3,frac)))))); | |||
| return VSHR32(EXTEND32(frac), -integer-2); | |||
| } | |||
| /* constants in Q14 */ | |||
| #define C0 3634 | |||
| #define C1 21173 | |||
| #define C2 -12627 | |||
| #define C3 4204 | |||
| /*****************************************************************************/ | |||
| /* g729Sqrt_Q0Q7 : Square root */ | |||
| /* x is not tested to be >=0, shall be done by caller function */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 32 bits integer in Q0 */ | |||
| /* return value: */ | |||
| /* - sqrt(x) in Q7 on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word32_t g729Sqrt_Q0Q7(word32_t x) | |||
| { | |||
| if (x==0) return 0; | |||
| int k; | |||
| word32_t rt; | |||
| /* set x in Q14 in range [0.25,1[ */ | |||
| k = (18-countLeadingZeros(x))>>1; | |||
| x = VSHR32(x, (k<<1)); /* x = x.2^-2k */ | |||
| /* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */ | |||
| /* consider x as in Q14: y = x.2^(-2k-14) -> and give sqrt(y).2^14 = sqrt(x).2^(-k-7).2^14 */ | |||
| rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3))))))); /* rt = sqrt(x).2^(7-k)*/ | |||
| rt = VSHR32(rt,-k); /* rt = sqrt(x).2^7 */ | |||
| return rt; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* g729InvSqrt_Q0Q31 : Inverse Square root(1/Sqrt(x) */ | |||
| /* x is not tested to be >=1, shall be done by caller function */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 32 bits integer in Q0 in range [1, MAXINT32] */ | |||
| /* return value: */ | |||
| /* - 1/sqrt(x) in Q31 on 32 bits in range [43341/2^31, MAXINT32] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word32_t g729InvSqrt_Q0Q31(word32_t x) | |||
| { | |||
| if (x==1) return MAXINT32; | |||
| return (word32_t)(DIV32_32_Q24(g729Sqrt_Q0Q7(x),x)); /* sqrt(x) in Q7 + Q24 -> Q31 */ | |||
| } | |||
| /* constants Q0.15 */ | |||
| #define Kcos1 32768 | |||
| #define Kcos2 -16384 | |||
| #define Kcos3 1365 | |||
| #define Kcos4 -46 | |||
| #define Ksin1 32768 | |||
| #define Ksin2 -5461 | |||
| #define Ksin3 273 | |||
| #define Ksin4 -7 | |||
| /*****************************************************************************/ | |||
| /* g729Cos_Q13Q15 : Cosine fonction in [0, Pi] */ | |||
| /* x is not tested to be in correct range */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 16 bits integer in Q13 in range [0, Pi(25736)] */ | |||
| /* return value: */ | |||
| /* - cos(x) in Q0.15 on 16 bits in range [-1, 1[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word16_t g729Cos_Q13Q15(word16_t x) | |||
| { | |||
| /* input var x in Q2.13 and in ]0, Pi[ */ | |||
| word16_t x2,xScaled; | |||
| if (x<12868) { | |||
| if (x<6434) { /* x in ]0, Pi/4[ */ | |||
| x2 = MULT16_16_P11(x,x); /* in Q0.15 */ | |||
| return SATURATE(ADD32(Kcos1, MULT16_16_P15(x2, ADD32(Kcos2, MULT16_16_P15(x2, ADD32(Kcos3, MULT16_16_P15(Kcos4, x2)))))), MAXINT16); /* return cos x, must saturate if return value is +1 */ | |||
| } else {/* x in [Pi/4, Pi/2[ */ | |||
| x = SUB16(12868,x); /* x = pi/2 -x, x in [0, Pi/4] in Q0.13 */ | |||
| x2 = MULT16_16_P11(x,x); /* in Q0.15 */ | |||
| return (MULT16_16_P13(x,ADD32(Ksin1, MULT16_16_P15(x2, ADD32(Ksin2, MULT16_16_P15(x2, ADD32(Ksin3, MULT16_16_P15(Ksin4, x2)))))))); /* return cos x as sin(pi/2 -x) */ | |||
| } | |||
| } else { /* x in [Pi/2, Pi[ */ | |||
| xScaled = SUB16(25736,x); /* xScaled = Pi - x -> in [0,Pi/2] with cos(Pi-x) = -cos(x) and sin(Pi-x) = */ | |||
| if (x<19302) { /* x in [Pi/2, 3Pi/4], xScaled in [Pi/4, Pi/2] */ | |||
| xScaled = SUB16(12868,xScaled); /* xScaled = pi/2 - xScaled = x - Pi/2, xScaled in [0, Pi/4] in Q0.13 */ | |||
| x2 = MULT16_16_P11(xScaled,xScaled); /* in Q0.15 */ | |||
| return (MULT16_16_P13(-xScaled,ADD32(Ksin1, MULT16_16_P15(x2, ADD32(Ksin2, MULT16_16_P15(x2, ADD32(Ksin3, MULT16_16_P15(Ksin4, x2)))))))); /* return cos x as -sin(x - Pi/2) */ | |||
| } else { /* x in [3Pi/4, Pi[ -> xScaled in [0, Pi/4], cos(xScaled) = -cos(x) */ | |||
| x2 = MULT16_16_P11(xScaled,xScaled); /* in Q0.15 */ | |||
| return (SUB32(-Kcos1, MULT16_16_P15(x2, ADD32(Kcos2, MULT16_16_P15(x2, ADD32(Kcos3, MULT16_16_P15(Kcos4, x2))))))); /* return cos x as -cos(Pi -x) */ | |||
| } | |||
| } | |||
| } | |||
| /* KPI6 = pi/6 in Q15 */ | |||
| #define KPI6 17157 | |||
| /* KtanPI6 = tan(pi/6) in Q15 */ | |||
| #define KtanPI6 18919 | |||
| /* KtanPI12 = tan(pi/12) in Q15 */ | |||
| #define KtanPI12 8780 | |||
| /* B = 0.257977658811405 in Q15 */ | |||
| #define atanB 8453 | |||
| /* C = 0.59120450521312 in Q15 */ | |||
| #define atanC 19373 | |||
| /*****************************************************************************/ | |||
| /* g729Atan_Q15Q13: ArcTangent fonction in [-2^16, 2^16[ */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 32 bits integer in Q15 in range [-2^16, 2^16[ */ | |||
| /* return value: */ | |||
| /* - atan(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word16_t g729Atan_Q15Q13(word32_t x) | |||
| { | |||
| /* constants for rational polynomial */ | |||
| word32_t angle; | |||
| word16_t x2; | |||
| int highSegment = 0; | |||
| /* make argument positive */ | |||
| int sign = 0; | |||
| if (x < 0) { | |||
| x = NEG16(x); | |||
| sign = 1; | |||
| } | |||
| /* limit argument to 0..1 */ | |||
| int complement = 0; | |||
| if(x > ONE_IN_Q15){ | |||
| complement = 1; | |||
| x = DIV32(ONE_IN_Q30, x); /* 1/x in Q15 */ | |||
| } | |||
| /* determine segmentation */ | |||
| if(x > KtanPI12){ | |||
| highSegment = 1; | |||
| /* x = (x - k)/(1 + k*x); */ | |||
| x = DIV32(SHL(SUB32(x, KtanPI6), 15), ADD32(MULT16_16_Q15(KtanPI6, x), ONE_IN_Q15)); | |||
| } | |||
| /* argument is now < tan(15 degrees) */ | |||
| /* approximate the function */ | |||
| x2 = MULT16_16_Q15(x,x); | |||
| angle = DIV32(MULT16_16(x, ADD32(ONE_IN_Q15, MULT16_16_Q15(atanB, x2))), ADD32(ONE_IN_Q15, MULT16_16_Q15(atanC, x2))); /* ang = x*(1 + B*x2)/(1 + C*x2) */ | |||
| /* now restore offset if needed */ | |||
| if(highSegment) { | |||
| angle += KPI6; | |||
| } | |||
| /* restore complement if needed */ | |||
| if(complement) { | |||
| angle = SUB32(HALF_PI_Q15, angle); | |||
| } | |||
| /* set result in Q13 */ | |||
| angle = PSHR(angle, 2); | |||
| /* restore sign if needed */ | |||
| if(sign) { | |||
| return NEG16(angle); | |||
| } else { | |||
| return angle; | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| /* g729Asin_Q15Q13: ArcSine fonction */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 16 bits integer in Q15 in range ]-1, 1[ */ | |||
| /* return value: */ | |||
| /* - asin(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word16_t g729Asin_Q15Q13(word16_t x) | |||
| { | |||
| return g729Atan_Q15Q13(DIV32(SHL(x,15), PSHR(g729Sqrt_Q0Q7(SUB32(ONE_IN_Q30, MULT16_16(x,x))),7))); /* atan(x/sqrt(1.0 - x*x)) */ | |||
| } | |||
| /*****************************************************************************/ | |||
| /* g729Acos_Q15Q13: ArcCosine fonction */ | |||
| /* paremeters: */ | |||
| /* -(i) x : 16 bits integer in Q15 in range ]-1, 1[ */ | |||
| /* return value: */ | |||
| /* - acos(x) in Q2.13 on 16 bits in range ]0, Pi(25736)[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline word16_t g729Acos_Q15Q13(word16_t x) | |||
| { | |||
| return(HALF_PI_Q13 - g729Asin_Q15Q13(x)); | |||
| } | |||
| #endif /* ifndef G729FIXEDPOINTMATH_H */ | |||
| @ -0,0 +1,44 @@ | |||
| /* | |||
| gainQuantization.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef GAINQUANTIZATION_H | |||
| #define GAINQUANTIZATION_H | |||
| void initGainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* gainQuantization : compute quantized adaptative and fixed codebooks gains */ | |||
| /* spec 3.9 */ | |||
| /* parameters: */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) targetSignal: 40 values in Q0, x in eq63 */ | |||
| /* -(i) filteredAdaptativeCodebookVector: 40 values in Q0, y in eq63 */ | |||
| /* -(i) convolvedFixedCodebookVector: 40 values in Q12, z in eq63 */ | |||
| /* -(i) fixedCodebookVector: 40 values in Q13 */ | |||
| /* -(i) xy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* -(i) yy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* -(o) quantizedAdaptativeCodebookGain : in Q14 */ | |||
| /* -(o) quantizedFixedCodebookGain : in Q1 */ | |||
| /* -(o) gainCodebookStage1 : GA parameter value (3 bits) */ | |||
| /* -(o) gainCodebookStage2 : GB parameter value (4 bits) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word16_t convolvedFixedCodebookVector[], word16_t fixedCodebookVector[], word64_t Xy64, word64_t Yy64, | |||
| word16_t *quantizedAdaptativeCodebookGain, word16_t *quantizedFixedCodebookGain, uint16_t *gainCodebookStage1, uint16_t *gainCodebookStage2); | |||
| #endif /* ifndef GAINQUANTIZATION_H */ | |||
| @ -0,0 +1,33 @@ | |||
| /* | |||
| interpolateqLSP.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef INTERPOLATATEQLSP_H | |||
| #define INTERPOLATATEQLSP_H | |||
| /*****************************************************************************/ | |||
| /* interpolateqLSP : interpolate previous and current qLSP according to */ | |||
| /* spec. 3.2.5 : interpolated = (current+previous)/2 */ | |||
| /* parameters: */ | |||
| /* -(i) previousqLSP : 10 values in Q0.15: the qLSP of previous frame */ | |||
| /* -(i) currentqLSP : 10 values in Q0.15: the qLSP of current frame */ | |||
| /* -(o) interpolatedqLSP : 10 values in Q0.15 : the interpolated qLSP */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void interpolateqLSP(word16_t previousqLSP[], word16_t currentqLSP[], word16_t interpolatedqLSP[]); | |||
| #endif /* ifndef INTERPOLATATEQLSP_H */ | |||
| @ -0,0 +1,40 @@ | |||
| /* | |||
| postFilter.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef POSTFILTER_H | |||
| #define POSTFILTER_H | |||
| /* init function */ | |||
| void initPostFilter(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* postFilter: filter the reconstructed speech according to spec A.4.2 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) LPCoefficients: 10 LP coeff for current subframe in Q12 */ | |||
| /* -(i) reconstructedSpeech: output of LP Synthesis, 50 values in Q0 */ | |||
| /* 10 values of previous subframe, accessed in range [-10, 39] */ | |||
| /* -(i) intPitchDelay: the integer part of Pitch Delay in Q0 */ | |||
| /* -(i) subframeIndex: 0 or L_SUBFRAME for subframe 0 or 1 */ | |||
| /* -(o) postFilteredSignal: 40 values in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t *LPCoefficients, word16_t *reconstructedSpeech, int16_t intPitchDelay, int subframeIndex, | |||
| word16_t *postFilteredSignal); | |||
| #endif /* ifndef POSTFILTER_H */ | |||
| @ -0,0 +1,35 @@ | |||
| /* | |||
| postProcessing.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef POSTPROCESSING_H | |||
| #define POSTPROCESSING_H | |||
| void initPostProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* postProcessing : high pass filtering and upscaling Spec 4.2.5 */ | |||
| /* Algorithm: */ | |||
| /* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i/o) signal : 40 values in Q0, reconstructed speech, output */ | |||
| /* replaces the input in buffer */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void postProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t signal[]); | |||
| #endif /* ifndef POSTPROCESSING_H */ | |||
| @ -0,0 +1,37 @@ | |||
| /* | |||
| preProcessing.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef PREPROCESSING_H | |||
| #define PREPROCESSING_H | |||
| /* internal variable initialisations */ | |||
| void initPreProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* preProcessing : 2nd order highpass filter with cut off frequency at 140Hz */ | |||
| /* Algorithm: */ | |||
| /* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */ | |||
| /* parameters : */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) signal : 80 values in Q0 */ | |||
| /* -(o) preProcessedSignal : 80 values in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void preProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t signal[], word16_t preProcessedSignal[]); | |||
| #endif /* ifndef PREPROCESSING_H */ | |||
| @ -0,0 +1,31 @@ | |||
| /* | |||
| qLSP2LP.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef QLSP2LP_H | |||
| #define QLSP2LP_H | |||
| /*****************************************************************************/ | |||
| /* qLSP2LP : convert qLSP into LP parameters according to spec. 3.2.6 */ | |||
| /* parameters: */ | |||
| /* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */ | |||
| /* -(o) LP : 10 LP coefficients in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void qLSP2LP(word16_t qLSP[], word16_t LP[]); | |||
| #endif /* ifndef QLSP2LP_H */ | |||
| @ -0,0 +1,146 @@ | |||
| /* | |||
| typedef.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef TYPEDEF_H | |||
| #define TYPEDEF_H | |||
| #include <stdint.h> | |||
| #include "codecParameters.h" | |||
| #include "bcg729/encoder.h" | |||
| #include "bcg729/decoder.h" | |||
| typedef int16_t word16_t; | |||
| typedef uint16_t uword16_t; | |||
| typedef int32_t word32_t; | |||
| typedef uint32_t uword32_t; | |||
| typedef int64_t word64_t; | |||
| /* define the context structure to store all static data for a decoder channel */ | |||
| struct bcg729DecoderChannelContextStruct_struct { | |||
| /*** buffers used in decoder bloc ***/ | |||
| word16_t previousqLSP[NB_LSP_COEFF]; /* previous quantised LSP in Q0.15 */ | |||
| word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* in Q0 this vector contains: | |||
| 0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10) | |||
| 154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */ | |||
| word16_t boundedAdaptativeCodebookGain; /* the pitch gain from last subframe bounded in range [0.2,0.8] in Q0.14 */ | |||
| word16_t adaptativeCodebookGain; /* the gains needs to be stored in case of frame erasure in Q14 */ | |||
| word16_t fixedCodebookGain; /* in Q14.1 */ | |||
| word16_t reconstructedSpeech[NB_LSP_COEFF+L_FRAME]; /* in Q0, output of the LP synthesis filter, the first 10 words store the previous frame output */ | |||
| uint16_t pseudoRandomSeed; /* seed used in the pseudo random number generator */ | |||
| /*** buffers used in decodeLSP bloc ***/ | |||
| word16_t lastqLSF[NB_LSP_COEFF]; /* this buffer stores the last qLSF to be used in case of frame lost in Q2.13 */ | |||
| /* buffer to store the last 4 frames codewords, used to compute the current qLSF */ | |||
| word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF]; /* in Q2.13, buffer to store the last 4 frames codewords, used to compute the current qLSF */ | |||
| /* the values stored are the codewords computed from the codebooks and rearranged */ | |||
| word16_t lastValidL0; /* this one store the L0 of last valid frame to be used in case of frame erased */ | |||
| /*** buffer used in decodeAdaptativeCodeVector bloc ***/ | |||
| uint16_t previousIntPitchDelay; /* store the last valid Integer Pitch Delay computed, used in case of parity error or frame erased */ | |||
| /*** buffer used in decodeGains bloc ***/ | |||
| word16_t previousGainPredictionError[4]; /* the last four gain prediction error U(m) eq69 and eq72, spec3.9.1 in Q10*/ | |||
| /*** buffers used in postFilter bloc ***/ | |||
| word16_t residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* store the residual signal (current subframe and MAXIMUM_INT_PITCH_DELAY of previous values) in Q0 */ | |||
| word16_t scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* same as previous but in Q-2 */ | |||
| word16_t longTermFilteredResidualSignalBuffer[1+L_SUBFRAME]; /* the output of long term filter in Q0, need 1 word from previous subframe for tilt compensation filter */ | |||
| word16_t *longTermFilteredResidualSignal; /* points to the beginning of current subframe longTermFilteredResidualSignal */ | |||
| word16_t shortTermFilteredResidualSignalBuffer[NB_LSP_COEFF+L_SUBFRAME]; /* the output of short term filter(synthesis filter) in Q0, need NB_LSP_COEFF word from previous subframe as filter memory */ | |||
| word16_t *shortTermFilteredResidualSignal; /* points to the beginning of current subframe shortTermFilteredResidualSignal */ | |||
| word16_t previousAdaptativeGain; /* previous gain for adaptative gain control */ | |||
| /*** buffers used in postProcessing bloc ***/ | |||
| word16_t inputX0; | |||
| word16_t inputX1; | |||
| word32_t outputY2; | |||
| word32_t outputY1; | |||
| }; | |||
| /* define the context structure to store all static data for an encoder channel */ | |||
| struct bcg729EncoderChannelContextStruct_struct { | |||
| /*** buffers used in decoder bloc ***/ | |||
| /* Signal buffer mapping : 240 word16_t length */ | |||
| /* <---- 120 word16_t -->|<---- 80 word16_t ---->|<---- 40 word16_t --->| */ | |||
| /* |----- old signal -----|----------- current frame -------------------|-----next subframe 1 ------------| */ | |||
| /* |----- subframe 1 -----|----- subframe 2 -----| */ | |||
| /* |--------------- last input frame -----------------------| */ | |||
| /* ^ ^ ^ */ | |||
| /* | | | */ | |||
| /* signalBuffer signalCurrentFrame signalLastInputFrame */ | |||
| word16_t signalBuffer[L_LP_ANALYSIS_WINDOW]; /* this buffer stores the input signal */ | |||
| word16_t *signalLastInputFrame; /* point to the beginning of the last frame in the signal buffer */ | |||
| word16_t *signalCurrentFrame; /* point to the beginning of the current frame in the signal buffer */ | |||
| word16_t previousLSPCoefficients[NB_LSP_COEFF]; /* LSP coefficient of previous frame */ | |||
| word16_t previousqLSPCoefficients[NB_LSP_COEFF]; /* Quantized LSP coefficient of previous frame */ | |||
| word16_t weightedInputSignal[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* buffer storing the weightedInputSignal on current frame and MAXIMUM_INT_PITCH_DELAY of previous values */ | |||
| word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* in Q0 this vector contains: | |||
| 0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10) | |||
| 154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */ | |||
| word16_t targetSignal[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, buffer holding the target signal (x[n]) as in spec A.3.6, the first NB_LSP_COEFF values are memory from previous subframe used in filtering(computed according to spec A.3.10), the following values are the target signal for current subframe */ | |||
| word16_t lastQuantizedAdaptativeCodebookGain; /* in Q14, the quantized adaptive codebook gain from previous subframe */ | |||
| /*** buffer used in preProcessing ***/ | |||
| word16_t inputX0, inputX1; | |||
| word32_t outputY2, outputY1; | |||
| /*** buffer used in LSPQuantization ***/ | |||
| word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF]; /* previousqLSF of the last 4(MA pred buffer size) frames in Q13, contains actually quantizer output (l) and not LSF (w)*/ | |||
| /*** buffer used in gainQuantization ***/ | |||
| word16_t previousGainPredictionError[4]; /* the last four gain prediction error U(m) eq69 and eq72, spec3.9.1 in Q10*/ | |||
| }; | |||
| /* MAXINTXX define the maximum signed integer value on XX bits(2^(XX-1) - 1) */ | |||
| /* used to check on overflows in fixed point mode */ | |||
| #define MAXINT16 0x7fff | |||
| #define MAXINT28 0x7ffffff | |||
| #define MAXINT29 0xfffffff | |||
| #define MININT32 0x80000000 | |||
| #define MAXINT32 0x7fffffff | |||
| #define MAXINT64 0x7fffffffffffffffLL | |||
| /* several values used for inits */ | |||
| #define ONE_IN_Q31 0x7FFFFFFF | |||
| #define ONE_IN_Q30 0x40000000 | |||
| #define ONE_IN_Q27 0x08000000 | |||
| #define ONE_IN_Q15 0x00008000 | |||
| #define ONE_IN_Q13 0x00002000 | |||
| #define ONE_IN_Q12 0x00001000 | |||
| #define ONE_IN_Q11 0x00000800 | |||
| #define HALF_PI_Q13 12868 | |||
| #define HALF_PI_Q15 51472 | |||
| /* 0.04*Pi + 1 and 0.92*Pi - 1 used by LSPQuantization */ | |||
| #define OO4PIPLUS1_IN_Q13 9221 | |||
| #define O92PIMINUS1_IN_Q13 15485 | |||
| /* 1.2 in Q14 */ | |||
| #define ONE_POINT_2_IN_Q14 19661 | |||
| /* 0.7 in Q12 */ | |||
| #define O7_IN_Q12 2867 | |||
| /* 0.2 in Q14 */ | |||
| #define O2_IN_Q14 3277 | |||
| /* 0.2 in Q15 */ | |||
| #define O2_IN_Q15 6554 | |||
| #endif /* ifndef TYPEDEF_H */ | |||
| @ -0,0 +1,163 @@ | |||
| /* | |||
| utils.h | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #ifndef UTILS_H | |||
| #define UTILS_H | |||
| /*****************************************************************************/ | |||
| /* insertionSort : sort an array in growing order using insertion algorithm */ | |||
| /* parameters : */ | |||
| /* -(i/o) x: the array to be sorted */ | |||
| /* -(i) length: the array length */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void insertionSort(word16_t x[], int length); | |||
| /*****************************************************************************/ | |||
| /* computeParity : compute parity for pitch delay adaptative codebook index */ | |||
| /* XOR of the 6 MSB (pitchDelay on 8 bits) */ | |||
| /* parameters : */ | |||
| /* -(i) adaptativeCodebookIndex: the pitch delay on 8 bits */ | |||
| /* return value : */ | |||
| /* the parity bit */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| uint16_t computeParity(uint16_t adaptativeCodebookIndex); | |||
| /*****************************************************************************/ | |||
| /* rearrangeCoefficients: rearrange coefficients according to spec 3.2.4 */ | |||
| /* Have a minimum distance of J beetwen two consecutive coefficients */ | |||
| /* parameters: */ | |||
| /* -(i/o) qLSP: 10 ordered coefficients in Q13 replaced by new values */ | |||
| /* if needed */ | |||
| /* -(i) J: minimum distance between coefficients in Q0.13 (10 or 5) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void rearrangeCoefficients(word16_t qLSP[], word16_t J); | |||
| /*****************************************************************************/ | |||
| /* synthesisFilter : compute 1/[A(z)] using the following algorithm */ | |||
| /* filteredSignal[n] = inputSignal[n] */ | |||
| /* - Sum(i=1..10)filterCoefficients[i]*filteredSignal[n-i] */ | |||
| /* for n in [0, L_SUBFRAME[ */ | |||
| /* parameters: */ | |||
| /* -(i) inputSignal: 40 values in Q0 */ | |||
| /* -(i) filterCoefficients: 10 coefficients in Q12 */ | |||
| /* -(i/o) filteredSignal: 50 values in Q0 accessed in ranges [-10,-1] */ | |||
| /* as input and [0, 39] as output. */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void synthesisFilter(word16_t inputSignal[], word16_t filterCoefficients[], word16_t filteredSignal[]); | |||
| /*****************************************************************************/ | |||
| /* correlateVectors : compute the correlations between two vectors of */ | |||
| /* L_SUBFRAME length: c[i] = Sum(x[j]*y[j-i]) j in [i..L_SUBFRAME] */ | |||
| /* parameters: */ | |||
| /* -(i) x : L_SUBFRAME length input vector on 16 bits */ | |||
| /* -(i) y : L_SUBFRAME length input vector on 16 bits */ | |||
| /* -(o) c : L_SUBFRAME length output vector on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void correlateVectors (word16_t x[], word16_t y[], word32_t c[]); | |||
| /*****************************************************************************/ | |||
| /* countLeadingZeros : return the number of zero heading the argument */ | |||
| /* MSB is excluded as considered sign bit. */ | |||
| /* May be replaced by one asm instruction. */ | |||
| /* parameters : */ | |||
| /* -(i) x : 32 bits values >= 0 (no checking done by this function) */ | |||
| /* return value : */ | |||
| /* - number of heading zeros(MSB excluded. Ex: 0x0080 00000 returns 7) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static inline uint16_t countLeadingZeros(word32_t x) | |||
| { | |||
| if (x==0) return 31; | |||
| uint16_t leadingZeros = 0; | |||
| while (x<(word32_t)0x40000000) { | |||
| leadingZeros++; | |||
| x <<=1; | |||
| } | |||
| return leadingZeros; | |||
| } | |||
| /*** gain related functions ***/ | |||
| /*****************************************************************************/ | |||
| /* MACodeGainPrediction : spec 3.9.1 */ | |||
| /* parameters: */ | |||
| /* -(i) previousGainPredictionError: qU(m) in eq69 4 values in Q10 */ | |||
| /* -(i) fixedCodebookVector: the current subframe fixed codebook vector */ | |||
| /* 40 values in Q1.13 */ | |||
| /* return value : */ | |||
| /* - predicted Fixed Codebook gain on 32 bits in Q16 range [3, 1830] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *fixedCodebookVector); | |||
| /*****************************************************************************/ | |||
| /* computeGainPredictionError : apply eq72 to compute current fixed Codebook */ | |||
| /* gain prediction error and store the result in the adhoc array */ | |||
| /* parameters : */ | |||
| /* -(i) fixedCodebookGainCorrectionFactor: gamma in eq72 in Q3.12 */ | |||
| /* -(i/o) previousGainPredictionError: array to be updated in Q10 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeGainPredictionError(word16_t fixedCodebookGainCorrectionFactor, word16_t *previousGainPredictionError); | |||
| /*** bitStream to parameters Array conversions functions ***/ | |||
| /* Note: these functions are in utils.c because used by test source code too */ | |||
| /*****************************************************************************/ | |||
| /* parametersArray2BitStream : convert array of parameters to bitStream */ | |||
| /* according to spec 4 - Table 8 and following mapping of values */ | |||
| /* 0 -> L0 (1 bit) */ | |||
| /* 1 -> L1 (7 bits) */ | |||
| /* 2 -> L2 (5 bits) */ | |||
| /* 3 -> L3 (5 bits) */ | |||
| /* 4 -> P1 (8 bit) */ | |||
| /* 5 -> P0 (1 bits) */ | |||
| /* 6 -> C1 (13 bits) */ | |||
| /* 7 -> S1 (4 bits) */ | |||
| /* 8 -> GA1(3 bits) */ | |||
| /* 9 -> GB1(4 bits) */ | |||
| /* 10 -> P2 (5 bits) */ | |||
| /* 11 -> C2 (13 bits) */ | |||
| /* 12 -> S2 (4 bits) */ | |||
| /* 13 -> GA2(3 bits) */ | |||
| /* 14 -> GB2(4 bits) */ | |||
| /* parameters: */ | |||
| /* -(i) parameters : 16 values parameters array */ | |||
| /* -(o) bitStream : the 16 values streamed on 80 bits in a */ | |||
| /* 10*8bits values array */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void parametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]); | |||
| /*****************************************************************************/ | |||
| /* parametersArray2BitStream : convert bitStream to an array of parameters */ | |||
| /* reverse operation of previous funtion */ | |||
| /* parameters: */ | |||
| /* -(i) bitStream : the 16 values streamed on 80 bits in a */ | |||
| /* 10*8bits values array */ | |||
| /* -(o) parameters : 16 values parameters array */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void parametersBitStream2Array(uint8_t bitStream[], uint16_t parameters[]); | |||
| #endif /* ifndef UTILS_H */ | |||
| @ -0,0 +1,10 @@ | |||
| # This is a comment | |||
| prefix=@prefix@ | |||
| exec_prefix=@exec_prefix@ | |||
| includedir=@includedir@ | |||
| Name: libbcg729 | |||
| Description: Implement the ITU G729 speech codec. | |||
| Version: @PACKAGE_VERSION@ | |||
| Libs: -L@libdir@ -lbcg729 | |||
| Cflags: -I@includedir@ | |||
| @ -0,0 +1,18 @@ | |||
| pluginsdir = $(libdir)/mediastreamer/plugins | |||
| plugins_LTLIBRARIES=libmsbcg729.la | |||
| libmsbcg729_la_SOURCES=bcg729_dec.c bcg729_enc.c | |||
| libmsbcg729_la_LIBADD=\ | |||
| $(ORTP_LIBS) \ | |||
| $(MEDIASTREAMER_LIBS) \ | |||
| $(top_builddir)/src/libbcg729.la | |||
| libmsbcg729_la_LDFLAGS=-module -no-undefined | |||
| INCLUDES = -I$(top_srcdir)/include | |||
| libmsbcg729_la_CFLAGS= $(ORTP_CFLAGS) $(MEDIASTREMER2_CFLAGS) | |||
| @ -0,0 +1,106 @@ | |||
| /* | |||
| bcg729_dec.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Jehan Monnier | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "mediastreamer2/mscodecutils.h" | |||
| #include "mediastreamer2/msfilter.h" | |||
| #include "mediastreamer2/msticker.h" | |||
| #include "bcg729/decoder.h" | |||
| /* signal and bitstream frame size in byte */ | |||
| #define SIGNAL_FRAME_SIZE 160 | |||
| #define BITSTREAM_FRAME_SIZE 10 | |||
| /* decoder struct: context for decoder channel and concealment */ | |||
| struct bcg729Decoder_struct { | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext; | |||
| MSConcealerContext *concealer; | |||
| }; | |||
| static void filter_init(MSFilter *f){ | |||
| f->data = ms_new0(struct bcg729Decoder_struct,1); | |||
| } | |||
| static void filter_preprocess(MSFilter *f){ | |||
| struct bcg729Decoder_struct* obj= (struct bcg729Decoder_struct*) f->data; | |||
| obj->decoderChannelContext = initBcg729DecoderChannel(); /* initialize bcg729 decoder, return channel context */ | |||
| obj->concealer = ms_concealer_context_new(UINT32_MAX); | |||
| } | |||
| static void filter_process(MSFilter *f){ | |||
| struct bcg729Decoder_struct* obj= (struct bcg729Decoder_struct*) f->data; | |||
| mblk_t *inputMessage, *outputMessage; | |||
| while((inputMessage=ms_queue_get(f->inputs[0]))) { | |||
| while(inputMessage->b_rptr<inputMessage->b_wptr) { | |||
| outputMessage = allocb(SIGNAL_FRAME_SIZE,0); | |||
| bcg729Decoder(obj->decoderChannelContext, inputMessage->b_rptr, 0, (int16_t *)(outputMessage->b_wptr)); | |||
| outputMessage->b_wptr+=SIGNAL_FRAME_SIZE; | |||
| inputMessage->b_rptr+=BITSTREAM_FRAME_SIZE; | |||
| ms_queue_put(f->outputs[0],outputMessage); | |||
| ms_concealer_inc_sample_time(obj->concealer,f->ticker->time,10, 1); | |||
| } | |||
| freemsg(inputMessage); | |||
| } | |||
| if (ms_concealer_context_is_concealement_required(obj->concealer, f->ticker->time)) { | |||
| outputMessage = allocb(SIGNAL_FRAME_SIZE,0); | |||
| bcg729Decoder(obj->decoderChannelContext, NULL, 1, (int16_t *)(outputMessage->b_wptr)); | |||
| outputMessage->b_wptr+=SIGNAL_FRAME_SIZE; | |||
| ms_queue_put(f->outputs[0],outputMessage); | |||
| ms_concealer_inc_sample_time(obj->concealer,f->ticker->time,10, 0); | |||
| } | |||
| } | |||
| static void filter_postprocess(MSFilter *f){ | |||
| struct bcg729Decoder_struct* obj= (struct bcg729Decoder_struct*) f->data; | |||
| ms_concealer_context_destroy(obj->concealer); | |||
| closeBcg729DecoderChannel(obj->decoderChannelContext); | |||
| } | |||
| static void filter_uninit(MSFilter *f){ | |||
| ms_free(f->data); | |||
| } | |||
| /*filter specific method*/ | |||
| static MSFilterMethod filter_methods[]={ | |||
| { 0, NULL} | |||
| }; | |||
| MSFilterDesc ms_bcg729_dec_desc={ | |||
| .id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/ | |||
| .name="MSBCG729Dec", | |||
| .text="G729 decoder filter.", | |||
| .category=MS_FILTER_DECODER, | |||
| .enc_fmt="G729", | |||
| .ninputs=1, /*number of inputs*/ | |||
| .noutputs=1, /*number of outputs*/ | |||
| .init=filter_init, | |||
| .preprocess=filter_preprocess, | |||
| .process=filter_process, | |||
| .postprocess=filter_postprocess, | |||
| .uninit=filter_uninit, | |||
| .methods=filter_methods, | |||
| .flags=MS_FILTER_IS_PUMP | |||
| }; | |||
| MS_FILTER_DESC_EXPORT(ms_bcg729_dec_desc) | |||
| @ -0,0 +1,148 @@ | |||
| /* | |||
| bcg729_enc.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Jehan Monnier | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "mediastreamer2/msfilter.h" | |||
| #include "mediastreamer2/mscodecutils.h" | |||
| #include "bcg729/encoder.h" | |||
| /*filter common method*/ | |||
| struct bcg729Encoder_struct { | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext; | |||
| MSBufferizer *bufferizer; | |||
| unsigned char ptime; | |||
| unsigned char max_ptime; | |||
| uint32_t ts; | |||
| }; | |||
| static void filter_init(MSFilter *f){ | |||
| f->data = ms_new0(struct bcg729Encoder_struct,1); | |||
| struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data; | |||
| obj->ptime=20; | |||
| obj->max_ptime=100; | |||
| } | |||
| static void filter_preprocess(MSFilter *f){ | |||
| struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data; | |||
| obj->encoderChannelContext = initBcg729EncoderChannel(); /* initialize bcg729 encoder, return context */ | |||
| obj->bufferizer=ms_bufferizer_new(); | |||
| } | |||
| static void filter_process(MSFilter *f){ | |||
| struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data; | |||
| mblk_t *inputMessage; | |||
| mblk_t *outputMessage=NULL; | |||
| uint8_t inputBuffer[160]; /* 2bytes per sample at 8000Hz -> 16 bytes per ms */ | |||
| uint8_t bufferIndex=0; | |||
| /* get all input data into a buffer */ | |||
| while((inputMessage=ms_queue_get(f->inputs[0]))!=NULL){ | |||
| ms_bufferizer_put(obj->bufferizer,inputMessage); | |||
| } | |||
| /* process ptimes ms of data : (ptime in ms)/1000->ptime is seconds * 8000(sample rate) * 2(byte per sample) */ | |||
| while(ms_bufferizer_get_avail(obj->bufferizer)>=obj->ptime*16){ | |||
| outputMessage = allocb(obj->ptime,0); /* output bitStream is 80 bits long * number of samples */ | |||
| /* process buffer in 10 ms frames */ | |||
| for (bufferIndex=0; bufferIndex<obj->ptime; bufferIndex+=10) { | |||
| ms_bufferizer_read(obj->bufferizer,inputBuffer,160); | |||
| bcg729Encoder(obj->encoderChannelContext, (int16_t *)inputBuffer, outputMessage->b_wptr); | |||
| outputMessage->b_wptr+=10; | |||
| } | |||
| obj->ts+=obj->ptime*8; | |||
| mblk_set_timestamp_info(outputMessage,obj->ts); | |||
| ms_queue_put(f->outputs[0],outputMessage); | |||
| } | |||
| } | |||
| static void filter_postprocess(MSFilter *f){ | |||
| struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data; | |||
| ms_bufferizer_destroy(obj->bufferizer); | |||
| closeBcg729EncoderChannel(obj->encoderChannelContext); | |||
| } | |||
| static void filter_uninit(MSFilter *f){ | |||
| ms_free(f->data); | |||
| } | |||
| /*filter specific method*/ | |||
| static int filter_add_fmtp(MSFilter *f, void *arg){ | |||
| char buf[64]; | |||
| struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data; | |||
| const char *fmtp=(const char *)arg; | |||
| buf[0] ='\0'; | |||
| if (fmtp_get_value(fmtp,"maxptime:",buf,sizeof(buf))){ | |||
| obj->max_ptime=atoi(buf); | |||
| if (obj->max_ptime <10 || obj->max_ptime >100 ) { | |||
| ms_warning("MSBCG729Enc: unknown value [%i] for maxptime, use default value (100) instead",obj->max_ptime); | |||
| obj->max_ptime=100; | |||
| } | |||
| ms_message("MSBCG729Enc: got maxptime=%i",obj->max_ptime); | |||
| } else if (fmtp_get_value(fmtp,"ptime",buf,sizeof(buf))){ | |||
| obj->ptime=atoi(buf); | |||
| if (obj->ptime > obj->max_ptime) { | |||
| obj->ptime=obj->max_ptime; | |||
| } else if (obj->ptime%10) { | |||
| //if the ptime is not a mulptiple of 10, go to the next multiple | |||
| obj->ptime = obj->ptime - obj->ptime%10 + 10; | |||
| } | |||
| ms_message("MSBCG729Enc: got ptime=%i",obj->ptime); | |||
| } | |||
| return 0; | |||
| } | |||
| static MSFilterMethod filter_methods[]={ | |||
| { MS_FILTER_ADD_FMTP , filter_add_fmtp }, | |||
| { 0, NULL} | |||
| }; | |||
| MSFilterDesc ms_bcg729_enc_desc={ | |||
| .id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/ | |||
| .name="MSBCG729Enc", | |||
| .text="G729 audio encoder filter.", | |||
| .category=MS_FILTER_ENCODER, | |||
| .enc_fmt="G729", | |||
| .ninputs=1, /*number of inputs*/ | |||
| .noutputs=1, /*number of outputs*/ | |||
| .init=filter_init, | |||
| .preprocess=filter_preprocess, | |||
| .process=filter_process, | |||
| .postprocess=filter_postprocess, | |||
| .uninit=filter_uninit, | |||
| .methods=filter_methods | |||
| }; | |||
| MS_FILTER_DESC_EXPORT(ms_bcg729_enc_desc) | |||
| extern MSFilterDesc ms_bcg729_dec_desc; | |||
| #ifndef VERSION | |||
| #define VERSION "debug" | |||
| #endif | |||
| void libmsbcg729_init(){ | |||
| ms_filter_register(&ms_bcg729_enc_desc); | |||
| ms_filter_register(&ms_bcg729_dec_desc); | |||
| ms_message(" libmsbcg729 " VERSION " plugin loaded"); | |||
| } | |||
| @ -0,0 +1,162 @@ | |||
| /* | |||
| LP2LSPConversion.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "LP2LSPConversion.h" | |||
| /* local functions and codebook */ | |||
| word32_t ChebyshevPolynomial(word16_t x, word32_t f[]); /* return value in Q24 */ | |||
| static const word16_t cosW0pi[NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL]; /* cos(w) from 0 to Pi in 50 steps */ | |||
| /*****************************************************************************/ | |||
| /* LP2LSPConversion : Compute polynomials, find their roots as in spec A3.2.3*/ | |||
| /* parameters: */ | |||
| /* -(i) LPCoefficients[] : 10 coefficients in Q12 */ | |||
| /* -(o) LSPCoefficients[] : 10 coefficients in Q15 */ | |||
| /* */ | |||
| /* return value : */ | |||
| /* - boolean: 1 if all roots found, 0 if unable to compute 10 roots */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[]) | |||
| { | |||
| uint8_t i; | |||
| /*** Compute the polynomials coefficients according to spec 3.2.3 eq15 ***/ | |||
| word32_t f1[6]; | |||
| word32_t f2[6]; /* coefficients for polynomials F1 anf F2 in Q12 for computation, then converted in Q15 for the Chebyshev Polynomial function */ | |||
| f1[0] = ONE_IN_Q12; /* values 0 are not part of the output, they are just used for computation purpose */ | |||
| f2[0] = ONE_IN_Q12; | |||
| /* for (i = 0; i< 5; i++) { */ | |||
| /* f1[i+1] = a[i+1] + a[10-i] - f1[i]; */ | |||
| /* f2[i+1] = a[i+1] - a[10-i] + f2[i]; */ | |||
| /* } */ | |||
| for (i=0; i<5; i++) { | |||
| f1[i+1] = ADD32(LPCoefficients[i], SUB32(LPCoefficients[9-i], f1[i])); /* note: index on LPCoefficients are -1 respect to spec because the unused value 0 is not stored */ | |||
| f2[i+1] = ADD32(f2[i], SUB32(LPCoefficients[i], LPCoefficients[9-i])); /* note: index on LPCoefficients are -1 respect to spec because the unused value 0 is not stored */ | |||
| } | |||
| /* convert the coefficients from Q12 to Q15 to be used by the Chebyshev Polynomial function (f1/2[0] aren't used so they are not converted) */ | |||
| for (i=1; i<6; i++) { | |||
| f1[i] = SHL(f1[i], 3); | |||
| f2[i] = SHL(f2[i], 3); | |||
| } | |||
| /*** Compute at each step(50 steps for the AnnexA version) the Chebyshev polynomial to find the 10 roots ***/ | |||
| /* start using f1 polynomials coefficients and altern with f2 after founding each root (spec 3.2.3 eq13 and eq14) */ | |||
| uint8_t numberOfRootFound = 0; /* used to check the final number of roots found and exit the loop on each polynomial computation when we have 10 roots */ | |||
| word32_t *polynomialCoefficients = f1; /* start with f1 coefficients */ | |||
| word32_t previousCx = ChebyshevPolynomial(cosW0pi[0], polynomialCoefficients); /* compute the first point and store it as the previous value for polynomial */ | |||
| word32_t Cx; /* value of Chebyshev Polynomial at current point in Q15 */ | |||
| for (i=1; i<NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL; i++) { | |||
| Cx = ChebyshevPolynomial(cosW0pi[i], polynomialCoefficients); | |||
| if ((previousCx^Cx)&0x10000000) { /* check signe change by XOR on the value of first bit */ | |||
| /* divide 2 times the interval to find a more accurate root */ | |||
| uint8_t j; | |||
| word16_t xLow = cosW0pi[i-1]; | |||
| word16_t xHigh = cosW0pi[i]; | |||
| word16_t xMean; | |||
| for (j=0; j<2; j++) { | |||
| xMean = (word16_t)SHR(ADD32(xLow, xHigh), 1); | |||
| word32_t middleCx = ChebyshevPolynomial(xMean, polynomialCoefficients); /* compute the polynome for the value in the middle of current interval */ | |||
| if ((previousCx^middleCx)&0x10000000) { /* check signe change by XOR on the value of first bit */ | |||
| xHigh = xMean; | |||
| Cx = middleCx; /* used for linear interpolation on root */ | |||
| } else { | |||
| xLow = xMean; | |||
| previousCx = middleCx; | |||
| } | |||
| } | |||
| /* toggle the polynomial coefficients in use between f1 and f2 */ | |||
| if (polynomialCoefficients==f1) { | |||
| polynomialCoefficients = f2; | |||
| } else { | |||
| polynomialCoefficients = f1; | |||
| } | |||
| /* linear interpolation for better root accuracy */ | |||
| /* xMean = xLow - (xHigh-xLow)* previousCx/(Cx-previousCx); */ | |||
| xMean = (word16_t)SUB32(xLow, MULT16_32_Q15(SUB32(xHigh, xLow), DIV32(SHL(previousCx, 14), SHR(SUB32(Cx, previousCx), 1)))); /* Cx are in Q2.15 so we can shift them left 14 bits, the denominator is shifted righ by 1 so the division result is in Q15 */ | |||
| /* recompute previousCx with the new coefficients */ | |||
| previousCx = ChebyshevPolynomial(xMean, polynomialCoefficients); | |||
| LSPCoefficients[numberOfRootFound] = xMean; | |||
| numberOfRootFound++; | |||
| if (numberOfRootFound == NB_LSP_COEFF) break; /* exit the for loop as soon as we habe all the LSP*/ | |||
| } | |||
| } | |||
| if (numberOfRootFound != NB_LSP_COEFF) return 0; /* we were not able to find the 10 roots */ | |||
| return 1; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* ChebyshevPolynomial : Compute the Chebyshev polynomial, spec 3.2.3 eq17 */ | |||
| /* parameters: */ | |||
| /* -(i) x : input value of polynomial function in Q15 */ | |||
| /* -(i) f : the polynome coefficients, 6 values in Q15 on 32 bits */ | |||
| /* f[0] is not used */ | |||
| /* return value : */ | |||
| /* - result of polynomial function in Q15 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word32_t ChebyshevPolynomial(word16_t x, word32_t f[]) | |||
| { | |||
| /* bk in Q15*/ | |||
| word32_t bk; | |||
| word32_t bk1 = ADD32(SHL(x,1), f[1]); /* init: b4=2x+f1 */ | |||
| word32_t bk2 = ONE_IN_Q15; /* init: b5=1 */ | |||
| uint8_t k; | |||
| for (k=3; k>0; k--) { /* at the end of loop execution we have b1 in bk1 and b2 in bk2 */ | |||
| bk = SUB32(ADD32(SHL(MULT16_32_Q15(x,bk1), 1), f[5-k]), bk2); /* bk = 2*x*bk1 − bk2 + f(5-k) all in Q15*/ | |||
| bk2 = bk1; | |||
| bk1 = bk; | |||
| } | |||
| return SUB32(ADD32(MULT16_32_Q15(x,bk1), SHR(f[5],1)), bk2); /* C(x) = x*b1 - b2 + f(5)/2 */ | |||
| } | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Codebook: */ | |||
| /* */ | |||
| /* x = cos(w) with w in [0,Pi] in 50 steps */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| static const word16_t cosW0pi[NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL] = { /* in Q15 */ | |||
| 32760, 32703, 32509, 32187, 31738, 31164, | |||
| 30466, 29649, 28714, 27666, 26509, 25248, | |||
| 23886, 22431, 20887, 19260, 17557, 15786, | |||
| 13951, 12062, 10125, 8149, 6140, 4106, | |||
| 2057, 0, -2057, -4106, -6140, -8149, | |||
| -10125, -12062, -13951, -15786, -17557, -19260, | |||
| -20887, -22431, -23886, -25248, -26509, -27666, | |||
| -28714, -29649, -30466, -31164, -31738, -32187, | |||
| -32509, -32703, -32760}; | |||
| @ -0,0 +1,49 @@ | |||
| /* | |||
| LPSynthesisFilter.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| /*****************************************************************************/ | |||
| /* LPSynthesisFilter : as decribed in spec 4.1.6 eq77 */ | |||
| /* parameters: */ | |||
| /* -(i) excitationVector: u(n), the excitation, 40 values in Q0 */ | |||
| /* -(i) LPCoefficients: 10 LP coefficients in Q12 */ | |||
| /* -(i/o) recontructedSpeech: 50 values in Q0 */ | |||
| /* [-NB_LSP_COEFF, -1] of previous values as input */ | |||
| /* [0, L_SUBFRAME[ as output */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void LPSynthesisFilter (word16_t *excitationVector, word16_t *LPCoefficients, word16_t *reconstructedSpeech) | |||
| { | |||
| int i; | |||
| /* compute excitationVector[i] - Sum0-9(LPCoefficients[j]*reconstructedSpeech[i-j]) */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| word32_t acc = SHL(excitationVector[i],12); /* acc get the first term of the sum, in Q12 (excitationVector is in Q0)*/ | |||
| int j; | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| acc = MSU16_16(acc, LPCoefficients[j], reconstructedSpeech[i-j-1]); | |||
| } | |||
| reconstructedSpeech[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift right acc to get it back in Q0 and check overflow on 16 bits */ | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,264 @@ | |||
| /* | |||
| LSPQuantization.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "g729FixedPointMath.h" | |||
| #include "codebooks.h" | |||
| #include "LSPQuantization.h" | |||
| #include "string.h" | |||
| /* static buffers */ | |||
| word16_t previousqLSFInit[NB_LSP_COEFF] = {2339, 4679, 7018, 9358, 11698, 14037, 16377, 18717, 21056, 23396}; /* PI*(float)(j+1)/(float)(M+1) */ | |||
| /* initialise the stactic buffers */ | |||
| void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext) | |||
| { | |||
| int i; | |||
| for (i=0; i<MA_MAX_K; i++) { | |||
| memcpy(encoderChannelContext->previousqLSF[i], previousqLSFInit, NB_LSP_COEFF*sizeof(word16_t)); | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* LSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */ | |||
| /* qLSF->qLSP as described in spec A3.2.4 */ | |||
| /* parameters: */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */ | |||
| /* -(i) qLSPCoefficients : 10 qLSP coefficients in Q15 */ | |||
| /* -(o) parameters : 4 parameters L0, L1, L2, L3 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[]) | |||
| { | |||
| int i,j; | |||
| /*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/ | |||
| word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| LSF[i] = g729Acos_Q15Q13(LSPCoefficients[i]); | |||
| } | |||
| /*** compute the weights vector as in spec 3.2.4 eq22 ***/ | |||
| word16_t weights[NB_LSP_COEFF]; /* weights in Q11 */ | |||
| word16_t weightsThreshold[NB_LSP_COEFF]; /* store in Q13 the threshold used to compute the weights */ | |||
| weightsThreshold[0] = SUB16(LSF[1], OO4PIPLUS1_IN_Q13); | |||
| for (i=1; i<NB_LSP_COEFF-1; i++) { | |||
| weightsThreshold[i] = SUB16(SUB16(LSF[i+1], LSF[i-1]), ONE_IN_Q13); | |||
| } | |||
| weightsThreshold[NB_LSP_COEFF-1] = SUB16(O92PIMINUS1_IN_Q13, LSF[NB_LSP_COEFF-2]); | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| if (weightsThreshold[i]>0) { | |||
| weights[i] = ONE_IN_Q11; | |||
| } else { | |||
| weights[i] = (word16_t)SATURATE(ADD32(PSHR(MULT16_16(MULT16_16_Q13(weightsThreshold[i], weightsThreshold[i]), 10), 2), ONE_IN_Q11), MAXINT16); | |||
| } | |||
| } | |||
| weights[4] = MULT16_16_Q14(weights[4], ONE_POINT_2_IN_Q14); | |||
| weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14); | |||
| /*** compute the coefficients for the two MA Predictors ***/ | |||
| int L0; | |||
| word32_t weightedMeanSquareError[L0_RANGE]; | |||
| word16_t L1index[L0_RANGE]; | |||
| word16_t L2index[L0_RANGE]; | |||
| word16_t L3index[L0_RANGE]; | |||
| for (L0=0; L0<L0_RANGE; L0++) { | |||
| /* compute the target Vector (l) to be quantized as in spec 3.2.4 eq23 */ | |||
| word16_t targetVector[NB_LSP_COEFF]; /* vector to be quantized in Q13 */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| word32_t acc = SHL(LSF[i],15); /* acc in Q2.28 */ | |||
| for (j=0; j<MA_MAX_K; j++) { | |||
| acc = MSU16_16(acc, encoderChannelContext->previousqLSF[j][i], MAPredictor[L0][j][i]); /* previousqLSF in Q2.13 and MAPredictor in Q0.15-> acc in Q2.28 */ | |||
| } | |||
| targetVector[i] = MULT16_16_Q12((word16_t)PSHR(acc, 15), invMAPredictorSum[L0][i]); /* acc->Q13 and invMAPredictorSum in Q12 -> targetVector in Q13 */ | |||
| } | |||
| /* find closest match for predictionError (minimize mean square diff) in L1 codebook */ | |||
| word32_t meanSquareDiff = MAXINT32; | |||
| for (i=0; i<L1_RANGE; i++) { | |||
| word32_t acc = 0; | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| word16_t difftargetVectorL1 = SATURATE(SUB32(targetVector[j], L1[i][j]), MAXINT16); | |||
| acc = MAC16_16(acc, difftargetVectorL1, difftargetVectorL1); | |||
| } | |||
| if (acc<meanSquareDiff) { | |||
| meanSquareDiff = acc; | |||
| L1index[L0] = i; | |||
| } | |||
| } | |||
| /* find the closest match in L2 wich will minimise the weighted sum of (targetVector - L1 result - L2)^2 */ | |||
| /* using eq20, eq21 and eq23 in spec 3.2.4 -> l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */ | |||
| /* works on the first five coefficients only */ | |||
| meanSquareDiff = MAXINT32; | |||
| for (i=0; i<L2_RANGE; i++) { | |||
| word32_t acc = 0; | |||
| for (j=0; j<NB_LSP_COEFF/2; j++) { | |||
| /* commented code : compute in the same way of the ITU code: ignore the denonimator and minimize (wi - w^[i])/(1-SumMAPred[i]) instead of (wi - w^[i]) square sum */ | |||
| //word16_t difftargetVectorL1L2 = SATURATE(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ | |||
| word16_t difftargetVectorL1L2 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ | |||
| acc = MAC16_16(acc, difftargetVectorL1L2, MULT16_16_Q11(difftargetVectorL1L2, weights[j])); /* weights in Q11, diff in Q13 */ | |||
| } | |||
| if (acc<meanSquareDiff) { | |||
| meanSquareDiff = acc; | |||
| L2index[L0] = i; | |||
| } | |||
| } | |||
| /* find the closest match in L3 wich will minimise the weighted sum of (targetVector - L1 result - L3)^2 */ | |||
| /* using eq20, eq21 and eq23 in spec 3.2.4 -> l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */ | |||
| /* works on the first five coefficients only */ | |||
| meanSquareDiff = MAXINT32; | |||
| for (i=0; i<L2_RANGE; i++) { | |||
| word32_t acc = 0; | |||
| for (j=NB_LSP_COEFF/2; j<NB_LSP_COEFF; j++) { | |||
| /* commented code : compute in the same way of the ITU code: ignore the denonimator and minimize (wi - w^[i])/(1-SumMAPred[i]) instead of (wi - w^[i]) square sum */ | |||
| //word16_t difftargetVectorL1L3 = SATURATE(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ | |||
| word16_t difftargetVectorL1L3 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ | |||
| acc = MAC16_16(acc, difftargetVectorL1L3, MULT16_16_Q11(difftargetVectorL1L3, weights[j])); /* weights in Q11, diff in Q13 */ | |||
| } | |||
| if (acc<meanSquareDiff) { | |||
| meanSquareDiff = acc; | |||
| L3index[L0] = i; | |||
| } | |||
| } | |||
| /* compute the quantized vector L1+L2/L3 and rearrange it as specified in spec 3.2.4(first the higher part (L2) and then the lower part (L3)) */ | |||
| /* Note: according to the spec, the rearrangement shall be done on each candidate while looking for best match, but the ITU code does it after picking the best match and so we do */ | |||
| word16_t quantizedVector[NB_LSP_COEFF]; /* in Q13, the current state of quantized vector */ | |||
| for (i=0; i<NB_LSP_COEFF/2; i++) { | |||
| quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L2index[L0]][i]); | |||
| } | |||
| for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) { | |||
| quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L3index[L0]][i]); | |||
| } | |||
| /* rearrange with a minimum distance of 0.0012 */ | |||
| for (i=1; i<NB_LSP_COEFF/2; i++) { | |||
| if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) { | |||
| quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); | |||
| quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); | |||
| } | |||
| } | |||
| for (i=NB_LSP_COEFF/2+1; i<NB_LSP_COEFF; i++) { | |||
| if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP1)) { | |||
| quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); | |||
| quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); | |||
| } | |||
| } | |||
| /* rearrange the whole quantizedVector with a distance of 0.0006 */ | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| if (quantizedVector[i-1]>SUB16(quantizedVector[i],GAP2)) { | |||
| quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); | |||
| quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); | |||
| } | |||
| } | |||
| /* compute the weighted mean square distance using the final quantized vector according to eq21 */ | |||
| weightedMeanSquareError[L0]=0; | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| word16_t difftargetVectorQuantizedVector = SATURATE(MULT16_16_Q15(SUB32(targetVector[i], quantizedVector[i]), MAPredictorSum[L0][i]), MAXINT16); /* targetVector and quantizedVector in Q13 -> result in Q13 */ | |||
| weightedMeanSquareError[L0] = MAC16_16(weightedMeanSquareError[L0], difftargetVectorQuantizedVector, MULT16_16_Q11(difftargetVectorQuantizedVector, weights[i])); /* weights in Q11, diff in Q13 */ | |||
| } | |||
| } | |||
| /* now select L0 and copy the selected coefficients to the output buffer */ | |||
| if (weightedMeanSquareError[0]<weightedMeanSquareError[1]) { | |||
| parameters[0] = 0; | |||
| parameters[1] = L1index[0]; | |||
| parameters[2] = L2index[0]; | |||
| parameters[3] = L3index[0]; | |||
| } else { | |||
| parameters[0] = 1; | |||
| parameters[1] = L1index[1]; | |||
| parameters[2] = L2index[1]; | |||
| parameters[3] = L3index[1]; | |||
| } | |||
| /*** Compute the quantized LSF from the L coefficients ***/ | |||
| word16_t quantizerOutput[NB_LSP_COEFF]; | |||
| word16_t qLSF[NB_LSP_COEFF]; | |||
| /* reconstruct vector from the codebooks using the selected parameters spec 3.2.4 eq19 */ | |||
| for (i=0; i<NB_LSP_COEFF/2; i++) { | |||
| quantizerOutput[i] = ADD16(L1[parameters[1]][i], L2L3[parameters[2]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */ | |||
| } | |||
| for ( i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) { | |||
| quantizerOutput[i] = ADD16(L1[parameters[1]][i], L2L3[parameters[3]][i]); /* same as previous, output in Q2.13 */ | |||
| } | |||
| /* rearrange in order to have a minimum distance between two consecutives coefficients spec 3.2.4 */ | |||
| rearrangeCoefficients(quantizerOutput, GAP1); | |||
| rearrangeCoefficients(quantizerOutput, GAP2); /* currentqLSF still in Q2.13 */ | |||
| /* compute qLSF spec 3.2.4 eq20 */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| word32_t acc = MULT16_16(MAPredictorSum[parameters[0]][i], quantizerOutput[i]); /* (1 - ∑Pi,k)*lˆi(m) Q15 * Q13 -> Q28 */ | |||
| for (j=0; j<MA_MAX_K; j++) { | |||
| acc = MAC16_16(acc, MAPredictor[parameters[0]][j][i], encoderChannelContext->previousqLSF[j][i]); | |||
| } | |||
| /* acc in Q2.28, shift back the acc to a Q2.13 with rounding */ | |||
| qLSF[i] = (word16_t)PSHR(acc, 15); /* qLSF in Q2.13 */ | |||
| } | |||
| /* update the previousqLSF buffer with current quantizer output */ | |||
| for (i=MA_MAX_K-1; i>0; i--) { | |||
| memcpy(encoderChannelContext->previousqLSF[i], encoderChannelContext->previousqLSF[i-1], NB_LSP_COEFF*sizeof(word16_t)); | |||
| } | |||
| memcpy(encoderChannelContext->previousqLSF[0], quantizerOutput, NB_LSP_COEFF*sizeof(word16_t)); | |||
| /*** qLSF stability check ***/ | |||
| insertionSort(qLSF, NB_LSP_COEFF); | |||
| /* check for low limit on qLSF[0] */ | |||
| if (qLSF[1]<qLSF_MIN) { | |||
| qLSF[1] = qLSF_MIN; | |||
| } | |||
| /* check and rectify minimum distance between two consecutive qLSF */ | |||
| for (i=0; i<NB_LSP_COEFF-1; i++) { | |||
| if (SUB16(qLSF[i+1],qLSF[i])<MIN_qLSF_DISTANCE) { | |||
| qLSF[i+1] = qLSF[i]+MIN_qLSF_DISTANCE; | |||
| } | |||
| } | |||
| /* check for upper limit on qLSF[NB_LSP_COEFF-1] */ | |||
| if (qLSF[NB_LSP_COEFF-1]>qLSF_MAX) { | |||
| qLSF[NB_LSP_COEFF-1] = qLSF_MAX; | |||
| } | |||
| /* convert qLSF to qLSP: qLSP = cos(qLSF) */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| qLSPCoefficients[i] = g729Cos_Q13Q15(qLSF[i]); /* ouput in Q0.15 */ | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,31 @@ | |||
| lib_LTLIBRARIES = libbcg729.la | |||
| libbcg729_la_SOURCES= LP2LSPConversion.c \ | |||
| LPSynthesisFilter.c \ | |||
| LSPQuantization.c \ | |||
| adaptativeCodebookSearch.c \ | |||
| codebooks.c \ | |||
| computeAdaptativeCodebookGain.c \ | |||
| computeLP.c \ | |||
| computeWeightedSpeech.c \ | |||
| decodeAdaptativeCodeVector.c \ | |||
| decodeFixedCodeVector.c \ | |||
| decodeGains.c \ | |||
| decodeLSP.c \ | |||
| decoder.c \ | |||
| encoder.c \ | |||
| findOpenLoopPitchDelay.c \ | |||
| fixedCodebookSearch.c \ | |||
| gainQuantization.c \ | |||
| interpolateqLSP.c \ | |||
| postFilter.c \ | |||
| postProcessing.c \ | |||
| preProcessing.c \ | |||
| qLSP2LP.c \ | |||
| utils.c | |||
| libbcg729_la_LDFLAGS=-fvisibility=hidden | |||
| INCLUDES= -I$(top_srcdir)/include | |||
| @ -0,0 +1,192 @@ | |||
| /* | |||
| adaptativeCodebookSearch.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "codebooks.h" | |||
| #include <string.h> | |||
| #include "adaptativeCodebookSearch.h" | |||
| /*** local functions ***/ | |||
| void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay); | |||
| /*****************************************************************************/ | |||
| /* adaptativeCodebookSearch: compute parameter P1 and P2 as in spec A.3.7 */ | |||
| /* compute also adaptative codebook vector as in spec 3.7.1 */ | |||
| /* parameters: */ | |||
| /* -(i/o) excitationVector: [-154,0[ previous excitation as input */ | |||
| /* Range [0,39[ */ | |||
| /* 40 words of LPResidualSignal as substitute for current */ | |||
| /* excitation (spec A.3.7) as input */ | |||
| /* 40 words of adaptative codebook vector in Q0 as output */ | |||
| /* Buffer in Q0 accessed in range [-154, 39] */ | |||
| /* -(i/o) intPitchDelayMin: low boundary for pitch delay search */ | |||
| /* -(i/o) intPitchDelayMax: low boundary for pitch delay search */ | |||
| /* Boundaries are updated during first subframe search */ | |||
| /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ | |||
| /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ | |||
| /* */ | |||
| /* -(o) intPitchDelay: the integer pitch delay */ | |||
| /* -(o) fracPitchDelay: the fractionnal part of pitch delay */ | |||
| /* -(o) pitchDelayCodeword: P1 or P2 codeword as in spec 3.7.2 */ | |||
| /* -(o) adaptativeCodebookVector: 40 words of adaptative codebook vector*/ | |||
| /* as described in spec 3.7.1, in Q0. */ | |||
| /* -(i) subFrameIndex: 0 for the first subframe, 40 for the second */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDelayMin, int16_t *intPitchDelayMax, word16_t impulseResponse[], word16_t targetSignal[], | |||
| int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex) | |||
| { | |||
| int i,j; | |||
| word32_t backwardFilteredTargetSignal[L_SUBFRAME]; | |||
| /* compute the backward Filtered Target Signal as specified in A.3.7: correlation of target signal and impulse response */ | |||
| correlateVectors(targetSignal, impulseResponse, backwardFilteredTargetSignal); /* targetSignal in Q0, impulseResponse in Q12 -> backwardFilteredTargetSignal in Q12 */ | |||
| /* maximise the sum as in spec A.3.7, eq A.7 */ | |||
| word32_t correlationMax = MININT32; | |||
| for (i=*intPitchDelayMin; i<=*intPitchDelayMax; i++) { | |||
| word32_t correlation = 0; | |||
| for (j=0; j<L_SUBFRAME; j++) { | |||
| correlation = MAC16_32_Q12(correlation, excitationVector[j-i], backwardFilteredTargetSignal[j]); | |||
| } | |||
| if (correlation>correlationMax) { | |||
| correlationMax=correlation; | |||
| *intPitchDelay = i; | |||
| } | |||
| } | |||
| /* compute the adaptativeCodebookVector (with fracPitchDelay at 0) */ | |||
| /* output is in excitationVector[0,L_SUBRAME[ */ | |||
| generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 0); | |||
| /* if we are at first subframe and intPitchDelay >= 85 -> do not compute fracPitchDelay, set it to 0 */ | |||
| *fracPitchDelay=0; | |||
| if (!(subFrameIndex==0 && *intPitchDelay>=85)) { | |||
| /* compute the fracPitchDelay*/ | |||
| word16_t adaptativeCodebookVector[L_SUBFRAME]; /* as the adaptativeCodebookVector is computed in the excitation vector, use this buffer to backup the one giving the highest numerator */ | |||
| /* search the fractionnal part to get the best correlation */ | |||
| /* we already have in excitationVector for fracPitchDelay = 0 the adaptativeCodebookVector (see specA.3.7) */ | |||
| correlationMax = 0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| correlationMax = MAC16_32_Q12(correlationMax, excitationVector[i], backwardFilteredTargetSignal[i]); | |||
| } | |||
| /* backup the adaptativeCodebookVector */ | |||
| memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t)); | |||
| /* Fractionnal part = -1 */ | |||
| generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, -1); | |||
| word32_t correlation=0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]); | |||
| } | |||
| if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */ | |||
| *fracPitchDelay=-1; | |||
| correlationMax = correlation; | |||
| /* backup the adaptativeCodebookVector */ | |||
| memcpy(adaptativeCodebookVector, excitationVector, L_SUBFRAME*sizeof(word16_t)); | |||
| } | |||
| /* Fractionnal part = 1 */ | |||
| generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, 1); | |||
| correlation=0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]); | |||
| } | |||
| if (correlation>correlationMax) { /* fractional part at -1 gives higher correlation */ | |||
| *fracPitchDelay=1; | |||
| } else { /* previously computed fractional part gives better result */ | |||
| /* restore the adaptativeCodebookVector*/ | |||
| memcpy(excitationVector, adaptativeCodebookVector, L_SUBFRAME*sizeof(word16_t)); | |||
| } | |||
| } | |||
| /* compute the codeword and intPitchDelayMin/intPitchDelayMax if needed (first subframe only) */ | |||
| if (subFrameIndex==0) { /* first subframe */ | |||
| /* compute intPitchDelayMin/intPitchDelayMax as in spec A.3.7 */ | |||
| *intPitchDelayMin = *intPitchDelay - 5; | |||
| if (*intPitchDelayMin < 20) { | |||
| *intPitchDelayMin = 20; | |||
| } | |||
| *intPitchDelayMax = *intPitchDelayMin + 9; | |||
| if (*intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) { | |||
| *intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY; | |||
| *intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 9; | |||
| } | |||
| /* compute the codeword as in spec 3.7.2 */ | |||
| if (*intPitchDelay<=85) { | |||
| *pitchDelayCodeword = 3*(*intPitchDelay) - 58 + *fracPitchDelay; | |||
| } else { | |||
| *pitchDelayCodeword = *intPitchDelay + 112; | |||
| } | |||
| } else { /* second subframe */ | |||
| /* compute the codeword as in spec 3.7.2 */ | |||
| *pitchDelayCodeword = 3*(*intPitchDelay-*intPitchDelayMin) + *fracPitchDelay +2; | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| /* generateAdaptativeCodebookVector : according to spec 3.7.1 eq40: */ | |||
| /* generates the adaptative codebook vector by interpolation of past */ | |||
| /* excitation */ | |||
| /* Note : specA.3.7 mention that excitation vector in range [0,39[ being */ | |||
| /* unknown is replaced by LP Residual signal, the ITU code use this */ | |||
| /* buffer to store the adaptative codebok vector and then use it in case*/ | |||
| /* of intPitchDelay<40. */ | |||
| /* parameters : */ | |||
| /* -(i/o) excitationVector: in Q0 the past excitation vector accessed */ | |||
| /* [-154,0[. Range [0,39[ is the output in Q0 */ | |||
| /* -(i) intPitchDelay: the integer pitch delay used to access the past */ | |||
| /* excitation */ | |||
| /* -(i) fracPitchDelay: fractional part of the pitch delay: -1, 0 or 1 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay) | |||
| { | |||
| int n,i,j; | |||
| /* fracPitchDelay is in range [-1, 1], convert it to [0,2] needed by eqA.8 */ | |||
| fracPitchDelay = -fracPitchDelay; | |||
| if (fracPitchDelay <0) { /* if fracPitchDelay is 1 -> pitchDelay of int+(1/3) -> int+1-(2/3)*/ | |||
| intPitchDelay++; | |||
| fracPitchDelay = 2; | |||
| } | |||
| /**/ | |||
| word16_t *delayedExcitationVector = &(excitationVector[-intPitchDelay]); /* delayedExcitationVector is used to address the excitation vector at index -intPitchDelay (-k in eq40) */ | |||
| word16_t *b30Increased = &(b30[fracPitchDelay]); /* b30 increased points to b30[fracPitchDelay] : b30[t] in eq40. b30 in Q15 */ | |||
| word16_t *b30Decreased = &(b30[3-fracPitchDelay]); /* b30 decreased points to b30[-fracPitchDelay] : b30[3-t] in eq40. b30 in Q15 */ | |||
| for (n=0; n<L_SUBFRAME; n++) { | |||
| word32_t acc = 0; /* acc in Q15 */ | |||
| for (i=0, j=0; i<10; i++, j+=3) { /* j is used as a 3*i index */ | |||
| acc = MAC16_16(acc, delayedExcitationVector[n-i], b30Increased[j]); /* WARNING: spec 3.7.1 and A.8 give an equation leading to delayedExcitationVector[n+i] but ITU code uses delayedExcitationVector[n-i], implemented as code */ | |||
| acc = MAC16_16(acc, delayedExcitationVector[n+1+i], b30Decreased[j]); | |||
| } | |||
| excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */ | |||
| } | |||
| } | |||
| @ -0,0 +1,296 @@ | |||
| /* | |||
| codebooks.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| /*** codebooks for quantization of the LSP coefficient - doc: 3.2.4 ***/ | |||
| word16_t L1[L1_RANGE][NB_LSP_COEFF] = { /* The first stage is a 10-dimensional VQ using codebook L1 with 128 entries (7 bits) */ | |||
| /* Q2.13 */ | |||
| { 1486, 2168, 3751, 9074, 12134, 13944, 17983, 19173, 21190, 21820}, | |||
| { 1730, 2640, 3450, 4870, 6126, 7876, 15644, 17817, 20294, 21902}, | |||
| { 1568, 2256, 3088, 4874, 11063, 13393, 18307, 19293, 21109, 21741}, | |||
| { 1733, 2512, 3357, 4708, 6977, 10296, 17024, 17956, 19145, 20350}, | |||
| { 1744, 2436, 3308, 8731, 10432, 12007, 15614, 16639, 21359, 21913}, | |||
| { 1786, 2369, 3372, 4521, 6795, 12963, 17674, 18988, 20855, 21640}, | |||
| { 1631, 2433, 3361, 6328, 10709, 12013, 13277, 13904, 19441, 21088}, | |||
| { 1489, 2364, 3291, 6250, 9227, 10403, 13843, 15278, 17721, 21451}, | |||
| { 1869, 2533, 3475, 4365, 9152, 14513, 15908, 17022, 20611, 21411}, | |||
| { 2070, 3025, 4333, 5854, 7805, 9231, 10597, 16047, 20109, 21834}, | |||
| { 1910, 2673, 3419, 4261, 11168, 15111, 16577, 17591, 19310, 20265}, | |||
| { 1141, 1815, 2624, 4623, 6495, 9588, 13968, 16428, 19351, 21286}, | |||
| { 2192, 3171, 4707, 5808, 10904, 12500, 14162, 15664, 21124, 21789}, | |||
| { 1286, 1907, 2548, 3453, 9574, 11964, 15978, 17344, 19691, 22495}, | |||
| { 1921, 2720, 4604, 6684, 11503, 12992, 14350, 15262, 16997, 20791}, | |||
| { 2052, 2759, 3897, 5246, 6638, 10267, 15834, 16814, 18149, 21675}, | |||
| { 1798, 2497, 5617, 11449, 13189, 14711, 17050, 18195, 20307, 21182}, | |||
| { 1009, 1647, 2889, 5709, 9541, 12354, 15231, 18494, 20966, 22033}, | |||
| { 3016, 3794, 5406, 7469, 12488, 13984, 15328, 16334, 19952, 20791}, | |||
| { 2203, 3040, 3796, 5442, 11987, 13512, 14931, 16370, 17856, 18803}, | |||
| { 2912, 4292, 7988, 9572, 11562, 13244, 14556, 16529, 20004, 21073}, | |||
| { 2861, 3607, 5923, 7034, 9234, 12054, 13729, 18056, 20262, 20974}, | |||
| { 3069, 4311, 5967, 7367, 11482, 12699, 14309, 16233, 18333, 19172}, | |||
| { 2434, 3661, 4866, 5798, 10383, 11722, 13049, 15668, 18862, 19831}, | |||
| { 2020, 2605, 3860, 9241, 13275, 14644, 16010, 17099, 19268, 20251}, | |||
| { 1877, 2809, 3590, 4707, 11056, 12441, 15622, 17168, 18761, 19907}, | |||
| { 2107, 2873, 3673, 5799, 13579, 14687, 15938, 17077, 18890, 19831}, | |||
| { 1612, 2284, 2944, 3572, 8219, 13959, 15924, 17239, 18592, 20117}, | |||
| { 2420, 3156, 6542, 10215, 12061, 13534, 15305, 16452, 18717, 19880}, | |||
| { 1667, 2612, 3534, 5237, 10513, 11696, 12940, 16798, 18058, 19378}, | |||
| { 2388, 3017, 4839, 9333, 11413, 12730, 15024, 16248, 17449, 18677}, | |||
| { 1875, 2786, 4231, 6320, 8694, 10149, 11785, 17013, 18608, 19960}, | |||
| { 679, 1411, 4654, 8006, 11446, 13249, 15763, 18127, 20361, 21567}, | |||
| { 1838, 2596, 3578, 4608, 5650, 11274, 14355, 15886, 20579, 21754}, | |||
| { 1303, 1955, 2395, 3322, 12023, 13764, 15883, 18077, 20180, 21232}, | |||
| { 1438, 2102, 2663, 3462, 8328, 10362, 13763, 17248, 19732, 22344}, | |||
| { 860, 1904, 6098, 7775, 9815, 12007, 14821, 16709, 19787, 21132}, | |||
| { 1673, 2723, 3704, 6125, 7668, 9447, 13683, 14443, 20538, 21731}, | |||
| { 1246, 1849, 2902, 4508, 7221, 12710, 14835, 16314, 19335, 22720}, | |||
| { 1525, 2260, 3862, 5659, 7342, 11748, 13370, 14442, 18044, 21334}, | |||
| { 1196, 1846, 3104, 7063, 10972, 12905, 14814, 17037, 19922, 22636}, | |||
| { 2147, 3106, 4475, 6511, 8227, 9765, 10984, 12161, 18971, 21300}, | |||
| { 1585, 2405, 2994, 4036, 11481, 13177, 14519, 15431, 19967, 21275}, | |||
| { 1778, 2688, 3614, 4680, 9465, 11064, 12473, 16320, 19742, 20800}, | |||
| { 1862, 2586, 3492, 6719, 11708, 13012, 14364, 16128, 19610, 20425}, | |||
| { 1395, 2156, 2669, 3386, 10607, 12125, 13614, 16705, 18976, 21367}, | |||
| { 1444, 2117, 3286, 6233, 9423, 12981, 14998, 15853, 17188, 21857}, | |||
| { 2004, 2895, 3783, 4897, 6168, 7297, 12609, 16445, 19297, 21465}, | |||
| { 1495, 2863, 6360, 8100, 11399, 14271, 15902, 17711, 20479, 22061}, | |||
| { 2484, 3114, 5718, 7097, 8400, 12616, 14073, 14847, 20535, 21396}, | |||
| { 2424, 3277, 5296, 6284, 11290, 12903, 16022, 17508, 19333, 20283}, | |||
| { 2565, 3778, 5360, 6989, 8782, 10428, 14390, 15742, 17770, 21734}, | |||
| { 2727, 3384, 6613, 9254, 10542, 12236, 14651, 15687, 20074, 21102}, | |||
| { 1916, 2953, 6274, 8088, 9710, 10925, 12392, 16434, 20010, 21183}, | |||
| { 3384, 4366, 5349, 7667, 11180, 12605, 13921, 15324, 19901, 20754}, | |||
| { 3075, 4283, 5951, 7619, 9604, 11010, 12384, 14006, 20658, 21497}, | |||
| { 1751, 2455, 5147, 9966, 11621, 13176, 14739, 16470, 20788, 21756}, | |||
| { 1442, 2188, 3330, 6813, 8929, 12135, 14476, 15306, 19635, 20544}, | |||
| { 2294, 2895, 4070, 8035, 12233, 13416, 14762, 17367, 18952, 19688}, | |||
| { 1937, 2659, 4602, 6697, 9071, 12863, 14197, 15230, 16047, 18877}, | |||
| { 2071, 2663, 4216, 9445, 10887, 12292, 13949, 14909, 19236, 20341}, | |||
| { 1740, 2491, 3488, 8138, 9656, 11153, 13206, 14688, 20896, 21907}, | |||
| { 2199, 2881, 4675, 8527, 10051, 11408, 14435, 15463, 17190, 20597}, | |||
| { 1943, 2988, 4177, 6039, 7478, 8536, 14181, 15551, 17622, 21579}, | |||
| { 1825, 3175, 7062, 9818, 12824, 15450, 18330, 19856, 21830, 22412}, | |||
| { 2464, 3046, 4822, 5977, 7696, 15398, 16730, 17646, 20588, 21320}, | |||
| { 2550, 3393, 5305, 6920, 10235, 14083, 18143, 19195, 20681, 21336}, | |||
| { 3003, 3799, 5321, 6437, 7919, 11643, 15810, 16846, 18119, 18980}, | |||
| { 3455, 4157, 6838, 8199, 9877, 12314, 15905, 16826, 19949, 20892}, | |||
| { 3052, 3769, 4891, 5810, 6977, 10126, 14788, 15990, 19773, 20904}, | |||
| { 3671, 4356, 5827, 6997, 8460, 12084, 14154, 14939, 19247, 20423}, | |||
| { 2716, 3684, 5246, 6686, 8463, 10001, 12394, 14131, 16150, 19776}, | |||
| { 1945, 2638, 4130, 7995, 14338, 15576, 17057, 18206, 20225, 20997}, | |||
| { 2304, 2928, 4122, 4824, 5640, 13139, 15825, 16938, 20108, 21054}, | |||
| { 1800, 2516, 3350, 5219, 13406, 15948, 17618, 18540, 20531, 21252}, | |||
| { 1436, 2224, 2753, 4546, 9657, 11245, 15177, 16317, 17489, 19135}, | |||
| { 2319, 2899, 4980, 6936, 8404, 13489, 15554, 16281, 20270, 20911}, | |||
| { 2187, 2919, 4610, 5875, 7390, 12556, 14033, 16794, 20998, 21769}, | |||
| { 2235, 2923, 5121, 6259, 8099, 13589, 15340, 16340, 17927, 20159}, | |||
| { 1765, 2638, 3751, 5730, 7883, 10108, 13633, 15419, 16808, 18574}, | |||
| { 3460, 5741, 9596, 11742, 14413, 16080, 18173, 19090, 20845, 21601}, | |||
| { 3735, 4426, 6199, 7363, 9250, 14489, 16035, 17026, 19873, 20876}, | |||
| { 3521, 4778, 6887, 8680, 12717, 14322, 15950, 18050, 20166, 21145}, | |||
| { 2141, 2968, 6865, 8051, 10010, 13159, 14813, 15861, 17528, 18655}, | |||
| { 4148, 6128, 9028, 10871, 12686, 14005, 15976, 17208, 19587, 20595}, | |||
| { 4403, 5367, 6634, 8371, 10163, 11599, 14963, 16331, 17982, 18768}, | |||
| { 4091, 5386, 6852, 8770, 11563, 13290, 15728, 16930, 19056, 20102}, | |||
| { 2746, 3625, 5299, 7504, 10262, 11432, 13172, 15490, 16875, 17514}, | |||
| { 2248, 3556, 8539, 10590, 12665, 14696, 16515, 17824, 20268, 21247}, | |||
| { 1279, 1960, 3920, 7793, 10153, 14753, 16646, 18139, 20679, 21466}, | |||
| { 2440, 3475, 6737, 8654, 12190, 14588, 17119, 17925, 19110, 19979}, | |||
| { 1879, 2514, 4497, 7572, 10017, 14948, 16141, 16897, 18397, 19376}, | |||
| { 2804, 3688, 7490, 10086, 11218, 12711, 16307, 17470, 20077, 21126}, | |||
| { 2023, 2682, 3873, 8268, 10255, 11645, 15187, 17102, 18965, 19788}, | |||
| { 2823, 3605, 5815, 8595, 10085, 11469, 16568, 17462, 18754, 19876}, | |||
| { 2851, 3681, 5280, 7648, 9173, 10338, 14961, 16148, 17559, 18474}, | |||
| { 1348, 2645, 5826, 8785, 10620, 12831, 16255, 18319, 21133, 22586}, | |||
| { 2141, 3036, 4293, 6082, 7593, 10629, 17158, 18033, 21466, 22084}, | |||
| { 1608, 2375, 3384, 6878, 9970, 11227, 16928, 17650, 20185, 21120}, | |||
| { 2774, 3616, 5014, 6557, 7788, 8959, 17068, 18302, 19537, 20542}, | |||
| { 1934, 4813, 6204, 7212, 8979, 11665, 15989, 17811, 20426, 21703}, | |||
| { 2288, 3507, 5037, 6841, 8278, 9638, 15066, 16481, 21653, 22214}, | |||
| { 2951, 3771, 4878, 7578, 9016, 10298, 14490, 15242, 20223, 20990}, | |||
| { 3256, 4791, 6601, 7521, 8644, 9707, 13398, 16078, 19102, 20249}, | |||
| { 1827, 2614, 3486, 6039, 12149, 13823, 16191, 17282, 21423, 22041}, | |||
| { 1000, 1704, 3002, 6335, 8471, 10500, 14878, 16979, 20026, 22427}, | |||
| { 1646, 2286, 3109, 7245, 11493, 12791, 16824, 17667, 18981, 20222}, | |||
| { 1708, 2501, 3315, 6737, 8729, 9924, 16089, 17097, 18374, 19917}, | |||
| { 2623, 3510, 4478, 5645, 9862, 11115, 15219, 18067, 19583, 20382}, | |||
| { 2518, 3434, 4728, 6388, 8082, 9285, 13162, 18383, 19819, 20552}, | |||
| { 1726, 2383, 4090, 6303, 7805, 12845, 14612, 17608, 19269, 20181}, | |||
| { 2860, 3735, 4838, 6044, 7254, 8402, 14031, 16381, 18037, 19410}, | |||
| { 4247, 5993, 7952, 9792, 12342, 14653, 17527, 18774, 20831, 21699}, | |||
| { 3502, 4051, 5680, 6805, 8146, 11945, 16649, 17444, 20390, 21564}, | |||
| { 3151, 4893, 5899, 7198, 11418, 13073, 15124, 17673, 20520, 21861}, | |||
| { 3960, 4848, 5926, 7259, 8811, 10529, 15661, 16560, 18196, 20183}, | |||
| { 4499, 6604, 8036, 9251, 10804, 12627, 15880, 17512, 20020, 21046}, | |||
| { 4251, 5541, 6654, 8318, 9900, 11686, 15100, 17093, 20572, 21687}, | |||
| { 3769, 5327, 7865, 9360, 10684, 11818, 13660, 15366, 18733, 19882}, | |||
| { 3083, 3969, 6248, 8121, 9798, 10994, 12393, 13686, 17888, 19105}, | |||
| { 2731, 4670, 7063, 9201, 11346, 13735, 16875, 18797, 20787, 22360}, | |||
| { 1187, 2227, 4737, 7214, 9622, 12633, 15404, 17968, 20262, 23533}, | |||
| { 1911, 2477, 3915, 10098, 11616, 12955, 16223, 17138, 19270, 20729}, | |||
| { 1764, 2519, 3887, 6944, 9150, 12590, 16258, 16984, 17924, 18435}, | |||
| { 1400, 3674, 7131, 8718, 10688, 12508, 15708, 17711, 19720, 21068}, | |||
| { 2322, 3073, 4287, 8108, 9407, 10628, 15862, 16693, 19714, 21474}, | |||
| { 2630, 3339, 4758, 8360, 10274, 11333, 12880, 17374, 19221, 19936}, | |||
| { 1721, 2577, 5553, 7195, 8651, 10686, 15069, 16953, 18703, 19929} | |||
| }; | |||
| word16_t L2L3[L2_RANGE][NB_LSP_COEFF] = { /* The second stage is a 10-bit VQ splitted in L2(first 5 values of a vector) and L3(last five value in each vector) containing 32 entries (5 bits). */ | |||
| /* Q0.13 but max value<0.5 so fitting actually on 12+1(sign) bits */ | |||
| { -435, -815, -742, 1033, -518, 582, -1201, 829, 86, 385}, | |||
| { -833, -891, 463, -8, -1251, 1450, 72, -231, 864, 661}, | |||
| {-1021, 231, -306, 321, -220, -163, -526, -754, -1633, 267}, | |||
| { 57, -198, -339, -33, -1468, 573, 796, -169, -631, 816}, | |||
| { 171, -350, 294, 1660, 453, 519, 291, 159, -640, -1296}, | |||
| { -701, -842, -58, 950, 892, 1549, 715, 527, -714, -193}, | |||
| { 584, 31, -289, 356, -333, -457, 612, -283, -1381, -741}, | |||
| { -109, -808, 231, 77, -87, -344, 1341, 1087, -654, -569}, | |||
| { -859, 1236, 550, 854, 714, -543, -1752, -195, -98, -276}, | |||
| { -877, -954, -1248, -299, 212, -235, -728, 949, 1517, 895}, | |||
| { -77, 344, -620, 763, 413, 502, -362, -960, -483, 1386}, | |||
| { -314, -307, -256, -1260, -429, 450, -466, -108, 1010, 2223}, | |||
| { 711, 693, 521, 650, 1305, -28, -378, 744, -1005, 240}, | |||
| { -112, -271, -500, 946, 1733, 271, -15, 909, -259, 1688}, | |||
| { 575, -10, -468, -199, 1101, -1011, 581, -53, -747, 878}, | |||
| { 145, -285, -1280, -398, 36, -498, -1377, 18, -444, 1483}, | |||
| {-1133, -835, 1350, 1284, -95, 1015, -222, 443, 372, -354}, | |||
| {-1459, -1237, 416, -213, 466, 669, 659, 1640, 932, 534}, | |||
| { -15, 66, 468, 1019, -748, 1385, -182, -907, -721, -262}, | |||
| { -338, 148, 1445, 75, -760, 569, 1247, 337, 416, -121}, | |||
| { 389, 239, 1568, 981, 113, 369, -1003, -507, -587, -904}, | |||
| { -312, -98, 949, 31, 1104, 72, -141, 1465, 63, -785}, | |||
| { 1127, 584, 835, 277, -1159, 208, 301, -882, 117, -404}, | |||
| { 539, -114, 856, -493, 223, -912, 623, -76, 276, -440}, | |||
| { 2197, 2337, 1268, 670, 304, -267, -525, 140, 882, -139}, | |||
| {-1596, 550, 801, -456, -56, -697, 865, 1060, 413, 446}, | |||
| { 1154, 593, -77, 1237, -31, 581, -1037, -895, 669, 297}, | |||
| { 397, 558, 203, -797, -919, 3, 692, -292, 1050, 782}, | |||
| { 334, 1475, 632, -80, 48, -1061, -484, 362, -597, -852}, | |||
| { -545, -330, -429, -680, 1133, -1182, -744, 1340, 262, 63}, | |||
| { 1320, 827, -398, -576, 341, -774, -483, -1247, -70, 98}, | |||
| { -163, 674, -11, -886, 531, -1125, -265, -242, 724, 934} | |||
| }; | |||
| word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF] = { /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */ | |||
| { | |||
| { 8421, 9109, 9175, 8965, 9034, 9057, 8765, 8775, 9106, 8673}, | |||
| { 7018, 7189, 7638, 7307, 7444, 7379, 7038, 6956, 6930, 6868}, | |||
| { 5472, 4990, 5134, 5177, 5246, 5141, 5206, 5095, 4830, 5147}, | |||
| { 4056, 3031, 2614, 3024, 2916, 2713, 3309, 3237, 2857, 3473} | |||
| }, | |||
| { | |||
| { 7733, 7880, 8188, 8175, 8247, 8490, 8637, 8601, 8359, 7569}, | |||
| { 4210, 3031, 2552, 3473, 3876, 3853, 4184, 4154, 3909, 3968}, | |||
| { 3214, 1930, 1313, 2143, 2493, 2385, 2755, 2706, 2542, 2919}, | |||
| { 3024, 1592, 940, 1631, 1723, 1579, 2034, 2084, 1913, 2601} | |||
| } | |||
| }; | |||
| word16_t MAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1 - Sum(MAPredictor) in Q0.15 */ | |||
| { 7798, 8447, 8205, 8293, 8126, 8477, 8447, 8703, 9043, 8604}, | |||
| {14585, 18333, 19772, 17344, 16426, 16459, 15155, 15220, 16043, 15708} | |||
| }; | |||
| word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1/(1 - Sum(MAPredictor)) in Q3.12 */ | |||
| {17210, 15888, 16357, 16183, 16516, 15833, 15888, 15421, 14840, 15597}, | |||
| { 9202, 7320, 6788, 7738, 8170, 8154, 8856, 8818, 8366, 8544} | |||
| }; | |||
| /* codebook for adaptative code vector */ | |||
| word16_t b30[31] = { /* in Q0.15 */ | |||
| 29443, 25207, 14701, 3143, -4402, -5850, -2783, 1211, 3130, 2259, 0, -1652, -1666, -464, 756, 1099, 550, -245, -634, -451, 0, 308, 296, 78, -120, -165, -79, 34, 91, 70, 0}; | |||
| /*** Gains related codebooks ***/ | |||
| /* codebook index mapping */ | |||
| uint16_t reverseIndexMappingGA[8] = {5, 1, 7, 4, 2, 0, 6, 3}; | |||
| uint16_t reverseIndexMappingGB[16] = {2, 14, 3, 13, 0, 15, 1, 12, 6, 10, 7, 9, 4, 11, 5, 8}; | |||
| uint16_t indexMappingGA[8] = {5, 1, 4, 7, 3, 0, 6, 2}; | |||
| uint16_t indexMappingGB[16] = {4, 6, 0, 2, 12, 14, 8, 10, 15, 11, 9, 13, 7, 3, 1, 5}; | |||
| /* GA and GB codebooks: first element is for adaptativeCodebookGain (in Q14), second element is for fixedCodebookGain computation (in Q12) */ | |||
| word16_t GACodebook[8][2] = { | |||
| /* Q14 Q12 */ | |||
| { 0 , 758 }, | |||
| { 1551 , 1213 }, | |||
| { 1831 , 2511 }, | |||
| { 57 , 2702 }, | |||
| { 1921 , 4646 }, | |||
| { 3242 , 4975 }, | |||
| { 356 , 7378 }, | |||
| { 2678 , 13581 } | |||
| }; | |||
| word16_t GBCodebook[16][2] = { | |||
| /* Q14 Q12 */ | |||
| { 826 , 1003 }, | |||
| { 1994 , 0 }, | |||
| { 5142 , 296 }, | |||
| { 6160 , 1197 }, | |||
| { 8091 , 2431 }, | |||
| { 9120 , 263 }, | |||
| { 10573 , 1483 }, | |||
| { 11569 , 598 }, | |||
| { 13260 , 1628 }, | |||
| { 14194 , 815 }, | |||
| { 15132 , 2457 }, | |||
| { 15161 , 7138 }, | |||
| { 15434 , 119 }, | |||
| { 16112 , 1696 }, | |||
| { 17299 , 931 }, | |||
| { 18973 , 2968 } | |||
| }; | |||
| /* according to spec 3.9.1: MA predictionCoefficients {0.68, 0.58, 0.34, 0.19} in Q14 */ | |||
| word16_t MAPredictionCoefficients[4] = { 11141, 9503, 5571, 3113 }; | |||
| /* Hamming_cos window for LPC analysis as defined in spec 3.2.1 eq3 */ | |||
| word16_t wlp[L_LP_ANALYSIS_WINDOW] = { /* in Q15 */ | |||
| 2621, 2623, 2629, 2638, 2651, 2668, 2689, 2713, 2741, 2772, | |||
| 2808, 2847, 2890, 2936, 2986, 3040, 3097, 3158, 3223, 3291, | |||
| 3363, 3438, 3517, 3599, 3685, 3774, 3867, 3963, 4063, 4166, | |||
| 4272, 4382, 4495, 4611, 4731, 4853, 4979, 5108, 5240, 5376, | |||
| 5514, 5655, 5800, 5947, 6097, 6250, 6406, 6565, 6726, 6890, | |||
| 7057, 7227, 7399, 7573, 7750, 7930, 8112, 8296, 8483, 8672, | |||
| 8863, 9057, 9252, 9450, 9650, 9852, 10055, 10261, 10468, 10677, | |||
| 10888, 11101, 11315, 11531, 11748, 11967, 12187, 12409, 12632, 12856, | |||
| 13082, 13308, 13536, 13764, 13994, 14225, 14456, 14688, 14921, 15155, | |||
| 15389, 15624, 15859, 16095, 16331, 16568, 16805, 17042, 17279, 17516, | |||
| 17754, 17991, 18228, 18465, 18702, 18939, 19175, 19411, 19647, 19882, | |||
| 20117, 20350, 20584, 20816, 21048, 21279, 21509, 21738, 21967, 22194, | |||
| 22420, 22644, 22868, 23090, 23311, 23531, 23749, 23965, 24181, 24394, | |||
| 24606, 24816, 25024, 25231, 25435, 25638, 25839, 26037, 26234, 26428, | |||
| 26621, 26811, 26999, 27184, 27368, 27548, 27727, 27903, 28076, 28247, | |||
| 28415, 28581, 28743, 28903, 29061, 29215, 29367, 29515, 29661, 29804, | |||
| 29944, 30081, 30214, 30345, 30472, 30597, 30718, 30836, 30950, 31062, | |||
| 31170, 31274, 31376, 31474, 31568, 31659, 31747, 31831, 31911, 31988, | |||
| 32062, 32132, 32198, 32261, 32320, 32376, 32428, 32476, 32521, 32561, | |||
| 32599, 32632, 32662, 32688, 32711, 32729, 32744, 32755, 32763, 32767, | |||
| 32767, 32741, 32665, 32537, 32359, 32129, 31850, 31521, 31143, 30716, | |||
| 30242, 29720, 29151, 28538, 27879, 27177, 26433, 25647, 24821, 23957, | |||
| 23055, 22117, 21145, 20139, 19102, 18036, 16941, 15820, 14674, 13505, | |||
| 12315, 11106, 9879, 8637, 7381, 6114, 4838, 3554, 2264, 971}; | |||
| /* lag window as defined in spec 3.2.1 eq6 */ | |||
| word16_t wlag[NB_LSP_COEFF+1] = { /* in Q15 note first coeff is not used */ | |||
| 32767, 32728, 32619, 32438, 32187, 31867, 31480, 31029, 30517, 29946, 29321}; | |||
| @ -0,0 +1,67 @@ | |||
| /* | |||
| computeAdaptativeCodebookGain.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "computeAdaptativeCodebookGain.h" | |||
| /*****************************************************************************/ | |||
| /* computeAdaptativeCodebookGain: compute gain, return result in Q14 */ | |||
| /* in range [0,1.2]. Spec 3.7.3 */ | |||
| /* parameters: */ | |||
| /* -(i) targetSignal: 40 values in Q0 */ | |||
| /* -(i) filteredAdaptativeCodebookVector: 40 values in Q0 */ | |||
| /* -(o) gainQuantizationXy in Q0 on 64 bits used for gain quantization */ | |||
| /* -(o) gainQuantizationYy in Q0 on 64 bits used for gain quantization */ | |||
| /* return value: */ | |||
| /* - the adaptative codebook gain on 16 bits in Q14 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word64_t *gainQuantizationXy, word64_t *gainQuantizationYy) | |||
| { | |||
| int i; | |||
| *gainQuantizationXy = 0; /* contains the scalar product targetSignal, filteredAdaptativeCodebookVector : numerator */ | |||
| *gainQuantizationYy = 0; /* contains the scalar product filteredAdaptativeCodebookVector^2 : denominator */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| *gainQuantizationXy = MAC64(*gainQuantizationXy, targetSignal[i], filteredAdaptativeCodebookVector[i]); | |||
| *gainQuantizationYy = MAC64(*gainQuantizationYy, filteredAdaptativeCodebookVector[i], filteredAdaptativeCodebookVector[i]); | |||
| } | |||
| /* check on values of xx and xy */ | |||
| if (*gainQuantizationXy<=0) { /* gain would be negative -> return 0 */ | |||
| /* this test covers the case of yy(denominator)==0 because if yy==0 then all y==0 and thus xy==0 */ | |||
| return 0; | |||
| } | |||
| /* output shall be in Q14 */ | |||
| word32_t gain = DIV64(SHL64(*gainQuantizationXy,14),*gainQuantizationYy); /* gain in Q14 */ | |||
| /* check if it is not above 1.2 */ | |||
| if (gain>ONE_POINT_2_IN_Q14) { | |||
| gain = ONE_POINT_2_IN_Q14; | |||
| } | |||
| return (word16_t)gain; | |||
| } | |||
| @ -0,0 +1,172 @@ | |||
| /* | |||
| computeLP.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "codebooks.h" | |||
| #include "utils.h" | |||
| #include "computeLP.h" | |||
| /*****************************************************************************/ | |||
| /* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */ | |||
| /* Autocorrelation and Levinson-Durbin algorithm */ | |||
| /* parameters: */ | |||
| /* -(i) signal: 240 samples in Q0, the last 40 are from next frame */ | |||
| /* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[]) | |||
| { | |||
| int i,j; | |||
| /*********************************************************************/ | |||
| /* Compute the windowed signal according to spec 3.2.1 eq4 */ | |||
| /*********************************************************************/ | |||
| word16_t windowedSignal[L_LP_ANALYSIS_WINDOW]; | |||
| for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) { | |||
| windowedSignal[i] = MULT16_16_P15(signal[i], wlp[i]); /* signal in Q0, wlp in Q0.15, windowedSignal in Q0 */ | |||
| } | |||
| /*********************************************************************************/ | |||
| /* Compute the autoCorrelation coefficients r[0..10] according to spec 3.2.1 eq5 */ | |||
| /*********************************************************************************/ | |||
| word32_t autoCorrelationCoefficient[NB_LSP_COEFF+1]; | |||
| /* Compute autoCorrelationCoefficient[0] first as it is the highest number and normalise it on 32 bits then apply the same normalisation to the other coefficients */ | |||
| /* autoCorrelationCoefficient are normalised on 32 bits and then considered as Q31 in range [-1,1[ */ | |||
| /* autoCorrelationCoefficient[0] is computed on 64 bits as it is likely to overflow 32 bits */ | |||
| word64_t acc64=0; /* acc on 64 bits */ | |||
| for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) { | |||
| acc64 = MAC64(acc64, windowedSignal[i], windowedSignal[i]); | |||
| } | |||
| if (acc64==0) { | |||
| acc64 = 1; /* spec 3.2.1: To avoid arithmetic problems for low-level input signals the value of r(0) has a lower boundary of r(0) = 1.0 */ | |||
| } | |||
| /* normalise the acc64 on 32 bits */ | |||
| int rightShiftToNormalise=0; | |||
| if (acc64>MAXINT32) { | |||
| do { | |||
| acc64 = SHR(acc64,1); | |||
| rightShiftToNormalise++; | |||
| } while (acc64>MAXINT32); | |||
| autoCorrelationCoefficient[0] = acc64; | |||
| } else { | |||
| rightShiftToNormalise = -countLeadingZeros((word32_t)acc64); | |||
| autoCorrelationCoefficient[0] = SHL((word32_t)acc64, -rightShiftToNormalise); | |||
| } | |||
| /* compute autoCorrelationCoefficient 1 to 10 */ | |||
| if (rightShiftToNormalise>0) { /* acc64 was not fitting on 32 bits so compute the other sum on 64 bits too */ | |||
| for (i=1; i<NB_LSP_COEFF+1; i++) { | |||
| /* compute the sum in the 64 bits acc*/ | |||
| acc64=0; | |||
| for (j=i; j<L_LP_ANALYSIS_WINDOW; j++) { | |||
| acc64 = ADD64_32(acc64, MULT16_16(windowedSignal[j], windowedSignal[j-i])); | |||
| } | |||
| /* normalise it */ | |||
| autoCorrelationCoefficient[i] = SHR(acc64 ,rightShiftToNormalise); | |||
| } | |||
| } else { /* acc64 was fitting on 32 bits, compute the other sum on 32 bits only as it is faster */ | |||
| for (i=1; i<NB_LSP_COEFF+1; i++) { | |||
| /* compute the sum in the 64 bits acc*/ | |||
| word32_t acc32=0; | |||
| for (j=i; j<L_LP_ANALYSIS_WINDOW; j++) { | |||
| acc32 = MAC16_16(acc32, windowedSignal[j], windowedSignal[j-i]); | |||
| } | |||
| /* normalise it */ | |||
| autoCorrelationCoefficient[i] = SHL(acc32, -rightShiftToNormalise); | |||
| } | |||
| } | |||
| /* apply lag window on the autocorrelation coefficients spec 3.2.1 eq7 */ | |||
| for (i=1; i<NB_LSP_COEFF+1; i++) { | |||
| autoCorrelationCoefficient[i] = MULT16_32_P15(wlag[i], autoCorrelationCoefficient[i]); /* wlag in Q15 */ | |||
| //autoCorrelationCoefficient[i] = MULT32_32_Q31(wlag[i], autoCorrelationCoefficient[i]); /* wlag in Q31 */ | |||
| } | |||
| /*********************************************************************************/ | |||
| /* Compute the LP Coefficient using Levinson-Durbin algo spec 3.2.2 */ | |||
| /*********************************************************************************/ | |||
| /* start a iteration i=2, init values as after iteration i=1 : */ | |||
| /* a[0] = 1 */ | |||
| /* a[1] = -r1/r0 */ | |||
| /* E = r0(1 - a[1]^2) */ | |||
| /* */ | |||
| /* iterations i = 2..10 */ | |||
| /* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */ | |||
| /* a[i] = -sum/E */ | |||
| /* iterations j = 1..i-1 */ | |||
| /* a[j] += a[i]*a{i-1}[i-j] use a{i-1}: from previous iteration */ | |||
| /* E *=(1-a[i]^2) */ | |||
| /* */ | |||
| /* r in Q31 (normalised) stored in array autoCorrelationCoefficient */ | |||
| /* E in Q31 (can't be > 1) */ | |||
| /* sum in Q27 (sum can't be > 1 but intermediate accumulation can) */ | |||
| /* a in Q4.27 with full range possible */ | |||
| /* Note: during iteration, current a[i] is in Q31 (can't be >1) and is */ | |||
| /* set to Q27 at the end of current iteration */ | |||
| /* */ | |||
| /*********************************************************************************/ | |||
| word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* to compute a[]*/ | |||
| word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */ | |||
| word32_t sum = 0; /* in Q27 */ | |||
| word32_t E = 0; /* in Q31 */ | |||
| /* init */ | |||
| LPCoefficients[0] = ONE_IN_Q27; | |||
| LPCoefficients[1] = -DIV32_32_Q27(autoCorrelationCoefficient[1], autoCorrelationCoefficient[0]); /* result in Q27(but<1) */ | |||
| /* E = r0(1 - a[1]^2) in Q31 */ | |||
| E = MULT32_32_Q31(autoCorrelationCoefficient[0], SUB32(ONE_IN_Q31, MULT32_32_Q23(LPCoefficients[1], LPCoefficients[1]))); /* LPCoefficient[1] is in Q27, using a Q23 operation will result in a Q31 variable */ | |||
| for (i=2; i<NB_LSP_COEFF+1; i++) { | |||
| /* update the previousIterationLPCoefficients needed for this one */ | |||
| for (j=1; j<i; j++) { | |||
| previousIterationLPCoefficients[j] = LPCoefficients[j]; | |||
| } | |||
| /* sum = r[i] + ∑ a[j]*r[i-j] with j = 1..i-1 (a[0] is always 1) */ | |||
| sum = 0; | |||
| for (j=1; j<i; j++) { | |||
| sum = MAC32_32_Q31(sum, LPCoefficients[j], autoCorrelationCoefficient[i-j]);/* LPCoefficients in Q27, autoCorrelation in Q31 -> result in Q27 -> sum in Q27 */ | |||
| } | |||
| sum = ADD32(SHL(sum, 4), autoCorrelationCoefficient[i]); /* set sum in Q31 and add r[0] */ | |||
| /* a[i] = -sum/E */ | |||
| LPCoefficients[i] = -DIV32_32_Q31(sum,E); /* LPCoefficient of current iteration is in Q31 for now, it will be set to Q27 at the end of this iteration */ | |||
| /* iterations j = 1..i-1 */ | |||
| /* a[j] += a[i]*a[i-j] */ | |||
| for (j=1; j<i; j++) { | |||
| LPCoefficients[j] = MAC32_32_Q31(LPCoefficients[j], LPCoefficients[i], previousIterationLPCoefficients[i-j]); /*LPCoefficients in Q27 except for LPCoefficients[i] in Q31 */ | |||
| } | |||
| /* E *=(1-a[i]^2) */ | |||
| E = MULT32_32_Q31(E, SUB32(ONE_IN_Q31, MULT32_32_Q31(LPCoefficients[i], LPCoefficients[i]))); /* all in Q31 */ | |||
| /* set LPCoefficients[i] from Q31 to Q27 */ | |||
| LPCoefficients[i] = SHR(LPCoefficients[i], 4); | |||
| } | |||
| /* convert with rounding the LP Coefficients form Q27 to Q12, ignore first coefficient which is always 1 */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| LPCoefficientsQ12[i] = (word16_t)SATURATE(PSHR(LPCoefficients[i+1], 15), MAXINT16); | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,88 @@ | |||
| /* | |||
| computeWeightedSpeech.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "computeWeightedSpeech.h" | |||
| /*****************************************************************************/ | |||
| /* computeWeightedSpeech: compute wieghted speech according to spec A3.3.3 */ | |||
| /* parameters: */ | |||
| /* -(i) inputSignal : 90 values buffer accessed in range [-10, 79] in Q0*/ | |||
| /* -(i) qLPCoefficients: 20 coefficients(10 for each subframe) in Q12 */ | |||
| /* -(i) weightedqLPCoefficients: 20 coefficients(10 for each subframe) */ | |||
| /* in Q12 */ | |||
| /* -(i/o) weightedInputSignal: 90 values in Q0: [-10, -1] as input */ | |||
| /* [0,79] as output in Q0 */ | |||
| /* -(o) LPResidualSignal: 80 values of residual signal in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], word16_t weightedqLPCoefficients[], word16_t weightedInputSignal[], word16_t LPResidualSignal[]) | |||
| { | |||
| /* algo as specified in A3.3.3: */ | |||
| /* first compute LPResidualSignal[n] = inputSignal[n] + ∑(i=1..10)qLP[i]*inputSignal[n-i] specA3.3.3 eqA.3 */ | |||
| /* then compute qLP' coefficients as qLP'[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */ | |||
| /* finally get the weightedInputSignal[n] = LPResidualSignal[n] - ∑(i=1..10)qLP'[i]*weightedInputSignal[n-i] spec A3.3.3 eqA.2 */ | |||
| int i,j; | |||
| /*** compute LPResisualSignal (spec A3.3.3 eqA.3) in Q0 ***/ | |||
| /* compute residual signal for the first subframe: use the first 10 qLPCoefficients */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| word32_t acc = SHL((word32_t)inputSignal[i], 12); /* inputSignal in Q0 is shifted to set acc in Q12 */ | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| acc = MAC16_16(acc, qLPCoefficients[j],inputSignal[i-j-1]); /* qLPCoefficients in Q12, inputSignal in Q0 -> acc in Q12 */ | |||
| } | |||
| LPResidualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */ | |||
| } | |||
| /* compute residual signal for the second subframe: use the second part of qLPCoefficients */ | |||
| for (i=L_SUBFRAME; i<L_FRAME; i++) { | |||
| word32_t acc = SHL((word32_t)inputSignal[i], 12); /* inputSignal in Q0 is shifted to set acc in Q12 */ | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| acc = MAC16_16(acc, qLPCoefficients[NB_LSP_COEFF+j],inputSignal[i-j-1]); /* qLPCoefficients in Q12, inputSignal in Q0 -> acc in Q12 */ | |||
| } | |||
| LPResidualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */ | |||
| } | |||
| /*** compute weightedqLPLowPassCoefficients and weightedInputSignal for first subframe ***/ | |||
| /* spec A3.3.3 a' = weightedqLPLowPassCoefficients[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */ | |||
| word16_t weightedqLPLowPassCoefficients[NB_LSP_COEFF]; /* in Q12 */ | |||
| weightedqLPLowPassCoefficients[0] = SUB16(weightedqLPCoefficients[0],O7_IN_Q12); /* weightedqLP[-1] = 1 -> weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */ | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| weightedqLPLowPassCoefficients[i] = SUB16(weightedqLPCoefficients[i], MULT16_16_Q12(weightedqLPCoefficients[i-1], O7_IN_Q12)); | |||
| } | |||
| /* weightedInputSignal for the first subframe: synthesis filter 1/[A'(z)] */ | |||
| synthesisFilter(LPResidualSignal, weightedqLPLowPassCoefficients, weightedInputSignal); | |||
| /*** compute weightedqLPLowPassCoefficients and weightedInputSignal for second subframe ***/ | |||
| /* spec A3.3.3 a' = weightedqLPLowPassCoefficients[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */ | |||
| weightedqLPLowPassCoefficients[0] = SUB16(weightedqLPCoefficients[NB_LSP_COEFF],O7_IN_Q12); /* weightedqLP[-1] = 1 -> weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */ | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| weightedqLPLowPassCoefficients[i] = SUB16(weightedqLPCoefficients[NB_LSP_COEFF+i], MULT16_16_Q12(weightedqLPCoefficients[NB_LSP_COEFF+i-1], O7_IN_Q12)); | |||
| } | |||
| /* weightedInputSignal for the second subframe: synthesis filter 1/[A'(z)] */ | |||
| synthesisFilter(&(LPResidualSignal[L_SUBFRAME]), weightedqLPLowPassCoefficients, &(weightedInputSignal[L_SUBFRAME])); | |||
| } | |||
| @ -0,0 +1,145 @@ | |||
| /* | |||
| decodeAdaptativeCodeVector.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "codebooks.h" | |||
| #include "decodeAdaptativeCodeVector.h" | |||
| /* init function */ | |||
| void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| decoderChannelContext->previousIntPitchDelay = 60; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* decodeAdaptativeCodeVector : as in spec 4.1.3 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) subFrameIndex : 0 or 40 for subframe 1 or subframe 2 */ | |||
| /* -(i) adaptativeCodebookIndex : parameter P1 or P2 */ | |||
| /* -(i) parityFlag : based on P1 parity flag : set if parity error */ | |||
| /* -(i) frameErasureFlag : set in case of frame erasure */ | |||
| /* -(i/o) intPitchDelay : the integer part of Pitch Delay. Computed from*/ | |||
| /* P1 on subframe 1. On Subframe 2, contains the intPitchDelay */ | |||
| /* computed on Subframe 1. */ | |||
| /* -(i/o) excitationVector : in Q0 excitation accessed from */ | |||
| /* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */ | |||
| /* and [0, L_SUBFRAME[ as output to store the adaptative */ | |||
| /* codebook vector */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext, int subFrameIndex, uint16_t adaptativeCodebookIndex, uint8_t parityFlag, uint8_t frameErasureFlag, | |||
| int16_t *intPitchDelay, word16_t *excitationVector) | |||
| { | |||
| int16_t fracPitchDelay; | |||
| /*** Compute the Pitch Delay from the Codebook index ***/ | |||
| /* fracPitchDelay is computed in the range -1,0,1 */ | |||
| if (subFrameIndex == 0 ) { /* first subframe */ | |||
| if (parityFlag|frameErasureFlag) { /* there is an error (either parity or frame erased) */ | |||
| *intPitchDelay = decoderChannelContext->previousIntPitchDelay; /* set the integer part of Pitch Delay to the last second subframe Pitch Delay computed spec: 4.1.2 */ | |||
| /* Note: unable to find anything regarding this part in the spec, just copied it from the ITU source code */ | |||
| fracPitchDelay = 0; | |||
| decoderChannelContext->previousIntPitchDelay++; | |||
| if (decoderChannelContext->previousIntPitchDelay>MAXIMUM_INT_PITCH_DELAY) decoderChannelContext->previousIntPitchDelay=MAXIMUM_INT_PITCH_DELAY; | |||
| } else { /* parity and frameErasure flags are off, do the normal computation (doc 4.1.3) */ | |||
| if (adaptativeCodebookIndex<197) { | |||
| /* *intPitchDelay = (P1 + 2 )/ 3 + 19 */ | |||
| *intPitchDelay = ADD16(MULT16_16_Q15(ADD16(adaptativeCodebookIndex,2), 10923), 19); /* MULT in Q15: 1/3 in Q15: 10923 */ | |||
| /* fracPitchDelay = P1 − 3*intPitchDelay + 58 : fracPitchDelay in -1, 0, 1 */ | |||
| fracPitchDelay = ADD16(SUB16(adaptativeCodebookIndex, MULT16_16(*intPitchDelay, 3)), 58); | |||
| } else {/* adaptativeCodebookIndex>= 197 */ | |||
| *intPitchDelay = SUB16(adaptativeCodebookIndex, 112); | |||
| fracPitchDelay = 0; | |||
| } | |||
| /* backup the intPitchDelay */ | |||
| decoderChannelContext->previousIntPitchDelay = *intPitchDelay; | |||
| } | |||
| } else { /* second subframe */ | |||
| if (frameErasureFlag) { /* there is an error : frame erased, in case of parity error, it has been taken in account at first subframe */ | |||
| /* unable to find anything regarding this part in the spec, just copied it from the ITU source code */ | |||
| *intPitchDelay = decoderChannelContext->previousIntPitchDelay; | |||
| fracPitchDelay = 0; | |||
| decoderChannelContext->previousIntPitchDelay++; | |||
| if (decoderChannelContext->previousIntPitchDelay>MAXIMUM_INT_PITCH_DELAY) decoderChannelContext->previousIntPitchDelay=MAXIMUM_INT_PITCH_DELAY; | |||
| } else { /* frameErasure flags are off, do the normal computation (doc 4.1.3) */ | |||
| int16_t tMin = SUB16(*intPitchDelay,5); /* intPitchDelay contains the intPitch computed for subframe one */ | |||
| if (tMin<20) { | |||
| tMin = 20; | |||
| } | |||
| if (tMin>134) { | |||
| tMin = 134; | |||
| } | |||
| /* intPitchDelay = (P2 + 2 )/ 3 − 1 */ | |||
| *intPitchDelay = SUB16(MULT16_16_Q15(ADD16(adaptativeCodebookIndex, 2), 10923), 1); | |||
| /* fracPitchDelay = P2 − 2 − 3((P 2 + 2 )/ 3 − 1) */ | |||
| fracPitchDelay = SUB16(SUB16(adaptativeCodebookIndex, MULT16_16(*intPitchDelay, 3)), 2); | |||
| /* *intPitchDelay = (P2 + 2 )/ 3 − 1 + tMin */ | |||
| *intPitchDelay = ADD16(*intPitchDelay,tMin); | |||
| /* backup the intPitchDelay */ | |||
| decoderChannelContext->previousIntPitchDelay = *intPitchDelay; | |||
| } | |||
| } | |||
| /* now compute the adaptative codebook vector using the pitch delay we just get and the past excitation vector */ | |||
| /* from spec 4.1.3 and 3.7.1 */ | |||
| /* shall compute v(n ) = ∑ u (n - k + i )b30 (t + 3i ) + ∑ u (n - k + 1 + i )b30 (3 - t + 3i ) for i=0,...,9 and n = 0,...,39 (t in 0, 1, 2) */ | |||
| /* with k = intPitchDelay and t = fracPitchDelay wich must be converted from range -1,0,1 to 0,1,2 */ | |||
| /* u the past excitation vector */ | |||
| /* v the adaptative codebook vector */ | |||
| /* b30 an interpolation filter */ | |||
| word16_t *excitationVectorMinusK; /* pointer to u(-k) */ | |||
| /* scale fracPichDelay from -1,0.1 to 0,1,2 */ | |||
| if (fracPitchDelay==1) { | |||
| excitationVectorMinusK = &(excitationVector[-(*intPitchDelay+1)]); /* fracPitchDelay being positive -> increase by one the integer part and set to 2 the fractional part : -(k+1/3) -> -(k+1)+2/3 */ | |||
| fracPitchDelay = 2; | |||
| } else { | |||
| fracPitchDelay = -fracPitchDelay; /* 0 unchanged, -1 -> +1 */ | |||
| excitationVectorMinusK = &(excitationVector[-(*intPitchDelay)]); /* -(k-1/3) -> -k+1/3 or -(k) -> -k*/ | |||
| } | |||
| int n; | |||
| for (n=0; n<L_SUBFRAME; n++) { /* loop over the whole subframe */ | |||
| word16_t *excitationVectorNMinusK = &(excitationVectorMinusK[n]); /* point to u(n-k), unscaled value, full range */ | |||
| word16_t *excitationVectorNMinusKPlusOne = &(excitationVectorMinusK[n+1]); /* point to u(n-k+1), unscaled value, full range */ | |||
| word16_t *b301 = &(b30[fracPitchDelay]); /* point to b30(t) in Q0.15 : sums of all b30 coeffs is < 2, no overflow possible on 32 bits */ | |||
| word16_t *b302 = &(b30[3-fracPitchDelay]); /* point to b30(3-t) in Q0.15*/ | |||
| int i,j; /* j will store 3i */ | |||
| word32_t acc = 0; /* in Q15 */ | |||
| for (i=0, j=0; i<10; i++, j+=3) { | |||
| acc = MAC16_16(acc, excitationVectorNMinusK[-i], b301[j]); /* Note : the spec says: u(n−k+i)b30(t+3i) but the ITU code do (and here too) u(n-k-i )b30(t+3i) */ | |||
| acc = MAC16_16(acc, excitationVectorNMinusKPlusOne[i], b302[j]); /* u(n-k+1+i)b30(3-t+3i) */ | |||
| } | |||
| excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */ | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,74 @@ | |||
| /* | |||
| decodeFixedCodeVector.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| /*****************************************************************************/ | |||
| /* decodeFixedCodeVector : compute the fixed codebook vector as in spec 4.1.4*/ | |||
| /* parameters: */ | |||
| /* -(i) signs: parameter S(4 signs bit) eq61 */ | |||
| /* -(i) positions: parameter C(4 3bits position and jx bit) eq62 */ | |||
| /* -(i) intPitchDelay: integer part of pitch Delay (T) */ | |||
| /* -(i) boundedPitchGain: Beta in eq47 and eq48, in Q14 */ | |||
| /* -(o) fixedCodebookVector: 40 values in Q13, range: [-1.8,+1.8] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchDelay, word16_t boundedPitchGain, | |||
| word16_t *fixedCodebookVector) | |||
| { | |||
| uint16_t positionsArray[4]; | |||
| uint16_t jx; | |||
| /* get the positions into an array: mapping according to eq62 and table7 in spec 3.8 */ | |||
| positionsArray[0] = (positions&(uint16_t)7)*5; /* m0 = 5*C, do not use macro here as whatever fixed or floating point computation we use, these are integers */ | |||
| positions = SHR(positions, 3); /* shift right by 3 to get the 3 next bits(m1/5) as LSB */ | |||
| positionsArray[1] = ((positions&(uint16_t)7)*5) + 1; /* m1 = 5*C + 1, do not use macro here as whatever fixed or floating point computation we use, these are integers */ | |||
| positions = SHR(positions, 3); /* shift right by 3 to get the 3 next bits(m2/5) as LSB */ | |||
| positionsArray[2] = ((positions&(uint16_t)7)*5) + 2; /* m2 = 5*C + 2, do not use macro here as whatever fixed or floating point computation we use, these are integers */ | |||
| positions = SHR(positions, 3); /* shift right by 3 to get the last 4 bits(m3/5 and jx) as LSB */ | |||
| jx = positions&(uint16_t)1; /* jx from eq62 is the last bit */ | |||
| positions = SHR(positions, 1); /* shift right by 1 to get the last 3 bits as LSB */ | |||
| positionsArray[3] = ((positions&(uint16_t)7)*5) + 3 + jx; /* m3 = 5*C + 3 + jx, do not use macro here as whatever fixed or floating point computation we use, these are integers */ | |||
| /* initialise the output Vector */ | |||
| int i; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| fixedCodebookVector[i]=0; | |||
| } | |||
| /* get the signs and compute the fixedCodebookVector */ | |||
| for (i=0; i<4; i++) { | |||
| if ((signs&(uint16_t)1) != 0) { /* sign bit is 1 */ | |||
| fixedCodebookVector[positionsArray[i]] = 8192; /* +1 in Q13 */ | |||
| } else { | |||
| fixedCodebookVector[positionsArray[i]] = -8192; /* -1 in Q13 */ | |||
| } | |||
| signs = SHR(signs, 1); /* shift signs right by one to get the next sign bit at next loop */ | |||
| } | |||
| /* if intPitchDelay is smaller than subframe length, give some correction using boundedPitchGain according to eq48 */ | |||
| for (i=intPitchDelay; i<L_SUBFRAME; i++) { | |||
| /* fixedCodebookVector[i] = fixedCodebookVector[i] + fixedCodebookVector[i-intPitchDelay]*boundedPitchGain */ | |||
| fixedCodebookVector[i] = ADD16(fixedCodebookVector[i], MULT16_16_P14(fixedCodebookVector[i-intPitchDelay], boundedPitchGain)); | |||
| } | |||
| } | |||
| @ -0,0 +1,111 @@ | |||
| /* | |||
| decodeGains.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "codebooks.h" | |||
| #include "utils.h" | |||
| #include "decodeGains.h" | |||
| /* init function */ | |||
| void initDecodeGains(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| /*init previousGainPredictionError to -14 in Q10 */ | |||
| decoderChannelContext->previousGainPredictionError[0] = -14336; | |||
| decoderChannelContext->previousGainPredictionError[1] = -14336; | |||
| decoderChannelContext->previousGainPredictionError[2] = -14336; | |||
| decoderChannelContext->previousGainPredictionError[3] = -14336; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* decodeGains : decode adaptive and fixed codebooks gains as in spec 4.1.5 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) GA : parameter GA: Gain Codebook Stage 1 (3 bits) */ | |||
| /* -(i) GB : paremeter GB: Gain Codebook Stage 2 (4 bits) */ | |||
| /* -(i) fixedCodebookVector: 40 values current fixed Codebook vector */ | |||
| /* in Q1.13. */ | |||
| /* -(i) frameErasureFlag : set in case of frame erasure */ | |||
| /* -(i/o) adaptativeCodebookGain : input previous/output current */ | |||
| /* subframe Pitch Gain in Q14 */ | |||
| /* -(i/o) fixedCodebookGain : input previous/output current Fixed */ | |||
| /* Codebook Gain in Q1 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t GA, uint16_t GB, word16_t *fixedCodebookVector, uint8_t frameErasureFlag, | |||
| word16_t *adaptativeCodebookGain, word16_t *fixedCodebookGain) | |||
| { | |||
| /* check the erasure flag */ | |||
| if (frameErasureFlag != 0) { /* we have a frame erasure, proceed as described in spec 4.4.2 */ | |||
| /* adaptativeCodebookGain as in eq94 */ | |||
| if (*adaptativeCodebookGain < 16384) { /* last subframe gain < 1 in Q14 */ | |||
| *adaptativeCodebookGain = MULT16_16_Q15(*adaptativeCodebookGain, 29491 ); /* *0.9 in Q15 */ | |||
| } else { /* bound current subframe gain to 0.9 (14746 in Q14) */ | |||
| *adaptativeCodebookGain = 14746; | |||
| } | |||
| /* fixedCodebookGain as in eq93 */ | |||
| *fixedCodebookGain = MULT16_16_Q15(*fixedCodebookGain, 32113 ); /* *0.98 in Q15 */ | |||
| /* And update the previousGainPredictionError according to spec 4.4.3 */ | |||
| int i; | |||
| word32_t currentGainPredictionError =0; | |||
| for (i=0; i<4; i++) { | |||
| currentGainPredictionError = ADD32(currentGainPredictionError, decoderChannelContext->previousGainPredictionError[i]); /* previousGainPredictionError in Q3.10-> Sum in Q5.10 (on 32 bits) */ | |||
| } | |||
| currentGainPredictionError = PSHR(currentGainPredictionError,2); /* /4 -> Q3.10 */ | |||
| if (currentGainPredictionError < -10240) { /* final result is low bounded by -14, so check before doing -4 if it's over -10(-10240 in Q10) or not */ | |||
| currentGainPredictionError = -14336; /* set to -14 in Q10 */ | |||
| } else { /* substract 4 */ | |||
| currentGainPredictionError = SUB32(currentGainPredictionError,4096); /* in Q10 */ | |||
| } | |||
| /* shift the array and insert the current Prediction Error */ | |||
| decoderChannelContext->previousGainPredictionError[3] = decoderChannelContext->previousGainPredictionError[2]; | |||
| decoderChannelContext->previousGainPredictionError[2] = decoderChannelContext->previousGainPredictionError[1]; | |||
| decoderChannelContext->previousGainPredictionError[1] = decoderChannelContext->previousGainPredictionError[0]; | |||
| decoderChannelContext->previousGainPredictionError[0] = (word16_t)currentGainPredictionError; | |||
| return; | |||
| } | |||
| /* First recover the GA and GB real index from their mapping tables(spec 3.9.3) */ | |||
| GA = reverseIndexMappingGA[GA]; | |||
| GB = reverseIndexMappingGB[GB]; | |||
| /* Compute the adaptativeCodebookGain from the tables according to eq73 in spec3.9.2 */ | |||
| /* adaptativeCodebookGain = GACodebook[GA][0] + GBCodebook[GB][0] */ | |||
| *adaptativeCodebookGain = ADD16(GACodebook[GA][0], GBCodebook[GB][0]); /* result in Q1.14 */ | |||
| /* Fixed Codebook: MA code-gain prediction */ | |||
| word32_t predictedFixedCodebookGain = MACodeGainPrediction(decoderChannelContext->previousGainPredictionError, fixedCodebookVector); /* predictedFixedCodebookGain on 32 bits in Q11.16 */ | |||
| /* get fixed codebook gain correction factor(gama) from the codebooks GA and GB according to eq74 */ | |||
| word16_t fixedCodebookGainCorrectionFactor = ADD16(GACodebook[GA][1], GBCodebook[GB][1]); /* result in Q3.12 (range [0.185, 5.05])*/ | |||
| /* compute fixedCodebookGain according to eq74 */ | |||
| *fixedCodebookGain = (word16_t)PSHR(MULT16_32_Q12(fixedCodebookGainCorrectionFactor, predictedFixedCodebookGain), 15); /* Q11.16*Q3.12 -> Q14.16, shift by 15 to get a Q14.1 which fits on 16 bits */ | |||
| /* use eq72 to compute current prediction error in order to update the previousGainPredictionError array */ | |||
| computeGainPredictionError(fixedCodebookGainCorrectionFactor, decoderChannelContext->previousGainPredictionError); | |||
| } | |||
| @ -0,0 +1,166 @@ | |||
| /* | |||
| decodeLSP.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "codebooks.h" | |||
| #include "utils.h" | |||
| #include "g729FixedPointMath.h" | |||
| /* define the initialisation vector for qLSP */ | |||
| /* previous L Code Word initial values (Pi/11 steps) in Q2.13 */ | |||
| static word16_t previousLCodeWordInit[NB_LSP_COEFF] = {2339, 4679, 7018, 9358, 11698, 14037, 16377, 18717, 21056, 23396}; | |||
| /* initialisations */ | |||
| void initDecodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| int i,j; | |||
| /* init the previousLCodeWord buffer according to doc 3.2.4 -> pi/11 steps */ | |||
| for (i=0; i<MA_MAX_K; i++) { | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| decoderChannelContext->previousLCodeWord[i][j] = previousLCodeWordInit[j]; | |||
| } | |||
| } | |||
| /* init the last valid values just to avoid problem in case the first frame is a lost one */ | |||
| decoderChannelContext->lastValidL0 = 0; | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| decoderChannelContext->lastqLSF[j] = previousLCodeWordInit[j]; | |||
| } | |||
| } | |||
| /*****************************************************************************/ | |||
| /* decodeLSP : decode LSP coefficients as in spec 4.1.1/3.2.4 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) L: 4 elements array containing L[0-3] the first and */ | |||
| /* second stage vector of LSP quantizer */ | |||
| /* -(i) frameErased : a boolean, when true, frame has been erased */ | |||
| /* -(o) qLSP: 10 quantized LSP coefficients in Q15 in range [-1,+1[ */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t L[], word16_t qLSP[], uint8_t frameErased) | |||
| { | |||
| int i,j; | |||
| word16_t currentqLSF[NB_LSP_COEFF]; /* buffer to the current qLSF in Q2.13 */ | |||
| if (frameErased == 0) { /* frame is ok, proceed according to 3.2.4 section of the doc */ | |||
| /*** doc 3.2.4 eq(19) ***/ | |||
| /* get the L codewords from the codebooks L1, L2 and L3 */ | |||
| /* for easier implementation, L2 and L3 5 dimensional codebooks have been stored in one 10 dimensional L2L3 codebook */ | |||
| /* get the 5 first coefficient from the L1 and L2 codebooks */ | |||
| /* Note : currentqLSF buffer contains L codewords and not qLSF */ | |||
| for (i=0; i<NB_LSP_COEFF/2; i++) { | |||
| currentqLSF[i] = ADD16(L1[L[1]][i], L2L3[L[2]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */ | |||
| } | |||
| /* get the 5 last coefficient from L1 and L3 codebooks */ | |||
| for ( i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) { | |||
| currentqLSF[i] = ADD16(L1[L[1]][i], L2L3[L[3]][i]); /* same as previous, output in Q2.13 */ | |||
| } | |||
| /*** rearrange in order to have a minimum distance between two consecutives coefficients ***/ | |||
| rearrangeCoefficients(currentqLSF, GAP1); | |||
| rearrangeCoefficients(currentqLSF, GAP2); /* currentqLSF still in Q2.13 */ | |||
| /*** doc 3.2.4 eq(20) ***/ | |||
| /* compute the qLSF as a weighted sum(weighted by MA coefficient selected according to L0 value) of previous and current frame L codewords coefficients */ | |||
| /* L[0] is the Switched MA predictor of LSP quantizer(1 bit) */ | |||
| /* currentqLSF and previousLCodeWord in Q2.13 */ | |||
| /* MAPredictor and MAPredictorSum in Q0.15 with MAPredictorSum[MA switch][i]+Sum[j=0-3](MAPredictor[MA switch][j][i])=1 -> acc will end up being in Q2.28*/ | |||
| /* Note : previousLCodeWord array containing the last 4 code words is updated during this phase */ | |||
| word32_t acc; /* Accumulator in Q2.28 */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| acc = MULT16_16(MAPredictorSum[L[0]][i], currentqLSF[i]); | |||
| for (j=MA_MAX_K-1; j>=0; j--) { | |||
| acc = MAC16_16(acc, MAPredictor[L[0]][j][i], decoderChannelContext->previousLCodeWord[j][i]); | |||
| decoderChannelContext->previousLCodeWord[j][i] = (j>0)?decoderChannelContext->previousLCodeWord[j-1][i]:currentqLSF[i]; /* update the previousqLCodeWord array: row[0] = current code word and row[j]=row[j-1] */ | |||
| } | |||
| /* acc in Q2.28, shift back the acc to a Q2.13 with rounding */ | |||
| currentqLSF[i] = (word16_t)PSHR(acc, 15); /* currentqLSF in Q2.13 */ | |||
| } | |||
| /* Note : currentqLSF buffer now contains qLSF */ | |||
| /*** doc 3.2.4 qLSF stability ***/ | |||
| /* qLSF in Q2.13 as are qLSF_MIN and qLSF_MAX and MIN_qLSF_DISTANCE */ | |||
| /* sort the currentqLSF array */ | |||
| insertionSort(currentqLSF, NB_LSP_COEFF); | |||
| /* check for low limit on qLSF[0] */ | |||
| if (currentqLSF[1]<qLSF_MIN) { | |||
| currentqLSF[1] = qLSF_MIN; | |||
| } | |||
| /* check and rectify minimum distance between two consecutive qLSF */ | |||
| for (i=0; i<NB_LSP_COEFF-1; i++) { | |||
| if (SUB16(currentqLSF[i+1],currentqLSF[i])<MIN_qLSF_DISTANCE) { | |||
| currentqLSF[i+1] = currentqLSF[i]+MIN_qLSF_DISTANCE; | |||
| } | |||
| } | |||
| /* check for upper limit on qLSF[NB_LSP_COEFF-1] */ | |||
| if (currentqLSF[NB_LSP_COEFF-1]>qLSF_MAX) { | |||
| currentqLSF[NB_LSP_COEFF-1] = qLSF_MAX; | |||
| } | |||
| /* backup the qLSF and L0 to restore them in case of frame erased */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| decoderChannelContext->lastqLSF[i] = currentqLSF[i]; | |||
| } | |||
| decoderChannelContext->lastValidL0 = L[0]; | |||
| } else { /* frame erased indicator is set, proceed according to section 4.4 of the specs */ | |||
| /* restore the qLSF of last valid frame */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| currentqLSF[i] = decoderChannelContext->lastqLSF[i]; | |||
| } | |||
| word32_t acc; /* acc in Q2.28 */ | |||
| /* compute back the codewords from the qLSF and store them in the previousLCodeWord buffer */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { /* currentqLSF and previousLCodeWord in Q2.13, MAPredictor in Q0.15 and invMAPredictorSum in Q3.12 */ | |||
| acc = SHL(decoderChannelContext->lastqLSF[i],15); /* Q2.13 -> Q2.28 */ | |||
| for (j=0; j<MA_MAX_K; j++) { | |||
| acc = MSU16_16(acc, MAPredictor[decoderChannelContext->lastValidL0][j][i], decoderChannelContext->previousLCodeWord[j][i]); /* acc in Q2.28 - MAPredictor in Q0.15 * previousLCodeWord in Q2.13 -> acc in Q2.28 (because 1-Sum(MAPred) < 0.6) */ | |||
| } | |||
| acc = MULT16_32_Q12(invMAPredictorSum[decoderChannelContext->lastValidL0][i], acc); /* Q3.12*Q2.28 >>12 -> Q2.28 because invMAPredictor is 1/(1 - Sum(MAPred))*/ | |||
| /* update the array of previoux Code Words */ | |||
| for (j=MA_MAX_K-1; j>=0; j--) { | |||
| /* acc in Q2.28, shift back the acc to a Q2.13 with rounding */ | |||
| decoderChannelContext->previousLCodeWord[j][i] = (j>0)?decoderChannelContext->previousLCodeWord[j-1][i]:(word16_t)PSHR(acc, 15); /* update the previousqLSF array: row[0] = computed code word and row[j]=row[j-1] */ | |||
| } | |||
| } | |||
| } | |||
| /* convert qLSF to qLSP: qLSP = cos(qLSF) */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| qLSP[i] = g729Cos_Q13Q15(currentqLSF[i]); /* ouput in Q0.15 */ | |||
| } | |||
| /* output: the qLSP buffer in Q0.15 */ | |||
| return; | |||
| } | |||
| @ -0,0 +1,257 @@ | |||
| /* | |||
| decoder.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include <string.h> | |||
| #include <stdlib.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "bcg729/decoder.h" | |||
| #include "decodeLSP.h" | |||
| #include "interpolateqLSP.h" | |||
| #include "qLSP2LP.h" | |||
| #include "decodeAdaptativeCodeVector.h" | |||
| #include "decodeFixedCodeVector.h" | |||
| #include "decodeGains.h" | |||
| #include "LPSynthesisFilter.h" | |||
| #include "postFilter.h" | |||
| #include "postProcessing.h" | |||
| /* buffers allocation */ | |||
| static const word16_t previousqLSPInitialValues[NB_LSP_COEFF] = {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; /* in Q0.15 the initials values for the previous qLSP buffer */ | |||
| /* internal functions */ | |||
| uint16_t pseudoRandom(bcg729DecoderChannelContextStruct *decoderChannelContext); | |||
| /*****************************************************************************/ | |||
| /* initBcg729DecoderChannel : create context structure and initialise it */ | |||
| /* return value : */ | |||
| /* - the decoder channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| bcg729DecoderChannelContextStruct *initBcg729DecoderChannel() | |||
| { | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| /* intialise statics buffers and variables */ | |||
| memcpy(decoderChannelContext->previousqLSP, previousqLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* initialise the previousqLSP buffer */ | |||
| memset(decoderChannelContext->excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */ | |||
| decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MIN; | |||
| decoderChannelContext->pseudoRandomSeed = 21845; /* initialise pseudo Random seed according to spec 4.4.4 */ | |||
| decoderChannelContext->adaptativeCodebookGain = 0; /* gains are initialised at 0 */ | |||
| decoderChannelContext->fixedCodebookGain = 0; | |||
| memset(decoderChannelContext->reconstructedSpeech, 0, NB_LSP_COEFF*sizeof(word16_t)); /* initialise to zero all the values used from previous frame to get the current frame reconstructed speech */ | |||
| /* initialisation of the differents blocs which need to be initialised */ | |||
| initDecodeLSP(decoderChannelContext); | |||
| initDecodeAdaptativeCodeVector(decoderChannelContext); | |||
| initDecodeGains(decoderChannelContext); | |||
| initPostFilter(decoderChannelContext); | |||
| initPostProcessing(decoderChannelContext); | |||
| return decoderChannelContext; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* closeBcg729DecoderChannel : free memory of context structure */ | |||
| /* parameters: */ | |||
| /* -(i) decoderChannelContext : the channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| free(decoderChannelContext); | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* bcg729Decoder : */ | |||
| /* parameters: */ | |||
| /* -(i) decoderChannelContext : the channel context data */ | |||
| /* -(i) bitStream : 15 parameters on 80 bits */ | |||
| /* -(i) frameErased: flag: true, frame has been erased */ | |||
| /* -(o) signal : a decoded frame 80 samples (16 bits PCM) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, int16_t signal[]) | |||
| { | |||
| int i; | |||
| uint16_t parameters[NB_PARAMETERS]; | |||
| /*** parse the bitstream and get all parameter into an array as in spec 4 - Table 8 ***/ | |||
| /* parameters buffer mapping : */ | |||
| /* 0 -> L0 (1 bit) */ | |||
| /* 1 -> L1 (7 bits) */ | |||
| /* 2 -> L2 (5 bits) */ | |||
| /* 3 -> L3 (5 bits) */ | |||
| /* 4 -> P1 (8 bit) */ | |||
| /* 5 -> P0 (1 bits) */ | |||
| /* 6 -> C1 (13 bits) */ | |||
| /* 7 -> S1 (4 bits) */ | |||
| /* 8 -> GA1(3 bits) */ | |||
| /* 9 -> GB1(4 bits) */ | |||
| /* 10 -> P2 (5 bits) */ | |||
| /* 11 -> C2 (13 bits) */ | |||
| /* 12 -> S2 (4 bits) */ | |||
| /* 13 -> GA2(3 bits) */ | |||
| /* 14 -> GB2(4 bits) */ | |||
| if (bitStream!=NULL) { /* bitStream might be null in case of frameErased (which shall be set in the appropriated flag)*/ | |||
| parametersBitStream2Array(bitStream, parameters); | |||
| } else { /* avoid compiler complaining for non inizialazed use of variable */ | |||
| for (i=0; i<NB_PARAMETERS; i++) { | |||
| parameters[i]=0; | |||
| } | |||
| } | |||
| /* internal buffers which we do not need to keep between calls */ | |||
| word16_t qLSP[NB_LSP_COEFF]; /* store the qLSP coefficients in Q0.15 */ | |||
| word16_t interpolatedqLSP[NB_LSP_COEFF]; /* store the interpolated qLSP coefficient in Q0.15 */ | |||
| word16_t LP[2*NB_LSP_COEFF]; /* store the 2 sets of LP coefficients in Q12 */ | |||
| int16_t intPitchDelay; /* store the Pitch Delay in and out of decodeAdaptativeCodeVector, in for decodeFixedCodeVector */ | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; /* the fixed Codebook Vector in Q1.13*/ | |||
| word16_t postFilteredSignal[L_SUBFRAME]; /* store the postfiltered signal in Q0 */ | |||
| /*****************************************************************************************/ | |||
| /*** on frame basis : decodeLSP, interpolate them with previous ones and convert to LP ***/ | |||
| decodeLSP(decoderChannelContext, parameters, qLSP, frameErasureFlag); /* decodeLSP need the first 4 parameters: L0-L3 */ | |||
| interpolateqLSP(decoderChannelContext->previousqLSP, qLSP, interpolatedqLSP); | |||
| /* copy the currentqLSP to previousqLSP buffer */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| decoderChannelContext->previousqLSP[i] = qLSP[i]; | |||
| } | |||
| /* call the qLSP2LP function for first subframe */ | |||
| qLSP2LP(interpolatedqLSP, LP); | |||
| /* call the qLSP2LP function for second subframe */ | |||
| qLSP2LP(qLSP, &(LP[NB_LSP_COEFF])); | |||
| /* check the parity on the adaptativeCodebookIndexSubframe1(P1) with the received one (P0)*/ | |||
| uint8_t parityErrorFlag = (uint8_t)(computeParity(parameters[4]) ^ parameters[5]); | |||
| /* loop over the two subframes */ | |||
| int subframeIndex; | |||
| int parametersIndex = 4; /* this is used to select the right parameter according to the subframe currently computed, start pointing to P1 */ | |||
| int LPCoefficientsIndex = 0; /* this is used to select the right LP Coefficients according to the subframe currently computed */ | |||
| for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) { | |||
| /* decode the adaptative Code Vector */ | |||
| decodeAdaptativeCodeVector( decoderChannelContext, | |||
| subframeIndex, | |||
| parameters[parametersIndex], | |||
| parityErrorFlag, | |||
| frameErasureFlag, | |||
| &intPitchDelay, | |||
| &(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex])); | |||
| if (subframeIndex==0) { /* at first subframe we have P0 between P1 and C1 */ | |||
| parametersIndex+=2; | |||
| } else { | |||
| parametersIndex++; | |||
| } | |||
| /* in case of frame erasure we shall generate pseudoRandom signs and index for fixed code vector decoding according to spec 4.4.4 */ | |||
| if (frameErasureFlag) { | |||
| parameters[parametersIndex] = pseudoRandom(decoderChannelContext)&(uint16_t)0x1fff; /* signs are set to the 13 LSB of the first pseudoRandom number */ | |||
| parameters[parametersIndex+1] = pseudoRandom(decoderChannelContext)&(uint16_t)0x000f; /* signs are set to the 4 LSB of the second pseudoRandom number */ | |||
| } | |||
| /* decode the fixed Code Vector */ | |||
| decodeFixedCodeVector(parameters[parametersIndex+1], parameters[parametersIndex], intPitchDelay, decoderChannelContext->boundedAdaptativeCodebookGain, fixedCodebookVector); | |||
| parametersIndex+=2; | |||
| /* decode gains */ | |||
| decodeGains(decoderChannelContext, parameters[parametersIndex], parameters[parametersIndex+1], fixedCodebookVector, frameErasureFlag, | |||
| &(decoderChannelContext->adaptativeCodebookGain), &(decoderChannelContext->fixedCodebookGain)); | |||
| parametersIndex+=2; | |||
| /* update bounded Adaptative Codebook Gain (in Q14) according to eq47 */ | |||
| decoderChannelContext->boundedAdaptativeCodebookGain = decoderChannelContext->adaptativeCodebookGain; | |||
| if (decoderChannelContext->boundedAdaptativeCodebookGain>BOUNDED_PITCH_GAIN_MAX) { | |||
| decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MAX; | |||
| } | |||
| if (decoderChannelContext->boundedAdaptativeCodebookGain<BOUNDED_PITCH_GAIN_MIN) { | |||
| decoderChannelContext->boundedAdaptativeCodebookGain = BOUNDED_PITCH_GAIN_MIN; | |||
| } | |||
| /* compute excitation vector according to eq75 */ | |||
| /* excitationVector = adaptative Codebook Vector * adaptativeCodebookGain + fixed Codebook Vector * fixedCodebookGain */ | |||
| /* the adaptative Codebook Vector is in the excitationVector buffer [L_PAST_EXCITATION + subframeIndex] */ | |||
| /* with adaptative Codebook Vector in Q0, adaptativeCodebookGain in Q14, fixed Codebook Vector in Q1.13 and fixedCodebookGain in Q14.1 -> result in Q14 on 32 bits */ | |||
| /* -> shift right 14 bits and store the value in Q0 in a 16 bits type */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i] = (word16_t)(SATURATE(PSHR( | |||
| ADD32( | |||
| MULT16_16(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i], decoderChannelContext->adaptativeCodebookGain), | |||
| MULT16_16(fixedCodebookVector[i], decoderChannelContext->fixedCodebookGain) | |||
| ), 14), MAXINT16)); | |||
| } | |||
| /* reconstruct speech using LP synthesis filter spec 4.1.6 eq77 */ | |||
| /* excitationVector in Q0, LP in Q12, recontructedSpeech in Q0 -> +NB_LSP_COEFF on the index of this one because the first NB_LSP_COEFF elements store the previous frame filter output */ | |||
| LPSynthesisFilter(&(decoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(LP[LPCoefficientsIndex]), &(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]) ); | |||
| /* NOTE: ITU code check for overflow after LP Synthesis Filter computation and if it happened, divide excitation buffer by 2 and recompute the LP Synthesis Filter */ | |||
| /* here, possible overflows are managed directly inside the Filter by saturation at MAXINT16 on each result */ | |||
| /* postFilter */ | |||
| postFilter(decoderChannelContext, &(LP[LPCoefficientsIndex]), /* select the LP coefficients for this subframe */ | |||
| &(decoderChannelContext->reconstructedSpeech[NB_LSP_COEFF+subframeIndex]), intPitchDelay, subframeIndex, postFilteredSignal); | |||
| /* postProcessing */ | |||
| postProcessing(decoderChannelContext, postFilteredSignal); | |||
| /* copy postProcessing Output to the signal output buffer */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| signal[subframeIndex+i] = postFilteredSignal[i]; | |||
| } | |||
| /* increase LPCoefficient Indexes */ | |||
| LPCoefficientsIndex+=NB_LSP_COEFF; | |||
| } | |||
| /* Shift Excitation Vector by L_FRAME left */ | |||
| memmove(decoderChannelContext->excitationVector, &(decoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t)); | |||
| /* Copy the last 10 words of reconstructed Speech to the begining of the array for next frame computation */ | |||
| memcpy(decoderChannelContext->reconstructedSpeech, &(decoderChannelContext->reconstructedSpeech[L_FRAME]), NB_LSP_COEFF*sizeof(word16_t)); | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* pseudoRandom : generate pseudo random number as in spec 4.4.4 eq96 */ | |||
| /* parameters: */ | |||
| /* -(i) decoderChannelContext : the channel context data */ | |||
| /* return value : */ | |||
| /* - a unsigned 16 bits pseudo random number */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| uint16_t pseudoRandom(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| /* pseudoRandomSeed is stored in an uint16_t var, we shall not worry about overflow here */ | |||
| /* pseudoRandomSeed*31821 + 13849; */ | |||
| return decoderChannelContext->pseudoRandomSeed = MAC16_16(13849, (decoderChannelContext->pseudoRandomSeed), 31821); | |||
| } | |||
| @ -0,0 +1,277 @@ | |||
| /* | |||
| encoder.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include <string.h> | |||
| #include <stdlib.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "bcg729/encoder.h" | |||
| #include "interpolateqLSP.h" | |||
| #include "qLSP2LP.h" | |||
| #include "preProcessing.h" | |||
| #include "computeLP.h" | |||
| #include "LP2LSPConversion.h" | |||
| #include "LSPQuantization.h" | |||
| #include "computeWeightedSpeech.h" | |||
| #include "findOpenLoopPitchDelay.h" | |||
| #include "adaptativeCodebookSearch.h" | |||
| #include "computeAdaptativeCodebookGain.h" | |||
| #include "fixedCodebookSearch.h" | |||
| #include "gainQuantization.h" | |||
| /* buffers allocation */ | |||
| static const word16_t previousLSPInitialValues[NB_LSP_COEFF] = {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; /* in Q0.15 the initials values for the previous LSP buffer */ | |||
| /*****************************************************************************/ | |||
| /* initBcg729EncoderChannel : create context structure and initialise it */ | |||
| /* return value : */ | |||
| /* - the encoder channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| bcg729EncoderChannelContextStruct *initBcg729EncoderChannel() | |||
| { | |||
| /* create the context structure */ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct)); | |||
| /* initialise statics buffers and variables */ | |||
| memset(encoderChannelContext->signalBuffer, 0, (L_LP_ANALYSIS_WINDOW-L_FRAME)*sizeof(word16_t)); /* set to zero all the past signal */ | |||
| encoderChannelContext->signalLastInputFrame = &(encoderChannelContext->signalBuffer[L_LP_ANALYSIS_WINDOW-L_FRAME]); /* point to the last frame in the signal buffer */ | |||
| encoderChannelContext->signalCurrentFrame = &(encoderChannelContext->signalBuffer[L_LP_ANALYSIS_WINDOW-L_SUBFRAME-L_FRAME]); /* point to the current frame */ | |||
| memcpy(encoderChannelContext->previousLSPCoefficients, previousLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* reset the previous quantized and unquantized LSP vector with the same value */ | |||
| memcpy(encoderChannelContext->previousqLSPCoefficients, previousLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); | |||
| memset(encoderChannelContext->weightedInputSignal, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); /* set to zero values of previous weighted signal */ | |||
| memset(encoderChannelContext->excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* set to zero values of previous excitation vector */ | |||
| memset(encoderChannelContext->targetSignal, 0, NB_LSP_COEFF*sizeof(word16_t)); /* set to zero values filter memory for the targetSignal computation */ | |||
| encoderChannelContext->lastQuantizedAdaptativeCodebookGain = O2_IN_Q14; /* quantized gain is initialized at his minimum value: 0.2 */ | |||
| /* initialisation of the differents blocs which need to be initialised */ | |||
| initPreProcessing(encoderChannelContext); | |||
| initLSPQuantization(encoderChannelContext); | |||
| initGainQuantization(encoderChannelContext); | |||
| return encoderChannelContext; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* closeBcg729EncoderChannel : free memory of context structure */ | |||
| /* parameters: */ | |||
| /* -(i) encoderChannelContext : the channel context data */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext) | |||
| { | |||
| free(encoderChannelContext); | |||
| } | |||
| /*****************************************************************************/ | |||
| /* bcg729Encoder : */ | |||
| /* parameters: */ | |||
| /* -(i) encoderChannelContext : context for this encoder channel */ | |||
| /* -(i) inputFrame : 80 samples (16 bits PCM) */ | |||
| /* -(o) bitStream : The 15 parameters for a frame on 80 bits */ | |||
| /* on 80 bits (10 8bits words) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[]) | |||
| { | |||
| int i; | |||
| uint16_t parameters[NB_PARAMETERS]; /* the output parameters in an array */ | |||
| /* internal buffers which we do not need to keep between calls */ | |||
| word16_t LPCoefficients[NB_LSP_COEFF]; /* the LP coefficients in Q3.12 */ | |||
| word16_t qLPCoefficients[2*NB_LSP_COEFF]; /* the quantized LP coefficients in Q3.12 computed from the qLSP one after interpolation: two sets, one for each subframe */ | |||
| word16_t weightedqLPCoefficients[2*NB_LSP_COEFF]; /* the qLP coefficients in Q3.12 weighted according to spec A3.3.3 */ | |||
| word16_t LSPCoefficients[NB_LSP_COEFF]; /* the LSP coefficients in Q15 */ | |||
| word16_t qLSPCoefficients[NB_LSP_COEFF]; /* the quantized LSP coefficients in Q15 */ | |||
| word16_t interpolatedqLSP[NB_LSP_COEFF]; /* the interpolated qLSP used for first subframe in Q15 */ | |||
| /*****************************************************************************************/ | |||
| /*** on frame basis : preProcessing, LP Analysis, Open-loop pitch search ***/ | |||
| preProcessing(encoderChannelContext, inputFrame, encoderChannelContext->signalLastInputFrame); /* output of the function in the signal buffer */ | |||
| computeLP(encoderChannelContext->signalBuffer, LPCoefficients); /* use the whole signal Buffer for windowing and autocorrelation */ | |||
| /*** compute LSP: it might fail, get the previous one in this case ***/ | |||
| if (!LP2LSPConversion(LPCoefficients, LSPCoefficients)) { | |||
| /* unable to find the 10 roots repeat previous LSP */ | |||
| memcpy(LSPCoefficients, encoderChannelContext->previousLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t)); | |||
| } | |||
| /*** LSPQuantization and compute L0, L1, L2, L3: the first four parameters ***/ | |||
| LSPQuantization(encoderChannelContext, LSPCoefficients, qLSPCoefficients, parameters); | |||
| /*** interpolate qLSP and convert to LP ***/ | |||
| interpolateqLSP(encoderChannelContext->previousqLSPCoefficients, qLSPCoefficients, interpolatedqLSP); | |||
| /* copy the currentqLSP to previousqLSP buffer */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| encoderChannelContext->previousqLSPCoefficients[i] = qLSPCoefficients[i]; | |||
| } | |||
| /* first subframe */ | |||
| qLSP2LP(interpolatedqLSP, qLPCoefficients); | |||
| /* second subframe */ | |||
| qLSP2LP(qLSPCoefficients, &(qLPCoefficients[NB_LSP_COEFF])); | |||
| /*** Compute the weighted Quantized LP Coefficients according to spec A3.3.3 ***/ | |||
| /* weightedqLPCoefficients[0] = qLPCoefficients[0]*Gamma^(i+1) (i=0..9) with Gamma = 0.75 in Q15 */ | |||
| weightedqLPCoefficients[0] = MULT16_16_P15(qLPCoefficients[0], GAMMA_E1); | |||
| weightedqLPCoefficients[1] = MULT16_16_P15(qLPCoefficients[1], GAMMA_E2); | |||
| weightedqLPCoefficients[2] = MULT16_16_P15(qLPCoefficients[2], GAMMA_E3); | |||
| weightedqLPCoefficients[3] = MULT16_16_P15(qLPCoefficients[3], GAMMA_E4); | |||
| weightedqLPCoefficients[4] = MULT16_16_P15(qLPCoefficients[4], GAMMA_E5); | |||
| weightedqLPCoefficients[5] = MULT16_16_P15(qLPCoefficients[5], GAMMA_E6); | |||
| weightedqLPCoefficients[6] = MULT16_16_P15(qLPCoefficients[6], GAMMA_E7); | |||
| weightedqLPCoefficients[7] = MULT16_16_P15(qLPCoefficients[7], GAMMA_E8); | |||
| weightedqLPCoefficients[8] = MULT16_16_P15(qLPCoefficients[8], GAMMA_E9); | |||
| weightedqLPCoefficients[9] = MULT16_16_P15(qLPCoefficients[9], GAMMA_E10); | |||
| weightedqLPCoefficients[10] = MULT16_16_P15(qLPCoefficients[10], GAMMA_E1); | |||
| weightedqLPCoefficients[11] = MULT16_16_P15(qLPCoefficients[11], GAMMA_E2); | |||
| weightedqLPCoefficients[12] = MULT16_16_P15(qLPCoefficients[12], GAMMA_E3); | |||
| weightedqLPCoefficients[13] = MULT16_16_P15(qLPCoefficients[13], GAMMA_E4); | |||
| weightedqLPCoefficients[14] = MULT16_16_P15(qLPCoefficients[14], GAMMA_E5); | |||
| weightedqLPCoefficients[15] = MULT16_16_P15(qLPCoefficients[15], GAMMA_E6); | |||
| weightedqLPCoefficients[16] = MULT16_16_P15(qLPCoefficients[16], GAMMA_E7); | |||
| weightedqLPCoefficients[17] = MULT16_16_P15(qLPCoefficients[17], GAMMA_E8); | |||
| weightedqLPCoefficients[18] = MULT16_16_P15(qLPCoefficients[18], GAMMA_E9); | |||
| weightedqLPCoefficients[19] = MULT16_16_P15(qLPCoefficients[19], GAMMA_E10); | |||
| /*** Compute weighted signal according to spec A3.3.3, this function also set LPResidualSignal(entire frame values) as specified in eq A.3 in excitationVector[L_PAST_EXCITATION] ***/ | |||
| computeWeightedSpeech(encoderChannelContext->signalCurrentFrame, qLPCoefficients, weightedqLPCoefficients, &(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]), &(encoderChannelContext->excitationVector[L_PAST_EXCITATION])); /* weightedInputSignal contains MAXIMUM_INT_PITCH_DELAY values from previous frame, points to current frame */ | |||
| /*** find the open loop pitch delay ***/ | |||
| uint16_t openLoopPitchDelay = findOpenLoopPitchDelay(&(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY])); | |||
| /* define boundaries for closed loop pitch delay search as specified in 3.7 */ | |||
| int16_t intPitchDelayMin = openLoopPitchDelay-3; | |||
| if (intPitchDelayMin < 20) { | |||
| intPitchDelayMin = 20; | |||
| } | |||
| int16_t intPitchDelayMax = intPitchDelayMin + 6; | |||
| if (intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) { | |||
| intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY; | |||
| intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 6; | |||
| } | |||
| /*****************************************************************************************/ | |||
| /* loop over the two subframes: Closed-loop pitch search(adaptative codebook), fixed codebook, memory update */ | |||
| /* set index and buffers */ | |||
| int subframeIndex; | |||
| int LPCoefficientsIndex = 0; | |||
| int parametersIndex = 4; /* index to insert parameters in the parameters output array */ | |||
| word16_t impulseResponseInput[L_SUBFRAME]; /* input buffer for the impulse response computation: in Q12, 1 followed by all zeros see spec A3.5*/ | |||
| impulseResponseInput[0] = ONE_IN_Q12; | |||
| memset(&(impulseResponseInput[1]), 0, (L_SUBFRAME-1)*sizeof(word16_t)); | |||
| for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) { | |||
| /*** Compute the impulse response : filter a subframe long buffer filled with unit and only zero through the 1/weightedqLPCoefficients as in spec A.3.5 ***/ | |||
| word16_t impulseResponseBuffer[NB_LSP_COEFF+L_SUBFRAME]; /* impulseResponseBuffer in Q12, need NB_LSP_COEFF as past value to go through filtering function */ | |||
| memset(impulseResponseBuffer, 0, (NB_LSP_COEFF)*sizeof(word16_t)); /* set the past values to zero */ | |||
| synthesisFilter(impulseResponseInput, &(weightedqLPCoefficients[LPCoefficientsIndex]), &(impulseResponseBuffer[NB_LSP_COEFF])); | |||
| /*** Compute the target signal (x[n]) as in spec A.3.6 in Q0 ***/ | |||
| /* excitationVector[L_PAST_EXCITATION+subframeIndex] currently store in Q0 the LPResidualSignal as in spec A.3.3 eq A.3*/ | |||
| synthesisFilter( &(encoderChannelContext->excitationVector[L_PAST_EXCITATION+subframeIndex]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF])); | |||
| /*** Adaptative Codebook search : compute the intPitchDelay, fracPitchDelay and associated parameter, compute also the adaptative codebook vector used to generate the excitation ***/ | |||
| /* after this call, the excitationVector[L_PAST_EXCITATION + subFrameIndex] contains the adaptative codebook vector as in spec 3.7.1 */ | |||
| int16_t intPitchDelay, fracPitchDelay; | |||
| adaptativeCodebookSearch(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &intPitchDelayMin, &intPitchDelayMax, &(impulseResponseBuffer[NB_LSP_COEFF]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF]), | |||
| &intPitchDelay, &fracPitchDelay, &(parameters[parametersIndex]), subframeIndex); | |||
| /*** Compute adaptative codebook gain spec 3.7.3, result in Q14 ***/ | |||
| /* compute the filtered adaptative codebook vector spec 3.7.3 */ | |||
| /* this computation makes use of two partial results used for gainQuantization too (yy and xy in eq63), they are part of the function output */ | |||
| /* note spec 3.7.3 eq44 make use of convolution of impulseResponse and adaptative codebook vector to compute the filtered version */ | |||
| /* in the Annex A, the filter being simpler, it's faster to directly filter the the vector using the weightedqLPCoefficients */ | |||
| word16_t filteredAdaptativeCodebookVector[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, the first NB_LSP_COEFF words are set to zero and used by filter only */ | |||
| memset(filteredAdaptativeCodebookVector, 0, NB_LSP_COEFF*sizeof(word16_t)); | |||
| synthesisFilter(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF])); | |||
| word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */ | |||
| word16_t adaptativeCodebookGain = computeAdaptativeCodebookGain(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), &gainQuantizationXy, &gainQuantizationYy); /* gain in Q14 */ | |||
| /* increase parameters index and compute P0 if needed */ | |||
| parametersIndex++; | |||
| if (subframeIndex==0) { /* first subframe compute P0, the parity bit of P1 */ | |||
| parameters[parametersIndex] = computeParity(parameters[parametersIndex-1]); | |||
| parametersIndex++; | |||
| } | |||
| /*** Fixed Codebook Search : compute the parameters for fixed codebook and the regular and convolved version of the fixed codebook vector ***/ | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; /* in Q13 */ | |||
| word16_t convolvedFixedCodebookVector[L_SUBFRAME]; /* in Q12 */ | |||
| fixedCodebookSearch(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(impulseResponseBuffer[NB_LSP_COEFF]), intPitchDelay, encoderChannelContext->lastQuantizedAdaptativeCodebookGain, &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), adaptativeCodebookGain, | |||
| &(parameters[parametersIndex]), &(parameters[parametersIndex+1]), fixedCodebookVector, convolvedFixedCodebookVector); | |||
| parametersIndex+=2; | |||
| /*** gains Quantization ***/ | |||
| word16_t quantizedAdaptativeCodebookGain; /* in Q14 */ | |||
| word16_t quantizedFixedCodebookGain; /* in Q1 */ | |||
| gainQuantization(encoderChannelContext, &(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), convolvedFixedCodebookVector, fixedCodebookVector, gainQuantizationXy, gainQuantizationYy, | |||
| &quantizedAdaptativeCodebookGain, &quantizedFixedCodebookGain, &(parameters[parametersIndex]), &(parameters[parametersIndex+1])); | |||
| parametersIndex+=2; | |||
| /*** subframe basis indexes and memory updates ***/ | |||
| LPCoefficientsIndex+= NB_LSP_COEFF; | |||
| encoderChannelContext->lastQuantizedAdaptativeCodebookGain = quantizedAdaptativeCodebookGain; | |||
| if (encoderChannelContext->lastQuantizedAdaptativeCodebookGain>ONE_POINT_2_IN_Q14) encoderChannelContext->lastQuantizedAdaptativeCodebookGain = ONE_POINT_2_IN_Q14; | |||
| if (encoderChannelContext->lastQuantizedAdaptativeCodebookGain<O2_IN_Q14) encoderChannelContext->lastQuantizedAdaptativeCodebookGain = O2_IN_Q14; | |||
| /* compute excitation for current subframe as in spec A.3.10 */ | |||
| /* excitationVector[L_PAST_EXCITATION + subframeIndex] currently contains in Q0 the adaptative codebook vector, quantizedAdaptativeCodebookGain in Q14 */ | |||
| /* fixedCodebookVector in Q13, quantizedFixedCodebookGain in Q1 */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i] = (word16_t)(SATURATE(PSHR(ADD32(MULT16_16(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex + i], quantizedAdaptativeCodebookGain), | |||
| MULT16_16(fixedCodebookVector[i], quantizedFixedCodebookGain)), 14), MAXINT16)); /* result in Q0 */ | |||
| } | |||
| /* update targetSignal memory as in spec A.3.10 */ | |||
| quantizedAdaptativeCodebookGain = PSHR(quantizedAdaptativeCodebookGain, 1); /* quantizedAdaptativeCodebookGain in Q13 */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| /* targetSignal[i] = targetSignal[L_SUBFRAME+i] - quantizedAdaptativeCodebookGain*filteredAdaptativeCodebookVector[L_SUBFRAME+i] - quantizedFixedCodebookGain*convolvedFixedCodebookVector[L_SUBFRAME-NB_LSP_COEFF+i]*/ | |||
| word32_t acc = MAC16_16(MULT16_16(quantizedAdaptativeCodebookGain, filteredAdaptativeCodebookVector[L_SUBFRAME+i]), quantizedFixedCodebookGain, convolvedFixedCodebookVector[L_SUBFRAME-NB_LSP_COEFF+i]); /* acc in Q13 */ | |||
| encoderChannelContext->targetSignal[i] = (word16_t)(SATURATE(SUB32(encoderChannelContext->targetSignal[L_SUBFRAME+i], PSHR(acc, 13)), MAXINT16)); | |||
| } | |||
| } | |||
| /*****************************************************************************************/ | |||
| /*** frame basis memory updates ***/ | |||
| /* shift left by L_FRAME the signal buffer */ | |||
| memmove(encoderChannelContext->signalBuffer, &(encoderChannelContext->signalBuffer[L_FRAME]), (L_LP_ANALYSIS_WINDOW-L_FRAME)*sizeof(word16_t)); | |||
| /* update previousLSP coefficient buffer */ | |||
| memcpy(encoderChannelContext->previousLSPCoefficients, LSPCoefficients, NB_LSP_COEFF*sizeof(word16_t)); | |||
| memcpy(encoderChannelContext->previousqLSPCoefficients, qLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t)); | |||
| /* shift left by L_FRAME the weightedInputSignal buffer */ | |||
| memmove(encoderChannelContext->weightedInputSignal, &(encoderChannelContext->weightedInputSignal[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); | |||
| /* shift left by L_FRAME the excitationVector */ | |||
| memmove(encoderChannelContext->excitationVector, &(encoderChannelContext->excitationVector[L_FRAME]), L_PAST_EXCITATION*sizeof(word16_t)); | |||
| /*** Convert array of parameters into bitStream ***/ | |||
| parametersArray2BitStream(parameters, bitStream); | |||
| return; | |||
| } | |||
| @ -0,0 +1,198 @@ | |||
| /* | |||
| findOpenLoopPitchDelay.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include <string.h> | |||
| #include <stdlib.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "g729FixedPointMath.h" | |||
| /* local functions prototypes */ | |||
| /* compute eqA.4 from spec A3.4 on the given range and step(1 compute all the correlation in range, 2 only the even ones) return the maximum and set the index giving it in the first parameter */ | |||
| word32_t getCorrelationMax(uint16_t *index, word16_t inputSignal[], uint16_t rangeOpen, uint16_t rangeClose, uint16_t step); | |||
| /* compute eqA.4 from spec3.4 */ | |||
| word32_t getCorrelation(word16_t inputSignal[], uint16_t index); | |||
| /*****************************************************************************/ | |||
| /* findOpenLoopPitchDelay : as specified in specA3.4 */ | |||
| /* paremeters: */ | |||
| /* -(i) weightedInputSignal: 223 values in Q0, buffer */ | |||
| /* accessed in range [-MAXIMUM_INT_PITCH_DELAY(143), L_FRAME(80)[ */ | |||
| /* return value: */ | |||
| /* - the openLoopIntegerPitchDelay in Q0 range [20, 143] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[]) | |||
| { | |||
| int i; | |||
| /*** scale the signal to avoid overflows ***/ | |||
| word16_t scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* this buffer might store the scaled version of input Signal, if scaling is not needed, it is not used */ | |||
| word16_t *scaledWeightedInputSignal; /* points to the begining of present frame either scaled or directly the input signal */ | |||
| /* compute on 64 bits the autocorrelation on the input signal and if needed scale to have it on 32 bits */ | |||
| word64_t autocorrelation = 0; | |||
| for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) { | |||
| autocorrelation = MAC64(autocorrelation, weightedInputSignal[i], weightedInputSignal[i]); | |||
| } | |||
| if (autocorrelation>MAXINT32) { | |||
| scaledWeightedInputSignal = &(scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY]); | |||
| int overflowScale = PSHR(31-countLeadingZeros((word32_t)(autocorrelation>>31)),1); /* count number of bits needed over the 31 bits allowed and divide by 2 to get the right scaling for the signal */ | |||
| for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) { | |||
| scaledWeightedInputSignal[i] = SHR(weightedInputSignal[i], overflowScale); | |||
| } | |||
| } else { /* scaledWeightedInputSignal points directly to weightedInputSignal */ | |||
| scaledWeightedInputSignal = weightedInputSignal; | |||
| } | |||
| /*** compute the correlationMax in the different ranges ***/ | |||
| uint16_t indexRange1=0, indexRange2=0, indexRange3Even=0, indexRange3; | |||
| word32_t correlationMaxRange1 = getCorrelationMax(&indexRange1, scaledWeightedInputSignal, 20, 39, 1); | |||
| word32_t correlationMaxRange2 = getCorrelationMax(&indexRange2, scaledWeightedInputSignal, 40, 79, 1); | |||
| word32_t correlationMaxRange3 = getCorrelationMax(&indexRange3Even, scaledWeightedInputSignal, 80, 143, 2); | |||
| indexRange3 = indexRange3Even; | |||
| /* for the third range, correlationMax shall be computed at +1 and -1 around the maximum found as described in spec A3.4 */ | |||
| word32_t correlationMaxRange3Odd; | |||
| if (indexRange3>80) { /* don't test value out of range [80, 143] */ | |||
| correlationMaxRange3Odd = getCorrelation(scaledWeightedInputSignal, indexRange3-1); | |||
| if (correlationMaxRange3Odd>correlationMaxRange3) { | |||
| correlationMaxRange3 = correlationMaxRange3Odd; | |||
| indexRange3 = indexRange3Even-1; | |||
| } | |||
| } | |||
| correlationMaxRange3Odd = getCorrelation(scaledWeightedInputSignal, indexRange3+1); | |||
| if (correlationMaxRange3Odd>correlationMaxRange3) { | |||
| correlationMaxRange3 = correlationMaxRange3Odd; | |||
| indexRange3 = indexRange3Even+1; | |||
| } | |||
| /*** normalise the correlations ***/ | |||
| word32_t autoCorrelationRange1 = getCorrelation(&(scaledWeightedInputSignal[-indexRange1]), 0); | |||
| word32_t autoCorrelationRange2 = getCorrelation(&(scaledWeightedInputSignal[-indexRange2]), 0); | |||
| word32_t autoCorrelationRange3 = getCorrelation(&(scaledWeightedInputSignal[-indexRange3]), 0); | |||
| if (autoCorrelationRange1==0) { | |||
| autoCorrelationRange1 = 1; /* avoid division by 0 */ | |||
| } | |||
| if (autoCorrelationRange2==0) { | |||
| autoCorrelationRange2 = 1; /* avoid division by 0 */ | |||
| } | |||
| if (autoCorrelationRange3==0) { | |||
| autoCorrelationRange3 = 1; /* avoid division by 0 */ | |||
| } | |||
| /* according to ITU code comments, the normalisedCorrelationMax values fit on 16 bits when in Q0, so keep them in Q8 on 32 bits shall not give any overflow */ | |||
| word32_t normalisedCorrelationMaxRange1 = MULT32_32_Q23(correlationMaxRange1, g729InvSqrt_Q0Q31(autoCorrelationRange1)); | |||
| word32_t normalisedCorrelationMaxRange2 = MULT32_32_Q23(correlationMaxRange2, g729InvSqrt_Q0Q31(autoCorrelationRange2)); | |||
| word32_t normalisedCorrelationMaxRange3 = MULT32_32_Q23(correlationMaxRange3, g729InvSqrt_Q0Q31(autoCorrelationRange3)); | |||
| /*** Favouring the delays with the values in the lower range ***/ | |||
| /* not clearly documented in spec A3.4, algo from the ITU code */ | |||
| uint16_t indexMultiple = SHL(indexRange2,1); /* indexMultiple = 2*indexRange2 */ | |||
| if( abs(indexMultiple - indexRange3) < 5) { /* 2*indexRange2 - indexRange3 < 5 */ | |||
| normalisedCorrelationMaxRange2 = ADD32(normalisedCorrelationMaxRange2, SHR(normalisedCorrelationMaxRange3,2)); /* Max2 += Max3*0.25 */ | |||
| } | |||
| if( abs(indexMultiple + indexRange2 - indexRange3) < 7) { /* 3*indexRange2 - indexRange3 < 5 */ | |||
| normalisedCorrelationMaxRange2 = ADD32(normalisedCorrelationMaxRange2, SHR(normalisedCorrelationMaxRange3,2)); /* Max2 += Max3*0.25 */ | |||
| } | |||
| indexMultiple = SHL(indexRange1,1); /* indexMultiple = 2*indexRange1 */ | |||
| if( abs(indexMultiple - indexRange2) < 5) { /* 2*indexRange1 - indexRange2 < 5 */ | |||
| normalisedCorrelationMaxRange1 = MAC16_32_P15(normalisedCorrelationMaxRange1, O2_IN_Q15, normalisedCorrelationMaxRange2); /* Max1 += Max2*0.2 */ | |||
| } | |||
| if( abs(indexMultiple + indexRange1 - indexRange2) < 7) { /* 3*indexRange1 - indexRange2 < 7 */ | |||
| normalisedCorrelationMaxRange1 = MAC16_32_P15(normalisedCorrelationMaxRange1, O2_IN_Q15, normalisedCorrelationMaxRange2); /* Max1 += Max2*0.2 */ | |||
| } | |||
| /*** return the index corresponding to the greatest normalised Correlation */ | |||
| if (normalisedCorrelationMaxRange1<normalisedCorrelationMaxRange2) { | |||
| normalisedCorrelationMaxRange1 = normalisedCorrelationMaxRange2; | |||
| indexRange1 = indexRange2; | |||
| } | |||
| if (normalisedCorrelationMaxRange1<normalisedCorrelationMaxRange3) { | |||
| indexRange1 = indexRange3; | |||
| } | |||
| return indexRange1; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* getCorrelation : as specified in specA3.4 eqA.4 */ | |||
| /* correlation = ∑(i=0..39)inputSignal[2*i]*inputSignal[2*i-index] */ | |||
| /* paremeters: */ | |||
| /* -(i) inputSignal: 223 values in Q0, buffer accessed in range */ | |||
| /* [-index, L_FRAME[ */ | |||
| /* -(i) index: integer value in range [20,143] */ | |||
| /* return value: */ | |||
| /* -the correlation in Q0 on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word32_t getCorrelation(word16_t inputSignal[], uint16_t index) | |||
| { | |||
| int i,j=-index; /* i will be the [2*i] index and j the [2*i-index] in eqA.4 */ | |||
| word32_t correlation = 0; | |||
| for (i=0; i<L_FRAME; i+=2,j+=2) { | |||
| correlation = MAC16_16(correlation, inputSignal[i], inputSignal[j]); | |||
| } | |||
| return correlation; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* getCorrelation : compute eqA.4 from spec A3.4 on the given range and */ | |||
| /* step(1 compute all the correlation in range, 2 only the even ones) */ | |||
| /* then return the maximum as specified in specA3.4 eqA.4 */ | |||
| /* paremeters: */ | |||
| /* -(o) index : the index giving the maximum of correlation on the */ | |||
| /* considered range */ | |||
| /* -(i) inputSignal: signal used to compute the correlation, in Q0 */ | |||
| /* accessed in range [-rangeClose, L_FRAME[ */ | |||
| /* -(i) rangeOpen and rangeClose : the index range in which looking for */ | |||
| /* the correlation max */ | |||
| /* -(i) step : incrementing step for the index */ | |||
| /* return value : */ | |||
| /* - the correlation maximum found on the given range in Q0 on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word32_t getCorrelationMax(uint16_t *index, word16_t inputSignal[], uint16_t rangeOpen, uint16_t rangeClose, uint16_t step) | |||
| { | |||
| int i; | |||
| word32_t correlationMax = MININT32; | |||
| for (i=rangeOpen; i<=rangeClose; i+=step) { | |||
| word32_t correlation = getCorrelation(inputSignal, i); | |||
| if (correlation>correlationMax) { | |||
| *index = i; | |||
| correlationMax = correlation; | |||
| } | |||
| } | |||
| return correlationMax; | |||
| } | |||
| @ -0,0 +1,397 @@ | |||
| /* | |||
| fixedCodebookSearch.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include <stdlib.h> | |||
| #include "fixedCodebookSearch.h" | |||
| /*** local functions ***/ | |||
| void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME]); | |||
| void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling); | |||
| /*****************************************************************************/ | |||
| /* fixedCodebookSearch: compute fixed codebook parameters (codeword and sign)*/ | |||
| /* compute also fixed codebook vector as in spec 3.8.1 */ | |||
| /* parameters: */ | |||
| /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ | |||
| /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ | |||
| /* -(i) intPitchDelay: current integer pitch delay */ | |||
| /* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */ | |||
| /* gain quantized in Q14 */ | |||
| /* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */ | |||
| /* -(i) adaptativeCodebookGain : in Q14 */ | |||
| /* -(o) fixedCodebookParameter */ | |||
| /* -(o) fixedCodebookPulsesSigns */ | |||
| /* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q13 */ | |||
| /* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */ | |||
| /* in Q12. */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], int16_t intPitchDelay, word16_t lastQuantizedAdaptativeCodebookGain, word16_t filteredAdaptativeCodebookVector[], word16_t adaptativeCodebookGain, | |||
| uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[]) | |||
| { | |||
| int i,j,n; | |||
| /* compute the target signal for fixed codebook spec 3.8.1 eq50 : fixedCodebookTargetSignal[i] = targetSignal[i] - (adaptativeCodebookGain * filteredAdaptativeCodebookVector[i]) */ | |||
| word16_t fixedCodebookTargetSignal[L_SUBFRAME]; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| fixedCodebookTargetSignal[i] = MSU16_16_Q14(targetSignal[i], filteredAdaptativeCodebookVector[i], adaptativeCodebookGain); /* adaptativeCodebookGain in Q14, other values in Q0 */ | |||
| } | |||
| /* update impulse vector as in spec 3.8 eq49 */ | |||
| for (i=intPitchDelay; i<L_SUBFRAME; i++) { | |||
| impulseResponse[i] = MAC16_16_Q14(impulseResponse[i], impulseResponse[i-intPitchDelay], lastQuantizedAdaptativeCodebookGain); /* h[n] = h[n] + β*h[n-T], impulseResponse in Q12, lastQuantizedAdaptativeCodebookGain in Q14 */ | |||
| } | |||
| /* compute the correlation signal as in spec 3.8.1 eq52 */ | |||
| word32_t correlationSignal32[L_SUBFRAME]; /* on 32 bits in Q12 */ | |||
| word16_t correlationSignal[L_SUBFRAME]; /* normalised to fit on 13 bits */ | |||
| word32_t correlationSignalMax = 0; | |||
| /* compute on 32 bits and get the maximum */ | |||
| for (n=0; n<L_SUBFRAME; n++) { | |||
| correlationSignal32[n] = 0; | |||
| for (i=n; i<L_SUBFRAME; i++) { | |||
| correlationSignal32[n] = MAC16_16(correlationSignal32[n], fixedCodebookTargetSignal[i], impulseResponse[i-n]); | |||
| } | |||
| word32_t abscCrrelationSignal32 = correlationSignal32[n]>=0?correlationSignal32[n]:-correlationSignal32[n]; | |||
| if (abscCrrelationSignal32>correlationSignalMax) { | |||
| correlationSignalMax = abscCrrelationSignal32; | |||
| } | |||
| } | |||
| /* normalise on 13 bits */ | |||
| uint16_t correlationSignalMaxNorm = countLeadingZeros(correlationSignalMax); | |||
| if (correlationSignalMaxNorm<18) { /* if it doesn't already fit on 13 bits */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| correlationSignal[i] = (word16_t)(SHR(correlationSignal32[i], 18-correlationSignalMaxNorm)); | |||
| } | |||
| } else { /* it fits on 13 bits, just copy it to the 16 bits buffer */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| correlationSignal[i] = (word16_t)correlationSignal32[i]; | |||
| } | |||
| } | |||
| int correlationSignalSign[L_SUBFRAME]; /* to store the sign of each correlationSignal element */ | |||
| /* build the matrix Ф' : impulseResponse correlation matrix spec 3.8.1 eq51, eq56 and eq57 */ | |||
| /* correlationSignal turns to absolute values and sign of elements is stored in correlationSignalSign */ | |||
| word32_t Phi[L_SUBFRAME][L_SUBFRAME]; | |||
| computeImpulseResponseCorrelationMatrix(impulseResponse, correlationSignal, correlationSignalSign, Phi); | |||
| /* search for impulses leading to a max in C^2/E : spec 3.8.1 eq53 */ | |||
| int m3Base; | |||
| int i0=0, i1=0, i2=0, i3=0; | |||
| word32_t correlationSquareMax = -1; | |||
| word32_t energyMax = 1; | |||
| int m0=0, m1=0, m2=0, m3=0; | |||
| int mSwitch[2][4] = {{2,3,0,1},{3,0,1,2}}; | |||
| int mIndex; | |||
| int jx = 0; | |||
| /* algorithm, not described in spec, retrieved from ITU code */ | |||
| /* by tracks are intended series of index m0 track is 0,5,10,...35. m1 is 1,6,11,..,36. m2 is 2,7,12,..,37. m3 is 3,8,13,..,38. m4 is 4,9,14,..,39 */ | |||
| /* note index m3 will follow track m3 and m4 */ | |||
| /* The following search is performed twice: first with m3 index following m3 track, and then m3 index follow m4 track */ | |||
| /* The following operation are performed twice, first using indexes m2, m3, m0, m1 and then m3, m0, m1, m2 as following */ | |||
| /* description is made for the first run, for the second one, juste substitute m2 by m3, m3 by m0, m0 by m1 and m1 by m2 */ | |||
| /* - search in m2 track two maxima for the correlation Signal. For each of this maximum : */ | |||
| /* -- compute for the whole m3 track (8 values) the values C^2 and E (see eq58 and 59) and keep the one giving the best ratio */ | |||
| /* - compute for the whole tracks m0 and m1 (64 values) the values C^2 and E (keeping the m2 and m3 previously computed) and save the one giving the best ratio */ | |||
| for (m3Base=3; m3Base<5; m3Base++) { | |||
| for(mIndex=0; mIndex<2; mIndex++) { | |||
| /* define for this loop on m3 track the Correlation and Energy giving the maximum of eq53 */ | |||
| word32_t m3TrackCorrelationSquare = -1; | |||
| word32_t m3TrackEnergy = 1; | |||
| /* Loop on the two maxima of correlation in the m2 index */ | |||
| int firstM2 = 0; /* save the first maximum index to not select it again */ | |||
| word16_t correlationM2M3Max = 0; /* stores the contribution of m2 and m3 impulses to the correlation for the maximum selected */ | |||
| word32_t energyM2M3Max = 0; /* same thing but for the energy */ | |||
| for (i=0; i<2; i++) { | |||
| word16_t correlationM2 = -1; | |||
| int currentM2=0; | |||
| for (j=mSwitch[mIndex][0]; j<L_SUBFRAME; j+=5) { /* in the m2 range, find the correlation Max -> select m2 */ | |||
| if (correlationSignal[j]>correlationM2 && j!=firstM2) { | |||
| currentM2 = j; | |||
| correlationM2=correlationSignal[j]; | |||
| } | |||
| } | |||
| firstM2 = currentM2; /* to avoid selecting the same maximum at next iteration */ | |||
| word32_t energyM2 = Phi[currentM2][currentM2]; /* compute the energy with terms of eq55 using m2 only: Phi'(m2,m2) */ | |||
| /* with selected m2, test the 8 m3 possibilities for the current m3 track */ | |||
| for (j=mSwitch[mIndex][1]; j<L_SUBFRAME; j+=5) { | |||
| word16_t correlationM2M3 = ADD16(correlationM2, correlationSignal[j]); /* compute the correlation sum due to m2 and m3 pulses */ | |||
| word32_t energyM2M3 = ADD32(energyM2, ADD32(Phi[currentM2][j], Phi[j][j])); /* compute the energy if eq55 using term including m2 and m3: Phi'(m2,m2) is already in energyM2 + Phi'(m2,m3) + Phi'(m3,m3) */ | |||
| word32_t correlationM2M3Square = MULT16_16(correlationM2M3, correlationM2M3); | |||
| /* check if the current correlation/energy couple gives better results than the stored one : maximise C^2/E -> C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */ | |||
| if (MULT32_32(m3TrackEnergy,correlationM2M3Square) > MULT32_32(energyM2M3, m3TrackCorrelationSquare)) { | |||
| m3TrackCorrelationSquare = correlationM2M3Square; | |||
| m3TrackEnergy = energyM2M3; | |||
| correlationM2M3Max = correlationM2M3; | |||
| m3 = j; | |||
| m2 = currentM2; | |||
| } | |||
| } | |||
| } | |||
| energyM2M3Max = m3TrackEnergy; | |||
| /* reset the current m3 track correlationSquare and energy */ | |||
| m3TrackCorrelationSquare = -1; | |||
| m3TrackEnergy = 1; | |||
| for (i=mSwitch[mIndex][2]; i<L_SUBFRAME; i+=5) { /* test the 8 possibilities for m0 track */ | |||
| word16_t correlationM2M3M0 = ADD16(correlationM2M3Max, correlationSignal[i]); /* compute correlation with current m0 taking in account the previously selected m2 and m3 */ | |||
| word32_t energyM2M3M0 = ADD32(energyM2M3Max, ADD32(Phi[i][i], ADD32(Phi[i][m2], Phi[i][m3]))); /* add to the previously computed energy the terms of eq59 we can compute with the selected m0: Phi'(m0,m0) + Phi'(m0,m2) + Phi'(m0,m3) */ | |||
| for (j=mSwitch[mIndex][3]; j<L_SUBFRAME; j+=5) { /* test the 8 possibilities for m1 track */ | |||
| word16_t correlationM2M3M0M1 = ADD16(correlationM2M3M0, correlationSignal[j]); /* compute correlation with current m1 taking in account the previously selected m2, m3 and m0 */ | |||
| word32_t energyM2M3M0M1 = ADD32(energyM2M3M0, ADD32(Phi[j][i], ADD32(Phi[j][j], ADD32(Phi[j][m2], Phi[j][m3])))); /* add to the previously computed energy the terms of eq59 we can compute with the selected m1: Phi'(m1,m0) + Phi'(m1,m1) + Phi'(m1,m2) + Phi'(m1,m3) */ | |||
| word32_t correlationM2M3M0M1Square = MULT16_16(correlationM2M3M0M1, correlationM2M3M0M1); | |||
| /* check if the current correlation/energy couple gives better results than the stored one : maximise C^2/E -> C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */ | |||
| if (MULT32_32(m3TrackEnergy,correlationM2M3M0M1Square) > MULT32_32(energyM2M3M0M1, m3TrackCorrelationSquare)) { | |||
| m3TrackCorrelationSquare = correlationM2M3M0M1Square; | |||
| m3TrackEnergy = energyM2M3M0M1; | |||
| m1 = j; | |||
| m0 = i; | |||
| } | |||
| } | |||
| } | |||
| /* check with currently selected indexes if this one is better */ | |||
| if (MULT32_32(energyMax,m3TrackCorrelationSquare) > MULT32_32(m3TrackEnergy, correlationSquareMax)) { | |||
| correlationSquareMax = m3TrackCorrelationSquare; | |||
| energyMax = m3TrackEnergy; | |||
| if (mIndex==0) { | |||
| i0 = m0; | |||
| i1 = m1; | |||
| i2 = m2; | |||
| i3 = m3; | |||
| } else { | |||
| i0 = m3; | |||
| i1 = m0; | |||
| i2 = m1; | |||
| i3 = m2; | |||
| } | |||
| jx = m3Base - 3; /* needed for parameter computation apec 3.8.2 eq62 */ | |||
| } | |||
| } | |||
| mSwitch[0][1]++; mSwitch[1][0]++; /*increment the m3Base into the mSwitch */ | |||
| } | |||
| /* compute the fixedCodebookVector */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| fixedCodebookVector[i] = 0; /* reset the vector */ | |||
| } | |||
| /* set the four pulses, in Q13 */ | |||
| fixedCodebookVector[i0] = SHL((word16_t)correlationSignalSign[i0], 13); | |||
| fixedCodebookVector[i1] = SHL((word16_t)correlationSignalSign[i1], 13); | |||
| fixedCodebookVector[i2] = SHL((word16_t)correlationSignalSign[i2], 13); | |||
| fixedCodebookVector[i3] = SHL((word16_t)correlationSignalSign[i3], 13); | |||
| /* adapt it according to eq48 */ | |||
| for (i=intPitchDelay; i<L_SUBFRAME; i++) { | |||
| fixedCodebookVector[i] = MAC16_16_Q14(fixedCodebookVector[i], fixedCodebookVector[i-intPitchDelay], lastQuantizedAdaptativeCodebookGain); /* h[n] = h[n] + β*h[n-T], fixedCodebookVector in Q13, lastQuantizedAdaptativeCodebookGain in Q14 */ | |||
| } | |||
| /* compute the parameters */ | |||
| *fixedCodebookParameter = (uint16_t)( MULT16_16_Q15((word16_t)i0, O2_IN_Q15) | |||
| + ((MULT16_16_Q15((word16_t)i1, O2_IN_Q15))<<3) | |||
| + ((MULT16_16_Q15((word16_t)i2, O2_IN_Q15))<<6) | |||
| + ((((MULT16_16_Q15((word16_t)i3, O2_IN_Q15))<<1)+jx)<<9) | |||
| ); | |||
| *fixedCodebookPulsesSigns = (uint16_t)((correlationSignalSign[i0]+1)>>1) | /* as in spec 3.8.2 eq61 */ | |||
| (uint16_t)(((correlationSignalSign[i1]+1)>>1)<<1) | | |||
| (uint16_t)(((correlationSignalSign[i2]+1)>>1)<<2) | | |||
| (uint16_t)(((correlationSignalSign[i3]+1)>>1)<<3); | |||
| /* compute the fixedCodebook vector convolved with impulse response spec 3.9 eq64 */ | |||
| /* this vector is used in gain quantization but computed here because it's faster doing it having directly the impulses positions */ | |||
| /* eq64 make use of fixedCodebook vector adapted by eq48, using the impulse position(and thus fixed codebook vector before the adaptation) but */ | |||
| /* the impulse response adapted as in eq49 gives the same output */ | |||
| /* reset the vector */ | |||
| for (i=0; i<i0; i++) fixedCodebookVectorConvolved[i] = 0; | |||
| if(correlationSignalSign[i0] > 0) { | |||
| for(i=i0, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = impulseResponse[j]; | |||
| } | |||
| } else { | |||
| for(i=i0, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = -impulseResponse[j]; | |||
| } | |||
| } | |||
| if(correlationSignalSign[i1] > 0) { | |||
| for(i=i1, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } else { | |||
| for(i=i1, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } | |||
| if(correlationSignalSign[i2] > 0) { | |||
| for(i=i2, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } else { | |||
| for(i=i2, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } | |||
| if(correlationSignalSign[i3] > 0) { | |||
| for(i=i3, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = ADD16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } else { | |||
| for(i=i3, j=0; i<L_SUBFRAME; i++, j++) { | |||
| fixedCodebookVectorConvolved[i] = SUB16(fixedCodebookVectorConvolved[i], impulseResponse[j]); | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* computeImpulseResponseCorrelationMatrix: as in spec 3.8.1 eq51, eq56, eq57*/ | |||
| /* parameters: */ | |||
| /* -(i) impulseResponse : 40 values in Q12 */ | |||
| /* -(i/o) correlationSignal: 40 values in Q12 get absolute value of */ | |||
| /* input as output as specified in spec 3.8.1 */ | |||
| /* -(o) correlationSignalSign : 40 values of -1 or 1 : the sign of */ | |||
| /* the input correlationSignal elements */ | |||
| /* */ | |||
| /* return value: a triangular matrix composed of Phi(i,j) in Q24 */ | |||
| /* where Phi(i,j) = ∑h(n-i)*h(n-j) n in i..39 */ | |||
| /* The matrix is then modified as decribed in eq56 and eq 57 */ | |||
| /* */ | |||
| /* Algorithm : the matrix elements are computed for j<=i */ | |||
| /* due to matrix element definition we have */ | |||
| /* Phi(i,j) = Phi(i+1,j+1) + h(39-i)*h(39-j) */ | |||
| /* - The matrix is computed starting from element Phi(39,x)=h(0)*h(39-x) */ | |||
| /* and adding terms h(39-i)*h(39-j) give all the element of the diagonal */ | |||
| /* up to Phi(39-x,0) */ | |||
| /* - Some diagonals are not computed because not needed : */ | |||
| /* Phi(39,34), Phi(39,29), Phi(39,24), .. Phi(39,4) */ | |||
| /* - The matrix elements signs are then adjusted according to eq56 */ | |||
| /* - The correlationSignal is modified to get absolute values of each */ | |||
| /* element in it. */ | |||
| /* - Matrix elements are then duplicated to make access to them easier */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME]) | |||
| { | |||
| int i,j,iComp; | |||
| /* first compute the diagonal Phi(x,x) : Phi(39,39) = h[0]^2 # Phi(38,38) = Phi(39,39)+h[1]^2 */ | |||
| /* this diagonal must be divided by 2 according to spec 3.8.1 eq57 */ | |||
| word32_t acc = 0; | |||
| for (i=0, iComp=L_SUBFRAME-1; i<L_SUBFRAME; i++, iComp--) { /* i in [0..39], iComp in [39..0] */ | |||
| acc = MAC16_16(acc, impulseResponse[i], impulseResponse[i]); /* impulseResponse in Q12 -> acc in Q24 */ | |||
| Phi[iComp][iComp] = SHR(acc,1); /* divide by 2: eq57*/ | |||
| } | |||
| /* check for possible overflow: Phi will be summed 10 times, so max Phi (by construction Phi[0][0]*2 is the max of Phi-> 2*Phi[0][0]*10 must be < 0x7fff ffff -> Phi[0][0]< 0x06666666 - otherwise scale Phi)*/ | |||
| uint16_t PhiScaling = 0; | |||
| if (Phi[0][0]>0x6666666) { | |||
| PhiScaling = 3 - countLeadingZeros((Phi[0][0]<<1) + 0x3333333); /* complement 0xccccccc adding 0x3333333 to shift by one when max(2*Phi[0][0]) is in 0x0fffffff < max < 0xcccccc */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| Phi[i][i] = SHR(Phi[i][i],PhiScaling); | |||
| } | |||
| } | |||
| /* Compute all diagonals but the 34, 29, 24, 19, 14, 9 and 4*/ | |||
| for (i=0; i<8; i++) { | |||
| for (j=0; j<4; j++) { | |||
| computePhiDiagonal(5*i+j, impulseResponse, Phi, PhiScaling); | |||
| } | |||
| } | |||
| /* correlationSignal -> absolute value and get sign (and his inverse in an array) */ | |||
| int correlationSignalSignInv[L_SUBFRAME]; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (correlationSignal[i] >= 0) { | |||
| correlationSignalSign[i] = 1; | |||
| correlationSignalSignInv[i] = -1; | |||
| } else { /* correlationSignal < 0 */ | |||
| correlationSignalSign[i] = -1; | |||
| correlationSignalSignInv[i] = 1; | |||
| correlationSignal[i] = -correlationSignal[i]; | |||
| } | |||
| } | |||
| /* modify the signs according to eq56 */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| int *signOfCorrelationSignalJ; | |||
| if (correlationSignalSign[i]>0) { /* is sign(correlationSignal[i]) is positive, use the correlationSignalSign otherwise the inverted one */ | |||
| signOfCorrelationSignalJ = correlationSignalSign; | |||
| } else { | |||
| signOfCorrelationSignalJ = correlationSignalSignInv; | |||
| } | |||
| for (j=0; j<=i; j++) { /* multiply by the selected sign the matrix element */ | |||
| /* Note : even the not needed and thus not computed elements are multiplicated... might found other way to do this sign stuff to be more efficient */ | |||
| Phi[i][j] = Phi[i][j] * signOfCorrelationSignalJ[j]; | |||
| } | |||
| } | |||
| /* duplicate the usefull values to their symetric part to get easier acces to the matrix elements */ | |||
| for (i=0; i<8; i++) { | |||
| for (j=0; j<4; j++) { | |||
| int k; | |||
| int startIndex = 5*i+j; | |||
| for(k=0; k<=startIndex; k++) { | |||
| Phi[startIndex-k][L_SUBFRAME-1-k] = Phi[L_SUBFRAME-1-k][startIndex-k]; | |||
| } | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| /* compute a diagonal of Phi values: start from Phi(39,j) and step Phi(38, j-1) down to Phi(39-j, 0) */ | |||
| /* Phi(i,j) = Phi(i+1,j+1) + h(39-i)*h(39-j) */ | |||
| void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling) | |||
| { | |||
| word32_t acc = 0; | |||
| int i=L_SUBFRAME -1; | |||
| int iComp = 0; | |||
| int jComp = L_SUBFRAME - 1 - j; | |||
| if (PhiScaling == 0) { | |||
| for (; j>=0; j--, i--, jComp++, iComp++) { | |||
| acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]); | |||
| Phi[i][j] = acc; | |||
| } | |||
| } else { | |||
| for (; j>=0; j--, i--, jComp++, iComp++) { | |||
| acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]); | |||
| Phi[i][j] = SHR(acc,PhiScaling); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,225 @@ | |||
| /* | |||
| gainQuantization.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "codebooks.h" | |||
| #include "gainQuantization.h" | |||
| void initGainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext) | |||
| { | |||
| /*init previousGainPredictionError to -14 in Q10 */ | |||
| encoderChannelContext->previousGainPredictionError[0] = -14336; | |||
| encoderChannelContext->previousGainPredictionError[1] = -14336; | |||
| encoderChannelContext->previousGainPredictionError[2] = -14336; | |||
| encoderChannelContext->previousGainPredictionError[3] = -14336; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* gainQuantization : compute quantized adaptative and fixed codebooks gains */ | |||
| /* spec 3.9 */ | |||
| /* parameters: */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) targetSignal: 40 values in Q0, x in eq63 */ | |||
| /* -(i) filteredAdaptativeCodebookVector: 40 values in Q0, y in eq63 */ | |||
| /* -(i) convolvedFixedCodebookVector: 40 values in Q12, z in eq63 */ | |||
| /* -(i) fixedCodebookVector: 40 values in Q13 */ | |||
| /* -(i) xy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* -(i) yy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* -(o) quantizedAdaptativeCodebookGain : in Q14 */ | |||
| /* -(o) quantizedFixedCodebookGain : in Q1 */ | |||
| /* -(o) gainCodebookStage1 : GA parameter value (3 bits) */ | |||
| /* -(o) gainCodebookStage2 : GB parameter value (4 bits) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word16_t convolvedFixedCodebookVector[], word16_t fixedCodebookVector[], word64_t xy64, word64_t yy64, | |||
| word16_t *quantizedAdaptativeCodebookGain, word16_t *quantizedFixedCodebookGain, uint16_t *gainCodebookStage1, uint16_t *gainCodebookStage2) | |||
| { | |||
| int i,j; | |||
| /*** compute spec 3.9 eq63 terms first on 64 bits and then scale them if needed to fit on 32 ***/ | |||
| /* Xy64 and Yy64 already computed during adaptativeCodebookGain computation */ | |||
| word64_t xz64=0, yz64=0, zz64=0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| xz64 = MAC64(xz64, targetSignal[i], convolvedFixedCodebookVector[i]); /* in Q12 */ | |||
| yz64 = MAC64(yz64, filteredAdaptativeCodebookVector[i], convolvedFixedCodebookVector[i]); /* in Q12 */ | |||
| zz64 = MAC64(zz64, convolvedFixedCodebookVector[i], convolvedFixedCodebookVector[i]); /* in Q24 */ | |||
| } | |||
| /* now scale this terms to have them fit on 32 bits - terms Xy, Xz and Yz shall fit on 31 bits because used in eq63 with a factor 2 */ | |||
| word32_t xy = SHR64(((xy64<0)?-xy64:xy64),30); | |||
| word32_t yy = SHR64(yy64,31); | |||
| word32_t xz = SHR64(((xz64<0)?-xz64:xz64),30); | |||
| word32_t yz = SHR64(((yz64<0)?-yz64:yz64),30); | |||
| word32_t zz = SHR64(zz64,31); | |||
| uint16_t minNormalization = 31; | |||
| uint16_t currentNormalization; | |||
| currentNormalization = countLeadingZeros(xy); | |||
| if (currentNormalization<minNormalization) { | |||
| minNormalization = currentNormalization; | |||
| } | |||
| currentNormalization = countLeadingZeros(xz); | |||
| if (currentNormalization<minNormalization) { | |||
| minNormalization = currentNormalization; | |||
| } | |||
| currentNormalization = countLeadingZeros(yz); | |||
| if (currentNormalization<minNormalization) { | |||
| minNormalization = currentNormalization; | |||
| } | |||
| currentNormalization = countLeadingZeros(yy); | |||
| if (currentNormalization<minNormalization) { | |||
| minNormalization = currentNormalization; | |||
| } | |||
| currentNormalization = countLeadingZeros(zz); | |||
| if (currentNormalization<minNormalization) { | |||
| minNormalization = currentNormalization; | |||
| } | |||
| if (minNormalization<31) { /* we shall normalise, values are over 32 bits */ | |||
| minNormalization = 31 - minNormalization; | |||
| xy = (word32_t)SHR64(xy64, minNormalization); | |||
| yy = (word32_t)SHR64(yy64, minNormalization); | |||
| xz = (word32_t)SHR64(xz64, minNormalization); | |||
| yz = (word32_t)SHR64(yz64, minNormalization); | |||
| zz = (word32_t)SHR64(zz64, minNormalization); | |||
| } else { /* no need to normalise, values already fit on 32 bits, just cast them */ | |||
| xy = (word32_t)xy64; /* in Q0 */ | |||
| yy = (word32_t)yy64; /* in Q0 */ | |||
| xz = (word32_t)xz64; /* in Q12 */ | |||
| yz = (word32_t)yz64; /* in Q12 */ | |||
| zz = (word32_t)zz64; /* in Q24 */ | |||
| } | |||
| /*** compute the best gains minimizinq eq63 ***/ | |||
| /* Note this bestgain computation is not at all described in the spec, got it from ITU code */ | |||
| /* bestAdaptativeCodebookGain = (zz.xy - xz.yz) / (yy*zz) - yz^2) */ | |||
| /* bestfixedCodebookGain = (yy*xz - xy*yz) / (yy*zz) - yz^2) */ | |||
| /* best gain are computed in Q9 and Q2 and fits on 16 bits */ | |||
| word32_t bestAdaptativeCodebookGain, bestFixedCodebookGain; | |||
| word64_t denominator = MAC64(MULT32_32(yy, zz), -yz, yz); /* (yy*zz) - yz^2) in Q24 (always >= 0)*/ | |||
| /* avoid division by zero */ | |||
| if (denominator==0) { /* consider it to be one */ | |||
| bestAdaptativeCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(zz, xy), -xz, yz), 15)); /* MAC in Q24 -> Q9 */ | |||
| bestFixedCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(yy, xz), -xy, yz), 10)); /* MAC in Q12 -> Q2 */ | |||
| } else { | |||
| /* bestAdaptativeCodebookGain in Q9 */ | |||
| word64_t numerator = MAC64(MULT32_32(zz, xy), -xz, yz); /* in Q24 */ | |||
| /* check if we can shift it by 9 without overflow as the bestAdaptativeCodebookGain in computed in Q9 */ | |||
| word32_t numeratorH = (word32_t)(SHR64(numerator,32)); | |||
| numeratorH = (numeratorH>0)?numeratorH:-numeratorH; | |||
| uint16_t numeratorNorm = countLeadingZeros(numeratorH); | |||
| if (numeratorNorm >= 9) { | |||
| bestAdaptativeCodebookGain = (word32_t)(DIV64(SHL64(numerator,9), denominator)); /* bestAdaptativeCodebookGain in Q9 */ | |||
| } else { | |||
| word64_t shiftedDenominator = SHR64(denominator, 9-numeratorNorm); | |||
| if (shiftedDenominator>0) { /* can't shift left by 9 the numerator, can we shift right by 9-numeratorNorm the denominator without hiting 0 */ | |||
| bestAdaptativeCodebookGain = (word32_t)(DIV64(SHL64(numerator, numeratorNorm),shiftedDenominator)); /* bestAdaptativeCodebookGain in Q9 */ | |||
| } else { | |||
| bestAdaptativeCodebookGain = SHL((word32_t)(DIV64(SHL64(numerator, numeratorNorm), denominator)), 9-numeratorNorm); /* shift left the division result to reach Q9 */ | |||
| } | |||
| } | |||
| numerator = MAC64(MULT32_32(yy, xz), -xy, yz); /* in Q12 */ | |||
| /* check if we can shift it by 14(it's in Q12 and denominator in Q24) without overflow as the bestFixedCodebookGain in computed in Q2 */ | |||
| numeratorH = (word32_t)(SHR64(numerator,32)); | |||
| numeratorH = (numeratorH>0)?numeratorH:-numeratorH; | |||
| numeratorNorm = countLeadingZeros(numeratorH); | |||
| if (numeratorNorm >= 14) { | |||
| bestFixedCodebookGain = (word32_t)(DIV64(SHL64(numerator,14), denominator)); | |||
| } else { | |||
| word64_t shiftedDenominator = SHR64(denominator, 14-numeratorNorm); /* bestFixedCodebookGain in Q14 */ | |||
| if (shiftedDenominator>0) { /* can't shift left by 9 the numerator, can we shift right by 9-numeratorNorm the denominator without hiting 0 */ | |||
| bestFixedCodebookGain = (word32_t)(DIV64(SHL64(numerator, numeratorNorm),shiftedDenominator)); /* bestFixedCodebookGain in Q14 */ | |||
| } else { | |||
| bestFixedCodebookGain = SHL((word32_t)(DIV64(SHL64(numerator, numeratorNorm), denominator)), 14-numeratorNorm); /* shift left the division result to reach Q14 */ | |||
| } | |||
| } | |||
| } | |||
| /*** Compute the predicted gain as in spec 3.9.1 eq71 in Q6 ***/ | |||
| word16_t predictedFixedCodebookGain = (word16_t)(SHR32(MACodeGainPrediction(encoderChannelContext->previousGainPredictionError, fixedCodebookVector), 12)); /* in Q16 -> Q4 range [3,1830] */ | |||
| /*** preselection spec 3.9.2 ***/ | |||
| /* Note: spec just says to select the best 50% of each vector, ITU code go through magical constant computation to select the begining of a continuous range */ | |||
| /* much more simple here : vector are ordened in growing order so just select 2 (4 for Gb) indexes before the first value to be superior to the best gain previously computed */ | |||
| uint16_t indexBaseGa=0; | |||
| uint16_t indexBaseGb=0; | |||
| while (indexBaseGa<6 && bestFixedCodebookGain>(MULT16_16_Q14(GACodebook[indexBaseGa][1],predictedFixedCodebookGain))) { /* bestFixedCodebookGain> in Q2, GACodebook in Q12 *predictedFixedCodebookGain in Q4 -> Q16-14 */ | |||
| indexBaseGa++; | |||
| } | |||
| if (indexBaseGa>0) indexBaseGa--; | |||
| if (indexBaseGa>0) indexBaseGa--; | |||
| while (indexBaseGb<12 && bestAdaptativeCodebookGain>(SHR(GBCodebook[indexBaseGb][0],5))) { | |||
| indexBaseGb++; | |||
| } | |||
| if (indexBaseGb>0) indexBaseGb--; | |||
| if (indexBaseGb>0) indexBaseGb--; | |||
| if (indexBaseGb>0) indexBaseGb--; | |||
| if (indexBaseGb>0) indexBaseGb--; | |||
| /*** test all possibilities of Ga and Gb indexes and select the best one ***/ | |||
| uint16_t indexGa=0, indexGb=0; | |||
| xy = -SHL(xy,1); /* xy term is always used with a -2 factor */ | |||
| xz = -SHL(xz,1); /* xz term is always used with a -2 factor */ | |||
| yz = SHL(yz,1); /* yz term is always used with a 2 factor */ | |||
| word64_t distanceMin = MAXINT64; | |||
| for (i=0; i<4; i++) { | |||
| for (j=0; j<8; j++) { | |||
| /* compute gamma->gc and gp */ | |||
| word16_t gp = ADD16(GACodebook[i+indexBaseGa][0], GBCodebook[j+indexBaseGb][0]); /* result in Q14 */ | |||
| word16_t gamma = ADD16(GACodebook[i+indexBaseGa][1], GBCodebook[j+indexBaseGb][1]); /* result in Q3.12 (range [0.185, 5.05])*/ | |||
| word32_t gc = MULT16_16_Q14(gamma, predictedFixedCodebookGain); /* gamma in Q12, predictedFixedCodebookGain in Q4 -> Q16 -14 -> Q2 */ | |||
| /* compute E as in eq63 (first term excluded) */ | |||
| word64_t acc = MULT32_32(MULT16_16(gp, gp), yy); /* acc = gp^2*yy gp in Q14, yy in Q0 -> acc in Q28 */ | |||
| acc = MAC64(acc, MULT16_16(gc, gc), zz); /* gc in Q2, zz in Q24 -> acc in Q28, note gc is on 32 bits but in a range making gc^2 fitting on 32 bits */ | |||
| acc = MAC64(acc, SHL32((word32_t)gp, 14), xy); /* gp in Q14 shifted to Q28, xy in Q0 -> acc in Q28 */ | |||
| acc = MAC64(acc, SHL32(gc, 14), xz); /* gc in Q2 shifted to Q16, xz in Q12 -> acc in Q28 */ | |||
| acc = MAC64(acc, MULT16_16(gp,gc), yz); /* gp in Q14, gc in Q2 yz in Q12 -> acc in Q28 */ | |||
| if (acc<distanceMin) { | |||
| distanceMin = acc; | |||
| indexGa = i+indexBaseGa; | |||
| indexGb = j+indexBaseGb; | |||
| *quantizedAdaptativeCodebookGain = gp; | |||
| *quantizedFixedCodebookGain = (word16_t)SHR(gc, 1); | |||
| } | |||
| } | |||
| } | |||
| /* update the previous gain prediction error */ | |||
| computeGainPredictionError(ADD16(GACodebook[indexGa][1], GBCodebook[indexGb][1]), encoderChannelContext->previousGainPredictionError); | |||
| /* mapping of indexes */ | |||
| *gainCodebookStage1 = indexMappingGA[indexGa]; | |||
| *gainCodebookStage2 = indexMappingGB[indexGb]; | |||
| return; | |||
| } | |||
| @ -0,0 +1,41 @@ | |||
| /* | |||
| interpolateqLSP.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| /*****************************************************************************/ | |||
| /* interpolateqLSP : interpolate previous and current qLSP according to */ | |||
| /* spec. 3.2.5 : interpolated = (current+previous)/2 */ | |||
| /* parameters: */ | |||
| /* -(i) previousqLSP : 10 values in Q0.15: the qLSP of previous frame */ | |||
| /* -(i) currentqLSP : 10 values in Q0.15: the qLSP of current frame */ | |||
| /* -(o) interpolatedqLSP : 10 values in Q0.15 : the interpolated qLSP */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void interpolateqLSP(word16_t previousqLSP[], word16_t currentqLSP[], word16_t interpolatedqLSP[]) | |||
| { /* interpolate previous and current qLSP according to spec. 3.2.5 : interpolated = (current+previous)/2 */ | |||
| int i; | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| interpolatedqLSP[i] = (word16_t)PSHR(ADD32(previousqLSP[i], currentqLSP[i]),1); | |||
| } | |||
| } | |||
| @ -0,0 +1,342 @@ | |||
| /* | |||
| postFilter.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "utils.h" | |||
| #include "g729FixedPointMath.h" | |||
| /* init function */ | |||
| void initPostFilter(bcg729DecoderChannelContextStruct *decoderChannelContext) | |||
| { | |||
| /* set to zero the residual signal memory */ | |||
| memset(decoderChannelContext->residualSignalBuffer, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); | |||
| memset(decoderChannelContext->scaledResidualSignalBuffer, 0, MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); | |||
| /* set to zero the one word of longTermFilteredResidualSignal needed as memory for tilt compensation filter */ | |||
| decoderChannelContext->longTermFilteredResidualSignalBuffer[0] = 0; | |||
| decoderChannelContext->longTermFilteredResidualSignal = &(decoderChannelContext->longTermFilteredResidualSignalBuffer[1]); /* init the pointer to the begining of longTermFilteredResidualSignal current subframe */ | |||
| /* intialise the shortTermFilteredResidualSignal filter memory and pointer*/ | |||
| memset(decoderChannelContext->shortTermFilteredResidualSignalBuffer, 0, NB_LSP_COEFF*sizeof(word16_t)); | |||
| decoderChannelContext->shortTermFilteredResidualSignal = &(decoderChannelContext->shortTermFilteredResidualSignalBuffer[NB_LSP_COEFF]); | |||
| /* initialise the previous Gain for adaptative gain control */ | |||
| decoderChannelContext->previousAdaptativeGain = 4096; /* 1 in Q12 */ | |||
| } | |||
| /*****************************************************************************/ | |||
| /* postFilter: filter the reconstructed speech according to spec A.4.2 */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i) LPCoefficients: 10 LP coeff for current subframe in Q12 */ | |||
| /* -(i) reconstructedSpeech: output of LP Synthesis, 50 values in Q0 */ | |||
| /* 10 values of previous subframe, accessed in range [-10, 39] */ | |||
| /* -(i) intPitchDelay: the integer part of Pitch Delay in Q0 */ | |||
| /* -(i) subframeIndex: 0 or L_SUBFRAME for subframe 0 or 1 */ | |||
| /* -(o) postFilteredSignal: 40 values in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t *LPCoefficients, word16_t *reconstructedSpeech, int16_t intPitchDelay, int subframeIndex, | |||
| word16_t *postFilteredSignal) | |||
| { | |||
| int i,j; | |||
| /********************************************************************/ | |||
| /* Long Term Post Filter */ | |||
| /********************************************************************/ | |||
| /*** Compute LPGammaN and LPGammaD coefficients : LPGamma[0] = LP[0]*Gamma^(i+1) (i=0..9) ***/ | |||
| word16_t LPGammaNCoefficients[NB_LSP_COEFF]; /* in Q12 */ | |||
| /* GAMMA_XX constants are in Q15 */ | |||
| LPGammaNCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_N1); | |||
| LPGammaNCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_N2); | |||
| LPGammaNCoefficients[2] = MULT16_16_P15(LPCoefficients[2], GAMMA_N3); | |||
| LPGammaNCoefficients[3] = MULT16_16_P15(LPCoefficients[3], GAMMA_N4); | |||
| LPGammaNCoefficients[4] = MULT16_16_P15(LPCoefficients[4], GAMMA_N5); | |||
| LPGammaNCoefficients[5] = MULT16_16_P15(LPCoefficients[5], GAMMA_N6); | |||
| LPGammaNCoefficients[6] = MULT16_16_P15(LPCoefficients[6], GAMMA_N7); | |||
| LPGammaNCoefficients[7] = MULT16_16_P15(LPCoefficients[7], GAMMA_N8); | |||
| LPGammaNCoefficients[8] = MULT16_16_P15(LPCoefficients[8], GAMMA_N9); | |||
| LPGammaNCoefficients[9] = MULT16_16_P15(LPCoefficients[9], GAMMA_N10); | |||
| /*** Compute the residual signal as described in spec 4.2.1 eq79 ***/ | |||
| /* Compute also a scaled residual signal: shift right by 2 to avoid overflows on 32 bits when computing correlation and energy */ | |||
| /* pointers to current subframe beginning */ | |||
| word16_t *residualSignal = &(decoderChannelContext->residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]); | |||
| word16_t *scaledResidualSignal = &(decoderChannelContext->scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]); | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| word32_t acc = SHL((word32_t)reconstructedSpeech[i], 12); /* reconstructedSpeech in Q0 shifted to set acc in Q12 */ | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| acc = MAC16_16(acc, LPGammaNCoefficients[j],reconstructedSpeech[i-j-1]); /* LPGammaNCoefficients in Q12, reconstructedSpeech in Q0 -> acc in Q12 */ | |||
| } | |||
| residualSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift back acc to Q0 and saturate it to avoid overflow when going back to 16 bits */ | |||
| scaledResidualSignal[i] = PSHR(residualSignal[i], 2); /* shift acc to Q-2 and saturate it to get the scaled version of the signal */ | |||
| } | |||
| /*** Compute the maximum correlation on scaledResidualSignal delayed by intPitchDelay +/- 3 to get the best delay. Spec 4.2.1 eq80 ***/ | |||
| /* using a scaled(Q-2) signals gives correlation in Q-4. */ | |||
| word32_t correlationMax = (word32_t)MININT32; | |||
| int16_t intPitchDelayMax = intPitchDelay+3; /* intPitchDelayMax shall be < MAXIMUM_INT_PITCH_DELAY(143) */ | |||
| int16_t bestIntPitchDelay = 0; | |||
| word16_t *delayedResidualSignal; | |||
| if (intPitchDelayMax>MAXIMUM_INT_PITCH_DELAY) { | |||
| intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY; | |||
| } | |||
| for (i=intPitchDelay-3; i<=intPitchDelayMax; i++) { | |||
| word32_t correlation = 0; | |||
| delayedResidualSignal = &(scaledResidualSignal[-i]); /* delayedResidualSignal points to scaledResidualSignal[-i] */ | |||
| /* compute correlation: ∑r(n)*rk(n) */ | |||
| for (j=0; j<L_SUBFRAME; j++) { | |||
| correlation = MAC16_16(correlation, delayedResidualSignal[j], scaledResidualSignal[j]); | |||
| } | |||
| /* if we have a maximum correlation */ | |||
| if (correlation>correlationMax) { | |||
| correlationMax = correlation; | |||
| bestIntPitchDelay = i; /* get the intPitchDelay */ | |||
| } | |||
| } | |||
| /* saturate correlation to a positive integer */ | |||
| if (correlationMax<0) { | |||
| correlationMax = 0; | |||
| } | |||
| /*** Compute the signal energy ∑r(n)*r(n) and delayed signal energy ∑rk(n)*rk(n) which shall be used to compute gl spec 4.2.1 eq81, eq 82 and eq83 ***/ | |||
| word32_t residualSignalEnergy = 0; /* in Q-4 */ | |||
| word32_t delayedResidualSignalEnergy = 0; /* in Q-4 */ | |||
| delayedResidualSignal = &(scaledResidualSignal[-bestIntPitchDelay]); /* in Q-2, points to the residual signal delayed to give the higher correlation: rk(n) */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| residualSignalEnergy = MAC16_16(residualSignalEnergy, scaledResidualSignal[i], scaledResidualSignal[i]); | |||
| delayedResidualSignalEnergy = MAC16_16(delayedResidualSignalEnergy, delayedResidualSignal[i], delayedResidualSignal[i]); | |||
| } | |||
| /*** Scale correlationMax, residualSignalEnergy and delayedResidualSignalEnergy to the best fit on 16 bits ***/ | |||
| /* these variables must fit on 16bits for the following computation, to avoid loosing information, scale them */ | |||
| /* at best fit: scale the higher of three to get the value over 2^14 and shift the other two from the same amount */ | |||
| /* Note: all three value are >= 0 */ | |||
| word32_t maximumThree = correlationMax; | |||
| if (maximumThree<residualSignalEnergy) { | |||
| maximumThree = residualSignalEnergy; | |||
| } | |||
| if (maximumThree<delayedResidualSignalEnergy) { | |||
| maximumThree = delayedResidualSignalEnergy; | |||
| } | |||
| int16_t leadingZeros = 0; | |||
| word16_t correlationMaxWord16 = 0; | |||
| word16_t residualSignalEnergyWord16 = 0; | |||
| word16_t delayedResidualSignalEnergyWord16 = 0; | |||
| if (maximumThree>0) { /* if all of them a null, just do nothing otherwise shift right to get the max number in range [0x4000,0x8000[ */ | |||
| leadingZeros = countLeadingZeros(maximumThree); | |||
| if (leadingZeros<16) { | |||
| correlationMaxWord16 = (word16_t)SHR32(correlationMax, 16-leadingZeros); | |||
| residualSignalEnergyWord16 = (word16_t)SHR32(residualSignalEnergy, 16-leadingZeros); | |||
| delayedResidualSignalEnergyWord16 = (word16_t)SHR32(delayedResidualSignalEnergy, 16-leadingZeros); | |||
| } else { /* if the values already fit on 16 bits, no need to shift */ | |||
| correlationMaxWord16 = (word16_t)correlationMax; | |||
| residualSignalEnergyWord16 = (word16_t)residualSignalEnergy; | |||
| delayedResidualSignalEnergyWord16 = (word16_t)delayedResidualSignalEnergy; | |||
| } | |||
| } | |||
| /* eq78: Hp(z)=(1 + γp*gl*z(−T))/(1 + γp*gl) -> (with g=γp*gl) Hp(z)=1/(1+g) + (g/(1+g))*z(-T) = g0 + g1*z(-T) */ | |||
| /* g = gl/2 (as γp=0.5)= (eq83) correlationMax/(2*delayedResidualSignalEnergy) */ | |||
| /* compute g0 = 1/(1+g)= delayedResidualSignalEnergy/(delayedResidualSignalEnergy+correlationMax/2) = 1-g1*/ | |||
| /* compute g1 = g/(1+g) = correlationMax/(2*delayedResidualSignalEnergy+correlationMax) = 1-g0 */ | |||
| /*** eq82 -> (correlationMax^2)/(residualSignalEnergy*delayedResidualSignalEnergy)<0.5 ***/ | |||
| /* (correlationMax^2) < (residualSignalEnergy*delayedResidualSignalEnergy)*0.5 */ | |||
| if ((MULT16_16(correlationMaxWord16, correlationMaxWord16) < SHR(MULT16_16(residualSignalEnergyWord16, delayedResidualSignalEnergyWord16), 1)) /* eq82 */ | |||
| || ((correlationMax==0) && (delayedResidualSignalEnergy==0))) { /* correlationMax and delayedResidualSignalEnergy values are 0 -> unable to compute g0 and g1 -> disable filter */ | |||
| /* long term post filter disabled */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| decoderChannelContext->longTermFilteredResidualSignal[i] = residualSignal[i]; | |||
| } | |||
| } else { /* eq82 gives long term filter enabled, */ | |||
| word16_t g0, g1; | |||
| /* eq83: gl = correlationMax/delayedResidualSignalEnergy bounded in ]0,1] */ | |||
| /* check if gl > 1 -> gl=1 -> g=1/2 -> g0=2/3 and g1=1/3 */ | |||
| if (correlationMax > delayedResidualSignalEnergy) { | |||
| g0 = 21845; /* 2/3 in Q15 */ | |||
| g1 = 10923; /* 1/3 in Q15 */ | |||
| } else { | |||
| /* g1 = correlationMax/(2*delayedResidualSignalEnergy+correlationMax) */ | |||
| g1 = DIV32((word32_t)SHL32(correlationMaxWord16,15),(word32_t)ADD32(SHL32(delayedResidualSignalEnergyWord16,1), correlationMaxWord16)); /* g1 in Q15 */ | |||
| g0 = SUB16(32767, g1); /* g0 = 1 - g1 in Q15 */ | |||
| } | |||
| /* longTermFilteredResidualSignal[i] = g0*residualSignal[i] + g1*delayedResidualSignal[i]*/ | |||
| delayedResidualSignal = &(residualSignal[-bestIntPitchDelay]); | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| decoderChannelContext->longTermFilteredResidualSignal[i] = (word16_t)SATURATE(PSHR(ADD32(MULT16_16(g0, residualSignal[i]), MULT16_16(g1, delayedResidualSignal[i])), 15), MAXINT16); | |||
| } | |||
| } | |||
| /********************************************************************/ | |||
| /* Tilt Compensation Filter */ | |||
| /********************************************************************/ | |||
| /* compute hf the truncated (to 22 coefficients) impulse response of the filter A(z/γn)/A(z/γd) described in spec 4.2.2 eq84 */ | |||
| /* hf(i) = LPGammaNCoeff[i] - ∑[j:0..9]LPGammaDCoeff[j]*hf[i-j-1]) */ | |||
| word16_t LPGammaDCoefficients[NB_LSP_COEFF]; /* in Q12 */ | |||
| /* GAMMA_XX constants are in Q15 */ | |||
| LPGammaDCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_D1); | |||
| LPGammaDCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_D2); | |||
| LPGammaDCoefficients[2] = MULT16_16_P15(LPCoefficients[2], GAMMA_D3); | |||
| LPGammaDCoefficients[3] = MULT16_16_P15(LPCoefficients[3], GAMMA_D4); | |||
| LPGammaDCoefficients[4] = MULT16_16_P15(LPCoefficients[4], GAMMA_D5); | |||
| LPGammaDCoefficients[5] = MULT16_16_P15(LPCoefficients[5], GAMMA_D6); | |||
| LPGammaDCoefficients[6] = MULT16_16_P15(LPCoefficients[6], GAMMA_D7); | |||
| LPGammaDCoefficients[7] = MULT16_16_P15(LPCoefficients[7], GAMMA_D8); | |||
| LPGammaDCoefficients[8] = MULT16_16_P15(LPCoefficients[8], GAMMA_D9); | |||
| LPGammaDCoefficients[9] = MULT16_16_P15(LPCoefficients[9], GAMMA_D10); | |||
| word16_t hf[22]; /* the truncated impulse response to short term filter Hf in Q12 */ | |||
| hf[0] = 4096; /* 1 in Q12 as LPGammaNCoefficients and LPGammaDCoefficient doesn't contain the first element which is 1 and past values of hf are 0 */ | |||
| for (i=1; i<11; i++) { | |||
| word32_t acc = (word32_t)SHL(LPGammaNCoefficients[i-1],12); /* LPGammaNCoefficients in Q12 -> acc in Q24 */ | |||
| for (j=0; j<NB_LSP_COEFF && j<i; j++) { /* j<i to avoid access to negative index of hf(past values are 0 anyway) */ | |||
| acc = MSU16_16(acc, LPGammaDCoefficients[j], hf[i-j-1]); /* LPGammaDCoefficient in Q12, hf in Q12 -> Q24 TODO: Possible overflow?? */ | |||
| } | |||
| hf[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* get result back in Q12 and saturate on 16 bits */ | |||
| } | |||
| for (i=11; i<22; i++) { | |||
| word32_t acc = 0; | |||
| for (j=0; j<NB_LSP_COEFF; j++) { /* j<i to avoid access to negative index of hf(past values are 0 anyway) */ | |||
| acc = MSU16_16(acc, LPGammaDCoefficients[j], hf[i-j-1]); /* LPGammaDCoefficient in Q12, hf in Q12 -> Q24 TODO: Possible overflow?? */ | |||
| } | |||
| hf[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* get result back in Q12 and saturate on 16 bits */ | |||
| } | |||
| /* hf is then used to compute k'1 spec 4.2.3 eq87: k'1 = -rh1/rh0 */ | |||
| /* rh0 = ∑[i:0..21]hf[i]*hf[i] */ | |||
| /* rh1 = ∑[i:0..20]hf[i]*hf[i+1] */ | |||
| word32_t rh1 = MULT16_16(hf[0], hf[1]); | |||
| for (i=1; i<21; i++) { | |||
| rh1 = MAC16_16(rh1, hf[i], hf[i+1]); /* rh1 in Q24 */ | |||
| } | |||
| /* tiltCompensationGain is set to 0 if k'1>0 -> rh1<0 (as rh0 is always>0) */ | |||
| word16_t tiltCompensatedSignal[L_SUBFRAME]; /* in Q0 */ | |||
| if (rh1<0) { /* tiltCompensationGain = 0 -> no gain filter is off, just copy the input */ | |||
| memcpy(tiltCompensatedSignal, decoderChannelContext->longTermFilteredResidualSignal, L_SUBFRAME*sizeof(word16_t)); | |||
| } else { /*compute tiltCompensationGain = k'1*γt */ | |||
| word32_t rh0 = MULT16_16(hf[0], hf[0]); | |||
| for (i=1; i<22; i++) { | |||
| rh0 = MAC16_16(rh0, hf[i], hf[i]); /* rh0 in Q24 */ | |||
| } | |||
| rh1 = MULT16_32_Q15(GAMMA_T, rh1); /* GAMMA_T in Q15, rh1 in Q24*/ | |||
| word16_t tiltCompensationGain = (word16_t)SATURATE((word32_t)(DIV32(rh1,PSHR(rh0,12))), MAXINT16); /* rh1 in Q24, PSHR(rh0,12) in Q12 -> tiltCompensationGain in Q12 */ | |||
| /* compute filter Ht (spec A.4.2.3 eqA14) = 1 + gain*z(-1) */ | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| tiltCompensatedSignal[i] = MSU16_16_Q12(decoderChannelContext->longTermFilteredResidualSignal[i], tiltCompensationGain, decoderChannelContext->longTermFilteredResidualSignal[i-1]); | |||
| } | |||
| } | |||
| /* update memory word of longTermFilteredResidualSignal for next subframe */ | |||
| decoderChannelContext->longTermFilteredResidualSignal[-1] = decoderChannelContext->longTermFilteredResidualSignal[L_SUBFRAME-1]; | |||
| /********************************************************************/ | |||
| /* synthesis filter 1/[Â(z /γd)] spec A.4.2.2 */ | |||
| /* */ | |||
| /* Note: Â(z/γn) was done before when computing residual signal */ | |||
| /********************************************************************/ | |||
| /* shortTermFilteredResidualSignal is accessed in range [-NB_LSP_COEFF,L_SUBFRAME[ */ | |||
| synthesisFilter(tiltCompensatedSignal, LPGammaDCoefficients, decoderChannelContext->shortTermFilteredResidualSignal); | |||
| /* get the last NB_LSP_COEFF of shortTermFilteredResidualSignal and set them as memory for next subframe(they do not overlap so use memcpy) */ | |||
| memcpy(decoderChannelContext->shortTermFilteredResidualSignalBuffer, &(decoderChannelContext->shortTermFilteredResidualSignalBuffer[L_SUBFRAME]), NB_LSP_COEFF*sizeof(word16_t)); | |||
| /********************************************************************/ | |||
| /* Adaptive Gain Control spec A.4.2.4 */ | |||
| /* */ | |||
| /********************************************************************/ | |||
| /*** compute G(gain scaling factor) according to eqA15 : G = Sqrt((∑s(n)^2)/∑sf(n)^2 ) ***/ | |||
| word16_t gainScalingFactor; /* in Q12 */ | |||
| /* compute ∑sf(n)^2 scale the signal shifting left by 2 to avoid overflow on 32 bits sum */ | |||
| word32_t shortTermFilteredResidualSignalSquareSum = 0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| shortTermFilteredResidualSignalSquareSum = MAC16_16_Q4(shortTermFilteredResidualSignalSquareSum, decoderChannelContext->shortTermFilteredResidualSignal[i], decoderChannelContext->shortTermFilteredResidualSignal[i]); | |||
| } | |||
| /* if the sum is null we can't compute gain -> output of postfiltering is the output of shortTermFilter and previousAdaptativeGain is set to 0 */ | |||
| /* the reset of previousAdaptativeGain is not mentionned in the spec but in ITU code only */ | |||
| if (shortTermFilteredResidualSignalSquareSum == 0) { | |||
| decoderChannelContext->previousAdaptativeGain = 0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| postFilteredSignal[i] = decoderChannelContext->shortTermFilteredResidualSignal[i]; | |||
| } | |||
| } else { /* we can compute adaptativeGain and output signal */ | |||
| /* compute ∑s(n)^2 scale the signal shifting left by 2 to avoid overflow on 32 bits sum */ | |||
| word32_t reconstructedSpeechSquareSum = 0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| reconstructedSpeechSquareSum = MAC16_16_Q4(reconstructedSpeechSquareSum, reconstructedSpeech[i], reconstructedSpeech[i]); | |||
| } | |||
| if (reconstructedSpeechSquareSum==0) { /* numerator is null -> current gain is null */ | |||
| gainScalingFactor = 0; | |||
| } else { | |||
| /* Compute ∑s(n)^2)/∑sf(n)^2 result shall be in Q10 */ | |||
| /* normalise the numerator on 32 bits */ | |||
| word16_t numeratorShift = countLeadingZeros(reconstructedSpeechSquareSum); | |||
| reconstructedSpeechSquareSum = SHL(reconstructedSpeechSquareSum, numeratorShift); /* reconstructedSpeechSquareSum*2^numeratorShift */ | |||
| /* normalise denominator to get the result directly in Q10 if possible */ | |||
| word32_t fractionResult; /* stores ∑s(n)^2)/∑sf(n)^2 */ | |||
| word32_t scaledShortTermFilteredResidualSignalSquareSum = VSHR32(shortTermFilteredResidualSignalSquareSum, 10-numeratorShift); /* shortTermFilteredResidualSignalSquareSum*2^(numeratorShift-10)*/ | |||
| if (scaledShortTermFilteredResidualSignalSquareSum==0) {/* shift might have sent to zero the denominator */ | |||
| fractionResult = DIV32(reconstructedSpeechSquareSum, shortTermFilteredResidualSignalSquareSum); /* result in QnumeratorShift */ | |||
| fractionResult = VSHR32(fractionResult, numeratorShift-10); /* result in Q10 */ | |||
| } else { /* ok denominator is still > 0 */ | |||
| fractionResult = DIV32(reconstructedSpeechSquareSum, scaledShortTermFilteredResidualSignalSquareSum); /* result in Q10 */ | |||
| } | |||
| /* now compute current Gain = Sqrt((∑s(n)^2)/∑sf(n)^2 ) */ | |||
| /* g729Sqrt_Q0Q7(Q0)->Q7, by giving a Q10 as input, output is in Q12 */ | |||
| gainScalingFactor = (word16_t)SATURATE(g729Sqrt_Q0Q7(fractionResult), MAXINT16); | |||
| /* multiply by 0.1 as described in spec A.4.2.4 */ | |||
| gainScalingFactor = MULT16_16_P15(gainScalingFactor, 3277); /* in Q12, 3277 = 0.1 in Q15*/ | |||
| } | |||
| /* Compute the signal according to eq89 (spec 4.2.4 and section A4.2.4) */ | |||
| /* currentGain = 0.9*previousGain + 0.1*gainScalingFactor the 0.1 factor has already been integrated in the variable gainScalingFactor */ | |||
| /* outputsignal = currentGain*shortTermFilteredResidualSignal */ | |||
| word16_t currentAdaptativeGain = decoderChannelContext->previousAdaptativeGain; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| currentAdaptativeGain = ADD16(gainScalingFactor, MULT16_16_P15(currentAdaptativeGain, 29491)); /* 29492 = 0.9 in Q15, result in Q12 */ | |||
| postFilteredSignal[i] = MULT16_16_Q12(currentAdaptativeGain, decoderChannelContext->shortTermFilteredResidualSignal[i]); | |||
| } | |||
| decoderChannelContext->previousAdaptativeGain = currentAdaptativeGain; | |||
| } | |||
| /* shift buffers if needed */ | |||
| if (subframeIndex>0) { /* only after 2nd subframe treatment */ | |||
| /* shift left by L_FRAME the residualSignal and scaledResidualSignal buffers */ | |||
| memmove(decoderChannelContext->residualSignalBuffer, &(decoderChannelContext->residualSignalBuffer[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); | |||
| memmove(decoderChannelContext->scaledResidualSignalBuffer, &(decoderChannelContext->scaledResidualSignalBuffer[L_FRAME]), MAXIMUM_INT_PITCH_DELAY*sizeof(word16_t)); | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,91 @@ | |||
| /* | |||
| postProcessing.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "preProcessing.h" | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Define filter coefficients */ | |||
| /* Coefficient are given by the filter transfert function : */ | |||
| /* */ | |||
| /* 0.46363718 - 0.92724705z(-1) + 0.46363718z(-2) */ | |||
| /* H(z) = −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− */ | |||
| /* 1 - 1.9059465z(-1) + 0.9114024z(-2) */ | |||
| /* */ | |||
| /* giving: */ | |||
| /* y[i] = B0*x[i] + B1*x[i-1] + B2*x[i-2] */ | |||
| /* + A1*y[i-1] + A2*y[i-2] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| /* coefficients are stored in Q1.13 */ | |||
| #define A1 ((word16_t)(15836)) | |||
| #define A2 ((word16_t)(-7667)) | |||
| #define B0 ((word16_t)(7699)) | |||
| #define B1 ((word16_t)(-15398)) | |||
| #define B2 ((word16_t)(7699)) | |||
| /* Initialization of context values */ | |||
| void initPostProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext) { | |||
| decoderChannelContext->outputY2 = 0; | |||
| decoderChannelContext->outputY1 = 0; | |||
| decoderChannelContext->inputX0 = 0; | |||
| decoderChannelContext->inputX1 = 0; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* postProcessing : high pass filtering and upscaling Spec 4.2.5 */ | |||
| /* Algorithm: */ | |||
| /* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */ | |||
| /* parameters: */ | |||
| /* -(i/o) decoderChannelContext : the channel context data */ | |||
| /* -(i/o) signal : 40 values in Q0, reconstructed speech, output */ | |||
| /* replaces the input in buffer */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void postProcessing(bcg729DecoderChannelContextStruct *decoderChannelContext, word16_t signal[]) { | |||
| int i; | |||
| word16_t inputX2; | |||
| word32_t acc; /* in Q13 */ | |||
| for(i=0; i<L_SUBFRAME; i++) { | |||
| inputX2 = decoderChannelContext->inputX1; | |||
| decoderChannelContext->inputX1 = decoderChannelContext->inputX0; | |||
| decoderChannelContext->inputX0 = signal[i]; | |||
| /* compute with acc and coefficients in Q13 */ | |||
| acc = MULT16_32_Q13(A1, decoderChannelContext->outputY1); /* Y1 in Q14.13 * A1 in Q1.13 -> acc in Q17.13*/ | |||
| acc = MAC16_32_Q13(acc, A2, decoderChannelContext->outputY2); /* Y2 in Q14.13 * A2 in Q0.13 -> Q15.13 + acc in Q17.13 -> acc in Q18.12 */ | |||
| /* 3*(Xi in Q15.0 * Bi in Q0.13)->Q17.13 + acc in Q18.13 -> acc in 19.13(Overflow??) */ | |||
| acc = MAC16_16(acc, decoderChannelContext->inputX0, B0); | |||
| acc = MAC16_16(acc, decoderChannelContext->inputX1, B1); | |||
| acc = SATURATE(MAC16_16(acc, inputX2, B2), MAXINT29); /* saturate the acc to keep in Q15.13 */ | |||
| signal[i] = SATURATE(PSHR(acc,12), MAXINT16); /* acc in Q13 -> *2 and scale back to Q0 */ | |||
| decoderChannelContext->outputY2 = decoderChannelContext->outputY1; | |||
| decoderChannelContext->outputY1 = acc; | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,96 @@ | |||
| /* | |||
| preProcessing.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "preProcessing.h" | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Define filter coefficients */ | |||
| /* Coefficient are given by the filter transfert function : */ | |||
| /* */ | |||
| /* 0.46363718 - 0.92724705z(-1) + 0.46363718z(-2) */ | |||
| /* H(z) = −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− */ | |||
| /* 1 - 1.9059465z(-1) + 0.9114024z(-2) */ | |||
| /* */ | |||
| /* giving: */ | |||
| /* y[i] = B0*x[i] + B1*x[i-1] + B2*x[i-2] */ | |||
| /* + A1*y[i-1] + A2*y[i-2] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| /* coefficients a stored in Q1.12 for A1 (the only one having a float value > 1) and Q0.12 for all the others */ | |||
| #define A1 ((word16_t)(7807)) | |||
| #define A2 ((word16_t)(-3733)) | |||
| #define B0 ((word16_t)(1899)) | |||
| #define B1 ((word16_t)(-3798)) | |||
| #define B2 ((word16_t)(1899)) | |||
| /* Initialization of context values */ | |||
| void initPreProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext) { | |||
| encoderChannelContext->outputY2 = 0; | |||
| encoderChannelContext->outputY1 = 0; | |||
| encoderChannelContext->inputX0 = 0; | |||
| encoderChannelContext->inputX1 = 0; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* preProcessing : 2nd order highpass filter with cut off frequency at 140Hz */ | |||
| /* Algorithm: */ | |||
| /* y[i] = BO*x[i] + B1*x[i-1] + B2*x[i-2] + A1*y[i-1] + A2*y[i-2] */ | |||
| /* parameters : */ | |||
| /* -(i/o) encoderChannelContext : the channel context data */ | |||
| /* -(i) signal : 80 values in Q0 */ | |||
| /* -(o) preProcessedSignal : 80 values in Q0 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void preProcessing(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t signal[], word16_t preProcessedSignal[]) { | |||
| int i; | |||
| word16_t inputX2; | |||
| word32_t acc; /* in Q12 */ | |||
| for(i=0; i<L_FRAME; i++) { | |||
| inputX2 = encoderChannelContext->inputX1; | |||
| encoderChannelContext->inputX1 = encoderChannelContext->inputX0; | |||
| encoderChannelContext->inputX0 = signal[i]; | |||
| /* compute with acc and coefficients in Q12 */ | |||
| acc = MULT16_32_Q12(A1, encoderChannelContext->outputY1); /* Y1 in Q15.12 * A1 in Q1.12 -> acc in Q17.12*/ | |||
| acc = MAC16_32_Q12(acc, A2, encoderChannelContext->outputY2); /* Y2 in Q15.12 * A2 in Q0.12 -> Q15.12 + acc in Q17.12 -> acc in Q18.12 */ | |||
| /* 3*(Xi in Q15.0 * Bi in Q0.12)->Q17.12 + acc in Q18.12 -> acc in 19.12 */ | |||
| acc = MAC16_16(acc, encoderChannelContext->inputX0, B0); | |||
| acc = MAC16_16(acc, encoderChannelContext->inputX1, B1); | |||
| acc = MAC16_16(acc, inputX2, B2); | |||
| /* acc in Q19.12 : We must check it won't overflow | |||
| - the Q15.12 of Y | |||
| - the Q15.0 extracted from it by shifting 12 right | |||
| -> saturate to 28 bits -> acc in Q15.12 */ | |||
| acc = SATURATE(acc, MAXINT28); | |||
| preProcessedSignal[i] = PSHR(acc,12); /* extract integer value of the Q15.12 representation */ | |||
| encoderChannelContext->outputY2 = encoderChannelContext->outputY1; | |||
| encoderChannelContext->outputY1 = acc; | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,96 @@ | |||
| /* | |||
| qLSP2LP.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "basicOperationsMacros.h" | |||
| /* local function */ | |||
| void computePolynomialCoefficients(word16_t qLSP[], word32_t f[]); | |||
| /*****************************************************************************/ | |||
| /* qLSP2LP : convert qLSP into LP parameters according to spec. 3.2.6 */ | |||
| /* parameters: */ | |||
| /* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */ | |||
| /* -(o) LP : 10 LP coefficients in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void qLSP2LP(word16_t qLSP[], word16_t LP[]) | |||
| { | |||
| int i; | |||
| word32_t f1[6], f2[6]; /* define two buffer to store the polynomials coefficients (size is 6 for 5 coefficient because fx[0] is used during computation as a buffer) */ | |||
| /* pointers to access directly the elements 1 of f1 and f2 */ | |||
| word32_t *fp1=&(f1[1]); | |||
| word32_t *fp2=&(f2[1]); | |||
| computePolynomialCoefficients(qLSP, f1); | |||
| computePolynomialCoefficients(&(qLSP[1]), f2); | |||
| /* convert f coefficient in f' coefficient f'1[i] = f1[i]+f[i-1] and f'2[i] = f2[i] - f2[i-1] */ | |||
| for (i=5; i>0; i--) { | |||
| f1[i] = ADD32(f1[i], f1[i-1]); /* f1 is still in Q24 */ | |||
| f2[i] = SUB32(f2[i], f2[i-1]); /* f1 is still in Q24 */ | |||
| } | |||
| /* compute the LP coefficients */ | |||
| /* fx[0] is not needed anymore, acces the f1 and f2 buffers via the fp1 and fp2 pointers */ | |||
| for (i=0; i<5; i++) { | |||
| /* i in [0,5[ : LP[i] = (f1[i] + f2[i])/2 */ | |||
| LP[i] = PSHR(ADD32(fp1[i], fp2[i]),13); /* f1 and f2 in Q24, LP in Q12 */ | |||
| /* i in [5,9[ : LP[i] = (f1[9-i] - f2[9-i])/2 */ | |||
| LP[9-i] = PSHR(SUB32(fp1[i], fp2[i]),13); /* f1 and f2 in Q24, LP in Q12 */ | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* computePolynomialCoefficients : according to spec. 3.2.6 */ | |||
| /* parameters: */ | |||
| /* -(i) qLSP : 10 LSP to be converted in Q0.15 range [-1, +1[ */ | |||
| /* -(o) f : 6 values in Q24 : polynomial coefficients on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computePolynomialCoefficients(word16_t qLSP[], word32_t f[]) | |||
| { | |||
| int i,j; | |||
| /* init values */ | |||
| /* f[-1] which is not available is to be egal at 0, it is directly removed in the following when used as a factor */ | |||
| f[0] = 16777216; /* 1 in Q24, f[0] is used only for the other coefficient computation */ | |||
| /* correspont to i=1 in the algorithm description in spec. 3.2.6 */ | |||
| f[1] = MULT16_16(qLSP[0], -1024); /* f[1] = -2*qLSP[0], with qLSP in Q0.15 * -2*2^9(-1024) -> f[1] in Q1.24 */ | |||
| /* so we start with i=2 */ | |||
| /* Note : index of qLSP are -1 respect of what is in the spec because qLSP array is indexed from 0-9 and not 1-10 */ | |||
| for (i=2; i<6; i++) { | |||
| /* spec: f[i] = 2(f[i-2] - qLSP[2i-1]*f[i-1]) */ | |||
| f[i] = SHL(SUB32(f[i-2], MULT16_32_P15(qLSP[2*i-2], f[i-1])),1); /* with qLSP in Q0.15 and f in Q24 */ | |||
| for (j=i-1; j>1; j--) { /* case of j=1 is just doing f[1] -= 2*qLSP[2i-1], done after the loop in order to avoid reference to f[-1] */ | |||
| /* spec: f[j] = f[j] -2*qLSP[2i-i]*f[j-1] + f[j-2] (all right terms refer to the value at the previous iteration on i indexed loop) */ | |||
| f[j] = ADD32(f[j], SUB32(f[j-2], MULT16_32_P14(qLSP[2*i-2], f[j-1]))); /* qLPS in Q0.15 and f in Q24, using MULT16_32_P14 instead of P15 does the *2 on qLSP. Result in Q24 */ | |||
| } | |||
| /* f[1] -= 2*qLSP[2i-1] */ | |||
| f[1] = SUB32(f[1], SHL(qLSP[2*i-2],10)); /* qLSP in Q0.15, must be shift by 9 to get in Q24 and one more to be *2 */ | |||
| } | |||
| return; | |||
| } | |||
| @ -0,0 +1,327 @@ | |||
| /* | |||
| utils.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include "typedef.h" | |||
| #include "basicOperationsMacros.h" | |||
| #include "codecParameters.h" | |||
| #include "g729FixedPointMath.h" | |||
| #include "codebooks.h" | |||
| /*****************************************************************************/ | |||
| /* insertionSort : sort an array in growing order using insertion algorithm */ | |||
| /* parameters : */ | |||
| /* -(i/o) x: the array to be sorted */ | |||
| /* -(i) length: the array length */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void insertionSort(word16_t x[], int length) | |||
| { | |||
| int i, j; | |||
| word16_t currentValue; | |||
| for (i=1; i<length; i++) { | |||
| currentValue = x[i]; | |||
| j = i-1; | |||
| while ((j>=0) && (x[j]>currentValue)) { | |||
| x[j+1] = x[j]; | |||
| j--; | |||
| } | |||
| x[j+1] = currentValue; | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* computeParity : compute parity for pitch delay adaptative codebook index */ | |||
| /* XOR of the 6 MSB (pitchDelay on 8 bits) */ | |||
| /* parameters : */ | |||
| /* -(i) adaptativeCodebookIndex: the pitch delay on 8 bits */ | |||
| /* return value : */ | |||
| /* the parity bit */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| uint16_t computeParity(uint16_t adaptativeCodebookIndex) | |||
| { | |||
| int i; | |||
| uint16_t parity = 1; | |||
| adaptativeCodebookIndex = SHR(adaptativeCodebookIndex,2); /* ignore the two LSB */ | |||
| for (i=0; i<6; i++) { | |||
| parity ^= adaptativeCodebookIndex&(uint16_t)1; /* XOR with the LSB */ | |||
| adaptativeCodebookIndex = SHR(adaptativeCodebookIndex,1); | |||
| } | |||
| return parity; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* rearrangeCoefficients: rearrange coefficients according to spec 3.2.4 */ | |||
| /* Have a minimum distance of J beetwen two consecutive coefficients */ | |||
| /* parameters: */ | |||
| /* -(i/o) qLSP: 10 ordered coefficients in Q13 replaced by new values */ | |||
| /* if needed */ | |||
| /* -(i) J: minimum distance between coefficients in Q0.13 (10 or 5) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void rearrangeCoefficients(word16_t qLSP[], word16_t J) | |||
| { /* qLSP in Q2.13 and J in Q0.13(fitting on 4 bits: possible values 10 and 5) */ | |||
| int i=1; | |||
| word16_t delta; /* in Q0.13 */ | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| delta = (ADD16(SUB16(qLSP[i-1],qLSP[i]),J))/2; /* delta = (l[i-1] - l[i] +J)/2 */ | |||
| if (delta > 0) { | |||
| qLSP[i-1] = SUB16(qLSP[i-1], delta); /* qLSP still in Q2.13 */ | |||
| qLSP[i] = ADD16(qLSP[i], delta); | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* synthesisFilter : compute 1/[A(z)] using the following algorithm */ | |||
| /* filteredSignal[n] = inputSignal[n] */ | |||
| /* - Sum(i=1..10)filterCoefficients[i]*filteredSignal[n-i] */ | |||
| /* for n in [0, L_SUBFRAME[ */ | |||
| /* parameters: */ | |||
| /* -(i) inputSignal: 40 values in Q0 */ | |||
| /* -(i) filterCoefficients: 10 coefficients in Q12 */ | |||
| /* -(i/o) filteredSignal: 50 values in Q0 accessed in ranges [-10,-1] */ | |||
| /* as input and [0, 39] as output. */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void synthesisFilter(word16_t inputSignal[], word16_t filterCoefficients[], word16_t filteredSignal[]) | |||
| { | |||
| int i; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| word32_t acc = SHL(inputSignal[i],12); /* acc get the first term of the sum, in Q12 (inputSignal is in Q0)*/ | |||
| int j; | |||
| for (j=0; j<NB_LSP_COEFF; j++) { | |||
| acc = MSU16_16(acc, filterCoefficients[j], filteredSignal[i-j-1]); /* filterCoefficients in Q12 and signal in Q0 -> acc in Q12 */ | |||
| } | |||
| filteredSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift right acc to get it back in Q0 and check overflow on 16 bits */ | |||
| } | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* correlateVectors : compute the correlations between two vectors of */ | |||
| /* L_SUBFRAME length: c[i] = Sum(x[j]*y[j-i]) j in [i, L_SUBFRAME[ */ | |||
| /* parameters: */ | |||
| /* -(i) x : L_SUBFRAME length input vector on 16 bits */ | |||
| /* -(i) y : L_SUBFRAME length input vector on 16 bits */ | |||
| /* -(o) c : L_SUBFRAME length output vector on 32 bits */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void correlateVectors (word16_t x[], word16_t y[], word32_t c[]) | |||
| { | |||
| int i,j; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| c[i] = 0; | |||
| for (j=i; j<L_SUBFRAME; j++) { | |||
| c[i] = MAC16_16(c[i], x[j], y[j-i]); | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| /*** gain related functions ***/ | |||
| /*****************************************************************************/ | |||
| /* MACodeGainPrediction : spec 3.9.1 */ | |||
| /* parameters: */ | |||
| /* -(i) previousGainPredictionError: qU(m) in eq69 4 values in Q10 */ | |||
| /* -(i) fixedCodebookVector: the current subframe fixed codebook vector */ | |||
| /* 40 values in Q1.13 */ | |||
| /* return value : */ | |||
| /* - predicted Fixed Codebook gain on 32 bits in Q16 range [3, 1830] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *fixedCodebookVector) | |||
| { | |||
| /***** algorithm described in spec 3.9.1 *****/ | |||
| /*** first compute eq66: E = 10log10((Sum0-39(fixedCodebookVector^2))/40) ***/ | |||
| /*** directly used in eq71 in E| - E = 30 - 10log10((Sum0-39(fixedCodebookVector^2))/40) */ | |||
| /* = 30 - 10log10((Sum*2^26)/(40*2^26)) */ | |||
| /* = 30 + 10log10(40*2^26) - (10/log2(10))*log2(Sum*2^26) [The Sum is computed in Q26] */ | |||
| /* = 30 + 94.2884 - 3.0103*log2(Sum*2^26) */ | |||
| /* = 124.2884 - 3.0103*log2(Sum*2^26) = E| - E as used in eq71 */ | |||
| /* compute the sum of squares of fixedCodebookVector in Q26 */ | |||
| int i; | |||
| word32_t fixedCodebookVectorSquaresSum = 0; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fixedCodebookVector[i] != 0) { /* as most of the codebook vector is egal to 0, it worth checking it to avoid useless multiplications */ | |||
| /* fixedCodebookVector in Q1.13 and final sum in range [4, 8.48] (4 values filled with abs values: 1,1,1.8 and 1.8 in the vector give max value of sum) */ | |||
| /* fixedCodebookVectorSquaresSum is then in Q4.26 */ | |||
| fixedCodebookVectorSquaresSum = MAC16_16(fixedCodebookVectorSquaresSum, fixedCodebookVector[i], fixedCodebookVector[i]); | |||
| } | |||
| } | |||
| /* compute E| - E as in eq71, result in Q16 */ | |||
| /* acc = 124.2884 - 3.0103*log2(Sum) */ | |||
| /* acc = 8145364[32 bits Q16] - 24660[16 bits Q2.13]*log2(Sum)[32 bits Q16] */ | |||
| word32_t acc = MAC16_32_Q13(8145364, -24660, g729Log2_Q0Q16(fixedCodebookVectorSquaresSum)); /* acc in Q16 */ | |||
| /* accumulate the MA prediction described in eq69 to the previous Sum, result will be in E~(m) + E| -E as used in eq71 */ | |||
| /* acc in Q16->Q24, previousGainPredictionError in Q10 and MAPredictionCoefficients in Q0.14*/ | |||
| acc = SHL(acc,8); /* acc in Q24 to match the fixed point of next accumulations */ | |||
| for (i=0; i<4; i++) { | |||
| acc = MAC16_16(acc, previousGainPredictionError[i], MAPredictionCoefficients[i]); | |||
| } | |||
| /* acc range [10, 65] -> Q6.24 */ | |||
| /* compute eq71, we already have the exposant in acc so */ | |||
| /* g'c = 10^(acc/20) */ | |||
| /* = 2^((acc*ln(10))/(20*ln(2))) */ | |||
| /* = 2^(0,1661*acc) */ | |||
| acc = SHR(acc,2); /* Q24->Q22 */ | |||
| acc = MULT16_32_Q15(5442, acc); /* 5442 is 0.1661 in Q15 -> acc now in Q4.22 range [1.6, 10.8] */ | |||
| acc = PSHR(acc,11); /* get acc in Q4.11 */ | |||
| return g729Exp2_Q11Q16((word16_t)acc); /* acc fits on 16 bits, cast it to word16_t to send it to the exp2 function, output in Q16*/ | |||
| } | |||
| /*****************************************************************************/ | |||
| /* computeGainPredictionError : apply eq72 to compute current fixed Codebook */ | |||
| /* gain prediction error and store the result in the adhoc array */ | |||
| /* parameters : */ | |||
| /* -(i) fixedCodebookGainCorrectionFactor: gamma in eq72 in Q3.12 */ | |||
| /* -(i/o) previousGainPredictionError: array to be updated in Q10 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void computeGainPredictionError(word16_t fixedCodebookGainCorrectionFactor, word16_t *previousGainPredictionError) | |||
| { | |||
| /* need to compute eq72: 20log10(fixedCodebookGainCorrectionFactor) */ | |||
| /* = (20/log2(10))*log2(fixedCodebookGainCorrectionFactor) */ | |||
| /* = 6.0206*log2(fixedCodebookGainCorrectionFactor) */ | |||
| /* log2 input in Q0, output in Q16,fixedCodebookGainCorrectionFactor being in Q12, we shall substract 12 in Q16(786432) to the result of log2 function -> final result in Q2.16 */ | |||
| word32_t currentGainPredictionError = SUB32(g729Log2_Q0Q16(fixedCodebookGainCorrectionFactor), 786432); | |||
| currentGainPredictionError = PSHR(MULT16_32_Q12(24660, currentGainPredictionError),6); /* 24660 = 6.0206 in Q3.12 -> mult result in Q16, precise shift right to get it in Q4.10 */ | |||
| /* shift the array and insert the current Prediction Error */ | |||
| previousGainPredictionError[3] = previousGainPredictionError[2]; | |||
| previousGainPredictionError[2] = previousGainPredictionError[1]; | |||
| previousGainPredictionError[1] = previousGainPredictionError[0]; | |||
| previousGainPredictionError[0] = (word16_t)currentGainPredictionError; | |||
| } | |||
| /*** bitStream to parameters Array conversions functions ***/ | |||
| /* Note: these functions are in utils.c because used by test source code too */ | |||
| /*****************************************************************************/ | |||
| /* parametersArray2BitStream : convert array of parameters to bitStream */ | |||
| /* according to spec 4 - Table 8 and following mapping of values */ | |||
| /* 0 -> L0 (1 bit) */ | |||
| /* 1 -> L1 (7 bits) */ | |||
| /* 2 -> L2 (5 bits) */ | |||
| /* 3 -> L3 (5 bits) */ | |||
| /* 4 -> P1 (8 bit) */ | |||
| /* 5 -> P0 (1 bits) */ | |||
| /* 6 -> C1 (13 bits) */ | |||
| /* 7 -> S1 (4 bits) */ | |||
| /* 8 -> GA1(3 bits) */ | |||
| /* 9 -> GB1(4 bits) */ | |||
| /* 10 -> P2 (5 bits) */ | |||
| /* 11 -> C2 (13 bits) */ | |||
| /* 12 -> S2 (4 bits) */ | |||
| /* 13 -> GA2(3 bits) */ | |||
| /* 14 -> GB2(4 bits) */ | |||
| /* parameters: */ | |||
| /* -(i) parameters : 16 values parameters array */ | |||
| /* -(o) bitStream : the 16 values streamed on 80 bits in a */ | |||
| /* 10*8bits values array */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void parametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]) | |||
| { | |||
| bitStream[0] = ((parameters[0]&((uint16_t) 0x1))<<7) | | |||
| (parameters[1]&((uint16_t) 0x7f)); | |||
| bitStream[1] = ((parameters[2]&((uint16_t) 0x1f))<<3) | | |||
| ((parameters[3]>>2)&((uint16_t) 0x7)); | |||
| bitStream[2] = ((parameters[3]&((uint16_t) 0x3))<<6) | | |||
| ((parameters[4]>>2)&((uint16_t) 0x3f)); | |||
| bitStream[3] = ((parameters[4]&((uint16_t) 0x3))<<6) | | |||
| ((parameters[5]&((uint16_t) 0x1))<<5) | | |||
| ((parameters[6]>>8)&((uint16_t) 0x1f)); | |||
| bitStream[4] = ((parameters[6])&((uint16_t) 0xff)); | |||
| bitStream[5] = ((parameters[7]&((uint16_t) 0xf))<<4) | | |||
| ((parameters[8]&((uint16_t) 0x7))<<1) | | |||
| ((parameters[9]>>3)&((uint16_t) 0x1)); | |||
| bitStream[6] = ((parameters[9]&((uint16_t) 0x7))<<5) | | |||
| (parameters[10]&((uint16_t) 0x1f)); | |||
| bitStream[7] = ((parameters[11]>>5)&((uint16_t) 0xff)); | |||
| bitStream[8] = ((parameters[11]&((uint16_t) 0x1f))<<3) | | |||
| ((parameters[12]>>1)&((uint16_t) 0x7)); | |||
| bitStream[9] = ((parameters[12]&((uint16_t) 0x1))<<7) | | |||
| ((parameters[13]&((uint16_t) 0x7))<<4) | | |||
| (parameters[14]&((uint16_t) 0xf)); | |||
| return; | |||
| } | |||
| /*****************************************************************************/ | |||
| /* parametersArray2BitStream : convert bitStream to an array of parameters */ | |||
| /* reverse operation of previous funtion */ | |||
| /* parameters: */ | |||
| /* -(i) bitStream : the 16 values streamed on 80 bits in a */ | |||
| /* 10*8bits values array */ | |||
| /* -(o) parameters : 16 values parameters array */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| void parametersBitStream2Array(uint8_t bitStream[], uint16_t parameters[]) | |||
| { | |||
| parameters[0] = (bitStream[0]>>7)&(uint16_t)0x1; | |||
| parameters[1] = bitStream[0]&(uint16_t)0x7f; | |||
| parameters[2] = (bitStream[1]>>3)&(uint16_t)0x1f; | |||
| parameters[3] = (((uint16_t)bitStream[1]&(uint16_t)0x7)<<2) | ((bitStream[2]>>6)&(uint16_t)0x3); | |||
| parameters[4] = (((uint16_t)bitStream[2])&(uint16_t)0x3f)<<2 | ((bitStream[3]>>6)&(uint16_t)0x3);; | |||
| parameters[5] = (bitStream[3]>>5)&(uint16_t)0x1; | |||
| parameters[6] = (((uint16_t)(bitStream[3]&(uint16_t)0x1f))<<8)| bitStream[4]; | |||
| parameters[7] = (bitStream[5]>>4)&(uint16_t)0xf; | |||
| parameters[8] = (bitStream[5]>>1)&(uint16_t)0x7; | |||
| parameters[9] = (((uint16_t)bitStream[5]&(uint16_t)0x1)<<3)|((bitStream[6]>>5)&(uint16_t)0x7); | |||
| parameters[10]= (uint16_t)bitStream[6]&(uint16_t)0x1f; | |||
| parameters[11]= (((uint16_t)bitStream[7])<<5)|((bitStream[8]>>3)&(uint16_t)0x1f); | |||
| parameters[12]= ((bitStream[8]&(uint16_t)0x7)<<1) | ((bitStream[9]>>7)&(uint16_t)0x1); | |||
| parameters[13]= (bitStream[9]>>4)&(uint16_t)0x7; | |||
| parameters[14]= bitStream[9]&(uint16_t)0xf; | |||
| return; | |||
| } | |||
| @ -0,0 +1,4 @@ | |||
| SUBDIRS = bin | |||
| TESTS_ENVIRONMENT = $(SHELL) | |||
| TESTS=testCampaignAll | |||
| @ -0,0 +1,2 @@ | |||
| #ignore all test bins | |||
| *Test | |||
| @ -0,0 +1,34 @@ | |||
| check_PROGRAMS=adaptativeCodebookSearchTest computeAdaptativeCodebookGainTest computeLPTest computeWeightedSpeechTest decodeAdaptativeCodeVectorTest decodeFixedCodeVectorTest decodeGainsTest decodeLSPTest \ | |||
| decoderTest encoderTest decoderMultiChannelTest encoderMultiChannelTest findOpenLoopPitchDelayTest fixedCodebookSearchTest g729FixedPointMathTest gainQuantizationTest interpolateqLSPAndConvert2LPTest \ | |||
| LP2LSPConversionTest LPSynthesisFilterTest LSPQuantizationTest postFilterTest postProcessingTest preProcessingTest | |||
| util_src=$(top_srcdir)/test/src/testUtils.c | |||
| adaptativeCodebookSearchTest_SOURCES=$(top_srcdir)/test/src/adaptativeCodebookSearchTest.c $(util_src) | |||
| computeAdaptativeCodebookGainTest_SOURCES=$(top_srcdir)/test/src/computeAdaptativeCodebookGainTest.c $(util_src) | |||
| computeLPTest_SOURCES=$(top_srcdir)/test/src/computeLPTest.c $(util_src) | |||
| computeWeightedSpeechTest_SOURCES=$(top_srcdir)/test/src/computeWeightedSpeechTest.c $(util_src) | |||
| decodeAdaptativeCodeVectorTest_SOURCES=$(top_srcdir)/test/src/decodeAdaptativeCodeVectorTest.c $(util_src) | |||
| decodeFixedCodeVectorTest_SOURCES=$(top_srcdir)/test/src/decodeFixedCodeVectorTest.c $(util_src) | |||
| decodeGainsTest_SOURCES=$(top_srcdir)/test/src/decodeGainsTest.c $(util_src) | |||
| decodeLSPTest_SOURCES=$(top_srcdir)/test/src/decodeLSPTest.c $(util_src) | |||
| decoderTest_SOURCES=$(top_srcdir)/test/src/decoderTest.c $(util_src) | |||
| decoderMultiChannelTest_SOURCES=$(top_srcdir)/test/src/decoderMultiChannelTest.c $(util_src) | |||
| encoderTest_SOURCES=$(top_srcdir)/test/src/encoderTest.c $(util_src) | |||
| encoderMultiChannelTest_SOURCES=$(top_srcdir)/test/src/encoderMultiChannelTest.c $(util_src) | |||
| findOpenLoopPitchDelayTest_SOURCES=$(top_srcdir)/test/src/findOpenLoopPitchDelayTest.c $(util_src) | |||
| fixedCodebookSearchTest_SOURCES=$(top_srcdir)/test/src/fixedCodebookSearchTest.c $(util_src) | |||
| g729FixedPointMathTest_SOURCES=$(top_srcdir)/test/src/g729FixedPointMathTest.c $(util_src) | |||
| g729FixedPointMathTest_LDADD=-lm | |||
| gainQuantizationTest_SOURCES=$(top_srcdir)/test/src/gainQuantizationTest.c $(util_src) | |||
| interpolateqLSPAndConvert2LPTest_SOURCES=$(top_srcdir)/test/src/interpolateqLSPAndConvert2LPTest.c $(util_src) | |||
| LP2LSPConversionTest_SOURCES=$(top_srcdir)/test/src/LP2LSPConversionTest.c $(util_src) | |||
| LPSynthesisFilterTest_SOURCES=$(top_srcdir)/test/src/LPSynthesisFilterTest.c $(util_src) | |||
| LSPQuantizationTest_SOURCES=$(top_srcdir)/test/src/LSPQuantizationTest.c $(util_src) | |||
| postFilterTest_SOURCES=$(top_srcdir)/test/src/postFilterTest.c $(util_src) | |||
| postProcessingTest_SOURCES=$(top_srcdir)/test/src/postProcessingTest.c $(util_src) | |||
| preProcessingTest_SOURCES=$(top_srcdir)/test/src/preProcessingTest.c $(util_src) | |||
| LDADD= $(top_builddir)/src/libbcg729.la | |||
| INCLUDES=-I$(top_srcdir)/include/ | |||
| @ -0,0 +1,108 @@ | |||
| /* | |||
| LP2LSPConversionTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for LP2LSPConversion bloc */ | |||
| /* Input: - 10 LP in Q12 */ | |||
| /* */ | |||
| /* Ouput: - 10 LSP in Q15 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "LP2LSPConversion.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: 10 LP Coefficients(Q12) */ | |||
| word16_t LP[NB_LSP_COEFF]; | |||
| /* output file: 10 LSP Coefficients(Q15) */ | |||
| word16_t LSP[NB_LSP_COEFF]; | |||
| word16_t previousLSP[NB_LSP_COEFF] = /* store previously computed LSP to be reused if we can't find 10 LSP from current LP */ | |||
| {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LP[0],&LP[1],&LP[2],&LP[3],&LP[4],&LP[5],&LP[6],&LP[7],&LP[8],&LP[9]) == 10) | |||
| { | |||
| int i; | |||
| /* call the tested funtion */ | |||
| if (LP2LSPConversion(LP, LSP)) { | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| previousLSP[i]=LSP[i]; | |||
| } | |||
| } else { /* unable to find the 10 roots repeat previous LSP */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| LSP[i]=previousLSP[i]; | |||
| } | |||
| } | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", LSP[0]); | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| fprintf(fpOutput,",%d", LSP[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,105 @@ | |||
| /* | |||
| LPSynthesisFilterTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for LPSynthesisFilter bloc */ | |||
| /* Input: - */ | |||
| /* */ | |||
| /* Ouput: - */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "LPSynthesisFilter.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: 10 LP Coefficients(Q12), 40 ExcitationVector(Q0), 10 past reconstructed speech(Q0) */ | |||
| word16_t LP[NB_LSP_COEFF]; | |||
| word16_t excitationVector[L_SUBFRAME]; /* this vector contains the subframe excitation vector in Q0 */ | |||
| /* output is in the reconstruted speech: for the test purpose it's long just memory+subframe */ | |||
| word16_t reconstructedSpeech[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, output of the LP synthesis filter, the first 10 words store the previous frame output */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LP[0],&LP[1],&LP[2],&LP[3],&LP[4],&LP[5],&LP[6],&LP[7],&LP[8],&LP[9]) != 10) break; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(excitationVector[i])) != 1) break; | |||
| } | |||
| if (fscanf(fpInput,",%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&reconstructedSpeech[0],&reconstructedSpeech[1],&reconstructedSpeech[2],&reconstructedSpeech[3],&reconstructedSpeech[4],&reconstructedSpeech[5],&reconstructedSpeech[6],&reconstructedSpeech[7],&reconstructedSpeech[8],&reconstructedSpeech[9]) != 10) break; | |||
| /* call the tested funtion */ | |||
| LPSynthesisFilter(excitationVector, LP, &(reconstructedSpeech[NB_LSP_COEFF])); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",reconstructedSpeech[NB_LSP_COEFF]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", reconstructedSpeech[NB_LSP_COEFF+i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| /* | |||
| LSPQuantizationTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for LSPQuantization bloc */ | |||
| /* Input: - 10 LSP in Q15 */ | |||
| /* */ | |||
| /* Ouput: - 10 qLSP in Q15 */ | |||
| /* - 4 parameters L0, L1, L2, L3 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "LSPQuantization.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: 10 LSP Coefficients(Q15) */ | |||
| word16_t LSP[NB_LSP_COEFF]; | |||
| /* output file: 10 qLSP Coefficients(Q15) */ | |||
| word16_t qLSP[NB_LSP_COEFF]; | |||
| uint16_t parametersL[4]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct)); | |||
| initLSPQuantization(encoderChannelContext); | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| // LSPQuantization(LSP, qLSP, parametersL); | |||
| //exit (0); | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LSP[0],&LSP[1],&LSP[2],&LSP[3],&LSP[4],&LSP[5],&LSP[6],&LSP[7],&LSP[8],&LSP[9]) == 10) | |||
| { | |||
| int i; | |||
| /* call the tested funtion */ | |||
| LSPQuantization(encoderChannelContext, LSP, qLSP, parametersL); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", qLSP[0]); | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| fprintf(fpOutput,",%d", qLSP[i]); | |||
| } | |||
| fprintf(fpOutput,",%d,%d,%d,%d\n",parametersL[0],parametersL[1],parametersL[2],parametersL[3]); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,133 @@ | |||
| /* | |||
| adaptativeCodebookSearchTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for adaptativeCodebookSearchTest bloc */ | |||
| /* Input: - the past excitation (excitationVector) : 234 values */ | |||
| /* - targetSignal : 40 values */ | |||
| /* - impulseResponse : 40 values */ | |||
| /* - intPitchDelayMin */ | |||
| /* - intPitchDelayMax */ | |||
| /* - subframeIndex (0 or 40) */ | |||
| /* */ | |||
| /* Ouput: - int Pitch Delay */ | |||
| /* - frac Pitch Delay */ | |||
| /* - intPitchDelayMin */ | |||
| /* - intPitchDelayMax */ | |||
| /* - adaptativeCodebookIndex */ | |||
| /* - adaptative codebook vector : 40 values */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "adaptativeCodebookSearch.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: pastExcitationVector: 234 values, targetSignal: 40 values, impulseReponse: 40 values, intPitchDelayMin, intPitchDelayMax, subframeIndex */ | |||
| word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* this vector contains: note on second subframe we have 40 useless values of past excitation | |||
| 0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10) | |||
| 154-> 154+L_SUBFRAME-1 : the current LPResidualSignal in input | |||
| 154-> 154+L_SUBFRAME-1 : the adaptative codebook vector in Q0 as output */ | |||
| word16_t targetSignal[L_SUBFRAME]; | |||
| word16_t impulseResponse[L_SUBFRAME]; | |||
| int16_t intPitchDelayMin, intPitchDelayMax; | |||
| int subFrameIndex; | |||
| /* outputs : */ | |||
| int16_t intPitchDelay; | |||
| int16_t fracPitchDelay; | |||
| uint16_t adaptativeCodebookIndex; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /* actually useless init, because the complete excitation buffer is reload at each subframe from input file, but shall be done in real decoder */ | |||
| memset(excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| for (i=0; i<234; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(excitationVector[i])) != 1) break; | |||
| } | |||
| for (i=0; i<40; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(targetSignal[i])) != 1) break; | |||
| } | |||
| for (i=0; i<40; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(impulseResponse[i])) != 1) break; | |||
| } | |||
| if (fscanf(fpInput,"%hd,",&intPitchDelayMin) != 1) break; | |||
| if (fscanf(fpInput,"%hd,",&intPitchDelayMax) != 1) break; | |||
| if (fscanf(fpInput,"%d",&subFrameIndex) != 1) break; | |||
| /* call the tested funtion */ | |||
| adaptativeCodebookSearch(&(excitationVector[L_PAST_EXCITATION + subFrameIndex]), &intPitchDelayMin, &intPitchDelayMax, impulseResponse, targetSignal, | |||
| &intPitchDelay, &fracPitchDelay, &adaptativeCodebookIndex, subFrameIndex); | |||
| /* write the output to the output file : intPitchDelay, fracPitchDelay, intPitchDelayMin, intPitchDelayMax, adaptativeCodebookIndex, adaptative codebook vector */ | |||
| fprintf(fpOutput, "%d,%d,%d,%d,%d,%d", intPitchDelay, fracPitchDelay, intPitchDelayMin, intPitchDelayMax, adaptativeCodebookIndex, excitationVector[L_PAST_EXCITATION+subFrameIndex]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", excitationVector[L_PAST_EXCITATION+subFrameIndex+i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,105 @@ | |||
| /* | |||
| computeAdaptativeCodebookGainTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for computeAdaptativeCodebookGainTest bloc */ | |||
| /* Input: - targetSignal : 40 values */ | |||
| /* - filtered adaptative codebook vector : 40 values */ | |||
| /* */ | |||
| /* Ouput: - adaptative codebook gain in Q14 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "computeAdaptativeCodebookGain.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t targetSignal[L_SUBFRAME]; | |||
| word16_t filteredAdaptativeCodebookVector[L_SUBFRAME]; | |||
| /* outputs : */ | |||
| word16_t adaptativeCodebookGain; | |||
| /* these buffers are part of the output but not of the pattern as they aren't scaled the same way the ITU code does. */ | |||
| word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&(filteredAdaptativeCodebookVector[0])) != 1) break; | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(filteredAdaptativeCodebookVector[i])) != 1) break; | |||
| } | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(targetSignal[i])) != 1) break; | |||
| } | |||
| /* call the tested funtion */ | |||
| adaptativeCodebookGain = computeAdaptativeCodebookGain(targetSignal, filteredAdaptativeCodebookVector, &gainQuantizationXy, &gainQuantizationYy); | |||
| /* write the output to the output file : adaptativeCodebookGain */ | |||
| fprintf(fpOutput,"%d\n", adaptativeCodebookGain); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,98 @@ | |||
| /* | |||
| computeLPTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for computeLP Bloc */ | |||
| /* Input: a CSV text with 240 values of 16 bits PCM on each row */ | |||
| /* Ouput: 10 LP values in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "computeLP.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t inputBuffer[L_LP_ANALYSIS_WINDOW]; | |||
| word16_t LPCoefficients[NB_LSP_COEFF]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_LP_ANALYSIS_WINDOW; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| /* call the preProcessing function: output will replace the input in the buffer */ | |||
| computeLP(inputBuffer, LPCoefficients); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", LPCoefficients[0]); | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| fprintf(fpOutput,",%d", LPCoefficients[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,117 @@ | |||
| /* | |||
| computeWeightedSpeechTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for computeWeightedSpeech bloc */ | |||
| /* Input: 90 values input signal, 10 values of previous weighted signal */ | |||
| /* 20 values of qLPCoefficients, 20 values of weightedqLPCoeffs */ | |||
| /* Ouput: 80 values of weightedSignal */ | |||
| /* 80 values of LP Residual Signal */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "computeWeightedSpeech.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t inputBuffer[NB_LSP_COEFF+L_FRAME]; /* buffer containing the input signal including 10 values from last frame in range [-10, 0[ */ | |||
| word16_t outputBuffer[NB_LSP_COEFF+L_FRAME]; /* same as input buffer, the values in range [-10,0[ are input */ | |||
| word16_t qLPCoefficients[2*NB_LSP_COEFF]; /* qLP coefficients in Q12: input */ | |||
| word16_t weightedqLPCoefficients[2*NB_LSP_COEFF]; /* weightedqLP coefficients in Q12: input */ | |||
| word16_t LPResidualSignal[L_FRAME]; /* LP Residual signal in Q0: ouput*/ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /*** read the input data until we have some ***/ | |||
| /* read the input signal */ | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_FRAME+NB_LSP_COEFF; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| /* read 10 values of weighted signal from previous frame */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| if (fscanf(fpInput,",%hd",&(outputBuffer[i])) != 1) break; /* the first 10 values of output buffer are input: weighted signal from previous frame */ | |||
| } | |||
| /* read qLPCoefficients */ | |||
| for (i=0; i<2*NB_LSP_COEFF; i++) { | |||
| if (fscanf(fpInput,",%hd",&(qLPCoefficients[i])) != 1) break; | |||
| } | |||
| /* read weightedqLPCoefficients */ | |||
| for (i=0; i<2*NB_LSP_COEFF; i++) { | |||
| if (fscanf(fpInput,",%hd",&(weightedqLPCoefficients[i])) != 1) break; | |||
| } | |||
| /* call the computeWeightedSignal function */ | |||
| computeWeightedSpeech(&(inputBuffer[NB_LSP_COEFF]), qLPCoefficients, weightedqLPCoefficients, &(outputBuffer[NB_LSP_COEFF]), LPResidualSignal); /* input and output buffer shall be accessed by the tested function in range [-NB_LSP_COEFF, LFRAME[ */ | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", outputBuffer[NB_LSP_COEFF]); | |||
| for (i=1; i<L_FRAME; i++) { | |||
| fprintf(fpOutput,",%d", outputBuffer[NB_LSP_COEFF+i]); | |||
| } | |||
| for (i=0; i<L_FRAME; i++) { | |||
| fprintf(fpOutput,",%d", LPResidualSignal[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,125 @@ | |||
| /* | |||
| decodeAdaptativeCodeVectorTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decodeAdaptativeCodeVectorTest bloc */ | |||
| /* Input: - the past excitation (excitationVector) */ | |||
| /* - subframeIndex */ | |||
| /* - frameErasureFlag */ | |||
| /* - parityFlag */ | |||
| /* - adaptative Codebook Index (P1 or P2) */ | |||
| /* */ | |||
| /* Ouput: - adaptative Codebook Vector for the current subframe */ | |||
| /* - int Pitch Delay (T) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "decodeAdaptativeCodeVector.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: frameErasureFlag, subframeIndex, P1/2, P0, pastExcitationVector: 154 values */ | |||
| /* output is in the excitationVector */ | |||
| int16_t frameErasureFlag; | |||
| int subFrameIndex; | |||
| uint16_t adaptativeCodebookIndex; | |||
| int16_t parityFlag; | |||
| word16_t excitationVector[L_PAST_EXCITATION + L_FRAME]; /* this vector contains: | |||
| 0->153 : the past excitation vector.(length is Max Pitch Delay: 144 + interpolation window size : 10) | |||
| 154-> 154+L_FRAME-1 : the current frame adaptative Code Vector first used to compute then the excitation vector */ | |||
| int16_t intPitchDelay; /* output of the function when called for subframe wich is sent back as an input for subframe2 */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| initDecodeAdaptativeCodeVector(decoderChannelContext); | |||
| /* initialise buffers */ | |||
| /* actually useless init, because the complete excitation buffer is reload at each subframe from input file, but shall be done in real decoder */ | |||
| memset(excitationVector, 0, L_PAST_EXCITATION*sizeof(word16_t)); /* initialise the part of the excitationVector containing the past excitation */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&frameErasureFlag) != 1) break; | |||
| if (fscanf(fpInput,",%d",&subFrameIndex) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&adaptativeCodebookIndex) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&parityFlag) != 1) break; | |||
| for (i=0; i<194; i++) { | |||
| if (fscanf(fpInput,",%hd",&(excitationVector[i])) != 1) break; | |||
| } | |||
| /* call the tested funtion */ | |||
| decodeAdaptativeCodeVector(decoderChannelContext, subFrameIndex, adaptativeCodebookIndex, (uint8_t)parityFlag, (uint8_t)frameErasureFlag, | |||
| &intPitchDelay, &(excitationVector[L_PAST_EXCITATION + subFrameIndex])); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",excitationVector[L_PAST_EXCITATION + subFrameIndex]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", excitationVector[L_PAST_EXCITATION + subFrameIndex+i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,105 @@ | |||
| /* | |||
| decodeFixedCodeVectorTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decodeFixedCodeVectorTest bloc */ | |||
| /* Input: - signs: parameter S(4 signs bit) eq61 */ | |||
| /* - positions: parameter C(4 3bits position and jx bit) eq62 */ | |||
| /* - intPitchDelay: integer part of pitch Delay (T) */ | |||
| /* - boundedPitchGain: Beta in eq47 and eq48, in Q14 */ | |||
| /* */ | |||
| /* Ouput: - fixedCodebookVector for current subframe in Q13 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "decodeFixedCodeVector.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: Positions(C parameter 13 bits), Signs(S parameter 4 bits), boundedPitchGain, intPitchDelay */ | |||
| /* output: fixedCodebookVector: subframe length vector in Q13 */ | |||
| int16_t signs; | |||
| int16_t positions; | |||
| word16_t boundedPitchGain; | |||
| int16_t intPitchDelay; | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput,"%hd,%hd,%hd,%hd", &positions, &signs, &boundedPitchGain, &intPitchDelay) == 4) /* loop until end of input data */ | |||
| { | |||
| int i; | |||
| /* call the tested funtion */ | |||
| decodeFixedCodeVector((uint16_t)signs, (uint16_t)positions, (int16_t)intPitchDelay, (word16_t)boundedPitchGain, fixedCodebookVector); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",fixedCodebookVector[0]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", fixedCodebookVector[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,116 @@ | |||
| /* | |||
| decodeGainsTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decodeGains bloc */ | |||
| /* Input: - GA parameter */ | |||
| /* - GB parameter */ | |||
| /* - frameErasureFlag */ | |||
| /* - adaptative Codebook Gain from previous frame */ | |||
| /* - fixed Codebook Gain from previous frame */ | |||
| /* - fixed Codebook Vector */ | |||
| /* */ | |||
| /* Ouput: - adaptative Codebook Gain */ | |||
| /* - fixed Codebook Gain */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "decodeGains.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: GA, GB, frameErasureFlag, fixedCodebookVector, adaptative codebook gain, fixed codebook gain */ | |||
| /* output : adaptative codebook gain, adaptative codebook gain */ | |||
| int16_t GA, GB; | |||
| int16_t frameErasureFlag; | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; | |||
| word16_t adaptativeCodebookGain, fixedCodebookGain; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| initDecodeGains(decoderChannelContext); | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&GA) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&GB) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&frameErasureFlag) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&adaptativeCodebookGain) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&fixedCodebookGain) != 1) break; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(fixedCodebookVector[i])) != 1) break; | |||
| } | |||
| /* call the tested funtion */ | |||
| decodeGains(decoderChannelContext, GA, GB, fixedCodebookVector, (uint8_t)frameErasureFlag, | |||
| &adaptativeCodebookGain, &fixedCodebookGain); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d,%d\n",adaptativeCodebookGain, fixedCodebookGain); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,97 @@ | |||
| /* | |||
| decodeLSPTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decodeLSP bloc */ | |||
| /* Input: L coefficient files: L0, L1, L2 and L3 in word16_t format in */ | |||
| /* a text CSV file, 4 values on each row. */ | |||
| /* Ouput: the output of the decodeLSP bloc in a file: series of word16_t */ | |||
| /* 10 elements vectors in a text CSV file */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "decodeLSP.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| uint16_t inputBuffer[4]; /* input buffer: an array containing the 4 L coefficients */ | |||
| word16_t frameErasedIndicator; /* part of the input file */ | |||
| word16_t outputBuffer[NB_LSP_COEFF]; /* output buffer: the quantized LSF coefficients in Q0.15 */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| initDecodeLSP(decoderChannelContext); | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd", &frameErasedIndicator, &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]))==5) | |||
| { | |||
| /* call the decodeLSP function */ | |||
| decodeLSP(decoderChannelContext, inputBuffer, outputBuffer, frameErasedIndicator); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",outputBuffer[0]); | |||
| int i; | |||
| for (i=1; i<NB_LSP_COEFF; i++) { | |||
| fprintf(fpOutput,",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,160 @@ | |||
| /* | |||
| decoderMultiChannelTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decoder on multichannels */ | |||
| /* Input: 15 parameters and the frame erasure flag on each row of a */ | |||
| /* a text CSV file in variable number of files */ | |||
| /* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */ | |||
| /* on a row of a text CSV file in same amount of files */ | |||
| /* */ | |||
| /* All arguments shall be filenames for input file */ | |||
| /* output file keep the prefix and change the file extension to .out.multi*/ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| #include <time.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "utils.h" | |||
| #include "testUtils.h" | |||
| #include "bcg729/decoder.h" | |||
| #define MAX_CHANNEL_NBR 50 | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| int i; | |||
| /*** get calling argument ***/ | |||
| char *filePrefix[MAX_CHANNEL_NBR]; | |||
| getArgumentsMultiChannel(argc, argv, filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput[MAX_CHANNEL_NBR]; | |||
| FILE *fpOutput[MAX_CHANNEL_NBR]; | |||
| FILE *fpBinOutput[MAX_CHANNEL_NBR]; | |||
| /*** input and output buffers ***/ | |||
| uint16_t inputBuffer[NB_PARAMETERS+1]; /* input buffer: an array containing the 15 parameters and the frame erasure flag */ | |||
| int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */ | |||
| uint8_t bitStream[10]; /* binary input for the decoder */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext[MAX_CHANNEL_NBR]; /* context array, one per channel */ | |||
| /*** inits ***/ | |||
| for (i=0; i<argc-1; i++) { | |||
| /* open the inputs file */ | |||
| if ( (fpInput[i] = fopen(argv[i+1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[i+1]); | |||
| exit(-1); | |||
| } | |||
| /* create the outputs file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix[i])+15)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out.multi",filePrefix[i]); | |||
| if ( (fpOutput[i] = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[i], outputFile); | |||
| exit(-1); | |||
| } | |||
| sprintf(outputFile, "%s.multi.pcm",filePrefix[i]); | |||
| if ( (fpBinOutput[i] = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| decoderChannelContext[i] = initBcg729DecoderChannel(); | |||
| } | |||
| /*** initialisation complete ***/ | |||
| /* perf measurement */ | |||
| clock_t start, end; | |||
| double cpu_time_used=0.0; | |||
| int framesNbr =0; | |||
| /* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */ | |||
| #define LOOP_N 1 | |||
| int j,k; | |||
| for (j=0; j<LOOP_N; j++) { | |||
| /* perf measurement */ | |||
| /*** loop over inputs file ***/ | |||
| int endedFilesNbr = 0; | |||
| int endedFiles[MAX_CHANNEL_NBR]; | |||
| for (k=0; k<argc-1; k++) { /* reset the array of boolean containing a flag for files already read */ | |||
| endedFiles[k]=0; | |||
| } | |||
| while (endedFilesNbr<argc-1) { /* loop until the longest file is over */ | |||
| for (k=0; k<argc-1; k++) { /* read one frame on each not ended file */ | |||
| if (endedFiles[k]==0) { /* read only if the file is not over */ | |||
| if (fscanf(fpInput[k], "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]))==16) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */ | |||
| { /* input buffer contains the parameters and in [15] the frame erasure flag */ | |||
| int i; | |||
| framesNbr++; | |||
| parametersArray2BitStream(inputBuffer, bitStream); | |||
| start = clock(); | |||
| bcg729Decoder(decoderChannelContext[k], bitStream, inputBuffer[15], outputBuffer); | |||
| end = clock(); | |||
| cpu_time_used += ((double) (end - start)); | |||
| /* write the output to the output file */ | |||
| if (j==0) { | |||
| fprintf(fpOutput[k],"%d",outputBuffer[0]); | |||
| for (i=1; i<L_FRAME; i++) { | |||
| fprintf(fpOutput[k],",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput[k],"\n"); | |||
| /* write the ouput to raw data file */ | |||
| fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput[k]); | |||
| } | |||
| } else { /* we've reach the end of the file */ | |||
| endedFiles[k]=1; | |||
| endedFilesNbr++; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* perf measurement */ | |||
| for (k=0; k<argc-1; k++) { | |||
| rewind(fpInput[k]); | |||
| } | |||
| } | |||
| /* close decoder channels */ | |||
| for (k=0; k<argc-1; k++) { | |||
| closeBcg729DecoderChannel(decoderChannelContext[k]); | |||
| } | |||
| /* Perf measurement: uncomment next line to print cpu usage */ | |||
| printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC)); | |||
| /* perf measurement */ | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,134 @@ | |||
| /* | |||
| decoderTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for decoder */ | |||
| /* Input: 15 parameters and the frame erasure flag on each row of a */ | |||
| /* a text CSV file. */ | |||
| /* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */ | |||
| /* on a row of a text CSV file */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| #include <time.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "utils.h" | |||
| #include "testUtils.h" | |||
| #include "bcg729/decoder.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| FILE *fpBinOutput; | |||
| /*** input and output buffers ***/ | |||
| uint16_t inputBuffer[NB_PARAMETERS+1]; /* input buffer: an array containing the 15 parameters and the frame erasure flag */ | |||
| uint8_t bitStream[10]; /* binary input for the decoder */ | |||
| int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| sprintf(outputFile, "%s.pcm",filePrefix); | |||
| if ( (fpBinOutput = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = initBcg729DecoderChannel(); | |||
| /*** initialisation complete ***/ | |||
| /* perf measurement */ | |||
| clock_t start, end; | |||
| double cpu_time_used=0.0; | |||
| int framesNbr =0; | |||
| /* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */ | |||
| #define LOOP_N 1 | |||
| int j; | |||
| for (j=0; j<LOOP_N; j++) { | |||
| /* perf measurement */ | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]))==16) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */ | |||
| { /* input buffer contains the parameters and in [15] the frame erasure flag */ | |||
| int i; | |||
| framesNbr++; | |||
| parametersArray2BitStream(inputBuffer, bitStream); | |||
| start = clock(); | |||
| bcg729Decoder(decoderChannelContext, bitStream, inputBuffer[15], outputBuffer); | |||
| end = clock(); | |||
| cpu_time_used += ((double) (end - start)); | |||
| /* write the output to the output files (only on first loop of perf measurement)*/ | |||
| if (j==0) { | |||
| fprintf(fpOutput,"%d",outputBuffer[0]); | |||
| for (i=1; i<L_FRAME; i++) { | |||
| fprintf(fpOutput,",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| /* write the ouput to raw data file */ | |||
| fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput); | |||
| } | |||
| } | |||
| /* perf measurement */ | |||
| rewind(fpInput); | |||
| } | |||
| closeBcg729DecoderChannel(decoderChannelContext); | |||
| /* Perf measurement: uncomment next line to print cpu usage */ | |||
| // printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC)); | |||
| /* perf measurement */ | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,178 @@ | |||
| /* | |||
| encoderMultiChannelTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for encoder on multichannels */ | |||
| /* Input: the reconstructed signal : each frame (80 16 bits PCM values) */ | |||
| /* on a row of a text CSV file */ | |||
| /* Output: 15 parameters on each row of a text CSV file. */ | |||
| /* */ | |||
| /* All arguments shall be filenames for input file */ | |||
| /* output file keep the prefix and change the file extension to .out.multi*/ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <time.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "utils.h" | |||
| #include "testUtils.h" | |||
| #include "bcg729/encoder.h" | |||
| #define MAX_CHANNEL_NBR 50 | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| int i,j,k; | |||
| /*** get calling argument ***/ | |||
| char *filePrefix[MAX_CHANNEL_NBR]; | |||
| getArgumentsMultiChannel(argc, argv, filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput[MAX_CHANNEL_NBR]; | |||
| FILE *fpOutput[MAX_CHANNEL_NBR]; | |||
| /*** input and output buffers ***/ | |||
| int16_t inputBuffer[L_FRAME]; /* output buffer: the signal */ | |||
| uint16_t outputBuffer[NB_PARAMETERS]; /* output buffer: an array containing the 15 parameters */ | |||
| uint8_t bitStream[10]; /* binary output of the encoder */ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext[MAX_CHANNEL_NBR]; /* context, one per channel */ | |||
| uint16_t inputIsBinary[MAX_CHANNEL_NBR]; /* store the information on each input file format (CVS or binary PCM) */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| for (i=0; i<argc-1; i++) { | |||
| inputIsBinary[i] = 0; | |||
| if (argv[i+1][strlen(argv[i+1])-1] == 'n') { /* input filename and by n, it's probably a .in : CSV file */ | |||
| if ( (fpInput[i] = fopen(argv[i+1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[i+1]); | |||
| exit(-1); | |||
| } | |||
| } else { /* it's probably a binary file */ | |||
| inputIsBinary[i] = 1; | |||
| if ( (fpInput[i] = fopen(argv[i+1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[i+1]); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix[i])+15)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out.multi",filePrefix[i]); | |||
| if ( (fpOutput[i] = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| encoderChannelContext[i] = initBcg729EncoderChannel(); | |||
| } | |||
| /*** initialisation complete ***/ | |||
| /* perf measurement */ | |||
| clock_t start, end; | |||
| double cpu_time_used=0.0; | |||
| int framesNbr =0; | |||
| /* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */ | |||
| #define LOOP_N 1 | |||
| for (j=0; j<LOOP_N; j++) { | |||
| /* perf measurement */ | |||
| /*** loop over inputs file ***/ | |||
| int endedFilesNbr = 0; | |||
| int endedFiles[MAX_CHANNEL_NBR]; | |||
| for (k=0; k<argc-1; k++) { /* reset the array of boolean containing a flag for files already read */ | |||
| endedFiles[k]=0; | |||
| } | |||
| while (endedFilesNbr<argc-1) { /* loop until the longest file is over */ | |||
| for (k=0; k<argc-1; k++) { /* read one frame on each not ended file */ | |||
| if (endedFiles[k]==0) { /* read only if the file is not over */ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (inputIsBinary[k]) { | |||
| if (fread(inputBuffer, sizeof(int16_t), L_FRAME, fpInput[k]) != L_FRAME) break; | |||
| } else { | |||
| if (fscanf(fpInput[k],"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_FRAME; i++) { | |||
| if (fscanf(fpInput[k],",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| } | |||
| framesNbr++; | |||
| start = clock(); | |||
| bcg729Encoder(encoderChannelContext[k], inputBuffer, bitStream); | |||
| end = clock(); | |||
| cpu_time_used += ((double) (end - start)); | |||
| /* convert bitStream output in an array for easier debug */ | |||
| parametersBitStream2Array(bitStream, outputBuffer); | |||
| if (j==0) { | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput[k],"%d",outputBuffer[0]); | |||
| for (i=1; i<NB_PARAMETERS; i++) { | |||
| fprintf(fpOutput[k],",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput[k],",0\n"); | |||
| } | |||
| } | |||
| /* we've reach the end of the file */ | |||
| endedFiles[k]=1; | |||
| endedFilesNbr++; | |||
| } | |||
| } | |||
| } | |||
| /* perf measurement */ | |||
| for (k=0; k<argc-1; k++) { | |||
| rewind(fpInput[k]); | |||
| } | |||
| } | |||
| /* close encoder channels */ | |||
| for (k=0; k<argc-1; k++) { | |||
| closeBcg729EncoderChannel(encoderChannelContext[k]); | |||
| } | |||
| /* Perf measurement: uncomment next line to print cpu usage */ | |||
| printf("Encode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC)); | |||
| /* perf measurement */ | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,145 @@ | |||
| /* | |||
| encoderTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for encoder */ | |||
| /* Input: the reconstructed signal : each frame (80 16 bits PCM values) */ | |||
| /* on a row of a text CSV file */ | |||
| /* Output: 15 parameters on each row of a text CSV file. */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <time.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "utils.h" | |||
| #include "testUtils.h" | |||
| #include "bcg729/encoder.h" | |||
| FILE *fpOutput; | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| /*** input and output buffers ***/ | |||
| int16_t inputBuffer[L_FRAME]; /* output buffer: the signal */ | |||
| uint8_t bitStream[10]; /* binary output of the encoder */ | |||
| uint16_t outputBuffer[NB_PARAMETERS]; /* output buffer: an array containing the 15 parameters */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| uint16_t inputIsBinary = 0; | |||
| if (argv[1][strlen(argv[1])-1] == 'n') { /* input filename and by n, it's probably a .in : CSV file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| } else { /* it's probably a binary file */ | |||
| inputIsBinary = 1; | |||
| if ( (fpInput = fopen(argv[1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext = initBcg729EncoderChannel(); | |||
| /*** initialisation complete ***/ | |||
| /* perf measurement */ | |||
| clock_t start, end; | |||
| double cpu_time_used=0.0; | |||
| int framesNbr =0; | |||
| /* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */ | |||
| #define LOOP_N 1 | |||
| int j; | |||
| for (j=0; j<LOOP_N; j++) { | |||
| /* perf measurement */ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (inputIsBinary) { | |||
| if (fread(inputBuffer, sizeof(int16_t), L_FRAME, fpInput) != L_FRAME) break; | |||
| } else { | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_FRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| } | |||
| framesNbr++; | |||
| start = clock(); | |||
| bcg729Encoder(encoderChannelContext, inputBuffer, bitStream); | |||
| end = clock(); | |||
| cpu_time_used += ((double) (end - start)); | |||
| /* convert bitStream output in an array for easier debug */ | |||
| parametersBitStream2Array(bitStream, outputBuffer); | |||
| if (j==0) { | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",outputBuffer[0]); | |||
| for (i=1; i<NB_PARAMETERS; i++) { | |||
| fprintf(fpOutput,",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,",0\n"); | |||
| } | |||
| } | |||
| /* perf measurement */ | |||
| rewind(fpInput); | |||
| } | |||
| closeBcg729EncoderChannel(encoderChannelContext); | |||
| /* Perf measurement: uncomment next line to print cpu usage */ | |||
| // printf("Encode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC)); | |||
| /* perf measurement */ | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,93 @@ | |||
| /* | |||
| findOpenLoopPitchDelayTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for find open loop pitch delay bloc */ | |||
| /* - input : 143+80 weighted Input Speech */ | |||
| /* - output : the open loop pitch delay in range [20, 143] */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "findOpenLoopPitchDelay.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t inputBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* 40 values in Q0 */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<MAXIMUM_INT_PITCH_DELAY+L_FRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| /* call the openLoopPitchDelay function, input buffer is accessed in range [-MAXIMUM_INT_PITCH_DELAY, L_FRAME] */ | |||
| int openLoopPitchDelay = findOpenLoopPitchDelay(&(inputBuffer[MAXIMUM_INT_PITCH_DELAY])); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d\n", openLoopPitchDelay); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,133 @@ | |||
| /* | |||
| fixedCodebookSearchTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for fixedCodebookSearchTest bloc */ | |||
| /* Input: */ | |||
| /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ | |||
| /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ | |||
| /* -(i) intPitchDelay: current integer pitch delay */ | |||
| /* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */ | |||
| /* gain quantized in Q14 */ | |||
| /* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */ | |||
| /* -(i) adaptativeCodebookGain : in Q14 */ | |||
| /* */ | |||
| /* Ouput: */ | |||
| /* -(o) fixedCodebookParameter */ | |||
| /* -(o) fixedCodebookPulsesSigns */ | |||
| /* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q0 */ | |||
| /* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */ | |||
| /* in Q12 */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "fixedCodebookSearch.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* inputs : */ | |||
| word16_t targetSignal[L_SUBFRAME]; /* Q0 */ | |||
| word16_t impulseResponse[L_SUBFRAME]; /* Q12 */ | |||
| int16_t intPitchDelay; | |||
| word16_t lastQuantizedAdaptativeCodebookGain, adaptativeCodebookGain; /* Q14 */ | |||
| word16_t filteredAdaptativeCodebookVector[L_SUBFRAME]; /* Q0 */ | |||
| /* outputs : */ | |||
| uint16_t fixedCodebookParameter, fixedCodebookPulsesSigns; | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; | |||
| word16_t fixedCodebookVectorConvolved[L_SUBFRAME]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| for (i=0; i<40; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(targetSignal[i])) != 1) break; | |||
| } | |||
| for (i=0; i<40; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(impulseResponse[i])) != 1) break; | |||
| } | |||
| if (fscanf(fpInput,"%hd,",&intPitchDelay) != 1) break; | |||
| if (fscanf(fpInput,"%hd,",&lastQuantizedAdaptativeCodebookGain) != 1) break; | |||
| for (i=0; i<40; i++) { | |||
| if (fscanf(fpInput,"%hd,",&(filteredAdaptativeCodebookVector[i])) != 1) break; | |||
| } | |||
| if (fscanf(fpInput,"%hd",&adaptativeCodebookGain) != 1) break; | |||
| /* call the tested funtion */ | |||
| fixedCodebookSearch(targetSignal, impulseResponse, intPitchDelay, lastQuantizedAdaptativeCodebookGain, filteredAdaptativeCodebookVector, adaptativeCodebookGain, | |||
| &fixedCodebookParameter, &fixedCodebookPulsesSigns, fixedCodebookVector, fixedCodebookVectorConvolved); | |||
| /* write the output to the output file : fixedCodebookParameter, fixedCodebookPulsesSigns, fixedCodebookVector */ | |||
| fprintf(fpOutput, "%d,%d,%d", fixedCodebookParameter, fixedCodebookPulsesSigns, fixedCodebookVector[0]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", fixedCodebookVector[i]); | |||
| } | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", fixedCodebookVectorConvolved[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,310 @@ | |||
| /* | |||
| g729FixedPointMathTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program g729 Fixed Point Math library */ | |||
| /* */ | |||
| /* library provides: */ | |||
| /* g729Log2_Q0Q16 : Logarithm base 2 */ | |||
| /* g729Exp2_Q11Q16 : Exponentiel base 2 */ | |||
| /* g729Sqrt_Q0Q7 : Square Root */ | |||
| /* g729Cos_Q13Q15 : Cosine */ | |||
| /* g729Atan_Q15Q13 : Arc Tangent */ | |||
| /* g729Asin_Q15Q13 : Arc Sine */ | |||
| /* g729Acos_Q15Q13 : Arc Cosine */ | |||
| /* */ | |||
| /* Extention QxxQyy stands for input in Qxx output in Qyy */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include "g729FixedPointMath.h" | |||
| #include "math.h" | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| /* convert the float result from math.h to a fixed point integer in Qxx */ | |||
| word32_t float2FixedPoint(float x, int Q) | |||
| { | |||
| return (word32_t)round((double)x*(double)(1<<Q)); | |||
| } | |||
| /* convert a Qxx integer to float */ | |||
| float fixedPoint2Float(word32_t x, int Q) | |||
| { | |||
| return (float)x/(float)(1<<Q); | |||
| } | |||
| /* no arguments just test all the functions */ | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| int64_t i; | |||
| int computationNumber = 0; | |||
| double diffSum = 0; | |||
| double diffSumPercent = 0; | |||
| int maxDiff = 0; | |||
| int maxDiffIndex = -1; | |||
| double maxDiffPercent = 0; | |||
| int maxDiffIndexPercent = -1; | |||
| /* g729Log2_Q0Q16 : Logarithm base 2 */ | |||
| for (i=1; i<0x7FFFFFF; i+=0x10) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Log2_Q0Q16((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(log2f(i), 16); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Log2 : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Exp2_Q11Q16 : Exponentiel base 2 */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=0; i<2048; i+=0x1) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Exp2_Q11Q16((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(exp2f(fixedPoint2Float(i,11)), 16); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Exp2 : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Sqrt_Q0Q7 : Square Root */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=0; i<0x7FFFFFF; i+=0x8) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Sqrt_Q0Q7((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(sqrtf(i), 7); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Square Root : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729InvSqrt_Q0Q30 : Inverse Square Root */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=1; i<0x7FFFFFF; i+=0x8) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729InvSqrt_Q0Q31((word32_t)i)>>1; | |||
| word32_t resMath = float2FixedPoint(1.0/sqrtf(i), 30); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Inverse Square Root : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Cos_Q13Q15 : Cosine */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=0; i<25736; i+=0x1) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Cos_Q13Q15((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(cosf(fixedPoint2Float(i,13)), 15); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Cosine : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Atan_Q15Q13 : Arc Tangent */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=-0x8000000; i<0x7ffffff; i+=0x1) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Atan_Q15Q13((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(atanf(fixedPoint2Float(i,15)), 13); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Arc Tangent : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Asin_Q15Q13 : Arc Sine */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=-0x7fff; i<0x7ffe; i+=0x1) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Asin_Q15Q13((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(asinf(fixedPoint2Float(i,15)), 13); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Arc Sine : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| /* g729Acos_Q15Q13 : Arc Cosine */ | |||
| computationNumber = 0; | |||
| diffSum = 0; | |||
| diffSumPercent = 0; | |||
| maxDiff = 0; | |||
| maxDiffIndex = -1; | |||
| maxDiffPercent = 0; | |||
| maxDiffIndexPercent = -1; | |||
| for (i=-0x7fff; i<0x7ffe; i+=0x1) { | |||
| computationNumber++; | |||
| word32_t resg729 = g729Acos_Q15Q13((word32_t)i); | |||
| word32_t resMath = float2FixedPoint(acosf(fixedPoint2Float(i,15)), 13); | |||
| int currentDiff = abs(resg729-resMath); | |||
| double currentDiffPercent = 0; | |||
| if (resMath!=0 && resg729!=0 && currentDiff!=0) currentDiffPercent = 100.0*currentDiff/(float)resMath; | |||
| diffSum += currentDiff; | |||
| diffSumPercent += currentDiffPercent; | |||
| if (currentDiff>maxDiff) { | |||
| maxDiff = currentDiff; | |||
| maxDiffIndex = i; | |||
| } | |||
| if (currentDiffPercent>maxDiffPercent) { | |||
| maxDiffPercent = currentDiffPercent; | |||
| maxDiffIndexPercent = i; | |||
| } | |||
| } | |||
| printf ("Arc Cosine : %d computation\n Mean Diff %f Mean Percent Diff %f\n Max Diff %d(%d) Max Percent Diff %f(%d)\n", | |||
| computationNumber, diffSum/computationNumber, diffSumPercent/computationNumber, maxDiff, maxDiffIndex, maxDiffPercent, maxDiffIndexPercent); | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,128 @@ | |||
| /* | |||
| gainQuantizationTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for gainQuantization bloc */ | |||
| /* Input: */ | |||
| /* -(i) targetSignal: 40 values in Q0, x in eq63 */ | |||
| /* -(i) filteredAdaptativeCodebookVector: 40 values in Q0, y in eq63 */ | |||
| /* -(i) convolvedFixedCodebookVector: 40 values in Q12, z in eq63 */ | |||
| /* -(i) fixedCodebookVector: 40 values in Q13 */ | |||
| /* -(i) xy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* -(i) yy in Q0 on 64 bits term of eq63 computed previously */ | |||
| /* */ | |||
| /* Ouput: */ | |||
| /* -(o) quantizedAdaptativeCodebookGain : in Q14 */ | |||
| /* -(o) quantizedFixedCodebookGain : in Q1 */ | |||
| /* -(o) gainCodebookStage1 : GA parameter value (3 bits) */ | |||
| /* -(o) gainCodebookStage2 : GB parameter value (4 bits) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "gainQuantization.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* inputs : */ | |||
| word16_t targetSignal[L_SUBFRAME]; /* Q0 */ | |||
| word16_t filteredAdaptativeCodebookVector[L_SUBFRAME]; /* Q0 */ | |||
| word16_t convolvedFixedCodebookVector[L_SUBFRAME]; /* Q12 */ | |||
| word16_t fixedCodebookVector[L_SUBFRAME]; /* Q13 */ | |||
| word64_t xy, yy; /* Q0 */ | |||
| /* outputs : */ | |||
| word16_t quantizedAdaptativeCodebookGain, quantizedFixedCodebookGain; /* Q14 */ | |||
| uint16_t gainCodebookStage1, gainCodebookStage2; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct)); | |||
| initGainQuantization(encoderChannelContext); | |||
| /* initialise buffers */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%lld,%lld",(long long*)&xy,(long long*) &yy) != 2) break; | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(targetSignal[i])) != 1) break; | |||
| } | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(filteredAdaptativeCodebookVector[i])) != 1) break; | |||
| } | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(convolvedFixedCodebookVector[i])) != 1) break; | |||
| } | |||
| for (i=0; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(fixedCodebookVector[i])) != 1) break; | |||
| } | |||
| /* call the tested funtion */ | |||
| gainQuantization(encoderChannelContext, targetSignal, filteredAdaptativeCodebookVector, convolvedFixedCodebookVector, fixedCodebookVector, xy, yy, | |||
| &quantizedAdaptativeCodebookGain, &quantizedFixedCodebookGain, &gainCodebookStage1, &gainCodebookStage2); | |||
| /* write the output to the output file : fixedCodebookParameter, fixedCodebookPulsesSigns, fixedCodebookVector */ | |||
| fprintf(fpOutput, "%d,%d,%d,%d\n", quantizedAdaptativeCodebookGain, quantizedFixedCodebookGain, gainCodebookStage1, gainCodebookStage2); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,114 @@ | |||
| /* | |||
| interpolateqLSPAndConvert2LPTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for interpolateqLSP and qLSP2LP Blocs */ | |||
| /* Input: 10 qLSP coefficients in word16_t format in Q0.15 */ | |||
| /* a text CSV file, 10 values on each row. */ | |||
| /* Ouput: the 10 LP coefficients for first and second subframe */ | |||
| /* 20 elements vectors in a text CSV file */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "interpolateqLSP.h" | |||
| #include "qLSP2LP.h" | |||
| /* buffers allocation */ | |||
| static word16_t previousqLSP[NB_LSP_COEFF]; | |||
| static const word16_t previousqLSPInitialValues[NB_LSP_COEFF] = {30000, 26000, 21000, 15000, 8000, 0, -8000,-15000,-21000,-26000}; /* in Q0.15 the initials values for the previous qLSP buffer */ | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t inputBuffer[NB_LSP_COEFF]; /* input buffer: an array containing the 10 qLSP coefficients for the current frame */ | |||
| word16_t outputBuffer[2*NB_LSP_COEFF]; /* output buffer: the LP coefficients in Q2.13 for subframe 1 and 2 (20 LP coefficients)*/ | |||
| word16_t interpolatedqLSP[NB_LSP_COEFF]; /* the interpolated qLSP used to produce 1st subframe LP */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* initialise buffers */ | |||
| memcpy(previousqLSP, previousqLSPInitialValues, NB_LSP_COEFF*sizeof(word16_t)); /* initialise the previousqLSP buffer */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]))==10) | |||
| { /* input buffer contains current qLSP */ | |||
| /* call the interpolate function, result will be stored in the interpolatedqLSP buffer */ | |||
| interpolateqLSP(previousqLSP, inputBuffer, interpolatedqLSP); | |||
| int i; | |||
| /* copy the currentqLSP to previousqLSP buffer */ | |||
| for (i=0; i<NB_LSP_COEFF; i++) { | |||
| previousqLSP[i] = inputBuffer[i]; | |||
| } | |||
| /* call the qLSP2LP function for first subframe */ | |||
| qLSP2LP(interpolatedqLSP, outputBuffer); | |||
| /* call the qLSP2LP function for second subframe */ | |||
| qLSP2LP(inputBuffer, &(outputBuffer[NB_LSP_COEFF])); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",outputBuffer[0]); | |||
| for (i=1; i<2*NB_LSP_COEFF; i++) { | |||
| fprintf(fpOutput,",%d",outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,119 @@ | |||
| /* | |||
| postFilterTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for postFilter */ | |||
| /* Input: - LPCoefficients: 10 LP coeff for current subframe(in Q12) */ | |||
| /* - reconstructedSpeech: output of LP Synthesis */ | |||
| /* 50 values in Q0: need 10 values of previous subframe */ | |||
| /* buffer is accessed in range [-10, 39] */ | |||
| /* - intPitchDelay: the integer part of Pitch Delay(in Q0) */ | |||
| /* - subframeIndex: 0 or L_SUBFRAME for subframe 0 or 1 */ | |||
| /* - residualSignal: 143+40 values of previous frames computation */ | |||
| /* */ | |||
| /* Ouput: - long term postfilered signal (40 values in Q0) */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "postFilter.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* input file: 10 LP Coefficients(Q12), 50 reconstructedSpeech, intPitchDelay (Q0), subframeIndex(0/40) */ | |||
| word16_t LP[NB_LSP_COEFF]; | |||
| word16_t reconstructedSpeech[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, output of the LP synthesis filter, the first 10 words store the previous subframe output */ | |||
| int16_t intPitchDelay; | |||
| int16_t subframeIndex; | |||
| /* output postFiltered signal(40 values in Q0) */ | |||
| word16_t postFilteredSignal[L_SUBFRAME]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "r")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "w")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| initPostFilter(decoderChannelContext); | |||
| /* initialise buffers */ | |||
| /* past reconstructedSpeech values shall be initialised, but we read them directly from input file */ | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data as long as we find some */ | |||
| if (fscanf(fpInput,"%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd",&LP[0],&LP[1],&LP[2],&LP[3],&LP[4],&LP[5],&LP[6],&LP[7],&LP[8],&LP[9]) != 10) break; | |||
| for (i=0; i<L_SUBFRAME+NB_LSP_COEFF; i++) { | |||
| if (fscanf(fpInput,",%hd",&(reconstructedSpeech[i])) != 1) break; | |||
| } | |||
| if (fscanf(fpInput,",%hd",&intPitchDelay) != 1) break; | |||
| if (fscanf(fpInput,",%hd",&subframeIndex) != 1) break; | |||
| /* call the tested funtion */ | |||
| postFilter(decoderChannelContext, LP, &(reconstructedSpeech[NB_LSP_COEFF]), intPitchDelay, subframeIndex, postFilteredSignal); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", postFilteredSignal[0]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d", postFilteredSignal[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,99 @@ | |||
| /* | |||
| postProcessingTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for postProcessing Bloc */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "postProcessing.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| /* output buffer is the same than input buffer */ | |||
| word16_t inputBuffer[L_SUBFRAME]; /* 40 values in Q0 */ | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729DecoderChannelContextStruct *decoderChannelContext = malloc(sizeof(bcg729DecoderChannelContextStruct)); | |||
| initPostProcessing(decoderChannelContext); | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| /* call the preProcessing function: output will replace the input in the buffer */ | |||
| postProcessing(decoderChannelContext, inputBuffer); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d",inputBuffer[0]); | |||
| for (i=1; i<L_SUBFRAME; i++) { | |||
| fprintf(fpOutput,",%d",inputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,101 @@ | |||
| /* | |||
| preProcessingTest.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| /*****************************************************************************/ | |||
| /* */ | |||
| /* Test Program for preProcessing Bloc */ | |||
| /* Input: a CSV text with frame of 80 values of 16 bits PCM on each row */ | |||
| /* Ouput: the filtered input, same format */ | |||
| /* */ | |||
| /*****************************************************************************/ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| #include "codecParameters.h" | |||
| #include "testUtils.h" | |||
| #include "preProcessing.h" | |||
| int main(int argc, char *argv[] ) | |||
| { | |||
| /*** get calling argument ***/ | |||
| char *filePrefix; | |||
| getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */ | |||
| /*** input and output file pointers ***/ | |||
| FILE *fpInput; | |||
| FILE *fpOutput; | |||
| /*** input and output buffers ***/ | |||
| word16_t inputBuffer[L_FRAME]; | |||
| word16_t outputBuffer[L_FRAME]; | |||
| /*** inits ***/ | |||
| /* open the input file */ | |||
| if ( (fpInput = fopen(argv[1], "rb")) == NULL) { | |||
| printf("%s - Error: can't open file %s\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| /* create the output file(filename is the same than input file with the .out extension) */ | |||
| char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char)); | |||
| sprintf(outputFile, "%s.out",filePrefix); | |||
| if ( (fpOutput = fopen(outputFile, "wb")) == NULL) { | |||
| printf("%s - Error: can't create file %s\n", argv[0], outputFile); | |||
| exit(-1); | |||
| } | |||
| /*** init of the tested bloc ***/ | |||
| /* create the context structure */ | |||
| bcg729EncoderChannelContextStruct *encoderChannelContext = malloc(sizeof(bcg729EncoderChannelContextStruct)); | |||
| initPreProcessing(encoderChannelContext); | |||
| /*** initialisation complete ***/ | |||
| /*** loop over input file ***/ | |||
| while(1) /* infinite loop, escape condition is in the reading of data */ | |||
| { | |||
| int i; | |||
| /* read the input data until we have some */ | |||
| if (fscanf(fpInput,"%hd",&(inputBuffer[0])) != 1) break; | |||
| for (i=1; i<L_FRAME; i++) { | |||
| if (fscanf(fpInput,",%hd",&(inputBuffer[i])) != 1) break; | |||
| } | |||
| /* call the preProcessing function: output will replace the input in the buffer */ | |||
| preProcessing(encoderChannelContext, inputBuffer, outputBuffer); | |||
| /* write the output to the output file */ | |||
| fprintf(fpOutput,"%d", outputBuffer[0]); | |||
| for (i=1; i<L_FRAME; i++) { | |||
| fprintf(fpOutput,",%d", outputBuffer[i]); | |||
| } | |||
| fprintf(fpOutput,"\n"); | |||
| } | |||
| exit (0); | |||
| } | |||
| @ -0,0 +1,103 @@ | |||
| /* | |||
| testUtils.c | |||
| Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| Author : Johan Pascal | |||
| This program is free software; you can redistribute it and/or | |||
| modify it under the terms of the GNU General Public License | |||
| as published by the Free Software Foundation; either version 2 | |||
| of the License, or (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include "typedef.h" | |||
| void printUsage(char *command) | |||
| { | |||
| printf ("Usage:\n %s -p|<input file name>\n\n This executable request one argument either:\n -p : display the computation type(fixed or floating) and exit\nor\n <input file name> : process the input file and write the output in a file with the same prefix a .out extension\n\n",command); | |||
| exit (-1); | |||
| } | |||
| int getArgument(int argc, char *argv[], char** filePrefix) | |||
| { | |||
| /* We have only one argument wich can be either the input filename or -p which will answer either floating or fixed according */ | |||
| /* computation mode being fixed or floating point */ | |||
| if (argc != 2) { | |||
| printUsage(argv[0]); | |||
| exit (-1); | |||
| } | |||
| if (argv[1][0] == '-') { | |||
| if (argv[1][1] == 'p') { /* -p switch, return fixed or floating and exit */ | |||
| #ifdef FLOATING_POINT | |||
| printf ("floating\n"); | |||
| #else /* ifdef FLOATING_POINT */ | |||
| printf ("fixed\n"); | |||
| #endif /* ifdef FLOATING_POINT */ | |||
| exit(0); | |||
| } else { /* unknow switch, display usage and exit */ | |||
| printUsage(argv[0]); | |||
| exit (-1); | |||
| } | |||
| } else { /* argument is the input file */ | |||
| /* get the input file prefix */ | |||
| int i = strlen(argv[1])-1; | |||
| int pos = 0; | |||
| while (pos==0) { | |||
| if (argv[1][i]=='.') { | |||
| pos = i; | |||
| } | |||
| i--; | |||
| if (i==0) { | |||
| printf("%s - Error input file %s doesn't contain any ., impossible to extract prefix\n", argv[0], argv[1]); | |||
| exit(-1); | |||
| } | |||
| } | |||
| *filePrefix = malloc((pos+3)*sizeof(char)); | |||
| strncpy(*filePrefix, argv[1], pos); | |||
| (*filePrefix)[pos]='\0'; | |||
| } | |||
| return 0; | |||
| } | |||
| int getArgumentsMultiChannel(int argc, char *argv[], char *filePrefix[]) | |||
| { | |||
| while (argc>1) { /* loop over all the argument which shall be input file names */ | |||
| argc--; | |||
| /* get the input file prefix */ | |||
| int i = strlen(argv[argc])-1; | |||
| int pos = 0; | |||
| while (pos==0) { | |||
| if (argv[argc][i]=='.') { | |||
| pos = i; | |||
| } | |||
| i--; | |||
| if (i==0) { | |||
| printf("%s - Error input file %s doesn't contain any ., impossible to extract prefix\n", argv[0], argv[argc]); | |||
| exit(-1); | |||
| } | |||
| } | |||
| filePrefix[argc-1] = malloc((pos+3)*sizeof(char)); | |||
| strncpy(filePrefix[argc-1], argv[argc], pos); | |||
| filePrefix[argc-1][pos]='\0'; | |||
| } | |||
| return 0; | |||
| } | |||
| @ -0,0 +1,3 @@ | |||
| void printUsage(char *command); | |||
| int getArgument(int argc, char *argv[], char** filePrefix); | |||
| int getArgumentsMultiChannel(int argc, char *argv[], char *filePrefix[]); | |||
| @ -0,0 +1,259 @@ | |||
| #!/usr/bin/perl -w | |||
| use Term::ANSIColor; | |||
| # testCampaign | |||
| # | |||
| # Copyright (C) 2011 Belledonne Communications, Grenoble, France | |||
| # Author : Johan Pascal | |||
| # | |||
| # This program is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU General Public License | |||
| # as published by the Free Software Foundation; either version 2 | |||
| # of the License, or (at your option) any later version. | |||
| # | |||
| # This program is distributed in the hope that it will be useful, | |||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| # GNU General Public License for more details. | |||
| # | |||
| # You should have received a copy of the GNU General Public License | |||
| # along with this program; if not, write to the Free Software | |||
| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| # This script allow testing of g729 encoder/decoder functional blocs | |||
| # by default each bloc output is supposed to be identical to the pattern | |||
| # it can be configured to monitor and accept a (setable) difference between output | |||
| # and pattern(which can occur if a bloc or macros are modified). | |||
| # Tune the defaultMaxDiff associative array definition to modify | |||
| # the behavior of this script for any functional bloc under test | |||
| my $binDirectory = "./bin/"; | |||
| my $patternDirectory = "./patterns"; | |||
| # softDiff: compare two CSV files with a margin of acceptance between the values found | |||
| # arguments : file1, file2, maximumDiff tolerated(value), maximum percentage abs((val1-val2)/val1)*100 tolerated | |||
| # maximum condition ignored when set to 0 so it might be used: | |||
| # - with one maximum condition | |||
| # - with both maximum condition : trigger a warning if both maxima are exceded | |||
| sub softDiff | |||
| { | |||
| my $filename1 = shift; | |||
| my $filename2 = shift; | |||
| my $maxDiff = shift; | |||
| my $percentMaxDiff = shift; | |||
| my $printStats = shift; | |||
| # open the file1 and file2 | |||
| open (FP1, $filename1) or die "Can't open $filename1: $!"; | |||
| open (FP2, $filename2) or die "Can't open $filename2: $!"; | |||
| # remove path from filename2 as it might be used in error report | |||
| $filename2 =~ s/.*\/(.*?)\..*$/$1/; | |||
| # total values number count variables for stats | |||
| my $nbr_values = 0; | |||
| my $total_diff = 0; | |||
| my $total_values = 0; | |||
| my $maxMaxDiff = 0; | |||
| my $maxPercentDiff = 0; | |||
| # boolean for return value: 0 no warning, 1 warning(s) | |||
| my $warnings = 0; | |||
| # loop over file1 | |||
| while(<FP1>) { | |||
| # get line number to display in potential message | |||
| my $lineNb = $.; | |||
| # get file1 and file2 CSV line into an array | |||
| my @line1 = (); | |||
| my @line2 = (); | |||
| @line1 = split (',', $_); | |||
| @line2 = split (',', <FP2>); | |||
| # check they have the same number of values | |||
| my $line1length = @line1; | |||
| my $line2length = @line2; | |||
| if ($line1length != $line2length) { | |||
| die "at line $., $filename1 and $filename2 doesn't have the same number of values"; | |||
| } | |||
| # loop on the values and compare them | |||
| for (my $i=0; $i<$line1length; $i++) { | |||
| chomp($line1[$i]); | |||
| chomp($line2[$i]); | |||
| my $diff = abs($line1[$i]-$line2[$i]); | |||
| my $percentDiff; | |||
| if (abs($line1[$i])+abs($line2[$i]) == 0) { | |||
| $percentDiff = 0; | |||
| } else { | |||
| $percentDiff = $diff/(abs($line1[$i])+abs($line2[$i]))*200; | |||
| } | |||
| # Stats if needed | |||
| if ($printStats) { | |||
| $nbr_values++; # increment values counts | |||
| $total_diff += $diff; | |||
| $total_values += (abs($line1[$i])+abs($line2[$i]))/2; | |||
| if ($diff>$maxMaxDiff) {$maxMaxDiff=$diff;$maxPercentDiff=$percentDiff;} | |||
| } | |||
| if ($maxDiff> 0 && $percentMaxDiff> 0) { | |||
| if (($diff>$maxDiff) && ($percentDiff>$percentMaxDiff)) { | |||
| $warnings =1; | |||
| print "WARNING : $filename2: line $lineNb value $i ($line1[$i] and $line2[$i]) differ by $diff(".$percentDiff."%)\n"; | |||
| } | |||
| } else { # on a une ou zero condition */ | |||
| if ($maxDiff> 0) { # if we shall check the absolute value difference | |||
| if ($diff>$maxDiff) { | |||
| $warnings =1; | |||
| print "WARNING : $filename2: line $lineNb value $i ($line1[$i] and $line2[$i]) differ by $diff\n"; | |||
| } | |||
| } | |||
| if ($percentMaxDiff> 0) { # if we shall check the percentage of difference | |||
| if ($percentDiff>$percentMaxDiff) { | |||
| $warnings =1; | |||
| print "WARNING : $filename2: line $lineNb. value $i ($line1[$i] and $line2[$i]) differ by ".$percentDiff."%\n"; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| close (FP1); | |||
| close (FP2); | |||
| if ($printStats) {printf ("Stats: Max Diff: %d(%f) mean diff: %0.3f mean percent diff : %0.2f\n",$maxMaxDiff, $maxPercentDiff, $total_diff/$nbr_values, $total_diff*100/$total_values);} | |||
| return $warnings; | |||
| } | |||
| if ((@ARGV < 1) || (@ARGV > 2)) | |||
| { | |||
| print "##############################################################################\n"; | |||
| print "# #\n"; | |||
| print "# testCampaign [-s] <test name> #\n"; | |||
| print "# test name in the following list : #\n"; | |||
| print "# - decoder #\n"; | |||
| print "# - decodeLSP #\n"; | |||
| print "# - interpolateqLSPAndConvert2LP #\n"; | |||
| print "# - decodeAdaptativeCodeVector #\n"; | |||
| print "# - decodeFixedCodeVector #\n"; | |||
| print "# - decodeGains #\n"; | |||
| print "# - LPSynthesisFilter #\n"; | |||
| print "# - postFilter #\n"; | |||
| print "# - postProcessing #\n"; | |||
| print "# #\n"; | |||
| print "# - encoder #\n"; | |||
| print "# - preProcessing #\n"; | |||
| print "# - computeLP #\n"; | |||
| print "# - LP2LSPConversion #\n"; | |||
| print "# - LSPQuantization #\n"; | |||
| print "# - computeWeightedSpeech #\n"; | |||
| print "# - findOpenLoopPitchDelay #\n"; | |||
| print "# - adaptativeCodebookSearch #\n"; | |||
| print "# - computeAdaptativeCodebookGain #\n"; | |||
| print "# - fixedCodebookSearch #\n"; | |||
| print "# - gainQuantization #\n"; | |||
| print "# #\n"; | |||
| print "# - all : perform all tests #\n"; | |||
| print "# Options switch: #\n"; | |||
| print "# -s : Display stats on each test (when running softDiff) #\n"; | |||
| print "# #\n"; | |||
| print "##############################################################################\n"; | |||
| exit; | |||
| } | |||
| # check command validity | |||
| # TODO | |||
| my $printStats = 0; | |||
| # Get the test name | |||
| my $command=$ARGV[@ARGV-1]; | |||
| # is there a switch? | |||
| if ($ARGV[0] eq "-s") { | |||
| $printStats= 1; | |||
| } | |||
| # define the default values to use for maxDiff and percentualMaxDiff for each test | |||
| # "<testedBlocName> => [<absolut maximum difference>,<percentual maximum difference>]" | |||
| # if both set to 0, the diff command will be used | |||
| %defaultMaxDiff = ( "preProcessing" => [0,0], | |||
| "computeLP" => [0,0], | |||
| "LP2LSPConversion" => [0,0], | |||
| "LSPQuantization" => [0,0], | |||
| "computeWeightedSpeech" => [0,0], | |||
| "findOpenLoopPitchDelay" => [0,0], | |||
| "adaptativeCodebookSearch" => [0,0], | |||
| "computeAdaptativeCodebookGain" => [0,0], | |||
| "fixedCodebookSearch" => [0,0], | |||
| "gainQuantization" => [0,0], | |||
| "encoder" => [0,0], | |||
| "decodeLSP" => [0,0], | |||
| "interpolateqLSPAndConvert2LP" => [0,0], | |||
| "decodeAdaptativeCodeVector" => [0,0], | |||
| "decodeFixedCodeVector" => [0,0], | |||
| "decodeGains" => [0,0], | |||
| "LPSynthesisFilter" => [0,0], | |||
| "postFilter" => [0,0], | |||
| "postProcessing" => [0,0], | |||
| "decoder" => [0,0] | |||
| ); | |||
| # check command: | |||
| if ($command eq "all") { # if run all tests, just get the defaultMaxDiff array as testsList as the test directory are retrieved from keys | |||
| %testsList = %defaultMaxDiff; | |||
| } else { | |||
| %testsList = ($command, 0); # we run one test: create an associative array with one element having a key matching the test name | |||
| } | |||
| #return value for autotools make check | |||
| my $exitVal = 0; | |||
| foreach my $testDirectory (keys %testsList) { | |||
| # get the files | |||
| opendir(DIR, $patternDirectory."/".$testDirectory) or die "can't open directory $patternDirectory/$testDirectory: $!"; | |||
| my @files = grep { /\.in$/ } readdir(DIR); | |||
| closedir(DIR); | |||
| my $testExec = $binDirectory.$testDirectory."Test"; | |||
| print "Test $testDirectory bloc\n"; | |||
| # for each *.in file found in the test directory | |||
| foreach my $file (@files) { | |||
| # run the testExecutable | |||
| my $filebase = $file; | |||
| $filebase =~ s/^(.*?)\..*/$1/; | |||
| print " $filebase"; | |||
| print `$testExec $patternDirectory/$testDirectory/$file`; | |||
| # compare the output file with the pattern file | |||
| my $filepattern = $file; | |||
| $filepattern =~ s/\.in$/\.pattern/; | |||
| my $fileout = $file; | |||
| $fileout =~ s/\.in$/\.out/; | |||
| my $maxDiffTolerated = $defaultMaxDiff{$testDirectory}[0]; | |||
| my $maxPercentualDiffTolerated = $defaultMaxDiff{$testDirectory}[1]; | |||
| if ($maxDiffTolerated==0 && $maxPercentualDiffTolerated==0) { # no difference accepted, use the classic diff function | |||
| $differs = `diff $patternDirectory/$testDirectory/$filepattern $patternDirectory/$testDirectory/$fileout`; | |||
| if ($differs ne "") { | |||
| print " ... "; | |||
| print colored("Fail\n", "red"); | |||
| $exitVal = 1; | |||
| } else { | |||
| printf " ... Pass\n" | |||
| } | |||
| } else { # accept difference => use the softDiff function | |||
| if (softDiff($patternDirectory."/".$testDirectory."/".$filepattern, $patternDirectory."/".$testDirectory."/".$fileout, $maxDiffTolerated, $maxPercentualDiffTolerated, $printStats) == 0) { | |||
| printf " ... Pass\n" | |||
| } else { | |||
| printf " $filebase ... "; | |||
| print colored("Fail\n", "red"); | |||
| $exitVal = 1; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| exit($exitVal); | |||
| @ -0,0 +1,31 @@ | |||
| #! /bin/sh | |||
| # This script check if we have the tests patterns and download them if needed | |||
| # then run all available tests | |||
| # Do we have a patterns directory | |||
| if [ ! -d "patterns" ]; then | |||
| # no pattern directory: download it from | |||
| # http://www.belledonne-communications.com/downloads/bcg729-patterns.zip | |||
| wget http://www.belledonne-communications.com/downloads/bcg729-patterns.zip | |||
| if [ -e bcg729-patterns.zip ]; then | |||
| # check file | |||
| if [[ `md5sum bcg729-patterns.zip | grep -c 75b4fb8b286485c375c9c326f8b9eb66` -ne 0 ]]; then | |||
| # file ok, unzip it | |||
| unzip bcg729-patterns.zip | |||
| if [[ $? -ne 0 ]]; then | |||
| echo "Error: unable to unzip correctly bcg729-patterns.zip, try to do it manually" | |||
| else | |||
| rm bcg729-patterns.zip | |||
| fi | |||
| else | |||
| echo "Error: bad checksum on bcg729-patterns.zip downloaded from http://www.belledonne-communications.com/downloads/.\nTry again" | |||
| exit 1 | |||
| fi | |||
| else | |||
| echo "Error: Unable to download bcg729-patterns.zip pattern archive from http://www.belledonne-communications.com/downloads/" | |||
| exit 1 | |||
| fi | |||
| fi | |||
| # run all the tests | |||
| ./testCampaign all | |||