diff --git a/.gitattributes b/.gitattributes
index a6344aac8c09253b3b630fb776ae94478aa0275b..e62b6dabd23e9bcadc58d7896d5f2b6ca83694da 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text
*tfevents* filter=lfs diff=lfs merge=lfs -text
+*.wav filter=lfs diff=lfs merge=lfs -text
+*.png filter=lfs diff=lfs merge=lfs -text
+*.so filter=lfs diff=lfs merge=lfs -text
+*.so.* filter=lfs diff=lfs merge=lfs -text
+*.a filter=lfs diff=lfs merge=lfs -text
+*.a.* filter=lfs diff=lfs merge=lfs -text
+duix-android/dh_aigc_android/duix-sdk/src/main/cpp/linux/gjgpgmain filter=lfs diff=lfs merge=lfs -text
diff --git a/duix-android/dh_aigc_android/.gitignore b/duix-android/dh_aigc_android/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..094ba2d776c830090adb0938251e3c5dfdb953ae
--- /dev/null
+++ b/duix-android/dh_aigc_android/.gitignore
@@ -0,0 +1,25 @@
+*.iml
+.gradle
+/local.properties
+/.idea/
+.DS_Store
+/build/
+*/build/
+*/*/build/
+*/debug/
+*/release/
+/captures
+.externalNativeBuild
+.cxx
+*.bat
+*.apk
+output-metadata.json
+# app用到zip的请忽略
+# 自定义了local.properties的请删除这条
+local.properties
+~$*
+gradlew
+.idea
+# 自定义了根目录gradle/gradle-wrapper.properties的请删除这条(不推荐自定义)
+#gradle
+build
diff --git a/duix-android/dh_aigc_android/README.md b/duix-android/dh_aigc_android/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..912eefd5e3502106e0061f86986c43014fc0ad0f
--- /dev/null
+++ b/duix-android/dh_aigc_android/README.md
@@ -0,0 +1,268 @@
+# DUIX-SDK
+2D虚拟数字人SDK,可以通过语音完成对虚拟人实时驱动。
+
+## 一、产品介绍
+
+2D 数字人虚拟人SDK ,可以通过语音完成对虚拟人实时驱动。
+
+### 1. 适用场景
+
+部署成本低: 无需客户提供技术团队进行配合,支持低成本快速部署在多种终端及大屏;
+网络依赖小:可落地在地铁、银行、政务等多种场景的虚拟助理自助服务上;
+功能多样化:可根据客户需求满足视频、媒体、客服、金融、广电等多个行业的多样化需求
+
+### 2. 核心功能
+
+提供定制形象的 AI 主播,智能客服等多场景形象租赁,支持客户快速部署和低成本运营;
+专属形象定制:支持定制专属的虚拟助理形象,可选低成本或深度形象生成;
+播报内容定制:支持定制专属的播报内容,应用在培训、播报等多种场景上;
+实时互动问答:支持实时对话,也可定制专属问答库,可满足咨询查询、语音闲聊、虚拟陪伴、垂类场景的客服问答等需求。
+
+## 二、SDK集成
+
+### 1. 支持的系统和硬件版本
+
+| 项目 | 描述 |
+|--------|------------------------------------------------------------------|
+| 系统 | 支持 Android 7.0+ ( API Level 24 )到 Android 13 ( API Level 33 )系统。 |
+| CPU架构 | armeabi-v7a, arm64-v8a |
+| 硬件要求 | 要求设备 CPU4 核极以上,内存 4G 及以上。可用存储空间 500MB 及以上。 |
+| 网络 | 支持 WIF 及移动网络。如果使用云端问答库,设备带宽(用于数字人的实际带宽)期望 10mbps 及以上。 |
+| 开发 IDE | Android Studio Giraffe \mid 2022.3.1 Patch 2 |
+| 内存要求 | 可用于数字人的内存 >= 400MB |
+
+##两个人物模型(切换男女形象,修改./duix-android/dh_aigc_android/test/src/main/java/ai/guiji/duix/test/ui/activity/MainActivity.kt的modelUrl变量即可)
+```
+ 女:https://cdn.guiji.ai/duix/digital/model/1712034391673/bendi1_0329.zip
+ 男:https://digital-public.obs.cn-east-3.myhuaweicloud.com/duix/digital/model/1706009711636/liangwei_540s.zip
+```
+
+### 2. SDK集成
+
+引入 sdk aar 包: duix_client_sdk_release_${version}.aar
+app 目录新建 libs 目录,放入 aar 包,在 build.gradle 中增加配置如下
+
+```gradle
+dependencies {
+ // 使用阿里ASR需要将nuisdk-release.aar放到libs目录下(必选)
+ implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
+ // sdk 中使用到 exoplayer 处理音频(必选)
+ implementation 'com.google.android.exoplayer:exoplayer:2.14.2'
+
+ // 云端问答接口使用的SSE组件(非必选)
+ implementation 'com.squareup.okhttp3:okhttp-sse:4.10.0'
+
+ ...
+}
+```
+
+权限要求, AndroidManifest.xml中,增加如下配置
+
+```xml
+
+
+
+
+
+
+
+
+
+
+```
+
+## 三、SDK调用及API说明
+
+### 1. 初始化SDK
+
+在渲染页onCreate()阶段构建DUIX对象并添加回调事件
+
+```kotlin
+duix = DUIX(mContext, baseDir, modelDir, mDUIXRender) { event, msg, info ->
+ when (event) {
+ ai.guiji.duix.sdk.client.Constant.CALLBACK_EVENT_INIT_READY -> {
+ initOK()
+ }
+
+ ai.guiji.duix.sdk.client.Constant.CALLBACK_EVENT_INIT_ERROR -> {
+
+ }
+ // ...
+
+ }
+}
+// 异步回调结果
+duix?.init()
+```
+
+
+
+DUIX对象构建说明:
+
+| 参数 | 类型 | 描述 |
+| -------- | ---------- | ------------------------------------------------------------ |
+| context | Context | 系统上下文 |
+| baseDir | String | 存放模型驱动的配置文件,需要自行管理. 可将压缩文件解压到外部存储并提供文件夹路径 |
+| modelDir | String | 存放模型文件的文件夹,需要自行管理. 可将压缩文件解压到外部存储并提供文件夹路径 |
+| render | RenderSink | 渲染数据接口,sdk提供了默认的渲染组件继承自该接口,也可以自己实现 |
+| callback | Callback | SDK处理的各种回调事件 |
+
+参考demo LiveActivity示例
+
+### 2. 获取SDK模型初始化状态
+
+```kotlin
+object : Callback {
+ fun onEvent(event: String, msg: String, info: Object) {
+ when (event) {
+ "init.ready" -> {
+ // SDK模型初始化成功
+ }
+
+ "init.error" -> {
+ //初始化失败
+ Log.e(TAG, "init error: $msg")
+ }
+ // ...
+
+ }
+ }
+}
+```
+
+### 3. 数字人形象展示
+
+使用RenderSink接口接受渲染帧数据,SDK中提供了该接口实现DUIXRenderer.java。也可以自己实现该接口自定义渲染。
+其中RenderSink的定义如下:
+
+```java
+/**
+ * 渲染管道,通过该接口返回渲染数据
+ */
+public interface RenderSink {
+
+ // frame中的buffer数据以bgr顺序排列
+ void onVideoFrame(ImageFrame imageFrame);
+
+}
+```
+
+使用DUIXRenderer及DUIXTextureView控件简单实现渲染展示,该控件支持透明通道可以自由设置背景及前景:
+
+```kotlin
+override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // ...
+ mDUIXRender =
+ DUIXRenderer(
+ mContext,
+ binding.glTextureView
+ )
+
+ binding.glTextureView.setEGLContextClientVersion(GL_CONTEXT_VERSION)
+ binding.glTextureView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) // 透明
+ binding.glTextureView.isOpaque = false // 透明
+ binding.glTextureView.setRenderer(mDUIXRender)
+ binding.glTextureView.renderMode =
+ GLSurfaceView.RENDERMODE_WHEN_DIRTY // 一定要在设置完Render之后再调用
+
+ duix = DUIX(mContext, duixOptions, mDUIXRender) { event, msg, _ ->
+ }
+ // ...
+}
+```
+
+### 4. 启动数字人播报
+
+在初始化成功后,可以播放音频以驱动形象
+
+```kotlin
+duix?.playAudio(wavPath)
+```
+
+参数说明:
+
+| 参数 | 类型 | 描述 |
+|---------|--------|-----------------------------|
+| wavPath | String | 16k采样率单通道的wav文件地址或https网络地址 |
+
+音频播放状态及进度回调:
+
+```kotlin
+object : Callback {
+ fun onEvent(event: String, msg: String, info: Object) {
+ when (event) {
+ // ...
+
+ "play.start" -> {
+ // 开始播放音频
+ }
+
+ "play.end" -> {
+ // 完成播放音频
+ }
+ "play.error" -> {
+ // 音频播放异常
+ }
+ "play.progress" -> {
+ // 音频播放进度
+ }
+
+ }
+ }
+}
+
+```
+
+### 5. 终止当前播报
+
+当数字人正在播报时调用该接口终止播报。
+
+函数定义:
+
+```
+boolean stopAudio();
+```
+
+调用示例如下:
+
+```kotlin
+duix?.stopAudio()
+```
+
+### 6. 播放动作区间
+
+当模型中支持播放动作区间时可使用该函数播放多做区间,多个时随机播放。
+
+函数定义:
+
+```
+void motion();
+```
+
+调用示例如下:
+
+```kotlin
+duix?.motion()
+```
+
+###
+
+### 四. Proguard配置
+
+如果代码使用了混淆,请在proguard-rules.pro中配置:
+
+```
+-keep class com.btows.ncnntest.**{*; }
+-dontwarn com.squareup.okhttp3.**
+-keep class com.squareup.okhttp3.** { *;}
+```
+
+## 五、注意事项
+
+1. 驱动渲染必须正确的配置基础配置文件夹和对应模型文件夹的存储路径。
+2. 播放的音频文件不宜过大,过大的音频导入会导致大量消耗CPU,从而造成绘制卡顿。
+
+
+
+## 六、版本记录
diff --git a/duix-android/dh_aigc_android/android_glide_lint.xml b/duix-android/dh_aigc_android/android_glide_lint.xml
new file mode 100644
index 0000000000000000000000000000000000000000..90c96a4f60566b2bf7f4cd2da58c3053ce1ee233
--- /dev/null
+++ b/duix-android/dh_aigc_android/android_glide_lint.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/build.gradle b/duix-android/dh_aigc_android/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d22ff0ce792960a3b1c3a20a83e1bfc76a4755ec
--- /dev/null
+++ b/duix-android/dh_aigc_android/build.gradle
@@ -0,0 +1,39 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+ repositories {
+
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://jitpack.io' }
+ maven { url 'https://repo1.maven.org/maven2/' }
+ google()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:8.1.2'
+ classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10'
+ }
+}
+
+allprojects {
+ repositories {
+
+ maven { url 'https://maven.aliyun.com/repository/public/' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://jitpack.io' }
+ maven { url 'https://repo1.maven.org/maven2/' }
+ google()
+ }
+}
+
+ext {
+ compileSdkVersion = 33
+ buildToolsVersion = '30.0.2'
+ minSdkVersion = 24
+ targetSdkVersion = 33
+ versionCode = 2
+ versionName = "0.0.2"
+}
diff --git a/duix-android/dh_aigc_android/demo.jks b/duix-android/dh_aigc_android/demo.jks
new file mode 100644
index 0000000000000000000000000000000000000000..3cfe0f594f0f2bcf1d273354d7c8d0066868a86c
Binary files /dev/null and b/duix-android/dh_aigc_android/demo.jks differ
diff --git a/duix-android/dh_aigc_android/duix-sdk/.gitignore b/duix-android/dh_aigc_android/duix-sdk/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/duix-sdk/build.gradle b/duix-android/dh_aigc_android/duix-sdk/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d4f1a8ae4bac60de29c572be4e4786964b0f8c54
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/build.gradle
@@ -0,0 +1,68 @@
+plugins {
+ id 'com.android.library'
+}
+
+android {
+ namespace 'ai.guiji.duix.sdk.client'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 24
+ versionCode 4
+ versionName '3.0.3'
+
+ externalNativeBuild {
+ cmake {
+ abiFilters 'arm64-v8a', "armeabi-v7a"
+ cppFlags "-std=c++17", "-fexceptions"
+ //arguments "-DANDROID_STL=c++_shared","-DANDROID_TOOLCHAIN=clang"
+ }
+ }
+ }
+
+ buildTypes {
+ debug {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+
+ buildConfigField("String", "VERSION_NAME", "\"${defaultConfig.versionName}\"")
+ buildConfigField('int', 'VERSION_CODE', "${defaultConfig.versionCode}")
+ }
+
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+
+ buildConfigField("String", "VERSION_NAME", "\"${defaultConfig.versionName}\"")
+ buildConfigField('int', 'VERSION_CODE', "${defaultConfig.versionCode}")
+
+ android.libraryVariants.all { variant ->
+ variant.outputs.all {
+ outputFileName = "duix_client_sdk_${buildType.name}_${defaultConfig.versionName}.aar"
+ }
+ }
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "src/main/cpp/CMakeLists.txt"
+ version "3.10.2"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+// kotlinOptions {
+// jvmTarget = '1.8'
+// }
+}
+
+dependencies {
+
+ implementation 'com.google.android.exoplayer:exoplayer:2.14.2'
+ implementation "org.java-websocket:Java-WebSocket:1.5.1"
+ implementation 'com.squareup.okhttp3:okhttp-sse:4.10.0'
+}
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/duix-sdk/consumer-rules.pro b/duix-android/dh_aigc_android/duix-sdk/consumer-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/duix-android/dh_aigc_android/duix-sdk/proguard-rules.pro b/duix-android/dh_aigc_android/duix-sdk/proguard-rules.pro
new file mode 100644
index 0000000000000000000000000000000000000000..a541d5df11e817a798ec59dc442d8e9355afefeb
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/proguard-rules.pro
@@ -0,0 +1,104 @@
+# 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
+
+-optimizationpasses 5 #指定代码的压缩级别 0 - 7,一般都是5,无需改变
+-dontusemixedcaseclassnames #不使用大小写混合
+#告诉Proguard 不要跳过对非公开类的处理,默认是跳过
+-dontskipnonpubliclibraryclasses #如果应用程序引入的有jar包,并且混淆jar包里面的class
+-verbose #混淆时记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射
+#指定混淆时的算法,后面的参数是一个过滤器
+#这个过滤器是谷歌推荐的算法,一般也不会改变
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+#类型转换错误 添加如下代码以便过滤泛型(不写可能会出现类型转换错误,一般情况把这个加上就是了),即避免泛型被混淆
+-keepattributes Signature
+#假如项目中有用到注解,应加入这行配置,对JSON实体映射也很重要,eg:fastjson
+-keepattributes *Annotation*
+#抛出异常时保留代码行数
+-keepattributes SourceFile,LineNumberTable
+#保持 native 的方法不去混淆
+-keepclasseswithmembernames class * {
+ native ;
+}
+
+#保持指定规则的方法不被混淆(Android layout 布局文件中为控件配置的onClick方法不能混淆)
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+#保持自定义控件指定规则的方法不被混淆
+-keep public class * extends android.view.View {
+ public (android.content.Context);
+ public (android.content.Context, android.util.AttributeSet);
+ public (android.content.Context, android.util.AttributeSet, int);
+ public void set*(...);
+}
+#保持枚举 enum 不被混淆
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+#保持 Parcelable 不被混淆(aidl文件不能去混淆)
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
+#需要序列化和反序列化的类不能被混淆(注:Java反射用到的类也不能被混淆)
+-keepnames class * implements java.io.Serializable
+#保护实现接口Serializable的类中,指定规则的类成员不被混淆
+-keepclassmembers class * implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ !static !transient ;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+#保持R文件不被混淆,否则,你的反射是获取不到资源id的
+-keep class **.R$* { *; }
+
+-keepclassmembers class * {
+ public (org.json.JSONObject);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+
+#以下针对App本身设置
+
+
+-keep class com.btows.ncnntest.**{*; }
+
+-keep class ai.guiji.duix.sdk.client.render.** {*;}
+-keep class ai.guiji.duix.sdk.client.render.**$* {*;}
+-keep class ai.guiji.duix.sdk.client.bean.** {*;}
+-keep class ai.guiji.duix.sdk.client.DUIX{*; }
+-keep class ai.guiji.duix.sdk.client.DUIX$* {*;}
+-keep class ai.guiji.duix.sdk.client.Constant{*; }
+-keep class ai.guiji.duix.sdk.client.Constant* {*;}
+-keep class ai.guiji.duix.sdk.client.DUIXOptions{*; }
+-keep class ai.guiji.duix.sdk.client.DUIXOptions* {*;}
+-keep class ai.guiji.duix.sdk.client.Callback{*; }
+-keep class ai.guiji.duix.sdk.client.Callback* {*;}
+-keep class ai.guiji.duix.sdk.client.render.DUIXTextureView{*; }
+-keep class ai.guiji.duix.sdk.client.render.DUIXTextureView$* {*;}
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/AndroidManifest.xml b/duix-android/dh_aigc_android/duix-sdk/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a8800291f3c2fb5aa0455bb8d4341b7f5528aeeb
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/Android.mk64 b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/Android.mk64
new file mode 100644
index 0000000000000000000000000000000000000000..cc93d444e645902a3321cf140b31d24c229bf4a8
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/Android.mk64
@@ -0,0 +1,86 @@
+#/****************************************************************************
+#* Cartoonifier, for Android.
+#*****************************************************************************
+#* by Shervin Emami, 5th Dec 2012 (shervin.emami@gmail.com)
+#* http://www.shervinemami.info/
+#*****************************************************************************
+#* Ch1 of the book "Mastering OpenCV with Practical Computer Vision Projects"
+#* Copyright Packt Publishing 2012.
+#* http://www.packtpub.com/cool-projects-with-opencv/book
+#****************************************************************************/
+
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+
+
+
+LOCAL_SRC_FILES += \
+ base/coffeecatch.c \
+ android/DigitJni.cpp \
+ android/MsgcbJni.cpp \
+ android/JniHelper.cpp \
+ aisdk/jmat.cpp \
+ android/kmatarm.cpp \
+ aisdk/wavreader.cpp \
+ aisdk/wenet.cpp \
+ aisdk/aimodel.cpp \
+ aisdk/scrfd.cpp \
+ aisdk/pfpld.cpp \
+ aisdk/munet.cpp \
+ aisdk/blendgram.cpp \
+ aisdk/face_utils.cpp \
+ digit/netwav.cpp \
+ digit/looper.cpp \
+ digit/netcurl.cpp \
+ digit/GRender.cpp \
+ digit/GDigit.cpp \
+ digit/dispatchqueue.cpp \
+ render/EglRenderer.cpp \
+ render/RgbVideoRenderer.cpp \
+ render/SurfaceVideoRenderer.cpp \
+ render/RenderHelper.cpp \
+ render/AudioTrack.cpp \
+ render/AudioRenderer.cpp \
+ render/GlesProgram.cpp \
+ base/Log.cpp \
+ base/FrameSource.cpp \
+ base/MediaData.cpp \
+ base/MessageSource.cpp \
+ base/MessageHelper.cpp \
+ base/LoopThread.cpp \
+ base/XThread.cpp \
+ base/XTick.c \
+ base/cJSON.c \
+ base/dh_mem.c \
+ digit/grtcfg.c \
+ base/LoopThreadHelper.cpp \
+ )
+
+LOCAL_ARM_NEON := true
+LOCAL_MODULE := facedetect
+LOCAL_LDLIBS += -llog -ldl -lm -lmediandk
+LOCAL_LDLIBS += -lEGL -lGLESv2 -landroid
+LOCAL_LDLIBS += -ljnigraphics -fopenmp
+
+LOCAL_CFLAGS += -fpermissive
+LOCAL_CPPFLAGS += -fpermissive
+#LOCAL_CFLAGS += -ftree-vectorizer-verbose=2
+LOCAL_CPPFLAGS += -std=c++17
+LOCAL_LDLIBS += -lstdc++
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)
+LOCAL_C_INCLUDES += include
+LOCAL_C_INCLUDES += base
+LOCAL_C_INCLUDES += aisdk
+LOCAL_C_INCLUDES += digit
+LOCAL_C_INCLUDES += render
+LOCAL_C_INCLUDES += android
+LOCAL_C_INCLUDES += third/arm/include
+LOCAL_C_INCLUDES += third/arm/include/ncnn
+LOCAL_C_INCLUDES += third/opencv-mobile-4.6.0-android/sdk/native/jni/include/
+LOCAL_C_INCLUDES += third/ncnn-20221128-android-vulkan-shared/arm64-v8a/include/ncnn
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/CMakeLists.txt b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..199c716d6b0534229b1412368fd6aa63c6ca88ef
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,169 @@
+project(scrfdncnn)
+
+cmake_minimum_required(VERSION 3.10.2)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -funwind-tables")
+
+set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/third/opencv-mobile-4.6.0-android/sdk/native/jni)
+find_package(OpenCV REQUIRED core imgproc highgui)
+
+#set(ncnn_DIR ${CMAKE_SOURCE_DIR}/third/ncnn-20221128-android-vulkan-shared/${ANDROID_ABI}/lib/cmake/ncnn)
+set(ncnn_DIR ${CMAKE_SOURCE_DIR}/third/ncnn-20231027-android-shared/${ANDROID_ABI}/lib/cmake/ncnn)
+find_package(ncnn REQUIRED)
+
+
+option(USE_OPENCV "shared library support" TRUE)
+option(USE_NCNN "shared library support" TRUE)
+
+include_directories(
+ include
+ base
+ render
+ aisdk
+ aes
+ digit
+ android
+ third/arm/include
+ third/arm/include/turbojpeg
+ )
+
+add_library(scrfdncnn SHARED
+ android/DigitJni.cpp
+ android/MsgcbJni.cpp
+ android/JniHelper.cpp
+ aisdk/jmat.cpp
+ aisdk/wavreader.cpp
+ aisdk/wenet.cpp
+ aisdk/aimodel.cpp
+ aisdk/scrfd.cpp
+ aisdk/pfpld.cpp
+ aisdk/munet.cpp
+ aisdk/malpha.cpp
+ aisdk/wavcache.cpp
+ aisdk/blendgram.cpp
+ aisdk/face_utils.cpp
+ aisdk/netwav.cpp
+ digit/looper.cpp
+ digit/netcurl.cpp
+ digit/GRender.cpp
+ digit/GDigit.cpp
+ digit/dispatchqueue.cpp
+ render/EglRenderer.cpp
+ render/RgbVideoRenderer.cpp
+ render/SurfaceVideoRenderer.cpp
+ render/RenderHelper.cpp
+ base/BaseRenderHelper.cpp
+ base/AudioTrack.cpp
+ render/AudioRenderer.cpp
+ render/GlesProgram.cpp
+ base/Log.cpp
+ base/FrameSource.cpp
+ base/MediaData.cpp
+ base/MessageSource.cpp
+ base/MessageHelper.cpp
+ base/LoopThread.cpp
+ base/XThread.cpp
+ base/XTick.c
+ base/cJSON.c
+ base/dh_mem.c
+ digit/grtcfg.c
+ base/LoopThreadHelper.cpp
+ base/coffeecatch.c
+ aes/aes_cbc.c aes/aes_core.c aes/aes_ecb.c aes/base64.c aes/cbc128.c aes/gj_aes.c
+ aes/aesmain.c
+ )
+
+
+add_library(turbojpeg STATIC IMPORTED)
+set_target_properties(turbojpeg
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libturbojpeg.a)
+
+add_library(libjpeg STATIC IMPORTED)
+set_target_properties(libjpeg
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libjpeg.a)
+
+ #add_library(pplcommon STATIC IMPORTED)
+#set_target_properties(pplcommon
+ # PROPERTIES IMPORTED_LOCATION
+ # ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libpplcommon_static.a)
+
+ #add_library(pplcv STATIC IMPORTED)
+#set_target_properties(pplcv
+ # PROPERTIES IMPORTED_LOCATION
+ # ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libpplcv_static.a)
+
+add_library(curl STATIC IMPORTED)
+set_target_properties(curl
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libcurl.a)
+
+add_library(ssl STATIC IMPORTED)
+set_target_properties(ssl
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libssl.a)
+
+add_library(crypto STATIC IMPORTED)
+set_target_properties(crypto
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libcrypto.a)
+
+add_library(avcodec STATIC IMPORTED)
+set_target_properties(avcodec
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/ffmpeg-lite/libavcodec.a)
+
+add_library(avformat STATIC IMPORTED)
+set_target_properties(avformat
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/ffmpeg-lite/libavformat.a)
+
+add_library(avutil STATIC IMPORTED)
+set_target_properties(avutil
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/ffmpeg-lite/libavutil.a)
+
+add_library(swresample STATIC IMPORTED)
+set_target_properties(swresample
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/ffmpeg-lite/libswresample.a)
+
+add_library(swscale STATIC IMPORTED)
+set_target_properties(swscale
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/ffmpeg-lite/libswscale.a)
+
+find_library(log-lib log)
+
+add_library(onnx-lib SHARED IMPORTED)
+set_target_properties(
+ onnx-lib
+ PROPERTIES IMPORTED_LOCATION
+ ${CMAKE_SOURCE_DIR}/third/arm/${ANDROID_ABI}/libonnxruntime.so)
+
+target_link_libraries(scrfdncnn
+ ncnn
+ ${OpenCV_LIBS}
+ ${log-lib}
+ onnx-lib
+ camera2ndk
+ mediandk
+ libjpeg
+ turbojpeg
+ avformat
+ avcodec
+ avutil
+ swresample
+ swscale
+ curl
+ ssl
+ crypto
+ -landroid
+ -lmediandk
+ -lEGL
+ -lGLESv2
+ -lm -lz
+)
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes.h
new file mode 100644
index 0000000000000000000000000000000000000000..854538ee0a1a75aa55ee5d385d9863048053f134
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes.h
@@ -0,0 +1,41 @@
+
+
+#ifndef HEADER_AES_H
+# define HEADER_AES_H
+
+# include
+
+# define AES_ENCRYPT 1
+# define AES_DECRYPT 0
+
+# define AES_MAXNR 14
+# define AES_BLOCK_SIZE 16
+
+struct aes_key_st {
+# ifdef AES_LONG
+ unsigned long rd_key[4 * (AES_MAXNR + 1)];
+# else
+ unsigned int rd_key[4 * (AES_MAXNR + 1)];
+# endif
+ int rounds;
+};
+
+typedef struct aes_key_st AES_KEY;
+
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+
+void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);
+void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key);
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key,
+ const int enc);
+
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+
+#endif
+
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_cbc.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_cbc.c
new file mode 100644
index 0000000000000000000000000000000000000000..3925bb1a0a987d7db7dbf59a3959ab74ef715a11
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_cbc.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "aes.h"
+#include "modes.h"
+
+void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec, const int enc)
+{
+
+ if (enc)
+ CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
+ (block128_f) AES_encrypt);
+ else
+ CRYPTO_cbc128_decrypt(in, out, len, key, ivec, (block128_f) AES_decrypt);
+}
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_core.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..58013093f0d97ce028156d3b6c41cd27882f94f5
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_core.c
@@ -0,0 +1,1127 @@
+#include
+
+#include "aes.h"
+#include "aes_locl.h"
+
+
+
+/*-
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01];
+*/
+
+static const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+static const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u8 Td4[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+static const u32 rcon[] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ */
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key)
+{
+
+ u32 *rk;
+ int i = 0;
+ u32 temp;
+
+ if (!userKey || !key)
+ return -1;
+ if (bits != 128 && bits != 192 && bits != 256)
+ return -2;
+
+ rk = key->rd_key;
+
+ if (bits == 128)
+ key->rounds = 10;
+ else if (bits == 192)
+ key->rounds = 12;
+ else
+ key->rounds = 14;
+
+ rk[0] = GETU32(userKey );
+ rk[1] = GETU32(userKey + 4);
+ rk[2] = GETU32(userKey + 8);
+ rk[3] = GETU32(userKey + 12);
+ if (bits == 128) {
+ while (1) {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te0[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te1[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10) {
+ return 0;
+ }
+ rk += 4;
+ }
+ }
+ rk[4] = GETU32(userKey + 16);
+ rk[5] = GETU32(userKey + 20);
+ if (bits == 192) {
+ while (1) {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te0[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te1[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8) {
+ return 0;
+ }
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ }
+ rk[6] = GETU32(userKey + 24);
+ rk[7] = GETU32(userKey + 28);
+ if (bits == 256) {
+ while (1) {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te0[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te1[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7) {
+ return 0;
+ }
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te2[(temp >> 24) ] & 0xff000000) ^
+ (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^
+ (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^
+ (Te1[(temp ) & 0xff] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+
+ rk += 8;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ */
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key)
+{
+
+ u32 *rk;
+ int i, j, status;
+ u32 temp;
+
+ /* first, start with an encryption schedule */
+ status = AES_set_encrypt_key(userKey, bits, key);
+ if (status < 0)
+ return status;
+
+ rk = key->rd_key;
+
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ for (i = 1; i < (key->rounds); i++) {
+ rk += 4;
+ rk[0] =
+ Td0[Te1[(rk[0] >> 24) ] & 0xff] ^
+ Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^
+ Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^
+ Td3[Te1[(rk[0] ) & 0xff] & 0xff];
+ rk[1] =
+ Td0[Te1[(rk[1] >> 24) ] & 0xff] ^
+ Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^
+ Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^
+ Td3[Te1[(rk[1] ) & 0xff] & 0xff];
+ rk[2] =
+ Td0[Te1[(rk[2] >> 24) ] & 0xff] ^
+ Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^
+ Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^
+ Td3[Te1[(rk[2] ) & 0xff] & 0xff];
+ rk[3] =
+ Td0[Te1[(rk[3] >> 24) ] & 0xff] ^
+ Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^
+ Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^
+ Td3[Te1[(rk[3] ) & 0xff] & 0xff];
+ }
+ return 0;
+}
+
+/*
+ * Encrypt a single block
+ * in and out can overlap
+ */
+void AES_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key) {
+
+ const u32 *rk;
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ assert(in && out && key);
+ rk = key->rd_key;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(in ) ^ rk[0];
+ s1 = GETU32(in + 4) ^ rk[1];
+ s2 = GETU32(in + 8) ^ rk[2];
+ s3 = GETU32(in + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+ if (key->rounds > 10) {
+ /* round 10: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+ if (key->rounds > 12) {
+ /* round 12: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+ }
+ }
+ rk += key->rounds << 2;
+#else /* !FULL_UNROLL */
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = key->rounds >> 1;
+ for (;;) {
+ t0 =
+ Te0[(s0 >> 24) ] ^
+ Te1[(s1 >> 16) & 0xff] ^
+ Te2[(s2 >> 8) & 0xff] ^
+ Te3[(s3 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Te0[(s1 >> 24) ] ^
+ Te1[(s2 >> 16) & 0xff] ^
+ Te2[(s3 >> 8) & 0xff] ^
+ Te3[(s0 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Te0[(s2 >> 24) ] ^
+ Te1[(s3 >> 16) & 0xff] ^
+ Te2[(s0 >> 8) & 0xff] ^
+ Te3[(s1 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Te0[(s3 >> 24) ] ^
+ Te1[(s0 >> 16) & 0xff] ^
+ Te2[(s1 >> 8) & 0xff] ^
+ Te3[(s2 ) & 0xff] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Te0[(t0 >> 24) ] ^
+ Te1[(t1 >> 16) & 0xff] ^
+ Te2[(t2 >> 8) & 0xff] ^
+ Te3[(t3 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Te0[(t1 >> 24) ] ^
+ Te1[(t2 >> 16) & 0xff] ^
+ Te2[(t3 >> 8) & 0xff] ^
+ Te3[(t0 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Te0[(t2 >> 24) ] ^
+ Te1[(t3 >> 16) & 0xff] ^
+ Te2[(t0 >> 8) & 0xff] ^
+ Te3[(t1 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Te0[(t3 >> 24) ] ^
+ Te1[(t0 >> 16) & 0xff] ^
+ Te2[(t1 >> 8) & 0xff] ^
+ Te3[(t2 ) & 0xff] ^
+ rk[3];
+ }
+#endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Te2[(t0 >> 24) ] & 0xff000000) ^
+ (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te1[(t3 ) & 0xff] & 0x000000ff) ^
+ rk[0];
+ PUTU32(out , s0);
+ s1 =
+ (Te2[(t1 >> 24) ] & 0xff000000) ^
+ (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te1[(t0 ) & 0xff] & 0x000000ff) ^
+ rk[1];
+ PUTU32(out + 4, s1);
+ s2 =
+ (Te2[(t2 >> 24) ] & 0xff000000) ^
+ (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te1[(t1 ) & 0xff] & 0x000000ff) ^
+ rk[2];
+ PUTU32(out + 8, s2);
+ s3 =
+ (Te2[(t3 >> 24) ] & 0xff000000) ^
+ (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te1[(t2 ) & 0xff] & 0x000000ff) ^
+ rk[3];
+ PUTU32(out + 12, s3);
+}
+
+/*
+ * Decrypt a single block
+ * in and out can overlap
+ */
+void AES_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key)
+{
+
+ const u32 *rk;
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+ int r;
+#endif /* ?FULL_UNROLL */
+
+ assert(in && out && key);
+ rk = key->rd_key;
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(in ) ^ rk[0];
+ s1 = GETU32(in + 4) ^ rk[1];
+ s2 = GETU32(in + 8) ^ rk[2];
+ s3 = GETU32(in + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+ if (key->rounds > 10) {
+ /* round 10: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+ if (key->rounds > 12) {
+ /* round 12: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+ }
+ }
+ rk += key->rounds << 2;
+#else /* !FULL_UNROLL */
+ /*
+ * Nr - 1 full rounds:
+ */
+ r = key->rounds >> 1;
+ for (;;) {
+ t0 =
+ Td0[(s0 >> 24) ] ^
+ Td1[(s3 >> 16) & 0xff] ^
+ Td2[(s2 >> 8) & 0xff] ^
+ Td3[(s1 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Td0[(s1 >> 24) ] ^
+ Td1[(s0 >> 16) & 0xff] ^
+ Td2[(s3 >> 8) & 0xff] ^
+ Td3[(s2 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Td0[(s2 >> 24) ] ^
+ Td1[(s1 >> 16) & 0xff] ^
+ Td2[(s0 >> 8) & 0xff] ^
+ Td3[(s3 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Td0[(s3 >> 24) ] ^
+ Td1[(s2 >> 16) & 0xff] ^
+ Td2[(s1 >> 8) & 0xff] ^
+ Td3[(s0 ) & 0xff] ^
+ rk[7];
+
+ rk += 8;
+ if (--r == 0) {
+ break;
+ }
+
+ s0 =
+ Td0[(t0 >> 24) ] ^
+ Td1[(t3 >> 16) & 0xff] ^
+ Td2[(t2 >> 8) & 0xff] ^
+ Td3[(t1 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Td0[(t1 >> 24) ] ^
+ Td1[(t0 >> 16) & 0xff] ^
+ Td2[(t3 >> 8) & 0xff] ^
+ Td3[(t2 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Td0[(t2 >> 24) ] ^
+ Td1[(t1 >> 16) & 0xff] ^
+ Td2[(t0 >> 8) & 0xff] ^
+ Td3[(t3 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Td0[(t3 >> 24) ] ^
+ Td1[(t2 >> 16) & 0xff] ^
+ Td2[(t1 >> 8) & 0xff] ^
+ Td3[(t0 ) & 0xff] ^
+ rk[3];
+ }
+#endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ ((u32)Td4[(t0 >> 24) ] << 24) ^
+ ((u32)Td4[(t3 >> 16) & 0xff] << 16) ^
+ ((u32)Td4[(t2 >> 8) & 0xff] << 8) ^
+ ((u32)Td4[(t1 ) & 0xff]) ^
+ rk[0];
+ PUTU32(out , s0);
+ s1 =
+ ((u32)Td4[(t1 >> 24) ] << 24) ^
+ ((u32)Td4[(t0 >> 16) & 0xff] << 16) ^
+ ((u32)Td4[(t3 >> 8) & 0xff] << 8) ^
+ ((u32)Td4[(t2 ) & 0xff]) ^
+ rk[1];
+ PUTU32(out + 4, s1);
+ s2 =
+ ((u32)Td4[(t2 >> 24) ] << 24) ^
+ ((u32)Td4[(t1 >> 16) & 0xff] << 16) ^
+ ((u32)Td4[(t0 >> 8) & 0xff] << 8) ^
+ ((u32)Td4[(t3 ) & 0xff]) ^
+ rk[2];
+ PUTU32(out + 8, s2);
+ s3 =
+ ((u32)Td4[(t3 >> 24) ] << 24) ^
+ ((u32)Td4[(t2 >> 16) & 0xff] << 16) ^
+ ((u32)Td4[(t1 >> 8) & 0xff] << 8) ^
+ ((u32)Td4[(t0 ) & 0xff]) ^
+ rk[3];
+ PUTU32(out + 12, s3);
+}
+
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_ecb.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_ecb.c
new file mode 100644
index 0000000000000000000000000000000000000000..647680319917cb2d93c29afe7af89b9f22638d0c
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_ecb.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include
+
+#include "aes.h"
+#include "aes_locl.h"
+
+void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key, const int enc)
+{
+ assert(in && out && key);
+ assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
+
+ if (AES_ENCRYPT == enc)
+ AES_encrypt(in, out, key);
+ else
+ AES_decrypt(in, out, key);
+}
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_locl.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_locl.h
new file mode 100644
index 0000000000000000000000000000000000000000..47d1dfa5a5bfbe383b8e6168667f73c362fec2e1
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aes_locl.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_AES_LOCL_H
+# define HEADER_AES_LOCL_H
+
+//# include
+# include
+# include
+# include
+
+# if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
+# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+# define GETU32(p) SWAP(*((u32 *)(p)))
+# define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+# else
+# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
+# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
+# endif
+
+# ifdef AES_LONG
+typedef unsigned long u32;
+# else
+typedef unsigned int u32;
+# endif
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+# define MAXKC (256/32)
+# define MAXKB (256/8)
+# define MAXNR 14
+
+/* This controls loop-unrolling in aes_core.c */
+# undef FULL_UNROLL
+
+#endif /* !HEADER_AES_LOCL_H */
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.c
new file mode 100644
index 0000000000000000000000000000000000000000..547eaf55e069a0950832d639acda43672d88a2fc
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.c
@@ -0,0 +1,111 @@
+#include
+#include
+#include
+#include
+#include "gj_aes.h"
+#include "aesmain.h"
+
+int mainenc(int enc,char* infn,char* outfn){
+ char result[255] ;
+ memset(result,0,255);
+ char* key = "yymrjzbwyrbjszrk";
+ char* aiv = "yymrjzbwyrbjszrk";
+ int base64 = 1;
+ int outlen = 0;
+ int encrst = 0;
+ char* fn1 = infn;
+ char* fn2 = outfn;
+ FILE* fr = fopen(fn1,"rb");
+ FILE* fw = fopen(fn2,"wb");
+ while(1){
+ if(!fr){
+ encrst = -1001;
+ break;
+ }
+ if(!fw){
+ encrst = -1002;
+ break;
+ }
+ gj_aesc_t* aesc = NULL;
+ init_aesc(key,aiv,enc,&aesc);
+ uint64_t size = 0;
+ uint64_t realsize = 0;
+ if(enc){
+ fwrite("gjdigits",1,8,fw);
+ fwrite(&size,1,8,fw);
+ fwrite(&size,1,8,fw);
+ fwrite(&size,1,8,fw);
+
+ while(!feof(fr)){
+ char data[16];
+ memset(data,0,16);
+ uint64_t rst = fread(data,1,16,fr);
+ if(rst){
+ size +=rst;
+ do_aesc(aesc,data,16,result,&outlen);
+ fwrite(result,1,outlen,fw);
+ }
+ }
+ fseek(fw,8,0);
+ fwrite(&size,1,8,fw);
+
+ }else{
+ uint64_t rst = fread(result,1,32,fr);
+ if(!rst){
+ encrst = -1003;
+ break;
+ }
+ if((result[0]!='g')||(result[1]!='j')){
+ encrst = -1004;
+ break;
+ }
+ uint64_t *psize = (uint64_t*)(result+8);
+ realsize = *psize;
+ if(realsize>1034*1024*1024){
+ encrst = -1005;
+ break;
+ }
+ while(!feof(fr)){
+ char data[16];
+ memset(data,0,16);
+ uint64_t rst = fread(data,1,16,fr);
+ if(rst){
+ size +=rst;
+ do_aesc(aesc,data,16,result,&outlen);
+ if(size>realsize){
+ outlen -= (size-realsize);
+ //printf("===%lu > %lu rst %lu %d outlen \n",size,realsize,rst,outlen);
+ }
+ fwrite(result,1,outlen,fw);
+ }
+ }
+ }
+ break;
+ }
+ if(fr) fclose(fr);
+ if(fw) fclose(fw);
+ return encrst;
+}
+
+
+#ifdef TEST
+int main(int argc,char** argv){
+ if(argc<4){
+ printf("gaes enc|dec filein fileout\n");
+ return 0;
+ }
+ char k = argv[1][0];
+ if(k=='e'){
+ int rst = mainenc(1,argv[2],argv[3]);
+ printf("====enc %s to %s rst %d\n",argv[2],argv[3],rst);
+ return rst;
+ }else if(k=='d'){
+ int rst = mainenc(0,argv[2],argv[3]);
+ printf("====dec %s to %s rst %d\n",argv[2],argv[3],rst);
+ return rst;
+ }else{
+ printf("gaes enc|dec filein fileout\n");
+ return 0;
+ }
+}
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.h
new file mode 100644
index 0000000000000000000000000000000000000000..48e53df4c4e8064ee0cbdf9855d2f997a880735b
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/aesmain.h
@@ -0,0 +1,16 @@
+
+#ifndef __AESMAIN_H
+#define __AESMAIN_H
+
+#include "gj_dll.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int mainenc(int enc,char* infn,char* outfn);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.c
new file mode 100644
index 0000000000000000000000000000000000000000..a35725db44df58fae410837dc33bb2561c2f68e2
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.c
@@ -0,0 +1,164 @@
+/* This is a public domain base64 implementation written by WEI Zhicheng. */
+
+#include "base64.h"
+
+#define BASE64_PAD '='
+#define BASE64DE_FIRST '+'
+#define BASE64DE_LAST 'z'
+
+/* BASE 64 encode table */
+static const char base64en[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/',
+};
+
+/* ASCII order for BASE 64 decode, 255 in unused character */
+static const unsigned char base64de[] = {
+ /* nul, soh, stx, etx, eot, enq, ack, bel, */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+
+ /* bs, ht, nl, vt, np, cr, so, si, */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+
+ /* dle, dc1, dc2, dc3, dc4, nak, syn, etb, */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+
+ /* can, em, sub, esc, fs, gs, rs, us, */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+
+ /* sp, '!', '"', '#', '$', '%', '&', ''', */
+ 255, 255, 255, 255, 255, 255, 255, 255,
+
+ /* '(', ')', '*', '+', ',', '-', '.', '/', */
+ 255, 255, 255, 62, 255, 255, 255, 63,
+
+ /* '0', '1', '2', '3', '4', '5', '6', '7', */
+ 52, 53, 54, 55, 56, 57, 58, 59,
+
+ /* '8', '9', ':', ';', '<', '=', '>', '?', */
+ 60, 61, 255, 255, 255, 255, 255, 255,
+
+ /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
+ 255, 0, 1, 2, 3, 4, 5, 6,
+
+ /* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
+ 7, 8, 9, 10, 11, 12, 13, 14,
+
+ /* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
+ 15, 16, 17, 18, 19, 20, 21, 22,
+
+ /* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
+ 23, 24, 25, 255, 255, 255, 255, 255,
+
+ /* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
+ 255, 26, 27, 28, 29, 30, 31, 32,
+
+ /* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
+ 33, 34, 35, 36, 37, 38, 39, 40,
+
+ /* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
+ 41, 42, 43, 44, 45, 46, 47, 48,
+
+ /* 'x', 'y', 'z', '{', '|', '}', '~', del, */
+ 49, 50, 51, 255, 255, 255, 255, 255
+};
+
+unsigned int
+gjbase64_encode(const unsigned char *in, unsigned int inlen, char *out)
+{
+ int s;
+ unsigned int i;
+ unsigned int j;
+ unsigned char c;
+ unsigned char l;
+
+ s = 0;
+ l = 0;
+ for (i = j = 0; i < inlen; i++) {
+ c = in[i];
+
+ switch (s) {
+ case 0:
+ s = 1;
+ out[j++] = base64en[(c >> 2) & 0x3F];
+ break;
+ case 1:
+ s = 2;
+ out[j++] = base64en[((l & 0x3) << 4) | ((c >> 4) & 0xF)];
+ break;
+ case 2:
+ s = 0;
+ out[j++] = base64en[((l & 0xF) << 2) | ((c >> 6) & 0x3)];
+ out[j++] = base64en[c & 0x3F];
+ break;
+ }
+ l = c;
+ }
+
+ switch (s) {
+ case 1:
+ out[j++] = base64en[(l & 0x3) << 4];
+ out[j++] = BASE64_PAD;
+ out[j++] = BASE64_PAD;
+ break;
+ case 2:
+ out[j++] = base64en[(l & 0xF) << 2];
+ out[j++] = BASE64_PAD;
+ break;
+ }
+
+ out[j] = 0;
+
+ return j;
+}
+
+unsigned int
+gjbase64_decode(const char *in, unsigned int inlen, unsigned char *out)
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned char c;
+
+ if (inlen & 0x3) {
+ return 0;
+ }
+
+ for (i = j = 0; i < inlen; i++) {
+ if (in[i] == BASE64_PAD) {
+ break;
+ }
+ if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST) {
+ return 0;
+ }
+
+ c = base64de[(unsigned char)in[i]];
+ if (c == 255) {
+ return 0;
+ }
+
+ switch (i & 0x3) {
+ case 0:
+ out[j] = (c << 2) & 0xFF;
+ break;
+ case 1:
+ out[j++] |= (c >> 4) & 0x3;
+ out[j] = (c & 0xF) << 4;
+ break;
+ case 2:
+ out[j++] |= (c >> 2) & 0xF;
+ out[j] = (c & 0x3) << 6;
+ break;
+ case 3:
+ out[j++] |= c;
+ break;
+ }
+ }
+
+ return j;
+}
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.h
new file mode 100644
index 0000000000000000000000000000000000000000..34ad9486bf6beae446796b083fab89b1d66bf794
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/base64.h
@@ -0,0 +1,29 @@
+#ifndef BASE64_H
+#define BASE64_H
+
+#define BASE64_ENCODE_OUT_SIZE(s) ((unsigned int)((((s) + 2) / 3) * 4 + 1))
+#define BASE64_DECODE_OUT_SIZE(s) ((unsigned int)(((s) / 4) * 3))
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*
+ * out is null-terminated encode string.
+ * return values is out length, exclusive terminating `\0'
+ */
+unsigned int
+gjbase64_encode(const unsigned char *in, unsigned int inlen, char *out);
+
+/*
+ * return values is out length
+ */
+unsigned int
+gjbase64_decode(const char *in, unsigned int inlen, unsigned char *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* BASE64_H */
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/cbc128.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/cbc128.c
new file mode 100644
index 0000000000000000000000000000000000000000..f10d9cae201a9d16295bd93c1ddc81e529b15ec6
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/cbc128.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+// #include
+#include "modes.h"
+#include
+
+#if !defined(STRICT_ALIGNMENT) && !defined(PEDANTIC)
+# define STRICT_ALIGNMENT 0
+#endif
+
+void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ unsigned char ivec[16], block128_f block)
+{
+ size_t n;
+ const unsigned char *iv = ivec;
+
+ if (len == 0)
+ return;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+ if (STRICT_ALIGNMENT &&
+ ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ while (len >= 16) {
+ for (n = 0; n < 16; ++n)
+ out[n] = in[n] ^ iv[n];
+ (*block) (out, out, key);
+ iv = out;
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ } else {
+ while (len >= 16) {
+ for (n = 0; n < 16; n += sizeof(size_t))
+ *(size_t *)(out + n) =
+ *(size_t *)(in + n) ^ *(size_t *)(iv + n);
+ (*block) (out, out, key);
+ iv = out;
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ }
+#endif
+ while (len) {
+ for (n = 0; n < 16 && n < len; ++n)
+ out[n] = in[n] ^ iv[n];
+ for (; n < 16; ++n)
+ out[n] = iv[n];
+ (*block) (out, out, key);
+ iv = out;
+ if (len <= 16)
+ break;
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ memcpy(ivec, iv, 16);
+}
+
+void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ unsigned char ivec[16], block128_f block)
+{
+ size_t n;
+ union {
+ size_t t[16 / sizeof(size_t)];
+ unsigned char c[16];
+ } tmp;
+
+ if (len == 0)
+ return;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+ if (in != out) {
+ const unsigned char *iv = ivec;
+
+ if (STRICT_ALIGNMENT &&
+ ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ while (len >= 16) {
+ (*block) (in, out, key);
+ for (n = 0; n < 16; ++n)
+ out[n] ^= iv[n];
+ iv = in;
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ } else if (16 % sizeof(size_t) == 0) { /* always true */
+ while (len >= 16) {
+ size_t *out_t = (size_t *)out, *iv_t = (size_t *)iv;
+
+ (*block) (in, out, key);
+ for (n = 0; n < 16 / sizeof(size_t); n++)
+ out_t[n] ^= iv_t[n];
+ iv = in;
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ }
+ memcpy(ivec, iv, 16);
+ } else {
+ if (STRICT_ALIGNMENT &&
+ ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+ unsigned char c;
+ while (len >= 16) {
+ (*block) (in, tmp.c, key);
+ for (n = 0; n < 16; ++n) {
+ c = in[n];
+ out[n] = tmp.c[n] ^ ivec[n];
+ ivec[n] = c;
+ }
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ } else if (16 % sizeof(size_t) == 0) { /* always true */
+ while (len >= 16) {
+ size_t c, *out_t = (size_t *)out, *ivec_t = (size_t *)ivec;
+ const size_t *in_t = (const size_t *)in;
+
+ (*block) (in, tmp.c, key);
+ for (n = 0; n < 16 / sizeof(size_t); n++) {
+ c = in_t[n];
+ out_t[n] = tmp.t[n] ^ ivec_t[n];
+ ivec_t[n] = c;
+ }
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+ }
+ }
+#endif
+ while (len) {
+ unsigned char c;
+ (*block) (in, tmp.c, key);
+ for (n = 0; n < 16 && n < len; ++n) {
+ c = in[n];
+ out[n] = tmp.c[n] ^ ivec[n];
+ ivec[n] = c;
+ }
+ if (len <= 16) {
+ for (; n < 16; ++n)
+ ivec[n] = in[n];
+ break;
+ }
+ len -= 16;
+ in += 16;
+ out += 16;
+ }
+}
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.cc b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b8812cda33071c9be0a2144de80d7ecb81c2dacd
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.cc
@@ -0,0 +1,213 @@
+
+#include "gaes_stream.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "gj_aes.h"
+
+
+class GaesIStreamBuf final: public std::streambuf
+{
+private:
+ char *m_inbuf;
+ size_t m_inbufsize;
+ bool m_owns_inbuf;
+ char *m_leftbuf;
+
+ FILE *file;
+ uint64_t cur_size;
+ uint64_t file_size;
+ gj_aesc_t* aesc ;
+protected:
+ virtual std::streambuf* setbuf(char *s, std::streamsize n){
+ setg(0, 0, 0);
+ if (m_owns_inbuf) {
+ delete [] m_inbuf;
+ }
+ m_inbufsize = n;
+ if (s) {
+ m_inbuf = s;
+ m_owns_inbuf = false;
+ } else {
+ m_inbuf = new char[m_inbufsize];
+ m_leftbuf = new char[m_inbufsize];
+ m_owns_inbuf = true;
+ }
+ return this;
+ }
+
+ virtual int sync(){
+ int result = 0;
+ return result;
+ }
+
+ virtual int underflow() override{
+ int __c = traits_type::eof();
+ if (!file) return __c;
+ if(cur_size>=file_size){
+ printf("===eof %ld ===%ld\n",cur_size,file_size);
+ return __c;
+ }
+ bool initial = false;
+ if (eback() == 0) {
+ setg(m_inbuf, m_inbuf + m_inbufsize, m_inbuf + m_inbufsize);
+ initial = true;
+ }
+ const size_t unget_sz = initial ? 0 : std::min((egptr() - eback()) / 2, 4);
+ if (gptr() == egptr()) {
+ memmove(eback(), egptr() - unget_sz, unget_sz);
+ size_t nmemb = static_cast(egptr() - eback() - unget_sz);
+ char* pdst = eback() + unget_sz;
+ int modb = nmemb % 16;
+ size_t leftb = nmemb - modb;
+ char* pbuf = m_leftbuf;
+ size_t leftf = file_size - cur_size;
+ if(leftb>leftf)leftb=leftf;
+ memset(pbuf,0,m_inbufsize);
+ size_t rd = fread(pbuf, 1, leftb, file);
+ //printf("%d-%ld-%ld----------------%ld--%ld#\n",cur_size,file_size,modb,nmemb,rd);
+ //ssize_t readed = read(m_fd, eback() + unget_sz, nmemb);
+ if(rd>0){
+ cur_size += rd;
+ int cnt = leftb /16;
+ int k;
+ for(k=0;kaesc);
+ char head[50];
+ memset(head,0,50);
+ uint64_t rst = fread(head,1,8,file);
+ rst = fread(&cur_size,1,8,file);
+ printf("===head %s size %ld\n",head,cur_size);
+ rst = fread(head,1,16,file);
+ cur_size = 32;
+ }
+
+ ~GaesIStreamBuf(){
+ close();
+ if (m_owns_inbuf) {
+ delete[] m_inbuf;
+ }
+ }
+
+ void close(){
+ if(aesc){
+ free_aesc(&this->aesc);
+ }
+ if (file){
+ fclose(file);
+ file = NULL;
+ }
+ }
+};
+
+
+
+GaesIStream::GaesIStream(std::string filename):
+ std::istream(new GaesIStreamBuf(filename)){
+}
+
+GaesIStream::~GaesIStream()
+{
+ delete rdbuf();
+}
+
+#ifdef TEST
+int maindec(int argc,char** argv){
+ std::string filename(argv[1]);// = "test.enc";
+ //std::string filename = "final.mdlenc";
+ GaesIStream fin(filename);
+ //std::string fn2 = "final.mdldec";
+ std::string fn2(argv[2]);// = "test.dec";
+ std::ofstream fout(fn2,std::ios::binary);
+
+ char buf[1024];
+ int rd = 0;
+ while(!fin.eof()){
+ //while((rd = fin.read(buf,16))>0){
+ //printf("===rd %ld\n",rd);
+ fin.read(buf,16);
+ fout.write(buf,16);
+
+ }
+ //char ch;
+ //while (fin.get(ch)) {
+ //printf("+");
+ //fout << ch;
+ //}
+ return 0;
+}
+
+
+
+int mainenc(int argc,char** argv){
+ char result[255] ;
+ memset(result,0,255);
+ char* key = "yymrjzbwyrbjszrk";
+ char* aiv = "yymrjzbwyrbjszrk";
+ int base64 = 1;
+ int outlen = 0;
+ gj_aesc_t* aesc = NULL;
+ init_aesc(key,aiv,1,&aesc);
+ char* fn1 = argv[1];
+ char* fn2 = argv[2];
+ FILE* fr = fopen(fn1,"rb");
+ FILE* fw = fopen(fn2,"wb");
+ fwrite("abcdefgh",1,8,fw);
+ uint64_t size = 0;
+ fwrite(&size,1,8,fw);
+ fwrite(&size,1,8,fw);
+ fwrite(&size,1,8,fw);
+ while(!feof(fr)){
+ char data[16];
+ memset(data,0,16);
+ uint64_t rst = fread(data,1,16,fr);
+ printf("===rst %d\n",rst);
+ if(rst){
+ size +=rst;
+ do_aesc(aesc,data,16,result,&outlen);
+ printf("===out %d\n",outlen);
+ fwrite(result,1,16,fw);
+ }
+ }
+ fseek(fw,8,0);
+ fwrite(&size,1,8,fw);
+ fclose(fr);
+ fclose(fw);
+ return 0;
+}
+
+int main(int argc,char** argv){
+ if(argc<4){
+ return mainenc(argc,argv);
+ }else{
+ return maindec(argc,argv);
+ }
+}
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3e2d1d01f7b730238a4d5743ca1163dd20d2e15
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaes_stream.h
@@ -0,0 +1,22 @@
+#ifndef COMPRESSED_STREAMS_ZSTD_STREAM_H
+#define COMPRESSED_STREAMS_ZSTD_STREAM_H
+
+#include
+
+
+
+
+
+class GaesIStream: public std::istream
+{
+public:
+ GaesIStream(std::string filename);
+
+ virtual ~GaesIStream();
+};
+
+
+
+
+
+#endif // COMPRESSED_STREAMS_ZSTD_STREAM_H
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaesmain b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaesmain
new file mode 100644
index 0000000000000000000000000000000000000000..c3cae0fd38f67f6bc71d88d564d9d3af7747fd46
Binary files /dev/null and b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gaesmain differ
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.c b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.c
new file mode 100644
index 0000000000000000000000000000000000000000..3314ef62acd90600ccac1746abc54914f9d3360f
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.c
@@ -0,0 +1,69 @@
+#include
+#include
+#include "gj_aes.h"
+#include "base64.h"
+
+#include "aes.h"
+
+
+struct gj_aesc_s{
+ char key[16];
+ char iv[16];
+ int enc;
+ AES_KEY *aeskey;
+};
+
+int free_aesc(gj_aesc_t** paesc){
+ if(!paesc||!*paesc)return -1;
+ if((*paesc)->aeskey)free((*paesc)->aeskey);
+ free(*paesc);
+ *paesc = NULL;
+ return 0;
+}
+
+
+int init_aesc(char* key,char* iv,int enc,gj_aesc_t** paesc){
+ if(strlen(key)!=16) return -1;
+ if(strlen(iv)!=16) return -2;
+ gj_aesc_t* aesc = (gj_aesc_t*)malloc(sizeof(gj_aesc_t));
+ int k;
+ for(k=0;k<16;k++){
+ aesc->key[k]=key[k];
+ aesc->iv[k]=iv[k];
+ }
+ aesc->aeskey = (AES_KEY*)malloc(sizeof(AES_KEY));
+ aesc->enc = enc;
+ if(enc){
+ AES_set_encrypt_key((const unsigned char*)aesc->key, 128, aesc->aeskey);
+ }else{
+ AES_set_decrypt_key((const unsigned char*)aesc->key, 128, aesc->aeskey);
+ }
+ *paesc = aesc;
+ return 0;
+}
+
+int do_aesc(gj_aesc_t* aesc,char* in,int inlen,char* out,int* outlen){
+ char* psrc = in;
+ char* pdest = out;
+ int cnt = 0;
+ int left=inlen;
+ while(left>0){
+ AES_cbc_encrypt((const unsigned char*)psrc,(unsigned char*)pdest,16,aesc->aeskey,(unsigned char*)aesc->iv,aesc->enc);
+ psrc += 16;
+ pdest += 16;
+ left -= 16;
+ cnt += 16;
+ }
+ *outlen = cnt;
+ return 0;
+}
+
+int do_base64(int enc,char* in,int inlen,char* out,int* outlen){
+ if(enc){
+ gjbase64_encode((unsigned char*)in,inlen,out);
+ *outlen = strlen(out);
+ }else{
+ *outlen = gjbase64_decode(in,inlen,(unsigned char*)out);
+ }
+ return 0;
+}
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.h
new file mode 100644
index 0000000000000000000000000000000000000000..a09338f9011cf4287cbec494345b9d76eec3c7f1
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_aes.h
@@ -0,0 +1,22 @@
+#ifndef __GJ_AES_H__
+#define __GJ_AES_H__
+
+#include "gj_dll.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct gj_aesc_s gj_aesc_t;
+
+GJLIBAPI int free_aesc(gj_aesc_t** paesc);
+GJLIBAPI int init_aesc(char* key,char* iv,int enc,gj_aesc_t** paesc);
+
+GJLIBAPI int do_aesc(gj_aesc_t* aesc,char* in,int inlen,char* out,int* outlen);
+
+GJLIBAPI int do_base64(int enc,char* in,int inlen,char* out,int* outlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_dll.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_dll.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d1c9536f027929a430a9be0ca2e46749656b153
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/gj_dll.h
@@ -0,0 +1,21 @@
+#ifndef __GJ_DLL_H__
+#define __GJ_DLL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define GJLIB_EXPORT 1
+#if defined(GJLIB_EXPORT)
+ #if defined _WIN32 || defined __CYGWIN__
+ #define GJLIBAPI __declspec(dllexport)
+ #else
+ #define GJLIBAPI __attribute__((visibility("default")))
+ #endif
+#else
+ #define GJLIBAPI
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/makefile b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dbe0cac9922691c427081872daadd9a808cfb328
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/makefile
@@ -0,0 +1,3 @@
+all:
+ g++ -fPIC -o gjaesmain -g aesmain.c \
+ aes_cbc.c aes_core.c aes_ecb.c cbc128.c base64.c gj_aes.c -lm --std=c++11 -I. -DTEST
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/modes.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/modes.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d2c17e0ca0fddd861e30975b3f7fa7fe9ade88f
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aes/modes.h
@@ -0,0 +1,22 @@
+#ifndef HEADER_MODES_H
+# define HEADER_MODES_H
+
+# include
+
+typedef void (*block128_f) (const unsigned char in[16],
+ unsigned char out[16], const void *key);
+
+typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ unsigned char ivec[16], int enc);
+
+void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ unsigned char ivec[16], block128_f block);
+void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const void *key,
+ unsigned char ivec[16], block128_f block);
+
+
+
+#endif
\ No newline at end of file
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aicommon.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aicommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef25518667a537dd5668a31c53fa88159670b929
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aicommon.h
@@ -0,0 +1,24 @@
+#pragma once
+
+//#define MFCC_OFFSET 6436
+#define MFCC_OFFSET 6400
+//##define MFCC_OFFSET 0
+#define MFCC_DEFRMS 0.1f
+#define MFCC_FPS 25
+#define MFCC_RATE 16000
+//#define MFCC_WAVCHUNK 960000
+#define MFCC_WAVCHUNK 560000
+//#define MFCC_WAVCHUNK 512
+
+//#define MFCC_MELBASE 6001
+#define MFCC_MELBASE 3501
+#define MFCC_MELCHUNK 80
+//#define MFCC_MELCHUNK 20
+
+//#define MFCC_BNFBASE 1499
+#define MFCC_BNFBASE 874
+#define MFCC_BNFCHUNK 256
+//input==== NodeArg(name='speech', type='tensor(float)', shape=['B', 'T', 80])
+//input==== NodeArg(name='speech_lengths', type='tensor(int32)', shape=['B'])
+//output==== NodeArg(name='encoder_out', type='tensor(float)', shape=['B', 'T_OUT', 'Addencoder_out_dim_2'])
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.cpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1ccf44987ef03123c9a8798ba42431325aa7f721
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.cpp
@@ -0,0 +1,438 @@
+#include "aimodel.h"
+#include
+#include
+
+void AiCfg::dump(){
+ int incnt = size_inputs.size();
+ int outcnt = size_outputs.size();
+ std::cout<<"======in onnx:"<=shape_inputs.size())return -1;
+ if(dim>=shape_inputs[inx].size())return -2;
+ shape_inputs[inx][dim] = val;
+ int size = 1;
+ for(int k=0;k0){
+ size_inputs[inx] = size;
+ }
+ return 0;
+}
+
+int AiCfg::outShape(int inx,int dim,int val){
+ if(inx>=shape_outputs.size())return -1;
+ if(dim>=shape_outputs[inx].size())return -2;
+ shape_outputs[inx][dim] = val;
+ int size = 1;
+ for(int k=0;k0){
+ size_outputs[inx] = size;
+ }
+ return 0;
+}
+
+AiCfg AiCfg::clone(){
+ AiCfg onecfg;
+ AiCfg* cfg = &onecfg;//new AiCfg();
+ //
+ cfg->names.assign(names.begin(),names.end());
+ cfg->kind_inputs.assign(kind_inputs.begin(),kind_inputs.end());
+ cfg->name_inputs.assign(name_inputs.begin(),name_inputs.end());
+ cfg->size_inputs.assign(size_inputs.begin(),size_inputs.end());
+ //cfg->m_sizeinput = m_sizeinput;
+ for(int k=0;k shape(shape_inputs[k]);
+ cfg->shape_inputs.push_back(shape);
+ }
+
+ cfg->kind_outputs.assign(kind_outputs.begin(),kind_outputs.end());
+ cfg->name_outputs.assign(name_outputs.begin(),name_outputs.end());
+ cfg->size_outputs.assign(size_outputs.begin(),size_outputs.end());
+ //cfg->m_sizeoutput = m_sizeoutput;
+ for(int k=0;k shape(shape_outputs[k]);
+ cfg->shape_outputs.push_back(shape);
+ }
+ return onecfg;//cfg;
+}
+
+AiModel::AiModel(){
+ m_cfg = new AiCfg();
+}
+
+AiModel::~AiModel(){
+ delete m_cfg;
+}
+
+int AiModel::doInitModel(){
+ return -1;
+}
+
+AiCfg AiModel::config(){
+ return m_cfg->clone();
+}
+
+void AiModel::dump(){
+ m_cfg->dump();
+}
+
+int AiModel::pushName(const char* name,int input){
+ std::string sname(name);
+ m_cfg->names.push_back(sname);
+ if(input){
+ m_cfg->name_inputs.push_back(m_cfg->names[m_cfg->names.size()-1].c_str());
+ }else{
+ m_cfg->name_outputs.push_back(m_cfg->names[m_cfg->names.size()-1].c_str());
+ }
+ return 0;
+}
+
+int AiModel::initModel(std::string& modelpath){
+ m_modelPath = modelpath;
+ m_inited = doInitModel();
+ printf("===init %d\n",m_inited);
+
+ return m_inited;
+}
+
+int AiModel::initModel(std::string& binfn,std::string& paramfn){
+ m_modelbin = binfn;
+ m_modelparam = paramfn;
+ m_inited = doInitModel();
+ //printf("===init %d\n",m_inited);
+
+ return m_inited;
+}
+
+int AiModel::doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg){
+ return 0;
+}
+
+
+int AiModel::runModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg){
+ if(m_inited){
+ //std::cout<<"model not inited:"< availableProviders = Ort::GetAvailableProviders();
+ //auto cudaAvailable = std::find(availableProviders.begin(), availableProviders.end(), "CUDAExecutionProvider");
+ //OrtCUDAProviderOptions cudaOption;
+
+ //if(cudaAvailable != availableProviders.end()){
+ //std::cout << "Inference device: GPU" << std::endl;
+ //sessionOptions.AppendExecutionProvider_CUDA(cudaOption);
+ //}else{
+ //std::cout << "Inference device: CPU" << std::endl;
+ //}
+
+ session = Ort::Session(env, m_modelPath.c_str(), sessionOptions);
+ //Ort::AllocatorWithDefaultOptions allocator;
+ size_t numInputNodes = session.GetInputCount();
+ size_t numOutputNodes = session.GetOutputCount();
+ //std::cout << "input NUM: " << numInputNodes << std::endl;
+ //std::cout << "Output NUM: " << numOutputNodes << std::endl;
+ for(int k=0;kname_inputs.push_back(session.GetInputName(k));//, allocator));
+ Ort::TypeInfo inputTypeInfo = session.GetInputTypeInfo(k);
+ auto tensorInfo = inputTypeInfo.GetTensorTypeAndShapeInfo();
+ auto elemType = tensorInfo.GetElementType();
+ m_cfg->kind_inputs.push_back((int)elemType);
+ std::vector inputTensorShape = tensorInfo.GetShape();
+
+ if(m_batch&&inputTensorShape.size()){
+ if(inputTensorShape[0]==-1)inputTensorShape[0]=m_batch;
+ }
+ if(m_batch&&(inputTensorShape.size()==4)){
+ if(inputTensorShape[0]==-1)inputTensorShape[0]=m_batch;
+ if(inputTensorShape[2]==-1)inputTensorShape[2]=m_height;
+ if(inputTensorShape[3]==-1)inputTensorShape[3]=m_width;
+ }
+ int size = 1;
+ for (auto shape : inputTensorShape){
+ size *= shape;
+ }
+ m_cfg->shape_inputs.push_back(inputTensorShape);
+ m_cfg->size_inputs.push_back(size);
+ }
+
+ for(int k=0;kname_outputs.push_back(session.GetOutputName(k));//, allocator));
+ Ort::TypeInfo outputTypeInfo = session.GetOutputTypeInfo(k);
+ auto tensorInfo = outputTypeInfo.GetTensorTypeAndShapeInfo();
+ auto elemType = tensorInfo.GetElementType();
+ m_cfg->kind_outputs.push_back((int)elemType);
+ std::vector outputTensorShape = tensorInfo.GetShape();
+ if(m_batch&&outputTensorShape.size()){
+ if(outputTensorShape[0]==-1)outputTensorShape[0]=m_batch;
+ }
+ if(m_batch&&(outputTensorShape.size()==4)){
+ if(outputTensorShape[0]==-1)outputTensorShape[0]=m_batch;
+ if(outputTensorShape[2]==-1)outputTensorShape[2]=m_height;
+ if(outputTensorShape[3]==-1)outputTensorShape[3]=m_width;
+ }
+ int size = 1;
+ for (auto shape : outputTensorShape){
+ size *= shape;
+ }
+ m_cfg->shape_outputs.push_back(outputTensorShape);
+ m_cfg->size_outputs.push_back(size);
+ }
+
+ return 0;
+}
+
+
+int OnnxModel::doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg){
+ AiCfg* cfg = pcfg==nullptr?m_cfg:pcfg;
+ int incnt = cfg->size_inputs.size();
+ int outcnt = cfg->size_outputs.size();
+ std::cout<<"run onnx:"< inputTensors;
+ Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu( OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault);
+ for(int k=0;ksize_inputs[k]*4 , cfg->shape_inputs[k].data(), cfg->shape_inputs[k].size(), (ONNXTensorElementDataType)cfg->kind_inputs[k] ));
+ }
+ std::vector outputTensors;
+ for(int k=0;ksize_outputs[k]*4 , cfg->shape_outputs[k].data(), cfg->shape_outputs[k].size(),(ONNXTensorElementDataType)cfg->kind_outputs[k] ));
+ }
+ this->session.Run(Ort::RunOptions{nullptr}, cfg->names_in, inputTensors.data(), incnt, cfg->names_out, outputTensors.data(),outcnt);
+ if(1)return 0;
+ /*
+ //for(int k=0;k<9;k++)dumpfloat((float*)arrout[k],10);//size_outputs[0]);
+ std::vector aoutputTensors = this->session.Run(Ort::RunOptions{nullptr}, name_inputs.data(), inputTensors.data(), 1, name_outputs.data(), 9);
+ //bool* pmsk = (bool*)aoutputTensors[1].GetTensorData();
+ for(int k=0;k<9;k++){
+ float* pbnf = (float*)aoutputTensors[0].GetTensorData();
+ memcpy(arrout[k],pbnf,size_outputs[k]*4);
+ }
+ */
+ return 0;
+}
+
+NcnnModel::NcnnModel():AiModel(){
+}
+
+NcnnModel::NcnnModel(int w,int h):AiModel(){
+ m_width = w;
+ m_height = h;
+}
+
+NcnnModel::~NcnnModel(){
+ net.clear();
+}
+
+int NcnnModel::doInitModel(){
+ net.clear();
+ net.load_param(m_modelparam.c_str());
+ net.load_model(m_modelbin.c_str());
+ return 0; //
+}
+
+int NcnnModel::doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg){
+ ncnn::Extractor ex = net.create_extractor();
+ AiCfg* cfg = pcfg==nullptr?m_cfg:pcfg;
+ int incnt = cfg->size_inputs.size();
+ int outcnt = cfg->size_outputs.size();
+ ncnn::Mat inmat[incnt];
+ for(int k=0;kname_inputs[k];
+ JMat* mat = (JMat*)arrin[k];
+ ncnn::Mat in_pack =mat->packingmat();
+ ex.input(name.c_str(), in_pack);
+ }
+ for(int k=0;kname_outputs[k];
+ JMat* mat = (JMat*)arrout[k];
+ ncnn::Mat output;
+ ex.extract(name.c_str(), output);
+ ncnn::Mat in_park;
+ ncnn::convert_packing(output,in_park,3);
+ int size = mat->width()*mat->height()*3*sizeof(float);
+ memcpy((uint8_t*)mat->data(),in_park,size);
+ }
+ return 0;
+}
+
+#ifdef _TENSORRT_
+#include "NvInferPlugin.h"
+#include "cuda_runtime_api.h"
+#include "cuda.h"
+#define FPW 4
+using namespace nvinfer1;
+
+int TrtModel::doInitModel(){
+ std::cout<<"deserialize eng !"<deserializeCudaEngine(modelMem,engSize);
+ runtime->destroy();
+ free(modelMem);
+ if(! m_engine){
+ std::cout<<"deserialize eng error!"<createExecutionContext();
+ int bindings = m_engine->getNbBindings();
+ std::cout<<"bindings!"<getBindingName(k);
+ std::string sname(name );
+ bool input = m_engine->bindingIsInput(k);
+ std::cout<<"name!"<getBindingDimensions(k);
+ auto dt = m_engine->getBindingDataType(k);
+ int tdt = dt==DataType::kFLOAT?ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT:ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32;
+ std::vector tensorShape;
+ int dsize = 1;
+ for(int i = 0 ;i < dims.nbDims; i++){
+ tensorShape.push_back(dims.d[i]);
+ dsize *= dims.d[i];
+ //cout<<"==dsize!"<kind_inputs.push_back(tdt);
+ m_cfg->shape_inputs.push_back(tensorShape);
+ m_cfg->size_inputs.push_back(size);
+ m_cfg->name_inputs.push_back(name);
+ }else{
+ m_cfg->kind_outputs.push_back(tdt);
+ m_cfg->size_outputs.push_back(size);
+ m_cfg->name_outputs.push_back(name);
+ m_cfg->shape_outputs.push_back(tensorShape);
+ }
+ }
+ //getchar();
+ /*
+ m_sizeinput = 0;
+ for(int k=0;ksize_inputs.size();k++){
+ int size = m_cfg->size_inputs[k];
+ void* input ;
+ //int flag = cudaMalloc(&input,size);
+ //m_inputs.push_back(input);
+ //m_bindings[k]=input;
+ m_sizeinput += size;
+ //printf("===input %d output %d \n",m_sizeinput,m_sizeoutput);
+ }
+ std::cout<<"bbb"<size_inputs.size();
+ for(int k=0;ksize_outputs.size();k++){
+ int size = m_cfg->size_outputs[k];
+ void* output ;
+ //int flag = cudaMalloc(&output,size);
+ //m_outputs.push_back(output);
+ //m_bindings[offset+k]=output;
+ m_sizeoutput += size;
+ //printf("===input %d output %d \n",m_sizeinput,m_sizeoutput);
+ }
+ std::cout<<"ccc"<size_inputs.size();
+ int outcnt = cfg->size_outputs.size();
+ std::cout<<"incnt:"< m_bindings(incnt+outcnt,NULL);
+ for(int k=0;ksize_inputs[k]<size_outputs[k]<enqueue(1,m_bindings.data(),(cudaStream_t)stream,nullptr);
+ return status?0:-1;
+}
+
+TrtModel::TrtModel(int b,int w,int h):AiModel(){
+}
+
+TrtModel::TrtModel():AiModel(){
+}
+
+TrtModel::~TrtModel(){
+ if(m_context){
+ m_context->destroy();
+ m_context = nullptr;
+ }
+ if(m_engine){
+ m_engine->destroy();
+ m_engine = nullptr;
+ }
+}
+
+#endif
+/*
+ int main(int argc,char** argv){
+ OnnxModel *model=new OnnxModel();
+ std::string fn = "onnx/mfcc.onnx";
+ model->initModel(fn);
+ delete model;
+ return 0;
+ }
+ */
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..1665bb68211a6ae8f7487ea2597e863c4d0abbd5
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/aimodel.h
@@ -0,0 +1,136 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include "jmat.h"
+
+struct AiCfg{
+ std::vector kind_inputs;
+ std::vector size_inputs;
+ std::vector names;
+ std::vector name_inputs;
+ //int m_sizeinput;
+ std::vector> shape_inputs;
+
+ std::vector kind_outputs;
+ std::vector size_outputs;
+ std::vector name_outputs;
+ //int m_sizeoutput;
+ std::vector> shape_outputs;
+
+ const char** names_in;
+ const char** names_out;
+ void dump();
+ int inShape(int inx,int dim,int val);
+ int outShape(int inx,int dim,int val);
+ AiCfg clone();
+};
+
+class AiModel{
+ protected:
+ int m_inited;
+ std::string m_modelPath;
+ std::string m_modelbin;
+ std::string m_modelparam;
+
+ AiCfg *m_cfg;
+
+ virtual int doInitModel();
+ virtual int doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg=nullptr);
+ public:
+ void dump();
+ AiCfg config();
+ int pushName(const char* name,int input);
+ int initModel(std::string& modelpath);
+ int initModel(std::string& binfn,std::string& paramfn);
+ int runModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg = nullptr);
+ AiModel();
+ virtual ~AiModel();
+};
+
+#define _ONNX_
+#ifdef _ONNX_
+#include "onnx/onnxruntime_cxx_api.h"
+class OnnxModel:public AiModel{
+ protected:
+ int m_batch = 0;
+ int m_width = 640;
+ int m_height = 960;
+ Ort::Env env{nullptr};
+ Ort::SessionOptions sessionOptions{nullptr};
+ Ort::Session session{nullptr};
+ int doInitModel()override;
+ int doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg=nullptr)override;
+ public:
+ OnnxModel(int b,int w,int h);
+ OnnxModel();
+ virtual ~OnnxModel();
+};
+#endif
+
+#define _NCNN_
+#ifdef _NCNN_
+#include "net.h"
+class NcnnModel:public AiModel{
+ protected:
+ int m_width = 160;
+ int m_height = 160;
+ ncnn::Net net;
+ int doInitModel()override;
+ int doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg=nullptr)override;
+ public:
+ NcnnModel(int w,int h);
+ NcnnModel();
+ virtual ~NcnnModel();
+};
+
+#endif
+
+#ifdef _TENSORRT_
+#include "NvInfer.h"
+#include "NvInferLegacyDims.h"
+#include "NvInferRuntime.h"
+class Logger:public nvinfer1::ILogger {
+ public:
+ void log(nvinfer1::ILogger::Severity severity, const char *msg) noexcept override {
+ // suppress info-level messages
+ if (severity == Severity::kINFO)
+ return;
+ switch (severity) {
+ case Severity::kINTERNAL_ERROR:
+ std::cerr << "INTERNAL_ERROR: ";
+ break;
+ case Severity::kERROR:
+ std::cerr << "ERROR: ";
+ break;
+ case Severity::kWARNING:
+ std::cerr << "WARNING: ";
+ break;
+ case Severity::kINFO:
+ std::cerr << "INFO: ";
+ break;
+ default:
+ std::cerr << "UNKNOWN: ";
+ break;
+ }
+ std::cerr << msg << std::endl;
+ }
+};
+
+class TrtModel:public AiModel{
+ protected:
+ Logger m_logger;
+ nvinfer1::IExecutionContext *m_context;
+ nvinfer1::ICudaEngine *m_engine;
+
+ int doInitModel()override;
+ int doRunModel(void** arrin,void** arrout,void* stream,AiCfg* pcfg=nullptr)override;
+ public:
+ TrtModel(int b,int w,int h);
+ TrtModel();
+ virtual ~TrtModel();
+};
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.cpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ffa62916f9c929274e977f8eab58b6c943446bb
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.cpp
@@ -0,0 +1,437 @@
+#include
+#include
+#include
+
+#include "blendgram.h"
+
+
+ void exColorBlend_Normal(uint8* T,uint8* A,uint8* B){ ColorBlend_Buffer(T,A,B,Normal); }
+ void exColorBlend_Lighten(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Lighten);}
+ void exColorBlend_Darken(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Darken);}
+ void exColorBlend_Multiply(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Multiply);}
+ void exColorBlend_Average(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Average);}
+ void exColorBlend_Add(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Add);}
+
+ void exColorBlend_Subtract(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Subtract);}
+ void exColorBlend_Difference(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Difference);}
+ void exColorBlend_Negation(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Negation);}
+ void exColorBlend_Screen(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Screen);}
+ void exColorBlend_Exclusion(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Exclusion);}
+
+ void exColorBlend_Overlay(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Overlay);}
+ void exColorBlend_SoftLight(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,SoftLight);}
+ void exColorBlend_HardLight(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,HardLight);}
+ void exColorBlend_ColorDodge(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,ColorDodge);}
+ void exColorBlend_ColorBurn(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,ColorBurn);}
+
+ void exColorBlend_LinearDodge(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,LinearDodge);}
+ void exColorBlend_LinearBurn(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,LinearBurn);}
+ void exColorBlend_LinearLight(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,LinearLight);}
+ void exColorBlend_VividLight(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,VividLight);}
+ void exColorBlend_PinLight(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,PinLight);}
+
+ void exColorBlend_HardMix(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,HardMix);}
+ void exColorBlend_Reflect(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Reflect);}
+ void exColorBlend_Glow(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Glow);}
+ void exColorBlend_Phoenix(uint8* T,uint8* A,uint8* B) { ColorBlend_Buffer(T,A,B,Phoenix);}
+
+typedef void (*BlendFunc) (uint8* T,uint8* A,uint8* B);
+static int MAX_FUNC = 25;
+static BlendFunc blendfuncs[25]={
+ &exColorBlend_Normal,
+ &exColorBlend_Lighten,
+ &exColorBlend_Darken,
+ &exColorBlend_Multiply,
+ &exColorBlend_Average,
+ &exColorBlend_Add,
+
+ &exColorBlend_Subtract,
+ &exColorBlend_Difference,
+ &exColorBlend_Negation,
+ &exColorBlend_Screen,
+ &exColorBlend_Exclusion,
+
+ &exColorBlend_Overlay,
+ &exColorBlend_SoftLight,
+ &exColorBlend_HardLight,
+ &exColorBlend_ColorDodge,
+ &exColorBlend_ColorBurn,
+
+ &exColorBlend_LinearDodge,
+ &exColorBlend_LinearBurn,
+ &exColorBlend_LinearLight,
+ &exColorBlend_VividLight,
+ &exColorBlend_PinLight,
+
+ &exColorBlend_HardMix,
+ &exColorBlend_Reflect,
+ &exColorBlend_Glow,
+ &exColorBlend_Phoenix
+};
+
+void BlendGramSimp(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height, int Mode)
+{
+ if(Mode<1)return;
+ if(Mode>=MAX_FUNC)return;
+ BlendFunc func=blendfuncs[Mode];
+ unsigned char *LinePS, *LinePD,*LinePM;
+ for (int Y = 0; Y < Height; Y += 1)
+ {
+ LinePS = Src + Y * Width * 4;
+ LinePM = Mask + Y * Width * 4;
+ LinePD = Dest + Y * Width * 4;
+ for (int X = 0; X < Width; X += 1)
+ {
+ func(LinePD,LinePS,LinePM);
+ LinePS += 4;
+ LinePM += 4;
+ LinePD += 4;
+ }
+ }
+}
+
+void BlendGramAlpha3(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height)
+{
+ printf("w %d h %d\n",Width,Height);
+ unsigned char *LinePS, *LinePD,*LinePM;
+ for (int Y = 0; Y < Height; Y += 1)
+ {
+ LinePS = Src + Y * Width * 3;
+ LinePM = Mask + Y * Width * 3;
+ LinePD = Dest + Y * Width * 3;
+ for (int X = 0; X < Width; X += 1)
+ {
+ //func(LinePD,LinePS,LinePM);
+ //ColorBlend_Alpha(LinePD,LinePD,LinePS,*LinePM);
+ float alpha = *LinePM/255.0f;
+ float beta = 1.0f-alpha;
+ //if(beta<0.5f) printf("==alpha %f beta %f\n",alpha,beta);
+ //if(beta<0.5f) printf("od %u ps %u\n",LinePD[0],LinePS[0]);
+ LinePD[0] = CLAMPCOLOR( LinePD[0]*alpha+LinePS[0]*beta);
+ //if(beta<0.5f) printf("new %u ps%u \n",LinePD[0],LinePS[0]);
+ //if(beta<0.5f) getchar();
+ LinePD[1] = CLAMPCOLOR(LinePD[1]*alpha+LinePS[1]*beta);
+ LinePD[2] = CLAMPCOLOR( LinePD[2]*alpha+LinePS[2]*beta);
+ LinePS += 3;
+ LinePM += 3;
+ LinePD += 3;
+ }
+ }
+}
+
+void BlendGramAlpha(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height)
+{
+ unsigned char *LinePS, *LinePD,*LinePM;
+ for (int Y = 0; Y < Height; Y += 1)
+ {
+ LinePS = Src + Y * Width * 3;
+ LinePM = Mask + Y * Width * 1;
+ LinePD = Dest + Y * Width * 3;
+ for (int X = 0; X < Width; X += 1)
+ {
+ //func(LinePD,LinePS,LinePM);
+ ColorBlend_Alpha(LinePD,LinePD,LinePS,*LinePM);
+ /*
+ float alpha = *LinePM/255.0f;
+ float beta = 1.0f-alpha;
+ //printf("==alpha %f beta %f\n",alpha,beta);
+ LinePD[0] = LinePD[0]*alpha+LinePS[0]*beta;
+ LinePD[1] = LinePD[1]*alpha+LinePS[1]*beta;
+ LinePD[2] = LinePD[2]*alpha+LinePS[2]*beta;
+ */
+ LinePS += 3;
+ LinePM += 1;
+ LinePD += 3;
+ }
+ }
+}
+
+void BlendGramAlphaRev(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height)
+{
+ unsigned char *LinePS, *LinePD,*LinePM;
+ for (int Y = 0; Y < Height; Y += 1)
+ {
+ LinePS = Src + Y * Width * 3;
+ LinePM = Mask + Y * Width * 1;
+ LinePD = Dest + Y * Width * 3;
+ for (int X = 0; X < Width; X += 1)
+ {
+ //func(LinePD,LinePS,LinePM);
+ ColorBlend_Alpha(LinePD,LinePS,LinePD,*LinePM);
+ LinePS += 3;
+ LinePM += 1;
+ LinePD += 3;
+ }
+ }
+}
+
+
+
+
+/*
+void BlendGram(CBitmap* image,CBitmap* mask,int mode)
+{
+ if(mode<1)return;
+ if(mode>=MAX_FUNC)return;
+ BlendFunc func=blendfuncs[mode];
+ int Stride=image->width*4;
+ unsigned char *LinePS, *LinePD,*LinePM;
+ for (int Y = 0; Y < image->height; Y += 1)
+ {
+ LinePS = (unsigned char*)image->pixels +image->stride*Y;
+ LinePM = (unsigned char*)mask->pixels + mask->stride*Y;
+ LinePD = (unsigned char*)image->pixels +image->stride*Y;
+ for (int X = 0; X < image->width; X += 1)
+ {
+ func(LinePD,LinePS,LinePM);
+ LinePS += 4;
+ LinePM += 4;
+ LinePD += 4;
+ }
+ }
+}
+
+void BlendImageAdjustWithMask(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int mode)
+{
+ unsigned char* bmppixels=(unsigned char*)bmp->pixels;
+ unsigned char* mskpixels=(unsigned char*)msk->pixels;
+ unsigned char* dstpixels=(unsigned char*)dst->pixels;
+ unsigned char* adjpixels=(unsigned char*)adj->pixels;
+ int stride=bmp->stride;
+ int width=bmp->width;
+ int height=bmp->height;
+ int X,Y;
+ unsigned char* LinePS , * LinePM , * LinePD , * LinePA ;
+ #pragma omp parallel for private(LinePS,LinePM,LinePD,LinePA,X,Y)
+ for (Y = 0; Y < height; Y ++)
+ {
+ int offset=stride*Y;
+ LinePS = bmppixels +offset;
+ LinePM = mskpixels +offset;
+ LinePD = dstpixels +offset;
+ LinePA = adjpixels +offset;
+ for (X = 0; X < width; X ++)
+ {
+ unsigned char M=*LinePM;
+ if(M==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else if(M==0x00){
+ LinePD[0]=LinePA[0];
+ LinePD[1]=LinePA[1];
+ LinePD[2]=LinePA[2];
+ }else{
+ ColorBlend_Alpha(LinePD,LinePS,LinePA,M);
+ }
+ LinePD[3]=LinePS[3];
+ LinePS += 4; LinePM += 4; LinePD += 4; LinePA += 4;
+ }
+ }
+}
+
+
+void BlendImageAdjustWithMaskEx(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int mode)
+{
+ unsigned char* bmppixels=(unsigned char*)bmp->pixels;
+ unsigned char* mskpixels=(unsigned char*)msk->pixels;
+ unsigned char* dstpixels=(unsigned char*)dst->pixels;
+ unsigned char* adjpixels=(unsigned char*)adj->pixels;
+ int stride=bmp->stride;
+ int width=bmp->width;
+ int height=bmp->height;
+ int X,Y;
+ unsigned char* LinePS , * LinePM , * LinePD , * LinePA ;
+ #pragma omp parallel for private(LinePS,LinePM,LinePD,LinePA,X,Y)
+ for (Y = 0; Y < height; Y ++)
+ {
+ int offset=stride*Y;
+ LinePS = bmppixels +offset;
+ LinePM = mskpixels +offset;
+ LinePD = dstpixels +offset;
+ LinePA = adjpixels +offset;
+ for (X = 0; X < width; X ++)
+ {
+ unsigned char M=*LinePM;
+ if(M==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else if(M==0x00){
+ LinePD[0]=LinePA[0];
+ LinePD[1]=LinePA[1];
+ LinePD[2]=LinePA[2];
+ }else{
+ //ColorBlend_Alpha(LinePD,LinePS,LinePA,M);
+ LinePD[0]=LinePS[0]*M>>8;
+ LinePD[1]=LinePS[1]*M>>8;
+ LinePD[2]=LinePS[2]*M>>8;
+ }
+ LinePD[3]=M;
+ LinePS += 4; LinePM += 4; LinePD += 4; LinePA += 4;
+ }
+ }
+}
+
+
+
+
+void BlendImageAdjustWithAlpha(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,int alpha,int mode){
+ unsigned char* bmppixels=(unsigned char*)bmp->pixels;
+ unsigned char* dstpixels=(unsigned char*)dst->pixels;
+ unsigned char* adjpixels=(unsigned char*)adj->pixels;
+ int stride=bmp->stride;
+ int width=bmp->width;
+ int height=bmp->height;
+ int X,Y;
+ unsigned char M=CLAMPCOLOR(alpha);
+ unsigned char *LinePS , *LinePD , *LinePA ;
+ #pragma omp parallel for private(LinePS,LinePD,LinePA,X,Y)
+ for (Y = 0; Y < height; Y ++)
+ {
+ int offset=stride*Y;
+ LinePS = bmppixels +offset;
+ LinePD = dstpixels +offset;
+ LinePA = adjpixels +offset;
+ for (X = 0; X < width; X ++)
+ {
+ if(M==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else if(M==0x00){
+ LinePD[0]=LinePA[0];
+ LinePD[1]=LinePA[1];
+ LinePD[2]=LinePA[2];
+ }else{
+ ColorBlend_Alpha(LinePD,LinePS,LinePA,M);
+ }
+ LinePD[3]=LinePS[3];
+ LinePS += 4; LinePD += 4; LinePA += 4;
+ }
+ }
+}
+
+void BlendImageAdjustWithAlphaMask(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int alpha,int mode){
+ unsigned char* bmppixels=(unsigned char*)bmp->pixels;
+ unsigned char* mskpixels=(unsigned char*)msk->pixels;
+ unsigned char* dstpixels=(unsigned char*)dst->pixels;
+ unsigned char* adjpixels=(unsigned char*)adj->pixels;
+ int stride=bmp->stride;
+ int width=bmp->width;
+ int height=bmp->height;
+ int X,Y;
+ unsigned char NM=CLAMPCOLOR(alpha);
+ unsigned char *LinePS , *LinePM , *LinePD , *LinePA ;
+ #pragma omp parallel for private(LinePS,LinePM,LinePD,LinePA,X,Y)
+ for (Y = 0; Y < height; Y ++)
+ {
+ int offset=stride*Y;
+ LinePS = bmppixels +offset;
+ LinePM = mskpixels +offset;
+ LinePD = dstpixels +offset;
+ LinePA = adjpixels +offset;
+ for (X = 0; X < width; X ++)
+ {
+ unsigned char M=*LinePM;
+ if(M==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else if(M==0x00){
+ if(NM==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else {
+ if(NM==0x00){
+ //none
+ LinePD[0]=LinePA[0];
+ LinePD[1]=LinePA[1];
+ LinePD[2]=LinePA[2];
+ }else{
+ ColorBlend_Alpha(LinePD,LinePS,LinePA,NM);
+ }
+ }
+ }else{
+ //
+ if(NM==0xFF){
+ LinePD[0]=LinePS[0];
+ LinePD[1]=LinePS[1];
+ LinePD[2]=LinePS[2];
+ }else{
+ if(NM==0x00){
+ ColorBlend_Alpha(LinePD,LinePS,LinePA,M);
+ }else{
+ ColorBlend_Alpha(LinePA,LinePS,LinePA,NM);
+ ColorBlend_Alpha(LinePD,LinePS,LinePA,M);
+ }
+ }
+ }
+ LinePD[3]=LinePS[3];
+ LinePS += 4; LinePM += 4; LinePD += 4; LinePA += 4;
+ }
+ }
+}
+
+void ReadAlphaBySrc(CBitmap* src,CBitmap* alpha){
+ memcpy(alpha,src,sizeof(CBitmap));
+ alpha->stride=src->width;
+ alpha->channel=1;
+ alpha->pixels=(CPixel*)malloc(alpha->width*alpha->height*sizeof(unsigned char));
+ unsigned char* bmppixels=(unsigned char*)src->pixels;
+ unsigned char* alapixels=(unsigned char*)alpha->pixels;
+ int stride=src->stride;
+ int width=src->width;
+ int height=src->height;
+ int X,Y;
+ unsigned char *LinePS , *LinePA;
+ //#pragma omp parallel for private(LinePS,LinePA)
+ for (Y = 0; Y < height; Y ++)
+ {
+ LinePS = bmppixels +stride*Y;
+ LinePA = alapixels +width*Y;
+ for (X = 0; X < width; X ++)
+ {
+ LinePA[0]=LinePS[3];
+ LinePS += 4; LinePA ++;
+ }
+ }
+}
+
+
+void CheckAlpha(CBitmap* bmp,CBitmap* alpha)
+{
+ unsigned char* bmppixels=(unsigned char*)bmp->pixels;
+ unsigned char* alapixels=(unsigned char*)alpha->pixels;
+ int stride=bmp->stride;
+ int width=bmp->width;
+ int height=bmp->height;
+ int X,Y;
+ unsigned char *LinePS , *LinePA;
+ //#pragma omp parallel for private(LinePS,LinePA)
+ for (Y = 0; Y < height; Y ++)
+ {
+ LinePS = bmppixels +stride*Y;
+ LinePA = alapixels +width*Y;
+ for (X = 0; X < width; X ++)
+ {
+ //unsigned char M=LinePA[0];
+ if(*LinePA==0x00){
+ LinePS[0]=0;
+ LinePS[1]=0;
+ LinePS[2]=0;
+ LinePS[3]=0;
+ //}else if(M<0xff){
+ //if(LinePD[0]>M)LinePD[0]=M;
+ //if(LinePD[1]>M)LinePD[1]=M;
+ //if(LinePD[2]>M)LinePD[2]=M;
+ //LinePD[3]=M;
+ }else{
+ }
+ LinePS += 4; LinePA++;
+ }
+ }
+}
+*/
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e8ec8a31470f272be10be28506b920681ba3e4a
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/blendgram.h
@@ -0,0 +1,287 @@
+#ifndef __BLENDGRAM_H__
+#define __BLENDGRAM_H__
+
+#include
+#include
+#include
+
+typedef unsigned char uchar;
+#define CLAMPCOLOR(x) (uchar)((x)<(0)?(0):((x)>(255)?(255):(x)))
+
+#define MMAX(A,B) ((A)>(B)?(A):(B))
+#define MMIN(A,B) ((A)<(B)?(A):(B))
+
+static int ConstBlend_Buffer = 0;
+static int ConstBlend_Normal=ConstBlend_Buffer+1;
+static int ConstBlend_Lighten=ConstBlend_Buffer+2;
+static int ConstBlend_Darken=ConstBlend_Buffer+3;
+static int ConstBlend_Multiply=ConstBlend_Buffer+4;
+static int ConstBlend_Average=ConstBlend_Buffer+5;
+
+static int ConstBlend_Add=ConstBlend_Buffer+6;
+static int ConstBlend_Subtract=ConstBlend_Buffer+7;
+static int ConstBlend_Difference=ConstBlend_Buffer+8;
+static int ConstBlend_Negation=ConstBlend_Buffer+9;
+static int ConstBlend_Screen=ConstBlend_Buffer+10;
+static int ConstBlend_Exclusion=ConstBlend_Buffer+11;
+static int ConstBlend_Overlay=ConstBlend_Buffer+12;
+static int ConstBlend_SoftLight=ConstBlend_Buffer+13;
+static int ConstBlend_HardLight=ConstBlend_Buffer+14;
+static int ConstBlend_ColorDodge=ConstBlend_Buffer+15;
+static int ConstBlend_ColorBurn=ConstBlend_Buffer+16;
+static int ConstBlend_LinearDodge=ConstBlend_Buffer+17;
+static int ConstBlend_LinearBurn=ConstBlend_Buffer+18;
+static int ConstBlend_LinearLight=ConstBlend_Buffer+19;
+static int ConstBlend_VividLight=ConstBlend_Buffer+20;
+static int ConstBlend_PinLight=ConstBlend_Buffer+21;
+static int ConstBlend_HardMix=ConstBlend_Buffer+22;
+static int ConstBlend_Reflect=ConstBlend_Buffer+23;
+static int ConstBlend_Glow=ConstBlend_Buffer+24;
+static int ConstBlend_Phoenix=ConstBlend_Buffer+25;
+
+//void BlendGram(CBitmap* immage,CBitmap* mask,int mode);
+
+//#typedef unsigned char uint8
+#define uint8 unsigned char
+#define float64 double
+#define TRUE 1
+#define FALSE 0
+
+inline uint8 mmin(uint8 A,uint8 B){
+ return AB?A:B;
+}
+
+#define ChannelBlend_Normal(A,B) ((uint8)(A))
+#define ChannelBlend_Lighten(A,B) ((uint8)((B > A) ? B:A))
+#define ChannelBlend_Darken(A,B) ((uint8)((B > A) ? A:B))
+#define ChannelBlend_Multiply(A,B) ((uint8)((A * B) / 255))
+#define ChannelBlend_Average(A,B) ((uint8)((A + B) / 2))
+#define ChannelBlend_Add(A,B) ((uint8)(mmin(255, (A + B))))
+#define ChannelBlend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255)))
+#define ChannelBlend_Difference(A,B) ((uint8)(abs(A - B)))
+#define ChannelBlend_Negation(A,B) ((uint8)(255 - abs(255 - A - B)))
+#define ChannelBlend_Screen(A,B) ((uint8)(255 - (((255 - A) * (255 - B)) >> 8)))
+#define ChannelBlend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B / 255))
+#define ChannelBlend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255)))
+#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))))
+#define ChannelBlend_HardLight(A,B) (ChannelBlend_Overlay(B,A))
+#define ChannelBlend_ColorDodge(A,B) ((uint8)((B == 255) ? B:mmin(255, ((A << 8 ) / (255 - B)))))
+#define ChannelBlend_ColorBurn(A,B) ((uint8)((B == 0) ? B:mmax(0, (255 - ((255 - A) << 8 ) / B))))
+#define ChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B))
+#define ChannelBlend_LinearBurn(A,B) (ChannelBlend_Subtract(A,B))
+#define ChannelBlend_LinearLight(A,B)((uint8)(B < 128)?ChannelBlend_LinearBurn(A,(2 * B)):ChannelBlend_LinearDodge(A,(2 * (B - 128))))
+#define ChannelBlend_VividLight(A,B) ((uint8)(B < 128)?ChannelBlend_ColorBurn(A,(2 * B)):ChannelBlend_ColorDodge(A,(2 * (B - 128))))
+#define ChannelBlend_PinLight(A,B) ((uint8)(B < 128)?ChannelBlend_Darken(A,(2 * B)):ChannelBlend_Lighten(A,(2 * (B - 128))))
+#define ChannelBlend_HardMix(A,B) ((uint8)((ChannelBlend_VividLight(A,B) < 128) ? 0:255))
+#define ChannelBlend_Reflect(A,B) ((uint8)((B == 255) ? B:mmin(255, (A * A / (255 - B)))))
+#define ChannelBlend_Glow(A,B) (ChannelBlend_Reflect(B,A))
+#define ChannelBlend_Phoenix(A,B) ((uint8)(mmin(A,B) - mmax(A,B) + 255))
+#define ChannelBlend_SoftEx(A,B) (A*B/255+A*(255-((255-A)*(255-B)/255)-A*B/255)/255)
+
+#define ChannelBlend_Alpha(A,B,O) ((uint8)(O * A + (1 - O) * B))
+#define ChannelBlend_AlphaEx(A,B,O) ((uint8)((O * A + (255 - O) * B)/255))
+#define ChannelBlend_AlphaF(A,B,F,O) (ChannelBlend_AlphaEx(F(A,B),A,O))
+
+#define ColorBlend_Alpha(T,A,B,O) (T)[0] = ChannelBlend_AlphaEx((A)[0], (B)[0],O), (T)[1] = ChannelBlend_AlphaEx((A)[1], (B)[1],O), (T)[2] = ChannelBlend_AlphaEx((A)[2], (B)[2],O)
+//, (T)[3] = ChannelBlend_AlphaEx((A)[3], (B)[3],O)
+#define ColorBlend_AlphaF(T,A,B,F,O) (T)[0] = ChannelBlend_AlphaF((A)[0], (B)[0],F,O), (T)[1] = ChannelBlend_AlphaF((A)[1], (B)[1],F,O), (T)[2] = ChannelBlend_AlphaF((A)[2], (B )[2],F,O) , (T)[3] = ChannelBlend_AlphaEx((A)[3], (B)[3],O)
+
+
+#define ColorBlend_Buffer(T,A,B,M) (T)[0] = ChannelBlend_##M((A)[0], (B)[0]), (T)[1] = ChannelBlend_##M((A)[1], (B)[1]), (T)[2] = ChannelBlend_##M((A)[2], (B)[2])
+
+#define ColorBlend_Normal(T,A,B) (ColorBlend_Buffer(T,A,B,Normal))
+#define ColorBlend_Lighten(T,A,B) (ColorBlend_Buffer(T,A,B,Lighten))
+#define ColorBlend_Darken(T,A,B) (ColorBlend_Buffer(T,A,B,Darken))
+#define ColorBlend_Multiply(T,A,B) (ColorBlend_Buffer(T,A,B,Multiply))
+#define ColorBlend_Average(T,A,B) (ColorBlend_Buffer(T,A,B,Average))
+#define ColorBlend_Add(T,A,B) (ColorBlend_Buffer(T,A,B,Add))
+#define ColorBlend_Subtract(T,A,B) (ColorBlend_Buffer(T,A,B,Subtract))
+#define ColorBlend_Difference(T,A,B) (ColorBlend_Buffer(T,A,B,Difference))
+#define ColorBlend_Negation(T,A,B) (ColorBlend_Buffer(T,A,B,Negation))
+#define ColorBlend_Screen(T,A,B) (ColorBlend_Buffer(T,A,B,Screen))
+#define ColorBlend_Exclusion(T,A,B) (ColorBlend_Buffer(T,A,B,Exclusion))
+#define ColorBlend_Overlay(T,A,B) (ColorBlend_Buffer(T,A,B,Overlay))
+#define ColorBlend_SoftLight(T,A,B) (ColorBlend_Buffer(T,A,B,SoftLight))
+#define ColorBlend_HardLight(T,A,B) (ColorBlend_Buffer(T,A,B,HardLight))
+#define ColorBlend_ColorDodge(T,A,B) (ColorBlend_Buffer(T,A,B,ColorDodge))
+#define ColorBlend_ColorBurn(T,A,B) (ColorBlend_Buffer(T,A,B,ColorBurn))
+#define ColorBlend_LinearDodge(T,A,B) (ColorBlend_Buffer(T,A,B,LinearDodge))
+#define ColorBlend_LinearBurn(T,A,B) (ColorBlend_Buffer(T,A,B,LinearBurn))
+#define ColorBlend_LinearLight(T,A,B) (ColorBlend_Buffer(T,A,B,LinearLight))
+#define ColorBlend_VividLight(T,A,B) (ColorBlend_Buffer(T,A,B,VividLight))
+#define ColorBlend_PinLight(T,A,B) (ColorBlend_Buffer(T,A,B,PinLight))
+#define ColorBlend_HardMix(T,A,B) (ColorBlend_Buffer(T,A,B,HardMix))
+#define ColorBlend_Reflect(T,A,B) (ColorBlend_Buffer(T,A,B,Reflect))
+#define ColorBlend_Glow(T,A,B) (ColorBlend_Buffer(T,A,B,Glow))
+#define ColorBlend_Phoenix(T,A,B) (ColorBlend_Buffer(T,A,B,Phoenix))
+
+
+#define ColorBlend_Hue(T,B,L) ColorBlend_Hls(T,B,L,HueL,LuminationB,SaturationB)
+#define ColorBlend_Saturation(T,B,L) ColorBlend_Hls(T,B,L,HueB,LuminationB,SaturationL)
+#define ColorBlend_Color(T,B,L) ColorBlend_Hls(T,B,L,HueL,LuminationB,SaturationL)
+#define ColorBlend_Luminosity(T,B,L) ColorBlend_Hls(T,B,L,HueB,LuminationL,SaturationB)
+
+
+
+#define ColorBlend_Hls(T,B,L,O1,O2,O3) { \
+ float64 HueB, LuminationB, SaturationB; \
+ float64 HueL, LuminationL, SaturationL; \
+ Color_RgbToHls((B)[2],(B)[1],(B)[0], &HueB, &LuminationB, &SaturationB); \
+ Color_RgbToHls((L)[2],(L)[1],(L)[0], &HueL, &LuminationL, &SaturationL); \
+ Color_HlsToRgb(O1,O2,O3,&(T)[2],&(T)[1],&(T)[0]); \
+ }
+
+
+/*********************************************************************/
+
+#define COLOR_OPAQUE (0)
+#define COLOR_TRANSPARENT (127)
+
+#define RGB_SIZE (3)
+#define RGB_BPP (24)
+#define RGB_MAXRED (255)
+#define RGB_MAXGREEN (255)
+#define RGB_MAXBLUE (255)
+
+#define ARGB_SIZE (4)
+#define ARGB_BPP (32)
+#define ARGB_MAXALPHA (127)
+#define ARGB_MAXRED (RGB_MAXRED)
+#define ARGB_MAXGREEN (RGB_MAXGREEN)
+#define ARGB_MAXBLUE (RGB_MAXBLUE)
+
+/*********************************************************************/
+
+#define Color_GetChannel(c,shift) ((uint8)((c) >> (shift)))
+#define Color_Reverse(c,bpp) ((((uint8)(c) << 24) | ((uint8)((c) >> 8 ) << 16) | ((uint8)((c) >> 16) << 8 ) | \ ((uint8)((c) >> 24))) >> (32 - (bpp)))
+
+#define Rgb_ByteWidth(width) ((width) * RGB_SIZE)
+#define Rgb_PixelWidth(width) ((width) / RGB_SIZE)
+
+#define Rgb_GetRed(rgb) (Color_GetChannel(rgb, 0))
+#define Rgb_GetGreen(rgb) (Color_GetChannel(rgb, 8))
+#define Rgb_GetBlue(rgb) (Color_GetChannel(rgb, 16))
+
+#define Rgba_GetRed(rgba) (Color_GetChannel(rgba, 24))
+#define Rgba_GetGreen(rgba) (Color_GetChannel(rgba, 16))
+#define Rgba_GetBlue(rgba) (Color_GetChannel(rgba, 8))
+#define Rgba_GetAlpha(rgba) (Color_GetChannel(rgba, 0))
+
+#define Argb_GetAlpha(argb) (Color_GetChannel(argb, 24))
+#define Argb_GetRed(argb) (Color_GetChannel(argb, 16))
+#define Argb_GetGreen(argb) (Color_GetChannel(argb, 8))
+#define Argb_GetBlue(argb) (Color_GetChannel(argb, 0))
+
+#define MakeRgb(r,g,b) (((uint32)(uint8)(b) << 16) | ((uint16)(uint8)(g) << 8 ) | (uint8)(r))
+#define MakeRgba(r,g,b,a) (((uint32)(uint8)(r) << 24) | ((uint16)(uint8)(g) << 16) | ((uint16)(uint8)(b) << 8 ) | (uint8)(a))
+#define MakeArgb(a,r,g,b) (((uint32)(uint8)(a) << 24) | ((uint32)(uint8)(r) << 16) | ((uint16)(uint8)(g) << 8 ) | (uint8)(b))
+#define HexToRgb(hex) (MakeRgb(((hex & 0xFF0000) >> 16), ((hex & 0x00FF00) >> 8 ), (hex & 0xFF)))
+
+inline int Color_HueToRgb(float64 M1, float64 M2, float64 Hue, float64 *Channel)
+{
+ if (Hue < 0.0)
+ Hue += 1.0;
+ else if (Hue > 1.0)
+ Hue -= 1.0;
+
+ if ((6.0 * Hue) < 1.0)
+ *Channel = (M1 + (M2 - M1) * Hue * 6.0);
+ else if ((2.0 * Hue) < 1.0)
+ *Channel = (M2);
+ else if ((3.0 * Hue) < 2.0)
+ *Channel = (M1 + (M2 - M1) * ((2.0F / 3.0F) - Hue) * 6.0);
+ else
+ *Channel = (M1);
+
+ return TRUE;
+}
+
+inline void Color_RgbToHls(uint8 Red, uint8 Green, uint8 Blue, float64 *Hue, float64 *Lumination, float64 *Saturation)
+{
+ float64 Delta;
+ float64 Max, Min;
+ float64 Redf, Greenf, Bluef;
+
+ Redf = (float64)Red / 255.0;
+ Greenf = (float64)Green / 255.0;
+ Bluef = (float64)Blue / 255.0;
+
+ //Max = fmax(fmax(Redf, Greenf), Bluef);
+ //Min = fmin(fmin(Redf, Greenf), Bluef);
+ Max = MMAX(MMAX(Red, Green), Blue)/255.0;
+ Min = MMIN(MMIN(Red, Green), Blue)/255.0;
+
+ *Hue = 0;
+ *Lumination = (Max + Min) / 2.0F;
+ *Saturation = 0;
+
+ if (Max == Min)
+ return ;
+
+ Delta = (Max - Min);
+
+ if (*Lumination < 0.5)
+ *Saturation = Delta / (Max + Min);
+ else
+ *Saturation = Delta / (2.0 - Max - Min);
+
+ if (Redf == Max)
+ *Hue = (Greenf - Bluef) / Delta;
+ else if (Greenf == Max)
+ *Hue = 2.0 + (Bluef - Redf) / Delta;
+ else
+ *Hue = 4.0 + (Redf - Greenf) / Delta;
+
+ *Hue /= 6.0;
+
+ if (*Hue < 0.0)
+ *Hue += 1.0;
+
+}
+
+inline void Color_HlsToRgb(float64 Hue, float64 Lumination, float64 Saturation, uint8 *Red, uint8 *Green, uint8 *Blue)
+{
+ float64 M1, M2;
+ float64 Redf, Greenf, Bluef;
+
+ if (Saturation == 0) {
+ Redf = Lumination;
+ Greenf = Lumination;
+ Bluef = Lumination;
+ } else {
+ if (Lumination <= 0.5)
+ M2 = Lumination * (1.0 + Saturation);
+ else
+ M2 = Lumination + Saturation - Lumination * Saturation;
+
+ M1 = (2.0 * Lumination - M2);
+
+ Color_HueToRgb(M1, M2, Hue + (1.0F / 3.0F), &Redf);
+ Color_HueToRgb(M1, M2, Hue, &Greenf);
+ Color_HueToRgb(M1, M2, Hue - (1.0F / 3.0F), &Bluef);
+ }
+
+ *Red = (uint8)(Redf * 255);
+ *Blue = (uint8)(Bluef * 255);
+ *Green = (uint8)(Greenf * 255);
+
+}
+
+void BlendGramSimp(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height, int Mode);
+void BlendGramAlpha(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height);
+void BlendGramAlpha3(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height);
+void BlendGramAlphaRev(unsigned char *Src,unsigned char* Mask, unsigned char *Dest, int Width, int Height);
+/*
+void BlendImageAdjustWithMask(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int mode);
+void BlendImageAdjustWithMaskEx(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int mode);
+void BlendImageAdjustWithAlpha(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,int alpha,int mode);
+void BlendImageAdjustWithAlphaMask(CBitmap* bmp,CBitmap* adj,CBitmap* dst ,CBitmap* msk,int alpha,int mode);
+
+void CheckAlpha(CBitmap* bmp,CBitmap* alpha);
+void ReadAlphaBySrc(CBitmap* src,CBitmap* alpha);
+*/
+
+#endif
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/bt b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/bt
new file mode 100644
index 0000000000000000000000000000000000000000..50f0612dd82a1beddbbbfcd5c22e8c8e24d8cbbd
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/bt
@@ -0,0 +1,19 @@
+g++ -g -I. \
+ -I/usr/include/opencv4 \
+ -I../third/x86/include \
+ -I../third/x86/include/ncnn/ \
+ -I../third/x86/include/onnx/ \
+ -I../third/x86/include/turbojpeg/ \
+ wavcache.cpp \
+ jmat.cpp \
+ wavreader.cpp \
+ wenet.cpp \
+ aimodel.cpp \
+ scrfd.cpp \
+ pfpld.cpp \
+ munet.cpp \
+ blendgram.cpp \
+ face_utils.cpp \
+ -L../third/x86/lib \
+ -lopencv_core -lopencv_dnn -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_videoio \
+ -lonnxruntime -lncnn \
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/face_utils.cpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/face_utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb3c4e8af47664a2090036117f32084df6961f42
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/face_utils.cpp
@@ -0,0 +1,114 @@
+#include "face_utils.h"
+//#include
+
+
+cv::Mat resize_image(cv::Mat srcimg, int height, int width, int* top, int* left){
+ cv::Mat dstimg;
+ int srch = srcimg.rows, srcw = srcimg.cols;
+ int neww = width;
+ int newh = height;
+ if (srch != srcw) {
+ float hw_scale = (float)srch / srcw;
+ if (hw_scale > 1) {
+ newh = height;
+ neww = int(width / hw_scale);
+ cv::resize(srcimg, dstimg, cv::Size(neww, newh), cv::INTER_AREA);
+ *left = int((width - neww) * 0.5);
+ cv::copyMakeBorder(dstimg, dstimg, 0, 0, *left, width - neww - *left, cv::BORDER_CONSTANT, 0);
+ }
+ else
+ {
+ newh = (int)height * hw_scale;
+ neww = width;
+ cv::resize(srcimg, dstimg,cv::Size(neww, newh), cv::INTER_AREA);
+ *top = (int)(height - newh) * 0.5;
+ cv::copyMakeBorder(dstimg, dstimg, *top, height - newh - *top, 0, 0, cv::BORDER_CONSTANT, 0);
+
+ }
+ } else {
+ cv::resize(srcimg, dstimg, cv::Size(neww, newh), cv::INTER_AREA);
+ }
+ return dstimg;
+}
+
+
+int dumpfile(char* file,char** pbuf){
+ std::string fname(file);
+ std::ifstream cache(fname,std::ios::binary);
+ cache.seekg(0,std::ios::end);
+ const int engSize = cache.tellg();
+ cache.seekg(0,std::ios::beg);
+ char *modelMem = (char*)malloc(engSize+8000);
+ cache.read(modelMem,engSize);
+ cache.close();
+ *pbuf = modelMem;
+ return engSize;
+}
+
+void dumpchar(char* abuf,int len){
+ uint8_t* buf = (uint8_t*)abuf;
+ printf("\n----------------------chardump------------------------\n");
+ int i;
+ for(i = 0; i < len; i++) {
+ printf("=%u=", buf[i]);
+ if( (i+1) % 16 == 0) {
+ printf("\n");
+ }
+ }
+ if(i%16 != 0) {
+ printf("\n");
+ }
+ printf("\n----------------------chardump------------------------\n");
+}
+
+
+void dumpfloat(float* abuf,int len){
+ printf("\n----------------------floatdump------------------------\n");
+ int i;
+ for(i = 0; i < len; i++) {
+ printf("=%f=", abuf[i]);
+ if( (i+1) % 16 == 0) {
+ printf("\n");
+ }
+ }
+ if(i%16 != 0) {
+ printf("\n");
+ }
+ printf("\n----------------------floatdump------------------------\n");
+}
+
+void dumphex(char* abuf,int len){
+ unsigned char* buf = (unsigned char*)abuf;
+ int i = 0;
+ printf("\n----------------------hexdump------------------------\n");
+ for(i = 0; i < len; i++) {
+ printf("=%02x=", buf[i]);
+ if( (i+1) % 16 == 0) {
+ printf("\n");
+ }
+ }
+ if(i%16 != 0) {
+ printf("\n");
+ }
+ printf("---------------------hexdump-------------------------\n\n");
+}
+
+int diffbuf(char* abuf,char* bbuf,int size){
+ char* pa = abuf;
+ char* pb = bbuf;
+ int diff = 0;
+ for(int k= 0;k
+#include
+#include
+#include
+//#include
+#include
+#include
+
+cv::Mat resize_image(cv::Mat srcimg, int height, int width, int* top, int* left);
+
+void dumpchar(char* abuf,int len);
+void dumphex(char* abuf,int len);
+void dumpfloat(float* abuf,int len);
+void dumpdouble(double* abuf,int len);
+int dumpfile(char* file,char** pbuf);
+int diffbuf(char* abuf,char* bbuf,int size);
+
+uint64_t timer_msstamp();
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jlog.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jlog.h
new file mode 100644
index 0000000000000000000000000000000000000000..92597882c742acfd24e4699ceb0dd20de80de73d
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jlog.h
@@ -0,0 +1,31 @@
+#pragma once
+#include
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef LIB_JNI
+#include
+#include
+
+#define LOG_TAG "tooken"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
+
+
+#else
+
+#define LOGE(...) printf(__VA_ARGS__)
+#define LOGI(...) printf(__VA_ARGS__)
+#define LOGD(...) printf(__VA_ARGS__)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.cpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e44b4bfc0f8fd90d517be16a1a2204ffa71e03de
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.cpp
@@ -0,0 +1,411 @@
+#include "jmat.h"
+
+extern "C"{
+#pragma pack(push)
+#pragma pack(4)
+
+ typedef struct _gpg_hdr {
+ char head[4];
+ int box[4];
+ int size[4];
+ int width[4];
+ int height[4];
+ uint8_t channel[4];
+ uint8_t bit[4];
+ }gpg_hdr;
+#pragma pack(pop)
+}
+
+
+int JBuf::zeros(){
+ memset(m_buf,0,m_size);
+ return m_size;
+}
+
+int JBuf::forceref(int bref){
+ if(m_ref!=bref){
+ m_ref = bref;
+ }
+ return 0;
+}
+
+JBuf::JBuf(uint32_t size,void* buf ){
+ if(buf){
+ m_ref = true;
+ m_buf = buf;
+ m_size = size;
+ }else{
+ m_ref = false;
+ m_size = size;
+ m_buf = malloc(size+1024);
+ }
+}
+
+JBuf::~JBuf(){
+ if(!m_ref){
+ free(m_buf);
+ m_buf = nullptr;
+ }
+}
+
+JBuf::JBuf(){
+ m_size = 0;
+ m_buf = nullptr;
+}
+
+JMat::JMat(){
+ init_tagarr();
+}
+
+void JMat::init_tagarr(){
+ memset(m_tagarr,0,512*sizeof(int));
+}
+
+int* JMat::tagarr(){
+ return m_tagarr;
+}
+
+int JMat::savegpg(std::string gpgfile){
+ gpg_hdr ghead;
+ memset(&ghead,0,sizeof(gpg_hdr));
+ ghead.head[0]='g';
+ ghead.head[1]='p';
+ ghead.head[2]='g';
+ ghead.head[3]='1';
+ ghead.size[0]=m_size;
+ ghead.width[0]=m_width;
+ ghead.height[0]=m_height;
+ ghead.channel[0]=m_channel;
+ ghead.bit[0]=m_bit;
+
+ FILE *gpgFile = NULL;
+ const char* fn = gpgfile.c_str();
+ if ((gpgFile = fopen(fn, "wb")) == NULL)return -1;
+ fwrite(&ghead,sizeof(gpg_hdr),1,gpgFile);
+ fwrite(m_buf, m_size, 1, gpgFile);
+ fclose(gpgFile);
+ return 0;
+}
+
+int JMat::load(std::string picfile){
+ const char* fn = picfile.c_str();
+ int len = strlen(fn);
+ if(len<4)return -1;
+ fn+= len-3;
+ int gpg = (fn[0]=='g')&&(fn[1]=='p')&&(fn[2]=='g');
+ if(gpg){
+ return loadgpg(picfile);
+ }else{
+ return loadjpg(picfile);
+ }
+
+}
+
+int JMat::loadgpg(std::string gpgfile){
+ FILE *gpgFile = NULL;
+ const char* fn = gpgfile.c_str();
+ if ((gpgFile = fopen(fn, "rb")) == NULL)return -1;
+ int rst = 0;
+ while(1){
+ gpg_hdr ghead;
+ memset(&ghead,0,sizeof(gpg_hdr));
+ fread(&ghead,sizeof(gpg_hdr),1,gpgFile);
+ char* arr=ghead.head;
+ if((arr[0]=='g')&&
+ (arr[1]=='p')&&
+ (arr[2]=='g')){
+
+ int imgSize = ghead.size[0];
+ if(m_sizem_buf,m_buf,m_size);
+ memcpy(cm->m_tagarr,m_tagarr,512*sizeof(int));
+ return cm;
+ }
+}
+
+JMat JMat::clone(){
+ JMat cm(m_width,m_height,m_channel,m_stride,m_bit);
+ //printf("==clone %d\n",m_size);
+ memcpy(cm.m_buf,m_buf,m_size);
+ memcpy(cm.m_tagarr,m_tagarr,512*sizeof(int));
+ return cm;
+}
+
+#ifdef USE_OPENCV
+JMat::JMat(std::string picfile,int flag):JBuf(){
+ cv::Mat image = cv::imread(picfile);
+ m_bit = flag?1:sizeof(float);
+ m_width = image.cols;
+ m_height = image.rows;
+ m_channel = 3;//image.channels();
+ //printf("===channels %d\n",m_channel);
+ m_stride = m_width*m_channel;
+ m_size = m_bit*m_stride*m_height;
+ m_buf = malloc(m_size+m_bit*m_stride);
+ m_ref = 0;
+ if(flag){
+ memcpy(m_buf,image.data,m_size);
+ //printf("===w %d h %d\n",image.cols,image.rows);
+ //cv::imshow("aaa",image);
+ //cv::waitKey(0);
+ //cv::Mat fmat(m_height,m_width,CV_8UC3,m_buf);
+ //float scale = 1.0f/255.0f;
+ //image.convertTo(fmat,CV_32F,scale);
+ }else{
+ cv::Mat fmat(m_height,m_width,CV_32FC3,m_buf);
+ float scale = 1.0f/255.0f;
+ image.convertTo(fmat,CV_32F,scale);
+ }
+ image.release();
+ init_tagarr();
+}
+#else
+JMat::JMat(std::string picfile,int flag):JBuf(){
+
+}
+#endif
+
+JMat::~JMat(){
+}
+
+float* JMat::fdata(){
+ return (float*)m_buf;
+}
+
+float* JMat::frow(int row){
+ return ((float*)m_buf)+ row*m_stride;
+}
+
+float* JMat::fitem(int row,int col){
+ return ((float*)m_buf)+ row*m_stride + col;
+
+}
+
+
+uint8_t* JMat::udata(){
+ return (uint8_t*)m_buf;
+}
+/*
+ nc::NdArray JMat::ncarray(){
+ bool own = false;
+ nc::NdArray arr = nc::NdArray((float*)m_buf, m_height, m_width, own);
+ return arr;
+ }
+ */
+
+
+#ifdef USE_NCNN
+ncnn::Mat JMat::packingmat(){
+ ncnn::Mat in_pack(m_width,m_height,1,(void*)m_buf,(size_t)4u*3,3);
+ ncnn::Mat in ;
+ ncnn::convert_packing(in_pack,in,1);
+ return in;
+}
+
+ncnn::Mat JMat::ncnnmat(){
+ unsigned char* data = (unsigned char*)m_buf;
+ if(m_channel == 3){
+ ncnn::Mat mat = ncnn::Mat::from_pixels(data, ncnn::Mat::PIXEL_BGR, m_width, m_height);
+ return mat;
+ }else if(m_channel == 4){
+ ncnn::Mat mat = ncnn::Mat::from_pixels(data, ncnn::Mat::PIXEL_BGRA, m_width, m_height);
+ return mat;
+ }else if(m_channel == 1){
+ ncnn::Mat mat = ncnn::Mat::from_pixels(data, ncnn::Mat::PIXEL_GRAY, m_width, m_height);
+ return mat;
+ }else {
+ ncnn::Mat mat = ncnn::Mat::from_pixels(data, ncnn::Mat::PIXEL_GRAY, m_width*m_channel, m_height);
+ return mat;
+ }
+}
+#endif
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ca5660d02a8dca3e98c9bdac13dc0b013ba66e1
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/jmat.h
@@ -0,0 +1,92 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "NumCpp.hpp"
+#define USE_OPENCV
+#define USE_NCNN
+#define USE_TURBOJPG
+
+#ifdef USE_OPENCV
+#include "opencv2/core.hpp"
+#include "opencv2/imgproc.hpp"
+#include "opencv2/highgui.hpp"
+#endif
+
+#ifdef USE_NCNN
+#include "mat.h"
+#endif
+
+#ifdef USE_EIGEN
+#include "eigen3/Eigen/Core"
+typedef Eigen::Matrix Vectorf;
+typedef Eigen::Matrix, 1, Eigen::Dynamic, Eigen::RowMajor> Vectorcf;
+typedef Eigen::Matrix Matrixf;
+typedef Eigen::Matrix, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Matrixcf;
+#endif
+
+class JBuf{
+ protected:
+ bool m_ref = 0;
+ uint32_t m_size = 0;
+ void* m_buf = NULL;
+ public:
+ uint32_t size(){return m_size;} ;
+ void* data(){return m_buf;};
+ bool ref(){return m_ref;};
+ int zeros();
+ int forceref(int bref);
+ JBuf();
+ JBuf(uint32_t size,void* buf = nullptr);
+ virtual ~JBuf();
+};
+
+class JMat:public JBuf{
+ protected:
+ int m_bit = 0;
+ int m_width = 0;
+ int m_height = 0;
+ int m_channel = 0;
+ int m_stride = 0;
+ int m_tagarr[512];
+ void init_tagarr();
+ public:
+ int height(){return m_height;}
+ int width(){return m_width;}
+ int stride(){return m_stride;}
+ int channel(){return m_channel;}
+ JMat(int w,int h,float *buf ,int c = 3 ,int d = 0);
+ JMat(int w,int h,uint8_t *buf ,int c = 3 ,int d = 0);
+ JMat(int w,int h,int c = 3,int d = 0,int b=0);
+ JMat(std::string picfile,int flag=0);
+ JMat();
+ int load(std::string picfile);
+ int loadjpg(std::string picfile,int flag=0);
+ int savegpg(std::string gpgfile);
+ int loadgpg(std::string gpgfile);
+ float* fdata();
+ float* frow(int row);
+ float* fitem(int row,int col);
+ int tojpg(const char* fn);
+ int tobin(const char* fn);
+ int show(const char* title);
+ JMat clone();
+ JMat* refclone(int ref=1);
+ uint8_t* udata();
+ virtual ~JMat();
+ int* tagarr();
+ //nc::NdArray ncarray();
+#ifdef USE_OPENCV
+ cv::Mat cvmat();
+#endif
+#ifdef USE_NCNN
+ ncnn::Mat ncnnmat();
+ ncnn::Mat packingmat();
+#endif
+ //Matrixf tomatrix();
+};
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.cpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e59a87ee93a7140bc52a892c8701a4e9ceb72aee
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.cpp
@@ -0,0 +1,229 @@
+#include "malpha.h"
+#include "blendgram.h"
+#include "face_utils.h"
+
+MWorkMat::MWorkMat(JMat* pic,JMat* msk,const int* boxs){
+ m_boxx = boxs[0];
+ m_boxy=boxs[1];
+ m_boxwidth=boxs[2]-m_boxx;
+ m_boxheight=boxs[3]-m_boxy;
+ //printf("x %d y %d w %d h %d \n",m_boxx,m_boxy,m_boxwidth,m_boxheight);
+ m_pic = pic;
+ m_msk = msk;
+
+ pic_real160 = new JMat(160,160,3,0,1);
+ pic_mask160 = new JMat(160,160,3,0,1);
+ //pic_crop160 = new JMat(160,160,3,0,1);
+
+ msk_real160 = new JMat(160,160,1,0,1);
+
+ //msk_mask160 = new JMat(160,160,3,0,1);
+
+}
+
+MWorkMat::~MWorkMat(){
+ matpic_org168.release();
+ matpic_roirst.release();
+ delete pic_real160;
+ delete pic_mask160;
+ delete msk_real160;
+ if(pic_clone160) delete pic_clone160;
+}
+
+int MWorkMat::munet(JMat** ppic,JMat** pmsk){
+ *ppic = pic_real160;
+ *pmsk = pic_mask160;
+ return 0;
+}
+
+int MWorkMat::premunet(){
+ matpic_roisrc = cv::Mat(m_pic->cvmat(),cv::Rect(m_boxx,m_boxy,m_boxwidth,m_boxheight));
+ cv::resize(matpic_roisrc , matpic_org168, cv::Size(168, 168), cv::INTER_AREA);
+ //vtacc
+ matpic_roi160 = cv::Mat(matpic_org168,cv::Rect(4,4,160,160));
+ cv::Mat cvmask = pic_mask160->cvmat();
+ cv::Mat cvreal = pic_real160->cvmat();
+ matpic_roi160.copyTo(cvmask);
+ matpic_roi160.copyTo(cvreal);
+ //cv::rectangle(cvmask,cv::Rect(5,5,150,150),cv::Scalar(0,0,0),-1);//,cv::LineTypes::FILLED);
+ cv::rectangle(cvmask,cv::Rect(5,5,150,145),cv::Scalar(0,0,0),-1);//,cv::LineTypes::FILLED);
+ //cv::rectangle(cvmask,cv::Rect(4,4,152,152),cv::Scalar(0,0,0),-1);//,cv::LineTypes::FILLED);
+ //cv::imwrite("cvmask.bmp",cvmask);
+ //cv::waitKey(0);
+ pic_clone160 = pic_real160->refclone(0);
+ return 0;
+}
+
+int MWorkMat::finmunet(JMat* fgpic){
+ cv::Mat cvreal = pic_real160->cvmat();
+ cvreal.copyTo(matpic_roi160);
+ //cv::imwrite("accpre.bmp",matpic_org168);
+ if(m_msk) vtacc((uint8_t*)matpic_org168.data,168*168);
+ //cv::imwrite("accend.bmp",matpic_org168);
+ cv::resize(matpic_org168, matpic_roirst, cv::Size(m_boxwidth, m_boxheight), cv::INTER_AREA);
+ if(fgpic){
+ matpic_roisrc = cv::Mat(fgpic->cvmat(),cv::Rect(m_boxx,m_boxy,m_boxwidth,m_boxheight));
+ matpic_roirst.copyTo(matpic_roisrc);
+ }else{
+ matpic_roirst.copyTo(matpic_roisrc);
+ }
+ return 0;
+}
+
+int MWorkMat::alpha(JMat** preal,JMat** pimg,JMat** pmsk){
+ *preal = pic_clone160;
+ *pimg = pic_real160;
+ *pmsk = msk_real160;
+ return 0;
+}
+
+int MWorkMat::prealpha(){
+ printf("x %d y %d w %d h %d \n",m_boxx,m_boxy,m_boxwidth,m_boxheight);
+ //m_msk->show("cba");
+ //cv::waitKey(0);
+ matmsk_roisrc = cv::Mat(m_msk->cvmat(),cv::Rect(m_boxx,m_boxy,m_boxwidth,m_boxheight));
+ cv::resize(matmsk_roisrc , matmsk_org168, cv::Size(168, 168), cv::INTER_AREA);
+
+ matmsk_roi160 = cv::Mat(matmsk_org168,cv::Rect(4,4,160,160));
+ cv::Mat cvmask = msk_real160->cvmat();
+ cv::cvtColor(matmsk_roi160,cvmask,cv::COLOR_RGB2GRAY);
+
+ //BlendGramAlphaRev(pic_clone160->udata(),msk_real160->udata(),pic_crop160->udata(),160,160);
+ //pic_crop160->show("aaa");
+ //cv::waitKey(0);
+ //pic_crop160
+ //
+ return 0;
+}
+
+int MWorkMat::finalpha(){
+ cv::Mat cvmask = msk_real160->cvmat();
+ cv::cvtColor(cvmask,matmsk_roi160,cv::COLOR_GRAY2RGB);
+ //
+ cv::resize(matmsk_org168, matmsk_roirst, cv::Size(m_boxwidth, m_boxheight), cv::INTER_AREA);
+ matmsk_roirst.copyTo(matmsk_roisrc);
+ return 0;
+}
+
+int MWorkMat::vtacc(uint8_t* buf,int count){
+ /*
+ int avgr = 0;
+ int avgb = 0;
+ int avgg = 0;
+ if(1){
+ uint8_t* pb = m_pic->udata();
+ for(int k=0;k<10;k++){
+ avgr += *pb++;
+ avgg += *pb++;
+ avgb += *pb++;
+ }
+ avgr =avgr/10 +10;
+ avgg =avgg/10 -20;
+ if(avgg<0)avgg=0;
+ avgb =avgb/10 + 10;
+ }
+ */
+ uint8_t* pb = buf;
+ for(int k=0;k=sum){
+ pb[1]=sum;
+ //pb[0]=0;
+ //pb[2]=0;
+ // }else if((pb[0]avgg)&&(pb[2]255.f)?255:mean;
+ //printf("sum %ld mean %f maxg %d\n",sum,mean,maxg);
+ //getchar();
+ pb = buf +1;
+ for(int k=0;kmaxg){
+ *pb = maxg;
+ }
+ pb+=3;
+ }
+ */
+ return 0;
+}
+
+int MAlpha::doModel(JMat* real,JMat* img,JMat* pha){
+ if(1)return 0;
+ /*
+ if(1)return 0;
+ JMat picimg(160,160,3,0,1);
+ JMat picreal(160,160,3,0,1);
+ cv::cvtColor(real->cvmat(),picreal.cvmat(),cv::COLOR_RGB2BGR);
+ cv::cvtColor(img->cvmat(),picimg.cvmat(),cv::COLOR_RGB2BGR);
+ */
+ float mean_vals[3] = {127.5f, 127.5f, 127.5f};
+ float norm_vals[3] = {1 / 127.5f, 1 / 127.5f, 1 / 127.5f};
+ ncnn::Mat inimg = ncnn::Mat::from_pixels(img->udata(), ncnn::Mat::PIXEL_BGR2RGB, 160, 160);
+ inimg.substract_mean_normalize(mean_vals, norm_vals);
+ ncnn::Mat inreal = ncnn::Mat::from_pixels(real->udata(), ncnn::Mat::PIXEL_BGR2RGB, 160, 160);
+ inreal.substract_mean_normalize(mean_vals, norm_vals);
+ ncnn::Mat inpha = ncnn::Mat::from_pixels(pha->udata(), ncnn::Mat::PIXEL_GRAY, 160, 160);
+ float gmean_vals[3] = {0.0f, 0.0f, 0.0f};
+ float gnorm_vals[3] = {1 / 255.0f, 1 / 255.0f, 1 / 255.0f};
+ inpha.substract_mean_normalize(gmean_vals, gnorm_vals);
+
+ ncnn::Mat inpic(160,160,7);
+ //printf("===in %d %d all %d %d pha %d %d\n",inreal.cstep,inreal.elempack,inpic.cstep,inpic.elempack,inpha.cstep,inpha.elempack);
+ //JMat picin(160,160,7);
+ float* buf = (float*)inpic.data;
+ memcpy(buf,inreal.data,inreal.cstep*inreal.c*sizeof(float));
+ buf += inpic.cstep*inreal.c;
+ memcpy(buf,inimg.data,inimg.cstep*inimg.c*sizeof(float));
+ buf += inimg.cstep*inimg.c;
+ memcpy(buf, inpha.data,inpha.cstep*sizeof(float));
+ //ncnn::Mat inpic(160,160,7,pd,4);
+ //ncnn::Mat inpack(160,160,1,pd,(size_t)4u*7,7);
+ //ncnn::Mat inpic;
+ //ncnn::convert_packing(inpack,inpic,1);
+ ncnn::Mat outpic;
+ ncnn::Extractor ex = net.create_extractor();
+ int rst = ex.input("input", inpic);
+ //printf("input %d\n",rst);
+ rst = ex.extract("output", outpic);
+ //printf("output %d\n",rst);
+ float outmean_vals[3] = {0.0f, 0.0f, 0.0f};
+ float outnorm_vals[3] = { 255.0f, 255.0f, 255.0f};
+ outpic.substract_mean_normalize(outmean_vals, outnorm_vals);
+ outpic.to_pixels(pha->udata(),ncnn::Mat::PIXEL_GRAY);
+ //pha->show("mmm");
+ //cv::waitKey(0);
+ //dumpfloat((float*)outpic.data+160*159,10);
+ //ncnn::Mat pakpic;
+ //ncnn::convert_packing(outpic,pakpic,1);
+ //dumpfloat((float*)pakpic.data,160*160*1);
+ //getchar();
+ /*
+ cv::Mat cvadj(160,160,CV_32FC1,outpic.data);
+ cv::Mat cvout;//(160,160,CV_8UC1);
+ float scale = 255.0f;//255.0f;
+ cvadj.convertTo(cvout,CV_8UC1,scale);
+ cvout.copyTo(pha->cvmat());
+ */
+ //cv::imshow("pha",cvout);
+ //pha->show("pha");
+ //cv::waitKey(0);
+ return 0;
+}
+
+MAlpha::MAlpha(const char* fnbin,const char* fnparam):NcnnModel(160,160){
+ std::string fb(fnbin);
+ std::string fp(fnparam);
+ initModel(fb,fp);
+}
+
+MAlpha::~MAlpha(){
+
+}
+
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.h b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bb007ef4ec78ad43525ecc28f8cebb67babac18
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/malpha.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "jmat.h"
+#include "net.h"
+#include
+#include
+#include
+#include
+#include
+#include "aimodel.h"
+
+class MWorkMat{
+ private:
+ int m_boxx;
+ int m_boxy;
+ int m_boxwidth;
+ int m_boxheight;
+ JMat* m_pic;
+ JMat* m_msk;
+
+ JMat* pic_real160;//blendimg
+ JMat* pic_mask160;
+
+ cv::Mat matpic_roisrc;//box area
+ cv::Mat matpic_org168;
+ cv::Mat matpic_roi160;
+ JMat* pic_clone160;//blendimg
+ cv::Mat matpic_roirst;
+
+ //JMat* pic_crop160;
+ //
+ JMat* msk_real160;
+ //JMat* msk_mask160;
+
+ cv::Mat matmsk_roisrc;//box area
+ cv::Mat matmsk_org168;
+ cv::Mat matmsk_roi160;
+
+ cv::Mat matmsk_roirst;
+
+ int vtacc(uint8_t* buf,int count);
+ public:
+ MWorkMat(JMat* pic,JMat* msk,const int* boxs);
+ int premunet();
+ int munet(JMat** ppic,JMat** pmsk);
+ int finmunet(JMat* fgpic=NULL);
+ int prealpha();
+ int alpha(JMat** preal,JMat** pimg,JMat** pmsk);
+ int finalpha();
+
+ virtual ~MWorkMat();
+};
+
+class MAlpha:public NcnnModel{
+ private:
+ public:
+ int doModel(JMat* real,JMat* img,JMat* pha);
+ MAlpha(const char* fnbin,const char* fnparam);
+ virtual ~MAlpha();
+};
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/AudioFFT.hpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/AudioFFT.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ccfcae672f67fb92b45a5a3d736404e0c80bed4
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/AudioFFT.hpp
@@ -0,0 +1,1264 @@
+#pragma once
+
+#ifndef _AUDIOFFT_H
+#define _AUDIOFFT_H
+
+
+
+#include
+#include
+#include
+#include
+#include
+
+//#define AUDIOFFT_APPLE_ACCELERATE //AUDIOFFT_INTEL_IPP//AUDIOFFT_FFTW3//AUDIOFFT_APPLE_ACCELERATE
+
+#if defined(AUDIOFFT_INTEL_IPP)
+#define AUDIOFFT_INTEL_IPP_USED
+ #include
+#elif defined(AUDIOFFT_APPLE_ACCELERATE)
+#define AUDIOFFT_APPLE_ACCELERATE_USED
+ #include
+ #include
+#elif defined (AUDIOFFT_FFTW3)
+#define AUDIOFFT_FFTW3_USED
+ #include
+#else
+#if !defined(AUDIOFFT_OOURA)
+#define AUDIOFFT_OOURA
+#endif
+#define AUDIOFFT_OOURA_USED
+#include
+#endif
+
+namespace audiofft
+{
+
+ namespace detail
+ {
+ class AudioFFTImpl;
+ }
+
+
+ // =============================================================
+
+
+ /**
+ * @class AudioFFT
+ * @brief Performs 1D FFTs
+ */
+ class AudioFFT
+ {
+ public:
+ /**
+ * @brief Constructor
+ */
+ AudioFFT();
+
+ AudioFFT(const AudioFFT&) = delete;
+ AudioFFT& operator=(const AudioFFT&) = delete;
+
+ /**
+ * @brief Destructor
+ */
+ ~AudioFFT();
+
+ /**
+ * @brief Initializes the FFT object
+ * @param size Size of the real input (must be power 2)
+ */
+ void init(size_t size);
+
+ /**
+ * @brief Performs the forward FFT
+ * @param data The real input data (has to be of the length as specified in init())
+ * @param re The real part of the complex output (has to be of length as returned by ComplexSize())
+ * @param im The imaginary part of the complex output (has to be of length as returned by ComplexSize())
+ */
+ void fft(const float* data, float* re, float* im);
+
+ /**
+ * @brief Performs the inverse FFT
+ * @param data The real output data (has to be of the length as specified in init())
+ * @param re The real part of the complex input (has to be of length as returned by ComplexSize())
+ * @param im The imaginary part of the complex input (has to be of length as returned by ComplexSize())
+ */
+ void ifft(float* data, const float* re, const float* im);
+
+ /**
+ * @brief Calculates the necessary size of the real/imaginary complex arrays
+ * @param size The size of the real data
+ * @return The size of the real/imaginary complex arrays
+ */
+ static size_t ComplexSize(size_t size);
+
+ private:
+ std::unique_ptr _impl;
+ };
+
+
+ /**
+ * @deprecated
+ * @brief Let's keep an AudioFFTBase type around for now because it has been here already in the 1st version in order to avoid breaking existing code.
+ */
+ typedef AudioFFT AudioFFTBase;
+
+} // End of namespace
+
+
+namespace audiofft
+{
+
+ namespace detail
+ {
+
+ class AudioFFTImpl
+ {
+ public:
+ AudioFFTImpl() = default;
+ AudioFFTImpl(const AudioFFTImpl&) = delete;
+ AudioFFTImpl& operator=(const AudioFFTImpl&) = delete;
+ virtual ~AudioFFTImpl() = default;
+ virtual void init(size_t size) = 0;
+ virtual void fft(const float* data, float* re, float* im) = 0;
+ virtual void ifft(float* data, const float* re, const float* im) = 0;
+ };
+
+
+ constexpr bool IsPowerOf2(size_t val)
+ {
+ return (val == 1 || (val & (val-1)) == 0);
+ }
+
+
+ template
+ void ConvertBuffer(TypeDest* dest, const TypeSrc* src, size_t len)
+ {
+ for (size_t i=0; i(src[i]);
+ }
+ }
+
+
+ template
+ void ScaleBuffer(TypeDest* dest, const TypeSrc* src, const TypeFactor factor, size_t len)
+ {
+ for (size_t i=0; i(static_cast(src[i]) * factor);
+ }
+ }
+
+ } // End of namespace detail
+
+
+ // ================================================================
+
+
+#ifdef AUDIOFFT_OOURA_USED
+
+ /**
+ * @internal
+ * @class OouraFFT
+ * @brief FFT implementation based on the great radix-4 routines by Takuya Ooura
+ */
+ class OouraFFT : public detail::AudioFFTImpl
+ {
+ public:
+ OouraFFT() :
+ detail::AudioFFTImpl(),
+ _size(0),
+ _ip(),
+ _w(),
+ _buffer()
+ {
+ }
+
+ OouraFFT(const OouraFFT&) = delete;
+ OouraFFT& operator=(const OouraFFT&) = delete;
+
+ virtual void init(size_t size) override
+ {
+ if (_size != size)
+ {
+ _ip.resize(2 + static_cast(std::sqrt(static_cast(size))));
+ _w.resize(size / 2);
+ _buffer.resize(size);
+ _size = size;
+
+ const int size4 = static_cast(_size) / 4;
+ makewt(size4, _ip.data(), _w.data());
+ makect(size4, _ip.data(), _w.data() + size4);
+ }
+ }
+
+ virtual void fft(const float* data, float* re, float* im) override
+ {
+ // Convert into the format as required by the Ooura FFT
+ detail::ConvertBuffer(_buffer.data(), data, _size);
+
+ rdft(static_cast(_size), +1, _buffer.data(), _ip.data(), _w.data());
+
+ // Convert back to split-complex
+ {
+ double* b = _buffer.data();
+ double* bEnd = b + _size;
+ float *r = re;
+ float *i = im;
+ while (b != bEnd)
+ {
+ *(r++) = static_cast(*(b++));
+ *(i++) = static_cast(-(*(b++)));
+ }
+ }
+ const size_t size2 = _size / 2;
+ re[size2] = -im[0];
+ im[0] = 0.0;
+ im[size2] = 0.0;
+ }
+
+ virtual void ifft(float* data, const float* re, const float* im) override
+ {
+ // Convert into the format as required by the Ooura FFT
+ {
+ double* b = _buffer.data();
+ double* bEnd = b + _size;
+ const float *r = re;
+ const float *i = im;
+ while (b != bEnd)
+ {
+ *(b++) = static_cast(*(r++));
+ *(b++) = -static_cast(*(i++));
+ }
+ _buffer[1] = re[_size / 2];
+ }
+
+ rdft(static_cast(_size), -1, _buffer.data(), _ip.data(), _w.data());
+
+ // Convert back to split-complex
+ detail::ScaleBuffer(data, _buffer.data(), 2.0 / static_cast(_size), _size);
+ }
+
+ private:
+ size_t _size;
+ std::vector _ip;
+ std::vector _w;
+ std::vector _buffer;
+
+ void rdft(int n, int isgn, double *a, int *ip, double *w)
+ {
+ int nw = ip[0];
+ int nc = ip[1];
+
+ if (isgn >= 0)
+ {
+ if (n > 4)
+ {
+ bitrv2(n, ip + 2, a);
+ cftfsub(n, a, w);
+ rftfsub(n, a, nc, w + nw);
+ }
+ else if (n == 4)
+ {
+ cftfsub(n, a, w);
+ }
+ double xi = a[0] - a[1];
+ a[0] += a[1];
+ a[1] = xi;
+ }
+ else
+ {
+ a[1] = 0.5 * (a[0] - a[1]);
+ a[0] -= a[1];
+ if (n > 4)
+ {
+ rftbsub(n, a, nc, w + nw);
+ bitrv2(n, ip + 2, a);
+ cftbsub(n, a, w);
+ }
+ else if (n == 4)
+ {
+ cftfsub(n, a, w);
+ }
+ }
+ }
+
+
+ /* -------- initializing routines -------- */
+
+ void makewt(int nw, int *ip, double *w)
+ {
+ int j, nwh;
+ double delta, x, y;
+
+ ip[0] = nw;
+ ip[1] = 1;
+ if (nw > 2) {
+ nwh = nw >> 1;
+ delta = atan(1.0) / nwh;
+ w[0] = 1;
+ w[1] = 0;
+ w[nwh] = cos(delta * nwh);
+ w[nwh + 1] = w[nwh];
+ if (nwh > 2) {
+ for (j = 2; j < nwh; j += 2) {
+ x = cos(delta * j);
+ y = sin(delta * j);
+ w[j] = x;
+ w[j + 1] = y;
+ w[nw - j] = y;
+ w[nw - j + 1] = x;
+ }
+ bitrv2(nw, ip + 2, w);
+ }
+ }
+ }
+
+
+ void makect(int nc, int *ip, double *c)
+ {
+ int j, nch;
+ double delta;
+
+ ip[1] = nc;
+ if (nc > 1) {
+ nch = nc >> 1;
+ delta = atan(1.0) / nch;
+ c[0] = cos(delta * nch);
+ c[nch] = 0.5 * c[0];
+ for (j = 1; j < nch; j++) {
+ c[j] = 0.5 * cos(delta * j);
+ c[nc - j] = 0.5 * sin(delta * j);
+ }
+ }
+ }
+
+
+ /* -------- child routines -------- */
+
+
+ void bitrv2(int n, int *ip, double *a)
+ {
+ int j, j1, k, k1, l, m, m2;
+ double xr, xi, yr, yi;
+
+ ip[0] = 0;
+ l = n;
+ m = 1;
+ while ((m << 3) < l) {
+ l >>= 1;
+ for (j = 0; j < m; j++) {
+ ip[m + j] = ip[j] + l;
+ }
+ m <<= 1;
+ }
+ m2 = 2 * m;
+ if ((m << 3) == l) {
+ for (k = 0; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 2 * j + ip[k];
+ k1 = 2 * k + ip[j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += 2 * m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 -= m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += 2 * m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ j1 = 2 * k + m2 + ip[k];
+ k1 = j1 + m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ } else {
+ for (k = 1; k < m; k++) {
+ for (j = 0; j < k; j++) {
+ j1 = 2 * j + ip[k];
+ k1 = 2 * k + ip[j];
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ j1 += m2;
+ k1 += m2;
+ xr = a[j1];
+ xi = a[j1 + 1];
+ yr = a[k1];
+ yi = a[k1 + 1];
+ a[j1] = yr;
+ a[j1 + 1] = yi;
+ a[k1] = xr;
+ a[k1 + 1] = xi;
+ }
+ }
+ }
+ }
+
+
+ void cftfsub(int n, double *a, double *w)
+ {
+ int j, j1, j2, j3, l;
+ double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ l = 2;
+ if (n > 8) {
+ cft1st(n, a, w);
+ l = 8;
+ while ((l << 2) < n) {
+ cftmdl(n, l, a, w);
+ l <<= 2;
+ }
+ }
+ if ((l << 2) == n) {
+ for (j = 0; j < l; j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i - x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ }
+ } else {
+ for (j = 0; j < l; j += 2) {
+ j1 = j + l;
+ x0r = a[j] - a[j1];
+ x0i = a[j + 1] - a[j1 + 1];
+ a[j] += a[j1];
+ a[j + 1] += a[j1 + 1];
+ a[j1] = x0r;
+ a[j1 + 1] = x0i;
+ }
+ }
+ }
+
+
+ void cftbsub(int n, double *a, double *w)
+ {
+ int j, j1, j2, j3, l;
+ double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ l = 2;
+ if (n > 8) {
+ cft1st(n, a, w);
+ l = 8;
+ while ((l << 2) < n) {
+ cftmdl(n, l, a, w);
+ l <<= 2;
+ }
+ }
+ if ((l << 2) == n) {
+ for (j = 0; j < l; j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = -a[j + 1] - a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = -a[j + 1] + a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i - x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i + x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i - x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i + x3r;
+ }
+ } else {
+ for (j = 0; j < l; j += 2) {
+ j1 = j + l;
+ x0r = a[j] - a[j1];
+ x0i = -a[j + 1] + a[j1 + 1];
+ a[j] += a[j1];
+ a[j + 1] = -a[j + 1] - a[j1 + 1];
+ a[j1] = x0r;
+ a[j1 + 1] = x0i;
+ }
+ }
+ }
+
+
+ void cft1st(int n, double *a, double *w)
+ {
+ int j, k1, k2;
+ double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
+ double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ x0r = a[0] + a[2];
+ x0i = a[1] + a[3];
+ x1r = a[0] - a[2];
+ x1i = a[1] - a[3];
+ x2r = a[4] + a[6];
+ x2i = a[5] + a[7];
+ x3r = a[4] - a[6];
+ x3i = a[5] - a[7];
+ a[0] = x0r + x2r;
+ a[1] = x0i + x2i;
+ a[4] = x0r - x2r;
+ a[5] = x0i - x2i;
+ a[2] = x1r - x3i;
+ a[3] = x1i + x3r;
+ a[6] = x1r + x3i;
+ a[7] = x1i - x3r;
+ wk1r = w[2];
+ x0r = a[8] + a[10];
+ x0i = a[9] + a[11];
+ x1r = a[8] - a[10];
+ x1i = a[9] - a[11];
+ x2r = a[12] + a[14];
+ x2i = a[13] + a[15];
+ x3r = a[12] - a[14];
+ x3i = a[13] - a[15];
+ a[8] = x0r + x2r;
+ a[9] = x0i + x2i;
+ a[12] = x2i - x0i;
+ a[13] = x0r - x2r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[10] = wk1r * (x0r - x0i);
+ a[11] = wk1r * (x0r + x0i);
+ x0r = x3i + x1r;
+ x0i = x3r - x1i;
+ a[14] = wk1r * (x0i - x0r);
+ a[15] = wk1r * (x0i + x0r);
+ k1 = 0;
+ for (j = 16; j < n; j += 16) {
+ k1 += 2;
+ k2 = 2 * k1;
+ wk2r = w[k1];
+ wk2i = w[k1 + 1];
+ wk1r = w[k2];
+ wk1i = w[k2 + 1];
+ wk3r = wk1r - 2 * wk2i * wk1i;
+ wk3i = 2 * wk2i * wk1r - wk1i;
+ x0r = a[j] + a[j + 2];
+ x0i = a[j + 1] + a[j + 3];
+ x1r = a[j] - a[j + 2];
+ x1i = a[j + 1] - a[j + 3];
+ x2r = a[j + 4] + a[j + 6];
+ x2i = a[j + 5] + a[j + 7];
+ x3r = a[j + 4] - a[j + 6];
+ x3i = a[j + 5] - a[j + 7];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j + 4] = wk2r * x0r - wk2i * x0i;
+ a[j + 5] = wk2r * x0i + wk2i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j + 2] = wk1r * x0r - wk1i * x0i;
+ a[j + 3] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j + 6] = wk3r * x0r - wk3i * x0i;
+ a[j + 7] = wk3r * x0i + wk3i * x0r;
+ wk1r = w[k2 + 2];
+ wk1i = w[k2 + 3];
+ wk3r = wk1r - 2 * wk2r * wk1i;
+ wk3i = 2 * wk2r * wk1r - wk1i;
+ x0r = a[j + 8] + a[j + 10];
+ x0i = a[j + 9] + a[j + 11];
+ x1r = a[j + 8] - a[j + 10];
+ x1i = a[j + 9] - a[j + 11];
+ x2r = a[j + 12] + a[j + 14];
+ x2i = a[j + 13] + a[j + 15];
+ x3r = a[j + 12] - a[j + 14];
+ x3i = a[j + 13] - a[j + 15];
+ a[j + 8] = x0r + x2r;
+ a[j + 9] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j + 12] = -wk2i * x0r - wk2r * x0i;
+ a[j + 13] = -wk2i * x0i + wk2r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j + 10] = wk1r * x0r - wk1i * x0i;
+ a[j + 11] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j + 14] = wk3r * x0r - wk3i * x0i;
+ a[j + 15] = wk3r * x0i + wk3i * x0r;
+ }
+ }
+
+
+ void cftmdl(int n, int l, double *a, double *w)
+ {
+ int j, j1, j2, j3, k, k1, k2, m, m2;
+ double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
+ double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+ m = l << 2;
+ for (j = 0; j < l; j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x0r - x2r;
+ a[j2 + 1] = x0i - x2i;
+ a[j1] = x1r - x3i;
+ a[j1 + 1] = x1i + x3r;
+ a[j3] = x1r + x3i;
+ a[j3 + 1] = x1i - x3r;
+ }
+ wk1r = w[2];
+ for (j = m; j < l + m; j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ a[j2] = x2i - x0i;
+ a[j2 + 1] = x0r - x2r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * (x0r - x0i);
+ a[j1 + 1] = wk1r * (x0r + x0i);
+ x0r = x3i + x1r;
+ x0i = x3r - x1i;
+ a[j3] = wk1r * (x0i - x0r);
+ a[j3 + 1] = wk1r * (x0i + x0r);
+ }
+ k1 = 0;
+ m2 = 2 * m;
+ for (k = m2; k < n; k += m2) {
+ k1 += 2;
+ k2 = 2 * k1;
+ wk2r = w[k1];
+ wk2i = w[k1 + 1];
+ wk1r = w[k2];
+ wk1i = w[k2 + 1];
+ wk3r = wk1r - 2 * wk2i * wk1i;
+ wk3i = 2 * wk2i * wk1r - wk1i;
+ for (j = k; j < l + k; j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j2] = wk2r * x0r - wk2i * x0i;
+ a[j2 + 1] = wk2r * x0i + wk2i * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * x0r - wk1i * x0i;
+ a[j1 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r - wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i + wk3i * x0r;
+ }
+ wk1r = w[k2 + 2];
+ wk1i = w[k2 + 3];
+ wk3r = wk1r - 2 * wk2r * wk1i;
+ wk3i = 2 * wk2r * wk1r - wk1i;
+ for (j = k + m; j < l + (k + m); j += 2) {
+ j1 = j + l;
+ j2 = j1 + l;
+ j3 = j2 + l;
+ x0r = a[j] + a[j1];
+ x0i = a[j + 1] + a[j1 + 1];
+ x1r = a[j] - a[j1];
+ x1i = a[j + 1] - a[j1 + 1];
+ x2r = a[j2] + a[j3];
+ x2i = a[j2 + 1] + a[j3 + 1];
+ x3r = a[j2] - a[j3];
+ x3i = a[j2 + 1] - a[j3 + 1];
+ a[j] = x0r + x2r;
+ a[j + 1] = x0i + x2i;
+ x0r -= x2r;
+ x0i -= x2i;
+ a[j2] = -wk2i * x0r - wk2r * x0i;
+ a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
+ x0r = x1r - x3i;
+ x0i = x1i + x3r;
+ a[j1] = wk1r * x0r - wk1i * x0i;
+ a[j1 + 1] = wk1r * x0i + wk1i * x0r;
+ x0r = x1r + x3i;
+ x0i = x1i - x3r;
+ a[j3] = wk3r * x0r - wk3i * x0i;
+ a[j3 + 1] = wk3r * x0i + wk3i * x0r;
+ }
+ }
+ }
+
+
+ void rftfsub(int n, double *a, int nc, double *c)
+ {
+ int j, k, kk, ks, m;
+ double wkr, wki, xr, xi, yr, yi;
+
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2) {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5 - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr - wki * xi;
+ yi = wkr * xi + wki * xr;
+ a[j] -= yr;
+ a[j + 1] -= yi;
+ a[k] += yr;
+ a[k + 1] -= yi;
+ }
+ }
+
+
+ void rftbsub(int n, double *a, int nc, double *c)
+ {
+ int j, k, kk, ks, m;
+ double wkr, wki, xr, xi, yr, yi;
+
+ a[1] = -a[1];
+ m = n >> 1;
+ ks = 2 * nc / m;
+ kk = 0;
+ for (j = 2; j < m; j += 2) {
+ k = n - j;
+ kk += ks;
+ wkr = 0.5 - c[nc - kk];
+ wki = c[kk];
+ xr = a[j] - a[k];
+ xi = a[j + 1] + a[k + 1];
+ yr = wkr * xr + wki * xi;
+ yi = wkr * xi - wki * xr;
+ a[j] -= yr;
+ a[j + 1] = yi - a[j + 1];
+ a[k] += yr;
+ a[k + 1] = yi - a[k + 1];
+ }
+ a[m + 1] = -a[m + 1];
+ }
+ };
+
+
+ /**
+ * @internal
+ * @brief Concrete FFT implementation
+ */
+ typedef OouraFFT AudioFFTImplementation;
+
+
+#endif // AUDIOFFT_OOURA_USED
+
+
+ // ================================================================
+
+
+#ifdef AUDIOFFT_INTEL_IPP_USED
+
+
+ /**
+ * @internal
+ * @class IntelIppFFT
+ * @brief FFT implementation using the Intel Integrated Performance Primitives
+ */
+ class IntelIppFFT : public detail::AudioFFTImpl
+ {
+ public:
+ IntelIppFFT() :
+ detail::AudioFFTImpl(),
+ _size(0),
+ _operationalBufferSize(0),
+ _powerOf2(0),
+ _fftSpec(nullptr),
+ _fftSpecBuf(0),
+ _fftWorkBuf(0),
+ _operationalBuffer(nullptr)
+ {
+ ippInit();
+ }
+
+ IntelIppFFT(const IntelIppFFT&) = delete;
+ IntelIppFFT& operator=(const IntelIppFFT&) = delete;
+
+ virtual ~IntelIppFFT()
+ {
+ init(0);
+ }
+
+ virtual void init(size_t size) override
+ {
+ if (_fftSpec)
+ {
+ if (_fftWorkBuf) ippFree(_fftWorkBuf);
+ if (_fftSpecBuf) ippFree(_fftSpecBuf);
+ ippFree(_operationalBuffer);
+
+ _size = 0;
+ _operationalBufferSize = 0;
+ _powerOf2 = 0;
+ _fftSpec = 0;
+ }
+
+ if (size > 0)
+ {
+ _size = size;
+ _operationalBufferSize = _size + 2;
+ _powerOf2 = (int)(log((double)_size)/log(2.0));
+
+ // Query to get buffer sizes
+ int sizeFFTSpec,
+ sizeFFTInitBuf,
+ sizeFFTWorkBuf;
+ ippsFFTGetSize_R_32f(
+ _powerOf2,
+ IPP_FFT_NODIV_BY_ANY,
+ ippAlgHintAccurate,
+ &sizeFFTSpec,
+ &sizeFFTInitBuf,
+ &sizeFFTWorkBuf
+ );
+
+ Ipp8u* fftInitBuf;
+
+ // init buffers
+ _fftSpecBuf = ippsMalloc_8u(sizeFFTSpec);
+ _fftWorkBuf = ippsMalloc_8u(sizeFFTWorkBuf);
+ fftInitBuf = ippsMalloc_8u(sizeFFTInitBuf);
+
+ // Initialize FFT
+ ippsFFTInit_R_32f(
+ &_fftSpec,
+ _powerOf2,
+ IPP_FFT_NODIV_BY_ANY,
+ ippAlgHintAccurate,
+ _fftSpecBuf,
+ fftInitBuf
+ );
+ if (fftInitBuf) ippFree(fftInitBuf);
+
+ // init operational buffer
+ _operationalBuffer = ippsMalloc_32f(
+ _operationalBufferSize
+ );
+ }
+ }
+
+ virtual void fft(const float* data, float* re, float* im) override
+ {
+ size_t complexNumbersCount = _operationalBufferSize / 2;
+ ippsFFTFwd_RToCCS_32f(
+ data,
+ _operationalBuffer,
+ _fftSpec,
+ _fftWorkBuf
+ );
+
+ // no need to scale
+
+ size_t complexCounter = 0;
+ for (int i = 0; i < complexNumbersCount; ++i)
+ {
+ re[i] = _operationalBuffer[complexCounter++];
+ im[i] = _operationalBuffer[complexCounter++];
+ }
+ }
+
+ virtual void ifft(float* data, const float* re, const float* im) override
+ {
+ size_t complexNumbersCount = _operationalBufferSize / 2;
+
+ size_t complexCounter = 0;
+ for (int i = 0; i < complexNumbersCount; ++i)
+ {
+ _operationalBuffer[complexCounter++] = re[i];
+ _operationalBuffer[complexCounter++] = im[i];
+ }
+
+ ippsFFTInv_CCSToR_32f(
+ _operationalBuffer,
+ data,
+ _fftSpec,
+ _fftWorkBuf
+ );
+
+ // scaling
+ const float factor = 1.0f / static_cast(_size);
+ ippsMulC_32f_I(factor, data, _size);
+ }
+
+ private:
+ size_t _size;
+ size_t _operationalBufferSize;
+ size_t _powerOf2;
+ IppsFFTSpec_R_32f* _fftSpec;
+ Ipp8u* _fftSpecBuf;
+ Ipp8u* _fftWorkBuf;
+ Ipp32f* _operationalBuffer;
+ };
+
+
+ /**
+ * @internal
+ * @brief Concrete FFT implementation
+ */
+ typedef IntelIppFFT AudioFFTImplementation;
+
+
+#endif // AUDIOFFT_INTEL_IPP_USED
+
+
+ // ================================================================
+
+
+#ifdef AUDIOFFT_APPLE_ACCELERATE_USED
+
+
+ /**
+ * @internal
+ * @class AppleAccelerateFFT
+ * @brief FFT implementation using the Apple Accelerate framework internally
+ */
+ class AppleAccelerateFFT : public detail::AudioFFTImpl
+ {
+ public:
+ AppleAccelerateFFT() :
+ detail::AudioFFTImpl(),
+ _size(0),
+ _powerOf2(0),
+ _fftSetup(0),
+ _re(),
+ _im()
+ {
+ }
+
+ AppleAccelerateFFT(const AppleAccelerateFFT&) = delete;
+ AppleAccelerateFFT& operator=(const AppleAccelerateFFT&) = delete;
+
+ virtual ~AppleAccelerateFFT()
+ {
+ init(0);
+ }
+
+ virtual void init(size_t size) override
+ {
+ if (_fftSetup)
+ {
+ vDSP_destroy_fftsetup(_fftSetup);
+ _size = 0;
+ _powerOf2 = 0;
+ _fftSetup = 0;
+ _re.clear();
+ _im.clear();
+ }
+
+ if (size > 0)
+ {
+ _size = size;
+ _powerOf2 = 0;
+ while ((1 << _powerOf2) < _size)
+ {
+ ++_powerOf2;
+ }
+ _fftSetup = vDSP_create_fftsetup(_powerOf2, FFT_RADIX2);
+ _re.resize(_size / 2);
+ _im.resize(_size / 2);
+ }
+ }
+
+ virtual void fft(const float* data, float* re, float* im) override
+ {
+ const size_t size2 = _size / 2;
+ DSPSplitComplex splitComplex;
+ splitComplex.realp = re;
+ splitComplex.imagp = im;
+ vDSP_ctoz(reinterpret_cast(data), 2, &splitComplex, 1, size2);
+ vDSP_fft_zrip(_fftSetup, &splitComplex, 1, _powerOf2, FFT_FORWARD);
+ const float factor = 0.5f;
+ vDSP_vsmul(re, 1, &factor, re, 1, size2);
+ vDSP_vsmul(im, 1, &factor, im, 1, size2);
+ re[size2] = im[0];
+ im[0] = 0.0f;
+ im[size2] = 0.0f;
+ }
+
+ virtual void ifft(float* data, const float* re, const float* im) override
+ {
+ const size_t size2 = _size / 2;
+ ::memcpy(_re.data(), re, size2 * sizeof(float));
+ ::memcpy(_im.data(), im, size2 * sizeof(float));
+ _im[0] = re[size2];
+ DSPSplitComplex splitComplex;
+ splitComplex.realp = _re.data();
+ splitComplex.imagp = _im.data();
+ vDSP_fft_zrip(_fftSetup, &splitComplex, 1, _powerOf2, FFT_INVERSE);
+ vDSP_ztoc(&splitComplex, 1, reinterpret_cast(data), 2, size2);
+ const float factor = 1.0f / static_cast(_size);
+ vDSP_vsmul(data, 1, &factor, data, 1, _size);
+ }
+
+ private:
+ size_t _size;
+ size_t _powerOf2;
+ FFTSetup _fftSetup;
+ std::vector _re;
+ std::vector _im;
+ };
+
+
+ /**
+ * @internal
+ * @brief Concrete FFT implementation
+ */
+ typedef AppleAccelerateFFT AudioFFTImplementation;
+
+
+#endif // AUDIOFFT_APPLE_ACCELERATE_USED
+
+
+ // ================================================================
+
+
+#ifdef AUDIOFFT_FFTW3_USED
+
+
+ /**
+ * @internal
+ * @class FFTW3FFT
+ * @brief FFT implementation using FFTW3 internally (see fftw.org)
+ */
+ class FFTW3FFT : public detail::AudioFFTImpl
+ {
+ public:
+ FFTW3FFT() :
+ detail::AudioFFTImpl(),
+ _size(0),
+ _complexSize(0),
+ _planForward(0),
+ _planBackward(0),
+ _data(0),
+ _re(0),
+ _im(0)
+ {
+ }
+
+ FFTW3FFT(const FFTW3FFT&) = delete;
+ FFTW3FFT& operator=(const FFTW3FFT&) = delete;
+
+ virtual ~FFTW3FFT()
+ {
+ init(0);
+ }
+
+ virtual void init(size_t size) override
+ {
+ if (_size != size)
+ {
+ if (_size > 0)
+ {
+ fftwf_destroy_plan(_planForward);
+ fftwf_destroy_plan(_planBackward);
+ _planForward = 0;
+ _planBackward = 0;
+ _size = 0;
+ _complexSize = 0;
+
+ if (_data)
+ {
+ fftwf_free(_data);
+ _data = 0;
+ }
+
+ if (_re)
+ {
+ fftwf_free(_re);
+ _re = 0;
+ }
+
+ if (_im)
+ {
+ fftwf_free(_im);
+ _im = 0;
+ }
+ }
+
+ if (size > 0)
+ {
+ _size = size;
+ _complexSize = AudioFFT::ComplexSize(_size);
+ const size_t complexSize = AudioFFT::ComplexSize(_size);
+ _data = reinterpret_cast(fftwf_malloc(_size * sizeof(float)));
+ _re = reinterpret_cast(fftwf_malloc(complexSize * sizeof(float)));
+ _im = reinterpret_cast(fftwf_malloc(complexSize * sizeof(float)));
+
+ fftw_iodim dim;
+ dim.n = static_cast(size);
+ dim.is = 1;
+ dim.os = 1;
+ _planForward = fftwf_plan_guru_split_dft_r2c(1, &dim, 0, 0, _data, _re, _im, FFTW_MEASURE);
+ _planBackward = fftwf_plan_guru_split_dft_c2r(1, &dim, 0, 0, _re, _im, _data, FFTW_MEASURE);
+ }
+ }
+ }
+
+ virtual void fft(const float* data, float* re, float* im) override
+ {
+ ::memcpy(_data, data, _size * sizeof(float));
+ fftwf_execute_split_dft_r2c(_planForward, _data, _re, _im);
+ ::memcpy(re, _re, _complexSize * sizeof(float));
+ ::memcpy(im, _im, _complexSize * sizeof(float));
+ }
+
+ virtual void ifft(float* data, const float* re, const float* im) override
+ {
+ ::memcpy(_re, re, _complexSize * sizeof(float));
+ ::memcpy(_im, im, _complexSize * sizeof(float));
+ fftwf_execute_split_dft_c2r(_planBackward, _re, _im, _data);
+ detail::ScaleBuffer(data, _data, 1.0f / static_cast(_size), _size);
+ }
+
+ private:
+ size_t _size;
+ size_t _complexSize;
+ fftwf_plan _planForward;
+ fftwf_plan _planBackward;
+ float* _data;
+ float* _re;
+ float* _im;
+ };
+
+
+ /**
+ * @internal
+ * @brief Concrete FFT implementation
+ */
+ typedef FFTW3FFT AudioFFTImplementation;
+
+
+#endif // AUDIOFFT_FFTW3_USED
+
+
+ // =============================================================
+
+
+ AudioFFT::AudioFFT() :
+ _impl(new AudioFFTImplementation())
+ {
+ }
+
+
+ AudioFFT::~AudioFFT()
+ {
+ }
+
+
+ void AudioFFT::init(size_t size)
+ {
+ assert(detail::IsPowerOf2(size));
+ _impl->init(size);
+ }
+
+
+ void AudioFFT::fft(const float* data, float* re, float* im)
+ {
+ _impl->fft(data, re, im);
+ }
+
+
+ void AudioFFT::ifft(float* data, const float* re, const float* im)
+ {
+ _impl->ifft(data, re, im);
+ }
+
+
+ size_t AudioFFT::ComplexSize(size_t size)
+ {
+ return (size / 2) + 1;
+ }
+
+} // End of namespace
+
+
+#endif // Header guard
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/iir_filter.hpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/iir_filter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3906806350e091d7836b88050316e4036a88a4a9
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/iir_filter.hpp
@@ -0,0 +1,375 @@
+#pragma once
+
+#ifndef SERVICESUPERVISOR_IIR_FILTER_H
+#define SERVICESUPERVISOR_IIR_FILTER_H
+
+//E(t,f) is computed using a first-order in-finite impulse response (IIR) filter
+#define UES_IIR_I
+//#define UES_IIR_II
+
+#ifdef UES_IIR_I
+
+class IIR_I
+{
+private:
+ double *m_pNum;
+ double *m_pDen;
+ double *m_px;
+ double *m_py;
+ int m_num_order;
+ int m_den_order;
+public:
+ IIR_I();
+ ~IIR_I();
+ void reset();
+ void setPara(double num[], int num_order, double den[], int den_order);
+ void resp(double data_in[], int m, double data_out[], int n);
+ void filter(double data_in[], double data_out[], int len);
+};
+/** \brief 将滤波器的内部状态清零,滤波器的系数保留
+ * \return
+ */
+void IIR_I::reset()
+{
+ for(int i = 0; i <= m_num_order; i++)
+ {
+ m_pNum[i] = 0.0;
+ }
+ for(int i = 0; i <= m_den_order; i++)
+ {
+ m_pDen[i] = 0.0;
+ }
+}
+IIR_I::IIR_I()
+{
+ m_pNum = NULL;
+ m_pDen = NULL;
+ m_px = NULL;
+ m_py = NULL;
+ m_num_order = -1;
+ m_den_order = -1;
+};
+IIR_I::~IIR_I()
+{
+ delete[] m_pNum;
+ delete[] m_pDen;
+ delete[] m_px;
+ delete[] m_py;
+ m_pNum = NULL;
+ m_pDen = NULL;
+ m_px = NULL;
+ m_py = NULL;
+};
+
+/** \brief
+ *
+ * \param num 分子多项式的系数,升序排列,num[0] 为常数项
+ * \param m 分子多项式的阶数
+ * \param den 分母多项式的系数,升序排列,den[0] 为常数项
+ * \param m 分母多项式的阶数
+ * \return
+ */
+void IIR_I::setPara(double num[], int num_order, double den[], int den_order)
+{
+ delete[] m_pNum;
+ delete[] m_pDen;
+ delete[] m_px;
+ delete[] m_py;
+ m_pNum = new double[num_order + 1];
+ m_pDen = new double[den_order + 1];
+ m_num_order = num_order;
+ m_den_order = den_order;
+ m_px = new double[num_order + 1];
+ m_py = new double[den_order + 1];
+ for(int i = 0; i < m_num_order; i++)
+ {
+ m_pNum[i] = num[i];
+ m_px[i] = 0.0;
+ }
+ m_pNum[m_num_order] = 0.0;
+ m_px[m_num_order] = 0.0;
+ for(int i = 0; i < m_den_order; i++)
+ {
+ m_pDen[i] = den[i];
+ m_py[i] = 0.0;
+ }
+ m_pDen[m_den_order] = 0.0;
+ m_py[m_den_order] = 0.0;
+}
+
+/** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态
+ * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1]
+ * \param data_out 滤波器的输出
+ * \param M 输入数据的长度
+ * \param N 输出数据的长度
+ * \return
+ */
+void IIR_I::resp(double data_in[], int M, double data_out[], int N)
+{
+ int i, k, il;
+ for(k = 0; k < N; k++)
+ {
+ data_out[k] = 0.0;
+ for(i = 0; i <= m_num_order; i++)
+ {
+ if( k - i >= 0)
+ {
+ il = ((k - i) < M) ? (k - i) : (M - 1);
+ data_out[k] = data_out[k] + m_pNum[i] * data_in[il];
+ }
+ }
+ for(i = 1; i <= m_den_order; i++)
+ {
+ if( k - i >= 0)
+ {
+ data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];
+ }
+ }
+ }
+}
+
+/** \brief 滤波函数,采用直接I型结构
+ * 注:该函数内部修改过,移植librosa.pcen时参照scipy.signal.lfilter所做的设计。
+ *
+ * \param data_in[] 输入数据
+ * \param data_out[] 保存滤波后的数据
+ * \param len 数组的长度
+ * \return
+ */
+void IIR_I::filter(double data_in[], double data_out[], int len)
+{
+ int i, k;
+ m_py[1] = 1; //修改的地方,因为公式中y[n-k],当为第一个元素时会出现y[-1],pcen中y[-1]会被认为为1。
+ for(k = 0; k < len; k++)
+ {
+ m_px[0] = data_in[k];
+ m_py[0] = 0.0;
+ for(i = 0; i <= m_num_order; i++)
+ {
+ m_py[0] = m_py[0] + m_pNum[i] * m_px[i];
+ }
+ for(i = 1; i <= m_den_order; i++)
+ {
+ m_py[0] = m_py[0] - m_pDen[i] * m_py[i];
+ }
+ for(i = m_num_order; i >= 1; i--)
+ {
+ m_px[i] = m_px[i-1];
+ }
+ for(i = m_den_order; i >= 1; i--)
+ {
+ m_py[i] = m_py[i-1];
+ }
+ data_out[k] = m_py[0];
+ }
+}
+
+#endif
+
+#ifdef UES_IIR_II
+
+/**< IIR 滤波器直接II型实现 */
+class IIR_II
+{
+public:
+ IIR_II();
+ void reset();
+ void setPara(double num[], int num_order, double den[], int den_order);
+ void resp(double data_in[], int m, double data_out[], int n);
+ double filter(double data);
+ void filter(double data[], int len);
+ void filter(double data_in[], double data_out[], int len);
+protected:
+private:
+ double *m_pNum;
+ double *m_pDen;
+ double *m_pW;
+ int m_num_order;
+ int m_den_order;
+ int m_N;
+};
+
+class IIR_BODE
+{
+private:
+ double *m_pNum;
+ double *m_pDen;
+ int m_num_order;
+ int m_den_order;
+ std::complex poly_val(double p[], int order, double omega);
+public:
+ IIR_BODE();
+ void setPara(double num[], int num_order, double den[], int den_order);
+ std::complex bode(double omega);
+ void bode(double omega[], int n, std::complex resp[]);
+};
+
+IIR_II::IIR_II()
+{
+//ctor
+m_pNum = NULL;
+m_pDen = NULL;
+m_pW = NULL;
+m_num_order = -1;
+m_den_order = -1;
+m_N = 0;
+};
+
+/** \brief 将滤波器的内部状态清零,滤波器的系数保留
+ * \return
+ */
+void IIR_II::reset()
+{
+ for(int i = 0; i < m_N; i++)
+ {
+ m_pW[i] = 0.0;
+ }
+}
+/** \brief
+ *
+ * \param num 分子多项式的系数,升序排列,num[0] 为常数项
+ * \param m 分子多项式的阶数
+ * \param den 分母多项式的系数,升序排列,den[0] 为常数项
+ * \param m 分母多项式的阶数
+ * \return
+ */
+void IIR_II::setPara(double num[], int num_order, double den[], int den_order)
+{
+ delete[] m_pNum;
+ delete[] m_pDen;
+ delete[] m_pW;
+ m_num_order = num_order;
+ m_den_order = den_order;
+ m_N = fmax(num_order, den_order) + 1;
+ m_pNum = new double[m_N];
+ m_pDen = new double[m_N];
+ m_pW = new double[m_N];
+ for(int i = 0; i < m_N; i++)
+ {
+ m_pNum[i] = 0.0;
+ m_pDen[i] = 0.0;
+ m_pW[i] = 0.0;
+ }
+ for(int i = 0; i <= num_order; i++)
+ {
+ m_pNum[i] = num[i];
+ }
+ for(int i = 0; i <= den_order; i++)
+ {
+ m_pDen[i] = den[i];
+ }
+}
+/** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态
+ * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1]
+ * \param data_out 滤波器的输出
+ * \param M 输入数据的长度
+ * \param N 输出数据的长度
+ * \return
+ */
+void IIR_II::resp(double data_in[], int M, double data_out[], int N)
+{
+ int i, k, il;
+ for(k = 0; k < N; k++)
+ {
+ data_out[k] = 0.0;
+ for(i = 0; i <= m_num_order; i++)
+ {
+ if( k - i >= 0)
+ {
+ il = ((k - i) < M) ? (k - i) : (M - 1);
+ data_out[k] = data_out[k] + m_pNum[i] * data_in[il];
+ }
+ }
+ for(i = 1; i <= m_den_order; i++)
+ {
+ if( k - i >= 0)
+ {
+ data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];
+ }
+ }
+ }
+}
+/** \brief 滤波函数,采用直接II型结构
+ *
+ * \param data 输入数据
+ * \return 滤波后的结果
+ */
+double IIR_II::filter(double data)
+{
+ m_pW[0] = data;
+ for(int i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
+ {
+ m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
+ }
+ data = 0.0;
+ for(int i = 0; i <= m_num_order; i++)
+ {
+ data = data + m_pNum[i] * m_pW[i];
+ }
+ for(int i = m_N - 1; i >= 1; i--)
+ {
+ m_pW[i] = m_pW[i-1];
+ }
+ return data;
+}
+/** \brief 滤波函数,采用直接II型结构
+ *
+ * \param data[] 传入输入数据,返回时给出滤波后的结果
+ * \param len data[] 数组的长度
+ * \return
+ */
+void IIR_II::filter(double data[], int len)
+{
+ int i, k;
+ for(k = 0; k < len; k++)
+ {
+ m_pW[0] = data[k];
+ for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
+ {
+ m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
+ }
+ data[k] = 0.0;
+ for(i = 0; i <= m_num_order; i++)
+ {
+ data[k] = data[k] + m_pNum[i] * m_pW[i];
+ }
+
+ for(i = m_N - 1; i >= 1; i--)
+ {
+ m_pW[i] = m_pW[i-1];
+ }
+ }
+}
+/** \brief 滤波函数,采用直接II型结构
+ *
+ * \param data_in[] 输入数据
+ * \param data_out[] 保存滤波后的数据
+ * \param len 数组的长度
+ * \return
+ */
+void IIR_II::filter(double data_in[], double data_out[], int len)
+{
+ int i, k;
+ for(k = 0; k < len; k++)
+ {
+ m_pW[0] = data_in[k];
+ for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
+ {
+ m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
+ }
+ data_out[k] = 0.0;
+ for(i = 0; i <= m_num_order; i++)
+ {
+ data_out[k] = data_out[k] + m_pNum[i] * m_pW[i];
+ }
+
+ for(i = m_N - 1; i >= 1; i--)
+ {
+ m_pW[i] = m_pW[i-1];
+ }
+ }
+}
+
+#endif
+
+#endif //SERVICESUPERVISOR_IIR_FILTER_H
diff --git a/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/mfcc.hpp b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/mfcc.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..19b561946a3553b9a5398d67bf7ec379f308ba10
--- /dev/null
+++ b/duix-android/dh_aigc_android/duix-sdk/src/main/cpp/aisdk/mfcc/mfcc.hpp
@@ -0,0 +1,441 @@
+#pragma once
+
+#include "AudioFFT.hpp"
+//#include"../third/numcpp/NumCpp.hpp"
+#include "opencv2/opencv.hpp"
+#include "iir_filter.hpp"
+#include "sas_util.h"
+
+int nSamplesPerSec = 16000; //采样率(每秒样本数) //Sample rate.(keda, thchs30, aishell)
+int length_DFT = 1024;//2048; //傅里叶点数 //fft points (samples)
+int hop_length = 160;//int(0.05 * nSamplesPerSec); //步长 //下一帧取数据相对于这一帧的右偏移量
+int win_length = 800;// int(0.1 * nSamplesPerSec); //帧长 //假设16000采样率,则取取0.1s时间的数据
+int number_filterbanks = 80; //过滤器数量 //Number of Mel banks to generate
+float preemphasis = 0.97; //预加重(高通滤波器比例值)
+int max_db = 100;
+int ref_db = 20;
+int r = 1; //librosa里的r=1,暂未深入分析其作用
+double pi = 3.14159265358979323846;
+
+cv::Mat_ mel_basis;
+cv::Mat_ hannWindow;
+
+std::shared_ptr filter;
+
+//"""Convert Hz to Mels"""
+double hz_to_mel(double frequencies, bool htk = false) {
+ if (htk) {
+ return 2595.0 * log10(1.0 + frequencies / 700.0);
+ }
+ // Fill in the linear part
+ double f_min = 0.0;
+ double f_sp = 200.0 / 3;
+ double mels = (frequencies - f_min) / f_sp;
+ // Fill in the log-scale part
+ double min_log_hz = 1000.0; // beginning of log region (Hz)
+ double min_log_mel = (min_log_hz - f_min) / f_sp; // same (Mels)
+ double logstep = log(6.4) / 27.0; // step size for log region
+
+ // 对照Python平台的librosa库,移植
+ //如果是多维数列
+// if (frequencies.ndim) {
+// // If we have array data, vectorize
+// log_t = (frequencies >= min_log_hz)
+// mels[log_t] = min_log_mel + np.log(frequencies[log_t] / min_log_hz) / logstep
+// } else
+ if (frequencies >= min_log_hz) {
+ // If we have scalar data, heck directly
+ mels = min_log_mel + log(frequencies / min_log_hz) / logstep;
+ }
+ return mels;
+}
+
+//"""Convert mel bin numbers to frequencies"""
+cv::Mat_ mel_to_hz(cv::Mat_ mels, bool htk = false) {
+// if (htk) {
+// return //python://700.0 * (10.0**(mels / 2595.0) - 1.0);
+// }
+ // Fill in the linear scale
+ double f_min = 0.0;
+ double f_sp = 200.0 / 3;
+ cv::Mat_ freqs = mels * f_sp + f_min;
+ // And now the nonlinear scale
+ double min_log_hz = 1000.0; // beginning of log region (Hz)
+ double min_log_mel = (min_log_hz - f_min) / f_sp; // same (Mels)
+ double logstep = log(6.4) / 27.0; // step size for log region
+ // 对照Python平台的librosa库,移植
+ //if (mels.ndim) {
+ // If we have vector data, vectorize
+ cv::Mat_ log_t = (mels >= min_log_mel);
+ for (int i = 0; i < log_t.cols; i++) {
+ if (log_t(0, i)) {
+ freqs(0, i) = cv::exp((mels(0, i) - min_log_mel) * logstep) * min_log_hz;
+ }
+ }
+ //}
+ return freqs;
+}
+
+// 生成等差数列,类似np.linspace
+cv::Mat_ cvlinspace(double min_, double max_, int length) {
+ auto cvmat = cv::Mat_(1, length);
+ for (int i = 0; i < length; i++) {
+ cvmat(0, i) = ((max_ - min_) / (length - 1) * i) + min_;
+ }
+ return cvmat;
+}
+
+//"""Create a Filterbank matrix to combine FFT bins into Mel-frequency bins"""
+cv::Mat_ mel_spectrogram_create(int nps, int n_fft, int n_mels) {
+ double f_max = nps / 2.0;
+ double f_min = 0;
+ int n_fft_2 = 1 + n_fft / 2;
+ // Initialize the weights
+ //auto weights = nc::zeros(nc::uint32(n_mels), nc::uint32(n_fft_2));
+ auto weights = cv::Mat_(n_mels, n_fft_2, 0.0);
+ // Center freqs of each FFT bin
+ //auto fftfreqs_ = nc::linspace(f_min, f_max, nc::uint32(n_fft_2), true);
+ auto fftfreqs = cvlinspace(f_min, f_max, n_fft_2);
+
+ // 'Center freqs' of mel bands - uniformly spaced between limits
+ double min_mel = hz_to_mel(f_min, false);
+ double max_mel = hz_to_mel(f_max, false);
+ //auto mels_ = nc::linspace(min_mel, max_mel, nc::uint32(n_mels + 2));
+ auto mels = cvlinspace(min_mel, max_mel, n_mels + 2);
+ auto mel_f = mel_to_hz(mels, false);
+
+ //auto fdiff_ = nc::diff(mel_f_); //沿着指定轴计算第N维的离散差值(后一个元素减去前一个元素)
+ cv::Mat_ d1(1, mel_f.cols * mel_f.rows - 1, (double *) (mel_f.data) + 1);
+ cv::Mat_ d2(1, mel_f.cols * mel_f.rows - 1, (double *) (mel_f.data));
+ cv::Mat_ fdiff = d1 - d2;
+
+ //auto ramps = nc::subtract.outer(mel_f, fftfreqs); //nc没有subtract.outer
+ //nc::NdArray ramps = nc::zeros(mel_f.cols, fftfreqs.cols);
+ auto ramps = cv::Mat_(mel_f.cols, fftfreqs.cols);
+ for (int i = 0; i < mel_f.cols; i++) {
+ for (int j = 0; j < fftfreqs.cols; j++) {
+ ramps(i, j) = mel_f(0, i) - fftfreqs(0, j);
+ }
+ }
+
+ for (int i = 0; i < n_mels; i++) {
+ // lower and upper slopes for all bins
+ //auto ramps_1 = nc::NdArray(1, ramps.cols);
+ auto ramps_1 = cv::Mat_(1, ramps.cols);
+ for (int j = 0; j < ramps.cols; j++) {
+ ramps_1(0, j) = ramps(i, j);
+ }
+ //auto ramps_2 = nc::NdArray(1, ramps.cols);
+ auto ramps_2 = cv::Mat_(1, ramps.cols);
+ for (int j = 0; j < ramps.cols; j++) {
+ ramps_2(0, j) = ramps(i + 2, j);
+ }
+ cv::Mat_ lower = ramps_1 * -1 / fdiff(0, i);
+ cv::Mat_ upper = ramps_2 / fdiff(0, i + 1);
+ // .. then intersect them with each other and zero
+ //auto weights_1 = nc::maximum(nc::zeros(1, ramps.cols), nc::minimum(lower, upper));
+ cv::Mat c1 = lower;//(cv::Mat_(1,5) << 1,2,-3,4,-5);
+ cv::Mat c2 = upper;
+ cv::Mat weights_1 = cv::Mat_(1, lower.cols);
+ cv::min(c1, c2, weights_1);
+ cv::max(weights_1, 0, weights_1);
+ for (int j = 0; j < n_fft_2; j++) {
+ weights(i, j) = weights_1.at(0, j);
+ }
+ }
+
+ // Slaney-style mel is scaled to be approx constant energy per channel
+ auto enorm = cv::Mat_(1, n_mels);
+ for (int j = 0; j < n_mels; j++) {
+ enorm(0, j) = 2.0 / (mel_f(0, j + 2) - mel_f(0, j));
+ }
+ for (int j = 0; j < n_mels; j++) {
+ for (int k = 0; k < n_fft_2; k++) {
+ weights(j, k) *= enorm(0, j);
+ }
+ }
+ return weights;
+}
+
+//"""Short-time Fourier transform (STFT)""": 默认center=True, window='hann', pad_mode='reflect'
+cv::Mat_ MagnitudeSpectrogram(const cv::Mat_ *emphasis_data, int n_fft = 2048, int hop_length = 0,
+ int win_length = 0) {
+ if (win_length == 0) {
+ win_length = n_fft;
+ }
+ if (hop_length == 0) {
+ hop_length = win_length / 4;
+ }
+
+ // reflect对称填充
+ int pad_lenght = n_fft / 2;
+ // 使用opencv里的copyMakeBorder来完成reflect填充
+ cv::Mat_ cv_padbuffer;
+ cv::copyMakeBorder(*emphasis_data, cv_padbuffer, 0, 0, pad_lenght, pad_lenght, cv::BORDER_REFLECT_101);
+
+ // windowing加窗:将每一帧乘以汉宁窗,以增加帧左端和右端的连续性。
+ // 生成一个1600长度的hannWindow,并居中到2048长度的
+ if (hannWindow.empty()) {
+ hannWindow = cv::Mat_(1, n_fft, 0.0f);
+ int insert_cnt = 0;
+ if (n_fft > win_length) {
+ insert_cnt = (n_fft - win_length) / 2;
+ } else {
+ //std::cout << "\tn_fft:" << n_fft << " > win_length:" << n_fft << std::endl;
+ return cv::Mat_(0, 0);
+ }
+ for (int k = 1; k <= win_length; k++) {
+ hannWindow(0, k - 1 + insert_cnt) = float(0.5 * (1 - cos(2 * pi * k / (win_length + 1))));
+ }
+ }
+ // opencv虽然有Hann窗生成函数,但是必须要求width > 1,height > 1
+ //cv::Mat_ cv_hannWindow;
+ //cv::createHanningWindow(cv_hannWindow, cv::Size(1, win_length), CV_64FC1);
+
+ int size = cv_padbuffer.rows * cv_padbuffer.cols;//padbuffer.size()
+ int number_feature_vectors = (size - n_fft) / hop_length + 1;
+ int number_coefficients = n_fft / 2 + 1;
+ cv::Mat_ feature_vector(number_feature_vectors, number_coefficients, 0.0f);
+
+ audiofft::AudioFFT fft; //将FFT初始化放在循环外,可达到最优速度
+ fft.init(size_t(n_fft));
+ for (int i = 0; i <= size - n_fft; i += hop_length) {
+ // 每次取一段数据
+ cv::Mat_ framef = cv::Mat_(1, n_fft, (float *) (cv_padbuffer.data) + i).clone();
+ // 加hann窗
+ framef = framef.mul(hannWindow);
+
+ // 复数:Xrf实数,Xif虚数。
+ cv::Mat_ Xrf(1, number_coefficients);
+ cv::Mat_ Xif(1, number_coefficients);
+ fft.fft((float *) (framef.data), (float *) (Xrf.data), (float *) (Xif.data));
+
+ // 求模
+ cv::pow(Xrf, 2, Xrf);
+ cv::pow(Xif, 2, Xif);
+ cv::Mat_ cv_feature(1, number_coefficients, &(feature_vector[i / hop_length][0]));
+ cv::sqrt(Xrf + Xif, cv_feature);
+ }
+ cv::Mat_ cv_mag;
+ cv::transpose(feature_vector, cv_mag);
+ cv::Mat_ mag;
+ cv_mag.convertTo(mag, CV_64FC1);
+
+ return mag;
+}
+
+/*********************************************
+ * 名称:log_mel
+ * 功能:传入音频数据,输出log-mel方式提取的特征数据。
+ * 参数:@ifile_data 传入的音频数据
+ * @nSamples_per_sec 音频采样率
+ * 返回:cv::Mat_ 特征数据
+*********************************************/
+//cv::Mat_ log_mel(std::vector &ifile_data, int nSamples_per_sec) {
+int log_mel(float* ifile_data, int ifile_length,int nSamples_per_sec,float* ofile_data) {
+ if (nSamples_per_sec != nSamplesPerSec) {
+ //std::cout << R"(the "nSamples_per_sec" is not 16000.)" << std::endl;
+ return -1;//cv::Mat_(0, 0);
+ }
+ //int ifile_length = int(ifile_data.size() / 4);
+
+ // pre-emphasis 预加重 //高通滤波
+ //cv::Mat_ d1(1, ifile_length - 1, (float *) (ifile_data.data()) + 1);
+ //cv::Mat_ d2(1, ifile_length-1 , (float *) (ifile_data.data()));
+ cv::Mat_ d1(1, ifile_length - 1, (float *) (ifile_data) + 1);
+ cv::Mat_ d2(1, ifile_length-1 , (float *) (ifile_data));
+
+ //std::cout< cv_emphasis_data;
+
+ cv::hconcat(cv::Mat_::zeros(1, 1), d1 - d2 * preemphasis, cv_emphasis_data);
+ //cv::print(cv_emphasis_data);
+ //std::cout< cvlfilter_zi(cv::Mat_ b, cv::Mat_ a) {
+ if ((b.rows != 1) || (a.rows != 1)) {
+ //std::cout << "Numerator b and Denominator a must be 1-D." << std::endl;
+ }
+ if (a(0, 0) != 1) {
+ // Normalize the coefficients so a[0] == 1.
+ b = b / a(0, 0);
+ a = a / a(0, 0);
+ }
+ int len_a = a.cols * a.rows;
+ int len_b = b.cols * b.rows;
+ int n = len_a > len_b ? len_a : len_b;
+ if (len_a < n) {
+ cv::hconcat(a, cv::Mat_::zeros(1, n - len_a), a);
+ } else if (len_b < n) {
+ cv::hconcat(b, cv::Mat_::zeros(1, n - len_b), b);
+ }
+ return cv::Mat_(0, 0);
+}
+/*
+// scipy.signal.lfilter()
+// Filter data along one-dimension with an IIR or FIR filter.
+cv::Mat_ cvlfilter(cv::Mat_ &b, cv::Mat_ &a, cv::Mat_ &x,
+ cv::Mat_ &zi, int axis = -1) {
+ if (a.rows * a.cols == 1) {
+ // This path only supports types fdgFDGO to mirror _linear_filter below.
+ // Any of b, a, x, or zi can set the dtype, but there is no default
+ // casting of other types; instead a NotImplementedError is raised.
+ // 后续如果需要,则进行补充
+ } else {
+ // return sigtools._linear_filter(b, a, x, axis, zi)
+ // sigtools._linear_filter()
+ // (y,Vf) = _linear_filter(b,a,X,Dim=-1,Vi=None) implemented using Direct Form II transposed flow diagram.
+ // If Vi is not given, Vf is not returned.
+ ;
+ }
+}
+*/
+/*********************************************
+ * 名称:pcen
+ * 功能:传入音频数据,输出pcen方式提取的特征数据。
+ * 参数:@ifile_data 传入的音频数据
+ * @nSamples_per_sec 音频采样率
+ * 返回:cv::Mat_ 特征数据
+*********************************************/
+cv::Mat_ pcen(std::vector &ifile_data, int nSamples_per_sec) {
+ //if (!(&ifile_data) || ifile_data.empty()) {
+ if (ifile_data.empty()) {
+ //std::cout << "error: invalid paramter: ifile_data" << std::endl;
+ return cv::Mat_(0, 0);
+ }
+ if (nSamples_per_sec != nSamplesPerSec) {
+// std::cout << R"(error: the "nSamples_per_sec" is not 16000.)" << std::endl;
+ return cv::Mat_(0, 0);
+ }
+ int ifile_length = int(ifile_data.size() / 4);
+ cv::Mat_ cv_emphasis_data(1, ifile_length, (float *) (ifile_data.data()));
+// std::cout< mel = mel_basis * mag;
+
+ // 计算pcen特征
+// double time_constant = 0.400;
+// int sr = 22050;
+// int hop_length = 512;
+// double t_frames = time_constant * sr / double(hop_length);
+// double b = (sqrt(1 + 4 * t_frames * t_frames) - 1) / (2 * t_frames * t_frames);
+// cv::Mat_ zi = (cv::Mat_(1, 1) << 0.94361056);
+//
+// cv::Mat_ in_b = (cv::Mat_(1, 1) << b);
+// cv::Mat_ in_a = (cv::Mat_(1, 2) << 1, b - 1);
+// cv::Mat_ zi = cvlfilter_zi(in_b, in_a);
+ // 第二个公式计算
+// cv::Mat_ S_smooth = cvlfilter(in_b, in_a, mel, zi);
+
+#if 1 // IIR滤波器
+ if (!filter) {
+ filter = std::make_shared();
+ double iir_b[1] = {0.05638943879134889};
+ double iir_a[2] = {1.0, -0.9436105612086512};
+ //filter.reset();
+ filter->setPara(iir_b, 1, iir_a, 2);
+ }
+ cv::Mat_ S_smooth = cv::Mat_(mel.rows, mel.cols);
+ for (int i = 0; i < mel.rows; i++) {
+ filter->filter(mel[i], S_smooth[i], mel.cols);
+ }
+
+#endif
+
+ // 第一个公式计算
+ double gain = 0.98;
+ double bias = 2.0;
+ double power = 0.5;
+ double eps = 1e-6;
+ //python: smooth = np.exp(-gain * (np.log(eps) + np.log1p(S_smooth / eps)))
+ cv::Mat_ S_smooth_log1p;
+ cv::log(S_smooth / eps + 1, S_smooth_log1p);
+ cv::Mat_ smooth;
+ cv::exp((S_smooth_log1p + cv::log(eps)) * (-gain), smooth);
+ //python: S_out = (bias ** power) * np.expm1(power * np.log1p(ref * smooth / bias))
+ cv::Mat_ smooth_log1p;
+ cv::Mat_ smooth_log1p_exp;
+ cv::log(mel.mul(smooth) / bias + 1, smooth_log1p);
+ cv::exp(power * smooth_log1p, smooth_log1p_exp);
+ cv::Mat_