Initial commit

This commit is contained in:
WhiteChi 2023-10-25 21:14:40 +08:00
commit bbe9ba3e6c
1582 changed files with 112385 additions and 0 deletions

26
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@ -0,0 +1,26 @@
---
name: 提交Bug / Submit Bug
about: 向我们报告一个Bug以帮助我们改进
title: 'bug: '
labels: bug
---
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/Shamrock/actions/workflows/build-apk.yml) 的 Shamrock.
- 确保您的问题尚未在 Issues 列表中提出.
- 确保您的问题不是由于您的代码错误导致的.
### 描述 Bug
请清晰地描述此 Bug 的具体表现,并提供错误日志。
### 复现 Bug
请提供复现 Bug 的详细步骤,以确保我们可以理解并定位问题。
## 系统信息
- Shamrock 版本:
- Android 版本:
- 设备的制造商和型号:
- 设备的 CPU 架构:

21
.github/ISSUE_TEMPLATE/feature.md vendored Normal file
View File

@ -0,0 +1,21 @@
---
name: 功能请求 / Feature Request
about: 向我们提交一个新功能的请求
title: 'feat: '
labels: enhancement
---
警告: 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭
- 确保您使用的是 [最新开发版本](https://github.com/whitechi73/Shamrock/actions/workflows/build-apk.yml) 的 Shamrock.
- 确保您的功能请求尚未在 Issues 列表中提出.
- 确保您的功能请求是与 Shamrock 相关的,且可以实现.
### 描述功能
请清晰地描述您想要的功能,并提供相关的信息。
### 实现方法
请提供您认为可以实现此功能的方法,如果您不知道如何实现,可以留空。
当然,如果您有兴趣,也可以自己实现并向我们提交 Pull Request。

87
.github/workflows/build-apk.yml vendored Normal file
View File

@ -0,0 +1,87 @@
name: Build Shamrock APK
on:
workflow_dispatch:
push:
branches: [ master ]
paths-ignore:
- '**.md'
- '**.txt'
- '.github/**'
- '.idea/**'
- '!.github/workflows/**'
jobs:
build:
name: Build APK
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: 17
cache: 'gradle'
- name: Setup cmake
run: |
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
echo "sdk.dir=${ANDROID_HOME}" > local.properties
- name: Setup Gradle
uses: gradle/gradle-build-action@v2.9.0
- name: Build with Gradle
run: |
echo ${{ secrets.SIGN_KEYSTORE_BASE64 }} | base64 -d > keystore.jks
chmod +x ./gradlew
./gradlew :app:assembleRelease --build-cache --parallel --daemon --warning-mode all --stacktrace
echo "APK_FILE_ALL=$(find app/build/outputs/apk/app/release -name '*.apk')" >> $GITHUB_ENV
echo "APK_FILE_ARM64=$(find app/build/outputs/apk/arm64/release -name '*.apk')" >> $GITHUB_ENV
echo "APK_FILE_X86_64=$(find app/build/outputs/apk/x64/release -name '*.apk')" >> $GITHUB_ENV
env:
KEYSTORE_PATH: "../keystore.jks"
KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.SIGN_ALIAS }}
KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
- name: Install aapt
run: sudo apt-get update && sudo apt-get install -y aapt
- name: Set Shamrock Version
run: |
apk_file=${{ env.APK_FILE_ALL }}
apk_dump=$(aapt dump badging "$apk_file")
version_name=$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<< "$apk_dump")
echo "SHAMROCK_VERSION=$version_name" >> $GITHUB_ENV
- name: Show Artifacts SHA256
run: |
echo "### Build Success :rocket:" >> $GITHUB_STEP_SUMMARY
echo "|ABI|SHA256|" >> $GITHUB_STEP_SUMMARY
echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY
all=($(sha256sum ${{ env.APK_FILE_ALL }}))
echo "|all|$all" >> $GITHUB_STEP_SUMMARY
arm64=($(sha256sum ${{ env.APK_FILE_ARM64 }}))
echo "|arm64|$arm64" >> $GITHUB_STEP_SUMMARY
x86_64=($(sha256sum ${{ env.APK_FILE_X86_64 }}))
echo "|x86_64|$x86_64" >> $GITHUB_STEP_SUMMARY
- name: Upload ALL APK RELEASE
uses: actions/upload-artifact@v3
with:
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-all
path: ${{ env.APK_FILE_ALL }}
- name: Upload ARM64 APK RELEASE
uses: actions/upload-artifact@v3
with:
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-arm64
path: ${{ env.APK_FILE_ARM64 }}
- name: Upload X86_64 APK RELEASE
uses: actions/upload-artifact@v3
with:
name: Shamrock-v${{ env.SHAMROCK_VERSION }}-x86_64
path: ${{ env.APK_FILE_X86_64 }}

57
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,57 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: '24 7 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 360
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3.6.0
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Setup JDK 17
uses: actions/setup-java@v3.12.0
with:
distribution: "temurin"
java-version: 17
- name: Setup Gradle
uses: gradle/gradle-build-action@v2.8.0
- name: Setup cmake
run: |
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
echo "sdk.dir=${ANDROID_HOME}" > local.properties
- name: Build
run: |
chmod +x ./gradlew
./gradlew :app:assembleAppRelease
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

73
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,73 @@
name: Shamrock Release
on:
push:
tags:
- 'v*'
jobs:
build:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: "temurin"
java-version: 17
cache: 'gradle'
- name: Setup cmake
run: |
echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.22.1" --sdk_root=${ANDROID_SDK_ROOT} &> /dev/null
echo "sdk.dir=${ANDROID_HOME}" > local.properties
- name: Setup Gradle
uses: gradle/gradle-build-action@v2.9.0
- name: Build with Gradle
run: |
echo ${{ secrets.SIGN_KEYSTORE_BASE64 }} | base64 -d > keystore.jks
chmod +x ./gradlew
./gradlew :app:assembleRelease --build-cache --parallel --daemon --warning-mode all --stacktrace
echo "APK_FILE_ALL=$(find app/build/outputs/apk/app/release -name '*.apk')" >> $GITHUB_ENV
echo "APK_FILE_ARM64=$(find app/build/outputs/apk/arm64/release -name '*.apk')" >> $GITHUB_ENV
echo "APK_FILE_X86_64=$(find app/build/outputs/apk/x64/release -name '*.apk')" >> $GITHUB_ENV
env:
KEYSTORE_PATH: "../keystore.jks"
KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.SIGN_ALIAS }}
KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
- name: Install aapt
run: sudo apt-get update && sudo apt-get install -y aapt
- name: Set Shamrock Version
run: |
apk_file=${{ env.APK_FILE_ALL }}
apk_dump=$(aapt dump badging "$apk_file")
version_name=$(sed -n "s/.*versionName='\([^']*\)'.*/\1/p" <<< "$apk_dump")
echo "SHAMROCK_VERSION=$version_name" >> $GITHUB_ENV
- name: Show Artifacts SHA256
run: |
echo "### Build Success :rocket:" >> $GITHUB_STEP_SUMMARY
echo "|ABI|SHA256|" >> $GITHUB_STEP_SUMMARY
echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY
all=($(sha256sum ${{ env.APK_FILE_ALL }}))
echo "|all|$all" >> $GITHUB_STEP_SUMMARY
arm64=($(sha256sum ${{ env.APK_FILE_ARM64 }}))
echo "|arm64|$arm64" >> $GITHUB_STEP_SUMMARY
x86_64=($(sha256sum ${{ env.APK_FILE_X86_64 }}))
echo "|x86_64|$x86_64" >> $GITHUB_STEP_SUMMARY
- name: Release
uses: marvinpinto/action-automatic-releases@latest
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
automatic_release_tag: Shamrock v${{ env.SHAMROCK_VERSION }}
files: |
${{ env.APK_FILE_ALL }}
${{ env.APK_FILE_ARM64 }}
${{ env.APK_FILE_X86_64 }}

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
*.iml
.gradle/
local.properties
.idea/
.DS_Store
build/
.externalNativeBuild
.cxx
app/app/release
app/arm64/release
app/x64/release

BIN
AudioLibrary.zip Normal file

Binary file not shown.

128
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
mut@vip.qq.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

1
CONTRIBUTING.md Normal file
View File

@ -0,0 +1 @@
docs

674
LICENSE Normal file
View File

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
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
state 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 3 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, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU 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 Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

106
README.md Normal file
View File

@ -0,0 +1,106 @@
<div align="center">
![][banner]
[![][actions]][actions-link]
[![][releases]][releases-link]
[![][downloads]][releases-link]
![][onebot-11]
![][onebot-12]
[![][license]](LICENSE)
[下载][download-link] | [部署][deploy-link] | [接口][api-link] | [文档][docs-link] | [加群][group-link]
</div>
## 简介
☘ 基于 Xposed 实现 OneBot 标准的 QQ 机器人框架,原作者**fuqiuluo**已脱离开发接下来由白池接手哦本项目为OpenShamrock不会有任何收费行为欢迎大家的加入
> 本项目仅提供学习与交流用途请在24小时内删除。
> 本项目目的是研究 Xposed 和 LSPosed 框架的使用。 Epic 框架开发相关知识。
> 如有违反法律,请联系删除。
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
## 兼容|迁移|替代 说明
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
- 平行部署:可多平台部署,未来将会支持 Docker 部署的教程。
> 若您追求小而轻便的Bot服务, [Chronocat](https://chronocat.vercel.app/)是您的不二之选,而不是迁移到闭源框架。
## 权限声明
如出现未在此处声明的权限,请警惕 Shamrock 是否被修改/植入恶意代码
- 网络访问权限: Shamrock 进程需要使用 HTTP API 来进行一些操作
- [Hook 系统框架][hook-system]: 为了保证息屏状态下服务不被杀死Shamrock 需要 Hook 系统框架
- 后台启动 Activity: 自动唤醒 QQ 时需要使用
## 语音解码
请参考文档中 [语音支持][voice-support] 部分
## 贡献说明
<img src="https://github.com/whitechi73/Shamrock/assets/61898844/b7b1f44a-2ab3-4eae-a955-4f8a7ef696f5" width="160px"> **我可爱吗?欢迎你的到来,这里是一个很大的地方,有着无限可能,主要是有你啦!**
## 开源协议
本项目使用 [GPL-3.0](LICENSE) 协议开放源代码
```text
Shamrock - OneBot standard QQ robot framework based on Xposed implementation
Copyright (C) 2023 Shamrock Team
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 3 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, see <http://www.gnu.org/licenses/>.
```
## 贡献者
[![][contrib-image]][contrib-link]
[banner]: https://socialify.git.ci/whitechi73/Shamrock/image?description=1&forks=1&issues=1&logo=https%3A%2F%2Fwhitechi73.github.io%2FShamrock%2Fshamrock.jpg&pattern=Plus&pulls=1&stargazers=1&theme=Auto
[actions]: https://img.shields.io/github/actions/workflow/status/whitechi73/Shamrock/build-apk.yml?style=for-the-badge
[actions-link]: https://github.com/whitechi73/Shamrock/actions/workflows/build-apk.yml
[releases]: https://img.shields.io/github/v/release/whitechi73/Shamrock?style=for-the-badge
[releases-link]: https://github.com/whitechi73/Shamrock/releases
[downloads]: https://img.shields.io/github/downloads/whitechi73/Shamrock/total?style=for-the-badge
[license]: https://img.shields.io/github/license/whitechi73/Shamrock?style=for-the-badge
[onebot-11]: https://img.shields.io/badge/OneBot-11-black?style=for-the-badge
[onebot-12]: https://img.shields.io/badge/OneBot-12-black?style=for-the-badge
[download-link]: https://whitechi73.github.io/Shamrock/guide/getting-started.html#%E4%B8%8B%E8%BD%BD
[deploy-link]: https://whitechi73.github.io/Shamrock/guide/getting-started.html#%E9%83%A8%E7%BD%B2
[api-link]: https://whitechi73.github.io/Shamrock/api
[docs-link]: https://whitechi73.github.io/Shamrock/
[group-link]: https://whitechi73.github.io/Shamrock/group.html
[hook-system]: https://github.com/whitechi73/Shamrock/wiki/perm_hook_android
[voice-support]: https://whitechi73.github.io/Shamrock/advanced/voice.html
[contrib-image]: https://contrib.rocks/image?repo=whitechi73/Shamrock
[contrib-link]: https://github.com/whitechi73/Shamrock/graphs/contributors

11
SECURITY.md Normal file
View File

@ -0,0 +1,11 @@
# Security Policy
## Support Version
| Version | Supported |
| ------- | ------------------ |
| 8.9.75 | :white_check_mark: |
| 8.9.73 | :white_check_mark: |
| 8.9.98 | :white_check_mark: |
| < 8.9.68| :x: |

2
app/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/build
/release/

204
app/build.gradle.kts Normal file
View File

@ -0,0 +1,204 @@
import com.android.build.api.dsl.ApplicationExtension
fun gitCommitHash(): String {
val builder = ProcessBuilder("git", "rev-parse", "--short", "HEAD")
val process = builder.start()
val reader = process.inputReader()
val hash = reader.readText().trim()
return if (hash.isNotEmpty()) ".$hash" else ""
}
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
kotlin("plugin.serialization") version "1.8.10"
}
android {
namespace = "moe.fuqiuluo.shamrock"
ndkVersion = "25.1.8937393"
compileSdk = 33
defaultConfig {
applicationId = "moe.fuqiuluo.shamrock"
minSdk = 24
targetSdk = 33
versionCode = (System.currentTimeMillis() / 1000).toInt()
versionName = "1.0.5-dev" + gitCommitHash()
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
externalNativeBuild {
cmake {
cppFlags += ""
}
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
android.applicationVariants.all {
outputs.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
.forEach {
val abi = it.outputFileName.split("-")[1].split(".apk")[0]
val abiName = when (abi) {
"app" -> "all"
"x64" -> "x86_64"
else -> abi
}
it.outputFileName = "Shamrock-v${versionName}-${abiName}.apk"
}
}
flavorDimensions.add("mode")
productFlavors {
create("app") {
dimension = "mode"
ndk {
abiFilters.add("arm64-v8a")
abiFilters.add("x86_64")
}
}
create("arm64") {
dimension = "mode"
ndk {
abiFilters.add("arm64-v8a")
}
}
create("x64") {
dimension = "mode"
ndk {
abiFilters.add("x86_64")
}
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.3"
}
packaging {
jniLibs {
useLegacyPackaging = true
}
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
excludes += "/META-INF/*"
excludes += "/META-INF/NOTICE.txt"
excludes += "/META-INF/DEPENDENCIES.txt"
excludes += "/META-INF/NOTICE"
excludes += "/META-INF/LICENSE"
excludes += "/META-INF/DEPENDENCIES"
excludes += "/META-INF/notice.txt"
excludes += "/META-INF/dependencies.txt"
excludes += "/META-INF/LGPL2.1"
excludes += "/META-INF/ASL2.0"
excludes += "/META-INF/INDEX.LIST"
excludes += "/META-INF/io.netty.versions.properties"
excludes += "/META-INF/INDEX.LIST"
excludes += "/META-INF/LICENSE.txt"
excludes += "/META-INF/license.txt"
excludes += "/META-INF/*.kotlin_module"
excludes += "/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration"
}
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
configureAppSigningConfigsForRelease(project)
}
fun configureAppSigningConfigsForRelease(project: Project) {
val keystorePath: String? = System.getenv("KEYSTORE_PATH")
if (keystorePath.isNullOrBlank()) {
return
}
project.configure<ApplicationExtension> {
signingConfigs {
create("release") {
storeFile = file(System.getenv("KEYSTORE_PATH"))
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
enableV2Signing = true
}
}
buildTypes {
release {
signingConfig = signingConfigs.findByName("release")
}
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
implementation("androidx.activity:activity-compose:1.7.2")
implementation(platform("androidx.compose:compose-bom:2023.06.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
//noinspection GradleDynamicVersion
implementation("com.google.accompanist:accompanist-pager:0.31.5+")
//noinspection GradleDynamicVersion
implementation("com.google.accompanist:accompanist-systemuicontroller:0.31.5+")
//noinspection GradleDynamicVersion useless
// implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0+")
implementation("io.coil-kt:coil:2.4.0")
implementation("io.coil-kt:coil-compose:2.4.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.1.16")
implementation("io.ktor:ktor-server-core:2.3.3")
implementation("io.ktor:ktor-server-host-common:2.3.3")
implementation("io.ktor:ktor-server-status-pages:2.3.3")
implementation("io.ktor:ktor-server-netty:2.3.3")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.3")
implementation("io.ktor:ktor-server-content-negotiation:2.3.3")
implementation("io.ktor:ktor-client-core:2.3.3")
implementation("io.ktor:ktor-client-cio:2.3.3")
implementation("io.ktor:ktor-client-content-negotiation:2.3.3")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.3")
// useless
//implementation ("com.maxkeppeler.sheets-compose-dialogs:core:1.2.0")
//implementation ("com.maxkeppeler.sheets-compose-dialogs:info:1.2.0")
//implementation ("com.maxkeppeler.sheets-compose-dialogs:input:1.2.0")
//implementation ("com.maxkeppeler.sheets-compose-dialogs:list:1.2.0")
//implementation ("com.maxkeppeler.sheets-compose-dialogs:state:1.2.0")
implementation(project(":xposed"))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}

215
app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,215 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# Never inline methods, but allow shrinking and obfuscation.
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.ViewCompat$Api* {
<methods>;
}
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.view.WindowInsetsCompat$*Impl* {
<methods>;
}
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.app.NotificationCompat$*$Api*Impl {
<methods>;
}
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.os.UserHandleCompat$Api*Impl {
<methods>;
}
-keepclassmembernames,allowobfuscation,allowshrinking class androidx.core.widget.EdgeEffectCompat$Api*Impl {
<methods>;
}
# Keep metadata about inner emulated classes. This helps with
# reflection on older platforms, but can be omitted if the
# metadata usage is not present in the app.
-keepclassmembers class * {
** CREATOR;
}
# Keep the special static methods that are required in all enumeration
# classes.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public class androidx.appcompat.widget.** { *; }
-keep public class androidx.appcompat.app.** { *; }
-keep public class androidx.appcompat.view.menu.** { *; }
# Ensure that reflectively-loaded inflater is not obfuscated. This can be
# removed when we stop supporting AAPT1 builds.
-keepnames class androidx.appcompat.app.AppCompatViewInflater
# aapt is not able to read app::actionViewClass and app:actionProviderClass to produce proguard
# keep rules. Add a commonly used SearchView to the keep list until b/109831488 is resolved.
-keep class androidx.appcompat.widget.SearchView { <init>(...); }
# CoordinatorLayout resolves the behaviors of its child components with reflection.
-keep public class * extends androidx.coordinatorlayout.widget.CoordinatorLayout$Behavior {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>();
}
# Make sure we keep annotations for CoordinatorLayout's DefaultBehavior
-keepattributes RuntimeVisible*Annotation*
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
# Don't print notes about potential mistakes or omissions in the configuration for kotlinx-serialization classes
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
-dontnote kotlinx.serialization.**
# Serialization core uses `java.lang.ClassValue` for caching inside these specified classes.
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
# However, since in this case they will not be used, we can disable these warnings
-dontwarn kotlinx.serialization.internal.ClassValueReferences
# Rule to save runtime annotations on serializable class.
# If the R8 full mode is used, annotations are removed from classes-files.
#
# For the annotation serializer, it is necessary to read the `Serializable` annotation inside the serializer<T>() function - if it is present,
# then `SealedClassSerializer` is used, if absent, then `PolymorphicSerializer'.
#
# When using R8 full mode, all interfaces will be serialized using `PolymorphicSerializer`.
#
# see https://github.com/Kotlin/kotlinx.serialization/issues/2050
-if @kotlinx.serialization.Serializable class **
-keep, allowshrinking, allowoptimization, allowobfuscation class <1>
# Entry point for retaining MainDispatcherLoader which uses a ServiceLoader.
-keep class kotlinx.coroutines.Dispatchers {
** getMain();
}
# Entry point for retaining CoroutineExceptionHandlerImpl.handlers which uses a ServiceLoader.
-keep class kotlinx.coroutines.CoroutineExceptionHandlerKt {
void handleCoroutineException(...);
}
# Entry point for the rest of coroutines machinery
-keep class kotlinx.coroutines.BuildersKt {
** runBlocking(...);
** launch(...);
}
# We are cheating a bit by not having android.jar on R8's library classpath. Ignore those warnings.
-ignorewarnings
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
-keep class kotlinx.coroutines.android.AndroidExceptionPreHandler {*;}
# Statically turn off all debugging facilities and assertions
-keepclassmembers class io.ktor.** { volatile <fields>; }
-keep class io.ktor.** { *; }
-keep class kotlinx.coroutines.** { *; }
-dontwarn kotlinx.atomicfu.**
-dontwarn io.netty.**
-dontwarn com.typesafe.**
-assumenosideeffects class * implements org.slf4j.Logger {
public *** trace(...);
public *** debug(...);
public *** info(...);
public *** warn(...);
public *** error(...);
}
-keep class kotlin.reflect.jvm.internal.** { *; }
-keep class com.arthenica.ffmpegkit.FFmpegKitConfig {
native <methods>;
void log(long, int, byte[]);
void statistics(long, int, float, float, long , int, double, double);
int safOpen(int);
int safClose(int);
}
-keep class com.arthenica.ffmpegkit.AbiDetect {
native <methods>;
}
-dontwarn android.view.RenderNode
-dontwarn android.view.DisplayListCanvas
-keepclassmembers class androidx.compose.ui.platform.ViewLayerContainer {
protected void dispatchGetDisplayList();
}
-keepclassmembers class androidx.compose.ui.platform.AndroidComposeView {
android.view.View findViewByAccessibilityIdTraversal(int);
}
# Users can create Modifier.Node instances that implement multiple Modifier.Node interfaces,
# so we cannot tell whether two modifier.node instances are of the same type without using
# reflection to determine the class type. See b/265188224 for more context.
-keep,allowshrinking class * extends androidx.compose.ui.node.ModifierNodeElement
-keep class org.jetbrains.skia.** { *; }
-keep class org.jetbrains.skiko.** { *; }
-assumenosideeffects public class androidx.compose.runtime.ComposerKt {
void sourceInformation(androidx.compose.runtime.Composer,java.lang.String);
void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String);
void sourceInformationMarkerEnd(androidx.compose.runtime.Composer);
}
-keep class com.arthenica.ffmpegkit.NativeLoader { *; }
-keep class moe.fuqiuluo.** { *; }
-keep class com.tencent.** { *; }
-keep class com.qq.** { *; }
-keep class com.google.gson.** { *; }
-keep class de.** { *; }
-keep class mqq.** { *; }
-keep class QQService.** { *; }
-keep class SummaryCard.** { *; }
-keep class tencent.** { *; }
-keepclassmembers class * {
native <methods>;
}
-keep class io.netty.** { *; }

View File

@ -0,0 +1,24 @@
package moe.fuqiuluo.shamrock
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("moe.fuqiuluo.shamrock", appContext.packageName)
}
}

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".app.MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Shamrock"
android:zygotePreloadName="@string/app_name"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Shamrock"
tools:ignore="RedundantLabel">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name=".ui.service.internal.MultifunctionalProvider"
android:authorities="moe.fuqiuluo.xqbot.provider"
android:exported="true"
android:grantUriPermissions="true"
tools:ignore="ExportedContentProvider" />
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="基于 Xposed 实现 OneBot 标准的 QQ 机器人框架" />
<meta-data
android:name="xposedminversion"
android:value="23" />
<meta-data
android:name="xposedscope"
android:resource="@array/xposed_scope" />
<!--适配华为huawei刘海屏-->
<meta-data
android:name="android.notch_support"
android:value="true" />
<!--适配小米xiaomi刘海屏-->
<meta-data
android:name="notch.config"
android:value="portrait|landscape" />
</application>
</manifest>

View File

@ -0,0 +1,52 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html.
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.
# Sets the minimum CMake version required for this project.
cmake_minimum_required(VERSION 3.22.1)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
# Since this is the top level CMakeLists.txt, the project name is also accessible
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
# build script scope).
project("shamrock")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
include_directories(interface)
include_directories(src)
AUX_SOURCE_DIRECTORY(src SRC_DIR)
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
${SRC_DIR}
md5.cpp
cqcode.cpp
silk.cpp
group_honor.cpp
message.cpp
shamrock.cpp)
# Specifies libraries CMake should link to your target library. You
# can link libraries from various origins, such as libraries defined in this
# build script, prebuilt third-party libraries, or Android system libraries.
target_link_libraries(${CMAKE_PROJECT_NAME}
# List libraries link to the target library
android
log)

123
app/src/main/cpp/cqcode.cpp Normal file
View File

@ -0,0 +1,123 @@
#include <stdexcept>
#include "cqcode.h"
inline void replace_string(std::string& str, const std::string& from, const std::string& to) {
size_t startPos = 0;
while ((startPos = str.find(from, startPos)) != std::string::npos) {
str.replace(startPos, from.length(), to);
startPos += to.length();
}
}
void decode_cqcode(const std::string& code, std::vector<std::unordered_map<std::string, std::string>>& dest) {
std::string cache;
bool is_start = false;
std::string key_tmp;
std::unordered_map<std::string, std::string> kv;
for(int i = 0; i < code.size(); i++) {
auto c = code[i];
if (c == '[') {
if (is_start) {
throw illegal_code();
} else {
if (!cache.empty()) {
std::unordered_map<std::string, std::string> kv;
kv.emplace("_type", "text");
kv.emplace("text", cache);
dest.push_back(kv);
cache.clear();
}
auto c1 = code[i + 1];
if (c1 == 'C') {
i++;
auto c2 = code[i + 1];
if(c2 == 'Q') {
i++;
auto c3 = code[i + 1];
if (c3 == ':') {
i++;
is_start = true;
} else {
cache += c;
cache += c1;
cache += c2;
continue;
}
} else {
cache += c;
cache += c1;
continue;
}
} else {
cache += c;
continue;
}
}
}
else if (c == '=') {
if (is_start) {
if (cache.empty()) {
throw illegal_code();
} else {
if (key_tmp.empty()) {
key_tmp.append(cache);
cache.clear();
} else {
cache += c;
}
}
} else {
cache += c;
}
}
else if (c == ',') {
if (is_start) {
if (kv.count("_type") == 0 && !cache.empty()) {
kv.emplace("_type", cache);
cache.clear();
} else {
if (!key_tmp.empty()) {
replace_string(cache, "&amp;", "&");
replace_string(cache, "&#91;", "[");
replace_string(cache, "&#93;", "]");
replace_string(cache, "&#44;", ",");
kv.emplace(key_tmp, cache);
cache.clear();
key_tmp.clear();
}
}
} else {
cache += c;
}
}
else if (c == ']') {
if (is_start) {
if (!cache.empty()) {
if (!key_tmp.empty()) {
replace_string(cache, "&amp;", "&");
replace_string(cache, "&#91;", "[");
replace_string(cache, "&#93;", "]");
replace_string(cache, "&#44;", ",");
kv.emplace(key_tmp, cache);
}
dest.push_back(kv);
kv.clear();
key_tmp.clear();
cache.clear();
is_start = false;
}
} else {
cache += c;
}
}
else {
cache += c;
}
}
if (!cache.empty()) {
std::unordered_map<std::string, std::string> kv;
kv.emplace("_type", "text");
kv.emplace("text", cache);
dest.push_back(kv);
}
}

View File

@ -0,0 +1,87 @@
#include "jni.h"
#include <vector>
#include <string>
#include <algorithm>
struct Honor {
int id;
std::string name;
std::string icon_url;
int priority;
};
int calc_honor_flag(int honor_id, char honor_flag);
jobject make_honor_object(JNIEnv *env, jobject user_id, const Honor& honor);
extern "C"
JNIEXPORT jobject JNICALL
Java_moe_fuqiuluo_shamrock_remote_action_handlers_GetTroopHonor_nativeDecodeHonor(JNIEnv *env, jobject thiz,
jstring user_id,
jint honor_id,
jbyte honor_flag) {
static std::vector<Honor> honor_list = {
Honor{1, "龙王", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150116_n4PxCiurbm.png", 1},
Honor{2, "群聊之火", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190136_92JEGFKC5k.png", 3},
Honor{3, "群聊炽焰", "https://qzonestyle.gtimg.cn/aoi/sola/20200217190204_zgCTeSrMq1.png", 4},
Honor{5, "冒尖小春笋", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150335_tUJCAtoKVP.png", 5},
Honor{6, "快乐源泉", "https://qzonestyle.gtimg.cn/aoi/sola/20200213150434_3tDmsJExCP.png", 7},
Honor{7, "学术新星", "https://sola.gtimg.cn/aoi/sola/20200515140645_j0X6gbuHNP.png", 8},
Honor{8, "顶尖学霸", "https://sola.gtimg.cn/aoi/sola/20200515140639_0CtWOpfVzK.png", 9},
Honor{9, "至尊学神", "https://sola.gtimg.cn/aoi/sola/20200515140628_P8UEYBjMBT.png", 10},
Honor{10, "一笔当先", "https://sola.gtimg.cn/aoi/sola/20200515140654_4r94tSCdaB.png", 11},
Honor{11, "奋进小翠竹", "https://sola.gtimg.cn/aoi/sola/20200812151819_wbj6z2NGoB.png", 6},
Honor{12, "氛围魔杖", "https://sola.gtimg.cn/aoi/sola/20200812151831_4ZJgQCaD1H.png", 2},
Honor{13, "壕礼皇冠", "https://sola.gtimg.cn/aoi/sola/20200930154050_juZOAMg7pt.png", 12},
};
int flag = calc_honor_flag(honor_id, honor_flag);
if ((honor_id != 1 && honor_id != 2 && honor_id != 3) || flag != 1) {
auto honor = *std::find_if(honor_list.begin(), honor_list.end(), [&honor_id](auto &honor) {
return honor.id == honor_id;
});
return make_honor_object(env, user_id, honor);
} else {
auto honor = *std::find_if(honor_list.begin(), honor_list.end(), [&honor_id](auto &honor) {
return honor.id == honor_id;
});
std::string url = "https://static-res.qq.com/static-res/groupInteract/vas/a/" + std::to_string(honor_id) + "_1.png";
honor = Honor{honor_id, honor.name, url, honor.priority};
return make_honor_object(env, user_id, honor);
}
}
int calc_honor_flag(int honor_id, char honor_flag) {
int flag;
if (honor_flag == 0) {
return 0;
}
if (honor_id == 1) {
flag = honor_flag;
} else if (honor_id == 2 || honor_id == 3) {
flag = honor_flag >> 2;
} else if (honor_id != 4) {
return 0;
} else {
flag = honor_flag >> 4;
}
return flag & 3;
}
jobject make_honor_object(JNIEnv *env, jobject user_id, const Honor& honor) {
jclass GroupMemberHonor = env->FindClass("moe/fuqiuluo/shamrock/remote/service/data/GroupMemberHonor");
jmethodID GroupMemberHonor_init = env->GetMethodID(GroupMemberHonor, "<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
auto user_id_str = (jstring) user_id;
jstring honor_desc = env->NewStringUTF(honor.name.c_str());
jstring uin_name = env->NewStringUTF("");
jstring honor_icon_url = env->NewStringUTF(honor.icon_url.c_str());
jobject ret = env->NewObject(GroupMemberHonor, GroupMemberHonor_init, user_id_str, uin_name, honor_icon_url, 0, honor.id, honor_desc);
env->DeleteLocalRef(GroupMemberHonor);
env->DeleteLocalRef(user_id_str);
env->DeleteLocalRef(honor_desc);
env->DeleteLocalRef(honor_icon_url);
return ret;
}

View File

@ -0,0 +1,152 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_SDK_API_H
#define SKP_SILK_SDK_API_H
#include "SKP_Silk_control.h"
#include "SKP_Silk_typedef.h"
#include "SKP_Silk_errors.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define SILK_MAX_FRAMES_PER_PACKET 5
/* Struct for TOC (Table of Contents) */
typedef struct {
SKP_int framesInPacket; /* Number of 20 ms frames in packet */
SKP_int fs_kHz; /* Sampling frequency in packet */
SKP_int inbandLBRR; /* Does packet contain LBRR information */
SKP_int corrupt; /* Packet is corrupt */
SKP_int vadFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* VAD flag for each frame in packet */
SKP_int sigtypeFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Signal type for each frame in packet */
} SKP_Silk_TOC_struct;
/****************************************/
/* Encoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk encoder state */
/***********************************************/
SKP_int SKP_Silk_SDK_Get_Encoder_Size(
SKP_int32 *encSizeBytes /* O: Number of bytes in SILK encoder state */
);
/*************************/
/* Init or reset encoder */
/*************************/
SKP_int SKP_Silk_SDK_InitEncoder(
void *encState, /* I/O: State */
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
);
/***************************************/
/* Read control structure from encoder */
/***************************************/
SKP_int SKP_Silk_SDK_QueryEncoder(
const void *encState, /* I: State */
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
);
/**************************/
/* Encode frame with Silk */
/**************************/
SKP_int SKP_Silk_SDK_Encode(
void *encState, /* I/O: State */
const SKP_SILK_SDK_EncControlStruct *encControl, /* I: Control status */
const SKP_int16 *samplesIn, /* I: Speech sample input vector */
SKP_int nSamplesIn, /* I: Number of samples in input vector */
SKP_uint8 *outData, /* O: Encoded output vector */
SKP_int16 *nBytesOut /* I/O: Number of bytes in outData (input: Max bytes) */
);
/****************************************/
/* Decoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk decoder state */
/***********************************************/
SKP_int SKP_Silk_SDK_Get_Decoder_Size(
SKP_int32 *decSizeBytes /* O: Number of bytes in SILK decoder state */
);
/*************************/
/* Init or Reset decoder */
/*************************/
SKP_int SKP_Silk_SDK_InitDecoder(
void *decState /* I/O: State */
);
/******************/
/* Decode a frame */
/******************/
SKP_int SKP_Silk_SDK_Decode(
void* decState, /* I/O: State */
SKP_SILK_SDK_DecControlStruct* decControl, /* I/O: Control Structure */
SKP_int lostFlag, /* I: 0: no loss, 1 loss */
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input bytes */
SKP_int16 *samplesOut, /* O: Decoded output speech vector */
SKP_int16 *nSamplesOut /* I/O: Number of samples (vector/decoded) */
);
/***************************************************************/
/* Find Low Bit Rate Redundancy (LBRR) information in a packet */
/***************************************************************/
void SKP_Silk_SDK_search_for_LBRR(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input Bytes */
SKP_int lost_offset, /* I: Offset from lost packet */
SKP_uint8 *LBRRData, /* O: LBRR payload */
SKP_int16 *nLBRRBytes /* O: Number of LBRR Bytes */
);
/**************************************/
/* Get table of contents for a packet */
/**************************************/
void SKP_Silk_SDK_get_TOC(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input bytes */
SKP_Silk_TOC_struct *Silk_TOC /* O: Table of contents */
);
/**************************/
/* Get the version number */
/**************************/
/* Return a pointer to string specifying the version */
const char *SKP_Silk_SDK_get_version(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,91 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_CONTROL_H
#define SKP_SILK_CONTROL_H
#include "SKP_Silk_typedef.h"
#ifdef __cplusplus
extern "C"
{
#endif
/***********************************************/
/* Structure for controlling encoder operation */
/***********************************************/
typedef struct {
/* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 API_sampleRate;
/* I: Maximum internal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 maxInternalSampleRate;
/* I: Number of samples per packet; must be equivalent of 20, 40, 60, 80 or 100 ms */
SKP_int packetSize;
/* I: Bitrate during active speech in bits/second; internally limited */
SKP_int32 bitRate;
/* I: Uplink packet loss in percent (0-100) */
SKP_int packetLossPercentage;
/* I: Complexity mode; 0 is lowest; 1 is medium and 2 is highest complexity */
SKP_int complexity;
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
SKP_int useInBandFEC;
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
SKP_int useDTX;
} SKP_SILK_SDK_EncControlStruct;
/**************************************************************************/
/* Structure for controlling decoder operation and reading decoder status */
/**************************************************************************/
typedef struct {
/* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 API_sampleRate;
/* O: Number of samples per frame */
SKP_int frameSize;
/* O: Frames per packet 1, 2, 3, 4, 5 */
SKP_int framesPerPacket;
/* O: Flag to indicate that the decoder has remaining payloads internally */
SKP_int moreInternalDecoderFrames;
/* O: Distance between main payload and redundant payload in packets */
SKP_int inBandFECOffset;
} SKP_SILK_SDK_DecControlStruct;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,89 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_ERRORS_H
#define SKP_SILK_ERRORS_H
#ifdef __cplusplus
extern "C"
{
#endif
/******************/
/* Error messages */
/******************/
#define SKP_SILK_NO_ERROR 0
/**************************/
/* Encoder error messages */
/**************************/
/* Input length is not a multiplum of 10 ms, or length is longer than the packet length */
#define SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -1
/* Sampling frequency not 8000, 12000, 16000 or 24000 Hertz */
#define SKP_SILK_ENC_FS_NOT_SUPPORTED -2
/* Packet size not 20, 40, 60, 80 or 100 ms */
#define SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -3
/* Allocated payload buffer too short */
#define SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT -4
/* Loss rate not between 0 and 100 percent */
#define SKP_SILK_ENC_INVALID_LOSS_RATE -5
/* Complexity setting not valid, use 0, 1 or 2 */
#define SKP_SILK_ENC_INVALID_COMPLEXITY_SETTING -6
/* Inband FEC setting not valid, use 0 or 1 */
#define SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING -7
/* DTX setting not valid, use 0 or 1 */
#define SKP_SILK_ENC_INVALID_DTX_SETTING -8
/* Internal encoder error */
#define SKP_SILK_ENC_INTERNAL_ERROR -9
/**************************/
/* Decoder error messages */
/**************************/
/* Output sampling frequency lower than internal decoded sampling frequency */
#define SKP_SILK_DEC_INVALID_SAMPLING_FREQUENCY -10
/* Payload size exceeded the maximum allowed 1024 bytes */
#define SKP_SILK_DEC_PAYLOAD_TOO_LARGE -11
/* Payload has bit errors */
#define SKP_SILK_DEC_PAYLOAD_ERROR -12
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,107 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef _SKP_SILK_API_TYPDEF_H_
#define _SKP_SILK_API_TYPDEF_H_
#ifndef SKP_USE_DOUBLE_PRECISION_FLOATS
#define SKP_USE_DOUBLE_PRECISION_FLOATS 0
#endif
#include <float.h>
#if defined( __GNUC__ )
#include <stdint.h>
#endif
#define SKP_int int /* used for counters etc; at least 16 bits */
#ifdef __GNUC__
# define SKP_int64 int64_t
#else
# define SKP_int64 long long
#endif
#define SKP_int32 int
#define SKP_int16 short
#define SKP_int8 signed char
#define SKP_uint unsigned int /* used for counters etc; at least 16 bits */
#ifdef __GNUC__
# define SKP_uint64 uint64_t
#else
# define SKP_uint64 unsigned long long
#endif
#define SKP_uint32 unsigned int
#define SKP_uint16 unsigned short
#define SKP_uint8 unsigned char
#define SKP_int_ptr_size intptr_t
#if SKP_USE_DOUBLE_PRECISION_FLOATS
# define SKP_float double
# define SKP_float_MAX DBL_MAX
#else
# define SKP_float float
# define SKP_float_MAX FLT_MAX
#endif
#define SKP_INLINE static __inline
#ifdef _WIN32
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
#else
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
#endif
#define SKP_int64_MAX ((SKP_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */
#define SKP_int64_MIN ((SKP_int64)0x8000000000000000LL) /* -2^63 */
#define SKP_int32_MAX 0x7FFFFFFF /* 2^31 - 1 = 2147483647*/
#define SKP_int32_MIN ((SKP_int32)0x80000000) /* -2^31 = -2147483648*/
#define SKP_int16_MAX 0x7FFF /* 2^15 - 1 = 32767*/
#define SKP_int16_MIN ((SKP_int16)0x8000) /* -2^15 = -32768*/
#define SKP_int8_MAX 0x7F /* 2^7 - 1 = 127*/
#define SKP_int8_MIN ((SKP_int8)0x80) /* -2^7 = -128*/
#define SKP_uint32_MAX 0xFFFFFFFF /* 2^32 - 1 = 4294967295 */
#define SKP_uint32_MIN 0x00000000
#define SKP_uint16_MAX 0xFFFF /* 2^16 - 1 = 65535 */
#define SKP_uint16_MIN 0x0000
#define SKP_uint8_MAX 0xFF /* 2^8 - 1 = 255 */
#define SKP_uint8_MIN 0x00
#define SKP_TRUE 1
#define SKP_FALSE 0
/* assertions */
#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS))
# ifndef SKP_assert
# include <crtdbg.h> /* ASSERTE() */
# define SKP_assert(COND) _ASSERTE(COND)
# endif
#else
# define SKP_assert(COND)
#endif
#endif

View File

@ -0,0 +1,20 @@
#ifndef UNTITLED_CQCODE_H
#define UNTITLED_CQCODE_H
#include <string>
#include <unordered_map>
#include <vector>
#include <exception>
class illegal_code: std::exception {
public:
[[nodiscard]] const char * what() const noexcept override {
return "Error cq code.";
}
};
void decode_cqcode(const std::string& code, std::vector<std::unordered_map<std::string, std::string>>& dest);
void encode_cqcode(const std::vector<std::unordered_map<std::string, std::string>>& segment, std::string& dest);
#endif //UNTITLED_CQCODE_H

View File

@ -0,0 +1,52 @@
#ifndef MD5_H
#define MD5_H
#include <string>
#include <fstream>
/* Type define */
using byte = std::byte;
typedef unsigned int uint32;
using std::string;
using std::ifstream;
/* MD5 declaration. */
class MD5 {
public:
MD5();
MD5(const void* input, size_t length);
MD5(const string& str);
MD5(ifstream& in);
void update(const void* input, size_t length);
void update(const string& str);
void update(ifstream& in);
const byte* digest();
string toString();
void reset();
private:
void update(const byte* input, size_t length);
void final();
void transform(const byte block[64]);
void encode(const uint32* input, byte* output, size_t length);
void decode(const byte* input, uint32* output, size_t length);
string bytesToHexString(const byte* input, size_t length);
/* class uncopyable */
MD5(const MD5&);
MD5& operator=(const MD5&);
private:
uint32 _state[4]; /* state (ABCD) */
uint32 _count[2]; /* number of bits, modulo 2^64 (low-order word first) */
byte _buffer[64]; /* input buffer */
byte _digest[16]; /* message digest */
bool _finished; /* calculate finished ? */
static const byte PADDING[64]; /* padding for calculate */
static const char HEX[16];
enum { BUFFER_SIZE = 1024 };
};
#endif /*MD5_H*/

344
app/src/main/cpp/md5.cpp Normal file
View File

@ -0,0 +1,344 @@
#include "md5.h"
using namespace std;
/* Constants for MD5Transform routine. */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + ac; \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
const std::byte MD5::PADDING[64] = { (byte) 0x80 };
const char MD5::HEX[16] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f'
};
/* Default construct. */
MD5::MD5() {
reset();
}
/* Construct a MD5 object with a input buffer. */
MD5::MD5(const void* input, size_t length) {
reset();
update(input, length);
}
/* Construct a MD5 object with a string. */
MD5::MD5(const string& str) {
reset();
update(str);
}
/* Construct a MD5 object with a file. */
MD5::MD5(ifstream& in) {
reset();
update(in);
}
/* Return the message-digest */
const byte* MD5::digest() {
if (!_finished) {
_finished = true;
final();
}
return _digest;
}
/* Reset the calculate state */
void MD5::reset() {
_finished = false;
/* reset number of bits. */
_count[0] = _count[1] = 0;
/* Load magic initialization constants. */
_state[0] = 0x67452301;
_state[1] = 0xefcdab89;
_state[2] = 0x98badcfe;
_state[3] = 0x10325476;
}
/* Updating the context with a input buffer. */
void MD5::update(const void* input, size_t length) {
update((const byte*)input, length);
}
/* Updating the context with a string. */
void MD5::update(const string& str) {
update((const byte*)str.c_str(), str.length());
}
/* Updating the context with a file. */
void MD5::update(ifstream& in) {
if (!in) {
return;
}
std::streamsize length;
char buffer[BUFFER_SIZE];
while (!in.eof()) {
in.read(buffer, BUFFER_SIZE);
length = in.gcount();
if (length > 0) {
update(buffer, length);
}
}
in.close();
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5::update(const byte* input, size_t length) {
uint32 i, index, partLen;
_finished = false;
/* Compute number of bytes mod 64 */
index = (uint32)((_count[0] >> 3) & 0x3f);
/* update number of bits */
if ((_count[0] += ((uint32)length << 3)) < ((uint32)length << 3)) {
++_count[1];
}
_count[1] += ((uint32)length >> 29);
partLen = 64 - index;
/* transform as many times as possible. */
if (length >= partLen) {
memcpy(&_buffer[index], input, partLen);
transform(_buffer);
for (i = partLen; i + 63 < length; i += 64) {
transform(&input[i]);
}
index = 0;
} else {
i = 0;
}
/* Buffer remaining input */
memcpy(&_buffer[index], &input[i], length - i);
}
/* MD5 finalization. Ends an MD5 message-_digest operation, writing the
the message _digest and zeroizing the context.
*/
void MD5::final() {
byte bits[8];
uint32 oldState[4];
uint32 oldCount[2];
uint32 index, padLen;
/* Save current state and count. */
memcpy(oldState, _state, 16);
memcpy(oldCount, _count, 8);
/* Save number of bits */
encode(_count, bits, 8);
/* Pad out to 56 mod 64. */
index = (uint32)((_count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
update(PADDING, padLen);
/* Append length (before padding) */
update(bits, 8);
/* Store state in digest */
encode(_state, _digest, 16);
/* Restore current state and count. */
memcpy(_state, oldState, 16);
memcpy(_count, oldCount, 8);
}
/* MD5 basic transformation. Transforms _state based on block. */
void MD5::transform(const byte block[64]) {
uint32 a = _state[0], b = _state[1], c = _state[2], d = _state[3], x[16];
decode(block, x, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
_state[0] += a;
_state[1] += b;
_state[2] += c;
_state[3] += d;
}
/* Encodes input (ulong) into output (byte). Assumes length is
a multiple of 4.
*/
void MD5::encode(const uint32* input, byte* output, size_t length) {
for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
output[j]= (byte)(input[i] & 0xff);
output[j + 1] = (byte)((input[i] >> 8) & 0xff);
output[j + 2] = (byte)((input[i] >> 16) & 0xff);
output[j + 3] = (byte)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (byte) into output (ulong). Assumes length is
a multiple of 4.
*/
void MD5::decode(const byte* input, uint32* output, size_t length) {
for (size_t i = 0, j = 0; j < length; ++i, j += 4) {
output[i] = ((uint32)input[j]) | (((uint32)input[j + 1]) << 8) |
(((uint32)input[j + 2]) << 16) | (((uint32)input[j + 3]) << 24);
}
}
/* Convert byte array to hex string. */
string MD5::bytesToHexString(const byte* input, size_t length) {
string str;
str.reserve(length << 1);
for (size_t i = 0; i < length; ++i) {
int t = (int) input[i];
int a = t / 16;
int b = t % 16;
str.append(1, HEX[a]);
str.append(1, HEX[b]);
}
return str;
}
/* Convert digest to string value */
string MD5::toString() {
return bytesToHexString(digest(), 16);
}

View File

@ -0,0 +1,157 @@
#include "jni.h"
#include "cqcode.h"
#include <random>
inline void replace_string(std::string& str, const std::string& from, const std::string& to) {
size_t startPos = 0;
while ((startPos = str.find(from, startPos)) != std::string::npos) {
str.replace(startPos, from.length(), to);
startPos += to.length();
}
}
extern "C"
JNIEXPORT jlong JNICALL
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_createMessageUniseq(JNIEnv *env, jobject thiz,
jint chat_type,
jlong time) {
static std::random_device rd;
static std::mt19937 generator(rd());
static std::uniform_int_distribution<int> distribution(INT32_MIN, INT32_MAX);
int64_t uniseq = (time / 1000) << (8 * 4);
auto msgtype = (int64_t) chat_type;
int64_t random = abs(distribution(generator)) & 0xffffff00L;
return uniseq | random | msgtype;
}
extern "C"
JNIEXPORT jint JNICALL
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_getChatType(JNIEnv *env, jobject thiz,
jlong msg_id) {
return (int32_t) ((int64_t) msg_id & 0xffL);
}
extern "C"
JNIEXPORT jobject JNICALL
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_nativeDecodeCQCode(JNIEnv *env, jobject thiz,
jstring code) {
jclass ArrayList = env->FindClass("java/util/ArrayList");
jmethodID NewArrayList = env->GetMethodID(ArrayList, "<init>", "()V");
jmethodID ArrayListAdd = env->GetMethodID(ArrayList, "add", "(Ljava/lang/Object;)Z");
jobject arrayList = env->NewObject(ArrayList, NewArrayList);
const char* cCode = env->GetStringUTFChars(code, nullptr);
std::string cppCode = cCode;
std::vector<std::unordered_map<std::string, std::string>> dest;
try {
decode_cqcode(cppCode, dest);
} catch (illegal_code& code) {
return arrayList;
}
jclass HashMap = env->FindClass("java/util/HashMap");
jmethodID NewHashMap = env->GetMethodID(HashMap, "<init>", "()V");
jclass String = env->FindClass("java/lang/String");
jmethodID NewString = env->GetMethodID(String, "<init>", "([BLjava/lang/String;)V");
jstring charset = env->NewStringUTF("UTF-8");
jmethodID put = env->GetMethodID(HashMap, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (auto& map : dest) {
jobject hashMap = env->NewObject(HashMap, NewHashMap);
for (const auto& pair : map) {
jbyteArray keyArray = env->NewByteArray((int) pair.first.size());
jbyteArray valueArray = env->NewByteArray((int) pair.second.size());
env->SetByteArrayRegion(keyArray, 0, (int) pair.first.size(), (jbyte*)pair.first.c_str());
env->SetByteArrayRegion(valueArray, 0, (int) pair.second.size(), (jbyte*)pair.second.c_str());
auto key = (jstring) env->NewObject(String, NewString, keyArray, charset);
auto value = (jstring) env->NewObject(String, NewString, valueArray, charset);
env->CallObjectMethod(hashMap, put, key, value);
}
env->CallBooleanMethod(arrayList, ArrayListAdd, hashMap);
}
env->DeleteLocalRef(ArrayList);
env->DeleteLocalRef(HashMap);
env->DeleteLocalRef(String);
env->DeleteLocalRef(charset);
env->ReleaseStringUTFChars(code, cCode);
return arrayList;
}
extern "C"
JNIEXPORT jstring JNICALL
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_nativeEncodeCQCode(JNIEnv *env, jobject thiz,
jobject segment_list) {
jclass List = env->FindClass("java/util/List");
jmethodID ListSize = env->GetMethodID(List, "size", "()I");
jmethodID ListGet = env->GetMethodID(List, "get", "(I)Ljava/lang/Object;");
jclass Map = env->FindClass("java/util/Map");
jmethodID MapGet = env->GetMethodID(Map, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
jmethodID entrySetMethod = env->GetMethodID(Map, "entrySet", "()Ljava/util/Set;");
jclass setClass = env->FindClass("java/util/Set");
jmethodID iteratorMethod = env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
jclass entryClass = env->FindClass("java/util/Map$Entry");
jmethodID getKeyMethod = env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
jmethodID getValueMethod = env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
std::string result;
jint size = env->CallIntMethod(segment_list, ListSize);
for (int i = 0; i < size; i++ ) {
jobject segment = env->CallObjectMethod(segment_list, ListGet, i);
jobject entrySet = env->CallObjectMethod(segment, entrySetMethod);
jobject iterator = env->CallObjectMethod(entrySet, iteratorMethod);
auto type = (jstring) env->CallObjectMethod(segment, MapGet, env->NewStringUTF("_type"));
auto typeString = env->GetStringUTFChars(type, nullptr);
if (strcmp(typeString, "text") == 0) {
auto text = (jstring) env->CallObjectMethod(segment, MapGet, env->NewStringUTF("text"));
auto textString = env->GetStringUTFChars(text, nullptr);
std::string tmpValue = textString;
replace_string(tmpValue, "&", "&amp;");
replace_string(tmpValue, "[", "&#91;");
replace_string(tmpValue, "]", "&#93;");
replace_string(tmpValue, ",", "&#44;");
result.append(tmpValue);
env->ReleaseStringUTFChars(text, textString);
} else {
result.append("[CQ:");
result.append(typeString);
while (env->CallBooleanMethod(iterator, env->GetMethodID(env->GetObjectClass(iterator), "hasNext", "()Z"))) {
jobject entry = env->CallObjectMethod(iterator, env->GetMethodID(env->GetObjectClass(iterator), "next", "()Ljava/lang/Object;"));
auto key = (jstring) env->CallObjectMethod(entry, getKeyMethod);
auto value = (jstring) env->CallObjectMethod(entry, getValueMethod);
auto keyString = env->GetStringUTFChars(key, nullptr);
auto valueString = env->GetStringUTFChars(value, nullptr);
if (strcmp(keyString, "_type") != 0) {
std::string tmpValue = valueString;
replace_string(tmpValue, "&", "&amp;");
replace_string(tmpValue, "[", "&#91;");
replace_string(tmpValue, "]", "&#93;");
replace_string(tmpValue, ",", "&#44;");
result.append(",").append(keyString).append("=").append(tmpValue);
}
env->ReleaseStringUTFChars(key, keyString);
env->ReleaseStringUTFChars(value, valueString);
env->DeleteLocalRef(entry);
env->DeleteLocalRef(key);
env->DeleteLocalRef(value);
}
result.append("]");
}
env->ReleaseStringUTFChars(type, typeString);
}
env->DeleteLocalRef(List);
env->DeleteLocalRef(Map);
env->DeleteLocalRef(setClass);
env->DeleteLocalRef(entryClass);
return env->NewStringUTF(result.c_str());
}
extern "C"
JNIEXPORT jlong JNICALL
Java_moe_fuqiuluo_shamrock_helper_MessageHelper_insertChatTypeToMsgId(JNIEnv *env, jobject thiz,
jlong msg_id, jint chat_type) {
return (msg_id & 0xffffffffffffff00L) | chat_type;
}

View File

@ -0,0 +1,54 @@
#include <jni.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <filesystem>
#include <random>
#include <android/log.h>
#include <sys/time.h>
#include "md5.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_moe_fuqiuluo_shamrock_xposed_actions_PullConfig_testNativeLibrary(JNIEnv *env, jobject thiz) {
return env->NewStringUTF("加载Shamrock库成功~");
}
extern "C"
JNIEXPORT jstring JNICALL
Java_moe_fuqiuluo_shamrock_utils_MD5_genFileMd5Hex(JNIEnv *env, jobject thiz, jstring file_path) {
auto cPathStr = env->GetStringUTFChars(file_path, nullptr);
std::filesystem::path filePath(cPathStr);
if (!std::filesystem::exists(filePath)) {
jclass exClass = env->FindClass("java/io/FileNotFoundException");
env->ThrowNew(exClass, "目标文件不存在");
env->DeleteLocalRef(exClass);
return nullptr;
}
auto file = std::ifstream(filePath.c_str(), std::ios::binary);
MD5 md5;
md5.update(file);
auto md5Hex = md5.toString();
env->ReleaseStringUTFChars(file_path, cPathStr);
return env->NewStringUTF(md5Hex.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_moe_fuqiuluo_shamrock_utils_MD5_getMd5Hex(JNIEnv *env, jobject thiz, jbyteArray bytes) {
auto len = env->GetArrayLength(bytes);
auto *cBytes = new unsigned char[len];
env->GetByteArrayRegion(bytes, 0, len, reinterpret_cast<jbyte *>(cBytes));
MD5 md5;
md5.update(cBytes, len);
auto md5Hex = md5.toString();
delete[] cBytes;
return env->NewStringUTF(md5Hex.c_str());
}

591
app/src/main/cpp/silk.cpp Normal file
View File

@ -0,0 +1,591 @@
#include <jni.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <random>
#include <android/log.h>
#include <sys/time.h>
#include "SKP_Silk_SDK_API.h"
#include "SKP_Silk_SigProc_FIX.h"
/* Define codec specific settings */
#define MAX_BYTES_PER_FRAME_ENC 250 // Equals peak bitrate of 100 kbps
#define MAX_INPUT_FRAMES 5
#define FRAME_LENGTH_MS 20
#define MAX_API_FS_KHZ 48
/* Define codec specific settings should be moved to h file */
#define MAX_BYTES_PER_FRAME_DEC 1024
#define MAX_INPUT_FRAMES 5
#define MAX_FRAME_LENGTH 480
#define FRAME_LENGTH_MS 20
#define MAX_API_FS_KHZ 48
#define MAX_LBRR_DELAY 2
#ifdef _SYSTEM_IS_BIG_ENDIAN
/* Function to convert a little endian int16 to a */
/* big endian int16 or vica verca */
void swap_endian(
SKP_int16 vec[],
SKP_int len
)
{
SKP_int i;
SKP_int16 tmp;
SKP_uint8 *p1, *p2;
for( i = 0; i < len; i++ ){
tmp = vec[ i ];
p1 = (SKP_uint8 *)&vec[ i ]; p2 = (SKP_uint8 *)&tmp;
p1[ 0 ] = p2[ 1 ]; p1[ 1 ] = p2[ 0 ];
}
}
#endif
#if (defined(_WIN32) || defined(_WINCE))
#include <windows.h> /* timer */
#else // Linux or Mac
#include <sys/time.h>
#endif
#ifdef _WIN32
unsigned long GetHighResolutionTime() /* O: time in usec*/
{
/* Returns a time counter in microsec */
/* the resolution is platform dependent */
/* but is typically 1.62 us resolution */
LARGE_INTEGER lpPerformanceCount;
LARGE_INTEGER lpFrequency;
QueryPerformanceCounter(&lpPerformanceCount);
QueryPerformanceFrequency(&lpFrequency);
return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart);
}
#else // Linux or Mac
unsigned long GetHighResolutionTime() /* O: time in usec*/
{
struct timeval tv;
gettimeofday(&tv, 0);
return((tv.tv_sec*1000000)+(tv.tv_usec));
}
#endif // _WIN32
/* Seed for the random number generator, which is used for simulating packet loss */
static SKP_int32 rand_seed = 1;
int silk_encode(int rate, char type, const char* inputFile, const char* outPutFile);
extern "C"
JNIEXPORT jint JNICALL
Java_moe_fuqiuluo_shamrock_utils_AudioUtils_pcmToSilk(JNIEnv *env, jobject thiz,
jint rate,
jbyte type,
jstring pcm_file,
jstring silk_file) {
auto pcm = env->GetStringUTFChars(pcm_file, nullptr);
auto silk = env->GetStringUTFChars(silk_file, nullptr);
return silk_encode(rate, type, pcm, silk);
}
int silk_encode(int rate, char type, const char* inputFile, const char* outPutFile) {
double filetime;
size_t counter;
SKP_int32 k, totPackets, totActPackets, ret;
SKP_int16 nBytes;
double sumBytes, sumActBytes, nrg;
SKP_uint8 payload[ MAX_BYTES_PER_FRAME_ENC * MAX_INPUT_FRAMES ];
SKP_int16 in[ FRAME_LENGTH_MS * MAX_API_FS_KHZ * MAX_INPUT_FRAMES ];
char speechInFileName[ 150 ], bitOutFileName[ 150 ];
FILE *bitOutFile, *speechInFile;
SKP_int32 encSizeBytes;
void *psEnc;
#ifdef _SYSTEM_IS_BIG_ENDIAN
SKP_int16 nBytes_LE;
#endif
/* default settings */
SKP_int32 API_fs_Hz = rate;
SKP_int32 max_internal_fs_Hz;
SKP_int32 targetRate_bps = 25000;
SKP_int32 smplsSinceLastPacket, packetSize_ms = 20;
SKP_int32 frameSizeReadFromFile_ms = 20;
SKP_int32 packetLoss_perc = 0;
#if LOW_COMPLEXITY_ONLY
SKP_int32 complexity_mode = 0;
#else
SKP_int32 complexity_mode = 2;
#endif
SKP_int32 DTX_enabled = 0, INBandFEC_enabled = 0;
SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
SKP_SILK_SDK_EncControlStruct encStatus; // Struct for status of encoder
/* get arguments */
strcpy( speechInFileName, inputFile );
strcpy( bitOutFileName, outPutFile );
/* If no max internal is specified, set to minimum of API fs and 24 kHz */
max_internal_fs_Hz = rate;
/* Open files */
speechInFile = fopen( speechInFileName, "rb" );
if( speechInFile == nullptr ) {
return -1;
}
bitOutFile = fopen( bitOutFileName, "wb" );
if( bitOutFile == nullptr ) {
return -2;
}
/* Add Silk header to stream */
{
char Tencent_break[1];
Tencent_break[0] = type;
fwrite( Tencent_break, sizeof( char ), 1, bitOutFile );
static const char Silk_header[] = "#!SILK_V3";
fwrite( Silk_header, sizeof( char ), strlen( Silk_header ), bitOutFile );
}
/* Create Encoder */
ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
if( ret ) {
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: SKP_Silk_create_encoder returned %d", ret );
return -3;
}
psEnc = malloc( encSizeBytes );
/* Reset Encoder */
ret = SKP_Silk_SDK_InitEncoder( psEnc, &encStatus );
if( ret ) {
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: SKP_Silk_reset_encoder returned %d", ret );
return -4;
}
/* Set Encoder parameters */
encControl.API_sampleRate = API_fs_Hz;
encControl.maxInternalSampleRate = max_internal_fs_Hz;
encControl.packetSize = ( packetSize_ms * API_fs_Hz ) / 1000;
encControl.packetLossPercentage = packetLoss_perc;
encControl.useInBandFEC = INBandFEC_enabled;
encControl.useDTX = DTX_enabled;
encControl.complexity = complexity_mode;
encControl.bitRate = targetRate_bps;
totPackets = 0;
totActPackets = 0;
smplsSinceLastPacket = 0;
sumBytes = 0.0;
sumActBytes = 0.0;
smplsSinceLastPacket = 0;
while( true ) {
/* Read input from file */
counter = fread( in, sizeof( SKP_int16 ), ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000, speechInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( in, counter );
#endif
if( ( SKP_int )counter < ( ( frameSizeReadFromFile_ms * API_fs_Hz ) / 1000 ) ) {
break;
}
/* max payload size */
nBytes = MAX_BYTES_PER_FRAME_ENC * MAX_INPUT_FRAMES;
/* Silk Encoder */
ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)counter, payload, &nBytes );
if( ret ) {
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "SKP_Silk_Encode returned %d", ret );
}
/* Get packet size */
packetSize_ms = ( SKP_int )( ( 1000 * ( SKP_int32 )encControl.packetSize ) / encControl.API_sampleRate );
smplsSinceLastPacket += ( SKP_int )counter;
if( ( ( 1000 * smplsSinceLastPacket ) / API_fs_Hz ) == packetSize_ms ) {
/* Sends a dummy zero size packet in case of DTX period */
/* to make it work with the decoder test program. */
/* In practice should be handled by RTP sequence numbers */
totPackets++;
sumBytes += nBytes;
nrg = 0.0;
for( k = 0; k < ( SKP_int )counter; k++ ) {
nrg += in[ k ] * (double)in[ k ];
}
if( ( nrg / ( SKP_int )counter ) > 1e3 ) {
sumActBytes += nBytes;
totActPackets++;
}
/* Write payload size */
#ifdef _SYSTEM_IS_BIG_ENDIAN
nBytes_LE = nBytes;
swap_endian( &nBytes_LE, 1 );
fwrite( &nBytes_LE, sizeof( SKP_int16 ), 1, bitOutFile );
#else
fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );
#endif
/* Write payload */
fwrite( payload, sizeof( SKP_uint8 ), nBytes, bitOutFile );
smplsSinceLastPacket = 0;
//fprintf(stderr, "\rPackets encoded: %d", totPackets);
}
}
/* Write dummy because it can not end with 0 bytes */
nBytes = -1;
/* Write payload size */
fwrite( &nBytes, sizeof( SKP_int16 ), 1, bitOutFile );
/* Free Encoder */
free( psEnc );
fclose( speechInFile );
fclose( bitOutFile );
filetime = totPackets * 1e-3 * packetSize_ms;
return (int) filetime;
}
extern "C"
JNIEXPORT jint JNICALL
Java_moe_fuqiuluo_shamrock_utils_AudioUtils_silkToPcm(JNIEnv *env, jobject thiz, jint rate, jbyte type,
jstring pcm_file, jstring silk_file) {
auto pcm = env->GetStringUTFChars(pcm_file, nullptr);
auto silk = env->GetStringUTFChars(silk_file, nullptr);
unsigned long tottime, starttime;
size_t counter;
SKP_int32 totPackets, i, k, ret, tot_len;
SKP_int16 len;
SKP_int16 nBytes;
SKP_uint8 payload[ MAX_BYTES_PER_FRAME_DEC * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
SKP_uint8 *payloadEnd, *payloadToDec = nullptr;
SKP_uint8 FECpayload[ MAX_BYTES_PER_FRAME_DEC * MAX_INPUT_FRAMES ], *payloadPtr;
SKP_int16 nBytesFEC;
SKP_int16 nBytesPerPacket[ MAX_LBRR_DELAY + 1 ], totBytes;
SKP_int16 out[ ( ( FRAME_LENGTH_MS * MAX_API_FS_KHZ ) << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
char speechOutFileName[ 150 ], bitInFileName[ 150 ];
FILE *bitInFile, *speechOutFile;
SKP_int32 API_Fs_Hz = rate;
SKP_int32 decSizeBytes;
void *psDec;
SKP_float loss_prob;
SKP_int32 frames, lost;
SKP_SILK_SDK_DecControlStruct DecControl;
/* default settings */
loss_prob = 0.0f;
strcpy( bitInFileName, silk);
strcpy( speechOutFileName, pcm);
/* Open files */
bitInFile = fopen( bitInFileName, "rb" );
if( bitInFile == nullptr ) {
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: could not open input file %s", bitInFileName );
return -1;
}
/* Check Silk header */
{
char header_buf[ 50 ];
fread(header_buf, sizeof(char), 1, bitInFile);
header_buf[ strlen( "" ) ] = '\0'; /* Terminate with a null character */
if( strcmp( header_buf, "" ) != 0 ) {
counter = fread( header_buf, sizeof( char ), strlen( "!SILK_V3" ), bitInFile );
header_buf[ strlen( "!SILK_V3" ) ] = '\0'; /* Terminate with a null character */
if( strcmp( header_buf, "!SILK_V3" ) != 0 ) {
/* Non-equal strings */
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: Wrong Header %s", header_buf );
return -2;
}
} else {
counter = fread( header_buf, sizeof( char ), strlen( "#!SILK_V3" ), bitInFile );
header_buf[ strlen( "#!SILK_V3" ) ] = '\0'; /* Terminate with a null character */
if( strcmp( header_buf, "#!SILK_V3" ) != 0 ) {
/* Non-equal strings */
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: Wrong Header %s", header_buf );
return -3;
}
}
}
speechOutFile = fopen( speechOutFileName, "wb" );
if( speechOutFile == nullptr ) {
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Error: could not open output file %s", speechOutFileName );
return -4;
}
/* Set the samplingrate that is requested for the output */
if( API_Fs_Hz == 0 ) {
DecControl.API_sampleRate = 24000;
} else {
DecControl.API_sampleRate = API_Fs_Hz;
}
/* Initialize to one frame per packet, for proper concealment before first packet arrives */
DecControl.framesPerPacket = 1;
/* Create decoder */
ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
}
psDec = malloc( decSizeBytes );
/* Reset decoder */
ret = SKP_Silk_SDK_InitDecoder( psDec );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_InitDecoder returned %d", ret );
}
totPackets = 0;
tottime = 0;
payloadEnd = payload;
/* Simulate the jitter buffer holding MAX_FEC_DELAY packets */
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
nBytesPerPacket[ i ] = nBytes;
payloadEnd += nBytes;
totPackets++;
}
while( 1 ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
if( nBytes < 0 || counter < 1 ) {
break;
}
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
/* Simulate losses */
rand_seed = SKP_RAND( rand_seed );
if( ( ( ( float )( ( rand_seed >> 16 ) + ( 1 << 15 ) ) ) / 65535.0f >= ( loss_prob / 100.0f ) ) && ( counter > 0 ) ) {
nBytesPerPacket[ MAX_LBRR_DELAY ] = nBytes;
payloadEnd += nBytes;
} else {
nBytesPerPacket[ MAX_LBRR_DELAY ] = 0;
}
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
starttime = GetHighResolutionTime();
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], ( i + 1 ), FECpayload, &nBytesFEC );
tottime += GetHighResolutionTime() - starttime;
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
starttime = GetHighResolutionTime();
if( lost == 0 ) {
/* No Loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
} while( DecControl.moreInternalDecoderFrames );
} else {
/* Loss: Decode enough frames to cover one packet duration */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
/* Generate 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
tottime += GetHighResolutionTime() - starttime;
totPackets++;
/* Write output to file */
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
/* Check if the received totBytes is valid */
if (totBytes < 0 || totBytes > sizeof(payload))
{
__android_log_print(ANDROID_LOG_ERROR, "silk.cpp", "Packets decoded: %d", totPackets );
return -1;
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
}
/* Empty the recieve buffer */
for( k = 0; k < MAX_LBRR_DELAY; k++ ) {
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
starttime = GetHighResolutionTime();
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], ( i + 1 ), FECpayload, &nBytesFEC );
tottime += GetHighResolutionTime() - starttime;
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
starttime = GetHighResolutionTime();
if( lost == 0 ) {
/* No loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
} while( DecControl.moreInternalDecoderFrames );
} else {
/* Loss: Decode enough frames to cover one packet duration */
/* Generate 20 ms */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
__android_log_print(ANDROID_LOG_DEBUG, "silk.cpp", "SKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
tottime += GetHighResolutionTime() - starttime;
totPackets++;
/* Write output to file */
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update Buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
/* Check if the received totBytes is valid */
if (totBytes < 0 || totBytes > sizeof(payload))
{
fprintf( stderr, "\rPackets decoded: %d", totPackets );
return -1;
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
}
/* Free decoder */
free( psDec );
/* Close files */
fclose( speechOutFile );
fclose( bitInFile );
return 0;
}

View File

@ -0,0 +1,287 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* Conversion between prediction filter coefficients and NLSFs */
/* Requires the order to be an even number */
/* A piecewise linear approximation maps LSF <-> cos(LSF) */
/* Therefore the result is not accurate NLSFs, but the two */
/* function are accurate inverses of each other */
#include "SKP_Silk_SigProc_FIX.h"
/* Number of binary divisions */
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
#define QPoly 16
#define MAX_ITERATIONS_A2NLSF_FIX 30
/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */
#define OVERSAMPLE_COSINE_TABLE 0
/* Helper function for A2NLSF(..) */
/* Transforms polynomials from cos(n*f) to cos(f)^n */
SKP_INLINE void SKP_Silk_A2NLSF_trans_poly(
SKP_int32 *p, /* I/O Polynomial */
const SKP_int dd /* I Polynomial order (= filter order / 2 ) */
)
{
SKP_int k, n;
for( k = 2; k <= dd; k++ ) {
for( n = dd; n > k; n-- ) {
p[ n - 2 ] -= p[ n ];
}
p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 );
}
}
#if EMBEDDED_ARM<6
/* Helper function for A2NLSF(..) */
/* Polynomial evaluation */
SKP_INLINE SKP_int32 SKP_Silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */
SKP_int32 *p, /* I Polynomial, QPoly */
const SKP_int32 x, /* I Evaluation point, Q12 */
const SKP_int dd /* I Order */
)
{
SKP_int n;
SKP_int32 x_Q16, y32;
y32 = p[ dd ]; /* QPoly */
x_Q16 = SKP_LSHIFT( x, 4 );
for( n = dd - 1; n >= 0; n-- ) {
y32 = SKP_SMLAWW( p[ n ], y32, x_Q16 ); /* QPoly */
}
return y32;
}
#else
SKP_int32 SKP_Silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */
SKP_int32 *p, /* I Polynomial, QPoly */
const SKP_int32 x, /* I Evaluation point, Q12 */
const SKP_int dd /* I Order */
);
#endif
SKP_INLINE void SKP_Silk_A2NLSF_init(
const SKP_int32 *a_Q16,
SKP_int32 *P,
SKP_int32 *Q,
const SKP_int dd
)
{
SKP_int k;
/* Convert filter coefs to even and odd polynomials */
P[dd] = SKP_LSHIFT( 1, QPoly );
Q[dd] = SKP_LSHIFT( 1, QPoly );
for( k = 0; k < dd; k++ ) {
#if( QPoly < 16 )
P[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
Q[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
#elif( QPoly == 16 )
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; // QPoly
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; // QPoly
#else
P[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
Q[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
#endif
}
/* Divide out zeros as we have that for even filter orders, */
/* z = 1 is always a root in Q, and */
/* z = -1 is always a root in P */
for( k = dd; k > 0; k-- ) {
P[ k - 1 ] -= P[ k ];
Q[ k - 1 ] += Q[ k ];
}
/* Transform polynomials from cos(n*f) to cos(f)^n */
SKP_Silk_A2NLSF_trans_poly( P, dd );
SKP_Silk_A2NLSF_trans_poly( Q, dd );
}
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
void SKP_Silk_A2NLSF(
SKP_int *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */
SKP_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
const SKP_int d /* I Filter order (must be even) */
)
{
SKP_int i, k, m, dd, root_ix, ffrac;
SKP_int32 xlo, xhi, xmid;
SKP_int32 ylo, yhi, ymid;
SKP_int32 nom, den;
SKP_int32 P[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
SKP_int32 Q[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
SKP_int32 *PQ[ 2 ];
SKP_int32 *p;
/* Store pointers to array */
PQ[ 0 ] = P;
PQ[ 1 ] = Q;
dd = SKP_RSHIFT( d, 1 );
SKP_Silk_A2NLSF_init( a_Q16, P, Q, dd );
/* Find roots, alternating between P and Q */
p = P; /* Pointer to polynomial */
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
if( ylo < 0 ) {
/* Set the first NLSF to zero and move on to the next */
NLSF[ 0 ] = 0;
p = Q; /* Pointer to polynomial */
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
root_ix = 1; /* Index of current root */
} else {
root_ix = 0; /* Index of current root */
}
k = 1; /* Loop counter */
i = 0; /* Counter for bandwidth expansions applied */
while( 1 ) {
/* Evaluate polynomial */
#if OVERSAMPLE_COSINE_TABLE
xhi = SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] +
( ( SKP_Silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] -
SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] ) >> 1 ); /* Q12 */
#else
xhi = SKP_Silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
#endif
yhi = SKP_Silk_A2NLSF_eval_poly( p, xhi, dd );
/* Detect zero crossing */
if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) {
/* Binary division */
#if OVERSAMPLE_COSINE_TABLE
ffrac = -128;
#else
ffrac = -256;
#endif
for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
/* Evaluate polynomial */
xmid = SKP_RSHIFT_ROUND( xlo + xhi, 1 );
ymid = SKP_Silk_A2NLSF_eval_poly( p, xmid, dd );
/* Detect zero crossing */
if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
/* Reduce frequency */
xhi = xmid;
yhi = ymid;
} else {
/* Increase frequency */
xlo = xmid;
ylo = ymid;
#if OVERSAMPLE_COSINE_TABLE
ffrac = SKP_ADD_RSHIFT( ffrac, 64, m );
#else
ffrac = SKP_ADD_RSHIFT( ffrac, 128, m );
#endif
}
}
/* Interpolate */
if( SKP_abs( ylo ) < 65536 ) {
/* Avoid dividing by zero */
den = ylo - yhi;
nom = SKP_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + SKP_RSHIFT( den, 1 );
if( den != 0 ) {
ffrac += SKP_DIV32( nom, den );
}
} else {
/* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
ffrac += SKP_DIV32( ylo, SKP_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
}
#if OVERSAMPLE_COSINE_TABLE
NLSF[ root_ix ] = (SKP_int)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 7 ) + ffrac, SKP_int16_MAX );
#else
NLSF[ root_ix ] = (SKP_int)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 8 ) + ffrac, SKP_int16_MAX );
#endif
SKP_assert( NLSF[ root_ix ] >= 0 );
SKP_assert( NLSF[ root_ix ] <= 32767 );
root_ix++; /* Next root */
if( root_ix >= d ) {
/* Found all roots */
break;
}
/* Alternate pointer to polynomial */
p = PQ[ root_ix & 1 ];
/* Evaluate polynomial */
#if OVERSAMPLE_COSINE_TABLE
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] +
( ( SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] -
SKP_Silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); // Q12
#else
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ k - 1 ]; // Q12
#endif
ylo = SKP_LSHIFT( 1 - ( root_ix & 2 ), 12 );
} else {
/* Increment loop counter */
k++;
xlo = xhi;
ylo = yhi;
#if OVERSAMPLE_COSINE_TABLE
if( k > 2 * LSF_COS_TAB_SZ_FIX ) {
#else
if( k > LSF_COS_TAB_SZ_FIX ) {
#endif
i++;
if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
/* Set NLSFs to white spectrum and exit */
NLSF[ 0 ] = SKP_DIV32_16( 1 << 15, d + 1 );
for( k = 1; k < d; k++ ) {
NLSF[ k ] = SKP_SMULBB( k + 1, NLSF[ 0 ] );
}
return;
}
/* Error: Apply progressively more bandwidth expansion and run again */
SKP_Silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015
SKP_Silk_A2NLSF_init( a_Q16, P, Q, dd );
p = P; /* Pointer to polynomial */
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
if( ylo < 0 ) {
/* Set the first NLSF to zero and move on to the next */
NLSF[ 0 ] = 0;
p = Q; /* Pointer to polynomial */
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
root_ix = 1; /* Index of current root */
} else {
root_ix = 0; /* Index of current root */
}
k = 1; /* Reset loop counter */
}
}
}
}

View File

@ -0,0 +1,85 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if defined(__arm__)
#include "SKP_Silk_AsmPreproc.h"
#if EMBEDDED_ARM>=6
VARDEF y32, r3
VARDEF pn1, r4
VARDEF pn2, r5
VARDEF lo, r6
VARDEF hi, r8
.globl SYM(SKP_Silk_A2NLSF_eval_poly)
SYM(SKP_Silk_A2NLSF_eval_poly):
stmdb sp!, {r4-r8, fp, ip, lr}
add fp, sp, #28
add r0, r0, r2, lsl #2
ldr y32, [r0], #-4
tst r2, #1
beq LR(1, f)
ldr pn1, [r0], #-4
sub r2, r2, #1
mov r1, r1, lsl #4
L(0)
smull lo, hi, y32, r1
subs r2, r2, #1
add y32, pn1, hi, lsl #16
ldr pn1, [r0], #-4
add y32, y32, lo, lsr #16
bgt LR(0, b)
smull lo, hi, y32, r1
add y32, pn1, hi, lsl #16
add r0, y32, lo, lsr #16
ldmia sp!, {r4-r8, fp, ip, pc}
L(1)/*EVEN:*/
add r0, r0, #4
ldmdb r0!, {pn1, pn2}
sub r2, r2, #2
mov r1, r1, lsl #4
L(0)
smull lo, hi, y32, r1
subs r2, r2, #2
add y32, pn2, hi, lsl #16
add y32, y32, lo, lsr #16
smull lo, hi, y32, r1
add y32, pn1, hi, lsl #16
ldmdb r0!, {pn1, pn2}
add y32, y32, lo, lsr #16
bgt LR(0, b)
smull lo, hi, y32, r1
add y32, pn2, hi, lsl #16
add y32, y32, lo, lsr #16
smull lo, hi, y32, r1
add y32, pn1, hi, lsl #16
add r0, y32, lo, lsr #16
ldmia sp!, {r4-r8, fp, ip, pc}
END
#endif
#endif

View File

@ -0,0 +1,180 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*
* SKP_Silk_AsmHelper.h
*
*
*
*
*/
#ifndef _SKP_ASM_HELPER_H_
#define _SKP_ASM_HELPER_H_
// Register bank
#define _REG 0
#define _DREG 1
// Arg registers
#define _R0 0
#define _R1 1
#define _R2 2
#define _R3 3
#define _R4 4
// GP registers
#define _R5 5
#define _R6 6
#define _R7 7
#define _R8 8
#define _SB 9
#define _SL 10
// fp and ip registers
#define _FP 11
#define _IP 12
// lr and sp registers
#define _SP 13
#define _LR 14
// Extension register bank
#define _numDReg
#define _Q0 0
#define _Q1 1
#define _Q2 2
#define _Q3 3
#define _Q4 4
#define _Q5 5
#define _Q6 6
#define _Q7 7
#define _Q8 8
#define _Q9 9
#define _Q10 10
#define _Q11 11
#define _Q12 12
#define _Q13 13
#define _Q14 14
#define _Q15 15
#if defined (_WINRT)
#else
#if defined (IPHONE)
#define MACRO .macro
#define END_MACRO .endmacro
#define ARG0_in
#define ARG1_in
#define ARG2_in
#define ARG3_in
#define ARG4_in
#define ARG5_in
#define ARG6_in
#define ARG7_in
#define ARG0 $0
#define ARG1 $1
#define ARG2 $2
#define ARG3 $3
#define ARG4 $4
#define ARG5 $5
#define ARG6 $6
#define ARG7 $7
#define RARG0 r$0
#define RARG1 r$1
#define QARG0 q$0
#define QARG1 q$1
MACRO CHECK_ABS ARG0_in, ARG1_in
.abs is_abs, ARG1
.if is_abs==1
.set ARG0, ARG1
.else
.set ARG0, -1
.endif
END_MACRO
#else
#define MACRO .macro
#define END_MACRO .endm
#define ARG0_in arg0=-1
#define ARG1_in arg1=-1
#define ARG2_in arg2=-1
#define ARG3_in arg3=-1
#define ARG4_in arg4=-1
#define ARG5_in arg5=-1
#define ARG6_in arg6=-1
#define ARG7_in arg7=-1
#define ARG0 \arg0
#define ARG1 \arg1
#define ARG2 \arg2
#define ARG3 \arg3
#define ARG4 \arg4
#define ARG5 \arg5
#define ARG6 \arg6
#define ARG7 \arg7
#define RARG0 r\arg0
#define RARG1 r\arg1
#define QARG0 q\arg0
#define QARG1 q\arg1
MACRO CHECK_ABS ARG0_in, ARG1_in
.set ARG0, ARG1
END_MACRO
#endif
MACRO VARDEF ARG0_in, ARG1_in
ARG0 .req ARG1
END_MACRO
MACRO VARDEFD ARG0_in, ARG1_in
ARG0 .req ARG1
END_MACRO
MACRO VARDEFQ ARG0_in, ARG1_in
ARG0 .req ARG1
END_MACRO
MACRO END
END_MACRO
MACRO EXTERN ARG0_in
END_MACRO
MACRO ALIGN ARG0_in
.align ARG0
END_MACRO
MACRO DATA
.data
END_MACRO
MACRO EXPORT ARG0_in
.globl ARG0
END_MACRO
#endif
#endif

View File

@ -0,0 +1,220 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* SKP_Silk_AsmPreProc.h
*
* General header for all ARM asms uses SigProcLib.
* It contains C preprocessor part and asm preprocessor part.
* C preprocessor part:
* * Interfacing makefile, arch, fpu and neon support
* * Interfacing different symbol styles and asm directives.
* * Interfacing compiling time standard output
* ASM preprocessor part:
* * Defining general asm header/footer for stack/return value
* * Allocating stack for local variables and nasted function
* * Defining simple syntax checking and debugging routines
*/
/*
* C preprocessor part
*/
#ifndef _SKP_ASM_PREPROC_H_
#define _SKP_ASM_PREPROC_H_
#include "SKP_Silk_AsmHelper.h"
/* Checking compilier __ARMEL__ defines */
#if !__ARMEL__ && (!defined(NO_ASM)) && (!defined(_WINRT))
#error Currently SKP_Silk_AsmPreProc only supports little endian.
// above line can be replaced by
// #warning __ARMEL__=0
// #define NOASM
#endif
/* Defining macro for different user label prefix. */
#ifndef __USER_LABEL_PREFIX__
#define __USER_LABEL_PREFIX__
#endif
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
/* Remapping register for iphone. */
#ifdef IPHONE
# define _fp r7
# define _r7 r11
#else
# define _fp fp
# define _r7 r7
#endif
/* Checking compiler __ARM_EABI__ defines */
#if __ARMEB__
#define NO_ASM //remove asm optimization for ARM big endian.
#else
#define ARM_LITTLE_ENDIAN
#endif
/* Interfacing some asm directives to macros*/
#define GBL .globl
/* Legacy definition wrapper */
#ifndef NO_ASM
#if defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5T__)
#define EMBEDDED_ARM 4
#define EMBEDDED_ARMv4
#elif defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5TEJ__)
#define EMBEDDED_ARM 5
#define EMBEDDED_ARMv5
#elif defined (__ARM_ARCH_6__) ||defined (__ARM_ARCH_6J__) || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
#define EMBEDDED_ARM 6
#define EMBEDDED_ARMv6
#elif defined (__ARM_ARCH_7A__) && defined (__ARM_NEON__)
#define EMBEDDED_ARM 7
#define EMBEDDED_ARMv6
#elif defined (__ARM_ARCH_7A__)
#define EMBEDDED_ARM 6
#define EMBEDDED_ARMv6
#else
#define EMBEDDED_ARM 0
#endif
#endif
#ifdef _WINRT
#define L(a) a
#define LR(a,d) %##d##a
#define TABLE(L, symbol) symbol
#else
#define L(a) a:
#define LR(a,d) a##d
#define DCD .long
#define DCW .short
#define TABLE(L, symbol) L
#endif
#ifdef _WINRT
#define streqh strheq
#define strneh strhne
#define strgth strhgt
#define strlth strhlt
#define ldrgtsh ldrshgt
#define ldmgtia ldmiagt
#define ldmgtdb ldmdbgt
#define ldrneh ldrhne
#define ldmltia ldmialt
#endif
/*
* ASM preprocessor part:
*/
#ifdef _WINRT
#else
// AT&T Format
#if EMBEDDED_ARM >= 7
.set _ARCH, 7
#elif EMBEDDED_ARM >= 6
.set _ARCH, 6
#elif EMBEDDED_ARM >= 5 // Should be re-considerred as ARMv5 != ARMv5E
.set _ARCH, 5
#elif EMBEDDED_ARM >= 4
.set _ARCH, 4
#else
.set _ARCH, 0
#endif
#if NEON
.set _NEON, 1
#else
.set _NEON, 0
#endif
MACRO SKP_TABLE ARG0_in, ARG1_in
SYM(ARG0):
END_MACRO
MACRO SKP_SMLAD ARG0_in, ARG1_in, ARG2_in, ARG3_in
#if EMBEDDED_ARM>=6
smlad ARG0, ARG1, ARG2, ARG3
#elif EMBEDDED_ARM>=5
smlabb ARG0, ARG1, ARG2, ARG3
smlatt ARG0, ARG1, ARG2, ARG0
#else
.abort "SKP_SMUAD can't be used for armv4 or lower device.."
#endif
END_MACRO
MACRO SKP_SMUAD ARG0_in, ARG1_in, ARG2_in
#if EMBEDDED_ARM>=6
smuad ARG0, ARG1, ARG2
#elif EMBEDDED_ARM>=5
smulbb ARG0, ARG1, ARG2
smlatt ARG0, ARG1, ARG2, ARG0
#else
.abort "SKP_SMUAD can't be used for armv4 or lower device.."
#endif
END_MACRO
MACRO SKP_SMLALD ARG0_in, ARG1_in, ARG2_in, ARG3_in
#if EMBEDDED_ARM>=6
smlald ARG0, ARG1, ARG2, ARG3
#elif EMBEDDED_ARM>=5
smlalbb ARG0, ARG1, ARG2, ARG3
smlaltt ARG0, ARG1, ARG2, ARG3
#else
.abort "SKP_SMLALD can't be used for armv4 or lower device.."
#endif
END_MACRO
MACRO SKP_RSHIFT_ROUND ARG0_in, ARG1_in, ARG2_in
#if EMBEDDED_ARM>=4
mov ARG0, ARG1, asr #(ARG2-1)
add ARG0, ARG0, #1
mov ARG0, ARG0, asr #1
#else
.abort "SKP_RSHIFT_ROUND can't be used for armv3 or lower device.."
#endif
END_MACRO
MACRO ADD_SHIFT ARG0_in, ARG1_in, ARG2_in, ARG3_in, ARG4_in
add ARG0, ARG1, ARG2, ARG3 ARG4
END_MACRO
MACRO POST_IR ARG0_in, ARG1_in, ARG2_in, ARG3_in
ARG0 ARG1, [ARG2], ARG3
END_MACRO
#endif
#endif //_SKP_ASM_PREPROC_H_

View File

@ -0,0 +1,149 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Generates excitation for CNG LPC synthesis */
SKP_INLINE void SKP_Silk_CNG_exc(
SKP_int16 residual[], /* O CNG residual signal Q0 */
SKP_int32 exc_buf_Q10[], /* I Random samples buffer Q10 */
SKP_int32 Gain_Q16, /* I Gain to apply */
SKP_int length, /* I Length */
SKP_int32 *rand_seed /* I/O Seed to random index generator */
)
{
SKP_int32 seed;
SKP_int i, idx, exc_mask;
exc_mask = CNG_BUF_MASK_MAX;
while( exc_mask > length ) {
exc_mask = SKP_RSHIFT( exc_mask, 1 );
}
seed = *rand_seed;
for( i = 0; i < length; i++ ) {
seed = SKP_RAND( seed );
idx = ( SKP_int )( SKP_RSHIFT( seed, 24 ) & exc_mask );
SKP_assert( idx >= 0 );
SKP_assert( idx <= CNG_BUF_MASK_MAX );
residual[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ), 10 ) );
}
*rand_seed = seed;
}
void SKP_Silk_CNG_Reset(
SKP_Silk_decoder_state *psDec /* I/O Decoder state */
)
{
SKP_int i, NLSF_step_Q15, NLSF_acc_Q15;
NLSF_step_Q15 = SKP_DIV32_16( SKP_int16_MAX, psDec->LPC_order + 1 );
NLSF_acc_Q15 = 0;
for( i = 0; i < psDec->LPC_order; i++ ) {
NLSF_acc_Q15 += NLSF_step_Q15;
psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
}
psDec->sCNG.CNG_smth_Gain_Q16 = 0;
psDec->sCNG.rand_seed = 3176576;
}
/* Updates CNG estimate, and applies the CNG when packet was lost */
void SKP_Silk_CNG(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* I/O Signal */
SKP_int length /* I Length of residual */
)
{
SKP_int i, subfr;
SKP_int32 tmp_32, Gain_Q26, max_Gain_Q16;
SKP_int16 LPC_buf[ MAX_LPC_ORDER ];
SKP_int16 CNG_sig[ MAX_FRAME_LENGTH ];
SKP_Silk_CNG_struct *psCNG;
psCNG = &psDec->sCNG;
if( psDec->fs_kHz != psCNG->fs_kHz ) {
/* Reset state */
SKP_Silk_CNG_Reset( psDec );
psCNG->fs_kHz = psDec->fs_kHz;
}
if( psDec->lossCnt == 0 && psDec->vadFlag == NO_VOICE_ACTIVITY ) {
/* Update CNG parameters */
/* Smoothing of LSF's */
for( i = 0; i < psDec->LPC_order; i++ ) {
psCNG->CNG_smth_NLSF_Q15[ i ] += SKP_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
}
/* Find the subframe with the highest gain */
max_Gain_Q16 = 0;
subfr = 0;
for( i = 0; i < NB_SUBFR; i++ ) {
if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
subfr = i;
}
}
/* Update CNG excitation buffer with excitation from this subframe */
SKP_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( NB_SUBFR - 1 ) * psDec->subfr_length * sizeof( SKP_int32 ) );
SKP_memcpy( psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( SKP_int32 ) );
/* Smooth gains */
for( i = 0; i < NB_SUBFR; i++ ) {
psCNG->CNG_smth_Gain_Q16 += SKP_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
}
}
/* Add CNG when packet is lost and / or when low speech activity */
if( psDec->lossCnt ) {//|| psDec->vadFlag == NO_VOICE_ACTIVITY ) {
/* Generate CNG excitation */
SKP_Silk_CNG_exc( CNG_sig, psCNG->CNG_exc_buf_Q10,
psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
SKP_Silk_NLSF2A_stable( LPC_buf, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
Gain_Q26 = ( SKP_int32 )1 << 26; /* 1.0 */
/* Generate CNG signal, by synthesis filtering */
if( psDec->LPC_order == 16 ) {
SKP_Silk_LPC_synthesis_order16( CNG_sig, LPC_buf,
Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length );
} else {
SKP_Silk_LPC_synthesis_filter( CNG_sig, LPC_buf,
Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length, psDec->LPC_order );
}
/* Mix with signal */
for( i = 0; i < length; i++ ) {
tmp_32 = signal[ i ] + CNG_sig[ i ];
signal[ i ] = SKP_SAT16( tmp_32 );
}
} else {
SKP_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( SKP_int32 ) );
}
}

View File

@ -0,0 +1,120 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_tuning_parameters.h"
#if HIGH_PASS_INPUT
#define SKP_RADIANS_CONSTANT_Q19 1482 // 0.45f * 2.0f * 3.14159265359 / 1000
#define SKP_LOG2_VARIABLE_HP_MIN_FREQ_Q7 809 // log(80) in Q7
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
void SKP_Silk_HP_variable_cutoff_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Encoder state FIX */
SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Encoder control FIX */
SKP_int16 *out, /* O high-pass filtered output signal */
const SKP_int16 *in /* I input signal */
)
{
SKP_int quality_Q15;
SKP_int32 B_Q28[ 3 ], A_Q28[ 2 ];
SKP_int32 Fc_Q19, r_Q28, r_Q22;
SKP_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
/*********************************************/
/* Estimate Low End of Pitch Frequency Range */
/*********************************************/
if( psEnc->sCmn.prev_sigtype == SIG_TYPE_VOICED ) {
/* difference, in log domain */
pitch_freq_Hz_Q16 = SKP_DIV32_16( SKP_LSHIFT( SKP_MUL( psEnc->sCmn.fs_kHz, 1000 ), 16 ), psEnc->sCmn.prevLag );
pitch_freq_log_Q7 = SKP_Silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 ); //0x70
/* adjustment based on quality */
quality_Q15 = psEncCtrl->input_quality_bands_Q15[ 0 ];
pitch_freq_log_Q7 = SKP_SUB32( pitch_freq_log_Q7, SKP_SMULWB( SKP_SMULWB( SKP_LSHIFT( quality_Q15, 2 ), quality_Q15 ),
pitch_freq_log_Q7 - SKP_LOG2_VARIABLE_HP_MIN_FREQ_Q7 ) );
pitch_freq_log_Q7 = SKP_ADD32( pitch_freq_log_Q7, SKP_RSHIFT( SKP_FIX_CONST( 0.6, 15 ) - quality_Q15, 9 ) );
//delta_freq = pitch_freq_log - psEnc->variable_HP_smth1;
delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEnc->variable_HP_smth1_Q15, 8 );
if( delta_freq_Q7 < 0 ) {
/* less smoothing for decreasing pitch frequency, to track something close to the minimum */
delta_freq_Q7 = SKP_MUL( delta_freq_Q7, 3 );
}
/* limit delta, to reduce impact of outliers */
delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
/* update smoother */
psEnc->variable_HP_smth1_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth1_Q15,
SKP_MUL( SKP_LSHIFT( psEnc->speech_activity_Q8, 1 ), delta_freq_Q7 ), SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
}
/* second smoother */
psEnc->variable_HP_smth2_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth2_Q15,
psEnc->variable_HP_smth1_Q15 - psEnc->variable_HP_smth2_Q15, SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) );
/* convert from log scale to Hertz */
psEncCtrl->pitch_freq_low_Hz = SKP_Silk_log2lin( SKP_RSHIFT( psEnc->variable_HP_smth2_Q15, 8 ) );
/* limit frequency range */
psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_32( psEncCtrl->pitch_freq_low_Hz,
SKP_FIX_CONST( VARIABLE_HP_MIN_FREQ, 0 ), SKP_FIX_CONST( VARIABLE_HP_MAX_FREQ, 0 ) );
/********************************/
/* Compute Filter Coefficients */
/********************************/
/* compute cut-off frequency, in radians */
//Fc_num = (SKP_float)( 0.45f * 2.0f * 3.14159265359 * psEncCtrl->pitch_freq_low_Hz );
//Fc_denom = (SKP_float)( 1e3f * psEnc->sCmn.fs_kHz );
SKP_assert( psEncCtrl->pitch_freq_low_Hz <= SKP_int32_MAX / SKP_RADIANS_CONSTANT_Q19 );
Fc_Q19 = SKP_DIV32_16( SKP_SMULBB( SKP_RADIANS_CONSTANT_Q19, psEncCtrl->pitch_freq_low_Hz ), psEnc->sCmn.fs_kHz ); // range: 3704 - 27787, 11-15 bits
SKP_assert( Fc_Q19 >= 3704 );
SKP_assert( Fc_Q19 <= 27787 );
r_Q28 = SKP_FIX_CONST( 1.0, 28 ) - SKP_MUL( SKP_FIX_CONST( 0.92, 9 ), Fc_Q19 );
SKP_assert( r_Q28 >= 255347779 );
SKP_assert( r_Q28 <= 266690872 );
/* b = r * [ 1; -2; 1 ]; */
/* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */
B_Q28[ 0 ] = r_Q28;
B_Q28[ 1 ] = SKP_LSHIFT( -r_Q28, 1 );
B_Q28[ 2 ] = r_Q28;
// -r * ( 2 - Fc * Fc );
r_Q22 = SKP_RSHIFT( r_Q28, 6 );
A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - SKP_FIX_CONST( 2.0, 22 ) );
A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 );
/********************************/
/* High-Pass Filter */
/********************************/
SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psEnc->sCmn.In_HP_State, out, psEnc->sCmn.frame_length );
}
#endif // HIGH_PASS_INPUT

View File

@ -0,0 +1,278 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*! \file SKP_Silk_Inlines.h
* \brief SKP_Silk_Inlines.h defines inline signal processing functions.
*/
#ifndef _SKP_SILK_FIX_INLINES_H_
#define _SKP_SILK_FIX_INLINES_H_
#include <assert.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* count leading zeros of SKP_int64 */
SKP_INLINE SKP_int32 SKP_Silk_CLZ64(SKP_int64 in)
{
SKP_int32 in_upper;
in_upper = (SKP_int32)SKP_RSHIFT64(in, 32);
if (in_upper == 0) {
/* Search in the lower 32 bits */
return 32 + SKP_Silk_CLZ32( (SKP_int32) in );
} else {
/* Search in the upper 32 bits */
return SKP_Silk_CLZ32( in_upper );
}
}
/* get number of leading zeros and fractional part (the bits right after the leading one */
SKP_INLINE void SKP_Silk_CLZ_FRAC(SKP_int32 in, /* I: input */
SKP_int32 *lz, /* O: number of leading zeros */
SKP_int32 *frac_Q7) /* O: the 7 bits right after the leading one */
{
SKP_int32 lzeros = SKP_Silk_CLZ32(in);
* lz = lzeros;
* frac_Q7 = SKP_ROR32(in, 24 - lzeros) & 0x7f;
}
/* Approximation of square root */
/* Accuracy: < +/- 10% for output values > 15 */
/* < +/- 2.5% for output values > 120 */
SKP_INLINE SKP_int32 SKP_Silk_SQRT_APPROX(SKP_int32 x)
{
SKP_int32 y, lz, frac_Q7;
if( x <= 0 ) {
return 0;
}
SKP_Silk_CLZ_FRAC(x, &lz, &frac_Q7);
if( lz & 1 ) {
y = 32768;
} else {
y = 46214; /* 46214 = sqrt(2) * 32768 */
}
/* get scaling right */
y >>= SKP_RSHIFT(lz, 1);
/* increment using fractional part of input */
y = SKP_SMLAWB(y, y, SKP_SMULBB(213, frac_Q7));
return y;
}
/* returns the number of left shifts before overflow for a 16 bit number (ITU definition with norm(0)=0) */
SKP_INLINE SKP_int32 SKP_Silk_norm16(SKP_int16 a) {
SKP_int32 a32;
/* if ((a == 0) || (a == SKP_int16_MIN)) return(0); */
if ((a << 1) == 0) return(0);
a32 = a;
/* if (a32 < 0) a32 = -a32 - 1; */
a32 ^= SKP_RSHIFT(a32, 31);
return SKP_Silk_CLZ32(a32) - 17;
}
/* returns the number of left shifts before overflow for a 32 bit number (ITU definition with norm(0)=0) */
SKP_INLINE SKP_int32 SKP_Silk_norm32(SKP_int32 a) {
/* if ((a == 0) || (a == SKP_int32_MIN)) return(0); */
if ((a << 1) == 0) return(0);
/* if (a < 0) a = -a - 1; */
a ^= SKP_RSHIFT(a, 31);
return SKP_Silk_CLZ32(a) - 1;
}
/* Divide two int32 values and return result as int32 in a given Q-domain */
SKP_INLINE SKP_int32 SKP_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
const SKP_int32 a32, /* I numerator (Q0) */
const SKP_int32 b32, /* I denominator (Q0) */
const SKP_int Qres /* I Q-domain of result (>= 0) */
)
{
SKP_int a_headrm, b_headrm, lshift;
SKP_int32 b32_inv, a32_nrm, b32_nrm, result;
SKP_assert( b32 != 0 );
SKP_assert( Qres >= 0 );
/* Compute number of bits head room and normalize inputs */
a_headrm = SKP_Silk_CLZ32( SKP_abs(a32) ) - 1;
a32_nrm = SKP_LSHIFT(a32, a_headrm); /* Q: a_headrm */
b_headrm = SKP_Silk_CLZ32( SKP_abs(b32) ) - 1;
b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */
/* Inverse of b32, with 14 bits of precision */
b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
/* First approximation */
result = SKP_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
/* Compute residual by subtracting product of denominator and first approximation */
a32_nrm -= SKP_LSHIFT_ovflw( SKP_SMMUL(b32_nrm, result), 3 ); /* Q: a_headrm */
/* Refinement */
result = SKP_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
/* Convert to Qres domain */
lshift = 29 + a_headrm - b_headrm - Qres;
if( lshift <= 0 ) {
return SKP_LSHIFT_SAT32(result, -lshift);
} else {
if( lshift < 32){
return SKP_RSHIFT(result, lshift);
} else {
/* Avoid undefined result */
return 0;
}
}
}
/* Invert int32 value and return result as int32 in a given Q-domain */
SKP_INLINE SKP_int32 SKP_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
const SKP_int32 b32, /* I denominator (Q0) */
const SKP_int Qres /* I Q-domain of result (> 0) */
)
{
SKP_int b_headrm, lshift;
SKP_int32 b32_inv, b32_nrm, err_Q32, result;
SKP_assert( b32 != 0 );
SKP_assert( b32 != SKP_int32_MIN ); /* SKP_int32_MIN is not handled by SKP_abs */
SKP_assert( Qres > 0 );
/* Compute number of bits head room and normalize input */
b_headrm = SKP_Silk_CLZ32( SKP_abs(b32) ) - 1;
b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */
/* Inverse of b32, with 14 bits of precision */
b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
/* First approximation */
result = SKP_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */
/* Compute residual by subtracting product of denominator and first approximation from one */
err_Q32 = SKP_LSHIFT_ovflw( -SKP_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */
/* Refinement */
result = SKP_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */
/* Convert to Qres domain */
lshift = 61 - b_headrm - Qres;
if( lshift <= 0 ) {
return SKP_LSHIFT_SAT32(result, -lshift);
} else {
if( lshift < 32){
return SKP_RSHIFT(result, lshift);
}else{
/* Avoid undefined result */
return 0;
}
}
}
#define SKP_SIN_APPROX_CONST0 (1073735400)
#define SKP_SIN_APPROX_CONST1 (-82778932)
#define SKP_SIN_APPROX_CONST2 (1059577)
#define SKP_SIN_APPROX_CONST3 (-5013)
/* Sine approximation; an input of 65536 corresponds to 2 * pi */
/* Uses polynomial expansion of the input to the power 0, 2, 4 and 6 */
/* The relative error is below 1e-5 */
SKP_INLINE SKP_int32 SKP_Silk_SIN_APPROX_Q24( /* O returns approximately 2^24 * sin(x * 2 * pi / 65536) */
SKP_int32 x
)
{
SKP_int y_Q30;
/* Keep only bottom 16 bits (the function repeats itself with period 65536) */
x &= 65535;
/* Split range in four quadrants */
if( x <= 32768 ) {
if( x < 16384 ) {
/* Return cos(pi/2 - x) */
x = 16384 - x;
} else {
/* Return cos(x - pi/2) */
x -= 16384;
}
if( x < 1100 ) {
/* Special case: high accuracy */
return SKP_SMLAWB( 1 << 24, SKP_MUL( x, x ), -5053 );
}
x = SKP_SMULWB( SKP_LSHIFT( x, 8 ), x ); /* contains x^2 in Q20 */
y_Q30 = SKP_SMLAWB( SKP_SIN_APPROX_CONST2, x, SKP_SIN_APPROX_CONST3 );
y_Q30 = SKP_SMLAWW( SKP_SIN_APPROX_CONST1, x, y_Q30 );
y_Q30 = SKP_SMLAWW( SKP_SIN_APPROX_CONST0 + 66, x, y_Q30 );
} else {
if( x < 49152 ) {
/* Return -cos(3*pi/2 - x) */
x = 49152 - x;
} else {
/* Return -cos(x - 3*pi/2) */
x -= 49152;
}
if( x < 1100 ) {
/* Special case: high accuracy */
return SKP_SMLAWB( -(1 << 24), SKP_MUL( x, x ), 5053 );
}
x = SKP_SMULWB( SKP_LSHIFT( x, 8 ), x ); /* contains x^2 in Q20 */
y_Q30 = SKP_SMLAWB( -SKP_SIN_APPROX_CONST2, x, -SKP_SIN_APPROX_CONST3 );
y_Q30 = SKP_SMLAWW( -SKP_SIN_APPROX_CONST1, x, y_Q30 );
y_Q30 = SKP_SMLAWW( -SKP_SIN_APPROX_CONST0, x, y_Q30 );
}
return SKP_RSHIFT_ROUND( y_Q30, 6 );
}
/* Cosine approximation; an input of 65536 corresponds to 2 * pi */
/* The relative error is below 1e-5 */
SKP_INLINE SKP_int32 SKP_Silk_COS_APPROX_Q24( /* O returns approximately 2^24 * cos(x * 2 * pi / 65536) */
SKP_int32 x
)
{
return SKP_Silk_SIN_APPROX_Q24( x + 16384 );
}
#ifdef __cplusplus
}
#endif
#endif /*_SKP_SILK_FIX_INLINES_H_*/

View File

@ -0,0 +1,40 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Resets LBRR buffer, used if packet size changes */
void SKP_Silk_LBRR_reset(
SKP_Silk_encoder_state *psEncC /* I/O state */
)
{
SKP_int i;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
psEncC->LBRR_buffer[ i ].usage = SKP_SILK_NO_LBRR;
}
}

View File

@ -0,0 +1,153 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_LPC_inverse_pred_gain.c *
* *
* Compute inverse of LPC prediction gain, and *
* test if LPC coefficients are stable (all poles within unit circle) *
* *
* Copyright 2008 (c), Skype Limited *
* */
#include "SKP_Silk_SigProc_FIX.h"
#define QA 16
#define A_LIMIT SKP_FIX_CONST( 0.99975, QA )
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
static SKP_int LPC_inverse_pred_gain_QA( /* O: Returns 1 if unstable, otherwise 0 */
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
SKP_int32 A_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ],
/* I: Prediction coefficients */
const SKP_int order /* I: Prediction order */
)
{
SKP_int k, n, headrm;
SKP_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16, tmp_QA;
SKP_int32 *Aold_QA, *Anew_QA;
Anew_QA = A_QA[ order & 1 ];
*invGain_Q30 = ( 1 << 30 );
for( k = order - 1; k > 0; k-- ) {
/* Check for stability */
if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
return 1;
}
/* Set RC equal to negated AR coef */
rc_Q31 = -SKP_LSHIFT( Anew_QA[ k ], 31 - QA );
/* rc_mult1_Q30 range: [ 1 : 2^30-1 ] */
rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 );
SKP_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
SKP_assert( rc_mult1_Q30 < ( 1 << 30 ) );
/* rc_mult2_Q16 range: [ 2^16 : SKP_int32_MAX ] */
rc_mult2_Q16 = SKP_INVERSE32_varQ( rc_mult1_Q30, 46 ); /* 16 = 46 - 30 */
/* Update inverse gain */
/* invGain_Q30 range: [ 0 : 2^30 ] */
*invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
SKP_assert( *invGain_Q30 >= 0 );
SKP_assert( *invGain_Q30 <= ( 1 << 30 ) );
/* Swap pointers */
Aold_QA = Anew_QA;
Anew_QA = A_QA[ k & 1 ];
/* Update AR coefficient */
headrm = SKP_Silk_CLZ32( rc_mult2_Q16 ) - 1;
rc_mult2_Q16 = SKP_LSHIFT( rc_mult2_Q16, headrm ); /* Q: 16 + headrm */
for( n = 0; n < k; n++ ) {
tmp_QA = Aold_QA[ n ] - SKP_LSHIFT( SKP_SMMUL( Aold_QA[ k - n - 1 ], rc_Q31 ), 1 );
Anew_QA[ n ] = SKP_LSHIFT( SKP_SMMUL( tmp_QA, rc_mult2_Q16 ), 16 - headrm );
}
}
/* Check for stability */
if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
return 1;
}
/* Set RC equal to negated AR coef */
rc_Q31 = -SKP_LSHIFT( Anew_QA[ 0 ], 31 - QA );
/* Range: [ 1 : 2^30 ] */
rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 );
/* Update inverse gain */
/* Range: [ 0 : 2^30 ] */
*invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
SKP_assert( *invGain_Q30 >= 0 );
SKP_assert( *invGain_Q30 <= 1<<30 );
return 0;
}
/* For input in Q12 domain */
SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
const SKP_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */
const SKP_int order /* I: Prediction order */
)
{
SKP_int k;
SKP_int32 Atmp_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ];
SKP_int32 *Anew_QA;
Anew_QA = Atmp_QA[ order & 1 ];
/* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) {
Anew_QA[ k ] = SKP_LSHIFT( (SKP_int32)A_Q12[ k ], QA - 12 );
}
return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
}
/* For input in Q24 domain */
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
const SKP_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */
const SKP_int order /* I: Prediction order */
)
{
SKP_int k;
SKP_int32 Atmp_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ];
SKP_int32 *Anew_QA;
Anew_QA = Atmp_QA[ order & 1 ];
/* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) {
Anew_QA[ k ] = SKP_RSHIFT_ROUND( A_Q24[ k ], 24 - QA );
}
return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
}

View File

@ -0,0 +1,117 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_LPC_synthesis_filter.c *
* Coefficients are in Q12 *
* *
* even order AR filter *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* even order AR filter */
void SKP_Silk_LPC_synthesis_filter(
const SKP_int16 *in, /* I: excitation signal */
const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */
const SKP_int32 Gain_Q26, /* I: gain */
SKP_int32 *S, /* I/O: state vector [Order] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len, /* I: signal length */
const SKP_int Order /* I: filter order, must be even */
)
{
SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 );
SKP_int32 SA, SB, out32_Q10, out32;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 Atmp, A_align_Q12[ SKP_Silk_MAX_ORDER_LPC >> 1 ];
/* combine two A_Q12 values and ensure 32-bit alignment */
for( k = 0; k < Order_half; k++ ) {
idx = SKP_SMULBB( 2, k );
A_align_Q12[ k ] = ( ( ( SKP_int32 )A_Q12[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( ( SKP_int32 )A_Q12[ idx + 1 ], 16 );
}
#endif
/* Order must be even */
SKP_assert( 2 * Order_half == Order );
/* S[] values are in Q14 */
for( k = 0; k < len; k++ ) {
SA = S[ Order - 1 ];
out32_Q10 = 0;
for( j = 0; j < ( Order_half - 1 ); j++ ) {
idx = SKP_SMULBB( 2, j ) + 1;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* multiply-add two prediction coefficients for each loop */
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
Atmp = A_align_Q12[ j ];
SB = S[ Order - 1 - idx ];
S[ Order - 1 - idx ] = SA;
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp );
SA = S[ Order - 2 - idx ];
S[ Order - 2 - idx ] = SB;
#else
SB = S[ Order - 1 - idx ];
S[ Order - 1 - idx ] = SA;
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ ( j << 1 ) ] );
out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ ( j << 1 ) + 1 ] );
SA = S[ Order - 2 - idx ];
S[ Order - 2 - idx ] = SB;
#endif
}
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* unrolled loop: epilog */
Atmp = A_align_Q12[ Order_half - 1 ];
SB = S[ 0 ];
S[ 0 ] = SA;
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp );
#else
/* unrolled loop: epilog */
SB = S[ 0 ];
S[ 0 ] = SA;
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ Order - 2 ] );
out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ Order - 1 ] );
#endif
/* apply gain to excitation signal and add to prediction */
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) );
/* scale to Q0 */
out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 );
/* saturate output */
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
/* move result into delay line */
S[ Order - 1 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
}
}

View File

@ -0,0 +1,216 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_LPC_synthesis_order16.c *
* Coefficients are in Q12 *
* *
* 16th order AR filter *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* 16th order AR filter */
void SKP_Silk_LPC_synthesis_order16(const SKP_int16 *in, /* I: excitation signal */
const SKP_int16 *A_Q12, /* I: AR coefficients [16], between -8_Q0 and 8_Q0 */
const SKP_int32 Gain_Q26, /* I: gain */
SKP_int32 *S, /* I/O: state vector [16] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len /* I: signal length, must be multiple of 16 */
)
{
SKP_int k;
SKP_int32 SA, SB, out32_Q10, out32;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 Atmp, A_align_Q12[ 8 ];
/* combine two A_Q12 values and ensure 32-bit alignment */
for( k = 0; k < 8; k++ ) {
A_align_Q12[ k ] = ( ( ( SKP_int32 )A_Q12[ 2 * k ] ) & 0x0000ffff ) | SKP_LSHIFT( ( SKP_int32 )A_Q12[ 2 * k + 1 ], 16 );
}
/* S[] values are in Q14 */
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
for( k = 0; k < len; k++ ) {
/* unrolled loop: prolog */
/* multiply-add two prediction coefficients per iteration */
SA = S[ 15 ];
Atmp = A_align_Q12[ 0 ];
SB = S[ 14 ];
S[ 14 ] = SA;
out32_Q10 = SKP_SMULWB( SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 13 ];
S[ 13 ] = SB;
/* unrolled loop: main loop */
Atmp = A_align_Q12[ 1 ];
SB = S[ 12 ];
S[ 12 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 11 ];
S[ 11 ] = SB;
Atmp = A_align_Q12[ 2 ];
SB = S[ 10 ];
S[ 10 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 9 ];
S[ 9 ] = SB;
Atmp = A_align_Q12[ 3 ];
SB = S[ 8 ];
S[ 8 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 7 ];
S[ 7 ] = SB;
Atmp = A_align_Q12[ 4 ];
SB = S[ 6 ];
S[ 6 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 5 ];
S[ 5 ] = SB;
Atmp = A_align_Q12[ 5 ];
SB = S[ 4 ];
S[ 4 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 3 ];
S[ 3 ] = SB;
Atmp = A_align_Q12[ 6 ];
SB = S[ 2 ];
S[ 2 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
SA = S[ 1 ];
S[ 1 ] = SB;
/* unrolled loop: epilog */
Atmp = A_align_Q12[ 7 ];
SB = S[ 0 ];
S[ 0 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
/* unrolled loop: end */
/* apply gain to excitation signal and add to prediction */
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) );
/* scale to Q0 */
out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 );
/* saturate output */
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
/* move result into delay line */
S[ 15 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
}
#else
for( k = 0; k < len; k++ ) {
/* unrolled loop: prolog */
/* multiply-add two prediction coefficients per iteration */
SA = S[ 15 ];
SB = S[ 14 ];
S[ 14 ] = SA;
out32_Q10 = SKP_SMULWB( SA, A_Q12[ 0 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 1 ] );
SA = S[ 13 ];
S[ 13 ] = SB;
/* unrolled loop: main loop */
SB = S[ 12 ];
S[ 12 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 2 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 3 ] );
SA = S[ 11 ];
S[ 11 ] = SB;
SB = S[ 10 ];
S[ 10 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 4 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 5 ] );
SA = S[ 9 ];
S[ 9 ] = SB;
SB = S[ 8 ];
S[ 8 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 6 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 7 ] );
SA = S[ 7 ];
S[ 7 ] = SB;
SB = S[ 6 ];
S[ 6 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 8 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 9 ] );
SA = S[ 5 ];
S[ 5 ] = SB;
SB = S[ 4 ];
S[ 4 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 10 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 11 ] );
SA = S[ 3 ];
S[ 3 ] = SB;
SB = S[ 2 ];
S[ 2 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 12 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 13 ] );
SA = S[ 1 ];
S[ 1 ] = SB;
/* unrolled loop: epilog */
SB = S[ 0 ];
S[ 0 ] = SA;
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 14 ] );
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 15 ] );
/* unrolled loop: end */
/* apply gain to excitation signal and add to prediction */
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) );
/* scale to Q0 */
out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 );
/* saturate output */
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
/* move result into delay line */
S[ 15 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
}
#endif
}

View File

@ -0,0 +1,194 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*
Elliptic/Cauer filters designed with 0.1 dB passband ripple,
80 dB minimum stopband attenuation, and
[0.95 : 0.15 : 0.35] normalized cut off frequencies.
*/
#include "SKP_Silk_main.h"
#if SWITCH_TRANSITION_FILTERING
/* Helper function, that interpolates the filter taps */
SKP_INLINE void SKP_Silk_LP_interpolate_filter_taps(
SKP_int32 B_Q28[ TRANSITION_NB ],
SKP_int32 A_Q28[ TRANSITION_NA ],
const SKP_int ind,
const SKP_int32 fac_Q16
)
{
SKP_int nb, na;
if( ind < TRANSITION_INT_NUM - 1 ) {
if( fac_Q16 > 0 ) {
if( fac_Q16 == SKP_SAT16( fac_Q16 ) ) { /* fac_Q16 is in range of a 16-bit int */
/* Piece-wise linear interpolation of B and A */
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
B_Q28[ nb ] = SKP_SMLAWB(
SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ],
SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ],
fac_Q16 );
}
for( na = 0; na < TRANSITION_NA; na++ ) {
A_Q28[ na ] = SKP_SMLAWB(
SKP_Silk_Transition_LP_A_Q28[ ind ][ na ],
SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
SKP_Silk_Transition_LP_A_Q28[ ind ][ na ],
fac_Q16 );
}
} else if( fac_Q16 == ( 1 << 15 ) ) { /* Neither fac_Q16 nor ( ( 1 << 16 ) - fac_Q16 ) is in range of a 16-bit int */
/* Piece-wise linear interpolation of B and A */
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
B_Q28[ nb ] = SKP_RSHIFT(
SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ] +
SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
1 );
}
for( na = 0; na < TRANSITION_NA; na++ ) {
A_Q28[ na ] = SKP_RSHIFT(
SKP_Silk_Transition_LP_A_Q28[ ind ][ na ] +
SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
1 );
}
} else { /* ( ( 1 << 16 ) - fac_Q16 ) is in range of a 16-bit int */
SKP_assert( ( ( 1 << 16 ) - fac_Q16 ) == SKP_SAT16( ( ( 1 << 16 ) - fac_Q16) ) );
/* Piece-wise linear interpolation of B and A */
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
B_Q28[ nb ] = SKP_SMLAWB(
SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
SKP_Silk_Transition_LP_B_Q28[ ind ][ nb ] -
SKP_Silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
( 1 << 16 ) - fac_Q16 );
}
for( na = 0; na < TRANSITION_NA; na++ ) {
A_Q28[ na ] = SKP_SMLAWB(
SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
SKP_Silk_Transition_LP_A_Q28[ ind ][ na ] -
SKP_Silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
( 1 << 16 ) - fac_Q16 );
}
}
} else {
SKP_memcpy( B_Q28, SKP_Silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( SKP_int32 ) );
SKP_memcpy( A_Q28, SKP_Silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( SKP_int32 ) );
}
} else {
SKP_memcpy( B_Q28, SKP_Silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( SKP_int32 ) );
SKP_memcpy( A_Q28, SKP_Silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( SKP_int32 ) );
}
}
/* Low-pass filter with variable cutoff frequency based on */
/* piece-wise linear interpolation between elliptic filters */
/* Start by setting psEncC->transition_frame_no = 1; */
/* Deactivate by setting psEncC->transition_frame_no = 0; */
void SKP_Silk_LP_variable_cutoff(
SKP_Silk_LP_state *psLP, /* I/O LP filter state */
SKP_int16 *out, /* O Low-pass filtered output signal */
const SKP_int16 *in, /* I Input signal */
const SKP_int frame_length /* I Frame length */
)
{
SKP_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
SKP_int ind = 0;
SKP_assert( psLP->transition_frame_no >= 0 );
SKP_assert( ( ( ( psLP->transition_frame_no <= TRANSITION_FRAMES_DOWN ) && ( psLP->mode == 0 ) ) ||
( ( psLP->transition_frame_no <= TRANSITION_FRAMES_UP ) && ( psLP->mode == 1 ) ) ) );
/* Interpolate filter coefficients if needed */
if( psLP->transition_frame_no > 0 ) {
if( psLP->mode == 0 ) {
if( psLP->transition_frame_no < TRANSITION_FRAMES_DOWN ) {
/* Calculate index and interpolation factor for interpolation */
#if( TRANSITION_INT_STEPS_DOWN == 32 )
fac_Q16 = SKP_LSHIFT( psLP->transition_frame_no, 16 - 5 );
#else
fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( psLP->transition_frame_no, 16 ), TRANSITION_INT_STEPS_DOWN );
#endif
ind = SKP_RSHIFT( fac_Q16, 16 );
fac_Q16 -= SKP_LSHIFT( ind, 16 );
SKP_assert( ind >= 0 );
SKP_assert( ind < TRANSITION_INT_NUM );
/* Interpolate filter coefficients */
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
/* Increment transition frame number for next frame */
psLP->transition_frame_no++;
} else {
SKP_assert( psLP->transition_frame_no == TRANSITION_FRAMES_DOWN );
/* End of transition phase */
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, TRANSITION_INT_NUM - 1, 0 );
}
} else {
SKP_assert( psLP->mode == 1 );
if( psLP->transition_frame_no < TRANSITION_FRAMES_UP ) {
/* Calculate index and interpolation factor for interpolation */
#if( TRANSITION_INT_STEPS_UP == 64 )
fac_Q16 = SKP_LSHIFT( TRANSITION_FRAMES_UP - psLP->transition_frame_no, 16 - 6 );
#else
fac_Q16 = SKP_DIV32_16( SKP_LSHIFT( TRANSITION_FRAMES_UP - psLP->transition_frame_no, 16 ), TRANSITION_INT_STEPS_UP );
#endif
ind = SKP_RSHIFT( fac_Q16, 16 );
fac_Q16 -= SKP_LSHIFT( ind, 16 );
SKP_assert( ind >= 0 );
SKP_assert( ind < TRANSITION_INT_NUM );
/* Interpolate filter coefficients */
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
/* Increment transition frame number for next frame */
psLP->transition_frame_no++;
} else {
SKP_assert( psLP->transition_frame_no == TRANSITION_FRAMES_UP );
/* End of transition phase */
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, 0, 0 );
}
}
}
if( psLP->transition_frame_no > 0 ) {
/* ARMA low-pass filtering */
SKP_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psLP->In_LP_State, out, frame_length );
} else {
/* Instead of using the filter, copy input directly to output */
SKP_memcpy( out, in, frame_length * sizeof( SKP_int16 ) );
}
}
#endif

View File

@ -0,0 +1,65 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SigProc_FIX.h"
// Q12 values (even)
const SKP_int SKP_Silk_LSFCosTab_FIX_Q12[LSF_COS_TAB_SZ_FIX + 1] = {
8192, 8190, 8182, 8170,
8152, 8130, 8104, 8072,
8034, 7994, 7946, 7896,
7840, 7778, 7714, 7644,
7568, 7490, 7406, 7318,
7226, 7128, 7026, 6922,
6812, 6698, 6580, 6458,
6332, 6204, 6070, 5934,
5792, 5648, 5502, 5352,
5198, 5040, 4880, 4718,
4552, 4382, 4212, 4038,
3862, 3684, 3502, 3320,
3136, 2948, 2760, 2570,
2378, 2186, 1990, 1794,
1598, 1400, 1202, 1002,
802, 602, 402, 202,
0, -202, -402, -602,
-802, -1002, -1202, -1400,
-1598, -1794, -1990, -2186,
-2378, -2570, -2760, -2948,
-3136, -3320, -3502, -3684,
-3862, -4038, -4212, -4382,
-4552, -4718, -4880, -5040,
-5198, -5352, -5502, -5648,
-5792, -5934, -6070, -6204,
-6332, -6458, -6580, -6698,
-6812, -6922, -7026, -7128,
-7226, -7318, -7406, -7490,
-7568, -7644, -7714, -7778,
-7840, -7896, -7946, -7994,
-8034, -8072, -8104, -8130,
-8152, -8170, -8182, -8190,
-8192
};

View File

@ -0,0 +1,80 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
void SKP_Silk_LTP_analysis_filter_FIX(
SKP_int16 *LTP_res, /* O: LTP residual signal of length NB_SUBFR * ( pre_length + subfr_length ) */
const SKP_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each NB_SUBFR subframe */
const SKP_int pitchL[ NB_SUBFR ], /* I: Pitch lag, one for each subframe */
const SKP_int32 invGains_Q16[ NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */
const SKP_int subfr_length, /* I: Length of each subframe */
const SKP_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */
)
{
const SKP_int16 *x_ptr, *x_lag_ptr;
SKP_int16 Btmp_Q14[ LTP_ORDER ];
SKP_int16 *LTP_res_ptr;
SKP_int k, i, j;
SKP_int32 LTP_est;
x_ptr = x;
LTP_res_ptr = LTP_res;
for( k = 0; k < NB_SUBFR; k++ ) {
x_lag_ptr = x_ptr - pitchL[ k ];
for( i = 0; i < LTP_ORDER; i++ ) {
Btmp_Q14[ i ] = LTPCoef_Q14[ k * LTP_ORDER + i ];
}
/* LTP analysis FIR filter */
for( i = 0; i < subfr_length + pre_length; i++ ) {
LTP_res_ptr[ i ] = x_ptr[ i ];
/* Long-term prediction */
LTP_est = SKP_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] );
for( j = 1; j < LTP_ORDER; j++ ) {
LTP_est = SKP_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] );
}
LTP_est = SKP_RSHIFT_ROUND( LTP_est, 14 ); // round and -> Q0
/* Subtract long-term prediction */
LTP_res_ptr[ i ] = ( SKP_int16 )SKP_SAT16( ( SKP_int32 )x_ptr[ i ] - LTP_est );
/* Scale residual */
LTP_res_ptr[ i ] = SKP_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] );
x_lag_ptr++;
}
/* Update pointers */
LTP_res_ptr += subfr_length + pre_length;
x_ptr += subfr_length;
}
}

View File

@ -0,0 +1,81 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#define NB_THRESHOLDS 11
/* Table containing trained thresholds for LTP scaling */
static const SKP_int16 LTPScaleThresholds_Q15[ NB_THRESHOLDS ] =
{
31129, 26214, 16384, 13107, 9830, 6554,
4915, 3276, 2621, 2458, 0
};
void SKP_Silk_LTP_scale_ctrl_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O encoder state FIX */
SKP_Silk_encoder_control_FIX *psEncCtrl /* I/O encoder control FIX */
)
{
SKP_int round_loss, frames_per_packet;
SKP_int g_out_Q5, g_limit_Q15, thrld1_Q15, thrld2_Q15;
/* 1st order high-pass filter */
psEnc->HPLTPredCodGain_Q7 = SKP_max_int( psEncCtrl->LTPredCodGain_Q7 - psEnc->prevLTPredCodGain_Q7, 0 )
+ SKP_RSHIFT_ROUND( psEnc->HPLTPredCodGain_Q7, 1 );
psEnc->prevLTPredCodGain_Q7 = psEncCtrl->LTPredCodGain_Q7;
/* combine input and filtered input */
g_out_Q5 = SKP_RSHIFT_ROUND( SKP_RSHIFT( psEncCtrl->LTPredCodGain_Q7, 1 ) + SKP_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 ), 3 );
g_limit_Q15 = SKP_Silk_sigm_Q15( g_out_Q5 - ( 3 << 5 ) );
/* Default is minimum scaling */
psEncCtrl->sCmn.LTP_scaleIndex = 0;
/* Round the loss measure to whole pct */
round_loss = ( SKP_int )psEnc->sCmn.PacketLoss_perc;
/* Only scale if first frame in packet 0% */
if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {
frames_per_packet = SKP_DIV32_16( psEnc->sCmn.PacketSize_ms, FRAME_LENGTH_MS );
round_loss += frames_per_packet - 1;
thrld1_Q15 = LTPScaleThresholds_Q15[ SKP_min_int( round_loss, NB_THRESHOLDS - 1 ) ];
thrld2_Q15 = LTPScaleThresholds_Q15[ SKP_min_int( round_loss + 1, NB_THRESHOLDS - 1 ) ];
if( g_limit_Q15 > thrld1_Q15 ) {
/* Maximum scaling */
psEncCtrl->sCmn.LTP_scaleIndex = 2;
} else if( g_limit_Q15 > thrld2_Q15 ) {
/* Medium scaling */
psEncCtrl->sCmn.LTP_scaleIndex = 1;
}
}
psEncCtrl->LTP_scale_Q14 = SKP_Silk_LTPScales_table_Q14[ psEncCtrl->sCmn.LTP_scaleIndex ];
}

View File

@ -0,0 +1,120 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_MA.c *
* *
* Variable order MA filter *
* *
* Copyright 2006 (c), Skype Limited *
* Date: 060221 *
* */
#include "SKP_Silk_SigProc_FIX.h"
#if EMBEDDED_ARM<5
/* Variable order MA prediction error filter */
void SKP_Silk_MA_Prediction(
const SKP_int16 *in, /* I: Input signal */
const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */
SKP_int32 *S, /* I/O: State vector [order] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len, /* I: Signal length */
const SKP_int32 order /* I: Filter order */
)
{
SKP_int k, d, in16;
SKP_int32 out32;
for( k = 0; k < len; k++ ) {
in16 = in[ k ];
out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ];
out32 = SKP_RSHIFT_ROUND( out32, 12 );
for( d = 0; d < order - 1; d++ ) {
S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B[ d ] );
}
S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] );
/* Limit */
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
}
}
#endif
#if EMBEDDED_ARM<5
void SKP_Silk_LPC_analysis_filter(
const SKP_int16 *in, /* I: Input signal */
const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */
SKP_int16 *S, /* I/O: State vector [order] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len, /* I: Signal length */
const SKP_int32 Order /* I: Filter order */
)
{
SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 );
SKP_int32 out32_Q12, out32;
SKP_int16 SA, SB;
/* Order must be even */
SKP_assert( 2 * Order_half == Order );
/* S[] values are in Q0 */
for( k = 0; k < len; k++ ) {
SA = S[ 0 ];
out32_Q12 = 0;
for( j = 0; j < ( Order_half - 1 ); j++ ) {
idx = SKP_SMULBB( 2, j ) + 1;
/* Multiply-add two prediction coefficients for each loop */
SB = S[ idx ];
S[ idx ] = SA;
out32_Q12 = SKP_SMLABB( out32_Q12, SA, B[ idx - 1 ] );
out32_Q12 = SKP_SMLABB( out32_Q12, SB, B[ idx ] );
SA = S[ idx + 1 ];
S[ idx + 1 ] = SB;
}
/* Unrolled loop: epilog */
SB = S[ Order - 1 ];
S[ Order - 1 ] = SA;
out32_Q12 = SKP_SMLABB( out32_Q12, SA, B[ Order - 2 ] );
out32_Q12 = SKP_SMLABB( out32_Q12, SB, B[ Order - 1 ] );
/* Subtract prediction */
out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 );
/* Scale to Q0 */
out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 );
/* Saturate output */
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
/* Move input line */
S[ 0 ] = in[ k ];
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,151 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* conversion between prediction filter coefficients and LSFs */
/* order should be even */
/* a piecewise linear approximation maps LSF <-> cos(LSF) */
/* therefore the result is not accurate LSFs, but the two */
/* function are accurate inverses of each other */
#include "SKP_Silk_SigProc_FIX.h"
/* helper function for NLSF2A(..) */
SKP_INLINE void SKP_Silk_NLSF2A_find_poly(
SKP_int32 *out, /* o intermediate polynomial, Q20 */
const SKP_int32 *cLSF, /* i vector of interleaved 2*cos(LSFs), Q20 */
SKP_int dd /* i polynomial order (= 1/2 * filter order) */
)
{
SKP_int k, n;
SKP_int32 ftmp;
out[0] = SKP_LSHIFT( 1, 20 );
out[1] = -cLSF[0];
for( k = 1; k < dd; k++ ) {
ftmp = cLSF[2*k]; // Q20
out[k+1] = SKP_LSHIFT( out[k-1], 1 ) - (SKP_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[k] ), 20 );
for( n = k; n > 1; n-- ) {
out[n] += out[n-2] - (SKP_int32)SKP_RSHIFT_ROUND64( SKP_SMULL( ftmp, out[n-1] ), 20 );
}
out[1] -= ftmp;
}
}
/* compute whitening filter coefficients from normalized line spectral frequencies */
void SKP_Silk_NLSF2A(
SKP_int16 *a, /* o monic whitening filter coefficients in Q12, [d] */
const SKP_int *NLSF, /* i normalized line spectral frequencies in Q15, [d] */
const SKP_int d /* i filter order (should be even) */
)
{
SKP_int k, i, dd;
SKP_int32 cos_LSF_Q20[SKP_Silk_MAX_ORDER_LPC];
SKP_int32 P[SKP_Silk_MAX_ORDER_LPC/2+1], Q[SKP_Silk_MAX_ORDER_LPC/2+1];
SKP_int32 Ptmp, Qtmp;
SKP_int32 f_int;
SKP_int32 f_frac;
SKP_int32 cos_val, delta;
SKP_int32 a_int32[SKP_Silk_MAX_ORDER_LPC];
SKP_int32 maxabs, absval, idx=0, sc_Q16;
SKP_assert(LSF_COS_TAB_SZ_FIX == 128);
/* convert LSFs to 2*cos(LSF(i)), using piecewise linear curve from table */
for( k = 0; k < d; k++ ) {
SKP_assert(NLSF[k] >= 0 );
SKP_assert(NLSF[k] <= 32767 );
/* f_int on a scale 0-127 (rounded down) */
f_int = SKP_RSHIFT( NLSF[k], 15 - 7 );
/* f_frac, range: 0..255 */
f_frac = NLSF[k] - SKP_LSHIFT( f_int, 15 - 7 );
SKP_assert(f_int >= 0);
SKP_assert(f_int < LSF_COS_TAB_SZ_FIX );
/* Read start and end value from table */
cos_val = SKP_Silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */
delta = SKP_Silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */
/* Linear interpolation */
cos_LSF_Q20[k] = SKP_LSHIFT( cos_val, 8 ) + SKP_MUL( delta, f_frac ); /* Q20 */
}
dd = SKP_RSHIFT( d, 1 );
/* generate even and odd polynomials using convolution */
SKP_Silk_NLSF2A_find_poly( P, &cos_LSF_Q20[0], dd );
SKP_Silk_NLSF2A_find_poly( Q, &cos_LSF_Q20[1], dd );
/* convert even and odd polynomials to SKP_int32 Q12 filter coefs */
for( k = 0; k < dd; k++ ) {
Ptmp = P[k+1] + P[k];
Qtmp = Q[k+1] - Q[k];
/* the Ptmp and Qtmp values at this stage need to fit in int32 */
a_int32[k] = -SKP_RSHIFT_ROUND( Ptmp + Qtmp, 9 ); /* Q20 -> Q12 */
a_int32[d-k-1] = SKP_RSHIFT_ROUND( Qtmp - Ptmp, 9 ); /* Q20 -> Q12 */
}
/* Limit the maximum absolute value of the prediction coefficients */
for( i = 0; i < 10; i++ ) {
/* Find maximum absolute value and its index */
maxabs = 0;
for( k = 0; k < d; k++ ) {
absval = SKP_abs( a_int32[k] );
if( absval > maxabs ) {
maxabs = absval;
idx = k;
}
}
if( maxabs > SKP_int16_MAX ) {
/* Reduce magnitude of prediction coefficients */
maxabs = SKP_min( maxabs, 98369 ); // ( SKP_int32_MAX / ( 65470 >> 2 ) ) + SKP_int16_MAX = 98369
sc_Q16 = 65470 - SKP_DIV32( SKP_MUL( 65470 >> 2, maxabs - SKP_int16_MAX ),
SKP_RSHIFT32( SKP_MUL( maxabs, idx + 1), 2 ) );
SKP_Silk_bwexpander_32( a_int32, d, sc_Q16 );
} else {
break;
}
}
/* Reached the last iteration */
if( i == 10 ) {
SKP_assert(0);
for( k = 0; k < d; k++ ) {
a_int32[k] = SKP_SAT16( a_int32[k] );
}
}
/* Return as SKP_int16 Q12 coefficients */
for( k = 0; k < d; k++ ) {
a[k] = (SKP_int16)a_int32[k];
}
}

View File

@ -0,0 +1,58 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Convert NLSF parameters to stable AR prediction filter coefficients */
void SKP_Silk_NLSF2A_stable(
SKP_int16 pAR_Q12[ MAX_LPC_ORDER ], /* O Stabilized AR coefs [LPC_order] */
const SKP_int pNLSF[ MAX_LPC_ORDER ], /* I NLSF vector [LPC_order] */
const SKP_int LPC_order /* I LPC/LSF order */
)
{
SKP_int i;
SKP_int32 invGain_Q30;
SKP_Silk_NLSF2A( pAR_Q12, pNLSF, LPC_order );
/* Ensure stable LPCs */
for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
if( SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, pAR_Q12, LPC_order ) == 1 ) {
SKP_Silk_bwexpander( pAR_Q12, LPC_order, 65536 - SKP_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015 */
} else {
break;
}
}
/* Reached the last iteration */
if( i == MAX_LPC_STABILIZE_ITERATIONS ) {
SKP_assert( 0 );
for( i = 0; i < LPC_order; i++ ) {
pAR_Q12[ i ] = 0;
}
}
}

View File

@ -0,0 +1,91 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* NLSF vector decoder */
void SKP_Silk_NLSF_MSVQ_decode(
SKP_int *pNLSF_Q15, /* O Pointer to decoded output vector [LPC_ORDER x 1] */
const SKP_Silk_NLSF_CB_struct *psNLSF_CB, /* I Pointer to NLSF codebook struct */
const SKP_int *NLSFIndices, /* I Pointer to NLSF indices [nStages x 1] */
const SKP_int LPC_order /* I LPC order used */
)
{
const SKP_int16 *pCB_element;
SKP_int s;
SKP_int i;
/* Check that each index is within valid range */
SKP_assert( 0 <= NLSFIndices[ 0 ] && NLSFIndices[ 0 ] < psNLSF_CB->CBStages[ 0 ].nVectors );
/* Point to the first vector element */
pCB_element = &psNLSF_CB->CBStages[ 0 ].CB_NLSF_Q15[ SKP_MUL( NLSFIndices[ 0 ], LPC_order ) ];
/* Initialize with the codebook vector from stage 0 */
for( i = 0; i < LPC_order; i++ ) {
pNLSF_Q15[ i ] = ( SKP_int )pCB_element[ i ];
}
for( s = 1; s < psNLSF_CB->nStages; s++ ) {
/* Check that each index is within valid range */
SKP_assert( 0 <= NLSFIndices[ s ] && NLSFIndices[ s ] < psNLSF_CB->CBStages[ s ].nVectors );
if( LPC_order == 16 ) {
/* Point to the first vector element */
pCB_element = &psNLSF_CB->CBStages[ s ].CB_NLSF_Q15[ SKP_LSHIFT( NLSFIndices[ s ], 4 ) ];
/* Add the codebook vector from the current stage */
pNLSF_Q15[ 0 ] += pCB_element[ 0 ];
pNLSF_Q15[ 1 ] += pCB_element[ 1 ];
pNLSF_Q15[ 2 ] += pCB_element[ 2 ];
pNLSF_Q15[ 3 ] += pCB_element[ 3 ];
pNLSF_Q15[ 4 ] += pCB_element[ 4 ];
pNLSF_Q15[ 5 ] += pCB_element[ 5 ];
pNLSF_Q15[ 6 ] += pCB_element[ 6 ];
pNLSF_Q15[ 7 ] += pCB_element[ 7 ];
pNLSF_Q15[ 8 ] += pCB_element[ 8 ];
pNLSF_Q15[ 9 ] += pCB_element[ 9 ];
pNLSF_Q15[ 10 ] += pCB_element[ 10 ];
pNLSF_Q15[ 11 ] += pCB_element[ 11 ];
pNLSF_Q15[ 12 ] += pCB_element[ 12 ];
pNLSF_Q15[ 13 ] += pCB_element[ 13 ];
pNLSF_Q15[ 14 ] += pCB_element[ 14 ];
pNLSF_Q15[ 15 ] += pCB_element[ 15 ];
} else {
/* Point to the first vector element */
pCB_element = &psNLSF_CB->CBStages[ s ].CB_NLSF_Q15[ SKP_SMULBB( NLSFIndices[ s ], LPC_order ) ];
/* Add the codebook vector from the current stage */
for( i = 0; i < LPC_order; i++ ) {
pNLSF_Q15[ i ] += pCB_element[ i ];
}
}
}
/* NLSF stabilization */
SKP_Silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->NDeltaMin_Q15, LPC_order );
}

View File

@ -0,0 +1,239 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
/***********************/
/* NLSF vector encoder */
/***********************/
void SKP_Silk_NLSF_MSVQ_encode_FIX(
SKP_int *NLSFIndices, /* O Codebook path vector [ CB_STAGES ] */
SKP_int *pNLSF_Q15, /* I/O Quantized NLSF vector [ LPC_ORDER ] */
const SKP_Silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
const SKP_int *pNLSF_q_Q15_prev, /* I Prev. quantized NLSF vector [LPC_ORDER] */
const SKP_int *pW_Q6, /* I NLSF weight vector [ LPC_ORDER ] */
const SKP_int NLSF_mu_Q15, /* I Rate weight for the RD optimization */
const SKP_int NLSF_mu_fluc_red_Q16, /* I Fluctuation reduction error weight */
const SKP_int NLSF_MSVQ_Survivors, /* I Max survivors from each stage */
const SKP_int LPC_order, /* I LPC order */
const SKP_int deactivate_fluc_red /* I Deactivate fluctuation reduction */
)
{
SKP_int i, s, k, cur_survivors = 0, prev_survivors, min_survivors, input_index, cb_index, bestIndex;
SKP_int32 rateDistThreshold_Q18;
#if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 1 )
SKP_int32 se_Q15, wsse_Q20, bestRateDist_Q20;
#endif
#if( LOW_COMPLEXITY_ONLY == 1 )
SKP_int32 pRateDist_Q18[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE ];
SKP_int32 pRate_Q5[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ];
SKP_int32 pRate_new_Q5[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ];
SKP_int pTempIndices[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ];
SKP_int pPath[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_CB_STAGES ];
SKP_int pPath_new[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_CB_STAGES ];
SKP_int pRes_Q15[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ];
SKP_int pRes_new_Q15[ MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * MAX_LPC_ORDER ];
#else
SKP_int32 pRateDist_Q18[ NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED ];
SKP_int32 pRate_Q5[ MAX_NLSF_MSVQ_SURVIVORS ];
SKP_int32 pRate_new_Q5[ MAX_NLSF_MSVQ_SURVIVORS ];
SKP_int pTempIndices[ MAX_NLSF_MSVQ_SURVIVORS ];
SKP_int pPath[ MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_CB_STAGES ];
SKP_int pPath_new[ MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_CB_STAGES ];
SKP_int pRes_Q15[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ];
SKP_int pRes_new_Q15[ MAX_NLSF_MSVQ_SURVIVORS * MAX_LPC_ORDER ];
#endif
const SKP_int *pConstInt;
SKP_int *pInt;
const SKP_int16 *pCB_element;
const SKP_Silk_NLSF_CBS *pCurrentCBStage;
#ifdef USE_UNQUANTIZED_LSFS
SKP_int NLSF_orig[ MAX_LPC_ORDER ];
SKP_memcpy( NLSF_orig, pNLSF_Q15, LPC_order * sizeof( SKP_int ) );
#endif
SKP_assert( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS );
SKP_assert( ( LOW_COMPLEXITY_ONLY == 0 ) || ( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ) );
/****************************************************/
/* Tree search for the multi-stage vector quantizer */
/****************************************************/
/* Clear accumulated rates */
SKP_memset( pRate_Q5, 0, NLSF_MSVQ_Survivors * sizeof( SKP_int32 ) );
/* Copy NLSFs into residual signal vector */
for( i = 0; i < LPC_order; i++ ) {
pRes_Q15[ i ] = pNLSF_Q15[ i ];
}
/* Set first stage values */
prev_survivors = 1;
/* Minimum number of survivors */
min_survivors = NLSF_MSVQ_Survivors / 2;
/* Loop over all stages */
for( s = 0; s < psNLSF_CB->nStages; s++ ) {
/* Set a pointer to the current stage codebook */
pCurrentCBStage = &psNLSF_CB->CBStages[ s ];
/* Calculate the number of survivors in the current stage */
cur_survivors = SKP_min_32( NLSF_MSVQ_Survivors, SKP_SMULBB( prev_survivors, pCurrentCBStage->nVectors ) );
#if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 0 )
/* Find a single best survivor in the last stage, if we */
/* do not need candidates for fluctuation reduction */
if( s == psNLSF_CB->nStages - 1 ) {
cur_survivors = 1;
}
#endif
/* Nearest neighbor clustering for multiple input data vectors */
SKP_Silk_NLSF_VQ_rate_distortion_FIX( pRateDist_Q18, pCurrentCBStage, pRes_Q15, pW_Q6,
pRate_Q5, NLSF_mu_Q15, prev_survivors, LPC_order );
/* Sort the rate-distortion errors */
SKP_Silk_insertion_sort_increasing( pRateDist_Q18, pTempIndices,
prev_survivors * pCurrentCBStage->nVectors, cur_survivors );
/* Discard survivors with rate-distortion values too far above the best one */
if( pRateDist_Q18[ 0 ] < SKP_int32_MAX / MAX_NLSF_MSVQ_SURVIVORS ) {
rateDistThreshold_Q18 = SKP_SMLAWB( pRateDist_Q18[ 0 ],
SKP_MUL( NLSF_MSVQ_Survivors, pRateDist_Q18[ 0 ] ), SKP_FIX_CONST( NLSF_MSVQ_SURV_MAX_REL_RD, 16 ) );
while( pRateDist_Q18[ cur_survivors - 1 ] > rateDistThreshold_Q18 && cur_survivors > min_survivors ) {
cur_survivors--;
}
}
/* Update accumulated codebook contributions for the 'cur_survivors' best codebook indices */
for( k = 0; k < cur_survivors; k++ ) {
if( s > 0 ) {
/* Find the indices of the input and the codebook vector */
if( pCurrentCBStage->nVectors == 8 ) {
input_index = SKP_RSHIFT( pTempIndices[ k ], 3 );
cb_index = pTempIndices[ k ] & 7;
} else {
input_index = SKP_DIV32_16( pTempIndices[ k ], pCurrentCBStage->nVectors );
cb_index = pTempIndices[ k ] - SKP_SMULBB( input_index, pCurrentCBStage->nVectors );
}
} else {
/* Find the indices of the input and the codebook vector */
input_index = 0;
cb_index = pTempIndices[ k ];
}
/* Subtract new contribution from the previous residual vector for each of 'cur_survivors' */
pConstInt = &pRes_Q15[ SKP_SMULBB( input_index, LPC_order ) ];
pCB_element = &pCurrentCBStage->CB_NLSF_Q15[ SKP_SMULBB( cb_index, LPC_order ) ];
pInt = &pRes_new_Q15[ SKP_SMULBB( k, LPC_order ) ];
for( i = 0; i < LPC_order; i++ ) {
pInt[ i ] = pConstInt[ i ] - ( SKP_int )pCB_element[ i ];
}
/* Update accumulated rate for stage 1 to the current */
pRate_new_Q5[ k ] = pRate_Q5[ input_index ] + pCurrentCBStage->Rates_Q5[ cb_index ];
/* Copy paths from previous matrix, starting with the best path */
pConstInt = &pPath[ SKP_SMULBB( input_index, psNLSF_CB->nStages ) ];
pInt = &pPath_new[ SKP_SMULBB( k, psNLSF_CB->nStages ) ];
for( i = 0; i < s; i++ ) {
pInt[ i ] = pConstInt[ i ];
}
/* Write the current stage indices for the 'cur_survivors' to the best path matrix */
pInt[ s ] = cb_index;
}
if( s < psNLSF_CB->nStages - 1 ) {
/* Copy NLSF residual matrix for next stage */
SKP_memcpy( pRes_Q15, pRes_new_Q15, SKP_SMULBB( cur_survivors, LPC_order ) * sizeof( SKP_int ) );
/* Copy rate vector for next stage */
SKP_memcpy( pRate_Q5, pRate_new_Q5, cur_survivors * sizeof( SKP_int32 ) );
/* Copy best path matrix for next stage */
SKP_memcpy( pPath, pPath_new, SKP_SMULBB( cur_survivors, psNLSF_CB->nStages ) * sizeof( SKP_int ) );
}
prev_survivors = cur_survivors;
}
/* (Preliminary) index of the best survivor, later to be decoded */
bestIndex = 0;
#if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 1 )
/******************************/
/* NLSF fluctuation reduction */
/******************************/
if( deactivate_fluc_red != 1 ) {
/* Search among all survivors, now taking also weighted fluctuation errors into account */
bestRateDist_Q20 = SKP_int32_MAX;
for( s = 0; s < cur_survivors; s++ ) {
/* Decode survivor to compare with previous quantized NLSF vector */
SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, &pPath_new[ SKP_SMULBB( s, psNLSF_CB->nStages ) ], LPC_order );
/* Compare decoded NLSF vector with the previously quantized vector */
wsse_Q20 = 0;
for( i = 0; i < LPC_order; i += 2 ) {
/* Compute weighted squared quantization error for index i */
se_Q15 = pNLSF_Q15[ i ] - pNLSF_q_Q15_prev[ i ]; // range: [ -32767 : 32767 ]
wsse_Q20 = SKP_SMLAWB( wsse_Q20, SKP_SMULBB( se_Q15, se_Q15 ), pW_Q6[ i ] );
/* Compute weighted squared quantization error for index i + 1 */
se_Q15 = pNLSF_Q15[ i + 1 ] - pNLSF_q_Q15_prev[ i + 1 ]; // range: [ -32767 : 32767 ]
wsse_Q20 = SKP_SMLAWB( wsse_Q20, SKP_SMULBB( se_Q15, se_Q15 ), pW_Q6[ i + 1 ] );
}
SKP_assert( wsse_Q20 >= 0 );
/* Add the fluctuation reduction penalty to the rate distortion error */
wsse_Q20 = SKP_ADD_POS_SAT32( pRateDist_Q18[ s ], SKP_SMULWB( wsse_Q20, NLSF_mu_fluc_red_Q16 ) );
/* Keep index of best survivor */
if( wsse_Q20 < bestRateDist_Q20 ) {
bestRateDist_Q20 = wsse_Q20;
bestIndex = s;
}
}
}
#endif
/* Copy best path to output argument */
SKP_memcpy( NLSFIndices, &pPath_new[ SKP_SMULBB( bestIndex, psNLSF_CB->nStages ) ], psNLSF_CB->nStages * sizeof( SKP_int ) );
/* Decode and stabilize the best survivor */
SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, NLSFIndices, LPC_order );
#ifdef USE_UNQUANTIZED_LSFS
SKP_memcpy( pNLSF_Q15, NLSF_orig, LPC_order * sizeof( SKP_int ) );
#endif
}

View File

@ -0,0 +1,61 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
/* Rate-Distortion calculations for multiple input data vectors */
void SKP_Silk_NLSF_VQ_rate_distortion_FIX(
SKP_int32 *pRD_Q20, /* O Rate-distortion values [psNLSF_CBS->nVectors*N] */
const SKP_Silk_NLSF_CBS *psNLSF_CBS, /* I NLSF codebook stage struct */
const SKP_int *in_Q15, /* I Input vectors to be quantized */
const SKP_int *w_Q6, /* I Weight vector */
const SKP_int32 *rate_acc_Q5, /* I Accumulated rates from previous stage */
const SKP_int mu_Q15, /* I Weight between weighted error and rate */
const SKP_int N, /* I Number of input vectors to be quantized */
const SKP_int LPC_order /* I LPC order */
)
{
SKP_int i, n;
SKP_int32 *pRD_vec_Q20;
/* Compute weighted quantization errors for all input vectors over one codebook stage */
SKP_Silk_NLSF_VQ_sum_error_FIX( pRD_Q20, in_Q15, w_Q6, psNLSF_CBS->CB_NLSF_Q15,
N, psNLSF_CBS->nVectors, LPC_order );
/* Loop over input vectors */
pRD_vec_Q20 = pRD_Q20;
for( n = 0; n < N; n++ ) {
/* Add rate cost to error for each codebook vector */
for( i = 0; i < psNLSF_CBS->nVectors; i++ ) {
SKP_assert( rate_acc_Q5[ n ] + psNLSF_CBS->Rates_Q5[ i ] >= 0 );
SKP_assert( rate_acc_Q5[ n ] + psNLSF_CBS->Rates_Q5[ i ] <= SKP_int16_MAX );
pRD_vec_Q20[ i ] = SKP_SMLABB( pRD_vec_Q20[ i ], rate_acc_Q5[ n ] + psNLSF_CBS->Rates_Q5[ i ], mu_Q15 );
SKP_assert( pRD_vec_Q20[ i ] >= 0 );
}
pRD_vec_Q20 += psNLSF_CBS->nVectors;
}
}

View File

@ -0,0 +1,83 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#if (!defined(__mips__)) && (EMBEDDED_ARM < 6)
/* Compute weighted quantization errors for an LPC_order element input vector, over one codebook stage */
void SKP_Silk_NLSF_VQ_sum_error_FIX(
SKP_int32 *err_Q20, /* O Weighted quantization errors [N*K] */
const SKP_int *in_Q15, /* I Input vectors to be quantized [N*LPC_order] */
const SKP_int *w_Q6, /* I Weighting vectors [N*LPC_order] */
const SKP_int16 *pCB_Q15, /* I Codebook vectors [K*LPC_order] */
const SKP_int N, /* I Number of input vectors */
const SKP_int K, /* I Number of codebook vectors */
const SKP_int LPC_order /* I Number of LPCs */
)
{
SKP_int i, n, m;
SKP_int32 diff_Q15, sum_error, Wtmp_Q6;
SKP_int32 Wcpy_Q6[ MAX_LPC_ORDER / 2 ];
const SKP_int16 *cb_vec_Q15;
SKP_assert( LPC_order <= 16 );
SKP_assert( ( LPC_order & 1 ) == 0 );
/* Copy to local stack and pack two weights per int32 */
for( m = 0; m < SKP_RSHIFT( LPC_order, 1 ); m++ ) {
Wcpy_Q6[ m ] = w_Q6[ 2 * m ] | SKP_LSHIFT( ( SKP_int32 )w_Q6[ 2 * m + 1 ], 16 );
}
/* Loop over input vectors */
for( n = 0; n < N; n++ ) {
/* Loop over codebook */
cb_vec_Q15 = pCB_Q15;
for( i = 0; i < K; i++ ) {
sum_error = 0;
for( m = 0; m < LPC_order; m += 2 ) {
/* Get two weights packed in an int32 */
Wtmp_Q6 = Wcpy_Q6[ SKP_RSHIFT( m, 1 ) ];
/* Compute weighted squared quantization error for index m */
diff_Q15 = in_Q15[ m ] - *cb_vec_Q15++; // range: [ -32767 : 32767 ]
sum_error = SKP_SMLAWB( sum_error, SKP_SMULBB( diff_Q15, diff_Q15 ), Wtmp_Q6 );
/* Compute weighted squared quantization error for index m + 1 */
diff_Q15 = in_Q15[m + 1] - *cb_vec_Q15++; // range: [ -32767 : 32767 ]
sum_error = SKP_SMLAWT( sum_error, SKP_SMULBB( diff_Q15, diff_Q15 ), Wtmp_Q6 );
}
SKP_assert( sum_error >= 0 );
err_Q20[ i ] = sum_error;
}
err_Q20 += K;
in_Q15 += LPC_order;
}
}
#endif

View File

@ -0,0 +1,161 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if __arm__
#include "SKP_Silk_AsmPreproc.h"
#if ( EMBEDDED_ARM >= 6 )
VARDEF val_N, r4
VARDEF val_K, r5
VARDEF val_order, r6
VARDEF val_in_Q15, _r7
VARDEF val_cb_Q15, r8
VARDEF val_wtmp_Q6, sb
VARDEF val_sum_error, sl
VARDEF val_diff, ip
VARDEF val_tmp, lr
VARDEF val_in_Q15_tmp, ip
VARDEF val_wtmp_Q6_tmp, lr
VARDEF ptr_wtmp, _r7
VARDEF val0_wtmp, sb
VARDEF val1_wtmp, r5
VARDEF val2_wtmp, r8
VARDEF ptr_err_Q20, r0
VARDEF ptr_in_Q15, r1
VARDEF ptr_w_Q6, r2
VARDEF ptr_pCB_Q15, r3
.set sp_wtmp, 0
.set sp_err_Q20, 32
.set sp_in_Q15, 36
.set sp_w_Q6, 40
.set sp_pCB_Q15, 44
.globl SYM(SKP_Silk_NLSF_VQ_sum_error_FIX)
SYM(SKP_Silk_NLSF_VQ_sum_error_FIX):
stmdb sp!, {r4-r10, fp, ip, lr}
add fp, sp, #36
sub sp, sp, #48
.set ptr_N, 88
.set ptr_K, 92
.set ptr_LPC_order, 96
str r0, [sp, #sp_err_Q20]
str r1, [sp, #sp_in_Q15]
str r2, [sp, #sp_w_Q6]
str r3, [sp, #sp_pCB_Q15]
ldr val_N, [sp, #ptr_N]
ldr val_order, [sp, #ptr_LPC_order]
ldr val1_wtmp, [r2], #4
ldr val2_wtmp, [r2], #4
sub val_order, val_order, #2
add ptr_wtmp, sp, #sp_wtmp
L(3)
pkhbt val0_wtmp, val1_wtmp, val2_wtmp, lsl #16
subs val_order, val_order, #2
ldr val1_wtmp, [r2], #4
ldr val2_wtmp, [r2], #4
str val0_wtmp, [ptr_wtmp], #4
bgt LR(3, b)
pkhbt val0_wtmp, val1_wtmp, val2_wtmp, lsl #16
str val0_wtmp, [ptr_wtmp], #4
ands val_tmp, ptr_pCB_Q15, #3
bgt LR(4, f)
/*OUTTER_LOOP*/
L(2)
ldr ptr_pCB_Q15, [sp, #sp_pCB_Q15]
ldr val_K, [sp, #ptr_K]
/*MIDDLE_LOOP*/
L(1)
ldr ptr_in_Q15, [sp, #sp_in_Q15]
add ptr_w_Q6, sp, #sp_wtmp
ldr val_order, [sp, #ptr_LPC_order]
mov val_sum_error, #0
/*INNER_LOOP*/
L(0)
ldmia ptr_in_Q15!, {val_in_Q15, val_in_Q15_tmp}
ldr val_wtmp_Q6, [ptr_w_Q6], #4
ldr val_cb_Q15, [ptr_pCB_Q15], #4
subs val_order, val_order, #2
pkhbt val_in_Q15, val_in_Q15, val_in_Q15_tmp, lsl #16
ssub16 val_diff, val_in_Q15, val_cb_Q15
smulbb val_tmp, val_diff, val_diff
smultt val_diff, val_diff, val_diff
smlawb val_sum_error, val_tmp, val_wtmp_Q6, val_sum_error
smlawt val_sum_error, val_diff, val_wtmp_Q6, val_sum_error
bgt LR(0, b)
subs val_K, val_K, #1
str val_sum_error, [ptr_err_Q20], #4
bgt LR(1, b)
subs val_N, val_N, #1
str ptr_in_Q15, [sp, #sp_in_Q15]
bgt LR(2, b)
add sp, sp, #48
ldmia sp!, {r4-r10, fp, ip, pc}
L(4)
ldr ptr_pCB_Q15, [sp, #sp_pCB_Q15]
ldr val_K, [sp, #ptr_K]
/*MIDDLE_LOOP*/
L(1)
ldr ptr_in_Q15, [sp, #sp_in_Q15]
add ptr_w_Q6, sp, #sp_wtmp
ldr val_order, [sp, #ptr_LPC_order]
mov val_sum_error, #0
/*INNER_LOOP*/
L(0)
ldmia ptr_in_Q15!, {val_in_Q15, val_in_Q15_tmp}
ldr val_wtmp_Q6, [ptr_w_Q6], #4
ldrh val_cb_Q15, [ptr_pCB_Q15], #2
ldrh val_tmp, [ptr_pCB_Q15], #2
subs val_order, val_order, #2
pkhbt val_in_Q15, val_in_Q15, val_in_Q15_tmp, lsl #16
pkhbt val_cb_Q15, val_cb_Q15, val_tmp, lsl #16
ssub16 val_diff, val_in_Q15, val_cb_Q15
smulbb val_tmp, val_diff, val_diff
smultt val_diff, val_diff, val_diff
smlawb val_sum_error, val_tmp, val_wtmp_Q6, val_sum_error
smlawt val_sum_error, val_diff, val_wtmp_Q6, val_sum_error
bgt LR(0, b)
subs val_K, val_K, #1
str val_sum_error, [ptr_err_Q20], #4
bgt LR(1, b)
subs val_N, val_N, #1
str ptr_in_Q15, [sp, #sp_in_Q15]
bgt LR(4, b)
add sp, sp, #48
ldmia sp!, {r4-r10, fp, ip, pc}
END
#endif
#endif

View File

@ -0,0 +1,79 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SigProc_FIX.h"
/*
R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
Signal Processing, pp. 641-644, 1991.
*/
#define Q_OUT 6
#define MIN_NDELTA 3
/* Laroia low complexity NLSF weights */
void SKP_Silk_NLSF_VQ_weights_laroia(
SKP_int *pNLSFW_Q6, /* O: Pointer to input vector weights [D x 1] */
const SKP_int *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */
const SKP_int D /* I: Input vector dimension (even) */
)
{
SKP_int k;
SKP_int32 tmp1_int, tmp2_int;
/* Check that we are guaranteed to end up within the required range */
SKP_assert( D > 0 );
SKP_assert( ( D & 1 ) == 0 );
/* First value */
tmp1_int = SKP_max_int( pNLSF_Q15[ 0 ], MIN_NDELTA );
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
tmp2_int = SKP_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], MIN_NDELTA );
tmp2_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp2_int );
pNLSFW_Q6[ 0 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
SKP_assert( pNLSFW_Q6[ 0 ] > 0 );
/* Main loop */
for( k = 1; k < D - 1; k += 2 ) {
tmp1_int = SKP_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], MIN_NDELTA );
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
pNLSFW_Q6[ k ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
SKP_assert( pNLSFW_Q6[ k ] > 0 );
tmp2_int = SKP_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], MIN_NDELTA );
tmp2_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp2_int );
pNLSFW_Q6[ k + 1 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
SKP_assert( pNLSFW_Q6[ k + 1 ] > 0 );
}
/* Last value */
tmp1_int = SKP_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], MIN_NDELTA );
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
pNLSFW_Q6[ D - 1 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
SKP_assert( pNLSFW_Q6[ D - 1 ] > 0 );
}

View File

@ -0,0 +1,139 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* NLSF stabilizer: */
/* */
/* - Moves NLSFs futher apart if they are too close */
/* - Moves NLSFs away from borders if they are too close */
/* - High effort to achieve a modification with minimum */
/* Euclidean distance to input vector */
/* - Output are sorted NLSF coefficients */
/* */
#include "SKP_Silk_SigProc_FIX.h"
/* Constant Definitions */
#define MAX_LOOPS 20
/* NLSF stabilizer, for a single input data vector */
void SKP_Silk_NLSF_stabilize(
SKP_int *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */
const SKP_int *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
const SKP_int L /* I: Number of NLSF parameters in the input vector */
)
{
SKP_int center_freq_Q15, diff_Q15, min_center_Q15, max_center_Q15;
SKP_int32 min_diff_Q15;
SKP_int loops;
SKP_int i, I=0, k;
/* This is necessary to ensure an output within range of a SKP_int16 */
SKP_assert( NDeltaMin_Q15[L] >= 1 );
for( loops = 0; loops < MAX_LOOPS; loops++ ) {
/**************************/
/* Find smallest distance */
/**************************/
/* First element */
min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
I = 0;
/* Middle elements */
for( i = 1; i <= L-1; i++ ) {
diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
if( diff_Q15 < min_diff_Q15 ) {
min_diff_Q15 = diff_Q15;
I = i;
}
}
/* Last element */
diff_Q15 = (1<<15) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
if( diff_Q15 < min_diff_Q15 ) {
min_diff_Q15 = diff_Q15;
I = L;
}
/***************************************************/
/* Now check if the smallest distance non-negative */
/***************************************************/
if (min_diff_Q15 >= 0) {
return;
}
if( I == 0 ) {
/* Move away from lower limit */
NLSF_Q15[0] = NDeltaMin_Q15[0];
} else if( I == L) {
/* Move away from higher limit */
NLSF_Q15[L-1] = (1<<15) - NDeltaMin_Q15[L];
} else {
/* Find the lower extreme for the location of the current center frequency */
min_center_Q15 = 0;
for( k = 0; k < I; k++ ) {
min_center_Q15 += NDeltaMin_Q15[k];
}
min_center_Q15 += SKP_RSHIFT( NDeltaMin_Q15[I], 1 );
/* Find the upper extreme for the location of the current center frequency */
max_center_Q15 = (1<<15);
for( k = L; k > I; k-- ) {
max_center_Q15 -= NDeltaMin_Q15[k];
}
max_center_Q15 -= ( NDeltaMin_Q15[I] - SKP_RSHIFT( NDeltaMin_Q15[I], 1 ) );
/* Move apart, sorted by value, keeping the same center frequency */
center_freq_Q15 = SKP_LIMIT_32( SKP_RSHIFT_ROUND( (SKP_int32)NLSF_Q15[I-1] + (SKP_int32)NLSF_Q15[I], 1 ),
min_center_Q15, max_center_Q15 );
NLSF_Q15[I-1] = center_freq_Q15 - SKP_RSHIFT( NDeltaMin_Q15[I], 1 );
NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
}
}
/* Safe and simple fall back method, which is less ideal than the above */
if( loops == MAX_LOOPS )
{
/* Insertion sort (fast for already almost sorted arrays): */
/* Best case: O(n) for an already sorted array */
/* Worst case: O(n^2) for an inversely sorted array */
SKP_Silk_insertion_sort_increasing_all_values(&NLSF_Q15[0], L);
/* First NLSF should be no less than NDeltaMin[0] */
NLSF_Q15[0] = SKP_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
/* Keep delta_min distance between the NLSFs */
for( i = 1; i < L; i++ )
NLSF_Q15[i] = SKP_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
/* Last NLSF should be no higher than 1 - NDeltaMin[L] */
NLSF_Q15[L-1] = SKP_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
/* Keep NDeltaMin distance between the NLSFs */
for( i = L-2; i >= 0; i-- )
NLSF_Q15[i] = SKP_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
}
}

View File

@ -0,0 +1,454 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
SKP_INLINE void SKP_Silk_nsq_scale_states(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
const SKP_int16 x[], /* I input in Q0 */
SKP_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
SKP_int subfr_length, /* I length of input */
const SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
SKP_int subfr, /* I subframe number */
const SKP_int LTP_scale_Q14, /* I */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int pitchL[ NB_SUBFR ] /* I */
);
SKP_INLINE void SKP_Silk_noise_shape_quantizer(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
SKP_int sigtype, /* I Signal type */
const SKP_int32 x_sc_Q10[], /* I */
SKP_int8 q[], /* O */
SKP_int16 xq[], /* O */
SKP_int32 sLTP_Q16[], /* I/O LTP state */
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
const SKP_int16 b_Q14[], /* I Long term prediction coefs */
const SKP_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
SKP_int lag, /* I Pitch lag */
SKP_int32 HarmShapeFIRPacked_Q14, /* I */
SKP_int Tilt_Q14, /* I Spectral tilt */
SKP_int32 LF_shp_Q14, /* I */
SKP_int32 Gain_Q16, /* I */
SKP_int Lambda_Q10, /* I */
SKP_int offset_Q10, /* I */
SKP_int length, /* I Input length */
SKP_int shapingLPCOrder, /* I Noise shaping AR filter order */
SKP_int predictLPCOrder /* I Prediction filter order */
);
void SKP_Silk_NSQ(
SKP_Silk_encoder_state *psEncC, /* I/O Encoder State */
SKP_Silk_encoder_control *psEncCtrlC, /* I Encoder Control */
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
const SKP_int16 x[], /* I prefiltered input signal */
SKP_int8 q[], /* O quantized qulse signal */
const SKP_int LSFInterpFactor_Q2, /* I LSF interpolation factor in Q2 */
const SKP_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ], /* I Long term prediction coefficients */
const SKP_int16 AR2_Q13[ NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */
const SKP_int HarmShapeGain_Q14[ NB_SUBFR ], /* I */
const SKP_int Tilt_Q14[ NB_SUBFR ], /* I Spectral tilt */
const SKP_int32 LF_shp_Q14[ NB_SUBFR ], /* I */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int Lambda_Q10, /* I */
const SKP_int LTP_scale_Q14 /* I LTP state scaling */
)
{
SKP_int k, lag, start_idx, LSF_interpolation_flag;
const SKP_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
SKP_int16 *pxq;
SKP_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ];
SKP_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
SKP_int32 HarmShapeFIRPacked_Q14;
SKP_int offset_Q10;
SKP_int32 FiltState[ MAX_LPC_ORDER ];
SKP_int32 x_sc_Q10[ MAX_FRAME_LENGTH / NB_SUBFR ];
NSQ->rand_seed = psEncCtrlC->Seed;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
SKP_assert( NSQ->prev_inv_gain_Q16 != 0 );
offset_Q10 = SKP_Silk_Quantization_Offsets_Q10[ psEncCtrlC->sigtype ][ psEncCtrlC->QuantOffsetType ];
if( LSFInterpFactor_Q2 == ( 1 << 2 ) ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
/* Setup pointers to start of sub frame */
NSQ->sLTP_shp_buf_idx = psEncC->frame_length;
NSQ->sLTP_buf_idx = psEncC->frame_length;
pxq = &NSQ->xq[ psEncC->frame_length ];
for( k = 0; k < NB_SUBFR; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
SKP_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
/* Voiced */
lag = psEncCtrlC->pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->frame_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
SKP_assert( start_idx >= 0 );
SKP_assert( start_idx <= psEncC->frame_length - psEncC->predictLPCOrder );
SKP_memset( FiltState, 0, psEncC->predictLPCOrder * sizeof( SKP_int32 ) );
SKP_Silk_MA_Prediction( &NSQ->xq[ start_idx + k * ( psEncC->frame_length >> 2 ) ],
A_Q12, FiltState, sLTP + start_idx, psEncC->frame_length - start_idx, psEncC->predictLPCOrder );
NSQ->rewhite_flag = 1;
NSQ->sLTP_buf_idx = psEncC->frame_length;
}
}
SKP_Silk_nsq_scale_states( NSQ, x, x_sc_Q10, psEncC->subfr_length, sLTP,
sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, psEncCtrlC->pitchL );
SKP_Silk_noise_shape_quantizer( NSQ, psEncCtrlC->sigtype, x_sc_Q10, q, pxq, sLTP_Q16, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder
);
x += psEncC->subfr_length;
q += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Update lagPrev for next frame */
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
/* Save quantized speech and noise shaping signals */
SKP_memcpy( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int16 ) );
SKP_memcpy( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int32 ) );
#ifdef USE_UNQUANTIZED_LSFS
DEBUG_STORE_DATA( xq_unq_lsfs.pcm, NSQ->xq, psEncC->frame_length * sizeof( SKP_int16 ) );
#endif
}
/***********************************/
/* SKP_Silk_noise_shape_quantizer */
/***********************************/
SKP_INLINE void SKP_Silk_noise_shape_quantizer(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
SKP_int sigtype, /* I Signal type */
const SKP_int32 x_sc_Q10[], /* I */
SKP_int8 q[], /* O */
SKP_int16 xq[], /* O */
SKP_int32 sLTP_Q16[], /* I/O LTP state */
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
const SKP_int16 b_Q14[], /* I Long term prediction coefs */
const SKP_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
SKP_int lag, /* I Pitch lag */
SKP_int32 HarmShapeFIRPacked_Q14, /* I */
SKP_int Tilt_Q14, /* I Spectral tilt */
SKP_int32 LF_shp_Q14, /* I */
SKP_int32 Gain_Q16, /* I */
SKP_int Lambda_Q10, /* I */
SKP_int offset_Q10, /* I */
SKP_int length, /* I Input length */
SKP_int shapingLPCOrder, /* I Noise shaping AR filter order */
SKP_int predictLPCOrder /* I Prediction filter order */
)
{
SKP_int i, j;
SKP_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
SKP_int32 n_LF_Q10, r_Q10, q_Q0, q_Q10;
SKP_int32 thr1_Q10, thr2_Q10, thr3_Q10;
SKP_int32 dither, exc_Q10, LPC_exc_Q10, xq_Q10;
SKP_int32 tmp1, tmp2, sLF_AR_shp_Q10;
SKP_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 a_Q12_tmp[ MAX_LPC_ORDER / 2 ], Atmp;
/* Preload LPC coefficients to array on stack. Gives small performance gain */
SKP_memcpy( a_Q12_tmp, a_Q12, predictLPCOrder * sizeof( SKP_int16 ) );
#endif
shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
/* Setup short term AR state */
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
/* Quantization thresholds */
thr1_Q10 = SKP_SUB_RSHIFT32( -1536, Lambda_Q10, 1 );
thr2_Q10 = SKP_SUB_RSHIFT32( -512, Lambda_Q10, 1 );
thr2_Q10 = SKP_ADD_RSHIFT32( thr2_Q10, SKP_SMULBB( offset_Q10, Lambda_Q10 ), 10 );
thr3_Q10 = SKP_ADD_RSHIFT32( 512, Lambda_Q10, 1 );
for( i = 0; i < length; i++ ) {
/* Generate dither */
NSQ->rand_seed = SKP_RAND( NSQ->rand_seed );
/* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
dither = SKP_RSHIFT( NSQ->rand_seed, 31 );
/* Short-term prediction */
SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */
/* check that array starts at 4-byte aligned address */
SKP_assert( ( ( SKP_int64 )( ( SKP_int8* )a_Q12 - ( SKP_int8* )0 ) & 3 ) == 0 );
SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
/* Partially unrolled */
Atmp = a_Q12_tmp[ 0 ]; /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -1 ], Atmp );
Atmp = a_Q12_tmp[ 1 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -3 ], Atmp );
Atmp = a_Q12_tmp[ 2 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -5 ], Atmp );
Atmp = a_Q12_tmp[ 3 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -7 ], Atmp );
Atmp = a_Q12_tmp[ 4 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -9 ], Atmp );
for( j = 10; j < predictLPCOrder; j += 2 ) {
Atmp = a_Q12_tmp[ j >> 1 ]; /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -j - 1 ], Atmp );
}
#else
/* Partially unrolled */
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
for( j = 10; j < predictLPCOrder; j ++ ) {
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
}
#endif
/* Long-term prediction */
if( sigtype == SIG_TYPE_VOICED ) {
/* Unrolled loop */
LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++;
} else {
LTP_pred_Q14 = 0;
}
/* Noise shape feedback */
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
tmp2 = psLPC_Q14[ 0 ];
tmp1 = NSQ->sAR2_Q14[ 0 ];
NSQ->sAR2_Q14[ 0 ] = tmp2;
n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
for( j = 2; j < shapingLPCOrder; j += 2 ) {
tmp2 = NSQ->sAR2_Q14[ j - 1 ];
NSQ->sAR2_Q14[ j - 1 ] = tmp1;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
tmp1 = NSQ->sAR2_Q14[ j + 0 ];
NSQ->sAR2_Q14[ j + 0 ] = tmp2;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
}
NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 );
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 );
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 );
SKP_assert( lag > 0 || sigtype == SIG_TYPE_UNVOICED );
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 );
shp_lag_ptr++;
} else {
n_LTP_Q14 = 0;
}
/* Input minus prediction plus noise feedback */
//r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP;
tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */
tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */
tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */
tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */
r_Q10 = SKP_SUB32( x_sc_Q10[ i ], tmp1 );
/* Flip sign depending on dither */
r_Q10 = ( r_Q10 ^ dither ) - dither;
r_Q10 = SKP_SUB32( r_Q10, offset_Q10 );
r_Q10 = SKP_LIMIT_32( r_Q10, -(64 << 10), 64 << 10 );
/* Quantize */
q_Q0 = 0;
q_Q10 = 0;
if( r_Q10 < thr2_Q10 ) {
if( r_Q10 < thr1_Q10 ) {
q_Q0 = SKP_RSHIFT_ROUND( SKP_ADD_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
} else {
q_Q0 = -1;
q_Q10 = -1024;
}
} else {
if( r_Q10 > thr3_Q10 ) {
q_Q0 = SKP_RSHIFT_ROUND( SKP_SUB_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
}
}
q[ i ] = ( SKP_int8 )q_Q0; /* No saturation needed because max is 64 */
/* Excitation */
exc_Q10 = SKP_ADD32( q_Q10, offset_Q10 );
exc_Q10 = ( exc_Q10 ^ dither ) - dither;
/* Add predictions */
LPC_exc_Q10 = SKP_ADD32( exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );
xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Scale XQ back to normal level before saving */
xq[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( xq_Q10, Gain_Q16 ), 10 ) );
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = SKP_LSHIFT( xq_Q10, 4 );
sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 );
NSQ->sLF_AR_shp_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 );
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 );
sLTP_Q16[ NSQ->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 );
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Make dither dependent on quantized signal */
NSQ->rand_seed += q[ i ];
}
/* Update LPC synth buffer */
SKP_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
}
SKP_INLINE void SKP_Silk_nsq_scale_states(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
const SKP_int16 x[], /* I input in Q0 */
SKP_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
SKP_int subfr_length, /* I length of input */
const SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
SKP_int subfr, /* I subframe number */
const SKP_int LTP_scale_Q14, /* I */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int pitchL[ NB_SUBFR ] /* I */
)
{
SKP_int i, lag;
SKP_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
inv_gain_Q16 = SKP_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 );
inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX );
lag = pitchL[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 );
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
SKP_assert( i < MAX_FRAME_LENGTH );
sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - subfr_length * NB_SUBFR; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
}
/* Scale long-term prediction state */
if( NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
}
}
NSQ->sLF_AR_shp_Q12 = SKP_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q12 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
NSQ->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
}
/* Scale input */
for( i = 0; i < subfr_length; i++ ) {
x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( SKP_int16 )inv_gain_Q16 ), 6 );
}
/* save inv_gain */
SKP_assert( inv_gain_Q16 != 0 );
NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
}

View File

@ -0,0 +1,733 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
typedef struct {
SKP_int32 RandState[ DECISION_DELAY ];
SKP_int32 Q_Q10[ DECISION_DELAY ];
SKP_int32 Xq_Q10[ DECISION_DELAY ];
SKP_int32 Pred_Q16[ DECISION_DELAY ];
SKP_int32 Shape_Q10[ DECISION_DELAY ];
SKP_int32 Gain_Q16[ DECISION_DELAY ];
SKP_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
SKP_int32 sLPC_Q14[ MAX_FRAME_LENGTH / NB_SUBFR + NSQ_LPC_BUF_LENGTH ];
SKP_int32 LF_AR_Q12;
SKP_int32 Seed;
SKP_int32 SeedInit;
SKP_int32 RD_Q10;
} NSQ_del_dec_struct;
typedef struct {
SKP_int32 Q_Q10;
SKP_int32 RD_Q10;
SKP_int32 xq_Q14;
SKP_int32 LF_AR_Q12;
SKP_int32 sLTP_shp_Q10;
SKP_int32 LPC_exc_Q16;
} NSQ_sample_struct;
SKP_INLINE void SKP_Silk_copy_del_dec_state(
NSQ_del_dec_struct *DD_dst, /* I Dst del dec state */
NSQ_del_dec_struct *DD_src, /* I Src del dec state */
SKP_int LPC_state_idx /* I Index to LPC buffer */
);
SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const SKP_int16 x[], /* I Input in Q0 */
SKP_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
SKP_int subfr_length, /* I Length of input */
const SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
SKP_int subfr, /* I Subframe number */
SKP_int nStatesDelayedDecision, /* I Number of del dec states */
SKP_int smpl_buf_idx, /* I Index to newest samples in buffers */
const SKP_int LTP_scale_Q14, /* I LTP state scaling */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int pitchL[ NB_SUBFR ] /* I Pitch lag */
);
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
SKP_int sigtype, /* I Signal type */
const SKP_int32 x_Q10[], /* I */
SKP_int8 q[], /* O */
SKP_int16 xq[], /* O */
SKP_int32 sLTP_Q16[], /* I/O LTP filter state */
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
const SKP_int16 b_Q14[], /* I Long term prediction coefs */
const SKP_int16 AR_shp_Q13[], /* I Noise shaping coefs */
SKP_int lag, /* I Pitch lag */
SKP_int32 HarmShapeFIRPacked_Q14, /* I */
SKP_int Tilt_Q14, /* I Spectral tilt */
SKP_int32 LF_shp_Q14, /* I */
SKP_int32 Gain_Q16, /* I */
SKP_int Lambda_Q10, /* I */
SKP_int offset_Q10, /* I */
SKP_int length, /* I Input length */
SKP_int subfr, /* I Subframe number */
SKP_int shapingLPCOrder, /* I Shaping LPC filter order */
SKP_int predictLPCOrder, /* I Prediction filter order */
SKP_int warping_Q16, /* I */
SKP_int nStatesDelayedDecision, /* I Number of states in decision tree */
SKP_int *smpl_buf_idx, /* I Index to newest samples in buffers */
SKP_int decisionDelay /* I */
);
void SKP_Silk_NSQ_del_dec(
SKP_Silk_encoder_state *psEncC, /* I/O Encoder State */
SKP_Silk_encoder_control *psEncCtrlC, /* I Encoder Control */
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
const SKP_int16 x[], /* I Prefiltered input signal */
SKP_int8 q[], /* O Quantized pulse signal */
const SKP_int LSFInterpFactor_Q2, /* I LSF interpolation factor in Q2 */
const SKP_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ], /* I LT prediction coefs */
const SKP_int16 AR2_Q13[ NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */
const SKP_int HarmShapeGain_Q14[ NB_SUBFR ], /* I */
const SKP_int Tilt_Q14[ NB_SUBFR ], /* I Spectral tilt */
const SKP_int32 LF_shp_Q14[ NB_SUBFR ], /* I */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int Lambda_Q10, /* I */
const SKP_int LTP_scale_Q14 /* I LTP state scaling */
)
{
SKP_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
SKP_int last_smple_idx, smpl_buf_idx, decisionDelay, subfr_length;
const SKP_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
SKP_int16 *pxq;
SKP_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ];
SKP_int16 sLTP[ 2 * MAX_FRAME_LENGTH ];
SKP_int32 HarmShapeFIRPacked_Q14;
SKP_int offset_Q10;
SKP_int32 FiltState[ MAX_LPC_ORDER ], RDmin_Q10;
SKP_int32 x_sc_Q10[ MAX_FRAME_LENGTH / NB_SUBFR ];
NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ];
NSQ_del_dec_struct *psDD;
subfr_length = psEncC->frame_length / NB_SUBFR;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
SKP_assert( NSQ->prev_inv_gain_Q16 != 0 );
/* Initialize delayed decision states */
SKP_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psDD->Seed = ( k + psEncCtrlC->Seed ) & 3;
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q12 = NSQ->sLF_AR_shp_Q12;
psDD->Shape_Q10[ 0 ] = NSQ->sLTP_shp_Q10[ psEncC->frame_length - 1 ];
SKP_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
SKP_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
}
offset_Q10 = SKP_Silk_Quantization_Offsets_Q10[ psEncCtrlC->sigtype ][ psEncCtrlC->QuantOffsetType ];
smpl_buf_idx = 0; /* index of oldest samples */
decisionDelay = SKP_min_int( DECISION_DELAY, subfr_length );
/* For voiced frames limit the decision delay to lower than the pitch lag */
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
for( k = 0; k < NB_SUBFR; k++ ) {
decisionDelay = SKP_min_int( decisionDelay, psEncCtrlC->pitchL[ k ] - LTP_ORDER / 2 - 1 );
}
} else {
if( lag > 0 ) {
decisionDelay = SKP_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
}
}
if( LSFInterpFactor_Q2 == ( 1 << 2 ) ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
/* Setup pointers to start of sub frame */
pxq = &NSQ->xq[ psEncC->frame_length ];
NSQ->sLTP_shp_buf_idx = psEncC->frame_length;
NSQ->sLTP_buf_idx = psEncC->frame_length;
subfr = 0;
for( k = 0; k < NB_SUBFR; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
SKP_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
/* Voiced */
lag = psEncCtrlC->pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
if( k == 2 ) {
/* RESET DELAYED DECISIONS */
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ i ].RD_Q10;
Winner_ind = i;
}
}
for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) {
if( i != Winner_ind ) {
psDelDec[ i ].RD_Q10 += ( SKP_int32_MAX >> 4 );
SKP_assert( psDelDec[ i ].RD_Q10 >= 0 );
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ],
psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
}
subfr = 0;
}
/* Rewhiten with new A coefs */
start_idx = psEncC->frame_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
SKP_assert( start_idx >= 0 );
SKP_assert( start_idx <= psEncC->frame_length - psEncC->predictLPCOrder );
SKP_memset( FiltState, 0, psEncC->predictLPCOrder * sizeof( SKP_int32 ) );
SKP_Silk_MA_Prediction( &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, FiltState, sLTP + start_idx, psEncC->frame_length - start_idx, psEncC->predictLPCOrder );
NSQ->sLTP_buf_idx = psEncC->frame_length;
NSQ->rewhite_flag = 1;
}
}
SKP_Silk_nsq_del_dec_scale_states( NSQ, psDelDec, x, x_sc_Q10,
subfr_length, sLTP, sLTP_Q16, k, psEncC->nStatesDelayedDecision, smpl_buf_idx,
LTP_scale_Q14, Gains_Q16, psEncCtrlC->pitchL );
SKP_Silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psEncCtrlC->sigtype, x_sc_Q10, q, pxq, sLTP_Q16,
A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ],
Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, psEncC->predictLPCOrder,
psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
x += psEncC->subfr_length;
q += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ k ].RD_Q10;
Winner_ind = k;
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
psEncCtrlC->Seed = psDD->SeedInit;
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay + i ] = psDD->Pred_Q16[ last_smple_idx ];
}
SKP_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
SKP_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
/* Update states */
NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
/* Save quantized speech and noise shaping signals */
SKP_memcpy( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int16 ) );
SKP_memcpy( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int32 ) );
#ifdef USE_UNQUANTIZED_LSFS
DEBUG_STORE_DATA( xq_unq_lsfs.pcm, NSQ->xq, psEncC->frame_length * sizeof( SKP_int16 ) );
#endif
}
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
SKP_int sigtype, /* I Signal type */
const SKP_int32 x_Q10[], /* I */
SKP_int8 q[], /* O */
SKP_int16 xq[], /* O */
SKP_int32 sLTP_Q16[], /* I/O LTP filter state */
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
const SKP_int16 b_Q14[], /* I Long term prediction coefs */
const SKP_int16 AR_shp_Q13[], /* I Noise shaping coefs */
SKP_int lag, /* I Pitch lag */
SKP_int32 HarmShapeFIRPacked_Q14, /* I */
SKP_int Tilt_Q14, /* I Spectral tilt */
SKP_int32 LF_shp_Q14, /* I */
SKP_int32 Gain_Q16, /* I */
SKP_int Lambda_Q10, /* I */
SKP_int offset_Q10, /* I */
SKP_int length, /* I Input length */
SKP_int subfr, /* I Subframe number */
SKP_int shapingLPCOrder, /* I Shaping LPC filter order */
SKP_int predictLPCOrder, /* I Prediction filter order */
SKP_int warping_Q16, /* I */
SKP_int nStatesDelayedDecision, /* I Number of states in decision tree */
SKP_int *smpl_buf_idx, /* I Index to newest samples in buffers */
SKP_int decisionDelay /* I */
)
{
SKP_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
SKP_int32 Winner_rand_state;
SKP_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
SKP_int32 n_LF_Q10, r_Q10, rr_Q20, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
SKP_int32 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10;
SKP_int32 tmp1, tmp2, sLF_AR_shp_Q10;
SKP_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 a_Q12_tmp[ MAX_LPC_ORDER / 2 ], Atmp;
/* Preload LPC coeficients to array on stack. Gives small performance gain */
SKP_memcpy( a_Q12_tmp, a_Q12, predictLPCOrder * sizeof( SKP_int16 ) );
#endif
shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */
/* Long-term prediction */
if( sigtype == SIG_TYPE_VOICED ) {
/* Unrolled loop */
LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++;
} else {
LTP_pred_Q14 = 0;
}
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 );
shp_lag_ptr++;
} else {
n_LTP_Q14 = 0;
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
/* Delayed decision state */
psDD = &psDelDec[ k ];
/* Sample state */
psSS = psSampleState[ k ];
/* Generate dither */
psDD->Seed = SKP_RAND( psDD->Seed );
/* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
dither = SKP_RSHIFT( psDD->Seed, 31 );
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */
SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */
SKP_assert( ( ( ( int )( ( char* )( a_Q12 ) - ( ( char* ) 0 ) ) ) & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* Partially unrolled */
Atmp = a_Q12_tmp[ 0 ]; /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -1 ], Atmp );
Atmp = a_Q12_tmp[ 1 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -3 ], Atmp );
Atmp = a_Q12_tmp[ 2 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -5 ], Atmp );
Atmp = a_Q12_tmp[ 3 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -7 ], Atmp );
Atmp = a_Q12_tmp[ 4 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -9 ], Atmp );
for( j = 10; j < predictLPCOrder; j += 2 ) {
Atmp = a_Q12_tmp[ j >> 1 ]; /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -j - 1 ], Atmp );
}
#else
/* Partially unrolled */
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
for( j = 10; j < predictLPCOrder; j ++ ) {
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
}
#endif
/* Noise shape feedback */
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
tmp2 = SKP_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
/* Loop over allpass sections */
for( j = 2; j < shapingLPCOrder; j += 2 ) {
/* Output of allpass section */
tmp2 = SKP_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
psDD->sAR2_Q14[ j - 1 ] = tmp1;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
/* Output of allpass section */
tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ j + 0 ] = tmp2;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
}
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psDD->LF_AR_Q12, Tilt_Q14 );
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 );
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 );
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */
tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */
tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */
tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */
r_Q10 = SKP_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
r_Q10 = ( r_Q10 ^ dither ) - dither;
r_Q10 = SKP_SUB32( r_Q10, offset_Q10 );
r_Q10 = SKP_LIMIT_32( r_Q10, -(64 << 10), 64 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
if( r_Q10 < -1536 ) {
q1_Q10 = SKP_LSHIFT( SKP_RSHIFT_ROUND( r_Q10, 10 ), 10 );
r_Q10 = SKP_SUB32( r_Q10, q1_Q10 );
rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( SKP_MUL( -SKP_ADD32( q1_Q10, offset_Q10 ), Lambda_Q10 ), r_Q10, r_Q10 ), 10 );
rd2_Q10 = SKP_ADD32( rd1_Q10, 1024 );
rd2_Q10 = SKP_SUB32( rd2_Q10, SKP_ADD_LSHIFT32( Lambda_Q10, r_Q10, 1 ) );
q2_Q10 = SKP_ADD32( q1_Q10, 1024 );
} else if( r_Q10 > 512 ) {
q1_Q10 = SKP_LSHIFT( SKP_RSHIFT_ROUND( r_Q10, 10 ), 10 );
r_Q10 = SKP_SUB32( r_Q10, q1_Q10 );
rd1_Q10 = SKP_RSHIFT( SKP_SMLABB( SKP_MUL( SKP_ADD32( q1_Q10, offset_Q10 ), Lambda_Q10 ), r_Q10, r_Q10 ), 10 );
rd2_Q10 = SKP_ADD32( rd1_Q10, 1024 );
rd2_Q10 = SKP_SUB32( rd2_Q10, SKP_SUB_LSHIFT32( Lambda_Q10, r_Q10, 1 ) );
q2_Q10 = SKP_SUB32( q1_Q10, 1024 );
} else { /* r_Q10 >= -1536 && q1_Q10 <= 512 */
rr_Q20 = SKP_SMULBB( offset_Q10, Lambda_Q10 );
rd2_Q10 = SKP_RSHIFT( SKP_SMLABB( rr_Q20, r_Q10, r_Q10 ), 10 );
rd1_Q10 = SKP_ADD32( rd2_Q10, 1024 );
rd1_Q10 = SKP_ADD32( rd1_Q10, SKP_SUB_RSHIFT32( SKP_ADD_LSHIFT32( Lambda_Q10, r_Q10, 1 ), rr_Q20, 9 ) );
q1_Q10 = -1024;
q2_Q10 = 0;
}
if( rd1_Q10 < rd2_Q10 ) {
psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 0 ].Q_Q10 = q1_Q10;
psSS[ 1 ].Q_Q10 = q2_Q10;
} else {
psSS[ 0 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 1 ].RD_Q10 = SKP_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 0 ].Q_Q10 = q2_Q10;
psSS[ 1 ].Q_Q10 = q1_Q10;
}
/* Update states for best quantization */
/* Quantized excitation */
exc_Q10 = SKP_ADD32( offset_Q10, psSS[ 0 ].Q_Q10 );
exc_Q10 = ( exc_Q10 ^ dither ) - dither;
/* Add predictions */
LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 );
xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Update states */
sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 );
psSS[ 0 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 );
psSS[ 0 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 );
psSS[ 0 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 );
psSS[ 0 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 );
/* Update states for second best quantization */
/* Quantized excitation */
exc_Q10 = SKP_ADD32( offset_Q10, psSS[ 1 ].Q_Q10 );
exc_Q10 = ( exc_Q10 ^ dither ) - dither;
/* Add predictions */
LPC_exc_Q10 = exc_Q10 + SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 );
xq_Q10 = SKP_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
/* Update states */
sLF_AR_shp_Q10 = SKP_SUB32( xq_Q10, n_AR_Q10 );
psSS[ 1 ].sLTP_shp_Q10 = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 );
psSS[ 1 ].LF_AR_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 );
psSS[ 1 ].xq_Q14 = SKP_LSHIFT( xq_Q10, 4 );
psSS[ 1 ].LPC_exc_Q16 = SKP_LSHIFT( LPC_exc_Q10, 6 );
}
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK; /* Index to newest samples */
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK; /* Index to decisionDelay old samples */
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
Winner_ind = k;
}
}
/* Increase RD values of expired states */
Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
for( k = 0; k < nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
psSampleState[ k ][ 0 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 0 ].RD_Q10, ( SKP_int32_MAX >> 4 ) );
psSampleState[ k ][ 1 ].RD_Q10 = SKP_ADD32( psSampleState[ k ][ 1 ].RD_Q10, ( SKP_int32_MAX >> 4 ) );
SKP_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
}
}
/* Find worst in first set and best in second set */
RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10;
RDmax_ind = 0;
RDmin_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
/* find worst in first set */
if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
RDmax_ind = k;
}
/* find best in second set */
if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10;
RDmin_ind = k;
}
}
/* Replace a state if best from second set outperforms worst in first set */
if( RDmin_Q10 < RDmax_Q10 ) {
SKP_Silk_copy_del_dec_state( &psDelDec[ RDmax_ind ], &psDelDec[ RDmin_ind ], i );
SKP_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
}
/* Write samples from winner to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
if( subfr > 0 || i >= decisionDelay ) {
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
xq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ];
sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q16[ last_smple_idx ];
}
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Update states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q12 = psSS->LF_AR_Q12;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q10[ *smpl_buf_idx ] = SKP_RSHIFT( psSS->xq_Q14, 4 );
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
psDD->Pred_Q16[ *smpl_buf_idx ] = psSS->LPC_exc_Q16;
psDD->Shape_Q10[ *smpl_buf_idx ] = psSS->sLTP_shp_Q10;
psDD->Seed = SKP_ADD_RSHIFT32( psDD->Seed, psSS->Q_Q10, 10 );
psDD->RandState[ *smpl_buf_idx ] = psDD->Seed;
psDD->RD_Q10 = psSS->RD_Q10;
psDD->Gain_Q16[ *smpl_buf_idx ] = Gain_Q16;
}
}
/* Update LPC states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
SKP_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
}
}
SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const SKP_int16 x[], /* I Input in Q0 */
SKP_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
SKP_int subfr_length, /* I Length of input */
const SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
SKP_int subfr, /* I Subframe number */
SKP_int nStatesDelayedDecision, /* I Number of del dec states */
SKP_int smpl_buf_idx, /* I Index to newest samples in buffers */
const SKP_int LTP_scale_Q14, /* I LTP state scaling */
const SKP_int32 Gains_Q16[ NB_SUBFR ], /* I */
const SKP_int pitchL[ NB_SUBFR ] /* I Pitch lag */
)
{
SKP_int i, k, lag;
SKP_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
NSQ_del_dec_struct *psDD;
inv_gain_Q16 = SKP_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 );
inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX );
lag = pitchL[ subfr ];
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 );
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
SKP_assert( i < MAX_FRAME_LENGTH );
sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - subfr_length * NB_SUBFR; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
}
/* Scale long-term prediction state */
if( NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
}
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
/* Scale scalar states */
psDD->LF_AR_Q12 = SKP_SMULWW( gain_adj_Q16, psDD->LF_AR_Q12 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
psDD->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
psDD->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
}
for( i = 0; i < DECISION_DELAY; i++ ) {
psDD->Pred_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Pred_Q16[ i ] );
psDD->Shape_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Shape_Q10[ i ] );
}
}
}
/* Scale input */
for( i = 0; i < subfr_length; i++ ) {
x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( SKP_int16 )inv_gain_Q16 ), 6 );
}
/* save inv_gain */
SKP_assert( inv_gain_Q16 != 0 );
NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
}
SKP_INLINE void SKP_Silk_copy_del_dec_state(
NSQ_del_dec_struct *DD_dst, /* I Dst del dec state */
NSQ_del_dec_struct *DD_src, /* I Src del dec state */
SKP_int LPC_state_idx /* I Index to LPC buffer */
)
{
SKP_memcpy( DD_dst->RandState, DD_src->RandState, sizeof( DD_src->RandState ) );
SKP_memcpy( DD_dst->Q_Q10, DD_src->Q_Q10, sizeof( DD_src->Q_Q10 ) );
SKP_memcpy( DD_dst->Pred_Q16, DD_src->Pred_Q16, sizeof( DD_src->Pred_Q16 ) );
SKP_memcpy( DD_dst->Shape_Q10, DD_src->Shape_Q10, sizeof( DD_src->Shape_Q10 ) );
SKP_memcpy( DD_dst->Xq_Q10, DD_src->Xq_Q10, sizeof( DD_src->Xq_Q10 ) );
SKP_memcpy( DD_dst->sAR2_Q14, DD_src->sAR2_Q14, sizeof( DD_src->sAR2_Q14 ) );
SKP_memcpy( &DD_dst->sLPC_Q14[ LPC_state_idx ], &DD_src->sLPC_Q14[ LPC_state_idx ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
DD_dst->LF_AR_Q12 = DD_src->LF_AR_Q12;
DD_dst->Seed = DD_src->Seed;
DD_dst->SeedInit = DD_src->SeedInit;
DD_dst->RD_Q10 = DD_src->RD_Q10;
}

View File

@ -0,0 +1,418 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
#include "SKP_Silk_PLC.h"
#define NB_ATT 2
static const SKP_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
static const SKP_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
static const SKP_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
void SKP_Silk_PLC_Reset(
SKP_Silk_decoder_state *psDec /* I/O Decoder state */
)
{
psDec->sPLC.pitchL_Q8 = SKP_RSHIFT( psDec->frame_length, 1 );
}
void SKP_Silk_PLC(
SKP_Silk_decoder_state *psDec, /* I Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I Decoder control */
SKP_int16 signal[], /* O Concealed signal */
SKP_int length, /* I length of residual */
SKP_int lost /* I Loss flag */
)
{
/* PLC control function */
if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
SKP_Silk_PLC_Reset( psDec );
psDec->sPLC.fs_kHz = psDec->fs_kHz;
}
if( lost ) {
/****************************/
/* Generate Signal */
/****************************/
SKP_Silk_PLC_conceal( psDec, psDecCtrl, signal, length );
psDec->lossCnt++;
} else {
/****************************/
/* Update state */
/****************************/
SKP_Silk_PLC_update( psDec, psDecCtrl, signal, length );
}
}
/**************************************************/
/* Update state of PLC */
/**************************************************/
void SKP_Silk_PLC_update(
SKP_Silk_decoder_state *psDec, /* (I/O) Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* (I/O) Decoder control */
SKP_int16 signal[],
SKP_int length
)
{
SKP_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
SKP_int i, j;
SKP_Silk_PLC_struct *psPLC;
psPLC = &psDec->sPLC;
/* Update parameters used in case of packet loss */
psDec->prev_sigtype = psDecCtrl->sigtype;
LTP_Gain_Q14 = 0;
if( psDecCtrl->sigtype == SIG_TYPE_VOICED ) {
/* Find the parameters for the last subframe which contains a pitch pulse */
for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ NB_SUBFR - 1 ]; j++ ) {
temp_LTP_Gain_Q14 = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( NB_SUBFR - 1 - j ) * LTP_ORDER + i ];
}
if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
LTP_Gain_Q14 = temp_LTP_Gain_Q14;
SKP_memcpy( psPLC->LTPCoef_Q14,
&psDecCtrl->LTPCoef_Q14[ SKP_SMULBB( NB_SUBFR - 1 - j, LTP_ORDER ) ],
LTP_ORDER * sizeof( SKP_int16 ) );
psPLC->pitchL_Q8 = SKP_LSHIFT( psDecCtrl->pitchL[ NB_SUBFR - 1 - j ], 8 );
}
}
#if USE_SINGLE_TAP
SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( SKP_int16 ) );
psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
#endif
/* Limit LT coefs */
if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
SKP_int scale_Q10;
SKP_int32 tmp;
tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
scale_Q10 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) );
for( i = 0; i < LTP_ORDER; i++ ) {
psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
}
} else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
SKP_int scale_Q14;
SKP_int32 tmp;
tmp = SKP_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
scale_Q14 = SKP_DIV32( tmp, SKP_max( LTP_Gain_Q14, 1 ) );
for( i = 0; i < LTP_ORDER; i++ ) {
psPLC->LTPCoef_Q14[ i ] = SKP_RSHIFT( SKP_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
}
}
} else {
psPLC->pitchL_Q8 = SKP_LSHIFT( SKP_SMULBB( psDec->fs_kHz, 18 ), 8 );
SKP_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( SKP_int16 ));
}
/* Save LPC coeficients */
SKP_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( SKP_int16 ) );
psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
/* Save Gains */
SKP_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, NB_SUBFR * sizeof( SKP_int32 ) );
}
void SKP_Silk_PLC_conceal(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* O concealed signal */
SKP_int length /* I length of residual */
)
{
SKP_int i, j, k;
SKP_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr;
SKP_int16 rand_scale_Q14;
union {
SKP_int16 as_int16[ MAX_LPC_ORDER ];
SKP_int32 as_int32[ MAX_LPC_ORDER / 2 ];
} A_Q12_tmp;
SKP_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15;
SKP_int lag, idx, sLTP_buf_idx, shift1, shift2;
SKP_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
SKP_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14;
SKP_Silk_PLC_struct *psPLC;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 Atmp;
#endif
psPLC = &psDec->sPLC;
/* Update LTP buffer */
SKP_memcpy( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->frame_length * sizeof( SKP_int32 ) );
/* LPC concealment. Apply BWE to previous LPC */
SKP_Silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, BWE_COEF_Q16 );
/* Find random noise component */
/* Scale previous excitation signal */
exc_buf_ptr = exc_buf;
for( k = ( NB_SUBFR >> 1 ); k < NB_SUBFR; k++ ) {
for( i = 0; i < psDec->subfr_length; i++ ) {
exc_buf_ptr[ i ] = ( SKP_int16 )SKP_RSHIFT(
SKP_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 );
}
exc_buf_ptr += psDec->subfr_length;
}
/* Find the subframe with lowest energy of the last two and use that as random noise generator */
SKP_Silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length );
SKP_Silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length );
if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy2, shift1 ) ) {
/* First sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ];
} else {
/* Second sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ];
}
/* Setup Gain to random noise component */
B_Q14 = psPLC->LTPCoef_Q14;
rand_scale_Q14 = psPLC->randScale_Q14;
/* Setup attenuation gains */
harm_Gain_Q15 = HARM_ATT_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ];
if( psDec->prev_sigtype == SIG_TYPE_VOICED ) {
rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ];
} else {
rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ SKP_min_int( NB_ATT - 1, psDec->lossCnt ) ];
}
/* First Lost frame */
if( psDec->lossCnt == 0 ) {
rand_scale_Q14 = (1 << 14 );
/* Reduce random noise Gain for voiced frames */
if( psDec->prev_sigtype == SIG_TYPE_VOICED ) {
for( i = 0; i < LTP_ORDER; i++ ) {
rand_scale_Q14 -= B_Q14[ i ];
}
rand_scale_Q14 = SKP_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
rand_scale_Q14 = ( SKP_int16 )SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
}
/* Reduce random noise for unvoiced frames with high LPC gain */
if( psDec->prev_sigtype == SIG_TYPE_UNVOICED ) {
SKP_int32 invGain_Q30, down_scale_Q30;
SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order );
down_scale_Q30 = SKP_min_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
down_scale_Q30 = SKP_max_32( SKP_RSHIFT( ( 1 << 30 ), LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
down_scale_Q30 = SKP_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
rand_Gain_Q15 = SKP_RSHIFT( SKP_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
}
}
rand_seed = psPLC->rand_seed;
lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
sLTP_buf_idx = psDec->frame_length;
/***************************/
/* LTP synthesis filtering */
/***************************/
sig_Q10_ptr = sig_Q10;
for( k = 0; k < NB_SUBFR; k++ ) {
/* Setup pointer */
pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < psDec->subfr_length; i++ ) {
rand_seed = SKP_RAND( rand_seed );
idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
/* Unrolled loop */
LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
pred_lag_ptr++;
/* Generate LPC residual */
LPC_exc_Q10 = SKP_LSHIFT( SKP_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */
LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */
/* Update states */
psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 );
sLTP_buf_idx++;
/* Save LPC residual */
sig_Q10_ptr[ i ] = LPC_exc_Q10;
}
sig_Q10_ptr += psDec->subfr_length;
/* Gradually reduce LTP gain */
for( j = 0; j < LTP_ORDER; j++ ) {
B_Q14[ j ] = SKP_RSHIFT( SKP_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
}
/* Gradually reduce excitation gain */
rand_scale_Q14 = SKP_RSHIFT( SKP_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
/* Slowly increase pitch lag */
psPLC->pitchL_Q8 += SKP_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
psPLC->pitchL_Q8 = SKP_min_32( psPLC->pitchL_Q8, SKP_LSHIFT( SKP_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
}
/***************************/
/* LPC synthesis filtering */
/***************************/
sig_Q10_ptr = sig_Q10;
/* Preload LPC coeficients to array on stack. Gives small performance gain */
SKP_memcpy( A_Q12_tmp.as_int16, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( SKP_int16 ) );
SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
for( k = 0; k < NB_SUBFR; k++ ) {
for( i = 0; i < psDec->subfr_length; i++ ){
/* partly unrolled */
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
Atmp = A_Q12_tmp.as_int32[ 0 ]; /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], Atmp );
Atmp = A_Q12_tmp.as_int32[ 1 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], Atmp );
Atmp = A_Q12_tmp.as_int32[ 2 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], Atmp );
Atmp = A_Q12_tmp.as_int32[ 3 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], Atmp );
Atmp = A_Q12_tmp.as_int32[ 4 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], Atmp );
for( j = 10 ; j < psDec->LPC_order ; j+=2 ) {
Atmp = A_Q12_tmp.as_int32[ j / 2 ];
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 - j ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 - j ], Atmp );
}
#else
LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp.as_int16[ 0 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp.as_int16[ 1 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp.as_int16[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp.as_int16[ 3 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp.as_int16[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp.as_int16[ 5 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp.as_int16[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp.as_int16[ 7 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp.as_int16[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp.as_int16[ 9 ] );
for( j = 10; j < psDec->LPC_order; j++ ) {
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp.as_int16[ j ] );
}
#endif
/* Add prediction to LPC residual */
sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 );
/* Update states */
psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT( sig_Q10_ptr[ i ], 4 );
}
sig_Q10_ptr += psDec->subfr_length;
/* Update LPC filter state */
SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( SKP_int32 ) );
}
/* Scale with Gain */
for( i = 0; i < psDec->frame_length; i++ ) {
signal[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ NB_SUBFR - 1 ] ), 10 ) );
}
/**************************************/
/* Update states */
/**************************************/
psPLC->rand_seed = rand_seed;
psPLC->randScale_Q14 = rand_scale_Q14;
for( i = 0; i < NB_SUBFR; i++ ) {
psDecCtrl->pitchL[ i ] = lag;
}
}
/* Glues concealed frames with new good recieved frames */
void SKP_Silk_PLC_glue_frames(
SKP_Silk_decoder_state *psDec, /* I/O decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* I/O signal */
SKP_int length /* I length of residual */
)
{
SKP_int i, energy_shift;
SKP_int32 energy;
SKP_Silk_PLC_struct *psPLC;
psPLC = &psDec->sPLC;
if( psDec->lossCnt ) {
/* Calculate energy in concealed residual */
SKP_Silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, signal, length );
psPLC->last_frame_lost = 1;
} else {
if( psDec->sPLC.last_frame_lost ) {
/* Calculate residual in decoded signal if last frame was lost */
SKP_Silk_sum_sqr_shift( &energy, &energy_shift, signal, length );
/* Normalize energies */
if( energy_shift > psPLC->conc_energy_shift ) {
psPLC->conc_energy = SKP_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
} else if( energy_shift < psPLC->conc_energy_shift ) {
energy = SKP_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
}
/* Fade in the energy difference */
if( energy > psPLC->conc_energy ) {
SKP_int32 frac_Q24, LZ;
SKP_int32 gain_Q12, slope_Q12;
LZ = SKP_Silk_CLZ32( psPLC->conc_energy );
LZ = LZ - 1;
psPLC->conc_energy = SKP_LSHIFT( psPLC->conc_energy, LZ );
energy = SKP_RSHIFT( energy, SKP_max_32( 24 - LZ, 0 ) );
frac_Q24 = SKP_DIV32( psPLC->conc_energy, SKP_max( energy, 1 ) );
gain_Q12 = SKP_Silk_SQRT_APPROX( frac_Q24 );
slope_Q12 = SKP_DIV32_16( ( 1 << 12 ) - gain_Q12, length );
for( i = 0; i < length; i++ ) {
signal[ i ] = SKP_RSHIFT( SKP_MUL( gain_Q12, signal[ i ] ), 12 );
gain_Q12 += slope_Q12;
gain_Q12 = SKP_min( gain_Q12, ( 1 << 12 ) );
}
}
}
psPLC->last_frame_lost = 0;
}
}

View File

@ -0,0 +1,79 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_PLC_FIX_H
#define SKP_SILK_PLC_FIX_H
#include "SKP_Silk_main.h"
#define BWE_COEF_Q16 64880 /* 0.99 in Q16 */
#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */
#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */
#define MAX_PITCH_LAG_MS 18
#define SA_THRES_Q8 50
#define USE_SINGLE_TAP 1
#define RAND_BUF_SIZE 128
#define RAND_BUF_MASK (RAND_BUF_SIZE - 1)
#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */
#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */
#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */
void SKP_Silk_PLC_Reset(
SKP_Silk_decoder_state *psDec /* I/O Decoder state */
);
void SKP_Silk_PLC(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* I/O signal */
SKP_int length, /* I length of residual */
SKP_int lost /* I Loss flag */
);
void SKP_Silk_PLC_update(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[],
SKP_int length
);
void SKP_Silk_PLC_conceal(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* O LPC residual signal */
SKP_int length /* I length of signal */
);
void SKP_Silk_PLC_glue_frames(
SKP_Silk_decoder_state *psDec, /* I/O decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int16 signal[], /* I/O signal */
SKP_int length /* I length of signal */
);
#endif

View File

@ -0,0 +1,663 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef _SKP_SILK_SIGPROC_FIX_H_
#define _SKP_SILK_SIGPROC_FIX_H_
#ifdef __cplusplus
extern "C"
{
#endif
#define SKP_Silk_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
#define SKP_Silk_MAX_CORRELATION_LENGTH 640 /* max input length to the correlation */
#include "SKP_Silk_typedef.h"
#include <string.h>
#include <stdlib.h> /* for abs() */
#include "SKP_Silk_resampler_structs.h"
#ifndef NO_ASM
# if defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__) || defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5T__)
# define EMBEDDED_ARM 4
# define EMBEDDED_ARMv4
# include "SKP_Silk_macros_arm.h"
# elif defined (__ARM_ARCH_5TE__) || defined (__ARM_ARCH_5TEJ__)
# define EMBEDDED_ARM 5
# define EMBEDDED_ARMv5
# include "SKP_Silk_macros_arm.h"
# elif defined (__ARM_ARCH_6__) ||defined (__ARM_ARCH_6J__) || defined (__ARM_ARCH_6Z__) || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
# define EMBEDDED_ARM 6
# define EMBEDDED_ARMv6
# include "SKP_Silk_macros_arm.h"
# elif defined (__ARM_ARCH_7A__) && defined (__ARM_NEON__)
# define EMBEDDED_ARM 7
# define EMBEDDED_ARMv6
# include "SKP_Silk_macros_arm.h"
# elif defined (__ARM_ARCH_7A__)
# define EMBEDDED_ARM 6
# define EMBEDDED_ARMv6
# include "SKP_Silk_macros_arm.h"
# else
# include "SKP_Silk_macros.h"
# endif
#else
# define EMBEDDED_ARM 0
# include "SKP_Silk_macros.h"
#endif
/********************************************************************/
/* SIGNAL PROCESSING FUNCTIONS */
/********************************************************************/
/*!
* Initialize/reset the resampler state for a given pair of input/output sampling rates
*/
SKP_int SKP_Silk_resampler_init(
SKP_Silk_resampler_state_struct *S, /* I/O: Resampler state */
SKP_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */
SKP_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */
);
/*!
* Clear the states of all resampling filters, without resetting sampling rate ratio
*/
SKP_int SKP_Silk_resampler_clear(
SKP_Silk_resampler_state_struct *S /* I/O: Resampler state */
);
/*!
* Resampler: convert from one sampling rate to another
*/
SKP_int SKP_Silk_resampler(
SKP_Silk_resampler_state_struct *S, /* I/O: Resampler state */
SKP_int16 out[], /* O: Output signal */
const SKP_int16 in[], /* I: Input signal */
SKP_int32 inLen /* I: Number of input samples */
);
/*!
Upsample 2x, low quality
*/
void SKP_Silk_resampler_up2(
SKP_int32 *S, /* I/O: State vector [ 2 ] */
SKP_int16 *out, /* O: Output signal [ 2 * len ] */
const SKP_int16 *in, /* I: Input signal [ len ] */
SKP_int32 len /* I: Number of input samples */
);
/*!
* Downsample 2x, mediocre quality
*/
void SKP_Silk_resampler_down2(
SKP_int32 *S, /* I/O: State vector [ 2 ] */
SKP_int16 *out, /* O: Output signal [ len ] */
const SKP_int16 *in, /* I: Input signal [ floor(len/2) ] */
SKP_int32 inLen /* I: Number of input samples */
);
/*!
* Downsample by a factor 2/3, low quality
*/
void SKP_Silk_resampler_down2_3(
SKP_int32 *S, /* I/O: State vector [ 6 ] */
SKP_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */
const SKP_int16 *in, /* I: Input signal [ inLen ] */
SKP_int32 inLen /* I: Number of input samples */
);
/*!
* Downsample by a factor 3, low quality
*/
void SKP_Silk_resampler_down3(
SKP_int32 *S, /* I/O: State vector [ 8 ] */
SKP_int16 *out, /* O: Output signal [ floor(inLen/3) ] */
const SKP_int16 *in, /* I: Input signal [ inLen ] */
SKP_int32 inLen /* I: Number of input samples */
);
/*!
* second order ARMA filter
* can handle (slowly) varying coefficients
*/
void SKP_Silk_biquad(
const SKP_int16 *in, /* I: input signal */
const SKP_int16 *B, /* I: MA coefficients, Q13 [3] */
const SKP_int16 *A, /* I: AR coefficients, Q13 [2] */
SKP_int32 *S, /* I/O: state vector [2] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len /* I: signal length */
);
/*!
* Second order ARMA filter;
* slower than biquad() but uses more precise coefficients
* can handle (slowly) varying coefficients
*/
void SKP_Silk_biquad_alt(
const SKP_int16 *in, /* I: Input signal */
const SKP_int32 *B_Q28, /* I: MA coefficients [3] */
const SKP_int32 *A_Q28, /* I: AR coefficients [2] */
SKP_int32 *S, /* I/O: State vector [2] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len /* I: Signal length (must be even) */
);
/*!
* variable order MA filter. Prediction error filter implementation. Coeficients negated and starting with coef to x[n - 1]
*/
void SKP_Silk_MA_Prediction(
const SKP_int16 *in, /* I: Input signal */
const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */
SKP_int32 *S, /* I/O: State vector [order] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len, /* I: Signal length */
const SKP_int32 order /* I: Filter order */
);
/*!
* 16th order AR filter for LPC synthesis, coefficients are in Q12
*/
void SKP_Silk_LPC_synthesis_order16(
const SKP_int16 *in, /* I: excitation signal */
const SKP_int16 *A_Q12, /* I: AR coefficients [16], between -8_Q0 and 8_Q0 */
const SKP_int32 Gain_Q26, /* I: gain */
SKP_int32 *S, /* I/O: state vector [16] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len /* I: signal length, must be multiple of 16 */
);
/* variable order MA prediction error filter. */
/* Inverse filter of SKP_Silk_LPC_synthesis_filter */
void SKP_Silk_LPC_analysis_filter(
const SKP_int16 *in, /* I: Input signal */
const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */
SKP_int16 *S, /* I/O: State vector [order] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len, /* I: Signal length */
const SKP_int32 Order /* I: Filter order */
);
/* even order AR filter */
void SKP_Silk_LPC_synthesis_filter(
const SKP_int16 *in, /* I: excitation signal */
const SKP_int16 *A_Q12, /* I: AR coefficients [Order], between -8_Q0 and 8_Q0 */
const SKP_int32 Gain_Q26, /* I: gain */
SKP_int32 *S, /* I/O: state vector [Order] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len, /* I: signal length */
const SKP_int Order /* I: filter order, must be even */
);
/* Chirp (bandwidth expand) LP AR filter */
void SKP_Silk_bwexpander(
SKP_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
const SKP_int d, /* I Length of ar */
SKP_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
);
/* Chirp (bandwidth expand) LP AR filter */
void SKP_Silk_bwexpander_32(
SKP_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
const SKP_int d, /* I Length of ar */
SKP_int32 chirp_Q16 /* I Chirp factor in Q16 */
);
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
const SKP_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */
const SKP_int order /* I: Prediction order */
);
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
const SKP_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */
const SKP_int order /* I: Prediction order */
);
/* split signal in two decimated bands using first-order allpass filters */
void SKP_Silk_ana_filt_bank_1(
const SKP_int16 *in, /* I: Input signal [N] */
SKP_int32 *S, /* I/O: State vector [2] */
SKP_int16 *outL, /* O: Low band [N/2] */
SKP_int16 *outH, /* O: High band [N/2] */
SKP_int32 *scratch, /* I: Scratch memory [3*N/2] */
const SKP_int32 N /* I: Number of input samples */
);
/********************************************************************/
/* SCALAR FUNCTIONS */
/********************************************************************/
/* Approximation of 128 * log2() (very close inverse of approx 2^() below) */
/* Convert input to a log scale */
SKP_int32 SKP_Silk_lin2log(const SKP_int32 inLin); /* I: Input in linear scale */
/* Approximation of a sigmoid function */
SKP_int SKP_Silk_sigm_Q15(SKP_int in_Q5);
/* approximation of 2^() (exact inverse of approx log2() above) */
/* convert input to a linear scale */
SKP_int32 SKP_Silk_log2lin(const SKP_int32 inLog_Q7); /* I: input on log scale */
/* Function that returns the maximum absolut value of the input vector */
SKP_int16 SKP_Silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */
const SKP_int16 *vec, /* I Input vector [len] */
const SKP_int32 len /* I Length of input vector */
);
/* Compute number of bits to right shift the sum of squares of a vector */
/* of int16s to make it fit in an int32 */
void SKP_Silk_sum_sqr_shift(
SKP_int32 *energy, /* O Energy of x, after shifting to the right */
SKP_int *shift, /* O Number of bits right shift applied to energy */
const SKP_int16 *x, /* I Input vector */
SKP_int len /* I Length of input vector */
);
/* Calculates the reflection coefficients from the correlation sequence */
/* Faster than schur64(), but much less accurate. */
/* Uses SMLAWB(), requiring armv5E and higher. */
SKP_int32 SKP_Silk_schur( /* O: Returns residual energy */
SKP_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */
const SKP_int32 *c, /* I: correlations [order+1] */
const SKP_int32 order /* I: prediction order */
);
/* Calculates the reflection coefficients from the correlation sequence */
/* Slower than schur(), but more accurate. */
/* Uses SMULL(), available on armv4 */
SKP_int32 SKP_Silk_schur64( /* O: returns residual energy */
SKP_int32 rc_Q16[], /* O: Reflection coefficients [order] Q16 */
const SKP_int32 c[], /* I: Correlations [order+1] */
SKP_int32 order /* I: Prediction order */
);
/* Step up function, converts reflection coefficients to prediction coefficients */
void SKP_Silk_k2a(
SKP_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */
const SKP_int16 *rc_Q15, /* I: Reflection coefficients [order] Q15 */
const SKP_int32 order /* I: Prediction order */
);
/* Step up function, converts reflection coefficients to prediction coefficients */
void SKP_Silk_k2a_Q16(
SKP_int32 *A_Q24, /* O: Prediction coefficients [order] Q24 */
const SKP_int32 *rc_Q16, /* I: Reflection coefficients [order] Q16 */
const SKP_int32 order /* I: Prediction order */
);
/* Apply sine window to signal vector. */
/* Window types: */
/* 1 -> sine window from 0 to pi/2 */
/* 2 -> sine window from pi/2 to pi */
/* Every other sample is linearly interpolated, for speed. */
void SKP_Silk_apply_sine_window(
SKP_int16 px_win[], /* O Pointer to windowed signal */
const SKP_int16 px[], /* I Pointer to input signal */
const SKP_int win_type, /* I Selects a window type */
const SKP_int length /* I Window length, multiple of 4 */
);
/* Compute autocorrelation */
void SKP_Silk_autocorr(
SKP_int32 *results, /* O Result (length correlationCount) */
SKP_int *scale, /* O Scaling of the correlation vector */
const SKP_int16 *inputData, /* I Input data to correlate */
const SKP_int inputDataSize, /* I Length of input */
const SKP_int correlationCount /* I Number of correlation taps to compute */
);
/* Pitch estimator */
#define SKP_Silk_PITCH_EST_MIN_COMPLEX 0
#define SKP_Silk_PITCH_EST_MID_COMPLEX 1
#define SKP_Silk_PITCH_EST_MAX_COMPLEX 2
void SKP_Silk_decode_pitch(
SKP_int lagIndex, /* I */
SKP_int contourIndex, /* O */
SKP_int pitch_lags[], /* O 4 pitch values */
SKP_int Fs_kHz /* I sampling frequency (kHz) */
);
SKP_int SKP_Silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
const SKP_int16 *signal, /* I Signal of length PITCH_EST_FRAME_LENGTH_MS*Fs_kHz */
SKP_int *pitch_out, /* O 4 pitch lag values */
SKP_int *lagIndex, /* O Lag Index */
SKP_int *contourIndex, /* O Pitch contour Index */
SKP_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
SKP_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
const SKP_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
const SKP_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */
const SKP_int Fs_kHz, /* I Sample frequency (kHz) */
const SKP_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
const SKP_int forLJC /* I 1 if this function is called from LJC code, 0 otherwise. */
);
/* parameter defining the size and accuracy of the piecewise linear */
/* cosine approximatin table. */
#define LSF_COS_TAB_SZ_FIX 128
/* rom table with cosine values */
extern const SKP_int SKP_Silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ];
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
void SKP_Silk_A2NLSF(
SKP_int *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */
SKP_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
const SKP_int d /* I Filter order (must be even) */
);
/* compute whitening filter coefficients from normalized line spectral frequencies */
void SKP_Silk_NLSF2A(
SKP_int16 *a, /* o monic whitening filter coefficients in Q12, [d] */
const SKP_int *NLSF, /* i normalized line spectral frequencies in Q15, [d] */
const SKP_int d /* i filter order (should be even) */
);
void SKP_Silk_insertion_sort_increasing(
SKP_int32 *a, /* I/O Unsorted / Sorted vector */
SKP_int *index, /* O: Index vector for the sorted elements */
const SKP_int L, /* I: Vector length */
const SKP_int K /* I: Number of correctly sorted positions */
);
void SKP_Silk_insertion_sort_decreasing_int16(
SKP_int16 *a, /* I/O: Unsorted / Sorted vector */
SKP_int *index, /* O: Index vector for the sorted elements */
const SKP_int L, /* I: Vector length */
const SKP_int K /* I: Number of correctly sorted positions */
);
void SKP_Silk_insertion_sort_increasing_all_values(
SKP_int *a, /* I/O: Unsorted / Sorted vector */
const SKP_int L /* I: Vector length */
);
/* NLSF stabilizer, for a single input data vector */
void SKP_Silk_NLSF_stabilize(
SKP_int *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vector in Q15 [L] */
const SKP_int *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
const SKP_int L /* I: Number of NLSF parameters in the input vector */
);
/* Laroia low complexity NLSF weights */
void SKP_Silk_NLSF_VQ_weights_laroia(
SKP_int *pNLSFW_Q6, /* O: Pointer to input vector weights [D x 1] */
const SKP_int *pNLSF_Q15, /* I: Pointer to input vector [D x 1] */
const SKP_int D /* I: Input vector dimension (even) */
);
/* Compute reflection coefficients from input signal */
void SKP_Silk_burg_modified(
SKP_int32 *res_nrg, /* O residual energy */
SKP_int *res_nrgQ, /* O residual energy Q value */
SKP_int32 A_Q16[], /* O prediction coefficients (length order) */
const SKP_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */
const SKP_int subfr_length, /* I input signal subframe length (including D preceeding samples) */
const SKP_int nb_subfr, /* I number of subframes stacked in x */
const SKP_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */
const SKP_int D /* I order */
);
/* Copy and multiply a vector by a constant */
void SKP_Silk_scale_copy_vector16(
SKP_int16 *data_out,
const SKP_int16 *data_in,
SKP_int32 gain_Q16, /* I: gain in Q16 */
const SKP_int dataSize /* I: length */
);
/* Some for the LTP related function requires Q26 to work.*/
void SKP_Silk_scale_vector32_Q26_lshift_18(
SKP_int32 *data1, /* I/O: Q0/Q18 */
SKP_int32 gain_Q26, /* I: Q26 */
SKP_int dataSize /* I: length */
);
/********************************************************************/
/* INLINE ARM MATH */
/********************************************************************/
/* return sum(inVec1[i]*inVec2[i]) */
/* inVec1 and inVec2 should be increasing ordered, and starting address should be 4 byte aligned. (a factor of 4)*/
SKP_int32 SKP_Silk_inner_prod_aligned(
const SKP_int16* const inVec1, /* I input vector 1 */
const SKP_int16* const inVec2, /* I input vector 2 */
const SKP_int len /* I vector lengths */
);
SKP_int64 SKP_Silk_inner_prod16_aligned_64(
const SKP_int16 *inVec1, /* I input vector 1 */
const SKP_int16 *inVec2, /* I input vector 2 */
const SKP_int len /* I vector lengths */
);
/********************************************************************/
/* MACROS */
/********************************************************************/
/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
left. Output is 32bit int.
Note: contemporary compilers recognize the C expressions below and
compile them into 'ror' instructions if available. No need for inline ASM! */
#if defined(EMBEDDED_MIPS)
/* For MIPS (and most likely for ARM! and >=i486) we don't have to handle
negative rot's as only 5 bits of rot are encoded into ROR instructions. */
SKP_INLINE SKP_int32 SKP_ROR32(SKP_int32 a32, SKP_int rot)
{
SKP_uint32 _x = (SKP_uint32) a32;
SKP_uint32 _r = (SKP_uint32) rot;
return (SKP_int32) ((_x << (32 - _r)) | (_x >> _r));
}
#else
/* PPC must use this generic implementation. */
SKP_INLINE SKP_int32 SKP_ROR32( SKP_int32 a32, SKP_int rot )
{
SKP_uint32 x = (SKP_uint32) a32;
SKP_uint32 r = (SKP_uint32) rot;
SKP_uint32 m = (SKP_uint32) -rot;
if(rot <= 0)
return (SKP_int32) ((x << m) | (x >> (32 - m)));
else
return (SKP_int32) ((x << (32 - r)) | (x >> r));
}
#endif
/* Allocate SKP_int16 alligned to 4-byte memory address */
#if EMBEDDED_ARM
#if defined(_WIN32) && defined(_M_ARM)
#define SKP_DWORD_ALIGN __declspec(align(4))
#else
#define SKP_DWORD_ALIGN __attribute__((aligned(4)))
#endif
#else
#define SKP_DWORD_ALIGN
#endif
/* Useful Macros that can be adjusted to other platforms */
#define SKP_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */
#define SKP_memset(a, b, c) memset((a), (b), (c)) /* Dest, value, ByteCount */
#define SKP_memmove(a, b, c) memmove((a), (b), (c)) /* Dest, Src, ByteCount */
/* fixed point macros */
// (a32 * b32) output have to be 32bit int
#define SKP_MUL(a32, b32) ((a32) * (b32))
// (a32 * b32) output have to be 32bit uint
#define SKP_MUL_uint(a32, b32) SKP_MUL(a32, b32)
// a32 + (b32 * c32) output have to be 32bit int
#define SKP_MLA(a32, b32, c32) SKP_ADD32((a32),((b32) * (c32)))
/* ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
#define SKP_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16))
/* a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
#define SKP_SMLATT(a32, b32, c32) SKP_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
#define SKP_SMLALBB(a64, b16, c16) SKP_ADD64((a64),(SKP_int64)((SKP_int32)(b16) * (SKP_int32)(c16)))
// (a32 * b32)
#define SKP_SMULL(a32, b32) ((SKP_int64)(a32) * /*(SKP_int64)*/(b32))
/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
(just standard two's complement implementation-specific behaviour) */
#define SKP_ADD32_ovflw(a, b) ((SKP_int32)((SKP_uint32)(a) + (SKP_uint32)(b)))
/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
(just standard two's complement implementation-specific behaviour) */
#define SKP_SUB32_ovflw(a, b) ((SKP_int32)((SKP_uint32)(a) - (SKP_uint32)(b)))
/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
#define SKP_MLA_ovflw(a32, b32, c32) SKP_ADD32_ovflw((a32), (SKP_uint32)(b32) * (SKP_uint32)(c32))
#ifndef SKP_SMLABB_ovflw
#define SKP_SMLABB_ovflw(a32, b32, c32) SKP_ADD32_ovflw((a32), SKP_SMULBB((b32),(c32)))
#endif
#define SKP_SMLATT_ovflw(a32, b32, c32) SKP_ADD32_ovflw((a32), SKP_SMULTT((b32),(c32)))
#define SKP_SMLAWB_ovflw(a32, b32, c32) SKP_ADD32_ovflw((a32), SKP_SMULWB((b32),(c32)))
#define SKP_SMLAWT_ovflw(a32, b32, c32) SKP_ADD32_ovflw((a32), SKP_SMULWT((b32),(c32)))
#define SKP_DIV32_16(a32, b16) ((SKP_int32)((a32) / (b16)))
#define SKP_DIV32(a32, b32) ((SKP_int32)((a32) / (b32)))
#define SKP_ADD32(a, b) ((a) + (b))
#define SKP_ADD64(a, b) ((a) + (b))
#define SKP_SUB32(a, b) ((a) - (b))
#define SKP_SAT16(a) ((a) > SKP_int16_MAX ? SKP_int16_MAX : \
((a) < SKP_int16_MIN ? SKP_int16_MIN : (a)))
#define SKP_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : \
((a) < SKP_int32_MIN ? SKP_int32_MIN : (a)))
#define SKP_CHECK_FIT16(a) (a)
#define SKP_CHECK_FIT32(a) (a)
#define SKP_ADD_SAT16(a, b) (SKP_int16)SKP_SAT16( SKP_ADD32( (SKP_int32)(a), (b) ) )
/* Add with saturation for positive input values */
#define SKP_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b)))
#define SKP_LSHIFT32(a, shift) ((a)<<(shift)) // shift >= 0, shift < 32
#define SKP_LSHIFT64(a, shift) ((a)<<(shift)) // shift >= 0, shift < 64
#define SKP_LSHIFT(a, shift) SKP_LSHIFT32(a, shift) // shift >= 0, shift < 32
#define SKP_RSHIFT32(a, shift) ((a)>>(shift)) // shift >= 0, shift < 32
#define SKP_RSHIFT64(a, shift) ((a)>>(shift)) // shift >= 0, shift < 64
#define SKP_RSHIFT(a, shift) SKP_RSHIFT32(a, shift) // shift >= 0, shift < 32
/* saturates before shifting */
#define SKP_LSHIFT_SAT32(a, shift) (SKP_LSHIFT32( SKP_LIMIT_32( (a), SKP_RSHIFT32( SKP_int32_MIN, (shift) ), \
SKP_RSHIFT32( SKP_int32_MAX, (shift) ) ), (shift) ))
#define SKP_LSHIFT_ovflw(a, shift) ((a)<<(shift)) // shift >= 0, allowed to overflow
#define SKP_LSHIFT_uint(a, shift) ((a)<<(shift)) // shift >= 0
#define SKP_RSHIFT_uint(a, shift) ((a)>>(shift)) // shift >= 0
#define SKP_ADD_LSHIFT(a, b, shift) ((a) + SKP_LSHIFT((b), (shift))) // shift >= 0
#define SKP_ADD_LSHIFT32(a, b, shift) SKP_ADD32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0
#define SKP_ADD_RSHIFT(a, b, shift) ((a) + SKP_RSHIFT((b), (shift))) // shift >= 0
#define SKP_ADD_RSHIFT32(a, b, shift) SKP_ADD32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0
#define SKP_ADD_RSHIFT_uint(a, b, shift) ((a) + SKP_RSHIFT_uint((b), (shift))) // shift >= 0
#define SKP_SUB_LSHIFT32(a, b, shift) SKP_SUB32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0
#define SKP_SUB_RSHIFT32(a, b, shift) SKP_SUB32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0
/* Requires that shift > 0 */
#define SKP_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
#define SKP_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
/* Number of rightshift required to fit the multiplication */
#define SKP_NSHIFT_MUL_32_32(a, b) ( -(31- (32-SKP_Silk_CLZ32(SKP_abs(a)) + (32-SKP_Silk_CLZ32(SKP_abs(b))))) )
#define SKP_min(a, b) (((a) < (b)) ? (a) : (b))
#define SKP_max(a, b) (((a) > (b)) ? (a) : (b))
/* Macro to convert floating-point constants to fixed-point */
#define SKP_FIX_CONST( C, Q ) ((SKP_int32)((C) * ((SKP_int64)1 << (Q)) + 0.5))
/* SKP_min() versions with typecast in the function call */
SKP_INLINE SKP_int SKP_min_int(SKP_int a, SKP_int b)
{
return (((a) < (b)) ? (a) : (b));
}
SKP_INLINE SKP_int32 SKP_min_32(SKP_int32 a, SKP_int32 b)
{
return (((a) < (b)) ? (a) : (b));
}
/* SKP_min() versions with typecast in the function call */
SKP_INLINE SKP_int SKP_max_int(SKP_int a, SKP_int b)
{
return (((a) > (b)) ? (a) : (b));
}
SKP_INLINE SKP_int16 SKP_max_16(SKP_int16 a, SKP_int16 b)
{
return (((a) > (b)) ? (a) : (b));
}
SKP_INLINE SKP_int32 SKP_max_32(SKP_int32 a, SKP_int32 b)
{
return (((a) > (b)) ? (a) : (b));
}
#define SKP_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
#define SKP_LIMIT_int SKP_LIMIT
#define SKP_LIMIT_32 SKP_LIMIT
//#define SKP_non_neg(a) ((a) & ((-(a)) >> (8 * sizeof(a) - 1))) /* doesn't seem faster than SKP_max(0, a);
#define SKP_abs(a) (((a) > 0) ? (a) : -(a)) // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN
#define SKP_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
/* PSEUDO-RANDOM GENERATOR */
/* Make sure to store the result as the seed for the next call (also in between */
/* frames), otherwise result won't be random at all. When only using some of the */
/* bits, take the most significant bits by right-shifting. Do not just mask off */
/* the lowest bits. */
#define SKP_RAND(seed) (SKP_MLA_ovflw(907633515, (seed), 196314165))
// Add some multiplication functions that can be easily mapped to ARM.
// SKP_SMMUL: Signed top word multiply.
// ARMv6 2 instruction cycles.
// ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)
//#define SKP_SMMUL(a32, b32) (SKP_int32)SKP_RSHIFT(SKP_SMLAL(SKP_SMULWB((a32), (b32)), (a32), SKP_RSHIFT_ROUND((b32), 16)), 16)
// the following seems faster on x86
//#define SKP_SMMUL(a32, b32) (SKP_int32)SKP_RSHIFT64(SKP_SMULL((a32), (b32)), 32)
#include "SKP_Silk_Inlines.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,320 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*
* File Name: SKP_Silk_VAD.c
* Description: Silk VAD.
*/
#include <stdlib.h>
#include "SKP_Silk_main.h"
/**********************************/
/* Initialization of the Silk VAD */
/**********************************/
SKP_int SKP_Silk_VAD_Init( /* O Return value, 0 if success */
SKP_Silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
)
{
SKP_int b, ret = 0;
/* reset state memory */
SKP_memset( psSilk_VAD, 0, sizeof( SKP_Silk_VAD_state ) );
/* init noise levels */
/* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NoiseLevelBias[ b ] = SKP_max_32( SKP_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
}
/* Initialize state */
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NL[ b ] = SKP_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
psSilk_VAD->inv_NL[ b ] = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->NL[ b ] );
}
psSilk_VAD->counter = 15;
/* init smoothed energy-to-noise ratio*/
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */
}
return( ret );
}
/* Weighting factors for tilt measure */
const static SKP_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
/***************************************/
/* Get the speech activity level in Q8 */
/***************************************/
SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Return value, 0 if success */
SKP_Silk_VAD_state *psSilk_VAD, /* I/O Silk VAD state */
SKP_int *pSA_Q8, /* O Speech activity level in Q8 */
SKP_int *pSNR_dB_Q7, /* O SNR for current frame in Q7 */
SKP_int pQuality_Q15[ VAD_N_BANDS ], /* O Smoothed SNR for each band */
SKP_int *pTilt_Q15, /* O current frame's frequency tilt */
const SKP_int16 pIn[], /* I PCM input [framelength] */
const SKP_int framelength /* I Input frame length */
)
{
SKP_int SA_Q15, input_tilt;
SKP_int32 scratch[ 3 * MAX_FRAME_LENGTH / 2 ];
SKP_int decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
SKP_int32 sumSquared, smooth_coef_Q16;
SKP_int16 HPstateTmp;
SKP_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ];
SKP_int32 Xnrg[ VAD_N_BANDS ];
SKP_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
SKP_int32 speech_nrg, x_tmp;
SKP_int ret = 0;
/* Safety checks */
SKP_assert( VAD_N_BANDS == 4 );
SKP_assert( MAX_FRAME_LENGTH >= framelength );
SKP_assert( framelength <= 512 );
/***********************/
/* Filter and Decimate */
/***********************/
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */
SKP_Silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], &scratch[ 0 ], framelength );
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */
SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], &scratch[ 0 ], SKP_RSHIFT( framelength, 1 ) );
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */
SKP_Silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], &scratch[ 0 ], SKP_RSHIFT( framelength, 2 ) );
/*********************************************/
/* HP filter on lowest band (differentiator) */
/*********************************************/
decimated_framelength = SKP_RSHIFT( framelength, 3 );
X[ 0 ][ decimated_framelength - 1 ] = SKP_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 );
HPstateTmp = X[ 0 ][ decimated_framelength - 1 ];
for( i = decimated_framelength - 1; i > 0; i-- ) {
X[ 0 ][ i - 1 ] = SKP_RSHIFT( X[ 0 ][ i - 1 ], 1 );
X[ 0 ][ i ] -= X[ 0 ][ i - 1 ];
}
X[ 0 ][ 0 ] -= psSilk_VAD->HPstate;
psSilk_VAD->HPstate = HPstateTmp;
/*************************************/
/* Calculate the energy in each band */
/*************************************/
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Find the decimated framelength in the non-uniformly divided bands */
decimated_framelength = SKP_RSHIFT( framelength, SKP_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
/* Split length into subframe lengths */
dec_subframe_length = SKP_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
dec_subframe_offset = 0;
/* Compute energy per sub-frame */
/* initialize with summed energy of last subframe */
Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
sumSquared = 0;
for( i = 0; i < dec_subframe_length; i++ ) {
/* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 );
sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp );
/* Safety check */
SKP_assert( sumSquared >= 0 );
}
/* Add/saturate summed energy of current subframe */
if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
} else {
/* Look-ahead subframe */
Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) );
}
dec_subframe_offset += dec_subframe_length;
}
psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
}
/********************/
/* Noise estimation */
/********************/
SKP_Silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
/***********************************************/
/* Signal-plus-noise to noise ratio estimation */
/***********************************************/
sumSquared = 0;
input_tilt = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
if( speech_nrg > 0 ) {
/* Divide, with sufficient resolution */
if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( SKP_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
} else {
NrgToNoiseRatio_Q8[ b ] = SKP_DIV32( Xnrg[ b ], SKP_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
}
/* Convert to log domain */
SNR_Q7 = SKP_Silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
/* Sum-of-squares */
sumSquared = SKP_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */
/* Tilt measure */
if( speech_nrg < ( 1 << 20 ) ) {
/* Scale down SNR value for small subband speech energies */
SNR_Q7 = SKP_SMULWB( SKP_LSHIFT( SKP_Silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
}
input_tilt = SKP_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
} else {
NrgToNoiseRatio_Q8[ b ] = 256;
}
}
/* Mean-of-squares */
sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
/* Root-mean-square approximation, scale to dBs, and write to output pointer */
*pSNR_dB_Q7 = ( SKP_int16 )( 3 * SKP_Silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
/*********************************/
/* Speech Probability Estimation */
/*********************************/
SA_Q15 = SKP_Silk_sigm_Q15( SKP_SMULWB( VAD_SNR_FACTOR_Q16, *pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
/**************************/
/* Frequency Tilt Measure */
/**************************/
*pTilt_Q15 = SKP_LSHIFT( SKP_Silk_sigm_Q15( input_tilt ) - 16384, 1 );
/**************************************************/
/* Scale the sigmoid output based on power levels */
/**************************************************/
speech_nrg = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Accumulate signal-without-noise energies, higher frequency bands have more weight */
speech_nrg += ( b + 1 ) * SKP_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = SKP_RSHIFT( SA_Q15, 1 );
} else if( speech_nrg < 32768 ) {
/* square-root */
speech_nrg = SKP_Silk_SQRT_APPROX( SKP_LSHIFT( speech_nrg, 15 ) );
SA_Q15 = SKP_SMULWB( 32768 + speech_nrg, SA_Q15 );
}
/* Copy the resulting speech activity in Q8 to *pSA_Q8 */
*pSA_Q8 = SKP_min_int( SKP_RSHIFT( SA_Q15, 7 ), SKP_uint8_MAX );
/***********************************/
/* Energy Level and SNR estimation */
/***********************************/
/* Smoothing coefficient */
smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) );
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* compute smoothed energy-to-noise ratio per band */
psSilk_VAD->NrgRatioSmth_Q8[ b ] = SKP_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
/* signal to noise ratio in dB per band */
SNR_Q7 = 3 * ( SKP_Silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
/* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
pQuality_Q15[ b ] = SKP_Silk_sigm_Q15( SKP_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
}
return( ret );
}
/**************************/
/* Noise level estimation */
/**************************/
void SKP_Silk_VAD_GetNoiseLevels(
const SKP_int32 pX[ VAD_N_BANDS ], /* I subband energies */
SKP_Silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
)
{
SKP_int k;
SKP_int32 nl, nrg, inv_nrg;
SKP_int coef, min_coef;
/* Initially faster smoothing */
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
min_coef = SKP_DIV32_16( SKP_int16_MAX, SKP_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
} else {
min_coef = 0;
}
for( k = 0; k < VAD_N_BANDS; k++ ) {
/* Get old noise level estimate for current band */
nl = psSilk_VAD->NL[ k ];
SKP_assert( nl >= 0 );
/* Add bias */
nrg = SKP_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
SKP_assert( nrg > 0 );
/* Invert energies */
inv_nrg = SKP_DIV32( SKP_int32_MAX, nrg );
SKP_assert( inv_nrg >= 0 );
/* Less update when subband energy is high */
if( nrg > SKP_LSHIFT( nl, 3 ) ) {
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
} else if( nrg < nl ) {
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
} else {
coef = SKP_SMULWB( SKP_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
}
/* Initially faster smoothing */
coef = SKP_max_int( coef, min_coef );
/* Smooth inverse energies */
psSilk_VAD->inv_NL[ k ] = SKP_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
SKP_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
/* Compute noise level by inverting again */
nl = SKP_DIV32( SKP_int32_MAX, psSilk_VAD->inv_NL[ k ] );
SKP_assert( nl >= 0 );
/* Limit noise levels (guarantee 7 bits of head room) */
nl = SKP_min( nl, 0x00FFFFFF );
/* Store as part of state */
psSilk_VAD->NL[ k ] = nl;
}
/* Increment frame counter */
psSilk_VAD->counter++;
}

View File

@ -0,0 +1,159 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
/* Entropy constrained MATRIX-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
void SKP_Silk_VQ_WMat_EC_FIX(
SKP_int *ind, /* O index of best codebook vector */
SKP_int32 *rate_dist_Q14, /* O best weighted quantization error + mu * rate*/
const SKP_int16 *in_Q14, /* I input vector to be quantized */
const SKP_int32 *W_Q18, /* I weighting matrix */
const SKP_int16 *cb_Q14, /* I codebook */
const SKP_int16 *cl_Q6, /* I code length for each codebook vector */
const SKP_int mu_Q8, /* I tradeoff between weighted error and rate */
SKP_int L /* I number of vectors in codebook */
)
{
SKP_int k;
const SKP_int16 *cb_row_Q14;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 sum1_Q14, sum2_Q16, diff_Q14_01, diff_Q14_23, diff_Q14_4;
#else
SKP_int16 diff_Q14[ 5 ];
SKP_int32 sum1_Q14, sum2_Q16;
#endif
/* Loop over codebook */
*rate_dist_Q14 = SKP_int32_MAX;
cb_row_Q14 = cb_Q14;
for( k = 0; k < L; k++ ) {
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* Pack pairs of int16 values per int32 */
diff_Q14_01 = ( SKP_uint16 )( in_Q14[ 0 ] - cb_row_Q14[ 0 ] ) | SKP_LSHIFT( ( SKP_int32 )in_Q14[ 1 ] - cb_row_Q14[ 1 ], 16 );
diff_Q14_23 = ( SKP_uint16 )( in_Q14[ 2 ] - cb_row_Q14[ 2 ] ) | SKP_LSHIFT( ( SKP_int32 )in_Q14[ 3 ] - cb_row_Q14[ 3 ], 16 );
diff_Q14_4 = in_Q14[ 4 ] - cb_row_Q14[ 4 ];
#else
diff_Q14[ 0 ] = in_Q14[ 0 ] - cb_row_Q14[ 0 ];
diff_Q14[ 1 ] = in_Q14[ 1 ] - cb_row_Q14[ 1 ];
diff_Q14[ 2 ] = in_Q14[ 2 ] - cb_row_Q14[ 2 ];
diff_Q14[ 3 ] = in_Q14[ 3 ] - cb_row_Q14[ 3 ];
diff_Q14[ 4 ] = in_Q14[ 4 ] - cb_row_Q14[ 4 ];
#endif
/* Weighted rate */
sum1_Q14 = SKP_SMULBB( mu_Q8, cl_Q6[ k ] );
SKP_assert( sum1_Q14 >= 0 );
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
/* Add weighted quantization error, assuming W_Q18 is symmetric */
/* NOTE: the code below loads two int16 values as one int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
/* first row of W_Q18 */
sum2_Q16 = SKP_SMULWT( W_Q18[ 1 ], diff_Q14_01 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14_23 );
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 3 ], diff_Q14_23 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14_4 );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14_01 );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_01 );
/* second row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14_23 );
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 8 ], diff_Q14_23 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14_4 );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 6 ], diff_Q14_01 );
sum1_Q14 = SKP_SMLAWT( sum1_Q14, sum2_Q16, diff_Q14_01 );
/* third row of W_Q18 */
sum2_Q16 = SKP_SMULWT( W_Q18[ 13 ], diff_Q14_23 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14_4 );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14_23 );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_23 );
/* fourth row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14_4 );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 18 ], diff_Q14_23 );
sum1_Q14 = SKP_SMLAWT( sum1_Q14, sum2_Q16, diff_Q14_23 );
/* last row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14_4 );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_4 );
#else
/* first row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
/* second row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
/* third row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
/* fourth row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
/* last row of W_Q18 */
sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
#endif
SKP_assert( sum1_Q14 >= 0 );
/* find best */
if( sum1_Q14 < *rate_dist_Q14 ) {
*rate_dist_Q14 = sum1_Q14;
*ind = k;
}
/* Go to next cbk vector */
cb_row_Q14 += LTP_ORDER;
}
}

View File

@ -0,0 +1,124 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if defined(__arm__)
#include "SKP_Silk_AsmPreproc.h"
#if EMBEDDED_ARM >= 5
VARDEF A, r2
VARDEF len, r4
VARDEF S00, r5
VARDEF ink1, r6
VARDEF ink2, r8
VARDEF Y2, sb
VARDEF outk1, sl
VARDEF outk2, ip
.globl SYM(SKP_Silk_allpass_int)
SYM(SKP_Silk_allpass_int):
stmdb sp!, {r4-r10, fp, ip, lr}
add fp, sp, #36
.set len_offset, 40
ldr len, [sp, #len_offset]
ldr S00, [r1]
movs A, A, lsl #17
sub len, len, #1
ldmia r0!, {ink1,ink2}
bge LR(1, f)/*AgeZero*/
L(0)
sub Y2, ink1, S00
smlawt outk1, Y2, A, ink1
add S00, Y2, outk1
subs len, len, #2
sub Y2, ink2, S00
smlawt outk2, Y2, A, ink2
#ifdef _WINRT
ble LR(3, f)
ldmia r0!, {ink1,ink2}
L(3)
#else
ldmgtia r0!, {ink1,ink2}
#endif
add S00, Y2, outk2
stmia r3!, {outk1, outk2}
bgt LR(0, b)
#ifdef _WINRT
bne LR(2, f)
ldr ink1, [r0], #4
sub Y2, ink1, S00
smlawt outk1, Y2, A, ink1
add S00, Y2, outk1
str outk1, [r3]
L(2)
#else
ldreq ink1, [r0], #4
subeq Y2, ink1, S00
smlawteq outk1, Y2, A, ink1
addeq S00, Y2, outk1
streq outk1, [r3]
#endif
str S00, [r1]
ldmia sp!, {r4-r10, fp, ip, pc}
L(1)/*AgeZero:*/
sub Y2, ink1, S00
smlawt outk1, Y2, A, S00
add S00, Y2, outk1
subs len, len, #2
sub Y2, ink2, S00
smlawt outk2, Y2, A, S00
#ifdef _WINRT
ble LR(3, f)
ldmia r0!, {ink1,ink2}
L(3)
#else
ldmgtia r0!, {ink1,ink2}
#endif
add S00, Y2, outk2
stmia r3!, {outk1, outk2}
bgt LR(1, b)
#ifdef _WINRT
bne LR(2, f)
ldr ink1, [r0], #4
sub Y2, ink1, S00
smlawt outk1, Y2, A, S00
add S00, Y2, outk1
str outk1, [r3]
L(2)
#else
ldreq ink1, [r0], #4
subeq Y2, ink1, S00
smlawteq outk1, Y2, A, S00
addeq S00, Y2, outk1
streq outk1, [r3]
#endif
str S00, [r1]
ldmia sp!, {r4-r10, fp, ip, pc}
END
#endif
#endif

View File

@ -0,0 +1,82 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_ana_filt_bank_1.c *
* *
* Split signal into two decimated bands using first-order allpass filters *
* *
* Copyright 2006 (c), Skype Limited *
* Date: 060221 *
* */
#include "SKP_Silk_SigProc_FIX.h"
#if EMBEDDED_ARM<5
/* Coefficients for 2-band filter bank based on first-order allpass filters */
// old
static SKP_int16 A_fb1_20[ 1 ] = { 5394 << 1 };
static SKP_int16 A_fb1_21[ 1 ] = { (SKP_int16) (20623 << 1) }; /* wrap-around to negative number is intentional */
/* Split signal into two decimated bands using first-order allpass filters */
void SKP_Silk_ana_filt_bank_1(
const SKP_int16 *in, /* I: Input signal [N] */
SKP_int32 *S, /* I/O: State vector [2] */
SKP_int16 *outL, /* O: Low band [N/2] */
SKP_int16 *outH, /* O: High band [N/2] */
SKP_int32 *scratch, /* I: Scratch memory [3*N/2] */ // todo: remove - no longer used
const SKP_int32 N /* I: Number of input samples */
)
{
SKP_int k, N2 = SKP_RSHIFT( N, 1 );
SKP_int32 in32, X, Y, out_1, out_2;
/* Internal variables and state are in Q10 format */
for( k = 0; k < N2; k++ ) {
/* Convert to Q10 */
in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 );
/* All-pass section for even input sample */
Y = SKP_SUB32( in32, S[ 0 ] );
X = SKP_SMLAWB( Y, Y, A_fb1_21[ 0 ] );
out_1 = SKP_ADD32( S[ 0 ], X );
S[ 0 ] = SKP_ADD32( in32, X );
/* Convert to Q10 */
in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 );
/* All-pass section for odd input sample */
Y = SKP_SUB32( in32, S[ 1 ] );
X = SKP_SMULWB( Y, A_fb1_20[ 0 ] );
out_2 = SKP_ADD32( S[ 1 ], X );
S[ 1 ] = SKP_ADD32( in32, X );
/* Add/subtract, convert back to int16 and store to output */
outL[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_ADD32( out_2, out_1 ), 11 ) );
outH[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( out_2, out_1 ), 11 ) );
}
}
#endif

View File

@ -0,0 +1,186 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if defined(__arm__)
#include "SKP_Silk_AsmPreproc.h"
#if EMBEDDED_ARM>=5
/*
* void SKP_Silk_ana_filt_bank_1(
* const SKP_int16 *in, I: Input signal [N]
* SKP_int32 *S, I/O: State vector [2]
* SKP_int16 *outL, O: Low band [N/2]
* SKP_int16 *outH, O: High band [N/2]
* SKP_int32 *scratch, I: Scratch memory [3*N/2]
* const SKP_int32 N I: Number of input samples
* )
*/
VARDEF ptr_in_lo, r0
VARDEF ptr_in_hi, r3
VARDEF val_in_lo, sb
VARDEF val_in_hi, sl
VARDEF ptr_scratch, r4
VARDEF ptr_scratch_N, r1
VARDEF ptr_scratch_halfN, r2
VARDEF idx_k, ip
VARDEF val_N, r8
VARDEF val_halfN, r8
VARDEF val_scratch1, r5
VARDEF val_scratch2, r6
VARDEF ptr_out_lo, r5
VARDEF ptr_out_hi, r6
VARDEF ptr_s, _r7
VARDEF val_const1, r2
VARDEF val_const2, ip // 0x03FF F800
VARDEF val_const3, sl // 0x0000 7FFF
VARDEF val_const4, lr // 0xFFFF 8000
VARDEF idx_k2, r8
VARDEF ptr_scratch_halfN_2, r3
VARDEF val_scratch3, r0
VARDEF val_scratch4, r1
VARDEF out_tmpla, sb
VARDEF out_tmplb, r2
VARDEF out_tmpha, r0
VARDEF out_tmphb, _r7
.set halfN, 0
.set sp_ptr_out_lo, 4
.set sp_ptr_out_hi, 8
EXTERN SYM(SKP_Silk_allpass_int)
.globl SYM(SKP_Silk_ana_filt_bank_1)
SYM(SKP_Silk_ana_filt_bank_1):
stmdb sp!, {r4-r10, fp, ip, lr}
add fp, sp, #36
sub sp, sp, #12
.set arg_scratch, 52
.set arg_N, 56
ldr ptr_scratch, [sp, #arg_scratch]
ldr val_N, [sp, #arg_N]
str r2, [sp, #sp_ptr_out_lo]
str r3, [sp, #sp_ptr_out_hi]
mov ptr_s, r1
mov val_halfN, val_N, asr #1
sub idx_k, val_halfN, #1
add ptr_in_hi, ptr_in_lo, #2
str val_halfN, [sp, #halfN]
ldrsh val_in_lo, [ptr_in_lo], #4
ldrsh val_in_hi, [ptr_in_hi], #4
add ptr_scratch_N, ptr_scratch, val_halfN, lsl #3
add ptr_scratch_halfN, ptr_scratch, val_halfN, lsl #2
L(0)
mov val_scratch1, val_in_lo, lsl #10
mov val_scratch2, val_in_hi, lsl #10
ldrsh val_in_lo, [ptr_in_lo], #4
ldrsh val_in_hi, [ptr_in_hi], #4
subs idx_k, idx_k, #1
str val_scratch1, [ptr_scratch_N], #4
str val_scratch2, [ptr_scratch_halfN], #4
bgt LR(0, b)
mov val_scratch1, val_in_lo, lsl #10
mov val_scratch2, val_in_hi, lsl #10
str val_scratch1, [ptr_scratch_N], #4
str val_scratch2, [ptr_scratch_halfN], #4
mov val_const1, #0x1500
add r0, ptr_scratch, val_halfN, lsl #2
add r1, ptr_s, #4
add val_const1, val_const1, #0x12
mov r3, ptr_scratch
bl SYM(SKP_Silk_allpass_int)
mov val_const1, #0x5000
add r0, ptr_scratch, val_halfN, lsl #3
mov r1, ptr_s
add val_const1, val_const1, #0x8F
add r3, ptr_scratch, val_halfN, lsl #2
bl SYM(SKP_Silk_allpass_int)
mvn val_const2, #0x80000000
add ptr_scratch_halfN_2, ptr_scratch, val_halfN, lsl #2
mov val_const3, val_const2, asr #16
rsb val_const4, val_const3, #0
mov idx_k2, val_halfN
mov val_const2, val_const3, lsl #11
ldr ptr_out_lo, [sp, #sp_ptr_out_lo]
ldr ptr_out_hi, [sp, #sp_ptr_out_hi]
L(1)
ldr val_scratch3, [ptr_scratch], #4
ldr val_scratch4, [ptr_scratch_halfN_2], #4
add out_tmpla, val_scratch3, val_scratch4
sub out_tmpha, val_scratch3, val_scratch4
add out_tmplb, out_tmpla, #1024
add out_tmphb, out_tmpha, #1024
mov out_tmplb, out_tmplb, asr #11
mov out_tmphb, out_tmphb, asr #11
strh out_tmplb, [ptr_out_lo], #2
strh out_tmphb, [ptr_out_hi], #2
#ifdef _WINRT
cmp out_tmpla, val_const2
ble LR(2, f)
strh val_const3, [ptr_out_lo, #-2]
L(2)
cmn out_tmpla, val_const2
bge LR(2, f)
strh val_const4, [ptr_out_lo, #-2]
L(2)
cmp out_tmpha, val_const2
ble LR(2, f)
strh val_const3, [ptr_out_hi, #-2]
L(2)
cmn out_tmpha, val_const2
bge LR(2, f)
strh val_const4, [ptr_out_hi, #-2]
L(2)
#else
cmp out_tmpla, val_const2
strgth val_const3, [ptr_out_lo, #-2]
cmn out_tmpla, val_const2
strlth val_const4, [ptr_out_lo, #-2]
cmp out_tmpha, val_const2
strgth val_const3, [ptr_out_hi, #-2]
cmn out_tmpha, val_const2
strlth val_const4, [ptr_out_hi, #-2]
#endif
subs idx_k2, idx_k2, #1
bgt LR(1, b)
add sp, sp, #12
ldmia sp!, {r4-r10, fp, ip, pc}
END
#endif
#endif

View File

@ -0,0 +1,120 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SigProc_FIX.h"
/* Apply sine window to signal vector. */
/* Window types: */
/* 1 -> sine window from 0 to pi/2 */
/* 2 -> sine window from pi/2 to pi */
/* Every other sample is linearly interpolated, for speed. */
/* Window length must be between 16 and 120 (incl) and a multiple of 4. */
/* Matlab code for table:
for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end
*/
static SKP_int16 freq_table_Q16[ 27 ] = {
12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202,
3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422,
2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702,
};
//#if EMBEDDED_ARM<6
void SKP_Silk_apply_sine_window(
SKP_int16 px_win[], /* O Pointer to windowed signal */
const SKP_int16 px[], /* I Pointer to input signal */
const SKP_int win_type, /* I Selects a window type */
const SKP_int length /* I Window length, multiple of 4 */
)
{
SKP_int k, f_Q16, c_Q16;
SKP_int32 S0_Q16, S1_Q16;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 px32;
#endif
SKP_assert( win_type == 1 || win_type == 2 );
/* Length must be in a range from 16 to 120 and a multiple of 4 */
SKP_assert( length >= 16 && length <= 120 );
SKP_assert( ( length & 3 ) == 0 );
/* Input pointer must be 4-byte aligned */
SKP_assert( ( ( SKP_int64 )( ( SKP_int8* )px - ( SKP_int8* )0 ) & 3 ) == 0 );
/* Frequency */
k = ( length >> 2 ) - 4;
SKP_assert( k >= 0 && k <= 26 );
f_Q16 = (SKP_int)freq_table_Q16[ k ];
/* Factor used for cosine approximation */
c_Q16 = SKP_SMULWB( f_Q16, -f_Q16 );
SKP_assert( c_Q16 >= -32768 );
/* initialize state */
if( win_type == 1 ) {
/* start from 0 */
S0_Q16 = 0;
/* approximation of sin(f) */
S1_Q16 = f_Q16 + SKP_RSHIFT( length, 3 );
} else {
/* start from 1 */
S0_Q16 = ( 1 << 16 );
/* approximation of cos(f) */
S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q16, 1 ) + SKP_RSHIFT( length, 4 );
}
/* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */
/* 4 samples at a time */
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
for( k = 0; k < length; k += 4 ) {
px32 = *( (SKP_int32 *)&px[ k ] ); /* load two values at once */
px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px32 );
px_win[ k + 1 ] = (SKP_int16)SKP_SMULWT( S1_Q16, px32 );
S0_Q16 = SKP_SMULWB( S1_Q16, c_Q16 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1;
S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) );
px32 = *( (SKP_int32 *)&px[k + 2] ); /* load two values at once */
px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px32 );
px_win[ k + 3 ] = (SKP_int16)SKP_SMULWT( S0_Q16, px32 );
S1_Q16 = SKP_SMULWB( S0_Q16, c_Q16 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16;
S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) );
}
#else
for( k = 0; k < length; k += 4 ) {
px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] );
px_win[ k + 1 ] = (SKP_int16)SKP_SMULWB( S1_Q16, px[ k + 1] );
S0_Q16 = SKP_SMULWB( S1_Q16, c_Q16 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1;
S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) );
px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] );
px_win[ k + 3 ] = (SKP_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] );
S1_Q16 = SKP_SMULWB( S0_Q16, c_Q16 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16;
S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) );
}
#endif
}
//#endif

View File

@ -0,0 +1,70 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_int16_array_maxabs.c *
* *
* Function that returns the maximum absolut value of *
* the input vector *
* *
* Copyright 2006 (c), Skype Limited *
* Date: 060221 *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* Function that returns the maximum absolut value of the input vector */
#if (EMBEDDED_ARM<4)
SKP_int16 SKP_Silk_int16_array_maxabs( /* O Maximum absolute value, max: 2^15-1 */
const SKP_int16 *vec, /* I Input vector [len] */
const SKP_int32 len /* I Length of input vector */
)
{
SKP_int32 max = 0, i, lvl = 0, ind;
if( len == 0 ) return 0;
ind = len - 1;
max = SKP_SMULBB( vec[ ind ], vec[ ind ] );
for( i = len - 2; i >= 0; i-- ) {
lvl = SKP_SMULBB( vec[ i ], vec[ i ] );
if( lvl > max ) {
max = lvl;
ind = i;
}
}
/* Do not return 32768, as it will not fit in an int16 so may lead to problems later on */
if( max >= 1073676289 ) { // (2^15-1)^2 = 1073676289
return( SKP_int16_MAX );
} else {
if( vec[ ind ] < 0 ) {
return( -vec[ ind ] );
} else {
return( vec[ ind ] );
}
}
}
#endif

View File

@ -0,0 +1,288 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if defined(__arm__)
#include "SKP_Silk_AsmPreproc.h"
#if EMBEDDED_ARM>=5
VARDEF ptr_vec, r0
VARDEF val_vec, r2
VARDEF val_return, r0
VARDEF len, r1
VARDEF val1_max, r3
VARDEF val2_max, r4
VARDEF val_lvl, r5
VARDEF val_ind, r6
VARDEF const_int16_MAX, r5
.globl SYM(SKP_Silk_int16_array_maxabs)
SYM(SKP_Silk_int16_array_maxabs):
stmdb sp!, {r4-r6, fp, ip, lr}
add fp, sp, #20
cmp r1, #6
mvn r5, #0 /*r5 = -1(max)*/
blt LR(7, f)
ands r2, r0, #3
bne LR(3, f)
ands r2, r1, #0x1
bne LR(1, f)
ldr val_vec, [ptr_vec], #4
sub len, len, #2
L(0)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldr val_vec, [ptr_vec], #4
cmp val1_max, r5
movge val_lvl, val1_max
#ifdef _WINRT
subge val_ind, ptr_vec, #4 /*address*/
subge val_ind, val_ind, #4 /*address*/
#else
subge val_ind, ptr_vec, #8 /*address*/
#endif
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #6
subs len, len, #2
bgt LR(0, b)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #4 /*address*/
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #2
b LR(9, f)
/*Odd number of iterations*/
L(1)
ldr val_vec, [ptr_vec], #4
sub len, len, #3
L(2)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldr val_vec, [ptr_vec], #4
cmp val1_max, val_lvl
movge val_lvl, val1_max
#ifdef _WINRT
subge val_ind, ptr_vec, #4 /*address*/
subge val_ind, val_ind, #4 /*address*/
#else
subge val_ind, ptr_vec, #8 /*address*/
#endif
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #6
subs len, len, #2
bgt LR(2, b)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldrsh val_vec, [ptr_vec], #2
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #6 /*address*/
smulbb val1_max, val_vec, val_vec
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #4
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #2 /*address*/
b LR(9, f)
/*Oddly aligned*/
L(3)
ands r2, r1, #0x1
bne LR(5, f)
ldrsh val_vec, [ptr_vec], #2
smulbb val1_max, val_vec, val_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #2
ldr val_vec, [ptr_vec], #4
sub len, len, #4
L(4)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldr val_vec, [ptr_vec], #4
cmp val1_max, val_lvl
movge val_lvl, val1_max
#ifdef _WINRT
subge val_ind, ptr_vec, #4 /*address*/
subge val_ind, val_ind, #4 /*address*/
#else
subge val_ind, ptr_vec, #8 /*address*/
#endif
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #6
subs len, len, #2
bgt LR(4, b)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldrsh val_vec, [ptr_vec], #2
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #6 /*address*/
smulbb val1_max, val_vec, val_vec
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #4
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #2 /*address*/
b LR(9, f)
/*Odd number of iterations+Oddly aligned*/
L(5)
ldrsh val_vec, [ptr_vec], #2
smulbb val1_max, val_vec, val_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #2
ldr val_vec, [ptr_vec], #4
sub len, len, #3
L(6)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
ldr val_vec, [ptr_vec], #4
cmp val1_max, val_lvl
movge val_lvl, val1_max
#ifdef _WINRT
subge val_ind, ptr_vec, #4 /*address*/
subge val_ind, val_ind, #4 /*address*/
#else
subge val_ind, ptr_vec, #8 /*address*/
#endif
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #6
subs len, len, #2
bgt LR(6, b)
smulbb val1_max, val_vec, val_vec
smultt val2_max, val_vec, val_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #4 /*address*/
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #2
b LR(9, f)
/*Less than 6 iterations*/
L(7)
ldrsh val_vec, [ptr_vec], #2
sub len, len, #1
L(8)
smulbb val1_max, val_vec, val_vec
ldrsh val_vec, [ptr_vec], #2
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #4
subs len, len, #1
bgt LR(8, b)
smulbb val1_max, val_vec, val_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #2
L(9)
ldrsh val_return, [val_ind]
mvn const_int16_MAX, #0x80000000
mov const_int16_MAX, const_int16_MAX, asr #16
cmp val_return, #0
rsblt val_return, val_return, #0
cmp val_return, const_int16_MAX
movge val_return, const_int16_MAX
ldmia sp!, {r4-r6, fp, ip, pc}
#elif EMBEDDED_ARM>=4
VARDEF ptr_vec, r0
VARDEF val1_vec, r2
VARDEF val2_vec, r7
VARDEF len, r1
VARDEF val1_max, r3
VARDEF val2_max, r8
VARDEF val_lvl, r5
VARDEF val_ind, r6
VARDEF val_return, r0
VARDEF const_int16_MAX, r5
.globl SYM(SKP_Silk_int16_array_maxabs)
SYM(SKP_Silk_int16_array_maxabs):
stmdb sp!, {r4-r8, fp, ip, lr}
add fp, sp, #28
mvn val_lvl, #0 /*r5 = -1(max)*/
ldrsh val1_vec, [ptr_vec], #2
ldrsh val2_vec, [ptr_vec], #2
sub len, len, #2
L(0)
mul val1_max, val1_vec, val1_vec
mul val2_max, val2_vec, val2_vec
ldrsh val1_vec, [ptr_vec], #2
ldrsh val2_vec, [ptr_vec], #2
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #8
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #6
subs len, len, #2
bgt LR(0, b)
mul val1_max, val1_vec, val1_vec
mul val2_max, val2_vec, val2_vec
cmp val1_max, val_lvl
movge val_lvl, val1_max
subge val_ind, ptr_vec, #4
cmn len, #1 /*r1?=-1*/
beq LR(1, f)
cmp val2_max, val_lvl
movge val_lvl, val2_max
subge val_ind, ptr_vec, #2
L(1)
ldrsh val_return, [val_ind]
mvn const_int16_MAX, #0x80000000
mov const_int16_MAX, const_int16_MAX, asr #16
cmp val_return, #0
rsblt val_return, val_return, #0
cmp val_return, const_int16_MAX
movge val_return, const_int16_MAX
ldmia sp!, {r4-r8, fp, ip, pc}
#endif
END
#endif

View File

@ -0,0 +1,81 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_autocorr.c *
* *
* Calculates the autocorrelation *
* The result has 29 non-zero bits for the first correlation, to leave *
* some room for adding white noise fractions etc. *
* *
* Copyright 2008 (c), Skype Limited *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* Compute autocorrelation */
void SKP_Silk_autocorr(
SKP_int32 *results, /* O Result (length correlationCount) */
SKP_int *scale, /* O Scaling of the correlation vector */
const SKP_int16 *inputData, /* I Input data to correlate */
const SKP_int inputDataSize, /* I Length of input */
const SKP_int correlationCount /* I Number of correlation taps to compute */
)
{
SKP_int i, lz, nRightShifts, corrCount;
SKP_int64 corr64;
corrCount = SKP_min_int( inputDataSize, correlationCount );
/* compute energy (zero-lag correlation) */
corr64 = SKP_Silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize );
/* deal with all-zero input data */
corr64 += 1;
/* number of leading zeros */
lz = SKP_Silk_CLZ64( corr64 );
/* scaling: number of right shifts applied to correlations */
nRightShifts = 35 - lz;
*scale = nRightShifts;
if( nRightShifts <= 0 ) {
results[ 0 ] = SKP_LSHIFT( (SKP_int32)SKP_CHECK_FIT32( corr64 ), -nRightShifts );
/* compute remaining correlations based on int32 inner product */
for( i = 1; i < corrCount; i++ ) {
results[ i ] = SKP_LSHIFT( SKP_Silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts );
}
} else {
results[ 0 ] = (SKP_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( corr64, nRightShifts ) );
/* compute remaining correlations based on int64 inner product */
for( i = 1; i < corrCount; i++ ) {
results[ i ] = (SKP_int32)SKP_CHECK_FIT32( SKP_RSHIFT64( SKP_Silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) );
}
}
}

View File

@ -0,0 +1,72 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_biquad.c *
* *
* Second order ARMA filter *
* Can handle slowly varying filter coefficients *
* *
* Copyright 2006 (c), Skype Limited *
* Date: 060221 *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* Second order ARMA filter */
/* Can handle slowly varying filter coefficients */
void SKP_Silk_biquad(
const SKP_int16 *in, /* I: input signal */
const SKP_int16 *B, /* I: MA coefficients, Q13 [3] */
const SKP_int16 *A, /* I: AR coefficients, Q13 [2] */
SKP_int32 *S, /* I/O: state vector [2] */
SKP_int16 *out, /* O: output signal */
const SKP_int32 len /* I: signal length */
)
{
SKP_int k, in16;
SKP_int32 A0_neg, A1_neg, S0, S1, out32, tmp32;
S0 = S[ 0 ];
S1 = S[ 1 ];
A0_neg = -A[ 0 ];
A1_neg = -A[ 1 ];
for( k = 0; k < len; k++ ) {
/* S[ 0 ], S[ 1 ]: Q13 */
in16 = in[ k ];
out32 = SKP_SMLABB( S0, in16, B[ 0 ] );
S0 = SKP_SMLABB( S1, in16, B[ 1 ] );
S0 += SKP_LSHIFT( SKP_SMULWB( out32, A0_neg ), 3 );
S1 = SKP_LSHIFT( SKP_SMULWB( out32, A1_neg ), 3 );
S1 = SKP_SMLABB( S1, in16, B[ 2 ] );
tmp32 = SKP_RSHIFT_ROUND( out32, 13 ) + 1;
out[ k ] = (SKP_int16)SKP_SAT16( tmp32 );
}
S[ 0 ] = S0;
S[ 1 ] = S1;
}

View File

@ -0,0 +1,73 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_biquad_alt.c *
* *
* Second order ARMA filter *
* Can handle slowly varying filter coefficients *
* */
#include "SKP_Silk_SigProc_FIX.h"
/* Second order ARMA filter, alternative implementation */
void SKP_Silk_biquad_alt(
const SKP_int16 *in, /* I: Input signal */
const SKP_int32 *B_Q28, /* I: MA coefficients [3] */
const SKP_int32 *A_Q28, /* I: AR coefficients [2] */
SKP_int32 *S, /* I/O: State vector [2] */
SKP_int16 *out, /* O: Output signal */
const SKP_int32 len /* I: Signal length (must be even) */
)
{
/* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
SKP_int k;
SKP_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
/* Negate A_Q28 values and split in two parts */
A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF; /* lower part */
A0_U_Q28 = SKP_RSHIFT( -A_Q28[ 0 ], 14 ); /* upper part */
A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF; /* lower part */
A1_U_Q28 = SKP_RSHIFT( -A_Q28[ 1 ], 14 ); /* upper part */
for( k = 0; k < len; k++ ) {
/* S[ 0 ], S[ 1 ]: Q12 */
inval = in[ k ];
out32_Q14 = SKP_LSHIFT( SKP_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
S[ 0 ] = S[1] + SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
S[ 0 ] = SKP_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
S[ 0 ] = SKP_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
S[ 1 ] = SKP_RSHIFT_ROUND( SKP_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
S[ 1 ] = SKP_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
S[ 1 ] = SKP_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
/* Scale back to Q0 and saturate */
out[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
}
}

View File

@ -0,0 +1,228 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/* *
* SKP_Silk_burg_modified.c *
* *
* Calculates the reflection coefficients from the input vector *
* Input vector contains nb_subfr sub vectors of length L_sub + D *
* *
* Copyright 2009 (c), Skype Limited *
* Date: 100105 *
*/
#include "SKP_Silk_SigProc_FIX.h"
#define MAX_FRAME_SIZE 544 // subfr_length * nb_subfr = ( 0.005 * 24000 + 16 ) * 4 = 544
#define MAX_NB_SUBFR 4
#define QA 25
#define N_BITS_HEAD_ROOM 2
#define MIN_RSHIFTS -16
#define MAX_RSHIFTS (32 - QA)
/* Compute reflection coefficients from input signal */
void SKP_Silk_burg_modified(
SKP_int32 *res_nrg, /* O residual energy */
SKP_int *res_nrg_Q, /* O residual energy Q value */
SKP_int32 A_Q16[], /* O prediction coefficients (length order) */
const SKP_int16 x[], /* I input signal, length: nb_subfr * ( D + subfr_length ) */
const SKP_int subfr_length, /* I input signal subframe length (including D preceeding samples) */
const SKP_int nb_subfr, /* I number of subframes stacked in x */
const SKP_int32 WhiteNoiseFrac_Q32, /* I fraction added to zero-lag autocorrelation */
const SKP_int D /* I order */
)
{
SKP_int k, n, s, lz, rshifts, rshifts_extra;
SKP_int32 C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
const SKP_int16 *x_ptr;
SKP_int32 C_first_row[ SKP_Silk_MAX_ORDER_LPC ];
SKP_int32 C_last_row[ SKP_Silk_MAX_ORDER_LPC ];
SKP_int32 Af_QA[ SKP_Silk_MAX_ORDER_LPC ];
SKP_int32 CAf[ SKP_Silk_MAX_ORDER_LPC + 1 ];
SKP_int32 CAb[ SKP_Silk_MAX_ORDER_LPC + 1 ];
SKP_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
SKP_assert( nb_subfr <= MAX_NB_SUBFR );
/* Compute autocorrelations, added over subframes */
SKP_Silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
if( rshifts > MAX_RSHIFTS ) {
C0 = SKP_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
SKP_assert( C0 > 0 );
rshifts = MAX_RSHIFTS;
} else {
lz = SKP_Silk_CLZ32( C0 ) - 1;
rshifts_extra = N_BITS_HEAD_ROOM - lz;
if( rshifts_extra > 0 ) {
rshifts_extra = SKP_min( rshifts_extra, MAX_RSHIFTS - rshifts );
C0 = SKP_RSHIFT32( C0, rshifts_extra );
} else {
rshifts_extra = SKP_max( rshifts_extra, MIN_RSHIFTS - rshifts );
C0 = SKP_LSHIFT32( C0, -rshifts_extra );
}
rshifts += rshifts_extra;
}
SKP_memset( C_first_row, 0, SKP_Silk_MAX_ORDER_LPC * sizeof( SKP_int32 ) );
if( rshifts > 0 ) {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
for( n = 1; n < D + 1; n++ ) {
C_first_row[ n - 1 ] += (SKP_int32)SKP_RSHIFT64(
SKP_Silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts );
}
}
} else {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
for( n = 1; n < D + 1; n++ ) {
C_first_row[ n - 1 ] += SKP_LSHIFT32(
SKP_Silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts );
}
}
}
SKP_memcpy( C_last_row, C_first_row, SKP_Silk_MAX_ORDER_LPC * sizeof( SKP_int32 ) );
/* Initialize */
CAb[ 0 ] = CAf[ 0 ] = C0 + SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1; // Q(-rshifts)
for( n = 0; n < D; n++ ) {
/* Update first row of correlation matrix (without first element) */
/* Update last row of correlation matrix (without last element, stored in reversed order) */
/* Update C * Af */
/* Update C * flipud(Af) (stored in reversed order) */
if( rshifts > -2 ) {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
x1 = -SKP_LSHIFT32( (SKP_int32)x_ptr[ n ], 16 - rshifts ); // Q(16-rshifts)
x2 = -SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts ); // Q(16-rshifts)
tmp1 = SKP_LSHIFT32( (SKP_int32)x_ptr[ n ], QA - 16 ); // Q(QA-16)
tmp2 = SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 ); // Q(QA-16)
for( k = 0; k < n; k++ ) {
C_first_row[ k ] = SKP_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts )
C_last_row[ k ] = SKP_SMLAWB( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts )
Atmp_QA = Af_QA[ k ];
tmp1 = SKP_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ] ); // Q(QA-16)
tmp2 = SKP_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] ); // Q(QA-16)
}
tmp1 = SKP_LSHIFT32( -tmp1, 32 - QA - rshifts ); // Q(16-rshifts)
tmp2 = SKP_LSHIFT32( -tmp2, 32 - QA - rshifts ); // Q(16-rshifts)
for( k = 0; k <= n; k++ ) {
CAf[ k ] = SKP_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ] ); // Q( -rshift )
CAb[ k ] = SKP_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] ); // Q( -rshift )
}
}
} else {
for( s = 0; s < nb_subfr; s++ ) {
x_ptr = x + s * subfr_length;
x1 = -SKP_LSHIFT32( (SKP_int32)x_ptr[ n ], -rshifts ); // Q( -rshifts )
x2 = -SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], -rshifts ); // Q( -rshifts )
tmp1 = SKP_LSHIFT32( (SKP_int32)x_ptr[ n ], 17 ); // Q17
tmp2 = SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n - 1 ], 17 ); // Q17
for( k = 0; k < n; k++ ) {
C_first_row[ k ] = SKP_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ] ); // Q( -rshifts )
C_last_row[ k ] = SKP_MLA( C_last_row[ k ], x2, x_ptr[ subfr_length - n + k ] ); // Q( -rshifts )
Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 17 ); // Q17
tmp1 = SKP_MLA( tmp1, x_ptr[ n - k - 1 ], Atmp1 ); // Q17
tmp2 = SKP_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 ); // Q17
}
tmp1 = -tmp1; // Q17
tmp2 = -tmp2; // Q17
for( k = 0; k <= n; k++ ) {
CAf[ k ] = SKP_SMLAWW( CAf[ k ], tmp1,
SKP_LSHIFT32( (SKP_int32)x_ptr[ n - k ], -rshifts - 1 ) ); // Q( -rshift )
CAb[ k ] = SKP_SMLAWW( CAb[ k ], tmp2,
SKP_LSHIFT32( (SKP_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) );// Q( -rshift )
}
}
}
/* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
tmp1 = C_first_row[ n ]; // Q( -rshifts )
tmp2 = C_last_row[ n ]; // Q( -rshifts )
num = 0; // Q( -rshifts )
nrg = SKP_ADD32( CAb[ 0 ], CAf[ 0 ] ); // Q( 1-rshifts )
for( k = 0; k < n; k++ ) {
Atmp_QA = Af_QA[ k ];
lz = SKP_Silk_CLZ32( SKP_abs( Atmp_QA ) ) - 1;
lz = SKP_min( 32 - QA, lz );
Atmp1 = SKP_LSHIFT32( Atmp_QA, lz ); // Q( QA + lz )
tmp1 = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( C_last_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts )
tmp2 = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts )
num = SKP_ADD_LSHIFT32( num, SKP_SMMUL( CAb[ n - k ], Atmp1 ), 32 - QA - lz ); // Q( -rshifts )
nrg = SKP_ADD_LSHIFT32( nrg, SKP_SMMUL( SKP_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ),
Atmp1 ), 32 - QA - lz ); // Q( 1-rshifts )
}
CAf[ n + 1 ] = tmp1; // Q( -rshifts )
CAb[ n + 1 ] = tmp2; // Q( -rshifts )
num = SKP_ADD32( num, tmp2 ); // Q( -rshifts )
num = SKP_LSHIFT32( -num, 1 ); // Q( 1-rshifts )
/* Calculate the next order reflection (parcor) coefficient */
if( SKP_abs( num ) < nrg ) {
rc_Q31 = SKP_DIV32_varQ( num, nrg, 31 );
} else {
/* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */
SKP_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( SKP_int32 ) );
SKP_assert( 0 );
break;
}
/* Update the AR coefficients */
for( k = 0; k < (n + 1) >> 1; k++ ) {
tmp1 = Af_QA[ k ]; // QA
tmp2 = Af_QA[ n - k - 1 ]; // QA
Af_QA[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // QA
Af_QA[ n - k - 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // QA
}
Af_QA[ n ] = SKP_RSHIFT32( rc_Q31, 31 - QA ); // QA
/* Update C * Af and C * Ab */
for( k = 0; k <= n + 1; k++ ) {
tmp1 = CAf[ k ]; // Q( -rshifts )
tmp2 = CAb[ n - k + 1 ]; // Q( -rshifts )
CAf[ k ] = SKP_ADD_LSHIFT32( tmp1, SKP_SMMUL( tmp2, rc_Q31 ), 1 ); // Q( -rshifts )
CAb[ n - k + 1 ] = SKP_ADD_LSHIFT32( tmp2, SKP_SMMUL( tmp1, rc_Q31 ), 1 ); // Q( -rshifts )
}
}
/* Return residual energy */
nrg = CAf[ 0 ]; // Q( -rshifts )
tmp1 = 1 << 16; // Q16
for( k = 0; k < D; k++ ) {
Atmp1 = SKP_RSHIFT_ROUND( Af_QA[ k ], QA - 16 ); // Q16
nrg = SKP_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 ); // Q( -rshifts )
tmp1 = SKP_SMLAWW( tmp1, Atmp1, Atmp1 ); // Q16
A_Q16[ k ] = -Atmp1;
}
*res_nrg = SKP_SMLAWW( nrg, SKP_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 ); // Q( -rshifts )
*res_nrg_Q = -rshifts;
}

View File

@ -0,0 +1,49 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SigProc_FIX.h"
/* Chirp (bandwidth expand) LP AR filter */
void SKP_Silk_bwexpander(
SKP_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
const SKP_int d, /* I Length of ar */
SKP_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
)
{
SKP_int i;
SKP_int32 chirp_minus_one_Q16;
chirp_minus_one_Q16 = chirp_Q16 - 65536;
/* NB: Dont use SKP_SMULWB, instead of SKP_RSHIFT_ROUND( SKP_MUL() , 16 ), below. */
/* Bias in SKP_SMULWB can lead to unstable filters */
for( i = 0; i < d - 1; i++ ) {
ar[ i ] = (SKP_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ i ] ), 16 );
chirp_Q16 += SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
}
ar[ d - 1 ] = (SKP_int16)SKP_RSHIFT_ROUND( SKP_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
}

View File

@ -0,0 +1,46 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SigProc_FIX.h"
/* Chirp (bandwidth expand) LP AR filter */
void SKP_Silk_bwexpander_32(
SKP_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
const SKP_int d, /* I Length of ar */
SKP_int32 chirp_Q16 /* I Chirp factor in Q16 */
)
{
SKP_int i;
SKP_int32 tmp_chirp_Q16;
tmp_chirp_Q16 = chirp_Q16;
for( i = 0; i < d - 1; i++ ) {
ar[ i ] = SKP_SMULWW( ar[ i ], tmp_chirp_Q16 );
tmp_chirp_Q16 = SKP_SMULWW( chirp_Q16, tmp_chirp_Q16 );
}
ar[ d - 1 ] = SKP_SMULWW( ar[ d - 1 ], tmp_chirp_Q16 );
}

View File

@ -0,0 +1,122 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#if defined(__arm__)
#include "SKP_Silk_AsmPreproc.h"
#if (EMBEDDED_ARM>0) && (EMBEDDED_ARM<5)
.globl SYM(SKP_Silk_CLZ16)
.globl SYM(SKP_Silk_CLZ32)
SYM(SKP_Silk_CLZ16):
str lr, [sp, #-4]!
mov r2, r0
mov r0, #0
ands r1, r2, #0xF000
movne r1, r2, asr #12
bne 0f
add r0, r0, #4
ands r1, r2, #0xF00
movne r1, r2, asr #8
bne 0f
add r0, r0, #4
ands r1, r2, #0xF0
movne r1, r2, asr #4
bne 0f
add r0, r0, #4
mov r1, r2
0:
ands r2, r1, #0x8
bne 1f
add r0, r0, #1
ands r2, r1, #0x4
bne 1f
add r0, r0, #1
ands r2, r1, #0x2
bne 1f
add r0, r0, #1
ands r2, r1, #0x1
bne 1f
add r0, r0, #1
1:
ldr pc, [sp], #4
SYM(SKP_Silk_CLZ32):
str lr, [sp, #-4]!
mov r2, r0
mov r0, #0
ands r1, r2, #0xF0000000
movne r1, r2, asr #28
bne 0f
add r0, r0, #4
ands r1, r2, #0xF000000
movne r1, r2, asr #24
bne 0f
add r0, r0, #4
ands r1, r2, #0xF00000
movne r1, r2, asr #20
bne 0f
add r0, r0, #4
ands r1, r2, #0xF0000
movne r1, r2, asr #16
bne 0f
add r0, r0, #4
ands r1, r2, #0xF000
movne r1, r2, asr #12
bne 0f
add r0, r0, #4
ands r1, r2, #0xF00
movne r1, r2, asr #8
bne 0f
add r0, r0, #4
ands r1, r2, #0xF0
movne r1, r2, asr #4
bne 0f
add r0, r0, #4
mov r1, r2
0:
ands r2, r1, #0x8
bne 1f
add r0, r0, #1
ands r2, r1, #0x4
bne 1f
add r0, r0, #1
ands r2, r1, #0x2
bne 1f
add r0, r0, #1
ands r2, r1, #0x1
bne 1f
add r0, r0, #1
1:
ldr pc, [sp], #4
#endif
#endif

View File

@ -0,0 +1,91 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
//#define SKP_enc_map(a) ((a) > 0 ? 1 : 0)
//#define SKP_dec_map(a) ((a) > 0 ? 1 : -1)
/* shifting avoids if-statement */
#define SKP_enc_map(a) ( SKP_RSHIFT( (a), 15 ) + 1 )
#define SKP_dec_map(a) ( SKP_LSHIFT( (a), 1 ) - 1 )
/* Encodes signs of excitation */
void SKP_Silk_encode_signs(
SKP_Silk_range_coder_state *sRC, /* I/O Range coder state */
const SKP_int8 q[], /* I Pulse signal */
const SKP_int length, /* I Length of input */
const SKP_int sigtype, /* I Signal type */
const SKP_int QuantOffsetType, /* I Quantization offset type */
const SKP_int RateLevelIndex /* I Rate level index */
)
{
SKP_int i;
SKP_int inData;
SKP_uint16 cdf[ 3 ];
i = SKP_SMULBB( N_RATE_LEVELS - 1, SKP_LSHIFT( sigtype, 1 ) + QuantOffsetType ) + RateLevelIndex;
cdf[ 0 ] = 0;
cdf[ 1 ] = SKP_Silk_sign_CDF[ i ];
cdf[ 2 ] = 65535;
for( i = 0; i < length; i++ ) {
if( q[ i ] != 0 ) {
inData = SKP_enc_map( q[ i ] ); /* - = 0, + = 1 */
SKP_Silk_range_encoder( sRC, inData, cdf );
}
}
}
/* Decodes signs of excitation */
void SKP_Silk_decode_signs(
SKP_Silk_range_coder_state *sRC, /* I/O Range coder state */
SKP_int q[], /* I/O pulse signal */
const SKP_int length, /* I length of output */
const SKP_int sigtype, /* I Signal type */
const SKP_int QuantOffsetType, /* I Quantization offset type */
const SKP_int RateLevelIndex /* I Rate Level Index */
)
{
SKP_int i;
SKP_int data;
SKP_uint16 cdf[ 3 ];
i = SKP_SMULBB( N_RATE_LEVELS - 1, SKP_LSHIFT( sigtype, 1 ) + QuantOffsetType ) + RateLevelIndex;
cdf[ 0 ] = 0;
cdf[ 1 ] = SKP_Silk_sign_CDF[ i ];
cdf[ 2 ] = 65535;
for( i = 0; i < length; i++ ) {
if( q[ i ] > 0 ) {
SKP_Silk_range_decoder( &data, sRC, cdf, 1 );
/* attach sign */
/* implementation with shift, subtraction, multiplication */
q[ i ] *= SKP_dec_map( data );
}
}
}

View File

@ -0,0 +1,76 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SIGPROC_COMMON_PITCH_EST_DEFINES_H
#define SIGPROC_COMMON_PITCH_EST_DEFINES_H
#include "SKP_Silk_SigProc_FIX.h"
/************************************************************/
/* Definitions For Fix pitch estimator */
/************************************************************/
#define PITCH_EST_MAX_FS_KHZ 24 /* Maximum sampling frequency used */
#define PITCH_EST_FRAME_LENGTH_MS 40 /* 40 ms */
#define PITCH_EST_MAX_FRAME_LENGTH (PITCH_EST_FRAME_LENGTH_MS * PITCH_EST_MAX_FS_KHZ)
#define PITCH_EST_MAX_FRAME_LENGTH_ST_1 (PITCH_EST_MAX_FRAME_LENGTH >> 2)
#define PITCH_EST_MAX_FRAME_LENGTH_ST_2 (PITCH_EST_MAX_FRAME_LENGTH >> 1)
#define PITCH_EST_MAX_SF_FRAME_LENGTH (PITCH_EST_SUB_FRAME * PITCH_EST_MAX_FS_KHZ)
#define PITCH_EST_MAX_LAG_MS 18 /* 18 ms -> 56 Hz */
#define PITCH_EST_MIN_LAG_MS 2 /* 2 ms -> 500 Hz */
#define PITCH_EST_MAX_LAG (PITCH_EST_MAX_LAG_MS * PITCH_EST_MAX_FS_KHZ)
#define PITCH_EST_MIN_LAG (PITCH_EST_MIN_LAG_MS * PITCH_EST_MAX_FS_KHZ)
#define PITCH_EST_NB_SUBFR 4
#define PITCH_EST_D_SRCH_LENGTH 24
#define PITCH_EST_MAX_DECIMATE_STATE_LENGTH 7
#define PITCH_EST_NB_STAGE3_LAGS 5
#define PITCH_EST_NB_CBKS_STAGE2 3
#define PITCH_EST_NB_CBKS_STAGE2_EXT 11
#define PITCH_EST_CB_mn2 1
#define PITCH_EST_CB_mx2 2
#define PITCH_EST_NB_CBKS_STAGE3_MAX 34
#define PITCH_EST_NB_CBKS_STAGE3_MID 24
#define PITCH_EST_NB_CBKS_STAGE3_MIN 16
extern const SKP_int16 SKP_Silk_CB_lags_stage2[PITCH_EST_NB_SUBFR][PITCH_EST_NB_CBKS_STAGE2_EXT];
extern const SKP_int16 SKP_Silk_CB_lags_stage3[PITCH_EST_NB_SUBFR][PITCH_EST_NB_CBKS_STAGE3_MAX];
extern const SKP_int16 SKP_Silk_Lag_range_stage3[ SKP_Silk_PITCH_EST_MAX_COMPLEX + 1 ] [ PITCH_EST_NB_SUBFR ][ 2 ];
extern const SKP_int16 SKP_Silk_cbk_sizes_stage3[ SKP_Silk_PITCH_EST_MAX_COMPLEX + 1 ];
extern const SKP_int16 SKP_Silk_cbk_offsets_stage3[ SKP_Silk_PITCH_EST_MAX_COMPLEX + 1 ];
#endif

View File

@ -0,0 +1,137 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Control internal sampling rate */
SKP_int SKP_Silk_control_audio_bandwidth(
SKP_Silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
const SKP_int32 TargetRate_bps /* I Target max bitrate (bps) */
)
{
SKP_int fs_kHz;
fs_kHz = psEncC->fs_kHz;
if( fs_kHz == 0 ) {
/* Encoder has just been initialized */
if( TargetRate_bps >= SWB2WB_BITRATE_BPS ) {
fs_kHz = 24;
} else if( TargetRate_bps >= WB2MB_BITRATE_BPS ) {
fs_kHz = 16;
} else if( TargetRate_bps >= MB2NB_BITRATE_BPS ) {
fs_kHz = 12;
} else {
fs_kHz = 8;
}
/* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
fs_kHz = SKP_min( fs_kHz, SKP_DIV32_16( psEncC->API_fs_Hz, 1000 ) );
fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
} else if( SKP_SMULBB( fs_kHz, 1000 ) > psEncC->API_fs_Hz || fs_kHz > psEncC->maxInternal_fs_kHz ) {
/* Make sure internal rate is not higher than external rate or maximum allowed */
fs_kHz = SKP_DIV32_16( psEncC->API_fs_Hz, 1000 );
fs_kHz = SKP_min( fs_kHz, psEncC->maxInternal_fs_kHz );
} else {
/* State machine for the internal sampling rate switching */
if( psEncC->API_fs_Hz > 8000 ) {
/* Accumulate the difference between the target rate and limit for switching down */
psEncC->bitrateDiff += SKP_MUL( psEncC->PacketSize_ms, TargetRate_bps - psEncC->bitrate_threshold_down );
psEncC->bitrateDiff = SKP_min( psEncC->bitrateDiff, 0 );
if( psEncC->vadFlag == NO_VOICE_ACTIVITY ) { /* Low speech activity */
/* Check if we should switch down */
#if SWITCH_TRANSITION_FILTERING
if( ( psEncC->sLP.transition_frame_no == 0 ) && /* Transition phase not active */
( psEncC->bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD || /* Bitrate threshold is met */
( psEncC->sSWBdetect.WB_detected * psEncC->fs_kHz == 24 ) ) ) { /* Forced down-switching due to WB input */
psEncC->sLP.transition_frame_no = 1; /* Begin transition phase */
psEncC->sLP.mode = 0; /* Switch down */
} else if(
( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES_DOWN ) && /* Transition phase complete */
( psEncC->sLP.mode == 0 ) ) { /* Ready to switch down */
psEncC->sLP.transition_frame_no = 0; /* Ready for new transition phase */
#else
if( psEncC->bitrateDiff <= -ACCUM_BITS_DIFF_THRESHOLD ) { /* Bitrate threshold is met */
#endif
psEncC->bitrateDiff = 0;
/* Switch to a lower sample frequency */
if( psEncC->fs_kHz == 24 ) {
fs_kHz = 16;
} else if( psEncC->fs_kHz == 16 ) {
fs_kHz = 12;
} else {
SKP_assert( psEncC->fs_kHz == 12 );
fs_kHz = 8;
}
}
/* Check if we should switch up */
if( ( ( psEncC->fs_kHz * 1000 < psEncC->API_fs_Hz ) &&
( TargetRate_bps >= psEncC->bitrate_threshold_up ) &&
( psEncC->sSWBdetect.WB_detected * psEncC->fs_kHz < 16 ) ) &&
( ( ( psEncC->fs_kHz == 16 ) && ( psEncC->maxInternal_fs_kHz >= 24 ) ) ||
( ( psEncC->fs_kHz == 12 ) && ( psEncC->maxInternal_fs_kHz >= 16 ) ) ||
( ( psEncC->fs_kHz == 8 ) && ( psEncC->maxInternal_fs_kHz >= 12 ) ) )
#if SWITCH_TRANSITION_FILTERING
&& ( psEncC->sLP.transition_frame_no == 0 ) ) { /* No transition phase running, ready to switch */
psEncC->sLP.mode = 1; /* Switch up */
#else
) {
#endif
psEncC->bitrateDiff = 0;
/* Switch to a higher sample frequency */
if( psEncC->fs_kHz == 8 ) {
fs_kHz = 12;
} else if( psEncC->fs_kHz == 12 ) {
fs_kHz = 16;
} else {
SKP_assert( psEncC->fs_kHz == 16 );
fs_kHz = 24;
}
}
}
}
#if SWITCH_TRANSITION_FILTERING
/* After switching up, stop transition filter during speech inactivity */
if( ( psEncC->sLP.mode == 1 ) &&
( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES_UP ) &&
( psEncC->vadFlag == NO_VOICE_ACTIVITY ) ) {
psEncC->sLP.transition_frame_no = 0;
/* Reset transition filter state */
SKP_memset( psEncC->sLP.In_LP_State, 0, 2 * sizeof( SKP_int32 ) );
}
#endif
}
return fs_kHz;
}

View File

@ -0,0 +1,402 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_setup_complexity.h"
SKP_INLINE SKP_int SKP_Silk_setup_resamplers_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
);
SKP_INLINE SKP_int SKP_Silk_setup_packetsize_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int PacketSize_ms /* I Packet length (ms) */
);
SKP_INLINE SKP_int SKP_Silk_setup_fs_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
);
SKP_INLINE SKP_int SKP_Silk_setup_rate_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int32 TargetRate_bps /* I Target max bitrate (if SNR_dB == 0) */
);
SKP_INLINE SKP_int SKP_Silk_setup_LBRR_FIX(
SKP_Silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk encoder state FIX */
);
/* Control encoder */
SKP_int SKP_Silk_control_encoder_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state */
const SKP_int PacketSize_ms, /* I Packet length (ms) */
const SKP_int32 TargetRate_bps, /* I Target max bitrate (bps) */
const SKP_int PacketLoss_perc, /* I Packet loss rate (in percent) */
const SKP_int DTX_enabled, /* I Enable / disable DTX */
const SKP_int Complexity /* I Complexity (0->low; 1->medium; 2->high) */
)
{
SKP_int fs_kHz, ret = 0;
if( psEnc->sCmn.controlled_since_last_payload != 0 ) {
if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {
/* Change in API sampling rate in the middle of encoding a packet */
ret += SKP_Silk_setup_resamplers_FIX( psEnc, psEnc->sCmn.fs_kHz );
}
return ret;
}
/* Beyond this point we know that there are no previously coded frames in the payload buffer */
/********************************************/
/* Determine internal sampling rate */
/********************************************/
fs_kHz = SKP_Silk_control_audio_bandwidth( &psEnc->sCmn, TargetRate_bps );
/********************************************/
/* Prepare resampler and buffered data */
/********************************************/
ret += SKP_Silk_setup_resamplers_FIX( psEnc, fs_kHz );
/********************************************/
/* Set packet size */
/********************************************/
ret += SKP_Silk_setup_packetsize_FIX( psEnc, PacketSize_ms );
/********************************************/
/* Set internal sampling frequency */
/********************************************/
ret += SKP_Silk_setup_fs_FIX( psEnc, fs_kHz );
/********************************************/
/* Set encoding complexity */
/********************************************/
ret += SKP_Silk_setup_complexity( &psEnc->sCmn, Complexity );
/********************************************/
/* Set bitrate/coding quality */
/********************************************/
ret += SKP_Silk_setup_rate_FIX( psEnc, TargetRate_bps );
/********************************************/
/* Set packet loss rate measured by farend */
/********************************************/
if( ( PacketLoss_perc < 0 ) || ( PacketLoss_perc > 100 ) ) {
ret = SKP_SILK_ENC_INVALID_LOSS_RATE;
}
psEnc->sCmn.PacketLoss_perc = PacketLoss_perc;
/********************************************/
/* Set LBRR usage */
/********************************************/
ret += SKP_Silk_setup_LBRR_FIX( psEnc );
/********************************************/
/* Set DTX mode */
/********************************************/
if( DTX_enabled < 0 || DTX_enabled > 1 ) {
ret = SKP_SILK_ENC_INVALID_DTX_SETTING;
}
psEnc->sCmn.useDTX = DTX_enabled;
psEnc->sCmn.controlled_since_last_payload = 1;
return ret;
}
/* Control low bitrate redundancy usage */
void SKP_Silk_LBRR_ctrl_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I Encoder state FIX */
SKP_Silk_encoder_control *psEncCtrlC /* I/O Encoder control */
)
{
SKP_int LBRR_usage;
if( psEnc->sCmn.LBRR_enabled ) {
/* Control LBRR */
/* Usage Control based on sensitivity and packet loss caracteristics */
/* For now only enable adding to next for active frames. Make more complex later */
LBRR_usage = SKP_SILK_NO_LBRR;
if( psEnc->speech_activity_Q8 > SKP_FIX_CONST( LBRR_SPEECH_ACTIVITY_THRES, 8 ) && psEnc->sCmn.PacketLoss_perc > LBRR_LOSS_THRES ) { // nb! maybe multiply loss prob and speech activity
LBRR_usage = SKP_SILK_ADD_LBRR_TO_PLUS1;
}
psEncCtrlC->LBRR_usage = LBRR_usage;
} else {
psEncCtrlC->LBRR_usage = SKP_SILK_NO_LBRR;
}
}
SKP_INLINE SKP_int SKP_Silk_setup_resamplers_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR;
if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz ) {
if( psEnc->sCmn.fs_kHz == 0 ) {
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret += SKP_Silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 );
} else {
/* Allocate space for worst case temporary upsampling, 8 to 48 kHz, so a factor 6 */
SKP_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ) * ( MAX_API_FS_KHZ / 8 ) ];
SKP_int32 nSamples_temp = SKP_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;
if( SKP_SMULBB( fs_kHz, 1000 ) < psEnc->sCmn.API_fs_Hz && psEnc->sCmn.fs_kHz != 0 ) {
/* Resample buffered data in x_buf to API_fs_Hz */
SKP_Silk_resampler_state_struct temp_resampler_state;
/* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
ret += SKP_Silk_resampler_init( &temp_resampler_state, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz );
/* Temporary resampling of x_buf data to API_fs_Hz */
ret += SKP_Silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, psEnc->x_buf, nSamples_temp );
/* Calculate number of samples that has been temporarily upsampled */
nSamples_temp = SKP_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, SKP_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
/* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
ret += SKP_Silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, SKP_SMULBB( fs_kHz, 1000 ) );
} else {
/* Copy data */
SKP_memcpy( x_buf_API_fs_Hz, psEnc->x_buf, nSamples_temp * sizeof( SKP_int16 ) );
}
if( 1000 * fs_kHz != psEnc->sCmn.API_fs_Hz ) {
/* Correct resampler state (unless resampling by a factor 1) by resampling buffered data from API_fs_Hz to fs_kHz */
ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state, psEnc->x_buf, x_buf_API_fs_Hz, nSamples_temp );
}
}
}
psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
return(ret);
}
SKP_INLINE SKP_int SKP_Silk_setup_packetsize_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int PacketSize_ms /* I Packet length (ms) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR;
/* Set packet size */
if( ( PacketSize_ms != 20 ) &&
( PacketSize_ms != 40 ) &&
( PacketSize_ms != 60 ) &&
( PacketSize_ms != 80 ) &&
( PacketSize_ms != 100 ) ) {
ret = SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
} else {
if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) {
psEnc->sCmn.PacketSize_ms = PacketSize_ms;
/* Packet length changes. Reset LBRR buffer */
SKP_Silk_LBRR_reset( &psEnc->sCmn );
}
}
return(ret);
}
SKP_INLINE SKP_int SKP_Silk_setup_fs_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int fs_kHz /* I Internal sampling rate (kHz) */
)
{
SKP_int ret = SKP_SILK_NO_ERROR;
/* Set internal sampling frequency */
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
/* reset part of the state */
SKP_memset( &psEnc->sShape, 0, sizeof( SKP_Silk_shape_state_FIX ) );
SKP_memset( &psEnc->sPrefilt, 0, sizeof( SKP_Silk_prefilter_state_FIX ) );
SKP_memset( &psEnc->sPred, 0, sizeof( SKP_Silk_predict_state_FIX ) );
SKP_memset( &psEnc->sCmn.sNSQ, 0, sizeof( SKP_Silk_nsq_state ) );
SKP_memset( psEnc->sCmn.sNSQ_LBRR.xq, 0, ( 2 * MAX_FRAME_LENGTH ) * sizeof( SKP_int16 ) );
SKP_memset( psEnc->sCmn.LBRR_buffer, 0, MAX_LBRR_DELAY * sizeof( SKP_SILK_LBRR_struct ) );
#if SWITCH_TRANSITION_FILTERING
SKP_memset( psEnc->sCmn.sLP.In_LP_State, 0, 2 * sizeof( SKP_int32 ) );
if( psEnc->sCmn.sLP.mode == 1 ) {
/* Begin transition phase */
psEnc->sCmn.sLP.transition_frame_no = 1;
} else {
/* End transition phase */
psEnc->sCmn.sLP.transition_frame_no = 0;
}
#endif
psEnc->sCmn.inputBufIx = 0;
psEnc->sCmn.nFramesInPayloadBuf = 0;
psEnc->sCmn.nBytesInPayloadBuf = 0;
psEnc->sCmn.oldest_LBRR_idx = 0;
psEnc->sCmn.TargetRate_bps = 0; /* Ensures that psEnc->SNR_dB is recomputed */
SKP_memset( psEnc->sPred.prev_NLSFq_Q15, 0, MAX_LPC_ORDER * sizeof( SKP_int ) );
/* Initialize non-zero parameters */
psEnc->sCmn.prevLag = 100;
psEnc->sCmn.prev_sigtype = SIG_TYPE_UNVOICED;
psEnc->sCmn.first_frame_after_reset = 1;
psEnc->sPrefilt.lagPrev = 100;
psEnc->sShape.LastGainIndex = 1;
psEnc->sCmn.sNSQ.lagPrev = 100;
psEnc->sCmn.sNSQ.prev_inv_gain_Q16 = 65536;
psEnc->sCmn.sNSQ_LBRR.prev_inv_gain_Q16 = 65536;
psEnc->sCmn.fs_kHz = fs_kHz;
if( psEnc->sCmn.fs_kHz == 8 ) {
psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER;
psEnc->sCmn.psNLSF_CB[ 0 ] = &SKP_Silk_NLSF_CB0_10;
psEnc->sCmn.psNLSF_CB[ 1 ] = &SKP_Silk_NLSF_CB1_10;
} else {
psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER;
psEnc->sCmn.psNLSF_CB[ 0 ] = &SKP_Silk_NLSF_CB0_16;
psEnc->sCmn.psNLSF_CB[ 1 ] = &SKP_Silk_NLSF_CB1_16;
}
psEnc->sCmn.frame_length = SKP_SMULBB( FRAME_LENGTH_MS, fs_kHz );
psEnc->sCmn.subfr_length = SKP_DIV32_16( psEnc->sCmn.frame_length, NB_SUBFR );
psEnc->sCmn.la_pitch = SKP_SMULBB( LA_PITCH_MS, fs_kHz );
psEnc->sPred.min_pitch_lag = SKP_SMULBB( 3, fs_kHz );
psEnc->sPred.max_pitch_lag = SKP_SMULBB( 18, fs_kHz );
psEnc->sPred.pitch_LPC_win_length = SKP_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
if( psEnc->sCmn.fs_kHz == 24 ) {
psEnc->mu_LTP_Q8 = SKP_FIX_CONST( MU_LTP_QUANT_SWB, 8 );
psEnc->sCmn.bitrate_threshold_up = SKP_int32_MAX;
psEnc->sCmn.bitrate_threshold_down = SWB2WB_BITRATE_BPS;
} else if( psEnc->sCmn.fs_kHz == 16 ) {
psEnc->mu_LTP_Q8 = SKP_FIX_CONST( MU_LTP_QUANT_WB, 8 );
psEnc->sCmn.bitrate_threshold_up = WB2SWB_BITRATE_BPS;
psEnc->sCmn.bitrate_threshold_down = WB2MB_BITRATE_BPS;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
psEnc->mu_LTP_Q8 = SKP_FIX_CONST( MU_LTP_QUANT_MB, 8 );
psEnc->sCmn.bitrate_threshold_up = MB2WB_BITRATE_BPS;
psEnc->sCmn.bitrate_threshold_down = MB2NB_BITRATE_BPS;
} else {
psEnc->mu_LTP_Q8 = SKP_FIX_CONST( MU_LTP_QUANT_NB, 8 );
psEnc->sCmn.bitrate_threshold_up = NB2MB_BITRATE_BPS;
psEnc->sCmn.bitrate_threshold_down = 0;
}
psEnc->sCmn.fs_kHz_changed = 1;
/* Check that settings are valid */
SKP_assert( ( psEnc->sCmn.subfr_length * NB_SUBFR ) == psEnc->sCmn.frame_length );
}
return( ret );
}
SKP_INLINE SKP_int SKP_Silk_setup_rate_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state FIX */
SKP_int32 TargetRate_bps /* I Target max bitrate (if SNR_dB == 0) */
)
{
SKP_int k, ret = SKP_SILK_NO_ERROR;
SKP_int32 frac_Q6;
const SKP_int32 *rateTable;
/* Set bitrate/coding quality */
if( TargetRate_bps != psEnc->sCmn.TargetRate_bps ) {
psEnc->sCmn.TargetRate_bps = TargetRate_bps;
/* If new TargetRate_bps, translate to SNR_dB value */
if( psEnc->sCmn.fs_kHz == 8 ) {
rateTable = TargetRate_table_NB;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
rateTable = TargetRate_table_MB;
} else if( psEnc->sCmn.fs_kHz == 16 ) {
rateTable = TargetRate_table_WB;
} else {
rateTable = TargetRate_table_SWB;
}
for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
/* Find bitrate interval in table and interpolate */
if( TargetRate_bps <= rateTable[ k ] ) {
frac_Q6 = SKP_DIV32( SKP_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
rateTable[ k ] - rateTable[ k - 1 ] );
psEnc->SNR_dB_Q7 = SKP_LSHIFT( SNR_table_Q1[ k - 1 ], 6 ) + SKP_MUL( frac_Q6, SNR_table_Q1[ k ] - SNR_table_Q1[ k - 1 ] );
break;
}
}
}
return( ret );
}
SKP_INLINE SKP_int SKP_Silk_setup_LBRR_FIX(
SKP_Silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk encoder state FIX */
)
{
SKP_int ret = SKP_SILK_NO_ERROR;
#if USE_LBRR
SKP_int32 LBRRRate_thres_bps;
if( psEnc->sCmn.useInBandFEC < 0 || psEnc->sCmn.useInBandFEC > 1 ) {
ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;
}
psEnc->sCmn.LBRR_enabled = psEnc->sCmn.useInBandFEC;
if( psEnc->sCmn.fs_kHz == 8 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 9000;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 6000;;
} else if( psEnc->sCmn.fs_kHz == 16 ) {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS - 3000;
} else {
LBRRRate_thres_bps = INBAND_FEC_MIN_RATE_BPS;
}
if( psEnc->sCmn.TargetRate_bps >= LBRRRate_thres_bps ) {
/* Set gain increase / rate reduction for LBRR usage */
/* Coarsely tuned with PESQ for now. */
/* Linear regression coefs G = 8 - 0.5 * loss */
/* Meaning that at 16% loss main rate and redundant rate is the same, -> G = 0 */
psEnc->sCmn.LBRR_GainIncreases = SKP_max_int( 8 - SKP_RSHIFT( psEnc->sCmn.PacketLoss_perc, 1 ), 0 );
/* Set main stream rate compensation */
if( psEnc->sCmn.LBRR_enabled && psEnc->sCmn.PacketLoss_perc > LBRR_LOSS_THRES ) {
/* Tuned to give approx same mean / weighted bitrate as no inband FEC */
psEnc->inBandFEC_SNR_comp_Q8 = SKP_FIX_CONST( 6.0f, 8 ) - SKP_LSHIFT( psEnc->sCmn.LBRR_GainIncreases, 7 );
} else {
psEnc->inBandFEC_SNR_comp_Q8 = 0;
psEnc->sCmn.LBRR_enabled = 0;
}
} else {
psEnc->inBandFEC_SNR_comp_Q8 = 0;
psEnc->sCmn.LBRR_enabled = 0;
}
#else
if( INBandFEC_enabled != 0 ) {
ret = SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING;
}
psEnc->sCmn.LBRR_enabled = 0;
#endif
return ret;
}

View File

@ -0,0 +1,153 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/**********************************************************************
* Correlation Matrix Computations for LS estimate.
**********************************************************************/
#include "SKP_Silk_main_FIX.h"
/* Calculates correlation vector X'*t */
void SKP_Silk_corrVector_FIX(
const SKP_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const SKP_int16 *t, /* I target vector [L] */
const SKP_int L, /* I Length of vectors */
const SKP_int order, /* I Max lag for correlation */
SKP_int32 *Xt, /* O Pointer to X'*t correlation vector [order] */
const SKP_int rshifts /* I Right shifts of correlations */
)
{
SKP_int lag, i;
const SKP_int16 *ptr1, *ptr2;
SKP_int32 inner_prod;
ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */
ptr2 = t;
/* Calculate X'*t */
if( rshifts > 0 ) {
/* Right shifting used */
for( lag = 0; lag < order; lag++ ) {
inner_prod = 0;
for( i = 0; i < L; i++ ) {
inner_prod += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
}
Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
ptr1--; /* Go to next column of X */
}
} else {
SKP_assert( rshifts == 0 );
for( lag = 0; lag < order; lag++ ) {
Xt[ lag ] = SKP_Silk_inner_prod_aligned( ptr1, ptr2, L ); /* X[:,lag]'*t */
ptr1--; /* Go to next column of X */
}
}
}
/* Calculates correlation matrix X'*X */
void SKP_Silk_corrMatrix_FIX(
const SKP_int16 *x, /* I x vector [L + order - 1] used to form data matrix X */
const SKP_int L, /* I Length of vectors */
const SKP_int order, /* I Max lag for correlation */
const SKP_int head_room, /* I Desired headroom */
SKP_int32 *XX, /* O Pointer to X'*X correlation matrix [ order x order ]*/
SKP_int *rshifts /* I/O Right shifts of correlations */
)
{
SKP_int i, j, lag, rshifts_local, head_room_rshifts;
SKP_int32 energy;
const SKP_int16 *ptr1, *ptr2;
/* Calculate energy to find shift used to fit in 32 bits */
SKP_Silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
/* Add shifts to get the desired head room */
head_room_rshifts = SKP_max( head_room - SKP_Silk_CLZ32( energy ), 0 );
energy = SKP_RSHIFT32( energy, head_room_rshifts );
rshifts_local += head_room_rshifts;
/* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
/* Remove contribution of first order - 1 samples */
for( i = 0; i < order - 1; i++ ) {
energy -= SKP_RSHIFT32( SKP_SMULBB( x[ i ], x[ i ] ), rshifts_local );
}
if( rshifts_local < *rshifts ) {
/* Adjust energy */
energy = SKP_RSHIFT32( energy, *rshifts - rshifts_local );
rshifts_local = *rshifts;
}
/* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
/* Fill out the diagonal of the correlation matrix */
matrix_ptr( XX, 0, 0, order ) = energy;
ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
for( j = 1; j < order; j++ ) {
energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
matrix_ptr( XX, j, j, order ) = energy;
}
ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
/* Calculate the remaining elements of the correlation matrix */
if( rshifts_local > 0 ) {
/* Right shifting used */
for( lag = 1; lag < order; lag++ ) {
/* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
energy = 0;
for( i = 0; i < L; i++ ) {
energy += SKP_RSHIFT32( SKP_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
}
/* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
matrix_ptr( XX, lag, 0, order ) = energy;
matrix_ptr( XX, 0, lag, order ) = energy;
for( j = 1; j < ( order - lag ); j++ ) {
energy = SKP_SUB32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
energy = SKP_ADD32( energy, SKP_RSHIFT32( SKP_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
matrix_ptr( XX, lag + j, j, order ) = energy;
matrix_ptr( XX, j, lag + j, order ) = energy;
}
ptr2--; /* Update pointer to first sample of next column (lag) in X */
}
} else {
for( lag = 1; lag < order; lag++ ) {
/* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
energy = SKP_Silk_inner_prod_aligned( ptr1, ptr2, L );
matrix_ptr( XX, lag, 0, order ) = energy;
matrix_ptr( XX, 0, lag, order ) = energy;
/* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
for( j = 1; j < ( order - lag ); j++ ) {
energy = SKP_SUB32( energy, SKP_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) );
energy = SKP_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] );
matrix_ptr( XX, lag + j, j, order ) = energy;
matrix_ptr( XX, j, lag + j, order ) = energy;
}
ptr2--;/* Update pointer to first sample of next column (lag) in X */
}
}
*rshifts = rshifts_local;
}

View File

@ -0,0 +1,53 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/************************/
/* Init Decoder State */
/************************/
SKP_int SKP_Silk_init_decoder(
SKP_Silk_decoder_state *psDec /* I/O Decoder state pointer */
)
{
SKP_memset( psDec, 0, sizeof( SKP_Silk_decoder_state ) );
/* Set sampling rate to 24 kHz, and init non-zero values */
SKP_Silk_decoder_set_fs( psDec, 24 );
/* Used to deactivate e.g. LSF interpolation and fluctuation reduction */
psDec->first_frame_after_reset = 1;
psDec->prev_inv_gain_Q16 = 65536;
/* Reset CNG state */
SKP_Silk_CNG_Reset( psDec );
SKP_Silk_PLC_Reset( psDec );
return(0);
}

View File

@ -0,0 +1,279 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_SDK_API.h"
#include "SKP_Silk_main.h"
/*********************/
/* Decoder functions */
/*********************/
SKP_int SKP_Silk_SDK_Get_Decoder_Size( SKP_int32 *decSizeBytes )
{
SKP_int ret = 0;
*decSizeBytes = sizeof( SKP_Silk_decoder_state );
return ret;
}
/* Reset decoder state */
SKP_int SKP_Silk_SDK_InitDecoder(
void* decState /* I/O: State */
)
{
SKP_int ret = 0;
SKP_Silk_decoder_state *struc;
struc = (SKP_Silk_decoder_state *)decState;
ret = SKP_Silk_init_decoder( struc );
return ret;
}
/* Decode a frame */
SKP_int SKP_Silk_SDK_Decode(
void* decState, /* I/O: State */
SKP_SILK_SDK_DecControlStruct* decControl, /* I/O: Control structure */
SKP_int lostFlag, /* I: 0: no loss, 1 loss */
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input Bytes */
SKP_int16 *samplesOut, /* O: Decoded output speech vector */
SKP_int16 *nSamplesOut /* I/O: Number of samples (vector/decoded) */
)
{
SKP_int ret = 0, used_bytes, prev_fs_kHz;
SKP_Silk_decoder_state *psDec;
SKP_int16 samplesOutInternal[ MAX_API_FS_KHZ * FRAME_LENGTH_MS ];
SKP_int16 *pSamplesOutInternal;
psDec = (SKP_Silk_decoder_state *)decState;
/* We need this buffer to have room for an internal frame */
pSamplesOutInternal = samplesOut;
if( psDec->fs_kHz * 1000 > decControl->API_sampleRate ) {
pSamplesOutInternal = samplesOutInternal;
}
/**********************************/
/* Test if first frame in payload */
/**********************************/
if( psDec->moreInternalDecoderFrames == 0 ) {
/* First Frame in Payload */
psDec->nFramesDecoded = 0; /* Used to count frames in packet */
}
if( psDec->moreInternalDecoderFrames == 0 && /* First frame in packet */
lostFlag == 0 && /* Not packet loss */
nBytesIn > MAX_ARITHM_BYTES ) { /* Too long payload */
/* Avoid trying to decode a too large packet */
lostFlag = 1;
ret = SKP_SILK_DEC_PAYLOAD_TOO_LARGE;
}
/* Save previous sample frequency */
prev_fs_kHz = psDec->fs_kHz;
/* Call decoder for one frame */
ret += SKP_Silk_decode_frame( psDec, pSamplesOutInternal, nSamplesOut, inData, nBytesIn,
lostFlag, &used_bytes );
if( used_bytes ) { /* Only Call if not a packet loss */
if( psDec->nBytesLeft > 0 && psDec->FrameTermination == SKP_SILK_MORE_FRAMES && psDec->nFramesDecoded < 5 ) {
/* We have more frames in the Payload */
psDec->moreInternalDecoderFrames = 1;
} else {
/* Last frame in Payload */
psDec->moreInternalDecoderFrames = 0;
psDec->nFramesInPacket = psDec->nFramesDecoded;
/* Track inband FEC usage */
if( psDec->vadFlag == VOICE_ACTIVITY ) {
if( psDec->FrameTermination == SKP_SILK_LAST_FRAME ) {
psDec->no_FEC_counter++;
if( psDec->no_FEC_counter > NO_LBRR_THRES ) {
psDec->inband_FEC_offset = 0;
}
} else if( psDec->FrameTermination == SKP_SILK_LBRR_VER1 ) {
psDec->inband_FEC_offset = 1; /* FEC info with 1 packet delay */
psDec->no_FEC_counter = 0;
} else if( psDec->FrameTermination == SKP_SILK_LBRR_VER2 ) {
psDec->inband_FEC_offset = 2; /* FEC info with 2 packets delay */
psDec->no_FEC_counter = 0;
}
}
}
}
if( MAX_API_FS_KHZ * 1000 < decControl->API_sampleRate ||
8000 > decControl->API_sampleRate ) {
ret = SKP_SILK_DEC_INVALID_SAMPLING_FREQUENCY;
return( ret );
}
/* Resample if needed */
if( psDec->fs_kHz * 1000 != decControl->API_sampleRate ) {
SKP_int16 samplesOut_tmp[ MAX_API_FS_KHZ * FRAME_LENGTH_MS ];
SKP_assert( psDec->fs_kHz <= MAX_API_FS_KHZ );
/* Copy to a tmp buffer as the resampling writes to samplesOut */
SKP_memcpy( samplesOut_tmp, pSamplesOutInternal, *nSamplesOut * sizeof( SKP_int16 ) );
/* (Re-)initialize resampler state when switching internal sampling frequency */
if( prev_fs_kHz != psDec->fs_kHz || psDec->prev_API_sampleRate != decControl->API_sampleRate ) {
ret = SKP_Silk_resampler_init( &psDec->resampler_state, SKP_SMULBB( psDec->fs_kHz, 1000 ), decControl->API_sampleRate );
}
/* Resample the output to API_sampleRate */
ret += SKP_Silk_resampler( &psDec->resampler_state, samplesOut, samplesOut_tmp, *nSamplesOut );
/* Update the number of output samples */
*nSamplesOut = SKP_DIV32( ( SKP_int32 )*nSamplesOut * decControl->API_sampleRate, psDec->fs_kHz * 1000 );
} else if( prev_fs_kHz * 1000 > decControl->API_sampleRate ) {
SKP_memcpy( samplesOut, pSamplesOutInternal, *nSamplesOut * sizeof( SKP_int16 ) );
}
psDec->prev_API_sampleRate = decControl->API_sampleRate;
/* Copy all parameters that are needed out of internal structure to the control stucture */
decControl->frameSize = (SKP_uint16)( decControl->API_sampleRate / 50 ) ;
decControl->framesPerPacket = ( SKP_int )psDec->nFramesInPacket;
decControl->inBandFECOffset = ( SKP_int )psDec->inband_FEC_offset;
decControl->moreInternalDecoderFrames = ( SKP_int )psDec->moreInternalDecoderFrames;
return ret;
}
/* Function to find LBRR information in a packet */
void SKP_Silk_SDK_search_for_LBRR(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input Bytes */
SKP_int lost_offset, /* I: Offset from lost packet */
SKP_uint8 *LBRRData, /* O: LBRR payload */
SKP_int16 *nLBRRBytes /* O: Number of LBRR Bytes */
)
{
SKP_Silk_decoder_state sDec; // Local decoder state to avoid interfering with running decoder */
SKP_Silk_decoder_control sDecCtrl;
SKP_int TempQ[ MAX_FRAME_LENGTH ];
if( lost_offset < 1 || lost_offset > MAX_LBRR_DELAY ) {
/* No useful FEC in this packet */
*nLBRRBytes = 0;
return;
}
sDec.nFramesDecoded = 0;
sDec.fs_kHz = 0; /* Force update parameters LPC_order etc */
sDec.lossCnt = 0; /* Avoid running bw expansion of the LPC parameters when searching for LBRR data */
SKP_memset( sDec.prevNLSF_Q15, 0, MAX_LPC_ORDER * sizeof( SKP_int ) );
SKP_Silk_range_dec_init( &sDec.sRC, inData, ( SKP_int32 )nBytesIn );
while(1) {
SKP_Silk_decode_parameters( &sDec, &sDecCtrl, TempQ, 0 );
if( sDec.sRC.error ) {
/* Corrupt stream */
*nLBRRBytes = 0;
return;
};
if( ( sDec.FrameTermination - 1 ) & lost_offset && sDec.FrameTermination > 0 && sDec.nBytesLeft >= 0 ) {
/* The wanted FEC is present in the packet */
*nLBRRBytes = sDec.nBytesLeft;
SKP_memcpy( LBRRData, &inData[ nBytesIn - sDec.nBytesLeft ], sDec.nBytesLeft * sizeof( SKP_uint8 ) );
break;
}
if( sDec.nBytesLeft > 0 && sDec.FrameTermination == SKP_SILK_MORE_FRAMES ) {
sDec.nFramesDecoded++;
} else {
LBRRData = NULL;
*nLBRRBytes = 0;
break;
}
}
}
/* Getting type of content for a packet */
void SKP_Silk_SDK_get_TOC(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input bytes */
SKP_Silk_TOC_struct *Silk_TOC /* O: Type of content */
)
{
SKP_Silk_decoder_state sDec; // Local Decoder state to avoid interfering with running decoder */
SKP_Silk_decoder_control sDecCtrl;
SKP_int TempQ[ MAX_FRAME_LENGTH ];
sDec.nFramesDecoded = 0;
sDec.fs_kHz = 0; /* Force update parameters LPC_order etc */
SKP_Silk_range_dec_init( &sDec.sRC, inData, ( SKP_int32 )nBytesIn );
Silk_TOC->corrupt = 0;
while( 1 ) {
SKP_Silk_decode_parameters( &sDec, &sDecCtrl, TempQ, 0 );
Silk_TOC->vadFlags[ sDec.nFramesDecoded ] = sDec.vadFlag;
Silk_TOC->sigtypeFlags[ sDec.nFramesDecoded ] = sDecCtrl.sigtype;
if( sDec.sRC.error ) {
/* Corrupt stream */
Silk_TOC->corrupt = 1;
break;
};
if( sDec.nBytesLeft > 0 && sDec.FrameTermination == SKP_SILK_MORE_FRAMES ) {
sDec.nFramesDecoded++;
} else {
break;
}
}
if( Silk_TOC->corrupt || sDec.FrameTermination == SKP_SILK_MORE_FRAMES ||
sDec.nFramesInPacket > SILK_MAX_FRAMES_PER_PACKET ) {
/* Corrupt packet */
SKP_memset( Silk_TOC, 0, sizeof( SKP_Silk_TOC_struct ) );
Silk_TOC->corrupt = 1;
} else {
Silk_TOC->framesInPacket = sDec.nFramesDecoded + 1;
Silk_TOC->fs_kHz = sDec.fs_kHz;
if( sDec.FrameTermination == SKP_SILK_LAST_FRAME ) {
Silk_TOC->inbandLBRR = sDec.FrameTermination;
} else {
Silk_TOC->inbandLBRR = sDec.FrameTermination - 1;
}
}
}
/**************************/
/* Get the version number */
/**************************/
/* Return a pointer to string specifying the version */
const char *SKP_Silk_SDK_get_version()
{
static const char version[] = "1.0.9.6";
return version;
}

View File

@ -0,0 +1,314 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
void SKP_Silk_decode_short_term_prediction(
SKP_int32 *vec_Q10,
SKP_int32 *pres_Q10,
SKP_int32 *sLPC_Q14,
SKP_int16 *A_Q12_tmp,
SKP_int LPC_order,
SKP_int subfr_length
);
/**********************************************************/
/* Core decoder. Performs inverse NSQ operation LTP + LPC */
/**********************************************************/
void SKP_Silk_decode_core(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
SKP_Silk_decoder_control *psDecCtrl, /* I Decoder control */
SKP_int16 xq[], /* O Decoded speech */
const SKP_int q[ MAX_FRAME_LENGTH ] /* I Pulse signal */
)
{
SKP_int i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, sigtype;
SKP_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
SKP_int16 sLTP[ MAX_FRAME_LENGTH ];
SKP_int32 LTP_pred_Q14, Gain_Q16, inv_gain_Q16, inv_gain_Q32, gain_adj_Q16, rand_seed, offset_Q10, dither;
SKP_int32 *pred_lag_ptr, *pexc_Q10, *pres_Q10;
SKP_int32 vec_Q10[ MAX_FRAME_LENGTH / NB_SUBFR ];
SKP_int32 FiltState[ MAX_LPC_ORDER ];
SKP_assert( psDec->prev_inv_gain_Q16 != 0 );
offset_Q10 = SKP_Silk_Quantization_Offsets_Q10[ psDecCtrl->sigtype ][ psDecCtrl->QuantOffsetType ];
if( psDecCtrl->NLSFInterpCoef_Q2 < ( 1 << 2 ) ) {
NLSF_interpolation_flag = 1;
} else {
NLSF_interpolation_flag = 0;
}
/* Decode excitation */
rand_seed = psDecCtrl->Seed;
for( i = 0; i < psDec->frame_length; i++ ) {
rand_seed = SKP_RAND( rand_seed );
/* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
dither = SKP_RSHIFT( rand_seed, 31 );
psDec->exc_Q10[ i ] = SKP_LSHIFT( ( SKP_int32 )q[ i ], 10 ) + offset_Q10;
psDec->exc_Q10[ i ] = ( psDec->exc_Q10[ i ] ^ dither ) - dither;
rand_seed += q[ i ];
}
pexc_Q10 = psDec->exc_Q10;
pres_Q10 = psDec->res_Q10;
pxq = &psDec->outBuf[ psDec->frame_length ];
sLTP_buf_idx = psDec->frame_length;
/* Loop over subframes */
for( k = 0; k < NB_SUBFR; k++ ) {
A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
/* Preload LPC coeficients to array on stack. Gives small performance gain */
SKP_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( SKP_int16 ) );
B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
Gain_Q16 = psDecCtrl->Gains_Q16[ k ];
sigtype = psDecCtrl->sigtype;
inv_gain_Q16 = SKP_INVERSE32_varQ( SKP_max( Gain_Q16, 1 ), 32 );
inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX );
/* Calculate Gain adjustment factor */
gain_adj_Q16 = ( SKP_int32 )1 << 16;
if( inv_gain_Q16 != psDec->prev_inv_gain_Q16 ) {
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, psDec->prev_inv_gain_Q16, 16 );
}
/* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
if( psDec->lossCnt && psDec->prev_sigtype == SIG_TYPE_VOICED &&
psDecCtrl->sigtype == SIG_TYPE_UNVOICED && k < ( NB_SUBFR >> 1 ) ) {
SKP_memset( B_Q14, 0, LTP_ORDER * sizeof( SKP_int16 ) );
B_Q14[ LTP_ORDER/2 ] = ( SKP_int16 )1 << 12; /* 0.25 */
sigtype = SIG_TYPE_VOICED;
psDecCtrl->pitchL[ k ] = psDec->lagPrev;
}
if( sigtype == SIG_TYPE_VOICED ) {
/* Voiced */
lag = psDecCtrl->pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - SKP_LSHIFT( NLSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psDec->frame_length - lag - psDec->LPC_order - LTP_ORDER / 2;
SKP_assert( start_idx >= 0 );
SKP_assert( start_idx <= psDec->frame_length - psDec->LPC_order );
SKP_memset( FiltState, 0, psDec->LPC_order * sizeof( SKP_int32 ) ); /* Not really necessary, but Valgrind and Coverity will complain otherwise */
SKP_Silk_MA_Prediction( &psDec->outBuf[ start_idx + k * ( psDec->frame_length >> 2 ) ],
A_Q12, FiltState, sLTP + start_idx, psDec->frame_length - start_idx, psDec->LPC_order );
/* After rewhitening the LTP state is unscaled */
inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 );
if( k == 0 ) {
/* Do LTP downscaling */
inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 );
}
for( i = 0; i < (lag + LTP_ORDER/2); i++ ) {
psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWB( inv_gain_Q32, sLTP[ psDec->frame_length - i - 1 ] );
}
} else {
/* Update LTP state when Gain changes */
if( gain_adj_Q16 != ( SKP_int32 )1 << 16 ) {
for( i = 0; i < ( lag + LTP_ORDER / 2 ); i++ ) {
psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = SKP_SMULWW( gain_adj_Q16, psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] );
}
}
}
}
/* Scale short term state */
for( i = 0; i < MAX_LPC_ORDER; i++ ) {
psDec->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDec->sLPC_Q14[ i ] );
}
/* Save inv_gain */
SKP_assert( inv_gain_Q16 != 0 );
psDec->prev_inv_gain_Q16 = inv_gain_Q16;
/* Long-term prediction */
if( sigtype == SIG_TYPE_VOICED ) {
/* Setup pointer */
pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < psDec->subfr_length; i++ ) {
/* Unrolled loop */
LTP_pred_Q14 = SKP_SMULWB( pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
LTP_pred_Q14 = SKP_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
pred_lag_ptr++;
/* Generate LPC residual */
pres_Q10[ i ] = SKP_ADD32( pexc_Q10[ i ], SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );
/* Update states */
psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( pres_Q10[ i ], 6 );
sLTP_buf_idx++;
}
} else {
SKP_memcpy( pres_Q10, pexc_Q10, psDec->subfr_length * sizeof( SKP_int32 ) );
}
SKP_Silk_decode_short_term_prediction(vec_Q10, pres_Q10, psDec->sLPC_Q14,A_Q12_tmp,psDec->LPC_order,psDec->subfr_length);
/* Scale with Gain */
for( i = 0; i < psDec->subfr_length; i++ ) {
pxq[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( vec_Q10[ i ], Gain_Q16 ), 10 ) );
}
/* Update LPC filter state */
SKP_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( SKP_int32 ) );
pexc_Q10 += psDec->subfr_length;
pres_Q10 += psDec->subfr_length;
pxq += psDec->subfr_length;
}
/* Copy to output */
SKP_memcpy( xq, &psDec->outBuf[ psDec->frame_length ], psDec->frame_length * sizeof( SKP_int16 ) );
}
#if EMBEDDED_ARM<5
void SKP_Silk_decode_short_term_prediction(
SKP_int32 *vec_Q10,
SKP_int32 *pres_Q10,
SKP_int32 *sLPC_Q14,
SKP_int16 *A_Q12_tmp,
SKP_int LPC_order,
SKP_int subfr_length
)
{
SKP_int i;
SKP_int32 LPC_pred_Q10;
#if !defined(_SYSTEM_IS_BIG_ENDIAN)
SKP_int32 Atmp;
/* Short term prediction */
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
/* the SMLAWB and SMLAWT instructions should solve the problem. */
if( LPC_order == 16 ) {
for( i = 0; i < subfr_length; i++ ) {
/* unrolled */
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 0 ] ); /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMULWB( sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 10 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 12 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 14 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], Atmp );
/* Add prediction to LPC residual */
vec_Q10[ i ] = SKP_ADD32( pres_Q10[ i ], LPC_pred_Q10 );
/* Update states */
sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT_ovflw( vec_Q10[ i ], 4 );
}
} else {
SKP_assert( LPC_order == 10 );
for( i = 0; i < subfr_length; i++ ) {
/* unrolled */
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 0 ] ); /* read two coefficients at once */
LPC_pred_Q10 = SKP_SMULWB( sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], Atmp );
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], Atmp );
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], Atmp );
/* Add prediction to LPC residual */
vec_Q10[ i ] = SKP_ADD32( pres_Q10[ i ], LPC_pred_Q10 );
/* Update states */
sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT_ovflw( vec_Q10[ i ], 4 );
}
}
#else
SKP_int j;
for( i = 0; i < subfr_length; i++ ) {
/* Partially unrolled */
LPC_pred_Q10 = SKP_SMULWB( sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp[ 1 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp[ 2 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp[ 3 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp[ 4 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp[ 5 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp[ 6 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp[ 7 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp[ 8 ] );
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
for( j = 10; j < LPC_order; j ++ ) {
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] );
}
/* Add prediction to LPC residual */
vec_Q10[ i ] = SKP_ADD32( pres_Q10[ i ], LPC_pred_Q10 );
/* Update states */
sLPC_Q14[ MAX_LPC_ORDER + i ] = SKP_LSHIFT_ovflw( vec_Q10[ i ], 4 );
}
#endif
}
#endif

View File

@ -0,0 +1,248 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_AsmPreproc.h"
#define MAX_LPC_ORDER 16
#define MAX_LPC_ORDER_INT32_OFFSET 64
#if EMBEDDED_ARM >= 5
VARDEF ptr_vec_Q10, r0
VARDEF ptr_pres_Q10, r1
VARDEF ptr_sLPC_Q14, r2
VARDEF ptr_A_Q12_tmp, r3
VARDEF ptr_LPC_Q14, r4
VARDEF val1_LPC_Q14, r5
VARDEF val_pres_Q10, r5
VARDEF val2_LPC_Q14, r6
VARDEF val_vec_Q10, r6
VARDEF val3_LPC_Q14, r8
VARDEF val4_LPC_Q14, sb
VARDEF val1_Atmp, sl
VARDEF val_LPC_Q14, sl
VARDEF val2_Atmp, ip
VARDEF val_subfr_length, _r7
VARDEF val_LPC_order, lr
VARDEF val_LPC_pred_Q10, lr
.globl SYM(SKP_Silk_decode_short_term_prediction)
SYM(SKP_Silk_decode_short_term_prediction):
stmdb sp!, {r4-r10, fp, ip, lr}
add fp, sp, #36
.set ptr_LPC_order, 40
.set ptr_subfr_length, 44
ldr val_LPC_order, [sp, #ptr_LPC_order]
ldr val_subfr_length, [sp, #ptr_subfr_length]
ands val1_Atmp, ptr_A_Q12_tmp, #3
add ptr_sLPC_Q14, ptr_sLPC_Q14, #MAX_LPC_ORDER_INT32_OFFSET
bne LR(2, f)
cmp val_LPC_order, #16
bne LR(1, f)
/*LPC_order == 16*/
L(0)
mov ptr_LPC_Q14, ptr_sLPC_Q14
ldmia ptr_A_Q12_tmp!, {val1_Atmp, val2_Atmp}
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smulwb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldr val2_Atmp, [ptr_A_Q12_tmp], #-28
smlawb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val_pres_Q10, [ptr_pres_Q10], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
subs val_subfr_length, val_subfr_length, #1
add val_vec_Q10, val_LPC_pred_Q10, val_pres_Q10
mov val_LPC_Q14, val_vec_Q10, lsl #4
str val_vec_Q10, [ptr_vec_Q10], #4
str val_LPC_Q14, [ptr_sLPC_Q14], #4
bgt LR(0, b)
ldmia sp!, {r4-r10, fp, ip, pc}
/*LPC_order == 10*/
L(1)
mov ptr_LPC_Q14, ptr_sLPC_Q14
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smulwb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldr val2_Atmp, [ptr_A_Q12_tmp], #-16
smlawb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val1_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val_pres_Q10, [ptr_pres_Q10], #4
smlawb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawt val_LPC_pred_Q10, val3_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
subs val_subfr_length, val_subfr_length, #1
add val_vec_Q10, val_LPC_pred_Q10, val_pres_Q10
mov val_LPC_Q14, val_vec_Q10, lsl #4
str val_vec_Q10, [ptr_vec_Q10], #4
str val_LPC_Q14, [ptr_sLPC_Q14], #4
bgt LR(1, b)
ldmia sp!, {r4-r10, fp, ip, pc}
L(2)
cmp val_LPC_order, #16
bne LR(4, f)
/*LPC_order == 16*/
L(3)
mov ptr_LPC_Q14, ptr_sLPC_Q14
ldrh val1_Atmp, [ptr_A_Q12_tmp], #2
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smulwb val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smlawt val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smlawt val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smlawt val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldrh val1_Atmp, [ptr_A_Q12_tmp], #-30
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val_pres_Q10, [ptr_pres_Q10], #4
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
subs val_subfr_length, val_subfr_length, #1
add val_vec_Q10, val_LPC_pred_Q10, val_pres_Q10
mov val_LPC_Q14, val_vec_Q10, lsl #4
str val_vec_Q10, [ptr_vec_Q10], #4
str val_LPC_Q14, [ptr_sLPC_Q14], #4
bgt LR(3, b)
ldmia sp!, {r4-r10, fp, ip, pc}
/*LPC_order == 10*/
L(4)
mov ptr_LPC_Q14, ptr_sLPC_Q14
ldrh val2_Atmp, [ptr_A_Q12_tmp], #2
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smulwb val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smlawt val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val1_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val1_LPC_Q14, val2_LPC_Q14}
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val2_Atmp, [ptr_A_Q12_tmp], #4
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldmdb ptr_LPC_Q14!, {val3_LPC_Q14, val4_LPC_Q14}
smlawt val_LPC_pred_Q10, val2_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
ldr val1_Atmp, [ptr_A_Q12_tmp], #-18
smlawb val_LPC_pred_Q10, val1_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
ldr val_pres_Q10, [ptr_pres_Q10], #4
smlawt val_LPC_pred_Q10, val4_LPC_Q14, val2_Atmp, val_LPC_pred_Q10
smlawb val_LPC_pred_Q10, val3_LPC_Q14, val1_Atmp, val_LPC_pred_Q10
subs val_subfr_length, val_subfr_length, #1
add val_vec_Q10, val_LPC_pred_Q10, val_pres_Q10
mov val_LPC_Q14, val_vec_Q10, lsl #4
str val_vec_Q10, [ptr_vec_Q10], #4
str val_LPC_Q14, [ptr_sLPC_Q14], #4
bgt LR(4, b)
ldmia sp!, {r4-r10, fp, ip, pc}
END
#endif

View File

@ -0,0 +1,155 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
#include "SKP_Silk_PLC.h"
/****************/
/* Decode frame */
/****************/
SKP_int SKP_Silk_decode_frame(
SKP_Silk_decoder_state *psDec, /* I/O Pointer to Silk decoder state */
SKP_int16 pOut[], /* O Pointer to output speech frame */
SKP_int16 *pN, /* O Pointer to size of output frame */
const SKP_uint8 pCode[], /* I Pointer to payload */
const SKP_int nBytes, /* I Payload length */
SKP_int action, /* I Action from Jitter Buffer */
SKP_int *decBytes /* O Used bytes to decode this frame */
)
{
SKP_Silk_decoder_control sDecCtrl;
SKP_int L, fs_Khz_old, ret = 0;
SKP_int Pulses[ MAX_FRAME_LENGTH ];
L = psDec->frame_length;
sDecCtrl.LTP_scale_Q14 = 0;
/* Safety checks */
SKP_assert( L > 0 && L <= MAX_FRAME_LENGTH );
/********************************************/
/* Decode Frame if packet is not lost */
/********************************************/
*decBytes = 0;
if( action == 0 ) {
/********************************************/
/* Initialize arithmetic coder */
/********************************************/
fs_Khz_old = psDec->fs_kHz;
if( psDec->nFramesDecoded == 0 ) {
/* Initialize range decoder state */
SKP_Silk_range_dec_init( &psDec->sRC, pCode, nBytes );
}
/********************************************/
/* Decode parameters and pulse signal */
/********************************************/
SKP_Silk_decode_parameters( psDec, &sDecCtrl, Pulses, 1 );
if( psDec->sRC.error ) {
psDec->nBytesLeft = 0;
action = 1; /* PLC operation */
/* revert fs if changed in decode_parameters */
SKP_Silk_decoder_set_fs( psDec, fs_Khz_old );
/* Avoid crashing */
*decBytes = psDec->sRC.bufferLength;
if( psDec->sRC.error == RANGE_CODER_DEC_PAYLOAD_TOO_LONG ) {
ret = SKP_SILK_DEC_PAYLOAD_TOO_LARGE;
} else {
ret = SKP_SILK_DEC_PAYLOAD_ERROR;
}
} else {
*decBytes = psDec->sRC.bufferLength - psDec->nBytesLeft;
psDec->nFramesDecoded++;
/* Update lengths. Sampling frequency could have changed */
L = psDec->frame_length;
/********************************************************/
/* Run inverse NSQ */
/********************************************************/
SKP_Silk_decode_core( psDec, &sDecCtrl, pOut, Pulses );
/********************************************************/
/* Update PLC state */
/********************************************************/
SKP_Silk_PLC( psDec, &sDecCtrl, pOut, L, action );
psDec->lossCnt = 0;
psDec->prev_sigtype = sDecCtrl.sigtype;
/* A frame has been decoded without errors */
psDec->first_frame_after_reset = 0;
}
}
/*************************************************************/
/* Generate Concealment frame if packet is lost, or corrupt */
/*************************************************************/
if( action == 1 ) {
/* Handle packet loss by extrapolation */
SKP_Silk_PLC( psDec, &sDecCtrl, pOut, L, action );
}
/*************************/
/* Update output buffer. */
/*************************/
SKP_memcpy( psDec->outBuf, pOut, L * sizeof( SKP_int16 ) );
/****************************************************************/
/* Ensure smooth connection of extrapolated and good frames */
/****************************************************************/
SKP_Silk_PLC_glue_frames( psDec, &sDecCtrl, pOut, L );
/************************************************/
/* Comfort noise generation / estimation */
/************************************************/
SKP_Silk_CNG( psDec, &sDecCtrl, pOut , L );
/********************************************/
/* HP filter output */
/********************************************/
SKP_assert( ( ( psDec->fs_kHz == 12 ) && ( L % 3 ) == 0 ) ||
( ( psDec->fs_kHz != 12 ) && ( L % 2 ) == 0 ) );
SKP_Silk_biquad( pOut, psDec->HP_B, psDec->HP_A, psDec->HPState, pOut, L );
/********************************************/
/* set output frame length */
/********************************************/
*pN = ( SKP_int16 )L;
/* Update some decoder state variables */
psDec->lagPrev = sDecCtrl.pitchL[ NB_SUBFR - 1 ];
return ret;
}

View File

@ -0,0 +1,244 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Decode parameters from payload */
void SKP_Silk_decode_parameters(
SKP_Silk_decoder_state *psDec, /* I/O State */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int q[], /* O Excitation signal */
const SKP_int fullDecoding /* I Flag to tell if only arithmetic decoding */
)
{
SKP_int i, k, Ix, fs_kHz_dec, nBytesUsed;
SKP_int Ixs[ NB_SUBFR ];
SKP_int GainsIndices[ NB_SUBFR ];
SKP_int NLSFIndices[ NLSF_MSVQ_MAX_CB_STAGES ];
SKP_int pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ];
const SKP_int16 *cbk_ptr_Q14;
const SKP_Silk_NLSF_CB_struct *psNLSF_CB = NULL;
SKP_Silk_range_coder_state *psRC = &psDec->sRC;
/************************/
/* Decode sampling rate */
/************************/
/* only done for first frame of packet */
if( psDec->nFramesDecoded == 0 ) {
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_SamplingRates_CDF, SKP_Silk_SamplingRates_offset );
/* check that sampling rate is supported */
if( Ix < 0 || Ix > 3 ) {
psRC->error = RANGE_CODER_ILLEGAL_SAMPLING_RATE;
return;
}
fs_kHz_dec = SKP_Silk_SamplingRates_table[ Ix ];
SKP_Silk_decoder_set_fs( psDec, fs_kHz_dec );
}
/*******************************************/
/* Decode signal type and quantizer offset */
/*******************************************/
if( psDec->nFramesDecoded == 0 ) {
/* first frame in packet: independent coding */
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_type_offset_CDF, SKP_Silk_type_offset_CDF_offset );
} else {
/* condidtional coding */
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_type_offset_joint_CDF[ psDec->typeOffsetPrev ],
SKP_Silk_type_offset_CDF_offset );
}
psDecCtrl->sigtype = SKP_RSHIFT( Ix, 1 );
psDecCtrl->QuantOffsetType = Ix & 1;
psDec->typeOffsetPrev = Ix;
/****************/
/* Decode gains */
/****************/
/* first subframe */
if( psDec->nFramesDecoded == 0 ) {
/* first frame in packet: independent coding */
SKP_Silk_range_decoder( &GainsIndices[ 0 ], psRC, SKP_Silk_gain_CDF[ psDecCtrl->sigtype ], SKP_Silk_gain_CDF_offset );
} else {
/* condidtional coding */
SKP_Silk_range_decoder( &GainsIndices[ 0 ], psRC, SKP_Silk_delta_gain_CDF, SKP_Silk_delta_gain_CDF_offset );
}
/* remaining subframes */
for( i = 1; i < NB_SUBFR; i++ ) {
SKP_Silk_range_decoder( &GainsIndices[ i ], psRC, SKP_Silk_delta_gain_CDF, SKP_Silk_delta_gain_CDF_offset );
}
/* Dequant Gains */
SKP_Silk_gains_dequant( psDecCtrl->Gains_Q16, GainsIndices, &psDec->LastGainIndex, psDec->nFramesDecoded );
/****************/
/* Decode NLSFs */
/****************/
/* Set pointer to NLSF VQ CB for the current signal type */
psNLSF_CB = psDec->psNLSF_CB[ psDecCtrl->sigtype ];
/* Range decode NLSF path */
SKP_Silk_range_decoder_multi( NLSFIndices, psRC, psNLSF_CB->StartPtr, psNLSF_CB->MiddleIx, psNLSF_CB->nStages );
/* From the NLSF path, decode an NLSF vector */
SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, NLSFIndices, psDec->LPC_order );
/************************************/
/* Decode NLSF interpolation factor */
/************************************/
SKP_Silk_range_decoder( &psDecCtrl->NLSFInterpCoef_Q2, psRC, SKP_Silk_NLSF_interpolation_factor_CDF,
SKP_Silk_NLSF_interpolation_factor_offset );
/* If just reset, e.g., because internal Fs changed, do not allow interpolation */
/* improves the case of packet loss in the first frame after a switch */
if( psDec->first_frame_after_reset == 1 ) {
psDecCtrl->NLSFInterpCoef_Q2 = 4;
}
if( fullDecoding ) {
/* Convert NLSF parameters to AR prediction filter coefficients */
SKP_Silk_NLSF2A_stable( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
if( psDecCtrl->NLSFInterpCoef_Q2 < 4 ) {
/* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
/* the previous NLSF1, and the current NLSF1 */
for( i = 0; i < psDec->LPC_order; i++ ) {
pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + SKP_RSHIFT( SKP_MUL( psDecCtrl->NLSFInterpCoef_Q2,
( pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ) ), 2 );
}
/* Convert NLSF parameters to AR prediction filter coefficients */
SKP_Silk_NLSF2A_stable( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
} else {
/* Copy LPC coefficients for first half from second half */
SKP_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ],
psDec->LPC_order * sizeof( SKP_int16 ) );
}
}
SKP_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( SKP_int ) );
/* After a packet loss do BWE of LPC coefs */
if( psDec->lossCnt ) {
SKP_Silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
SKP_Silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
}
if( psDecCtrl->sigtype == SIG_TYPE_VOICED ) {
/*********************/
/* Decode pitch lags */
/*********************/
/* Get lag index */
if( psDec->fs_kHz == 8 ) {
SKP_Silk_range_decoder( &Ixs[ 0 ], psRC, SKP_Silk_pitch_lag_NB_CDF, SKP_Silk_pitch_lag_NB_CDF_offset );
} else if( psDec->fs_kHz == 12 ) {
SKP_Silk_range_decoder( &Ixs[ 0 ], psRC, SKP_Silk_pitch_lag_MB_CDF, SKP_Silk_pitch_lag_MB_CDF_offset );
} else if( psDec->fs_kHz == 16 ) {
SKP_Silk_range_decoder( &Ixs[ 0 ], psRC, SKP_Silk_pitch_lag_WB_CDF, SKP_Silk_pitch_lag_WB_CDF_offset );
} else {
SKP_Silk_range_decoder( &Ixs[ 0 ], psRC, SKP_Silk_pitch_lag_SWB_CDF, SKP_Silk_pitch_lag_SWB_CDF_offset );
}
/* Get countour index */
if( psDec->fs_kHz == 8 ) {
/* Less codevectors used in 8 khz mode */
SKP_Silk_range_decoder( &Ixs[ 1 ], psRC, SKP_Silk_pitch_contour_NB_CDF, SKP_Silk_pitch_contour_NB_CDF_offset );
} else {
/* Joint for 12, 16, and 24 khz */
SKP_Silk_range_decoder( &Ixs[ 1 ], psRC, SKP_Silk_pitch_contour_CDF, SKP_Silk_pitch_contour_CDF_offset );
}
/* Decode pitch values */
SKP_Silk_decode_pitch( Ixs[ 0 ], Ixs[ 1 ], psDecCtrl->pitchL, psDec->fs_kHz );
/********************/
/* Decode LTP gains */
/********************/
/* Decode PERIndex value */
SKP_Silk_range_decoder( &psDecCtrl->PERIndex, psRC, SKP_Silk_LTP_per_index_CDF,
SKP_Silk_LTP_per_index_CDF_offset );
/* Decode Codebook Index */
cbk_ptr_Q14 = SKP_Silk_LTP_vq_ptrs_Q14[ psDecCtrl->PERIndex ]; /* set pointer to start of codebook */
for( k = 0; k < NB_SUBFR; k++ ) {
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_LTP_gain_CDF_ptrs[ psDecCtrl->PERIndex ],
SKP_Silk_LTP_gain_CDF_offsets[ psDecCtrl->PERIndex ] );
for( i = 0; i < LTP_ORDER; i++ ) {
psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = cbk_ptr_Q14[ Ix * LTP_ORDER + i ];
}
}
/**********************/
/* Decode LTP scaling */
/**********************/
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_LTPscale_CDF, SKP_Silk_LTPscale_offset );
psDecCtrl->LTP_scale_Q14 = SKP_Silk_LTPScales_table_Q14[ Ix ];
} else {
SKP_assert( psDecCtrl->sigtype == SIG_TYPE_UNVOICED );
SKP_memset( psDecCtrl->pitchL, 0, NB_SUBFR * sizeof( SKP_int ) );
SKP_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * NB_SUBFR * sizeof( SKP_int16 ) );
psDecCtrl->PERIndex = 0;
psDecCtrl->LTP_scale_Q14 = 0;
}
/***************/
/* Decode seed */
/***************/
SKP_Silk_range_decoder( &Ix, psRC, SKP_Silk_Seed_CDF, SKP_Silk_Seed_offset );
psDecCtrl->Seed = ( SKP_int32 )Ix;
/*********************************************/
/* Decode quantization indices of excitation */
/*********************************************/
SKP_Silk_decode_pulses( psRC, psDecCtrl, q, psDec->frame_length );
/*********************************************/
/* Decode VAD flag */
/*********************************************/
SKP_Silk_range_decoder( &psDec->vadFlag, psRC, SKP_Silk_vadflag_CDF, SKP_Silk_vadflag_offset );
/**************************************/
/* Decode Frame termination indicator */
/**************************************/
SKP_Silk_range_decoder( &psDec->FrameTermination, psRC, SKP_Silk_FrameTermination_CDF, SKP_Silk_FrameTermination_offset );
/****************************************/
/* get number of bytes used so far */
/****************************************/
SKP_Silk_range_coder_get_length( psRC, &nBytesUsed );
psDec->nBytesLeft = psRC->bufferLength - nBytesUsed;
if( psDec->nBytesLeft < 0 ) {
psRC->error = RANGE_CODER_READ_BEYOND_BUFFER;
}
/****************************************/
/* check remaining bits in last byte */
/****************************************/
if( psDec->nBytesLeft == 0 ) {
SKP_Silk_range_coder_check_after_decoding( psRC );
}
}

View File

@ -0,0 +1,57 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/***********************************************************
* Pitch analyser function
********************************************************** */
#include "SKP_Silk_SigProc_FIX.h"
#include "SKP_Silk_common_pitch_est_defines.h"
void SKP_Silk_decode_pitch(
SKP_int lagIndex, /* I */
SKP_int contourIndex, /* O */
SKP_int pitch_lags[], /* O 4 pitch values */
SKP_int Fs_kHz /* I sampling frequency (kHz) */
)
{
SKP_int lag, i, min_lag;
min_lag = SKP_SMULBB( PITCH_EST_MIN_LAG_MS, Fs_kHz );
/* Only for 24 / 16 kHz version for now */
lag = min_lag + lagIndex;
if( Fs_kHz == 8 ) {
/* Only a small codebook for 8 khz */
for( i = 0; i < PITCH_EST_NB_SUBFR; i++ ) {
pitch_lags[ i ] = lag + SKP_Silk_CB_lags_stage2[ i ][ contourIndex ];
}
} else {
for( i = 0; i < PITCH_EST_NB_SUBFR; i++ ) {
pitch_lags[ i ] = lag + SKP_Silk_CB_lags_stage3[ i ][ contourIndex ];
}
}
}

View File

@ -0,0 +1,105 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/*********************************************/
/* Decode quantization indices of excitation */
/*********************************************/
void SKP_Silk_decode_pulses(
SKP_Silk_range_coder_state *psRC, /* I/O Range coder state */
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
SKP_int q[], /* O Excitation signal */
const SKP_int frame_length /* I Frame length (preliminary) */
)
{
SKP_int i, j, k, iter, abs_q, nLS, bit;
SKP_int sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
SKP_int *pulses_ptr;
const SKP_uint16 *cdf_ptr;
/*********************/
/* Decode rate level */
/*********************/
SKP_Silk_range_decoder( &psDecCtrl->RateLevelIndex, psRC,
SKP_Silk_rate_levels_CDF[ psDecCtrl->sigtype ], SKP_Silk_rate_levels_CDF_offset );
/* Calculate number of shell blocks */
iter = frame_length / SHELL_CODEC_FRAME_LENGTH;
/***************************************************/
/* Sum-Weighted-Pulses Decoding */
/***************************************************/
cdf_ptr = SKP_Silk_pulses_per_block_CDF[ psDecCtrl->RateLevelIndex ];
for( i = 0; i < iter; i++ ) {
nLshifts[ i ] = 0;
SKP_Silk_range_decoder( &sum_pulses[ i ], psRC, cdf_ptr, SKP_Silk_pulses_per_block_CDF_offset );
/* LSB indication */
while( sum_pulses[ i ] == ( MAX_PULSES + 1 ) ) {
nLshifts[ i ]++;
SKP_Silk_range_decoder( &sum_pulses[ i ], psRC,
SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ], SKP_Silk_pulses_per_block_CDF_offset );
}
}
/***************************************************/
/* Shell decoding */
/***************************************************/
for( i = 0; i < iter; i++ ) {
if( sum_pulses[ i ] > 0 ) {
SKP_Silk_shell_decoder( &q[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRC, sum_pulses[ i ] );
} else {
SKP_memset( &q[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( SKP_int ) );
}
}
/***************************************************/
/* LSB Decoding */
/***************************************************/
for( i = 0; i < iter; i++ ) {
if( nLshifts[ i ] > 0 ) {
nLS = nLshifts[ i ];
pulses_ptr = &q[ SKP_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
abs_q = pulses_ptr[ k ];
for( j = 0; j < nLS; j++ ) {
abs_q = SKP_LSHIFT( abs_q, 1 );
SKP_Silk_range_decoder( &bit, psRC, SKP_Silk_lsb_CDF, 1 );
abs_q += bit;
}
pulses_ptr[ k ] = abs_q;
}
}
}
/****************************************/
/* Decode and add signs to pulse signal */
/****************************************/
SKP_Silk_decode_signs( psRC, q, frame_length, psDecCtrl->sigtype,
psDecCtrl->QuantOffsetType, psDecCtrl->RateLevelIndex);
}

View File

@ -0,0 +1,80 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/* Set decoder sampling rate */
void SKP_Silk_decoder_set_fs(
SKP_Silk_decoder_state *psDec, /* I/O Decoder state pointer */
SKP_int fs_kHz /* I Sampling frequency (kHz) */
)
{
if( psDec->fs_kHz != fs_kHz ) {
psDec->fs_kHz = fs_kHz;
psDec->frame_length = SKP_SMULBB( FRAME_LENGTH_MS, fs_kHz );
psDec->subfr_length = SKP_SMULBB( FRAME_LENGTH_MS / NB_SUBFR, fs_kHz );
if( psDec->fs_kHz == 8 ) {
psDec->LPC_order = MIN_LPC_ORDER;
psDec->psNLSF_CB[ 0 ] = &SKP_Silk_NLSF_CB0_10;
psDec->psNLSF_CB[ 1 ] = &SKP_Silk_NLSF_CB1_10;
} else {
psDec->LPC_order = MAX_LPC_ORDER;
psDec->psNLSF_CB[ 0 ] = &SKP_Silk_NLSF_CB0_16;
psDec->psNLSF_CB[ 1 ] = &SKP_Silk_NLSF_CB1_16;
}
/* Reset part of the decoder state */
SKP_memset( psDec->sLPC_Q14, 0, MAX_LPC_ORDER * sizeof( SKP_int32 ) );
SKP_memset( psDec->outBuf, 0, MAX_FRAME_LENGTH * sizeof( SKP_int16 ) );
SKP_memset( psDec->prevNLSF_Q15, 0, MAX_LPC_ORDER * sizeof( SKP_int ) );
psDec->lagPrev = 100;
psDec->LastGainIndex = 1;
psDec->prev_sigtype = 0;
psDec->first_frame_after_reset = 1;
if( fs_kHz == 24 ) {
psDec->HP_A = SKP_Silk_Dec_A_HP_24;
psDec->HP_B = SKP_Silk_Dec_B_HP_24;
} else if( fs_kHz == 16 ) {
psDec->HP_A = SKP_Silk_Dec_A_HP_16;
psDec->HP_B = SKP_Silk_Dec_B_HP_16;
} else if( fs_kHz == 12 ) {
psDec->HP_A = SKP_Silk_Dec_A_HP_12;
psDec->HP_B = SKP_Silk_Dec_B_HP_12;
} else if( fs_kHz == 8 ) {
psDec->HP_A = SKP_Silk_Dec_A_HP_8;
psDec->HP_B = SKP_Silk_Dec_B_HP_8;
} else {
/* unsupported sampling rate */
SKP_assert( 0 );
}
}
/* Check that settings are valid */
SKP_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
}

View File

@ -0,0 +1,306 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_DEFINE_H
#define SKP_SILK_DEFINE_H
#include "SKP_Silk_errors.h"
#include "SKP_Silk_typedef.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define MAX_FRAMES_PER_PACKET 5
/* Limits on bitrate */
#define MIN_TARGET_RATE_BPS 5000
#define MAX_TARGET_RATE_BPS 100000
/* Transition bitrates between modes */
#define SWB2WB_BITRATE_BPS 25000
#define WB2SWB_BITRATE_BPS 30000
#define WB2MB_BITRATE_BPS 14000
#define MB2WB_BITRATE_BPS 18000
#define MB2NB_BITRATE_BPS 10000
#define NB2MB_BITRATE_BPS 14000
/* Integration/hysteresis threshold for lowering internal sample frequency */
/* 30000000 -> 6 sec if bitrate is 5000 bps below limit; 3 sec if bitrate is 10000 bps below limit */
#define ACCUM_BITS_DIFF_THRESHOLD 30000000
#define TARGET_RATE_TAB_SZ 8
/* DTX settings */
#define NO_SPEECH_FRAMES_BEFORE_DTX 5 /* eq 100 ms */
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
#define USE_LBRR 1
/* Amount of concecutive no FEC packets before telling JB */
#define NO_LBRR_THRES 10
/* Maximum delay between real packet and LBRR packet */
#define MAX_LBRR_DELAY 2
#define LBRR_IDX_MASK 1
#define INBAND_FEC_MIN_RATE_BPS 18000 /* Dont use inband FEC below this total target rate */
#define LBRR_LOSS_THRES 1 /* Start adding LBRR at this loss rate */
/* LBRR usage defines */
#define SKP_SILK_NO_LBRR 0 /* No LBRR information for this packet */
#define SKP_SILK_ADD_LBRR_TO_PLUS1 1 /* Add LBRR for this packet to packet n + 1 */
#define SKP_SILK_ADD_LBRR_TO_PLUS2 2 /* Add LBRR for this packet to packet n + 2 */
/* Frame termination indicator defines */
#define SKP_SILK_LAST_FRAME 0 /* Last frames in packet */
#define SKP_SILK_MORE_FRAMES 1 /* More frames to follow this one */
#define SKP_SILK_LBRR_VER1 2 /* LBRR information from packet n - 1 */
#define SKP_SILK_LBRR_VER2 3 /* LBRR information from packet n - 2 */
#define SKP_SILK_EXT_LAYER 4 /* Extension layers added */
/* Number of Second order Sections for SWB detection HP filter */
#define NB_SOS 3
#define HP_8_KHZ_THRES 10 /* average energy per sample, above 8 kHz */
#define CONCEC_SWB_SMPLS_THRES 480 * 15 /* 300 ms */
#define WB_DETECT_ACTIVE_SPEECH_MS_THRES 15000 /* ms of active speech needed for WB detection */
/* Low complexity setting */
#define LOW_COMPLEXITY_ONLY 0
/* Activate bandwidth transition filtering for mode switching */
#define SWITCH_TRANSITION_FILTERING 1
/* Decoder Parameters */
#define DEC_HP_ORDER 2
/* Maximum sampling frequency, should be 16 for some embedded platforms */
#define MAX_FS_KHZ 24
#define MAX_API_FS_KHZ 48
/* Signal Types used by silk */
#define SIG_TYPE_VOICED 0
#define SIG_TYPE_UNVOICED 1
/* VAD Types used by silk */
#define NO_VOICE_ACTIVITY 0
#define VOICE_ACTIVITY 1
/* Number of samples per frame */
#define FRAME_LENGTH_MS 20
#define MAX_FRAME_LENGTH ( FRAME_LENGTH_MS * MAX_FS_KHZ )
/* Milliseconds of lookahead for pitch analysis */
#define LA_PITCH_MS 2
#define LA_PITCH_MAX ( LA_PITCH_MS * MAX_FS_KHZ )
/* Length of LPC window used in find pitch */
#define FIND_PITCH_LPC_WIN_MS ( 20 + (LA_PITCH_MS << 1) )
#define FIND_PITCH_LPC_WIN_MAX ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ )
/* Order of LPC used in find pitch */
#define MAX_FIND_PITCH_LPC_ORDER 16
#define PITCH_EST_COMPLEXITY_HC_MODE SKP_Silk_PITCH_EST_MAX_COMPLEX
#define PITCH_EST_COMPLEXITY_MC_MODE SKP_Silk_PITCH_EST_MID_COMPLEX
#define PITCH_EST_COMPLEXITY_LC_MODE SKP_Silk_PITCH_EST_MIN_COMPLEX
/* Milliseconds of lookahead for noise shape analysis */
#define LA_SHAPE_MS 5
#define LA_SHAPE_MAX ( LA_SHAPE_MS * MAX_FS_KHZ )
/* Max length of LPC window used in noise shape analysis */
#define SHAPE_LPC_WIN_MAX ( 15 * MAX_FS_KHZ )
/* Max number of bytes in payload output buffer (may contain multiple frames) */
#define MAX_ARITHM_BYTES 1024
#define RANGE_CODER_WRITE_BEYOND_BUFFER -1
#define RANGE_CODER_CDF_OUT_OF_RANGE -2
#define RANGE_CODER_NORMALIZATION_FAILED -3
#define RANGE_CODER_ZERO_INTERVAL_WIDTH -4
#define RANGE_CODER_DECODER_CHECK_FAILED -5
#define RANGE_CODER_READ_BEYOND_BUFFER -6
#define RANGE_CODER_ILLEGAL_SAMPLING_RATE -7
#define RANGE_CODER_DEC_PAYLOAD_TOO_LONG -8
/* dB level of lowest gain quantization level */
#define MIN_QGAIN_DB 6
/* dB level of highest gain quantization level */
#define MAX_QGAIN_DB 86
/* Number of gain quantization levels */
#define N_LEVELS_QGAIN 64
/* Max increase in gain quantization index */
#define MAX_DELTA_GAIN_QUANT 40
/* Max decrease in gain quantization index */
#define MIN_DELTA_GAIN_QUANT -4
/* Quantization offsets (multiples of 4) */
#define OFFSET_VL_Q10 32
#define OFFSET_VH_Q10 100
#define OFFSET_UVL_Q10 100
#define OFFSET_UVH_Q10 256
/* Maximum numbers of iterations used to stabilize a LPC vector */
#define MAX_LPC_STABILIZE_ITERATIONS 20
#define MAX_LPC_ORDER 16
#define MIN_LPC_ORDER 10
/* Find Pred Coef defines */
#define LTP_ORDER 5
/* LTP quantization settings */
#define NB_LTP_CBKS 3
/* Number of subframes */
#define NB_SUBFR 4
/* Flag to use harmonic noise shaping */
#define USE_HARM_SHAPING 1
/* Max LPC order of noise shaping filters */
#define MAX_SHAPE_LPC_ORDER 16
#define HARM_SHAPE_FIR_TAPS 3
/* Maximum number of delayed decision states */
#define MAX_DEL_DEC_STATES 4
#define LTP_BUF_LENGTH 512
#define LTP_MASK (LTP_BUF_LENGTH - 1)
#define DECISION_DELAY 32
#define DECISION_DELAY_MASK (DECISION_DELAY - 1)
/* number of subframes for excitation entropy coding */
#define SHELL_CODEC_FRAME_LENGTH 16
#define MAX_NB_SHELL_BLOCKS (MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH)
/* number of rate levels, for entropy coding of excitation */
#define N_RATE_LEVELS 10
/* maximum sum of pulses per shell coding frame */
#define MAX_PULSES 18
#define MAX_MATRIX_SIZE MAX_LPC_ORDER /* Max of LPC Order and LTP order */
#if( MAX_LPC_ORDER > DECISION_DELAY )
# define NSQ_LPC_BUF_LENGTH MAX_LPC_ORDER
#else
# define NSQ_LPC_BUF_LENGTH DECISION_DELAY
#endif
/***********************/
/* High pass filtering */
/***********************/
#define HIGH_PASS_INPUT 1
/***************************/
/* Voice activity detector */
/***************************/
#define VAD_N_BANDS 4
#define VAD_INTERNAL_SUBFRAMES_LOG2 2
#define VAD_INTERNAL_SUBFRAMES (1 << VAD_INTERNAL_SUBFRAMES_LOG2)
#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 1024 /* Must be < 4096 */
#define VAD_NOISE_LEVELS_BIAS 50
/* Sigmoid settings */
#define VAD_NEGATIVE_OFFSET_Q5 128 /* sigmoid is 0 at -128 */
#define VAD_SNR_FACTOR_Q16 45000
/* smoothing for SNR measurement */
#define VAD_SNR_SMOOTH_COEF_Q18 4096
/******************/
/* NLSF quantizer */
/******************/
# define NLSF_MSVQ_MAX_CB_STAGES 10 /* Update manually when changing codebooks */
# define NLSF_MSVQ_MAX_VECTORS_IN_STAGE 128 /* Update manually when changing codebooks */
# define NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END 16 /* Update manually when changing codebooks */
#define NLSF_MSVQ_FLUCTUATION_REDUCTION 1
#define MAX_NLSF_MSVQ_SURVIVORS 16
#define MAX_NLSF_MSVQ_SURVIVORS_LC_MODE 2
#define MAX_NLSF_MSVQ_SURVIVORS_MC_MODE 4
/* Based on above defines, calculate how much memory is necessary to allocate */
#if( NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ) )
# define NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE NLSF_MSVQ_MAX_VECTORS_IN_STAGE
#else
# define NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED_LC_MODE MAX_NLSF_MSVQ_SURVIVORS_LC_MODE * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END
#endif
#if( NLSF_MSVQ_MAX_VECTORS_IN_STAGE > ( MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END ) )
# define NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED NLSF_MSVQ_MAX_VECTORS_IN_STAGE
#else
# define NLSF_MSVQ_TREE_SEARCH_MAX_VECTORS_EVALUATED MAX_NLSF_MSVQ_SURVIVORS * NLSF_MSVQ_MAX_VECTORS_IN_STAGE_TWO_TO_END
#endif
#define NLSF_MSVQ_SURV_MAX_REL_RD 0.1f /* Must be < 0.5 */
/* Transition filtering for mode switching */
#if SWITCH_TRANSITION_FILTERING
# define TRANSITION_TIME_UP_MS 5120 // 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)
# define TRANSITION_TIME_DOWN_MS 2560 // 2560 = 32 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 32*(20*4)
# define TRANSITION_NB 3 /* Hardcoded in tables */
# define TRANSITION_NA 2 /* Hardcoded in tables */
# define TRANSITION_INT_NUM 5 /* Hardcoded in tables */
# define TRANSITION_FRAMES_UP ( TRANSITION_TIME_UP_MS / FRAME_LENGTH_MS )
# define TRANSITION_FRAMES_DOWN ( TRANSITION_TIME_DOWN_MS / FRAME_LENGTH_MS )
# define TRANSITION_INT_STEPS_UP ( TRANSITION_FRAMES_UP / ( TRANSITION_INT_NUM - 1 ) )
# define TRANSITION_INT_STEPS_DOWN ( TRANSITION_FRAMES_DOWN / ( TRANSITION_INT_NUM - 1 ) )
#endif
/* Row based */
#define matrix_ptr(Matrix_base_adr, row, column, N) *(Matrix_base_adr + ((row)*(N)+(column)))
#define matrix_adr(Matrix_base_adr, row, column, N) (Matrix_base_adr + ((row)*(N)+(column)))
/* Column based */
#ifndef matrix_c_ptr
# define matrix_c_ptr(Matrix_base_adr, row, column, M) *(Matrix_base_adr + ((row)+(M)*(column)))
#endif
#define matrix_c_adr(Matrix_base_adr, row, column, M) (Matrix_base_adr + ((row)+(M)*(column)))
/* BWE factors to apply after packet loss */
#define BWE_AFTER_LOSS_Q16 63570
/* Defines for CN generation */
#define CNG_BUF_MASK_MAX 255 /* 2^floor(log2(MAX_FRAME_LENGTH))-1 */
#define CNG_GAIN_SMTH_Q16 4634 /* 0.25^(1/4) */
#define CNG_NLSF_SMTH_Q16 16348 /* 0.25 */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,76 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
/*
* Detect SWB input by measuring energy above 8 kHz.
*/
#include "SKP_Silk_main.h"
void SKP_Silk_detect_SWB_input(
SKP_Silk_detect_SWB_state *psSWBdetect, /* (I/O) encoder state */
const SKP_int16 samplesIn[], /* (I) input to encoder */
SKP_int nSamplesIn /* (I) length of input */
)
{
SKP_int HP_8_kHz_len, i, shift;
SKP_int16 in_HP_8_kHz[ MAX_FRAME_LENGTH ];
SKP_int32 energy_32;
/* High pass filter with cutoff at 8 khz */
HP_8_kHz_len = SKP_min_int( nSamplesIn, MAX_FRAME_LENGTH );
HP_8_kHz_len = SKP_max_int( HP_8_kHz_len, 0 );
/* Cutoff around 9 khz */
/* A = conv(conv([8192,14613, 6868], [8192,12883, 7337]), [8192,11586, 7911]); */
/* B = conv(conv([575, -948, 575], [575, -221, 575]), [575, 104, 575]); */
SKP_Silk_biquad( samplesIn, SKP_Silk_SWB_detect_B_HP_Q13[ 0 ], SKP_Silk_SWB_detect_A_HP_Q13[ 0 ],
psSWBdetect->S_HP_8_kHz[ 0 ], in_HP_8_kHz, HP_8_kHz_len );
for( i = 1; i < NB_SOS; i++ ) {
SKP_Silk_biquad( in_HP_8_kHz, SKP_Silk_SWB_detect_B_HP_Q13[ i ], SKP_Silk_SWB_detect_A_HP_Q13[ i ],
psSWBdetect->S_HP_8_kHz[ i ], in_HP_8_kHz, HP_8_kHz_len );
}
/* Calculate energy in HP signal */
SKP_Silk_sum_sqr_shift( &energy_32, &shift, in_HP_8_kHz, HP_8_kHz_len );
/* Count concecutive samples above threshold, after adjusting threshold for number of input samples and shift */
if( energy_32 > SKP_RSHIFT( SKP_SMULBB( HP_8_KHZ_THRES, HP_8_kHz_len ), shift ) ) {
psSWBdetect->ConsecSmplsAboveThres += nSamplesIn;
if( psSWBdetect->ConsecSmplsAboveThres > CONCEC_SWB_SMPLS_THRES ) {
psSWBdetect->SWB_detected = 1;
}
} else {
psSWBdetect->ConsecSmplsAboveThres -= nSamplesIn;
psSWBdetect->ConsecSmplsAboveThres = SKP_max( psSWBdetect->ConsecSmplsAboveThres, 0 );
}
/* If sufficient speech activity and no SWB detected, we detect the signal as being WB */
if( ( psSWBdetect->ActiveSpeech_ms > WB_DETECT_ACTIVE_SPEECH_MS_THRES ) && ( psSWBdetect->SWB_detected == 0 ) ) {
psSWBdetect->WB_detected = 1;
}
}

View File

@ -0,0 +1,35 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_typedef.h"
SKP_int32 SKP_DIV32_arm( SKP_int32 a32, SKP_int32 b32 ) {
return ( ( SKP_int32 )( ( a32 ) / ( b32 ) ) );
}

View File

@ -0,0 +1,247 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_define.h"
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_SDK_API.h"
#include "SKP_Silk_control.h"
#include "SKP_Silk_typedef.h"
#include "SKP_Silk_structs.h"
#define SKP_Silk_EncodeControlStruct SKP_SILK_SDK_EncControlStruct
/****************************************/
/* Encoder functions */
/****************************************/
SKP_int SKP_Silk_SDK_Get_Encoder_Size( SKP_int32 *encSizeBytes )
{
SKP_int ret = 0;
*encSizeBytes = sizeof( SKP_Silk_encoder_state_FIX );
return ret;
}
/***************************************/
/* Read control structure from encoder */
/***************************************/
SKP_int SKP_Silk_SDK_QueryEncoder(
const void *encState, /* I: State Vector */
SKP_Silk_EncodeControlStruct *encStatus /* O: Control Structure */
)
{
SKP_Silk_encoder_state_FIX *psEnc;
SKP_int ret = 0;
psEnc = ( SKP_Silk_encoder_state_FIX* )encState;
encStatus->API_sampleRate = psEnc->sCmn.API_fs_Hz;
encStatus->maxInternalSampleRate = SKP_SMULBB( psEnc->sCmn.maxInternal_fs_kHz, 1000 );
encStatus->packetSize = ( SKP_int )SKP_DIV32_16( psEnc->sCmn.API_fs_Hz * psEnc->sCmn.PacketSize_ms, 1000 ); /* convert samples -> ms */
encStatus->bitRate = psEnc->sCmn.TargetRate_bps;
encStatus->packetLossPercentage = psEnc->sCmn.PacketLoss_perc;
encStatus->complexity = psEnc->sCmn.Complexity;
encStatus->useInBandFEC = psEnc->sCmn.useInBandFEC;
encStatus->useDTX = psEnc->sCmn.useDTX;
return ret;
}
/*************************/
/* Init or Reset encoder */
/*************************/
SKP_int SKP_Silk_SDK_InitEncoder(
void *encState, /* I/O: State */
SKP_Silk_EncodeControlStruct *encStatus /* O: Control structure */
)
{
SKP_Silk_encoder_state_FIX *psEnc;
SKP_int ret = 0;
psEnc = ( SKP_Silk_encoder_state_FIX* )encState;
/* Reset Encoder */
if( ret += SKP_Silk_init_encoder_FIX( psEnc ) ) {
SKP_assert( 0 );
}
/* Read control structure */
if( ret += SKP_Silk_SDK_QueryEncoder( encState, encStatus ) ) {
SKP_assert( 0 );
}
return ret;
}
/**************************/
/* Encode frame with Silk */
/**************************/
SKP_int SKP_Silk_SDK_Encode(
void *encState, /* I/O: State */
const SKP_Silk_EncodeControlStruct *encControl, /* I: Control structure */
const SKP_int16 *samplesIn, /* I: Speech sample input vector */
SKP_int nSamplesIn, /* I: Number of samples in input vector */
SKP_uint8 *outData, /* O: Encoded output vector */
SKP_int16 *nBytesOut /* I/O: Number of bytes in outData (input: Max bytes) */
)
{
SKP_int max_internal_fs_kHz, PacketSize_ms, PacketLoss_perc, UseInBandFEC, UseDTX, ret = 0;
SKP_int nSamplesToBuffer, Complexity, input_10ms, nSamplesFromInput = 0;
SKP_int32 TargetRate_bps, API_fs_Hz;
SKP_int16 MaxBytesOut;
SKP_Silk_encoder_state_FIX *psEnc = ( SKP_Silk_encoder_state_FIX* )encState;
SKP_assert( encControl != NULL );
/* Check sampling frequency first, to avoid divide by zero later */
if( ( ( encControl->API_sampleRate != 8000 ) &&
( encControl->API_sampleRate != 12000 ) &&
( encControl->API_sampleRate != 16000 ) &&
( encControl->API_sampleRate != 24000 ) &&
( encControl->API_sampleRate != 32000 ) &&
( encControl->API_sampleRate != 44100 ) &&
( encControl->API_sampleRate != 48000 ) ) ||
( ( encControl->maxInternalSampleRate != 8000 ) &&
( encControl->maxInternalSampleRate != 12000 ) &&
( encControl->maxInternalSampleRate != 16000 ) &&
( encControl->maxInternalSampleRate != 24000 ) ) ) {
ret = SKP_SILK_ENC_FS_NOT_SUPPORTED;
SKP_assert( 0 );
return( ret );
}
/* Set encoder parameters from control structure */
API_fs_Hz = encControl->API_sampleRate;
max_internal_fs_kHz = (SKP_int)( encControl->maxInternalSampleRate >> 10 ) + 1; /* convert Hz -> kHz */
PacketSize_ms = SKP_DIV32( 1000 * (SKP_int)encControl->packetSize, API_fs_Hz );
TargetRate_bps = encControl->bitRate;
PacketLoss_perc = encControl->packetLossPercentage;
UseInBandFEC = encControl->useInBandFEC;
Complexity = encControl->complexity;
UseDTX = encControl->useDTX;
/* Save values in state */
psEnc->sCmn.API_fs_Hz = API_fs_Hz;
psEnc->sCmn.maxInternal_fs_kHz = max_internal_fs_kHz;
psEnc->sCmn.useInBandFEC = UseInBandFEC;
/* Only accept input lengths that are a multiple of 10 ms */
input_10ms = SKP_DIV32( 100 * nSamplesIn, API_fs_Hz );
if( input_10ms * API_fs_Hz != 100 * nSamplesIn || nSamplesIn < 0 ) {
ret = SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
SKP_assert( 0 );
return( ret );
}
TargetRate_bps = SKP_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
if( ( ret = SKP_Silk_control_encoder_FIX( psEnc, PacketSize_ms, TargetRate_bps,
PacketLoss_perc, UseDTX, Complexity) ) != 0 ) {
SKP_assert( 0 );
return( ret );
}
/* Make sure no more than one packet can be produced */
if( 1000 * (SKP_int32)nSamplesIn > psEnc->sCmn.PacketSize_ms * API_fs_Hz ) {
ret = SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
SKP_assert( 0 );
return( ret );
}
#if MAX_FS_KHZ > 16
/* Detect energy above 8 kHz */
if( SKP_min( API_fs_Hz, 1000 * max_internal_fs_kHz ) == 24000 &&
psEnc->sCmn.sSWBdetect.SWB_detected == 0 &&
psEnc->sCmn.sSWBdetect.WB_detected == 0 ) {
SKP_Silk_detect_SWB_input( &psEnc->sCmn.sSWBdetect, samplesIn, ( SKP_int )nSamplesIn );
}
#endif
/* Input buffering/resampling and encoding */
MaxBytesOut = 0; /* return 0 output bytes if no encoder called */
while( 1 ) {
nSamplesToBuffer = psEnc->sCmn.frame_length - psEnc->sCmn.inputBufIx;
if( API_fs_Hz == SKP_SMULBB( 1000, psEnc->sCmn.fs_kHz ) ) {
nSamplesToBuffer = SKP_min_int( nSamplesToBuffer, nSamplesIn );
nSamplesFromInput = nSamplesToBuffer;
/* Copy to buffer */
SKP_memcpy( &psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput * sizeof( SKP_int16 ) );
} else {
nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * input_10ms * psEnc->sCmn.fs_kHz );
nSamplesFromInput = SKP_DIV32_16( nSamplesToBuffer * API_fs_Hz, psEnc->sCmn.fs_kHz * 1000 );
/* Resample and write to buffer */
ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state,
&psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput );
}
samplesIn += nSamplesFromInput;
nSamplesIn -= nSamplesFromInput;
psEnc->sCmn.inputBufIx += nSamplesToBuffer;
/* Silk encoder */
if( psEnc->sCmn.inputBufIx >= psEnc->sCmn.frame_length ) {
SKP_assert( psEnc->sCmn.inputBufIx == psEnc->sCmn.frame_length );
/* Enough data in input buffer, so encode */
if( MaxBytesOut == 0 ) {
/* No payload obtained so far */
MaxBytesOut = *nBytesOut;
if( ( ret = SKP_Silk_encode_frame_FIX( psEnc, outData, &MaxBytesOut, psEnc->sCmn.inputBuf ) ) != 0 ) {
SKP_assert( 0 );
}
} else {
/* outData already contains a payload */
if( ( ret = SKP_Silk_encode_frame_FIX( psEnc, outData, nBytesOut, psEnc->sCmn.inputBuf ) ) != 0 ) {
SKP_assert( 0 );
}
/* Check that no second payload was created */
SKP_assert( *nBytesOut == 0 );
}
psEnc->sCmn.inputBufIx = 0;
psEnc->sCmn.controlled_since_last_payload = 0;
if( nSamplesIn == 0 ) {
break;
}
} else {
break;
}
}
*nBytesOut = MaxBytesOut;
if( psEnc->sCmn.useDTX && psEnc->sCmn.inDTX ) {
/* DTX simulation */
*nBytesOut = 0;
}
return ret;
}

View File

@ -0,0 +1,413 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_tuning_parameters.h"
/****************/
/* Encode frame */
/****************/
SKP_int SKP_Silk_encode_frame_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
SKP_uint8 *pCode, /* O Pointer to payload */
SKP_int16 *pnBytesOut, /* I/O Pointer to number of payload bytes */
/* input: max length; output: used */
const SKP_int16 *pIn /* I Pointer to input speech frame */
)
{
SKP_Silk_encoder_control_FIX sEncCtrl;
SKP_int nBytes, ret = 0;
SKP_int16 *x_frame, *res_pitch_frame;
SKP_int16 xfw[ MAX_FRAME_LENGTH ];
SKP_int16 pIn_HP[ MAX_FRAME_LENGTH ];
SKP_int16 res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
SKP_int LBRR_idx, frame_terminator, SNR_dB_Q7;
const SKP_uint16 *FrameTermination_CDF;
/* Low bitrate redundancy parameters */
SKP_uint8 LBRRpayload[ MAX_ARITHM_BYTES ];
SKP_int16 nBytesLBRR;
sEncCtrl.sCmn.Seed = psEnc->sCmn.frameCounter++ & 3;
/**************************************************************/
/* Setup Input Pointers, and insert frame in input buffer */
/*************************************************************/
x_frame = psEnc->x_buf + psEnc->sCmn.frame_length; /* start of frame to encode */
res_pitch_frame = res_pitch + psEnc->sCmn.frame_length; /* start of pitch LPC residual frame */
/****************************/
/* Voice Activity Detection */
/****************************/
ret = SKP_Silk_VAD_GetSA_Q8( &psEnc->sCmn.sVAD, &psEnc->speech_activity_Q8, &SNR_dB_Q7,
sEncCtrl.input_quality_bands_Q15, &sEncCtrl.input_tilt_Q15,
pIn,psEnc->sCmn.frame_length );
/*******************************************/
/* High-pass filtering of the input signal */
/*******************************************/
#if HIGH_PASS_INPUT
/* Variable high-pass filter */
SKP_Silk_HP_variable_cutoff_FIX( psEnc, &sEncCtrl, pIn_HP, pIn );
#else
SKP_memcpy( pIn_HP, pIn, psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );
#endif
#if SWITCH_TRANSITION_FILTERING
/* Ensure smooth bandwidth transitions */
SKP_Silk_LP_variable_cutoff( &psEnc->sCmn.sLP, x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP, psEnc->sCmn.frame_length );
#else
SKP_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, pIn_HP,psEnc->sCmn.frame_length * sizeof( SKP_int16 ) );
#endif
/*****************************************/
/* Find pitch lags, initial LPC analysis */
/*****************************************/
SKP_Silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame );
/************************/
/* Noise shape analysis */
/************************/
SKP_Silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame );
/*****************************************/
/* Prefiltering for noise shaper */
/*****************************************/
SKP_Silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame );
/***************************************************/
/* Find linear prediction coefficients (LPC + LTP) */
/***************************************************/
SKP_Silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch );
/****************************************/
/* Process gains */
/****************************************/
SKP_Silk_process_gains_FIX( psEnc, &sEncCtrl );
/****************************************/
/* Low Bitrate Redundant Encoding */
/****************************************/
nBytesLBRR = MAX_ARITHM_BYTES;
SKP_Silk_LBRR_encode_FIX( psEnc, &sEncCtrl, LBRRpayload, &nBytesLBRR, xfw );
/*****************************************/
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
SKP_Silk_NSQ_del_dec( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sNSQ, xfw,
psEnc->sCmn.q, sEncCtrl.sCmn.NLSFInterpCoef_Q2,
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10,
sEncCtrl.LTP_scale_Q14 );
} else {
SKP_Silk_NSQ( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sNSQ, xfw,
psEnc->sCmn.q, sEncCtrl.sCmn.NLSFInterpCoef_Q2,
sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.Lambda_Q10,
sEncCtrl.LTP_scale_Q14 );
}
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
if( psEnc->speech_activity_Q8 < SKP_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
psEnc->sCmn.vadFlag = NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
if( psEnc->sCmn.noSpeechCounter > NO_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 1;
}
if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NO_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NO_SPEECH_FRAMES_BEFORE_DTX;
psEnc->sCmn.inDTX = 0;
}
} else {
psEnc->sCmn.noSpeechCounter = 0;
psEnc->sCmn.inDTX = 0;
psEnc->sCmn.vadFlag = VOICE_ACTIVITY;
}
/****************************************/
/* Initialize range coder */
/****************************************/
if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {
SKP_Silk_range_enc_init( &psEnc->sCmn.sRC );
psEnc->sCmn.nBytesInPayloadBuf = 0;
}
/****************************************/
/* Encode Parameters */
/****************************************/
SKP_Silk_encode_parameters( &psEnc->sCmn, &sEncCtrl.sCmn, &psEnc->sCmn.sRC, psEnc->sCmn.q );
FrameTermination_CDF = SKP_Silk_FrameTermination_CDF;
/****************************************/
/* Update Buffers and State */
/****************************************/
/* Update input buffer */
SKP_memmove( psEnc->x_buf, &psEnc->x_buf[ psEnc->sCmn.frame_length ],
( psEnc->sCmn.frame_length + LA_SHAPE_MS * psEnc->sCmn.fs_kHz ) * sizeof( SKP_int16 ) );
/* Parameters needed for next frame */
psEnc->sCmn.prev_sigtype = sEncCtrl.sCmn.sigtype;
psEnc->sCmn.prevLag = sEncCtrl.sCmn.pitchL[ NB_SUBFR - 1];
psEnc->sCmn.first_frame_after_reset = 0;
if( psEnc->sCmn.sRC.error ) {
/* Encoder returned error: clear payload buffer */
psEnc->sCmn.nFramesInPayloadBuf = 0;
} else {
psEnc->sCmn.nFramesInPayloadBuf++;
}
/****************************************/
/* Finalize payload and copy to output */
/****************************************/
if( psEnc->sCmn.nFramesInPayloadBuf * FRAME_LENGTH_MS >= psEnc->sCmn.PacketSize_ms ) {
LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK;
/* Check if FEC information should be added */
frame_terminator = SKP_SILK_LAST_FRAME;
if( psEnc->sCmn.LBRR_buffer[ LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS1 ) {
frame_terminator = SKP_SILK_LBRR_VER1;
}
if( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage == SKP_SILK_ADD_LBRR_TO_PLUS2 ) {
frame_terminator = SKP_SILK_LBRR_VER2;
LBRR_idx = psEnc->sCmn.oldest_LBRR_idx;
}
/* Add the frame termination info to stream */
SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF );
/* Payload length so far */
SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes );
/* Check that there is enough space in external output buffer, and move data */
if( *pnBytesOut >= nBytes ) {
SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC );
SKP_memcpy( pCode, psEnc->sCmn.sRC.buffer, nBytes * sizeof( SKP_uint8 ) );
if( frame_terminator > SKP_SILK_MORE_FRAMES &&
*pnBytesOut >= nBytes + psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes ) {
/* Get old packet and add to payload. */
SKP_memcpy( &pCode[ nBytes ],
psEnc->sCmn.LBRR_buffer[ LBRR_idx ].payload,
psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes * sizeof( SKP_uint8 ) );
nBytes += psEnc->sCmn.LBRR_buffer[ LBRR_idx ].nBytes;
}
*pnBytesOut = nBytes;
/* Update FEC buffer */
SKP_memcpy( psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].payload, LBRRpayload,
nBytesLBRR * sizeof( SKP_uint8 ) );
psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].nBytes = nBytesLBRR;
/* The line below describes how FEC should be used */
psEnc->sCmn.LBRR_buffer[ psEnc->sCmn.oldest_LBRR_idx ].usage = sEncCtrl.sCmn.LBRR_usage;
psEnc->sCmn.oldest_LBRR_idx = ( psEnc->sCmn.oldest_LBRR_idx + 1 ) & LBRR_IDX_MASK;
} else {
/* Not enough space: Payload will be discarded */
*pnBytesOut = 0;
nBytes = 0;
ret = SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT;
}
/* Reset the number of frames in payload buffer */
psEnc->sCmn.nFramesInPayloadBuf = 0;
} else {
/* No payload this time */
*pnBytesOut = 0;
/* Encode that more frames follows */
frame_terminator = SKP_SILK_MORE_FRAMES;
SKP_Silk_range_encoder( &psEnc->sCmn.sRC, frame_terminator, FrameTermination_CDF );
/* Payload length so far */
SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC, &nBytes );
}
/* Check for arithmetic coder errors */
if( psEnc->sCmn.sRC.error ) {
ret = SKP_SILK_ENC_INTERNAL_ERROR;
}
/* Simulate number of ms buffered in channel because of exceeding TargetRate */
SKP_assert( ( 8 * 1000 * ( (SKP_int64)nBytes - (SKP_int64)psEnc->sCmn.nBytesInPayloadBuf ) ) ==
SKP_SAT32( 8 * 1000 * ( (SKP_int64)nBytes - (SKP_int64)psEnc->sCmn.nBytesInPayloadBuf ) ) );
SKP_assert( psEnc->sCmn.TargetRate_bps > 0 );
psEnc->BufferedInChannel_ms += SKP_DIV32( 8 * 1000 * ( nBytes - psEnc->sCmn.nBytesInPayloadBuf ), psEnc->sCmn.TargetRate_bps );
psEnc->BufferedInChannel_ms -= FRAME_LENGTH_MS;
psEnc->BufferedInChannel_ms = SKP_LIMIT_int( psEnc->BufferedInChannel_ms, 0, 100 );
psEnc->sCmn.nBytesInPayloadBuf = nBytes;
if( psEnc->speech_activity_Q8 > SKP_FIX_CONST( WB_DETECT_ACTIVE_SPEECH_LEVEL_THRES, 8 ) ) {
psEnc->sCmn.sSWBdetect.ActiveSpeech_ms = SKP_ADD_POS_SAT32( psEnc->sCmn.sSWBdetect.ActiveSpeech_ms, FRAME_LENGTH_MS );
}
return( ret );
}
/* Low BitRate Redundancy encoding functionality. Reuse all parameters but encode residual with lower bitrate */
void SKP_Silk_LBRR_encode_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk encoder state */
SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O Pointer to Silk encoder control struct */
SKP_uint8 *pCode, /* O Pointer to payload */
SKP_int16 *pnBytesOut, /* I/O Pointer to number of payload bytes */
SKP_int16 xfw[] /* I Input signal */
)
{
SKP_int TempGainsIndices[ NB_SUBFR ], frame_terminator;
SKP_int nBytes, nFramesInPayloadBuf;
SKP_int32 TempGains_Q16[ NB_SUBFR ];
SKP_int typeOffset, LTP_scaleIndex, Rate_only_parameters = 0;
/*******************************************/
/* Control use of inband LBRR */
/*******************************************/
SKP_Silk_LBRR_ctrl_FIX( psEnc, &psEncCtrl->sCmn );
if( psEnc->sCmn.LBRR_enabled ) {
/* Save original gains */
SKP_memcpy( TempGainsIndices, psEncCtrl->sCmn.GainsIndices, NB_SUBFR * sizeof( SKP_int ) );
SKP_memcpy( TempGains_Q16, psEncCtrl->Gains_Q16, NB_SUBFR * sizeof( SKP_int32 ) );
typeOffset = psEnc->sCmn.typeOffsetPrev; // Temp save as cannot be overwritten
LTP_scaleIndex = psEncCtrl->sCmn.LTP_scaleIndex;
/* Set max rate where quant signal is encoded */
if( psEnc->sCmn.fs_kHz == 8 ) {
Rate_only_parameters = 13500;
} else if( psEnc->sCmn.fs_kHz == 12 ) {
Rate_only_parameters = 15500;
} else if( psEnc->sCmn.fs_kHz == 16 ) {
Rate_only_parameters = 17500;
} else if( psEnc->sCmn.fs_kHz == 24 ) {
Rate_only_parameters = 19500;
} else {
SKP_assert( 0 );
}
if( psEnc->sCmn.Complexity > 0 && psEnc->sCmn.TargetRate_bps > Rate_only_parameters ) {
if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {
/* First frame in packet; copy everything */
SKP_memcpy( &psEnc->sCmn.sNSQ_LBRR, &psEnc->sCmn.sNSQ, sizeof( SKP_Silk_nsq_state ) );
psEnc->sCmn.LBRRprevLastGainIndex = psEnc->sShape.LastGainIndex;
/* Increase Gains to get target LBRR rate */
psEncCtrl->sCmn.GainsIndices[ 0 ] = psEncCtrl->sCmn.GainsIndices[ 0 ] + psEnc->sCmn.LBRR_GainIncreases;
psEncCtrl->sCmn.GainsIndices[ 0 ] = SKP_LIMIT_int( psEncCtrl->sCmn.GainsIndices[ 0 ], 0, N_LEVELS_QGAIN - 1 );
}
/* Decode to get gains in sync with decoder */
/* Overwrite unquantized gains with quantized gains */
SKP_Silk_gains_dequant( psEncCtrl->Gains_Q16, psEncCtrl->sCmn.GainsIndices,
&psEnc->sCmn.LBRRprevLastGainIndex, psEnc->sCmn.nFramesInPayloadBuf );
/*****************************************/
/* Noise shaping quantization */
/*****************************************/
if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
SKP_Silk_NSQ_del_dec( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sNSQ_LBRR, xfw, psEnc->sCmn.q_LBRR,
psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );
} else {
SKP_Silk_NSQ( &psEnc->sCmn, &psEncCtrl->sCmn, &psEnc->sCmn.sNSQ_LBRR, xfw, psEnc->sCmn.q_LBRR,
psEncCtrl->sCmn.NLSFInterpCoef_Q2, psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
psEncCtrl->Gains_Q16, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );
}
} else {
SKP_memset( psEnc->sCmn.q_LBRR, 0, psEnc->sCmn.frame_length * sizeof( SKP_int8 ) );
psEncCtrl->sCmn.LTP_scaleIndex = 0;
}
/****************************************/
/* Initialize arithmetic coder */
/****************************************/
if( psEnc->sCmn.nFramesInPayloadBuf == 0 ) {
SKP_Silk_range_enc_init( &psEnc->sCmn.sRC_LBRR );
psEnc->sCmn.nBytesInPayloadBuf = 0;
}
/****************************************/
/* Encode Parameters */
/****************************************/
SKP_Silk_encode_parameters( &psEnc->sCmn, &psEncCtrl->sCmn,
&psEnc->sCmn.sRC_LBRR, psEnc->sCmn.q_LBRR );
if( psEnc->sCmn.sRC_LBRR.error ) {
/* Encoder returned error: clear payload buffer */
nFramesInPayloadBuf = 0;
} else {
nFramesInPayloadBuf = psEnc->sCmn.nFramesInPayloadBuf + 1;
}
/****************************************/
/* Finalize payload and copy to output */
/****************************************/
if( SKP_SMULBB( nFramesInPayloadBuf, FRAME_LENGTH_MS ) >= psEnc->sCmn.PacketSize_ms ) {
/* Check if FEC information should be added */
frame_terminator = SKP_SILK_LAST_FRAME;
/* Add the frame termination info to stream */
SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF );
/* Payload length so far */
SKP_Silk_range_coder_get_length( &psEnc->sCmn.sRC_LBRR, &nBytes );
/* Check that there is enough space in external output buffer and move data */
if( *pnBytesOut >= nBytes ) {
SKP_Silk_range_enc_wrap_up( &psEnc->sCmn.sRC_LBRR );
SKP_memcpy( pCode, psEnc->sCmn.sRC_LBRR.buffer, nBytes * sizeof( SKP_uint8 ) );
*pnBytesOut = nBytes;
} else {
/* Not enough space: payload will be discarded */
*pnBytesOut = 0;
SKP_assert( 0 );
}
} else {
/* No payload this time */
*pnBytesOut = 0;
/* Encode that more frames follows */
frame_terminator = SKP_SILK_MORE_FRAMES;
SKP_Silk_range_encoder( &psEnc->sCmn.sRC_LBRR, frame_terminator, SKP_Silk_FrameTermination_CDF );
}
/* Restore original Gains */
SKP_memcpy( psEncCtrl->sCmn.GainsIndices, TempGainsIndices, NB_SUBFR * sizeof( SKP_int ) );
SKP_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, NB_SUBFR * sizeof( SKP_int32 ) );
/* Restore LTP scale index and typeoffset */
psEncCtrl->sCmn.LTP_scaleIndex = LTP_scaleIndex;
psEnc->sCmn.typeOffsetPrev = typeOffset;
}
}

View File

@ -0,0 +1,162 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/*******************************************/
/* Encode parameters to create the payload */
/*******************************************/
void SKP_Silk_encode_parameters(
SKP_Silk_encoder_state *psEncC, /* I/O Encoder state */
SKP_Silk_encoder_control *psEncCtrlC, /* I/O Encoder control */
SKP_Silk_range_coder_state *psRC, /* I/O Range encoder state */
const SKP_int8 *q /* I Quantization indices */
)
{
SKP_int i, k, typeOffset;
const SKP_Silk_NLSF_CB_struct *psNLSF_CB;
/************************/
/* Encode sampling rate */
/************************/
/* only done for first frame in packet */
if( psEncC->nFramesInPayloadBuf == 0 ) {
/* get sampling rate index */
for( i = 0; i < 3; i++ ) {
if( SKP_Silk_SamplingRates_table[ i ] == psEncC->fs_kHz ) {
break;
}
}
SKP_Silk_range_encoder( psRC, i, SKP_Silk_SamplingRates_CDF );
}
/*******************************************/
/* Encode signal type and quantizer offset */
/*******************************************/
typeOffset = 2 * psEncCtrlC->sigtype + psEncCtrlC->QuantOffsetType;
if( psEncC->nFramesInPayloadBuf == 0 ) {
/* first frame in packet: independent coding */
SKP_Silk_range_encoder( psRC, typeOffset, SKP_Silk_type_offset_CDF );
} else {
/* condidtional coding */
SKP_Silk_range_encoder( psRC, typeOffset, SKP_Silk_type_offset_joint_CDF[ psEncC->typeOffsetPrev ] );
}
psEncC->typeOffsetPrev = typeOffset;
/****************/
/* Encode gains */
/****************/
/* first subframe */
if( psEncC->nFramesInPayloadBuf == 0 ) {
/* first frame in packet: independent coding */
SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ 0 ], SKP_Silk_gain_CDF[ psEncCtrlC->sigtype ] );
} else {
/* condidtional coding */
SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ 0 ], SKP_Silk_delta_gain_CDF );
}
/* remaining subframes */
for( i = 1; i < NB_SUBFR; i++ ) {
SKP_Silk_range_encoder( psRC, psEncCtrlC->GainsIndices[ i ], SKP_Silk_delta_gain_CDF );
}
/****************/
/* Encode NLSFs */
/****************/
/* Range encoding of the NLSF path */
psNLSF_CB = psEncC->psNLSF_CB[ psEncCtrlC->sigtype ];
SKP_Silk_range_encoder_multi( psRC, psEncCtrlC->NLSFIndices, psNLSF_CB->StartPtr, psNLSF_CB->nStages );
/* Encode NLSF interpolation factor */
SKP_assert( psEncC->useInterpolatedNLSFs == 1 || psEncCtrlC->NLSFInterpCoef_Q2 == ( 1 << 2 ) );
SKP_Silk_range_encoder( psRC, psEncCtrlC->NLSFInterpCoef_Q2, SKP_Silk_NLSF_interpolation_factor_CDF );
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
/*********************/
/* Encode pitch lags */
/*********************/
/* lag index */
if( psEncC->fs_kHz == 8 ) {
SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_NB_CDF );
} else if( psEncC->fs_kHz == 12 ) {
SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_MB_CDF );
} else if( psEncC->fs_kHz == 16 ) {
SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_WB_CDF );
} else {
SKP_Silk_range_encoder( psRC, psEncCtrlC->lagIndex, SKP_Silk_pitch_lag_SWB_CDF );
}
/* countour index */
if( psEncC->fs_kHz == 8 ) {
/* Less codevectors used in 8 khz mode */
SKP_Silk_range_encoder( psRC, psEncCtrlC->contourIndex, SKP_Silk_pitch_contour_NB_CDF );
} else {
/* Joint for 12, 16, 24 khz */
SKP_Silk_range_encoder( psRC, psEncCtrlC->contourIndex, SKP_Silk_pitch_contour_CDF );
}
/********************/
/* Encode LTP gains */
/********************/
/* PERIndex value */
SKP_Silk_range_encoder( psRC, psEncCtrlC->PERIndex, SKP_Silk_LTP_per_index_CDF );
/* Codebook Indices */
for( k = 0; k < NB_SUBFR; k++ ) {
SKP_Silk_range_encoder( psRC, psEncCtrlC->LTPIndex[ k ], SKP_Silk_LTP_gain_CDF_ptrs[ psEncCtrlC->PERIndex ] );
}
/**********************/
/* Encode LTP scaling */
/**********************/
SKP_Silk_range_encoder( psRC, psEncCtrlC->LTP_scaleIndex, SKP_Silk_LTPscale_CDF );
}
/***************/
/* Encode seed */
/***************/
SKP_Silk_range_encoder( psRC, psEncCtrlC->Seed, SKP_Silk_Seed_CDF );
/*********************************************/
/* Encode quantization indices of excitation */
/*********************************************/
SKP_Silk_encode_pulses( psRC, psEncCtrlC->sigtype, psEncCtrlC->QuantOffsetType, q, psEncC->frame_length );
/*********************************************/
/* Encode VAD flag */
/*********************************************/
SKP_Silk_range_encoder( psRC, psEncC->vadFlag, SKP_Silk_vadflag_CDF );
}

View File

@ -0,0 +1,195 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main.h"
/*********************************************/
/* Encode quantization indices of excitation */
/*********************************************/
SKP_INLINE SKP_int combine_and_check( /* return ok */
SKP_int *pulses_comb, /* O */
const SKP_int *pulses_in, /* I */
SKP_int max_pulses, /* I max value for sum of pulses */
SKP_int len /* I number of output values */
)
{
SKP_int k, sum;
for( k = 0; k < len; k++ ) {
sum = pulses_in[ 2 * k ] + pulses_in[ 2 * k + 1 ];
if( sum > max_pulses ) {
return 1;
}
pulses_comb[ k ] = sum;
}
return 0;
}
/* Encode quantization indices of excitation */
void SKP_Silk_encode_pulses(
SKP_Silk_range_coder_state *psRC, /* I/O Range coder state */
const SKP_int sigtype, /* I Sigtype */
const SKP_int QuantOffsetType,/* I QuantOffsetType */
const SKP_int8 q[], /* I quantization indices */
const SKP_int frame_length /* I Frame length */
)
{
SKP_int i, k, j, iter, bit, nLS, scale_down, RateLevelIndex = 0;
SKP_int32 abs_q, minSumBits_Q6, sumBits_Q6;
SKP_int abs_pulses[ MAX_FRAME_LENGTH ];
SKP_int sum_pulses[ MAX_NB_SHELL_BLOCKS ];
SKP_int nRshifts[ MAX_NB_SHELL_BLOCKS ];
SKP_int pulses_comb[ 8 ];
SKP_int *abs_pulses_ptr;
const SKP_int8 *pulses_ptr;
const SKP_uint16 *cdf_ptr;
const SKP_int16 *nBits_ptr;
SKP_memset( pulses_comb, 0, 8 * sizeof( SKP_int ) ); // Fixing Valgrind reported problem
/****************************/
/* Prepare for shell coding */
/****************************/
/* Calculate number of shell blocks */
iter = frame_length / SHELL_CODEC_FRAME_LENGTH;
/* Take the absolute value of the pulses */
for( i = 0; i < frame_length; i+=4 ) {
abs_pulses[i+0] = ( SKP_int )SKP_abs( q[ i + 0 ] );
abs_pulses[i+1] = ( SKP_int )SKP_abs( q[ i + 1 ] );
abs_pulses[i+2] = ( SKP_int )SKP_abs( q[ i + 2 ] );
abs_pulses[i+3] = ( SKP_int )SKP_abs( q[ i + 3 ] );
}
/* Calc sum pulses per shell code frame */
abs_pulses_ptr = abs_pulses;
for( i = 0; i < iter; i++ ) {
nRshifts[ i ] = 0;
while( 1 ) {
/* 1+1 -> 2 */
scale_down = combine_and_check( pulses_comb, abs_pulses_ptr, SKP_Silk_max_pulses_table[ 0 ], 8 );
/* 2+2 -> 4 */
scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 1 ], 4 );
/* 4+4 -> 8 */
scale_down += combine_and_check( pulses_comb, pulses_comb, SKP_Silk_max_pulses_table[ 2 ], 2 );
/* 8+8 -> 16 */
sum_pulses[ i ] = pulses_comb[ 0 ] + pulses_comb[ 1 ];
if( sum_pulses[ i ] > SKP_Silk_max_pulses_table[ 3 ] ) {
scale_down++;
}
if( scale_down ) {
/* We need to down scale the quantization signal */
nRshifts[ i ]++;
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
abs_pulses_ptr[ k ] = SKP_RSHIFT( abs_pulses_ptr[ k ], 1 );
}
} else {
/* Jump out of while(1) loop and go to next shell coding frame */
break;
}
}
abs_pulses_ptr += SHELL_CODEC_FRAME_LENGTH;
}
/**************/
/* Rate level */
/**************/
/* find rate level that leads to fewest bits for coding of pulses per block info */
minSumBits_Q6 = SKP_int32_MAX;
for( k = 0; k < N_RATE_LEVELS - 1; k++ ) {
nBits_ptr = SKP_Silk_pulses_per_block_BITS_Q6[ k ];
sumBits_Q6 = SKP_Silk_rate_levels_BITS_Q6[sigtype][ k ];
for( i = 0; i < iter; i++ ) {
if( nRshifts[ i ] > 0 ) {
sumBits_Q6 += nBits_ptr[ MAX_PULSES + 1 ];
} else {
sumBits_Q6 += nBits_ptr[ sum_pulses[ i ] ];
}
}
if( sumBits_Q6 < minSumBits_Q6 ) {
minSumBits_Q6 = sumBits_Q6;
RateLevelIndex = k;
}
}
SKP_Silk_range_encoder( psRC, RateLevelIndex, SKP_Silk_rate_levels_CDF[ sigtype ] );
/***************************************************/
/* Sum-Weighted-Pulses Encoding */
/***************************************************/
cdf_ptr = SKP_Silk_pulses_per_block_CDF[ RateLevelIndex ];
for( i = 0; i < iter; i++ ) {
if( nRshifts[ i ] == 0 ) {
SKP_Silk_range_encoder( psRC, sum_pulses[ i ], cdf_ptr );
} else {
SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, cdf_ptr );
for( k = 0; k < nRshifts[ i ] - 1; k++ ) {
SKP_Silk_range_encoder( psRC, MAX_PULSES + 1, SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] );
}
SKP_Silk_range_encoder( psRC, sum_pulses[ i ], SKP_Silk_pulses_per_block_CDF[ N_RATE_LEVELS - 1 ] );
}
}
/******************/
/* Shell Encoding */
/******************/
for( i = 0; i < iter; i++ ) {
if( sum_pulses[ i ] > 0 ) {
SKP_Silk_shell_encoder( psRC, &abs_pulses[ i * SHELL_CODEC_FRAME_LENGTH ] );
}
}
/****************/
/* LSB Encoding */
/****************/
for( i = 0; i < iter; i++ ) {
if( nRshifts[ i ] > 0 ) {
pulses_ptr = &q[ i * SHELL_CODEC_FRAME_LENGTH ];
nLS = nRshifts[ i ] - 1;
for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
abs_q = (SKP_int8)SKP_abs( pulses_ptr[ k ] );
for( j = nLS; j > 0; j-- ) {
bit = SKP_RSHIFT( abs_q, j ) & 1;
SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF );
}
bit = abs_q & 1;
SKP_Silk_range_encoder( psRC, bit, SKP_Silk_lsb_CDF );
}
}
}
/****************/
/* Encode signs */
/****************/
SKP_Silk_encode_signs( psRC, q, frame_length, sigtype, QuantOffsetType, RateLevelIndex );
}

View File

@ -0,0 +1,148 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_tuning_parameters.h"
/* Finds LPC vector from correlations, and converts to NLSF */
void SKP_Silk_find_LPC_FIX(
SKP_int NLSF_Q15[], /* O NLSFs */
SKP_int *interpIndex, /* O NLSF interpolation index, only used for NLSF interpolation */
const SKP_int prev_NLSFq_Q15[], /* I previous NLSFs, only used for NLSF interpolation */
const SKP_int useInterpolatedNLSFs, /* I Flag */
const SKP_int LPC_order, /* I LPC order */
const SKP_int16 x[], /* I Input signal */
const SKP_int subfr_length /* I Input signal subframe length including preceeding samples */
)
{
SKP_int k;
SKP_int32 a_Q16[ MAX_LPC_ORDER ];
SKP_int isInterpLower, shift;
SKP_int16 S[ MAX_LPC_ORDER ];
SKP_int32 res_nrg0, res_nrg1;
SKP_int rshift0, rshift1;
/* Used only for LSF interpolation */
SKP_int32 a_tmp_Q16[ MAX_LPC_ORDER ], res_nrg_interp, res_nrg, res_tmp_nrg;
SKP_int res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q;
SKP_int16 a_tmp_Q12[ MAX_LPC_ORDER ];
SKP_int NLSF0_Q15[ MAX_LPC_ORDER ];
SKP_int16 LPC_res[ ( MAX_FRAME_LENGTH + NB_SUBFR * MAX_LPC_ORDER ) / 2 ];
/* Default: no interpolation */
*interpIndex = 4;
/* Burg AR analysis for the full frame */
SKP_Silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, NB_SUBFR, SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order );
SKP_Silk_bwexpander_32( a_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
if( useInterpolatedNLSFs == 1 ) {
/* Optimal solution for last 10 ms */
SKP_Silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( NB_SUBFR >> 1 ) * subfr_length,
subfr_length, ( NB_SUBFR >> 1 ), SKP_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order );
SKP_Silk_bwexpander_32( a_tmp_Q16, LPC_order, SKP_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
/* subtract residual energy here, as that's easier than adding it to the */
/* residual energy of the first 10 ms in each iteration of the search below */
shift = res_tmp_nrg_Q - res_nrg_Q;
if( shift >= 0 ) {
if( shift < 32 ) {
res_nrg = res_nrg - SKP_RSHIFT( res_tmp_nrg, shift );
}
} else {
SKP_assert( shift > -32 );
res_nrg = SKP_RSHIFT( res_nrg, -shift ) - res_tmp_nrg;
res_nrg_Q = res_tmp_nrg_Q;
}
/* Convert to NLSFs */
SKP_Silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order );
/* Search over interpolation indices to find the one with lowest residual energy */
for( k = 3; k >= 0; k-- ) {
/* Interpolate NLSFs for first half */
SKP_Silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order );
/* Convert to LPC for residual energy evaluation */
SKP_Silk_NLSF2A_stable( a_tmp_Q12, NLSF0_Q15, LPC_order );
/* Calculate residual energy with NLSF interpolation */
SKP_memset( S, 0, LPC_order * sizeof( SKP_int16 ) );
SKP_Silk_LPC_analysis_filter( x, a_tmp_Q12, S, LPC_res, 2 * subfr_length, LPC_order );
SKP_Silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order, subfr_length - LPC_order );
SKP_Silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order );
/* Add subframe energies from first half frame */
shift = rshift0 - rshift1;
if( shift >= 0 ) {
res_nrg1 = SKP_RSHIFT( res_nrg1, shift );
res_nrg_interp_Q = -rshift0;
} else {
res_nrg0 = SKP_RSHIFT( res_nrg0, -shift );
res_nrg_interp_Q = -rshift1;
}
res_nrg_interp = SKP_ADD32( res_nrg0, res_nrg1 );
/* Compare with first half energy without NLSF interpolation, or best interpolated value so far */
shift = res_nrg_interp_Q - res_nrg_Q;
if( shift >= 0 ) {
if( SKP_RSHIFT( res_nrg_interp, shift ) < res_nrg ) {
isInterpLower = SKP_TRUE;
} else {
isInterpLower = SKP_FALSE;
}
} else {
if( -shift < 32 ) {
if( res_nrg_interp < SKP_RSHIFT( res_nrg, -shift ) ) {
isInterpLower = SKP_TRUE;
} else {
isInterpLower = SKP_FALSE;
}
} else {
isInterpLower = SKP_FALSE;
}
}
/* Determine whether current interpolated NLSFs are best so far */
if( isInterpLower == SKP_TRUE ) {
/* Interpolation has lower residual energy */
res_nrg = res_nrg_interp;
res_nrg_Q = res_nrg_interp_Q;
*interpIndex = k;
}
}
}
if( *interpIndex == 4 ) {
/* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
SKP_Silk_A2NLSF( NLSF_Q15, a_Q16, LPC_order );
}
}

View File

@ -0,0 +1,243 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_tuning_parameters.h"
/* Head room for correlations */
#define LTP_CORRS_HEAD_ROOM 2
void SKP_Silk_fit_LTP(
SKP_int32 LTP_coefs_Q16[ LTP_ORDER ],
SKP_int16 LTP_coefs_Q14[ LTP_ORDER ]
);
void SKP_Silk_find_LTP_FIX(
SKP_int16 b_Q14[ NB_SUBFR * LTP_ORDER ], /* O LTP coefs */
SKP_int32 WLTP[ NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O Weight for LTP quantization */
SKP_int *LTPredCodGain_Q7, /* O LTP coding gain */
const SKP_int16 r_first[], /* I residual signal after LPC signal + state for first 10 ms */
const SKP_int16 r_last[], /* I residual signal after LPC signal + state for last 10 ms */
const SKP_int lag[ NB_SUBFR ], /* I LTP lags */
const SKP_int32 Wght_Q15[ NB_SUBFR ], /* I weights */
const SKP_int subfr_length, /* I subframe length */
const SKP_int mem_offset, /* I number of samples in LTP memory */
SKP_int corr_rshifts[ NB_SUBFR ] /* O right shifts applied to correlations */
)
{
SKP_int i, k, lshift;
const SKP_int16 *r_ptr, *lag_ptr;
SKP_int16 *b_Q14_ptr;
SKP_int32 regu;
SKP_int32 *WLTP_ptr;
SKP_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ NB_SUBFR ], nrg[ NB_SUBFR ], g_Q26;
SKP_int32 w[ NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits;
SKP_int32 temp32, denom32;
SKP_int extra_shifts;
SKP_int rr_shifts, maxRshifts, maxRshifts_wxtra, LZs;
SKP_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16;
SKP_int32 Rr[ LTP_ORDER ], rr[ NB_SUBFR ];
SKP_int32 wd, m_Q12;
b_Q14_ptr = b_Q14;
WLTP_ptr = WLTP;
r_ptr = &r_first[ mem_offset ];
for( k = 0; k < NB_SUBFR; k++ ) {
if( k == ( NB_SUBFR >> 1 ) ) { /* shift residual for last 10 ms */
r_ptr = &r_last[ mem_offset ];
}
lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
SKP_Silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */
/* Assure headroom */
LZs = SKP_Silk_CLZ32( rr[k] );
if( LZs < LTP_CORRS_HEAD_ROOM ) {
rr[ k ] = SKP_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs );
rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs );
}
corr_rshifts[ k ] = rr_shifts;
SKP_Silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ] ); /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */
/* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */
SKP_Silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ] ); /* Rr_fix_ptr in Q( -corr_rshifts[ k ] ) */
if( corr_rshifts[ k ] > rr_shifts ) {
rr[ k ] = SKP_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */
}
SKP_assert( rr[ k ] >= 0 );
regu = 1;
regu = SKP_SMLAWB( regu, rr[ k ], SKP_FIX_CONST( LTP_DAMPING/3, 16 ) );
regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SKP_FIX_CONST( LTP_DAMPING/3, 16 ) );
regu = SKP_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SKP_FIX_CONST( LTP_DAMPING/3, 16 ) );
SKP_Silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER );
SKP_Silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */
/* Limit and store in Q14 */
SKP_Silk_fit_LTP( b_Q16, b_Q14_ptr );
/* Calculate residual energy */
nrg[ k ] = SKP_Silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */
/* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */
extra_shifts = SKP_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM );
denom32 = SKP_LSHIFT_SAT32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */
SKP_RSHIFT( SKP_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts ); /* Q( -corr_rshifts[ k ] + extra_shifts ) */
denom32 = SKP_max( denom32, 1 );
SKP_assert( ((SKP_int64)Wght_Q15[ k ] << 16 ) < SKP_int32_MAX ); /* Wght always < 0.5 in Q0 */
temp32 = SKP_DIV32( SKP_LSHIFT( ( SKP_int32 )Wght_Q15[ k ], 16 ), denom32 ); /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
temp32 = SKP_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 ); /* Q26 */
/* Limit temp such that the below scaling never wraps around */
WLTP_max = 0;
for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
WLTP_max = SKP_max( WLTP_ptr[ i ], WLTP_max );
}
lshift = SKP_Silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
SKP_assert( 26 - 18 + lshift >= 0 );
if( 26 - 18 + lshift < 31 ) {
temp32 = SKP_min_32( temp32, SKP_LSHIFT( ( SKP_int32 )1, 26 - 18 + lshift ) );
}
SKP_Silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
w[ k ] = matrix_ptr( WLTP_ptr, ( LTP_ORDER >> 1 ), ( LTP_ORDER >> 1 ), LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */
SKP_assert( w[k] >= 0 );
r_ptr += subfr_length;
b_Q14_ptr += LTP_ORDER;
WLTP_ptr += LTP_ORDER * LTP_ORDER;
}
maxRshifts = 0;
for( k = 0; k < NB_SUBFR; k++ ) {
maxRshifts = SKP_max_int( corr_rshifts[ k ], maxRshifts );
}
/* Compute LTP coding gain */
if( LTPredCodGain_Q7 != NULL ) {
LPC_LTP_res_nrg = 0;
LPC_res_nrg = 0;
SKP_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */
for( k = 0; k < NB_SUBFR; k++ ) {
LPC_res_nrg = SKP_ADD32( LPC_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
LPC_LTP_res_nrg = SKP_ADD32( LPC_LTP_res_nrg, SKP_RSHIFT( SKP_ADD32( SKP_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
}
LPC_LTP_res_nrg = SKP_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */
div_Q16 = SKP_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 );
*LTPredCodGain_Q7 = ( SKP_int )SKP_SMULBB( 3, SKP_Silk_lin2log( div_Q16 ) - ( 16 << 7 ) );
SKP_assert( *LTPredCodGain_Q7 == ( SKP_int )SKP_SAT16( SKP_MUL( 3, SKP_Silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) );
}
/* smoothing */
/* d = sum( B, 1 ); */
b_Q14_ptr = b_Q14;
for( k = 0; k < NB_SUBFR; k++ ) {
d_Q14[ k ] = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
d_Q14[ k ] += b_Q14_ptr[ i ];
}
b_Q14_ptr += LTP_ORDER;
}
/* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
/* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */
max_abs_d_Q14 = 0;
max_w_bits = 0;
for( k = 0; k < NB_SUBFR; k++ ) {
max_abs_d_Q14 = SKP_max_32( max_abs_d_Q14, SKP_abs( d_Q14[ k ] ) );
/* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */
/* Find bits needed in Q( 18 - maxRshifts ) */
max_w_bits = SKP_max_32( max_w_bits, 32 - SKP_Silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts );
}
/* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -SKP_int16_MIN */
SKP_assert( max_abs_d_Q14 <= ( 5 << 15 ) );
/* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */
extra_shifts = max_w_bits + 32 - SKP_Silk_CLZ32( max_abs_d_Q14 ) - 14;
/* Subtract what we got available; bits in output var plus maxRshifts */
extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */
extra_shifts = SKP_max_int( extra_shifts, 0 );
maxRshifts_wxtra = maxRshifts + extra_shifts;
temp32 = SKP_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */
wd = 0;
for( k = 0; k < NB_SUBFR; k++ ) {
/* w has at least 2 bits of headroom so no overflow should happen */
temp32 = SKP_ADD32( temp32, SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) ); /* Q( 18 - maxRshifts_wxtra ) */
wd = SKP_ADD32( wd, SKP_LSHIFT( SKP_SMULWW( SKP_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */
}
m_Q12 = SKP_DIV32_varQ( wd, temp32, 12 );
b_Q14_ptr = b_Q14;
for( k = 0; k < NB_SUBFR; k++ ) {
/* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */
if( 2 - corr_rshifts[k] > 0 ) {
temp32 = SKP_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] );
} else {
temp32 = SKP_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 );
}
g_Q26 = SKP_MUL(
SKP_DIV32(
SKP_FIX_CONST( LTP_SMOOTHING, 26 ),
SKP_RSHIFT( SKP_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ), /* Q10 */
SKP_LSHIFT_SAT32( SKP_SUB_SAT32( ( SKP_int32 )m_Q12, SKP_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) ); /* Q16 */
temp32 = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
delta_b_Q14[ i ] = SKP_max_16( b_Q14_ptr[ i ], 1638 ); /* 1638_Q14 = 0.1_Q0 */
temp32 += delta_b_Q14[ i ]; /* Q14 */
}
temp32 = SKP_DIV32( g_Q26, temp32 ); /* Q14->Q12 */
for( i = 0; i < LTP_ORDER; i++ ) {
b_Q14_ptr[ i ] = SKP_LIMIT_32( ( SKP_int32 )b_Q14_ptr[ i ] + SKP_SMULWB( SKP_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
}
b_Q14_ptr += LTP_ORDER;
}
}
void SKP_Silk_fit_LTP(
SKP_int32 LTP_coefs_Q16[ LTP_ORDER ],
SKP_int16 LTP_coefs_Q14[ LTP_ORDER ]
)
{
SKP_int i;
for( i = 0; i < LTP_ORDER; i++ ) {
LTP_coefs_Q14[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
}
}

View File

@ -0,0 +1,125 @@
/***********************************************************************
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, (subject to the limitations in the disclaimer below)
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Skype Limited, nor the names of specific
contributors, may be used to endorse or promote products derived from
this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#include "SKP_Silk_main_FIX.h"
#include "SKP_Silk_tuning_parameters.h"
/* Find pitch lags */
void SKP_Silk_find_pitch_lags_FIX(
SKP_Silk_encoder_state_FIX *psEnc, /* I/O encoder state */
SKP_Silk_encoder_control_FIX *psEncCtrl, /* I/O encoder control */
SKP_int16 res[], /* O residual */
const SKP_int16 x[] /* I Speech signal */
)
{
SKP_Silk_predict_state_FIX *psPredSt = &psEnc->sPred;
SKP_int buf_len, i, scale;
SKP_int32 thrhld_Q15, res_nrg;
const SKP_int16 *x_buf, *x_buf_ptr;
SKP_int16 Wsig[ FIND_PITCH_LPC_WIN_MAX ], *Wsig_ptr;
SKP_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
SKP_int16 rc_Q15[ MAX_FIND_PITCH_LPC_ORDER ];
SKP_int32 A_Q24[ MAX_FIND_PITCH_LPC_ORDER ];
SKP_int32 FiltState[ MAX_FIND_PITCH_LPC_ORDER ];
SKP_int16 A_Q12[ MAX_FIND_PITCH_LPC_ORDER ];
/******************************************/
/* Setup buffer lengths etc based on Fs */
/******************************************/
buf_len = SKP_ADD_LSHIFT( psEnc->sCmn.la_pitch, psEnc->sCmn.frame_length, 1 );
/* Safty check */
SKP_assert( buf_len >= psPredSt->pitch_LPC_win_length );
x_buf = x - psEnc->sCmn.frame_length;
/*************************************/
/* Estimate LPC AR coefficients */
/*************************************/
/* Calculate windowed signal */
/* First LA_LTP samples */
x_buf_ptr = x_buf + buf_len - psPredSt->pitch_LPC_win_length;
Wsig_ptr = Wsig;
SKP_Silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
/* Middle un - windowed samples */
Wsig_ptr += psEnc->sCmn.la_pitch;
x_buf_ptr += psEnc->sCmn.la_pitch;
SKP_memcpy( Wsig_ptr, x_buf_ptr, ( psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( SKP_int16 ) );
/* Last LA_LTP samples */
Wsig_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 );
x_buf_ptr += psPredSt->pitch_LPC_win_length - SKP_LSHIFT( psEnc->sCmn.la_pitch, 1 );
SKP_Silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
/* Calculate autocorrelation sequence */
SKP_Silk_autocorr( auto_corr, &scale, Wsig, psPredSt->pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1 );
/* Add white noise, as fraction of energy */
auto_corr[ 0 ] = SKP_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SKP_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
/* Calculate the reflection coefficients using schur */
res_nrg = SKP_Silk_schur( rc_Q15, auto_corr, psEnc->sCmn.pitchEstimationLPCOrder );
/* Prediction gain */
psEncCtrl->predGain_Q16 = SKP_DIV32_varQ( auto_corr[ 0 ], SKP_max_int( res_nrg, 1 ), 16 );
/* Convert reflection coefficients to prediction coefficients */
SKP_Silk_k2a( A_Q24, rc_Q15, psEnc->sCmn.pitchEstimationLPCOrder );
/* Convert From 32 bit Q24 to 16 bit Q12 coefs */
for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) {
A_Q12[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT( A_Q24[ i ], 12 ) );
}
/* Do BWE */
SKP_Silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SKP_FIX_CONST( FIND_PITCH_BANDWITH_EXPANSION, 16 ) );
/*****************************************/
/* LPC analysis filtering */
/*****************************************/
SKP_memset( FiltState, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int32 ) ); /* Not really necessary, but Valgrind will complain otherwise */
SKP_Silk_MA_Prediction( x_buf, A_Q12, FiltState, res, buf_len, psEnc->sCmn.pitchEstimationLPCOrder );
SKP_memset( res, 0, psEnc->sCmn.pitchEstimationLPCOrder * sizeof( SKP_int16 ) );
/* Threshold for pitch estimator */
thrhld_Q15 = SKP_FIX_CONST( 0.45, 15 );
thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( -0.004, 15 ), psEnc->sCmn.pitchEstimationLPCOrder );
thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( -0.1, 7 ), psEnc->speech_activity_Q8 );
thrhld_Q15 = SKP_SMLABB( thrhld_Q15, SKP_FIX_CONST( 0.15, 15 ), psEnc->sCmn.prev_sigtype );
thrhld_Q15 = SKP_SMLAWB( thrhld_Q15, SKP_FIX_CONST( -0.1, 16 ), psEncCtrl->input_tilt_Q15 );
thrhld_Q15 = SKP_SAT16( thrhld_Q15 );
/*****************************************/
/* Call pitch estimator */
/*****************************************/
psEncCtrl->sCmn.sigtype = SKP_Silk_pitch_analysis_core( res, psEncCtrl->sCmn.pitchL, &psEncCtrl->sCmn.lagIndex,
&psEncCtrl->sCmn.contourIndex, &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16,
( SKP_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, SKP_FALSE );
}

Some files were not shown because too many files have changed in this diff Show More