Full Code of fanyuan/MyMp3Convert for AI

master 3c25cbd543da cached
100 files
875.2 KB
278.7k tokens
678 symbols
1 requests
Download .txt
Showing preview only (921K chars total). Download the full file or copy to clipboard to get everything.
Repository: fanyuan/MyMp3Convert
Branch: master
Commit: 3c25cbd543da
Files: 100
Total size: 875.2 KB

Directory structure:
gitextract_rnfvjqig/

├── .gitignore
├── README.md
├── app/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── build.gradle
│   ├── key02.keystore
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── java/
│   │   │       └── com/
│   │   │           └── convert/
│   │   │               └── mymp3convert/
│   │   │                   └── ExampleInstrumentedTest.java
│   │   ├── main/
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── convert/
│   │   │   │           └── mymp3convert/
│   │   │   │               ├── MainActivity.java
│   │   │   │               ├── MainActivity2.kt
│   │   │   │               ├── Mp3ConvertUtil.java
│   │   │   │               ├── Mp3ConvertUtilHelper.java
│   │   │   │               ├── MyTest.java
│   │   │   │               └── test/
│   │   │   │                   └── Demo.java
│   │   │   ├── jni/
│   │   │   │   ├── NativeMp3ConvertUtil.cpp
│   │   │   │   ├── NativeMp3ConvertUtil.cpp.bak
│   │   │   │   ├── NativeMp3ConvertUtil.h
│   │   │   │   ├── NativeMyTest.cpp
│   │   │   │   ├── com_convert_mymp3convert_Mp3ConvertUtil.h
│   │   │   │   ├── com_convert_mymp3convert_MyTest.h
│   │   │   │   └── libmp3lame/
│   │   │   │       ├── VbrTag.c
│   │   │   │       ├── VbrTag.h
│   │   │   │       ├── bitstream.c
│   │   │   │       ├── bitstream.h
│   │   │   │       ├── encoder.c
│   │   │   │       ├── encoder.h
│   │   │   │       ├── fft.c
│   │   │   │       ├── fft.h
│   │   │   │       ├── gain_analysis.c
│   │   │   │       ├── gain_analysis.h
│   │   │   │       ├── id3tag.c
│   │   │   │       ├── id3tag.h
│   │   │   │       ├── l3side.h
│   │   │   │       ├── lame-analysis.h
│   │   │   │       ├── lame.c
│   │   │   │       ├── lame.h
│   │   │   │       ├── lame_global_flags.h
│   │   │   │       ├── lameerror.h
│   │   │   │       ├── machine.h
│   │   │   │       ├── mpglib_interface.c
│   │   │   │       ├── newmdct.c
│   │   │   │       ├── newmdct.h
│   │   │   │       ├── presets.c
│   │   │   │       ├── psymodel.c
│   │   │   │       ├── psymodel.h
│   │   │   │       ├── quantize.c
│   │   │   │       ├── quantize.h
│   │   │   │       ├── quantize_pvt.c
│   │   │   │       ├── quantize_pvt.h
│   │   │   │       ├── reservoir.c
│   │   │   │       ├── reservoir.h
│   │   │   │       ├── set_get.c
│   │   │   │       ├── set_get.h
│   │   │   │       ├── tables.c
│   │   │   │       ├── tables.h
│   │   │   │       ├── takehiro.c
│   │   │   │       ├── util.c
│   │   │   │       ├── util.h
│   │   │   │       ├── vbrquantize.c
│   │   │   │       ├── vbrquantize.h
│   │   │   │       ├── version.c
│   │   │   │       └── version.h
│   │   │   ├── library/
│   │   │   │   └── AndroidManifest.xml
│   │   │   └── res/
│   │   │       ├── drawable/
│   │   │       │   └── ic_launcher_background.xml
│   │   │       ├── drawable-v24/
│   │   │       │   └── ic_launcher_foreground.xml
│   │   │       ├── layout/
│   │   │       │   ├── activity_main.xml
│   │   │       │   └── activity_main2.xml
│   │   │       ├── mipmap-anydpi-v26/
│   │   │       │   ├── ic_launcher.xml
│   │   │       │   └── ic_launcher_round.xml
│   │   │       ├── values/
│   │   │       │   ├── colors.xml
│   │   │       │   ├── strings.xml
│   │   │       │   └── themes.xml
│   │   │       └── values-night/
│   │   │           └── themes.xml
│   │   └── test/
│   │       └── java/
│   │           └── com/
│   │               └── convert/
│   │                   └── mymp3convert/
│   │                       └── ExampleUnitTest.java
│   └── 说明 .txt
├── build.gradle
├── demo/
│   ├── .gitignore
│   ├── build.gradle
│   ├── libs/
│   │   └── app-release.aar
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── convert/
│       │               └── demo/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── convert/
│       │   │           └── demo/
│       │   │               └── MainActivity.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── values/
│       │       │   ├── colors.xml
│       │       │   ├── strings.xml
│       │       │   └── themes.xml
│       │       └── values-night/
│       │           └── themes.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── convert/
│                       └── demo/
│                           └── ExampleUnitTest.java
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
.idea/
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties


================================================
FILE: README.md
================================================
# MyMp3Convert
mp3Convert
一个mp3转换库,基于lame3来实现

模块简介:
================================================
主要实现了wav格式向mp3格式的转投;  
只需要关注3个方法就好;  
为了项目简单直观实用,节省代码空间,本模块遵循单一职责原则,只做格式转换,把wav格式音频转换成mp3格式

使用场景:
================================================
 用于在客户端需要把编辑好的wav转换成mp3格式,这样可以在不过大损失音频效果的同时有效节省空间,通常情况下,10M大小的wav文件通过转换后可以生成1M大小的mp3文件;  
 比如:用户在客户端录制好pcm音频文件,并由该文件编辑得到了可播放的wav文件,又需要把wav文件上传服务器,或者存在本地,但是wav文件过大,需要占用过大网络,在增加耗电量的同时,也给了服务器带来了压力,这个时候可以把文件转换成mp3格式文件(至于pcm到wav格式的转换,wav文件的编辑、剪切、拼接、混音合成可以使用另一模块来实现 链接:https://github.com/fanyuan/AudioUtil )


 使用:
 ================================================
只需要调用Mp3ConvertUtilHelper里的3个公开方法即可;   
使用很简单,只要把本module下载后以Android studio导入工程项目,设为library估其他module依赖就好  
对于和native c语言的交互已在Mp3ConvertUtil中封装好,采用了外观模式;  
使用时只需要调用Mp3ConvertUtilHelper类的相3个关公开方法  

=====================华丽丽的分割线========================

3个相关方法如下:
================================================

    /**
     * wav转换成mp3
     * @param wavInPath    需要转换的wav源文件输入路径
     * @param mp3OutPath   转换完成后的mp3目标文件输出路径
     */
    public static void convertmp3(String wavInPath, String mp3OutPath)

    /**
     * wav转换成mp3
     * @param wavInPath    需要转换的wav源文件输入路径
     * @param mp3OutPath   转换完成后的mp3目标文件输出路径
     * @param callback     转换相关的回调
     */
    public static void convertmp3(String wavInPath, String mp3OutPath, Mp3ConvertUtil.ConvertListener callback)}

    /**
     * 获取转换进度
     * @param outPath  在多个任务并行时以输出路径为token来查询相关转换文件的转换进度
     * @return
     */
    public static int getProgress(String outPath)

 =====================华丽丽的分割线==========================
 
使用示例如下:  

温馨提示:使用时请在子线程中使用,为了演示方便直观就不过多封装了

不带转换回调的使用示例:
================================================
new Thread(){
            @Override
            public void run() {

                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/姑娘我爱你convert.wav";//"temp/test123.wav";
                String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/姑娘我爱你out123.mp3";
                Mp3ConvertUtilHelper.convertmp3(path,pathTaret);

            }
        }.start();
        
不带回调的获取转换进度的方式: 
================================================
String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/姑娘我爱你out123.mp3";

int progress = Mp3ConvertUtilHelper.getProgress(pathTaret);

带转换回调的使用示例:
================================================
new Thread(){
            @Override
            public void run() {

                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out测试.wav";//"temp/test123.wav";
                String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out测试789.mp3";
                Mp3ConvertUtilHelper.convertmp3(path, pathTaret, new Mp3ConvertUtil.ConvertListener() {
                    @Override
                    public void notifyConvertProgress(int progress) {
                        Log.d("ddebug","convertByHelper02 --- notifyConvertProgress = " + progress);
                    }

                    @Override
                    public void convertFinish() {
                        Log.d("ddebug","convertByHelper02 --- convertFinish");
                    }

                    @Override
                    public void convertError(String errorMsg) {
                        Log.d("ddebug","convertByHelper02 --- convertError --- " + errorMsg);
                    }
                });
                

            }

        }.start();
        
        

简单实用^_^



================================================
FILE: app/.gitignore
================================================
/build

================================================
FILE: app/CMakeLists.txt
================================================

#指定CMake构建本地库时所需的最小版本
cmake_minimum_required(VERSION 3.4.1)

#该变量为真时会创建完整版本的Makefile
set(CMAKE_VERBOSE_MAKEFILE on)
set(LAME_LIBMP3_DIR ${CMAKE_SOURCE_DIR}/src/main/jni/libmp3lame)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLOGTEST")
include_directories(${CMAKE_SOURCE_DIR}/src/main/jni/libmp3lame)
include_directories(${CMAKE_SOURCE_DIR}/src/main/jni)

include_directories(E/work/sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/include)
add_library( # Sets the name of the library. 将资源文件生成动态链接库(so文件)的库名称(文件名称:“lib" +设置的名称)
        hello

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).资源文件(C或C++)的相对位置
        src/main/jni/NativeMp3ConvertUtil.cpp
        src/main/jni/NativeMyTest.cpp)
# 这里用来添加一个库
add_library(# 这里设置so库的名称为native-lib
        libmp3lame
        # 这里设置该库为共享
        SHARED
        #源码文件
        ${LAME_LIBMP3_DIR}/bitstream.c
        ${LAME_LIBMP3_DIR}/encoder.c
        ${LAME_LIBMP3_DIR}/fft.c
        ${LAME_LIBMP3_DIR}/gain_analysis.c
        ${LAME_LIBMP3_DIR}/id3tag.c
        ${LAME_LIBMP3_DIR}/lame.c
        ${LAME_LIBMP3_DIR}/mpglib_interface.c
        ${LAME_LIBMP3_DIR}/newmdct.c
        ${LAME_LIBMP3_DIR}/presets.c
        ${LAME_LIBMP3_DIR}/psymodel.c
        ${LAME_LIBMP3_DIR}/quantize.c
        ${LAME_LIBMP3_DIR}/quantize_pvt.c
        ${LAME_LIBMP3_DIR}/reservoir.c
        ${LAME_LIBMP3_DIR}/set_get.c
        ${LAME_LIBMP3_DIR}/tables.c
        ${LAME_LIBMP3_DIR}/takehiro.c
        ${LAME_LIBMP3_DIR}/util.c
        ${LAME_LIBMP3_DIR}/vbrquantize.c
        ${LAME_LIBMP3_DIR}/VbrTag.c
        ${LAME_LIBMP3_DIR}/version.c
        )
find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log )

target_link_libraries( # Specifies the target library.将所有的add_library中的库链接起来,有多少个add_library成的库就将其添加到这里
        hello  #这个和add_library中的指定的so库名称一致
        libmp3lame
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib} )


================================================
FILE: app/build.gradle
================================================
//plugins {
//    id 'com.android.application'
//}
if(isAppLibrary.toBoolean()){
    apply plugin: 'com.android.library'
}else {
    apply plugin: 'com.android.application'
}
apply plugin: 'kotlin-android'
android {
    externalNativeBuild { cmake { version "3.10.2" } }
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {

        if(!isAppLibrary.toBoolean()){
            applicationId "com.convert.mymp3convert"
        }

        minSdkVersion 18
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                // 指定一些编译选项
                cppFlags "-std=c++11 -frtti -fexceptions"
                cFlags "-DSTDC_HEADERS"
                abiFilters 'armeabi-v7a','arm64-v8a','x86'//'armeabi',
            }
        }
        ndk{
            //moduleName"hello"       //生成的so文件名字,调用C程序的代码中会用到该名字
            abiFilters 'armeabi-v7a','arm64-v8a' , 'x86'//,'arm64-v8a',  'x86_64'//'armeabi',
        }
        signingConfigs {
            release {
                storeFile file("key02.keystore")
                storePassword "1qazxsw2"
                keyAlias "key02"
                keyPassword "1qazxsw2"
                v1SigningEnabled true
                v2SigningEnabled true
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
    signingConfigs {
        dev {
            storeFile file('E:\\work\\keyStore\\demo\\key02.keystore')
            storePassword '1qazxsw2'
            keyAlias 'key02'
            keyPassword '1qazxsw2'
        }
    }
    sourceSets{
        main{
            if(isAppLibrary.toBoolean()){
                manifest.srcFile 'src/main/library/AndroidManifest.xml'
            }else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }

        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            jniDebuggable true
            signingConfig signingConfigs.release
        }
        dev {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            jniDebuggable true
            debuggable true
            signingConfig signingConfigs.release
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

================================================
FILE: app/proguard-rules.pro
================================================
# 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

================================================
FILE: app/src/androidTest/java/com/convert/mymp3convert/ExampleInstrumentedTest.java
================================================
package com.convert.mymp3convert;

import android.content.Context;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
        assertEquals("com.convert.mymp3convert", appContext.getPackageName());
    }
}

================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.convert.mymp3convert">

    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyMp3Convert">
        <activity android:name=".MainActivity2"></activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: app/src/main/java/com/convert/mymp3convert/MainActivity.java
================================================
package com.convert.mymp3convert;

import android.Manifest;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import java.io.File;

public class MainActivity extends AppCompatActivity {

    TextView tv;
    String [] perms = {Manifest.permission.MODIFY_AUDIO_SETTINGS,Manifest.permission.RECORD_AUDIO,
            Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
        String msg = Mp3ConvertUtil.hello("test");
        tv.setText(msg);
        Log.d("ddebug","hello jni = " + msg);

        ActivityCompat.requestPermissions(this, perms, 123);
    }
    public void test(View v){
        String str = MyTest.test();
        tv.append("\n"+str);
        Log.d("ddebug","test str = " + "str" + "----" + Mp3ConvertUtil.getLameVer());
        //Mp3ConvertUtil.convertmp3("test.wav","demo.mp3");
    }
    public void convert(View v){
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out.wav";//"temp/test123.wav";
        String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out123.mp3";
        Mp3ConvertUtil.convertmp3(path,pathTaret);
    }
    public void convertByHelper01(View v){
//        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out.wav";//"temp/test123.wav";
//        String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out456.mp3";
//        Mp3ConvertUtilHelper.convertmp3(path,pathTaret);

        new Thread(){
            @Override
            public void run() {

                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/姑娘我爱你convert.wav";//"temp/test123.wav";
                String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/姑娘我爱你out123.mp3";
                Mp3ConvertUtilHelper.convertmp3(path,pathTaret);

            }
        }.start();
    }
    public void convertByHelper02(View v){
        new Thread(){
            @Override
            public void run() {

                String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out测试.wav";//"temp/test123.wav";
                String pathTaret = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "temp/out测试789.mp3";
                Mp3ConvertUtilHelper.convertmp3(path, pathTaret, new Mp3ConvertUtil.ConvertListener() {
                    @Override
                    public void notifyConvertProgress(int progress) {
                        Log.d("ddebug","convertByHelper02 --- notifyConvertProgress = " + progress);
                    }

                    @Override
                    public void convertFinish() {
                        Log.d("ddebug","convertByHelper02 --- convertFinish");
                    }

                    @Override
                    public void convertError(String errorMsg) {
                        Log.d("ddebug","convertByHelper02 --- convertError --- " + errorMsg);
                    }
                });

            }
        }.start();

    }
}

================================================
FILE: app/src/main/java/com/convert/mymp3convert/MainActivity2.kt
================================================
package com.convert.mymp3convert

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
    }
}

================================================
FILE: app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtil.java
================================================
package com.convert.mymp3convert;

import android.util.Log;

import java.util.concurrent.ConcurrentHashMap;

public class Mp3ConvertUtil {
    static {
        System.loadLibrary("hello");
        System.loadLibrary("libmp3lame");
    }

    public static native String hello(String msg);
    /**
     * 获取LAME的版本信息
     *
     * @return
     */
    public static native String getLameVer();
    /**
     * wav转换成mp3的本地方法
     *
     * @param wav
     * @param mp3
     */
    public static native void convertmp3(String wav, String mp3);

    /**
     * 转换接口回调
     */
    public interface ConvertListener{
        public void notifyConvertProgress(int progress);
        /**
         * 转换完成回调
         */
        public  void convertFinish();

        /**
         * 转换完成回调
         * @param errorMsg
         */
        public  void convertError(String errorMsg);
    }

    /**
     * 提供的一个空实现
     */
    public static class SimpleConvertListener implements ConvertListener{

        @Override
        public void notifyConvertProgress(int progress) {

        }

        @Override
        public void convertFinish() {

        }

        @Override
        public void convertError(String errorMsg) {

        }
    }
    /**
     * 保存进度的地方
     */
    static ConcurrentHashMap<String,ConvertListener> mConvertCallbacks;
    /**
     * 保存进度的地方
     */
    static ConcurrentHashMap<String,Integer> mProgresses;


    /**
     * 注册转换回调类
     * @param mp3TargetPath
     * @param callback
     */
    protected static void registerCallback(String mp3TargetPath,ConvertListener callback){
        if(mConvertCallbacks == null){
            mConvertCallbacks = new ConcurrentHashMap<String, ConvertListener>();
        }
        mConvertCallbacks.put(mp3TargetPath,callback);
    }

    /**
     * 移除转换回调类
     * @param mp3TargetPath
     */
    private static void removeCallback(String mp3TargetPath){
        if(mConvertCallbacks == null){
            return;
        }
        if(mConvertCallbacks.containsKey(mp3TargetPath)){
            mConvertCallbacks.remove(mp3TargetPath);
        }
    }
    /**
     * 设置进度的方法
     * @param outPath
     */
    private static void setProgress(String outPath,int progress){
        if(mProgresses == null){
            mProgresses = new ConcurrentHashMap<String, Integer>();
        }
        mProgresses.put(outPath,progress);
        Log.d("ddebug","---setProgress---" + outPath + "=" + progress);
    }
    /**
     * 获取进度的方法
     * @param outPath
     * @return
     */
    protected static int getProgress(String outPath){
        if(mProgresses == null){
            return -1;
        }
        if(!mProgresses.containsKey(outPath)){
            return -1;
        }
        int progress = mProgresses.get(outPath);
        Log.d("ddebug","---getProgress---" + outPath + "=" + progress);
        return progress;
    }

    /**
     * 移除相关进度条目的方法
     *
     * @param outPath
     */
    private static void removeProgress(String outPath){
        if(mProgresses == null){
            return;
        }
        mProgresses.remove(outPath);
        Log.d("ddebug","---removeProgress---" + outPath);
    }
    /**
     * 日志打印方法,提供给C语言调用
     *
     * @param
     */
    public static void nativeLog(String logTag,String logMsg) {
        Log.d(logTag,"java nativeLog:" + logMsg);
    }
    /**
     * 设置进度条的进度,提供给C语言调用
     *
     * @param progress
     */
    public static void setConvertProgress(int progress,String outPath) {
        setProgress(outPath,progress);
        if(mConvertCallbacks == null){
            mConvertCallbacks = new ConcurrentHashMap<String, ConvertListener>();
        }
        if(mConvertCallbacks.containsKey(outPath)){
            mConvertCallbacks.get(outPath).notifyConvertProgress(progress);
        }
        Log.d("ddebug","转换进度为:"+ progress);
    }
    /**
     * 转换完成回调,提供给C语言调用
     *
     * @param outPath
     */
    public static void convertFinish(String outPath) {
        removeProgress(outPath);
        if(mConvertCallbacks == null){
            return;
        }
        if(mConvertCallbacks.containsKey(outPath)){
            mConvertCallbacks.get(outPath).convertFinish();
            removeCallback(outPath);
        }
        Log.d("ddebug","转换完成  convertFinish:"+ outPath);
    }
    /**
     * 转换完成回调,提供给C语言调用
     *
     * @param outPath
     */
    public static void convertError(String errorMsg,String outPath) {
        removeProgress(outPath);

        if(mConvertCallbacks == null){
            return;
        }
        if(mConvertCallbacks.containsKey(outPath)){
            mConvertCallbacks.get(outPath).convertError(errorMsg);
            removeCallback(outPath);
        }
        Log.d("ddebug","java convertError:" + errorMsg + " --- " + outPath);
    }

}


================================================
FILE: app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtilHelper.java
================================================
package com.convert.mymp3convert;

public class Mp3ConvertUtilHelper {
    /**
     * 获取版本号
     * @return
     */
    public static String getVer(){
        return Mp3ConvertUtil.getLameVer();
    }

    /**
     * wav转换成mp3
     * @param wavInPath   需要转换的wav源文件输入路径
     * @param mp3OutPath  转换完成后的mp3目标文件输出路径
     */
    public static void convertmp3(String wavInPath, String mp3OutPath){
        Mp3ConvertUtil.convertmp3(wavInPath,mp3OutPath);
    }

    /**
     * wav转换成mp3
     * @param wavInPath   需要转换的wav源文件输入路径
     * @param mp3OutPath  转换完成后的mp3目标文件输出路径
     * @param callback    转换相关的回调
     */
    public static void convertmp3(String wavInPath, String mp3OutPath, Mp3ConvertUtil.ConvertListener callback){
        Mp3ConvertUtil.registerCallback(mp3OutPath,callback);
        Mp3ConvertUtil.convertmp3(wavInPath,mp3OutPath);
    }
    /**
     * 获取转换进度
     * @param outPath  在多个任务并行时以输出路径为token来查询相关转换文件的转换进度
     * @return
     */
    public static int getProgress(String outPath){
        return Mp3ConvertUtil.getProgress(outPath);
    }
}


================================================
FILE: app/src/main/java/com/convert/mymp3convert/MyTest.java
================================================
package com.convert.mymp3convert;

public class MyTest {
    public static native String test();
}


================================================
FILE: app/src/main/java/com/convert/mymp3convert/test/Demo.java
================================================
package com.convert.mymp3convert.test;

import com.convert.mymp3convert.Mp3ConvertUtil;

public class Demo {
    private void test(){
        //Mp3ConvertUtil.registerCallback("",null);
    }
}


================================================
FILE: app/src/main/jni/NativeMp3ConvertUtil.cpp
================================================
//
// Created by shaomingfa on 2021/1/14.
//

#include <string>
#include "libmp3lame/lame.h"

#include <jni.h>

#include<stdio.h>
#include<malloc.h>
#include<lame.h>
#include<android/log.h>
#include "libmp3lame/lame.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>


#include "NativeMp3ConvertUtil.h"
#include "com_convert_mymp3convert_Mp3ConvertUtil.h"
#define LOG_TAG "System.out.c"
/**
 * 日志打印tag
 */
#define CONVERT_LOG_TAG "nativeTag"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)



#ifndef com_convert_mymp3convert_Mp3ConvertUtil
#define com_convert_mymp3convert_Mp3ConvertUtil
#ifdef __cplusplus
extern "C" {
#endif

/**
* 返回值 char* 这个代表char数组的首地址
*  Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
*/
char* Jstring2CStr(JNIEnv *env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env).FindClass( "java/lang/String"); //String
    jstring strencode = (*env).NewStringUTF( "GB2312"); // 得到一个java字符串 "GB2312"
    jmethodID mid = (*env).GetMethodID(clsstring, "getBytes",
                                       "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
    jbyteArray barr = (jbyteArray)(*env).CallObjectMethod(jstr, mid,
                                                          strencode); // String .getByte("GB2312");
    jsize alen = (*env).GetArrayLength( barr); // byte数组的长度
    jbyte* ba = (*env).GetByteArrayElements( barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1); //"\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env).ReleaseByteArrayElements(barr, ba, 0); //
    (*env).DeleteLocalRef(strencode);
    return rtn;
}
/**==============================================================================================================================================*/
/**
 * 调用java代码 更新程序的进度条
 */
void publishJavaProgress(JNIEnv * env, jobject obj, jint progress,jstring outPath) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    LOGI(" convert progress %d" , progress);

    //2 找到class 里面的方法定义

    jmethodID methodid = (*env).GetStaticMethodID(clazz,"setConvertProgress","(ILjava/lang/String;)V");//jmethodID methodid = (*env).GetMethodID(clazz, "setConvertProgress","(I)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");

    //3 .调用方法
    (*env).CallStaticVoidMethod(clazz, methodid, progress,outPath);//(*env).CallVoidMethod(obj, methodid, progress);
    //env -> CallVoidMethod(obj,methodid,progress);
    env->DeleteLocalRef(clazz);
    //env->DeleteLocalRef(methodid);
}
/**
 * 调用java代码 更新程序的进度条
 */
void convertFinish(JNIEnv * env, jstring mp3Path) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    const char *c = env->GetStringUTFChars(mp3Path, JNI_FALSE);
    LOGI(" convert finished %s" , c);
    env->ReleaseStringUTFChars(mp3Path,c);

    //2 找到class 里面的方法定义
    jmethodID methodid = (*env).GetStaticMethodID(clazz,"convertFinish","(Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find convertFinish methodid");

    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,mp3Path);
    env->DeleteLocalRef(clazz);
}
/**
 * 调用java代码 转换失败时调用
 */
void convertError(JNIEnv * env,jstring msg,jstring mp3Path) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }

    const char *c = (*env).GetStringUTFChars(mp3Path, JNI_FALSE);
    LOGI(" convert error %s" , c);
    (*env).ReleaseStringUTFChars(mp3Path,c);

    //2 找到class 里面的方法定义

    jmethodID methodid = (*env).GetStaticMethodID(clazz,"convertError",
                                                  "(Ljava/lang/String;Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");

    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,msg,mp3Path);
    env->DeleteLocalRef(clazz);
}
/**
 * 调用java代码 打印日志时调用
 */
void nativeLog(JNIEnv * env, jstring msg) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    //2 找到class 里面的方法定义
    jmethodID methodid = (*env).GetStaticMethodID(clazz,"nativeLog",
                                                  "(Ljava/lang/String;Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");
    jstring logTag = env->NewStringUTF(CONVERT_LOG_TAG);
    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,logTag,msg);
    env->DeleteLocalRef(logTag);
    env->DeleteLocalRef(clazz);
}
/**
 * 字符串拼接
 * @param env
 * @param cstr
 * @param jstr
 * @return
 */
jstring jstrCat(JNIEnv *env,char * cstr,jstring jstr){
    char *c =(char *)(*env).GetStringUTFChars(jstr,JNI_FALSE);
    char * bf = new char[strlen(cstr) + strlen(c) +1];
    memcpy(bf, cstr, strlen(cstr) + 1);
    strcat(bf, c);
    jstring  js = env->NewStringUTF(bf);
    delete [] bf;
    (*env).ReleaseStringUTFChars(jstr,c);
    return js;
}
/**
 * 获取文件的大小
 * @param filename
 * @return
 */
long long file_size(char* filename){
    struct stat statbuf;
    stat(filename,&statbuf);
    return statbuf.st_size;
}
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    hello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_hello
        (JNIEnv *env, jclass obj, jstring str){

    jstring js = env->NewStringUTF("/sd/mp3");
    publishJavaProgress(env,obj,123,js);
    env->DeleteLocalRef(js);

    jstring jstr = env->NewStringUTF("/sd/m/mp3");
    convertFinish(env,jstr);
    env->DeleteLocalRef(jstr);

    jstring msg = env->NewStringUTF("xxx原因导致了未转换成功");
    convertError(env,  msg, msg);
    env->DeleteLocalRef(msg);

    LOGD("lame ver = %s",get_lame_very_short_version());
    LOGI("convertmp3   %S  ===  %S","wav","mp3");
    LOGD("CONVERT   %S","test");
    return env->NewStringUTF("Hello From JNI!");//
}
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    getLameVer
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL
Java_com_convert_mymp3convert_Mp3ConvertUtil_getLameVer(JNIEnv *env, jclass obj) {
    LOGD("CONVERT  123321 测试 S ");
    LOGD("CONVERT  123321 测试 S --- %d",123);
    LOGD("CONVERT  123321 测试 S --- %s","test");
    return (*env).NewStringUTF(get_lame_version());
}
//int flag = 0;
/**
 *wav转换mp3
 * @param env
 * @param obj
 * @param wav
 * @param mp3
 */
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    convertmp3
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_com_convert_mymp3convert_Mp3ConvertUtil_convertmp3(JNIEnv *env, jclass obj, jstring wav,jstring mp3) {

    char* cwav = const_cast<char *>(env->GetStringUTFChars(wav, JNI_FALSE));//Jstring2CStr(env,wav) ;
    char* cmp3= const_cast<char *>(env->GetStringUTFChars(mp3, JNI_FALSE));//Jstring2CStr(env,mp3);
    LOGI("wav = %s", cwav);
    LOGI("mp3 = %s", cmp3);

    char buf[2048] = {};
    sprintf(buf, "source:%s,target:%s ", cwav,cmp3);
    LOGD(buf,NULL);

    if(access(cwav,F_OK) == -1){
        free(cwav);
        free(cmp3);
        LOGD("转换源文件不存在");
        jstring msg = jstrCat(env,"转换源文件不存在:",mp3);
        nativeLog(env, msg);
        convertError(env,msg,mp3);
        env->DeleteLocalRef(msg);
        return;
    }
    long long fileSize = file_size(cwav);
    if (fileSize == 0) {
        free(cwav);
        free(cmp3);
        jstring msg = jstrCat(env,"转换源文件大小为0:",mp3);
        nativeLog(env, msg);
        convertError(env,msg,mp3);
        env->DeleteLocalRef(msg);
        return;
    }
    //1.打开 wav,MP3文件
    FILE* fwav = fopen(cwav,"rb");
    FILE* fmp3 = fopen(cmp3,"wb");

    short int wav_buffer[8192*2]= {};
    unsigned char mp3_buffer[8192] = {};

    //1.初始化lame的编码器
    lame_t lame =  lame_init();
    //2. 设置lame mp3编码的采样率
    lame_set_in_samplerate(lame , 44100);
    lame_set_num_channels(lame,2);
    // 3. 设置MP3的编码方式
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);
    LOGI("lame init finish");

    int read ; int write; //代表读了多少个次 和写了多少次
    long long total=0; // 当前读的wav文件的byte数目

    LOGD("FILE SIZE = %d",fileSize);
    int progress = 0;
    do{
//        if(flag==404){
//            return;
//        }
        read = fread(wav_buffer,sizeof(short int)*2, 8192,fwav);
        total +=  read* sizeof(short int)*2;
        LOGI("converting ....%d", total);
        int tmpProgress = (total*100)/fileSize;
        LOGD("converting size = %d",tmpProgress);

        if(tmpProgress != progress){
            progress = tmpProgress;
            publishJavaProgress(env,obj,progress,mp3);
        }

        // 调用java代码 完成进度条的更新
        if(read!=0){
            write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
            //把转化后的mp3数据写到文件里
            fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
        }
        if(read==0){
            write = lame_encode_flush(lame,mp3_buffer,8192);
            fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
        }
    }while(read!=0);

    lame_close(lame);
    fclose(fwav);
    fclose(fmp3);
    env->ReleaseStringUTFChars(wav,cwav);
    env->ReleaseStringUTFChars(mp3,cmp3);

    convertFinish(env,mp3);
    LOGI("convert  finish");

}


#ifdef __cplusplus
}
#endif
#endif


================================================
FILE: app/src/main/jni/NativeMp3ConvertUtil.cpp.bak
================================================
//
// Created by shaomingfa on 2021/1/14.
//

#include <string>
#include "libmp3lame/lame.h"

#include <jni.h>

#include<stdio.h>
#include<malloc.h>
#include<lame.h>
#include<android/log.h>
#include "libmp3lame/lame.h"
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>


#include "NativeMp3ConvertUtil.h"
#include "com_convert_mymp3convert_Mp3ConvertUtil.h"
#define LOG_TAG "System.out.c"
/**
 * 日志打印tag
 */
#define CONVERT_LOG_TAG "nativeTag"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)



#ifndef com_convert_mymp3convert_Mp3ConvertUtil
#define com_convert_mymp3convert_Mp3ConvertUtil
#ifdef __cplusplus
extern "C" {
#endif

/**
* 返回值 char* 这个代表char数组的首地址
*  Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
*/
char* Jstring2CStr(JNIEnv *env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env).FindClass( "java/lang/String"); //String
    jstring strencode = (*env).NewStringUTF( "GB2312"); // 得到一个java字符串 "GB2312"
    jmethodID mid = (*env).GetMethodID(clsstring, "getBytes",
                                       "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
    jbyteArray barr = (jbyteArray)(*env).CallObjectMethod(jstr, mid,
                                                          strencode); // String .getByte("GB2312");
    jsize alen = (*env).GetArrayLength( barr); // byte数组的长度
    jbyte* ba = (*env).GetByteArrayElements( barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1); //"\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env).ReleaseByteArrayElements(barr, ba, 0); //
    (*env).DeleteLocalRef(strencode);
    return rtn;
}
/**==============================================================================================================================================*/
/**
 * 调用java代码 更新程序的进度条
 */
void publishJavaProgress(JNIEnv * env, jobject obj, jint progress,jstring outPath) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    LOGI(" convert progress %d" , progress);

    //2 找到class 里面的方法定义

    jmethodID methodid = (*env).GetStaticMethodID(clazz,"setConvertProgress","(ILjava/lang/String;)V");//jmethodID methodid = (*env).GetMethodID(clazz, "setConvertProgress","(I)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");

    //3 .调用方法
    (*env).CallStaticVoidMethod(clazz, methodid, progress,outPath);//(*env).CallVoidMethod(obj, methodid, progress);
    //env -> CallVoidMethod(obj,methodid,progress);
    env->DeleteLocalRef(clazz);
    //env->DeleteLocalRef(methodid);
}
/**
 * 调用java代码 更新程序的进度条
 */
void convertFinish(JNIEnv * env, jstring mp3Path) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    const char *c = env->GetStringUTFChars(mp3Path, JNI_FALSE);
    LOGI(" convert finished %s" , c);
    env->ReleaseStringUTFChars(mp3Path,c);

    //2 找到class 里面的方法定义
    jmethodID methodid = (*env).GetStaticMethodID(clazz,"convertFinish","(Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find convertFinish methodid");

    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,mp3Path);
    env->DeleteLocalRef(clazz);
}
/**
 * 调用java代码 转换失败时调用
 */
void convertError(JNIEnv * env,jstring msg,jstring mp3Path) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }

    const char *c = (*env).GetStringUTFChars(mp3Path, JNI_FALSE);
    LOGI(" convert error %s" , c);
    (*env).ReleaseStringUTFChars(mp3Path,c);

    //2 找到class 里面的方法定义

    jmethodID methodid = (*env).GetStaticMethodID(clazz,"convertError",
                                                  "(Ljava/lang/String;Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");

    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,msg,mp3Path);
    env->DeleteLocalRef(clazz);
}
/**
 * 调用java代码 打印日志时调用
 */
void nativeLog(JNIEnv * env, jstring msg) {
    //1.找到java的LameUtils的class          com/example/myjnidemo/
    jclass clazz = (*env).FindClass("com/convert/mymp3convert/Mp3ConvertUtil");
    if (clazz == 0) {
        LOGI("can't find clazz");
        return;
    }
    //2 找到class 里面的方法定义
    jmethodID methodid = (*env).GetStaticMethodID(clazz,"nativeLog",
                                                  "(Ljava/lang/String;Ljava/lang/String;)V");
    if (methodid == 0) {
        LOGI("can't find methodid");
        return;
    }
    LOGI(" find methodid");
    jstring logTag = env->NewStringUTF(CONVERT_LOG_TAG);
    //3 .调用方法
    env -> CallStaticVoidMethod(clazz,methodid,logTag,msg);
    env->DeleteLocalRef(logTag);
    env->DeleteLocalRef(clazz);
}
/**
 * 字符串拼接
 * @param env
 * @param cstr
 * @param jstr
 * @return
 */
jstring jstrCat(JNIEnv *env,char * cstr,jstring jstr){
    char *c =(char *)(*env).GetStringUTFChars(jstr,JNI_FALSE);
    char * bf = new char[strlen(cstr) + strlen(c) +1];
    memcpy(bf, cstr, strlen(cstr) + 1);
    strcat(bf, c);
    jstring  js = env->NewStringUTF(bf);
    delete [] bf;
    (*env).ReleaseStringUTFChars(jstr,c);
    return js;
}
/**
 * 获取文件的大小
 * @param filename
 * @return
 */
long long file_size(char* filename){
    struct stat statbuf;
    stat(filename,&statbuf);
    return statbuf.st_size;
}
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    hello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_hello
        (JNIEnv *env, jclass obj, jstring str){

    jstring js = env->NewStringUTF("/sd/mp3");
    publishJavaProgress(env,obj,123,js);
    env->DeleteLocalRef(js);

    jstring jstr = env->NewStringUTF("/sd/m/mp3");
    convertFinish(env,jstr);
    env->DeleteLocalRef(jstr);

    jstring msg = env->NewStringUTF("xxx原因导致了未转换成功");
    convertError(env,  msg, msg);
    env->DeleteLocalRef(msg);

    LOGD("lame ver = %s",get_lame_very_short_version());
    LOGI("convertmp3   %S  ===  %S","wav","mp3");
    LOGD("CONVERT   %S","test");
    return env->NewStringUTF("Hello From JNI!");//
}
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    getLameVer
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL
Java_com_convert_mymp3convert_Mp3ConvertUtil_getLameVer(JNIEnv *env, jclass obj) {
    LOGD("CONVERT  123321 测试 S ");
    LOGD("CONVERT  123321 测试 S --- %d",123);
    LOGD("CONVERT  123321 测试 S --- %s","test");
    return (*env).NewStringUTF(get_lame_version());
}
//int flag = 0;
/**
 *wav转换mp3
 * @param env
 * @param obj
 * @param wav
 * @param mp3
 */
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    convertmp3
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_com_convert_mymp3convert_Mp3ConvertUtil_convertmp3(JNIEnv *env, jclass obj, jstring wav,jstring mp3) {

    char* cwav = const_cast<char *>(env->GetStringUTFChars(wav, JNI_FALSE));//Jstring2CStr(env,wav) ;
    char* cmp3= const_cast<char *>(env->GetStringUTFChars(mp3, JNI_FALSE));//Jstring2CStr(env,mp3);
    LOGI("wav = %s", cwav);
    LOGI("mp3 = %s", cmp3);

    char buf[2048] = {};
    sprintf(buf, "source:%s,target:%s ", cwav,cmp3);
    LOGD(buf,NULL);

    if(access(cwav,F_OK) == -1){
        free(cwav);
        free(cmp3);
        LOGD("转换源文件不存在");
        jstring msg = jstrCat(env,"转换源文件不存在:",mp3);
        nativeLog(env, msg);
        convertError(env,msg,mp3);
        env->DeleteLocalRef(msg);
        return;
    }
    long long fileSize = file_size(cwav);
    if (fileSize == 0) {
        free(cwav);
        free(cmp3);
        jstring msg = jstrCat(env,"转换源文件大小为0:",mp3);
        nativeLog(env, msg);
        convertError(env,msg,mp3);
        env->DeleteLocalRef(msg);
        return;
    }
    //1.打开 wav,MP3文件
    FILE* fwav = fopen(cwav,"rb");
    FILE* fmp3 = fopen(cmp3,"wb");

    short int wav_buffer[8192*2]= {};
    unsigned char mp3_buffer[8192] = {};

    //1.初始化lame的编码器
    lame_t lame =  lame_init();
    //2. 设置lame mp3编码的采样率
    lame_set_in_samplerate(lame , 44100);
    lame_set_num_channels(lame,2);
    // 3. 设置MP3的编码方式
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);
    LOGI("lame init finish");

    int read ; int write; //代表读了多少个次 和写了多少次
    long long total=0; // 当前读的wav文件的byte数目

    LOGD("FILE SIZE = %d",fileSize);
    int progress = 0;
    do{
//        if(flag==404){
//            return;
//        }
        read = fread(wav_buffer,sizeof(short int)*2, 8192,fwav);
        total +=  read* sizeof(short int)*2;
        LOGI("converting ....%d", total);
        int tmpProgress = (total*100)/fileSize;
        LOGD("converting size = %d",tmpProgress);

        if(tmpProgress != progress){
            progress = tmpProgress;
            publishJavaProgress(env,obj,progress,mp3);
        }

        // 调用java代码 完成进度条的更新
        if(read!=0){
            write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
            //把转化后的mp3数据写到文件里
            fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
        }
        if(read==0){
            write = lame_encode_flush(lame,mp3_buffer,8192);
            fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
        }
    }while(read!=0);

    lame_close(lame);
    fclose(fwav);
    fclose(fmp3);
    env->ReleaseStringUTFChars(wav,cwav);
    env->ReleaseStringUTFChars(mp3,cmp3);

    convertFinish(env,mp3);
    LOGI("convert  finish");

}


#ifdef __cplusplus
}
#endif
#endif


================================================
FILE: app/src/main/jni/NativeMp3ConvertUtil.h
================================================
//
// Created by shaomingfa on 2021/1/14.
//
#include <jni.h>
#ifndef MYMP3CONVERT_NATIVEMP3CONVERTUTIL_H
#define MYMP3CONVERT_NATIVEMP3CONVERTUTIL_H


class NativeMp3ConvertUtil {

};


#endif //MYMP3CONVERT_NATIVEMP3CONVERTUTIL_H


================================================
FILE: app/src/main/jni/NativeMyTest.cpp
================================================
//
// Created by shaomingfa on 2021/1/14.
//
#include <jni.h>
#include <string>
#include "com_convert_mymp3convert_MyTest.h"
#include "libmp3lame/lame.h"
/**
 * 字符串拼接
 * @param env
 * @param cstr
 * @param jstr
 * @return
 */
jstring jstrCat(JNIEnv *env,char * cstr,jstring jstr){
    char *c =(char *)(*env).GetStringUTFChars(jstr,JNI_FALSE);
    char * bf = new char[strlen(cstr) + strlen(c) +1];
    memcpy(bf, cstr, strlen(cstr) + 1);
    strcat(bf, c);
    jstring  js = env->NewStringUTF(bf);
    delete [] bf;
    (*env).ReleaseStringUTFChars(jstr,c);
    return js;
}
/*
 * Class:     com_convert_mymp3convert_MyTest
 * Method:    test
 * Signature: ()Ljava/lang/String;
 */
extern "C" JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_MyTest_test
        (JNIEnv *env, jclass clazz){

    //1、直接使用GetStringUTFChars方法将传递过来的jstring转为char*
    char *c1 = "即将转换:";
    jstring mp3 = env->NewStringUTF("mp3");
    char *c2 = (char *) (env->GetStringUTFChars(mp3, JNI_FALSE));
    env->ReleaseStringUTFChars(mp3,c2);
    //2、再使用本地函数strcat 拼接两个char*对象,然后NewStringUTF转为jstring返回去
    jstring  res = jstrCat(env,c1,mp3);//strcat(c1, c2);
    jstring jstr = res;//env->NewStringUTF(res);
    //convertLog(env,jstr);
    env->DeleteLocalRef(jstr);

    return env->NewStringUTF(get_lame_very_short_version());
}



================================================
FILE: app/src/main/jni/com_convert_mymp3convert_Mp3ConvertUtil.h
================================================
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_convert_mymp3convert_Mp3ConvertUtil */

#ifndef _Included_com_convert_mymp3convert_Mp3ConvertUtil
#define _Included_com_convert_mymp3convert_Mp3ConvertUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    hello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_hello
  (JNIEnv *, jclass, jstring);

/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    getLameVer
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_getLameVer
  (JNIEnv *, jclass);

/*
 * Class:     com_convert_mymp3convert_Mp3ConvertUtil
 * Method:    convertmp3
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_convertmp3
  (JNIEnv *, jclass, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif


================================================
FILE: app/src/main/jni/com_convert_mymp3convert_MyTest.h
================================================
/* DO NOT EDIT THIS FILE - it is machine generated */
/* Header for class com_convert_mymp3convert_MyTest */

#pragma once
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_convert_mymp3convert_MyTest
 * Method:    test
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_MyTest_test
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif



================================================
FILE: app/src/main/jni/libmp3lame/VbrTag.c
================================================
/*
 *      Xing VBR tagging for LAME.
 *
 *      Copyright (c) 1999 A.L. Faber
 *      Copyright (c) 2001 Jonathan Dee
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* $Id: VbrTag.c,v 1.103.2.1 2011/11/18 09:18:28 robert Exp $ */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "util.h"
#include "bitstream.h"
#include "VbrTag.h"
#include "lame_global_flags.h"
#include "tables.h"

#ifdef __sun__
/* woraround for SunOS 4.x, it has SEEK_* defined here */
#include <unistd.h>
#endif


#ifdef _DEBUG
/*  #define DEBUG_VBRTAG */
#endif

/*
 *    4 bytes for Header Tag
 *    4 bytes for Header Flags
 *  100 bytes for entry (NUMTOCENTRIES)
 *    4 bytes for FRAME SIZE
 *    4 bytes for STREAM_SIZE
 *    4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst
 *   20 bytes for LAME tag.  for example, "LAME3.12 (beta 6)"
 * ___________
 *  140 bytes
*/
#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4)

#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2)

/* the size of the Xing header (MPEG1 and MPEG2) in kbps */
#define XING_BITRATE1 128
#define XING_BITRATE2  64
#define XING_BITRATE25 32

extern const char* get_lame_tag_encoder_short_version(void);

static const char VBRTag0[] = { "Xing" };
static const char VBRTag1[] = { "Info" };




/* Lookup table for fast CRC computation
 * See 'CRC_update_lookup'
 * Uses the polynomial x^16+x^15+x^2+1 */

static const unsigned int crc16_lookup[256] = {
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};





/***********************************************************************
 *  Robert Hegemann 2001-01-17
 ***********************************************************************/

static void
addVbr(VBR_seek_info_t * v, int bitrate)
{
    int     i;

    v->nVbrNumFrames++;
    v->sum += bitrate;
    v->seen++;

    if (v->seen < v->want) {
        return;
    }

    if (v->pos < v->size) {
        v->bag[v->pos] = v->sum;
        v->pos++;
        v->seen = 0;
    }
    if (v->pos == v->size) {
        for (i = 1; i < v->size; i += 2) {
            v->bag[i / 2] = v->bag[i];
        }
        v->want *= 2;
        v->pos /= 2;
    }
}

static void
Xing_seek_table(VBR_seek_info_t const* v, unsigned char *t)
{
    int     i, indx;
    int     seek_point;

    if (v->pos <= 0)
        return;

    for (i = 1; i < NUMTOCENTRIES; ++i) {
        float   j = i / (float) NUMTOCENTRIES, act, sum;
        indx = (int) (floor(j * v->pos));
        if (indx > v->pos - 1)
            indx = v->pos - 1;
        act = v->bag[indx];
        sum = v->sum;
        seek_point = (int) (256. * act / sum);
        if (seek_point > 255)
            seek_point = 255;
        t[i] = seek_point;
    }
}

#ifdef DEBUG_VBR_SEEKING_TABLE
static void
print_seeking(unsigned char *t)
{
    int     i;

    printf("seeking table ");
    for (i = 0; i < NUMTOCENTRIES; ++i) {
        printf(" %d ", t[i]);
    }
    printf("\n");
}
#endif


/****************************************************************************
 * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries
 * Paramters:
 *      nStreamPos: how many bytes did we write to the bitstream so far
 *                              (in Bytes NOT Bits)
 ****************************************************************************
*/
void
AddVbrFrame(lame_internal_flags * gfc)
{
    int     kbps = bitrate_table[gfc->cfg.version][gfc->ov_enc.bitrate_index];
    assert(gfc->VBR_seek_table.bag);
    addVbr(&gfc->VBR_seek_table, kbps);
}


/*-------------------------------------------------------------*/
static int
ExtractI4(const unsigned char *buf)
{
    int     x;
    /* big endian extract */
    x = buf[0];
    x <<= 8;
    x |= buf[1];
    x <<= 8;
    x |= buf[2];
    x <<= 8;
    x |= buf[3];
    return x;
}

static void
CreateI4(unsigned char *buf, uint32_t nValue)
{
    /* big endian create */
    buf[0] = (nValue >> 24) & 0xff;
    buf[1] = (nValue >> 16) & 0xff;
    buf[2] = (nValue >> 8) & 0xff;
    buf[3] = (nValue) & 0xff;
}



static void
CreateI2(unsigned char *buf, int nValue)
{
    /* big endian create */
    buf[0] = (nValue >> 8) & 0xff;
    buf[1] = (nValue) & 0xff;
}

/* check for magic strings*/
static int
IsVbrTag(const unsigned char *buf)
{
    int     isTag0, isTag1;

    isTag0 = ((buf[0] == VBRTag0[0]) && (buf[1] == VBRTag0[1]) && (buf[2] == VBRTag0[2])
              && (buf[3] == VBRTag0[3]));
    isTag1 = ((buf[0] == VBRTag1[0]) && (buf[1] == VBRTag1[1]) && (buf[2] == VBRTag1[2])
              && (buf[3] == VBRTag1[3]));

    return (isTag0 || isTag1);
}

#define SHIFT_IN_BITS_VALUE(x,n,v) ( x = (x << (n)) | ( (v) & ~(-1 << (n)) ) )

static void
setLameTagFrameHeader(lame_internal_flags const *gfc, unsigned char *buffer)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncResult_t const *const eov = &gfc->ov_enc;
    char    abyte, bbyte;

    SHIFT_IN_BITS_VALUE(buffer[0], 8u, 0xffu);

    SHIFT_IN_BITS_VALUE(buffer[1], 3u, 7);
    SHIFT_IN_BITS_VALUE(buffer[1], 1u, (cfg->samplerate_out < 16000) ? 0 : 1);
    SHIFT_IN_BITS_VALUE(buffer[1], 1u, cfg->version);
    SHIFT_IN_BITS_VALUE(buffer[1], 2u, 4 - 3);
    SHIFT_IN_BITS_VALUE(buffer[1], 1u, (!cfg->error_protection) ? 1 : 0);

    SHIFT_IN_BITS_VALUE(buffer[2], 4u, eov->bitrate_index);
    SHIFT_IN_BITS_VALUE(buffer[2], 2u, cfg->samplerate_index);
    SHIFT_IN_BITS_VALUE(buffer[2], 1u, 0);
    SHIFT_IN_BITS_VALUE(buffer[2], 1u, cfg->extension);

    SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->mode);
    SHIFT_IN_BITS_VALUE(buffer[3], 2u, eov->mode_ext);
    SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->copyright);
    SHIFT_IN_BITS_VALUE(buffer[3], 1u, cfg->original);
    SHIFT_IN_BITS_VALUE(buffer[3], 2u, cfg->emphasis);

    /* the default VBR header. 48 kbps layer III, no padding, no crc */
    /* but sampling freq, mode andy copyright/copy protection taken */
    /* from first valid frame */
    buffer[0] = (uint8_t) 0xff;
    abyte = (buffer[1] & (unsigned char) 0xf1);
    {
        int     bitrate;
        if (1 == cfg->version) {
            bitrate = XING_BITRATE1;
        }
        else {
            if (cfg->samplerate_out < 16000)
                bitrate = XING_BITRATE25;
            else
                bitrate = XING_BITRATE2;
        }

        if (cfg->vbr == vbr_off)
            bitrate = cfg->avg_bitrate;

        if (cfg->free_format)
            bbyte = 0x00;
        else
            bbyte = 16 * BitrateIndex(bitrate, cfg->version, cfg->samplerate_out);
    }

    /* Use as much of the info from the real frames in the
     * Xing header:  samplerate, channels, crc, etc...
     */
    if (cfg->version == 1) {
        /* MPEG1 */
        buffer[1] = abyte | (char) 0x0a; /* was 0x0b; */
        abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */
        buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG1 frame */
    }
    else {
        /* MPEG2 */
        buffer[1] = abyte | (char) 0x02; /* was 0x03; */
        abyte = buffer[2] & (char) 0x0d; /* AF keep also private bit */
        buffer[2] = (char) bbyte | abyte; /* 64kbs MPEG2 frame */
    }
}

#if 0
static int CheckVbrTag(unsigned char *buf);

/*-------------------------------------------------------------*/
/* Same as GetVbrTag below, but only checks for the Xing tag.
   requires buf to contain only 40 bytes */
/*-------------------------------------------------------------*/
int
CheckVbrTag(unsigned char *buf)
{
    int     h_id, h_mode;

    /* get selected MPEG header data */
    h_id = (buf[1] >> 3) & 1;
    h_mode = (buf[3] >> 6) & 3;

    /*  determine offset of header */
    if (h_id) {
        /* mpeg1 */
        if (h_mode != 3)
            buf += (32 + 4);
        else
            buf += (17 + 4);
    }
    else {
        /* mpeg2 */
        if (h_mode != 3)
            buf += (17 + 4);
        else
            buf += (9 + 4);
    }

    return IsVbrTag(buf);
}
#endif

int
GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf)
{
    int     i, head_flags;
    int     h_bitrate, h_id, h_mode, h_sr_index, h_layer;
    int     enc_delay, enc_padding;

    /* get Vbr header data */
    pTagData->flags = 0;

    /* get selected MPEG header data */
    h_layer = (buf[1] >> 1) & 3;
    if ( h_layer != 0x01 ) {
        /* the following code assumes Layer-3, so give up here */
        return 0;
    }
    h_id = (buf[1] >> 3) & 1;
    h_sr_index = (buf[2] >> 2) & 3;
    h_mode = (buf[3] >> 6) & 3;
    h_bitrate = ((buf[2] >> 4) & 0xf);
    h_bitrate = bitrate_table[h_id][h_bitrate];

    /* check for FFE syncword */
    if ((buf[1] >> 4) == 0xE)
        pTagData->samprate = samplerate_table[2][h_sr_index];
    else
        pTagData->samprate = samplerate_table[h_id][h_sr_index];
    /* if( h_id == 0 ) */
    /*  pTagData->samprate >>= 1; */



    /*  determine offset of header */
    if (h_id) {
        /* mpeg1 */
        if (h_mode != 3)
            buf += (32 + 4);
        else
            buf += (17 + 4);
    }
    else {
        /* mpeg2 */
        if (h_mode != 3)
            buf += (17 + 4);
        else
            buf += (9 + 4);
    }

    if (!IsVbrTag(buf))
        return 0;

    buf += 4;

    pTagData->h_id = h_id;

    head_flags = pTagData->flags = ExtractI4(buf);
    buf += 4;           /* get flags */

    if (head_flags & FRAMES_FLAG) {
        pTagData->frames = ExtractI4(buf);
        buf += 4;
    }

    if (head_flags & BYTES_FLAG) {
        pTagData->bytes = ExtractI4(buf);
        buf += 4;
    }

    if (head_flags & TOC_FLAG) {
        if (pTagData->toc != NULL) {
            for (i = 0; i < NUMTOCENTRIES; i++)
                pTagData->toc[i] = buf[i];
        }
        buf += NUMTOCENTRIES;
    }

    pTagData->vbr_scale = -1;

    if (head_flags & VBR_SCALE_FLAG) {
        pTagData->vbr_scale = ExtractI4(buf);
        buf += 4;
    }

    pTagData->headersize = ((h_id + 1) * 72000 * h_bitrate) / pTagData->samprate;

    buf += 21;
    enc_delay = buf[0] << 4;
    enc_delay += buf[1] >> 4;
    enc_padding = (buf[1] & 0x0F) << 8;
    enc_padding += buf[2];
    /* check for reasonable values (this may be an old Xing header, */
    /* not a INFO tag) */
    if (enc_delay < 0 || enc_delay > 3000)
        enc_delay = -1;
    if (enc_padding < 0 || enc_padding > 3000)
        enc_padding = -1;

    pTagData->enc_delay = enc_delay;
    pTagData->enc_padding = enc_padding;

#ifdef DEBUG_VBRTAG
    fprintf(stderr, "\n\n********************* VBR TAG INFO *****************\n");
    fprintf(stderr, "tag         :%s\n", VBRTag);
    fprintf(stderr, "head_flags  :%d\n", head_flags);
    fprintf(stderr, "bytes       :%d\n", pTagData->bytes);
    fprintf(stderr, "frames      :%d\n", pTagData->frames);
    fprintf(stderr, "VBR Scale   :%d\n", pTagData->vbr_scale);
    fprintf(stderr, "enc_delay  = %i \n", enc_delay);
    fprintf(stderr, "enc_padding= %i \n", enc_padding);
    fprintf(stderr, "toc:\n");
    if (pTagData->toc != NULL) {
        for (i = 0; i < NUMTOCENTRIES; i++) {
            if ((i % 10) == 0)
                fprintf(stderr, "\n");
            fprintf(stderr, " %3d", (int) (pTagData->toc[i]));
        }
    }
    fprintf(stderr, "\n***************** END OF VBR TAG INFO ***************\n");
#endif
    return 1;           /* success */
}


/****************************************************************************
 * InitVbrTag: Initializes the header, and write empty frame to stream
 * Paramters:
 *                              fpStream: pointer to output file stream
 *                              nMode   : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO
 ****************************************************************************
*/
int
InitVbrTag(lame_global_flags * gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    SessionConfig_t const *const cfg = &gfc->cfg;
    int     kbps_header;

#define MAXFRAMESIZE 2880 /* or 0xB40, the max freeformat 640 32kHz framesize */

    /*
     * Xing VBR pretends to be a 48kbs layer III frame.  (at 44.1kHz).
     * (at 48kHz they use 56kbs since 48kbs frame not big enough for
     * table of contents)
     * let's always embed Xing header inside a 64kbs layer III frame.
     * this gives us enough room for a LAME version string too.
     * size determined by sampling frequency (MPEG1)
     * 32kHz:    216 bytes@48kbs    288bytes@ 64kbs
     * 44.1kHz:  156 bytes          208bytes@64kbs     (+1 if padding = 1)
     * 48kHz:    144 bytes          192
     *
     * MPEG 2 values are the same since the framesize and samplerate
     * are each reduced by a factor of 2.
     */


    if (1 == cfg->version) {
        kbps_header = XING_BITRATE1;
    }
    else {
        if (cfg->samplerate_out < 16000)
            kbps_header = XING_BITRATE25;
        else
            kbps_header = XING_BITRATE2;
    }

    if (cfg->vbr == vbr_off)
        kbps_header = cfg->avg_bitrate;

    /** make sure LAME Header fits into Frame
     */
    {
        int     total_frame_size = ((cfg->version + 1) * 72000 * kbps_header) / cfg->samplerate_out;
        int     header_size = (cfg->sideinfo_len + LAMEHEADERSIZE);
        gfc->VBR_seek_table.TotalFrameSize = total_frame_size;
        if (total_frame_size < header_size || total_frame_size > MAXFRAMESIZE) {
            /* disable tag, it wont fit */
            gfc->cfg.write_lame_tag = 0;
            return 0;
        }
    }

    gfc->VBR_seek_table.nVbrNumFrames = 0;
    gfc->VBR_seek_table.nBytesWritten = 0;
    gfc->VBR_seek_table.sum = 0;

    gfc->VBR_seek_table.seen = 0;
    gfc->VBR_seek_table.want = 1;
    gfc->VBR_seek_table.pos = 0;

    if (gfc->VBR_seek_table.bag == NULL) {
        gfc->VBR_seek_table.bag = malloc(400 * sizeof(int));
        if (gfc->VBR_seek_table.bag != NULL) {
            gfc->VBR_seek_table.size = 400;
        }
        else {
            gfc->VBR_seek_table.size = 0;
            ERRORF(gfc, "Error: can't allocate VbrFrames buffer\n");
            gfc->cfg.write_lame_tag = 0;
            return -1;
        }
    }

    /* write dummy VBR tag of all 0's into bitstream */
    {
        uint8_t buffer[MAXFRAMESIZE];
        size_t  i, n;

        memset(buffer, 0, sizeof(buffer));
        setLameTagFrameHeader(gfc, buffer);
        n = gfc->VBR_seek_table.TotalFrameSize;
        for (i = 0; i < n; ++i) {
            add_dummy_byte(gfc, buffer[i], 1);
        }
    }
    /* Success */
    return 0;
}



/* fast CRC-16 computation - uses table crc16_lookup 8*/
static uint16_t
CRC_update_lookup(uint16_t value, uint16_t crc)
{
    uint16_t tmp;
    tmp = crc ^ value;
    crc = (crc >> 8) ^ crc16_lookup[tmp & 0xff];
    return crc;
}

void
UpdateMusicCRC(uint16_t * crc, unsigned char const *buffer, int size)
{
    int     i;
    for (i = 0; i < size; ++i)
        *crc = CRC_update_lookup(buffer[i], *crc);
}





/****************************************************************************
 * Jonathan Dee 2001/08/31
 *
 * PutLameVBR: Write LAME info: mini version + info on various switches used
 * Paramters:
 *                              pbtStreamBuffer : pointer to output buffer
 *                              id3v2size               : size of id3v2 tag in bytes
 *                              crc                             : computation of crc-16 of Lame Tag so far (starting at frame sync)
 *
 ****************************************************************************
*/
static int
PutLameVBR(lame_global_flags const *gfp, size_t nMusicLength, uint8_t * pbtStreamBuffer, uint16_t crc)
{
    lame_internal_flags const *gfc = gfp->internal_flags;
    SessionConfig_t const *const cfg = &gfc->cfg;

    int     nBytesWritten = 0;
    int     i;

    int     enc_delay = gfc->ov_enc.encoder_delay; /* encoder delay */
    int     enc_padding = gfc->ov_enc.encoder_padding; /* encoder padding  */

    /*recall: cfg->vbr_q is for example set by the switch -V  */
    /*   gfp->quality by -q, -h, -f, etc */

    int     nQuality = (100 - 10 * gfp->VBR_q - gfp->quality);


    /*
    NOTE:
            Even though the specification for the LAME VBR tag
            did explicitly mention other encoders than LAME,
            many SW/HW decoder seem to be able to make use of
            this tag only, if the encoder version starts with LAME.
            To be compatible with such decoders, ANY encoder will
            be forced to write a fake LAME version string!
            As a result, the encoder version info becomes worthless.
    */
    const char *szVersion = get_lame_tag_encoder_short_version();
    uint8_t nVBR;
    uint8_t nRevision = 0x00;
    uint8_t nRevMethod;
    uint8_t vbr_type_translator[] = { 1, 5, 3, 2, 4, 0, 3 }; /*numbering different in vbr_mode vs. Lame tag */

    uint8_t nLowpass =
        (((cfg->lowpassfreq / 100.0) + .5) > 255 ? 255 : (cfg->lowpassfreq / 100.0) + .5);

    uint32_t nPeakSignalAmplitude = 0;

    uint16_t nRadioReplayGain = 0;
    uint16_t nAudiophileReplayGain = 0;

    uint8_t nNoiseShaping = cfg->noise_shaping;
    uint8_t nStereoMode = 0;
    int     bNonOptimal = 0;
    uint8_t nSourceFreq = 0;
    uint8_t nMisc = 0;
    uint16_t nMusicCRC = 0;

    /*psy model type: Gpsycho or NsPsytune */
    unsigned char bExpNPsyTune = 1; /* only NsPsytune */
    unsigned char bSafeJoint = (cfg->use_safe_joint_stereo) != 0;

    unsigned char bNoGapMore = 0;
    unsigned char bNoGapPrevious = 0;

    int     nNoGapCount = gfp->nogap_total;
    int     nNoGapCurr = gfp->nogap_current;


    uint8_t nAthType = cfg->ATHtype; /*4 bits. */

    uint8_t nFlags = 0;

    /* if ABR, {store bitrate <=255} else { store "-b"} */
    int     nABRBitrate;
    switch (cfg->vbr) {
    case vbr_abr:{
            nABRBitrate = cfg->vbr_avg_bitrate_kbps;
            break;
        }
    case vbr_off:{
            nABRBitrate = cfg->avg_bitrate;
            break;
        }
    default:{          /*vbr modes */
            nABRBitrate = bitrate_table[cfg->version][cfg->vbr_min_bitrate_index];;
        }
    }


    /*revision and vbr method */
    if (cfg->vbr < sizeof(vbr_type_translator))
        nVBR = vbr_type_translator[cfg->vbr];
    else
        nVBR = 0x00;    /*unknown. */

    nRevMethod = 0x10 * nRevision + nVBR;


    /* ReplayGain */
    if (cfg->findReplayGain) {
        int     RadioGain = gfc->ov_rpg.RadioGain;
        if (RadioGain > 0x1FE)
            RadioGain = 0x1FE;
        if (RadioGain < -0x1FE)
            RadioGain = -0x1FE;

        nRadioReplayGain = 0x2000; /* set name code */
        nRadioReplayGain |= 0xC00; /* set originator code to `determined automatically' */

        if (RadioGain >= 0)
            nRadioReplayGain |= RadioGain; /* set gain adjustment */
        else {
            nRadioReplayGain |= 0x200; /* set the sign bit */
            nRadioReplayGain |= -RadioGain; /* set gain adjustment */
        }
    }

    /* peak sample */
    if (cfg->findPeakSample)
        nPeakSignalAmplitude =
            abs((int) ((((FLOAT) gfc->ov_rpg.PeakSample) / 32767.0) * pow(2, 23) + .5));

    /*nogap */
    if (nNoGapCount != -1) {
        if (nNoGapCurr > 0)
            bNoGapPrevious = 1;

        if (nNoGapCurr < nNoGapCount - 1)
            bNoGapMore = 1;
    }

    /*flags */

    nFlags = nAthType + (bExpNPsyTune << 4)
        + (bSafeJoint << 5)
        + (bNoGapMore << 6)
        + (bNoGapPrevious << 7);


    if (nQuality < 0)
        nQuality = 0;

    /*stereo mode field... a bit ugly. */

    switch (cfg->mode) {
    case MONO:
        nStereoMode = 0;
        break;
    case STEREO:
        nStereoMode = 1;
        break;
    case DUAL_CHANNEL:
        nStereoMode = 2;
        break;
    case JOINT_STEREO:
        if (cfg->force_ms)
            nStereoMode = 4;
        else
            nStereoMode = 3;
        break;
    case NOT_SET:
        /* FALLTHROUGH */
    default:
        nStereoMode = 7;
        break;
    }

    /*Intensity stereo : nStereoMode = 6. IS is not implemented */

    if (cfg->samplerate_in <= 32000)
        nSourceFreq = 0x00;
    else if (cfg->samplerate_in == 48000)
        nSourceFreq = 0x02;
    else if (cfg->samplerate_in > 48000)
        nSourceFreq = 0x03;
    else
        nSourceFreq = 0x01; /*default is 44100Hz. */


    /*Check if the user overrided the default LAME behaviour with some nasty options */

    if (cfg->short_blocks == short_block_forced || cfg->short_blocks == short_block_dispensed || ((cfg->lowpassfreq == -1) && (cfg->highpassfreq == -1)) || /* "-k" */
        (cfg->disable_reservoir && cfg->avg_bitrate < 320) ||
        cfg->noATH || cfg->ATHonly || (nAthType == 0) || cfg->samplerate_in <= 32000)
        bNonOptimal = 1;

    nMisc = nNoiseShaping + (nStereoMode << 2)
        + (bNonOptimal << 5)
        + (nSourceFreq << 6);


    nMusicCRC = gfc->nMusicCRC;


    /*Write all this information into the stream */
    CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality);
    nBytesWritten += 4;

    strncpy((char *) &pbtStreamBuffer[nBytesWritten], szVersion, 9);
    nBytesWritten += 9;

    pbtStreamBuffer[nBytesWritten] = nRevMethod;
    nBytesWritten++;

    pbtStreamBuffer[nBytesWritten] = nLowpass;
    nBytesWritten++;

    CreateI4(&pbtStreamBuffer[nBytesWritten], nPeakSignalAmplitude);
    nBytesWritten += 4;

    CreateI2(&pbtStreamBuffer[nBytesWritten], nRadioReplayGain);
    nBytesWritten += 2;

    CreateI2(&pbtStreamBuffer[nBytesWritten], nAudiophileReplayGain);
    nBytesWritten += 2;

    pbtStreamBuffer[nBytesWritten] = nFlags;
    nBytesWritten++;

    if (nABRBitrate >= 255)
        pbtStreamBuffer[nBytesWritten] = 0xFF;
    else
        pbtStreamBuffer[nBytesWritten] = nABRBitrate;
    nBytesWritten++;

    pbtStreamBuffer[nBytesWritten] = enc_delay >> 4; /* works for win32, does it for unix? */
    pbtStreamBuffer[nBytesWritten + 1] = (enc_delay << 4) + (enc_padding >> 8);
    pbtStreamBuffer[nBytesWritten + 2] = enc_padding;

    nBytesWritten += 3;

    pbtStreamBuffer[nBytesWritten] = nMisc;
    nBytesWritten++;


    pbtStreamBuffer[nBytesWritten++] = 0; /*unused in rev0 */

    CreateI2(&pbtStreamBuffer[nBytesWritten], cfg->preset);
    nBytesWritten += 2;

    CreateI4(&pbtStreamBuffer[nBytesWritten], (int) nMusicLength);
    nBytesWritten += 4;

    CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC);
    nBytesWritten += 2;

    /*Calculate tag CRC.... must be done here, since it includes
     *previous information*/

    for (i = 0; i < nBytesWritten; i++)
        crc = CRC_update_lookup(pbtStreamBuffer[i], crc);

    CreateI2(&pbtStreamBuffer[nBytesWritten], crc);
    nBytesWritten += 2;

    return nBytesWritten;
}

static long
skipId3v2(FILE * fpStream)
{
    size_t  nbytes;
    long    id3v2TagSize;
    unsigned char id3v2Header[10];

    /* seek to the beginning of the stream */
    if (fseek(fpStream, 0, SEEK_SET) != 0) {
        return -2;      /* not seekable, abort */
    }
    /* read 10 bytes in case there's an ID3 version 2 header here */
    nbytes = fread(id3v2Header, 1, sizeof(id3v2Header), fpStream);
    if (nbytes != sizeof(id3v2Header)) {
        return -3;      /* not readable, maybe opened Write-Only */
    }
    /* does the stream begin with the ID3 version 2 file identifier? */
    if (!strncmp((char *) id3v2Header, "ID3", 3)) {
        /* the tag size (minus the 10-byte header) is encoded into four
         * bytes where the most significant bit is clear in each byte */
        id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21)
                        | ((id3v2Header[7] & 0x7f) << 14)
                        | ((id3v2Header[8] & 0x7f) << 7)
                        | (id3v2Header[9] & 0x7f))
            + sizeof id3v2Header;
    }
    else {
        /* no ID3 version 2 tag in this stream */
        id3v2TagSize = 0;
    }
    return id3v2TagSize;
}



size_t
lame_get_lametag_frame(lame_global_flags const *gfp, unsigned char *buffer, size_t size)
{
    lame_internal_flags *gfc;
    SessionConfig_t const *cfg;
    unsigned long stream_size;
    unsigned int  nStreamIndex;
    uint8_t btToc[NUMTOCENTRIES];

    if (gfp == 0) {
        return 0;
    }
    gfc = gfp->internal_flags;
    if (gfc == 0) {
        return 0;
    }
    if (gfc->class_id != LAME_ID) {
        return 0;
    }
    cfg = &gfc->cfg;
    if (cfg->write_lame_tag == 0) {
        return 0;
    }
    if (gfc->VBR_seek_table.pos <= 0) {
        return 0;
    }
    if (size < gfc->VBR_seek_table.TotalFrameSize) {
        return gfc->VBR_seek_table.TotalFrameSize;
    }
    if (buffer == 0) {
        return 0;
    }

    memset(buffer, 0, gfc->VBR_seek_table.TotalFrameSize);

    /* 4 bytes frame header */

    setLameTagFrameHeader(gfc, buffer);

    /* Clear all TOC entries */
    memset(btToc, 0, sizeof(btToc));

    if (cfg->free_format) {
        int     i;
        for (i = 1; i < NUMTOCENTRIES; ++i)
            btToc[i] = 255 * i / 100;
    }
    else {
        Xing_seek_table(&gfc->VBR_seek_table, btToc);
    }
#ifdef DEBUG_VBR_SEEKING_TABLE
    print_seeking(btToc);
#endif

    /* Start writing the tag after the zero frame */
    nStreamIndex = cfg->sideinfo_len;
    /* note! Xing header specifies that Xing data goes in the
     * ancillary data with NO ERROR PROTECTION.  If error protecton
     * in enabled, the Xing data still starts at the same offset,
     * and now it is in sideinfo data block, and thus will not
     * decode correctly by non-Xing tag aware players */
    if (cfg->error_protection)
        nStreamIndex -= 2;

    /* Put Vbr tag */
    if (cfg->vbr == vbr_off) {
        buffer[nStreamIndex++] = VBRTag1[0];
        buffer[nStreamIndex++] = VBRTag1[1];
        buffer[nStreamIndex++] = VBRTag1[2];
        buffer[nStreamIndex++] = VBRTag1[3];

    }
    else {
        buffer[nStreamIndex++] = VBRTag0[0];
        buffer[nStreamIndex++] = VBRTag0[1];
        buffer[nStreamIndex++] = VBRTag0[2];
        buffer[nStreamIndex++] = VBRTag0[3];
    }

    /* Put header flags */
    CreateI4(&buffer[nStreamIndex], FRAMES_FLAG + BYTES_FLAG + TOC_FLAG + VBR_SCALE_FLAG);
    nStreamIndex += 4;

    /* Put Total Number of frames */
    CreateI4(&buffer[nStreamIndex], gfc->VBR_seek_table.nVbrNumFrames);
    nStreamIndex += 4;

    /* Put total audio stream size, including Xing/LAME Header */
    stream_size = gfc->VBR_seek_table.nBytesWritten + gfc->VBR_seek_table.TotalFrameSize;
    CreateI4(&buffer[nStreamIndex], stream_size);
    nStreamIndex += 4;

    /* Put TOC */
    memcpy(&buffer[nStreamIndex], btToc, sizeof(btToc));
    nStreamIndex += sizeof(btToc);


    if (cfg->error_protection) {
        /* (jo) error_protection: add crc16 information to header */
        CRC_writeheader(gfc, (char *) buffer);
    }
    {
        /*work out CRC so far: initially crc = 0 */
        uint16_t crc = 0x00;
        unsigned int i;
        for (i = 0; i < nStreamIndex; i++)
            crc = CRC_update_lookup(buffer[i], crc);
        /*Put LAME VBR info */
        nStreamIndex += PutLameVBR(gfp, stream_size, buffer + nStreamIndex, crc);
    }

#ifdef DEBUG_VBRTAG
    {
        VBRTAGDATA TestHeader;
        GetVbrTag(&TestHeader, buffer);
    }
#endif

    return gfc->VBR_seek_table.TotalFrameSize;
}

/***********************************************************************
 *
 * PutVbrTag: Write final VBR tag to the file
 * Paramters:
 *                              lpszFileName: filename of MP3 bit stream
 *                              nVbrScale       : encoder quality indicator (0..100)
 ****************************************************************************
 */

int
PutVbrTag(lame_global_flags const *gfp, FILE * fpStream)
{
    lame_internal_flags *gfc = gfp->internal_flags;

    long    lFileSize;
    long    id3v2TagSize;
    size_t  nbytes;
    uint8_t buffer[MAXFRAMESIZE];

    if (gfc->VBR_seek_table.pos <= 0)
        return -1;

    /* Seek to end of file */
    fseek(fpStream, 0, SEEK_END);

    /* Get file size */
    lFileSize = ftell(fpStream);

    /* Abort if file has zero length. Yes, it can happen :) */
    if (lFileSize == 0)
        return -1;

    /*
     * The VBR tag may NOT be located at the beginning of the stream.
     * If an ID3 version 2 tag was added, then it must be skipped to write
     * the VBR tag data.
     */

    id3v2TagSize = skipId3v2(fpStream);

    if (id3v2TagSize < 0) {
        return id3v2TagSize;
    }

    /*Seek to the beginning of the stream */
    fseek(fpStream, id3v2TagSize, SEEK_SET);

    nbytes = lame_get_lametag_frame(gfp, buffer, sizeof(buffer));
    if (nbytes > sizeof(buffer)) {
        return -1;
    }

    if (nbytes < 1) {
        return 0;
    }

    /* Put it all to disk again */
    if (fwrite(buffer, nbytes, 1, fpStream) != 1) {
        return -1;
    }

    return 0;           /* success */
}


================================================
FILE: app/src/main/jni/libmp3lame/VbrTag.h
================================================
/*
 *      Xing VBR tagging for LAME.
 *
 *      Copyright (c) 1999 A.L. Faber
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef LAME_VRBTAG_H
#define LAME_VRBTAG_H


/* -----------------------------------------------------------
 * A Vbr header may be present in the ancillary
 * data field of the first frame of an mp3 bitstream
 * The Vbr header (optionally) contains
 *      frames      total number of audio frames in the bitstream
 *      bytes       total number of bytes in the bitstream
 *      toc         table of contents

 * toc (table of contents) gives seek points
 * for random access
 * the ith entry determines the seek point for
 * i-percent duration
 * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes
 * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes
 */


#define FRAMES_FLAG     0x0001
#define BYTES_FLAG      0x0002
#define TOC_FLAG        0x0004
#define VBR_SCALE_FLAG  0x0008

#define NUMTOCENTRIES 100

#ifndef lame_internal_flags_defined
#define lame_internal_flags_defined
struct lame_internal_flags;
typedef struct lame_internal_flags lame_internal_flags;
#endif


/*structure to receive extracted header */
/* toc may be NULL*/
typedef struct {
    int     h_id;            /* from MPEG header, 0=MPEG2, 1=MPEG1 */
    int     samprate;        /* determined from MPEG header */
    int     flags;           /* from Vbr header data */
    int     frames;          /* total bit stream frames from Vbr header data */
    int     bytes;           /* total bit stream bytes from Vbr header data */
    int     vbr_scale;       /* encoded vbr scale from Vbr header data */
    unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired */
    int     headersize;      /* size of VBR header, in bytes */
    int     enc_delay;       /* encoder delay */
    int     enc_padding;     /* encoder paddign added at end of stream */
} VBRTAGDATA;

int     GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf);

int     InitVbrTag(lame_global_flags * gfp);
int     PutVbrTag(lame_global_flags const *gfp, FILE * fid);
void    AddVbrFrame(lame_internal_flags * gfc);
void    UpdateMusicCRC(uint16_t * crc, const unsigned char *buffer, int size);

#endif


================================================
FILE: app/src/main/jni/libmp3lame/bitstream.c
================================================
/*
 *      MP3 bitstream Output interface for LAME
 *
 *      Copyright (c) 1999-2000 Mark Taylor
 *      Copyright (c) 1999-2002 Takehiro Tominaga
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * $Id: bitstream.c,v 1.97 2011/05/07 16:05:17 rbrito Exp $
 */


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>
#include <stdio.h>

#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "util.h"
#include "tables.h"
#include "quantize_pvt.h"
#include "lame_global_flags.h"
#include "gain_analysis.h"
#include "VbrTag.h"
#include "bitstream.h"
#include "tables.h"



/* unsigned int is at least this large:  */
/* we work with ints, so when doing bit manipulation, we limit
 * ourselves to MAX_LENGTH-2 just to be on the safe side */
#define MAX_LENGTH      32



#ifdef DEBUG
static int hogege;
#endif



static int
calcFrameLength(SessionConfig_t const *const cfg, int kbps, int pad)
{
  return 8 * ((cfg->version + 1) * 72000 * kbps / cfg->samplerate_out + pad);
}


/***********************************************************************
 * compute bitsperframe and mean_bits for a layer III frame
 **********************************************************************/
int
getframebits(const lame_internal_flags * gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncResult_t const *const eov = &gfc->ov_enc;
    int     bit_rate;

    /* get bitrate in kbps [?] */
    if (eov->bitrate_index)
        bit_rate = bitrate_table[cfg->version][eov->bitrate_index];
    else
        bit_rate = cfg->avg_bitrate;
    /*assert(bit_rate <= 550); */
    assert(8 <= bit_rate && bit_rate <= 640);

    /* main encoding routine toggles padding on and off */
    /* one Layer3 Slot consists of 8 bits */
    return calcFrameLength(cfg, bit_rate, eov->padding);
}

int
get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint)
{
    int     maxmp3buf = 0;
    if (cfg->avg_bitrate > 320) {
        /* in freeformat the buffer is constant */
        if (constraint == MDB_STRICT_ISO) {
            maxmp3buf = calcFrameLength(cfg, cfg->avg_bitrate, 0);
        }
        else {
            /* maximum allowed bits per granule are 7680 */
            maxmp3buf = 7680 * (cfg->version + 1);
        }
    }
    else {
        int     max_kbps;
        if (cfg->samplerate_out < 16000) {
            max_kbps = bitrate_table[cfg->version][8]; /* default: allow 64 kbps (MPEG-2.5) */
        }
        else {
            max_kbps = bitrate_table[cfg->version][14];
        }
        switch (constraint) 
        {
        default:
        case MDB_DEFAULT:
            /* Bouvigne suggests this more lax interpretation of the ISO doc instead of using 8*960. */
            /* All mp3 decoders should have enough buffer to handle this value: size of a 320kbps 32kHz frame */
            maxmp3buf = 8 * 1440;
            break;
        case MDB_STRICT_ISO:
            maxmp3buf = calcFrameLength(cfg, max_kbps, 0);
            break;
        case MDB_MAXIMUM:
            maxmp3buf = 7680 * (cfg->version + 1);
            break;
        }
    }
    return maxmp3buf;
}


static void
putheader_bits(lame_internal_flags * gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncStateVar_t *const esv = &gfc->sv_enc;
    Bit_stream_struc *bs = &gfc->bs;
#ifdef DEBUG
    hogege += cfg->sideinfo_len * 8;
#endif
    memcpy(&bs->buf[bs->buf_byte_idx], esv->header[esv->w_ptr].buf, cfg->sideinfo_len);
    bs->buf_byte_idx += cfg->sideinfo_len;
    bs->totbit += cfg->sideinfo_len * 8;
    esv->w_ptr = (esv->w_ptr + 1) & (MAX_HEADER_BUF - 1);
}




/*write j bits into the bit stream */
inline static void
putbits2(lame_internal_flags * gfc, int val, int j)
{
    EncStateVar_t const *const esv = &gfc->sv_enc;
    Bit_stream_struc *bs;
    bs = &gfc->bs;

    assert(j < MAX_LENGTH - 2);

    while (j > 0) {
        int     k;
        if (bs->buf_bit_idx == 0) {
            bs->buf_bit_idx = 8;
            bs->buf_byte_idx++;
            assert(bs->buf_byte_idx < BUFFER_SIZE);
            assert(esv->header[esv->w_ptr].write_timing >= bs->totbit);
            if (esv->header[esv->w_ptr].write_timing == bs->totbit) {
                putheader_bits(gfc);
            }
            bs->buf[bs->buf_byte_idx] = 0;
        }

        k = Min(j, bs->buf_bit_idx);
        j -= k;

        bs->buf_bit_idx -= k;

        assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */
        assert(bs->buf_bit_idx < MAX_LENGTH);

        bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx);
        bs->totbit += k;
    }
}

/*write j bits into the bit stream, ignoring frame headers */
inline static void
putbits_noheaders(lame_internal_flags * gfc, int val, int j)
{
    Bit_stream_struc *bs;
    bs = &gfc->bs;

    assert(j < MAX_LENGTH - 2);

    while (j > 0) {
        int     k;
        if (bs->buf_bit_idx == 0) {
            bs->buf_bit_idx = 8;
            bs->buf_byte_idx++;
            assert(bs->buf_byte_idx < BUFFER_SIZE);
            bs->buf[bs->buf_byte_idx] = 0;
        }

        k = Min(j, bs->buf_bit_idx);
        j -= k;

        bs->buf_bit_idx -= k;

        assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */
        assert(bs->buf_bit_idx < MAX_LENGTH);

        bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx);
        bs->totbit += k;
    }
}


/*
  Some combinations of bitrate, Fs, and stereo make it impossible to stuff
  out a frame using just main_data, due to the limited number of bits to
  indicate main_data_length. In these situations, we put stuffing bits into
  the ancillary data...
*/

inline static void
drain_into_ancillary(lame_internal_flags * gfc, int remainingBits)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncStateVar_t *const esv = &gfc->sv_enc;
    int     i;
    assert(remainingBits >= 0);

    if (remainingBits >= 8) {
        putbits2(gfc, 0x4c, 8);
        remainingBits -= 8;
    }
    if (remainingBits >= 8) {
        putbits2(gfc, 0x41, 8);
        remainingBits -= 8;
    }
    if (remainingBits >= 8) {
        putbits2(gfc, 0x4d, 8);
        remainingBits -= 8;
    }
    if (remainingBits >= 8) {
        putbits2(gfc, 0x45, 8);
        remainingBits -= 8;
    }

    if (remainingBits >= 32) {
        const char *const version = get_lame_short_version();
        if (remainingBits >= 32)
            for (i = 0; i < (int) strlen(version) && remainingBits >= 8; ++i) {
                remainingBits -= 8;
                putbits2(gfc, version[i], 8);
            }
    }

    for (; remainingBits >= 1; remainingBits -= 1) {
        putbits2(gfc, esv->ancillary_flag, 1);
        esv->ancillary_flag ^= !cfg->disable_reservoir;
    }

    assert(remainingBits == 0);

}

/*write N bits into the header */
inline static void
writeheader(lame_internal_flags * gfc, int val, int j)
{
    EncStateVar_t *const esv = &gfc->sv_enc;
    int     ptr = esv->header[esv->h_ptr].ptr;

    while (j > 0) {
        int const k = Min(j, 8 - (ptr & 7));
        j -= k;
        assert(j < MAX_LENGTH); /* >> 32  too large for 32 bit machines */
        esv->header[esv->h_ptr].buf[ptr >> 3]
            |= ((val >> j)) << (8 - (ptr & 7) - k);
        ptr += k;
    }
    esv->header[esv->h_ptr].ptr = ptr;
}


static int
CRC_update(int value, int crc)
{
    int     i;
    value <<= 8;
    for (i = 0; i < 8; i++) {
        value <<= 1;
        crc <<= 1;

        if (((crc ^ value) & 0x10000))
            crc ^= CRC16_POLYNOMIAL;
    }
    return crc;
}


void
CRC_writeheader(lame_internal_flags const *gfc, char *header)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    int     crc = 0xffff;    /* (jo) init crc16 for error_protection */
    int     i;

    crc = CRC_update(((unsigned char *) header)[2], crc);
    crc = CRC_update(((unsigned char *) header)[3], crc);
    for (i = 6; i < cfg->sideinfo_len; i++) {
        crc = CRC_update(((unsigned char *) header)[i], crc);
    }

    header[4] = crc >> 8;
    header[5] = crc & 255;
}

inline static void
encodeSideInfo2(lame_internal_flags * gfc, int bitsPerFrame)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncResult_t const *const eov = &gfc->ov_enc;
    EncStateVar_t *const esv = &gfc->sv_enc;
    III_side_info_t *l3_side;
    int     gr, ch;

    l3_side = &gfc->l3_side;
    esv->header[esv->h_ptr].ptr = 0;
    memset(esv->header[esv->h_ptr].buf, 0, cfg->sideinfo_len);
    if (cfg->samplerate_out < 16000)
        writeheader(gfc, 0xffe, 12);
    else
        writeheader(gfc, 0xfff, 12);
    writeheader(gfc, (cfg->version), 1);
    writeheader(gfc, 4 - 3, 2);
    writeheader(gfc, (!cfg->error_protection), 1);
    writeheader(gfc, (eov->bitrate_index), 4);
    writeheader(gfc, (cfg->samplerate_index), 2);
    writeheader(gfc, (eov->padding), 1);
    writeheader(gfc, (cfg->extension), 1);
    writeheader(gfc, (cfg->mode), 2);
    writeheader(gfc, (eov->mode_ext), 2);
    writeheader(gfc, (cfg->copyright), 1);
    writeheader(gfc, (cfg->original), 1);
    writeheader(gfc, (cfg->emphasis), 2);
    if (cfg->error_protection) {
        writeheader(gfc, 0, 16); /* dummy */
    }

    if (cfg->version == 1) {
        /* MPEG1 */
        assert(l3_side->main_data_begin >= 0);
        writeheader(gfc, (l3_side->main_data_begin), 9);

        if (cfg->channels_out == 2)
            writeheader(gfc, l3_side->private_bits, 3);
        else
            writeheader(gfc, l3_side->private_bits, 5);

        for (ch = 0; ch < cfg->channels_out; ch++) {
            int     band;
            for (band = 0; band < 4; band++) {
                writeheader(gfc, l3_side->scfsi[ch][band], 1);
            }
        }

        for (gr = 0; gr < 2; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                gr_info *const gi = &l3_side->tt[gr][ch];
                writeheader(gfc, gi->part2_3_length + gi->part2_length, 12);
                writeheader(gfc, gi->big_values / 2, 9);
                writeheader(gfc, gi->global_gain, 8);
                writeheader(gfc, gi->scalefac_compress, 4);

                if (gi->block_type != NORM_TYPE) {
                    writeheader(gfc, 1, 1); /* window_switching_flag */
                    writeheader(gfc, gi->block_type, 2);
                    writeheader(gfc, gi->mixed_block_flag, 1);

                    if (gi->table_select[0] == 14)
                        gi->table_select[0] = 16;
                    writeheader(gfc, gi->table_select[0], 5);
                    if (gi->table_select[1] == 14)
                        gi->table_select[1] = 16;
                    writeheader(gfc, gi->table_select[1], 5);

                    writeheader(gfc, gi->subblock_gain[0], 3);
                    writeheader(gfc, gi->subblock_gain[1], 3);
                    writeheader(gfc, gi->subblock_gain[2], 3);
                }
                else {
                    writeheader(gfc, 0, 1); /* window_switching_flag */
                    if (gi->table_select[0] == 14)
                        gi->table_select[0] = 16;
                    writeheader(gfc, gi->table_select[0], 5);
                    if (gi->table_select[1] == 14)
                        gi->table_select[1] = 16;
                    writeheader(gfc, gi->table_select[1], 5);
                    if (gi->table_select[2] == 14)
                        gi->table_select[2] = 16;
                    writeheader(gfc, gi->table_select[2], 5);

                    assert(0 <= gi->region0_count && gi->region0_count < 16);
                    assert(0 <= gi->region1_count && gi->region1_count < 8);
                    writeheader(gfc, gi->region0_count, 4);
                    writeheader(gfc, gi->region1_count, 3);
                }
                writeheader(gfc, gi->preflag, 1);
                writeheader(gfc, gi->scalefac_scale, 1);
                writeheader(gfc, gi->count1table_select, 1);
            }
        }
    }
    else {
        /* MPEG2 */
        assert(l3_side->main_data_begin >= 0);
        writeheader(gfc, (l3_side->main_data_begin), 8);
        writeheader(gfc, l3_side->private_bits, cfg->channels_out);

        gr = 0;
        for (ch = 0; ch < cfg->channels_out; ch++) {
            gr_info *const gi = &l3_side->tt[gr][ch];
            writeheader(gfc, gi->part2_3_length + gi->part2_length, 12);
            writeheader(gfc, gi->big_values / 2, 9);
            writeheader(gfc, gi->global_gain, 8);
            writeheader(gfc, gi->scalefac_compress, 9);

            if (gi->block_type != NORM_TYPE) {
                writeheader(gfc, 1, 1); /* window_switching_flag */
                writeheader(gfc, gi->block_type, 2);
                writeheader(gfc, gi->mixed_block_flag, 1);

                if (gi->table_select[0] == 14)
                    gi->table_select[0] = 16;
                writeheader(gfc, gi->table_select[0], 5);
                if (gi->table_select[1] == 14)
                    gi->table_select[1] = 16;
                writeheader(gfc, gi->table_select[1], 5);

                writeheader(gfc, gi->subblock_gain[0], 3);
                writeheader(gfc, gi->subblock_gain[1], 3);
                writeheader(gfc, gi->subblock_gain[2], 3);
            }
            else {
                writeheader(gfc, 0, 1); /* window_switching_flag */
                if (gi->table_select[0] == 14)
                    gi->table_select[0] = 16;
                writeheader(gfc, gi->table_select[0], 5);
                if (gi->table_select[1] == 14)
                    gi->table_select[1] = 16;
                writeheader(gfc, gi->table_select[1], 5);
                if (gi->table_select[2] == 14)
                    gi->table_select[2] = 16;
                writeheader(gfc, gi->table_select[2], 5);

                assert(0 <= gi->region0_count && gi->region0_count < 16);
                assert(0 <= gi->region1_count && gi->region1_count < 8);
                writeheader(gfc, gi->region0_count, 4);
                writeheader(gfc, gi->region1_count, 3);
            }

            writeheader(gfc, gi->scalefac_scale, 1);
            writeheader(gfc, gi->count1table_select, 1);
        }
    }

    if (cfg->error_protection) {
        /* (jo) error_protection: add crc16 information to header */
        CRC_writeheader(gfc, esv->header[esv->h_ptr].buf);
    }

    {
        int const old = esv->h_ptr;
        assert(esv->header[old].ptr == cfg->sideinfo_len * 8);

        esv->h_ptr = (old + 1) & (MAX_HEADER_BUF - 1);
        esv->header[esv->h_ptr].write_timing = esv->header[old].write_timing + bitsPerFrame;

        if (esv->h_ptr == esv->w_ptr) {
            /* yikes! we are out of header buffer space */
            ERRORF(gfc, "Error: MAX_HEADER_BUF too small in bitstream.c \n");
        }

    }
}


inline static int
huffman_coder_count1(lame_internal_flags * gfc, gr_info const *gi)
{
    /* Write count1 area */
    struct huffcodetab const *const h = &ht[gi->count1table_select + 32];
    int     i, bits = 0;
#ifdef DEBUG
    int     gegebo = gfc->bs.totbit;
#endif

    int const *ix = &gi->l3_enc[gi->big_values];
    FLOAT const *xr = &gi->xr[gi->big_values];
    assert(gi->count1table_select < 2);

    for (i = (gi->count1 - gi->big_values) / 4; i > 0; --i) {
        int     huffbits = 0;
        int     p = 0, v;

        v = ix[0];
        if (v) {
            p += 8;
            if (xr[0] < 0.0f)
                huffbits++;
            assert(v <= 1);
        }

        v = ix[1];
        if (v) {
            p += 4;
            huffbits *= 2;
            if (xr[1] < 0.0f)
                huffbits++;
            assert(v <= 1);
        }

        v = ix[2];
        if (v) {
            p += 2;
            huffbits *= 2;
            if (xr[2] < 0.0f)
                huffbits++;
            assert(v <= 1);
        }

        v = ix[3];
        if (v) {
            p++;
            huffbits *= 2;
            if (xr[3] < 0.0f)
                huffbits++;
            assert(v <= 1);
        }

        ix += 4;
        xr += 4;
        putbits2(gfc, huffbits + h->table[p], h->hlen[p]);
        bits += h->hlen[p];
    }
#ifdef DEBUG
    DEBUGF(gfc, "count1: real: %ld counted:%d (bigv %d count1len %d)\n",
           gfc->bs.totbit - gegebo, gi->count1bits, gi->big_values, gi->count1);
#endif
    return bits;
}



/*
  Implements the pseudocode of page 98 of the IS
  */
inline static int
Huffmancode(lame_internal_flags * const gfc, const unsigned int tableindex,
            int start, int end, gr_info const *gi)
{
    struct huffcodetab const *const h = &ht[tableindex];
    unsigned int const linbits = h->xlen;
    int     i, bits = 0;

    assert(tableindex < 32u);
    if (!tableindex)
        return bits;

    for (i = start; i < end; i += 2) {
        int16_t  cbits = 0;
        uint16_t xbits = 0;
        unsigned int xlen = h->xlen;
        unsigned int ext = 0;
        unsigned int x1 = gi->l3_enc[i];
        unsigned int x2 = gi->l3_enc[i + 1];

        assert(gi->l3_enc[i] >= 0);
        assert(gi->l3_enc[i+1] >= 0);

        if (x1 != 0u) {
            if (gi->xr[i] < 0.0f)
                ext++;
            cbits--;
        }

        if (tableindex > 15u) {
            /* use ESC-words */
            if (x1 >= 15u) {
                uint16_t const linbits_x1 = x1 - 15u;
                assert(linbits_x1 <= h->linmax);
                ext |= linbits_x1 << 1u;
                xbits = linbits;
                x1 = 15u;
            }

            if (x2 >= 15u) {
                uint16_t const linbits_x2 = x2 - 15u;
                assert(linbits_x2 <= h->linmax);
                ext <<= linbits;
                ext |= linbits_x2;
                xbits += linbits;
                x2 = 15u;
            }
            xlen = 16;
        }

        if (x2 != 0u) {
            ext <<= 1;
            if (gi->xr[i + 1] < 0.0f)
                ext++;
            cbits--;
        }

        assert((x1 | x2) < 16u);

        x1 = x1 * xlen + x2;
        xbits -= cbits;
        cbits += h->hlen[x1];

        assert(cbits <= MAX_LENGTH);
        assert(xbits <= MAX_LENGTH);

        putbits2(gfc, h->table[x1], cbits);
        putbits2(gfc, (int)ext, xbits);
        bits += cbits + xbits;
    }
    return bits;
}

/*
  Note the discussion of huffmancodebits() on pages 28
  and 29 of the IS, as well as the definitions of the side
  information on pages 26 and 27.
  */
static int
ShortHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi)
{
    int     bits;
    int     region1Start;

    region1Start = 3 * gfc->scalefac_band.s[3];
    if (region1Start > gi->big_values)
        region1Start = gi->big_values;

    /* short blocks do not have a region2 */
    bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi);
    bits += Huffmancode(gfc, gi->table_select[1], region1Start, gi->big_values, gi);
    return bits;
}

static int
LongHuffmancodebits(lame_internal_flags * gfc, gr_info const *gi)
{
    unsigned int i;
    int     bigvalues, bits;
    int     region1Start, region2Start;

    bigvalues = gi->big_values;
    assert(0 <= bigvalues && bigvalues <= 576);

    assert(gi->region0_count >= -1);
    assert(gi->region1_count >= -1);
    i = gi->region0_count + 1;
    assert((size_t) i < dimension_of(gfc->scalefac_band.l));
    region1Start = gfc->scalefac_band.l[i];
    i += gi->region1_count + 1;
    assert((size_t) i < dimension_of(gfc->scalefac_band.l));
    region2Start = gfc->scalefac_band.l[i];

    if (region1Start > bigvalues)
        region1Start = bigvalues;

    if (region2Start > bigvalues)
        region2Start = bigvalues;

    bits = Huffmancode(gfc, gi->table_select[0], 0, region1Start, gi);
    bits += Huffmancode(gfc, gi->table_select[1], region1Start, region2Start, gi);
    bits += Huffmancode(gfc, gi->table_select[2], region2Start, bigvalues, gi);
    return bits;
}

inline static int
writeMainData(lame_internal_flags * const gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    III_side_info_t const *const l3_side = &gfc->l3_side;
    int     gr, ch, sfb, data_bits, tot_bits = 0;

    if (cfg->version == 1) {
        /* MPEG 1 */
        for (gr = 0; gr < 2; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                gr_info const *const gi = &l3_side->tt[gr][ch];
                int const slen1 = slen1_tab[gi->scalefac_compress];
                int const slen2 = slen2_tab[gi->scalefac_compress];
                data_bits = 0;
#ifdef DEBUG
                hogege = gfc->bs.totbit;
#endif
                for (sfb = 0; sfb < gi->sfbdivide; sfb++) {
                    if (gi->scalefac[sfb] == -1)
                        continue; /* scfsi is used */
                    putbits2(gfc, gi->scalefac[sfb], slen1);
                    data_bits += slen1;
                }
                for (; sfb < gi->sfbmax; sfb++) {
                    if (gi->scalefac[sfb] == -1)
                        continue; /* scfsi is used */
                    putbits2(gfc, gi->scalefac[sfb], slen2);
                    data_bits += slen2;
                }
                assert(data_bits == gi->part2_length);

                if (gi->block_type == SHORT_TYPE) {
                    data_bits += ShortHuffmancodebits(gfc, gi);
                }
                else {
                    data_bits += LongHuffmancodebits(gfc, gi);
                }
                data_bits += huffman_coder_count1(gfc, gi);
#ifdef DEBUG
                DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege);
#endif
                /* does bitcount in quantize.c agree with actual bit count? */
                assert(data_bits == gi->part2_3_length + gi->part2_length);
                tot_bits += data_bits;
            }           /* for ch */
        }               /* for gr */
    }
    else {
        /* MPEG 2 */
        gr = 0;
        for (ch = 0; ch < cfg->channels_out; ch++) {
            gr_info const *const gi = &l3_side->tt[gr][ch];
            int     i, sfb_partition, scale_bits = 0;
            assert(gi->sfb_partition_table);
            data_bits = 0;
#ifdef DEBUG
            hogege = gfc->bs.totbit;
#endif
            sfb = 0;
            sfb_partition = 0;

            if (gi->block_type == SHORT_TYPE) {
                for (; sfb_partition < 4; sfb_partition++) {
                    int const sfbs = gi->sfb_partition_table[sfb_partition] / 3;
                    int const slen = gi->slen[sfb_partition];
                    for (i = 0; i < sfbs; i++, sfb++) {
                        putbits2(gfc, Max(gi->scalefac[sfb * 3 + 0], 0), slen);
                        putbits2(gfc, Max(gi->scalefac[sfb * 3 + 1], 0), slen);
                        putbits2(gfc, Max(gi->scalefac[sfb * 3 + 2], 0), slen);
                        scale_bits += 3 * slen;
                    }
                }
                data_bits += ShortHuffmancodebits(gfc, gi);
            }
            else {
                for (; sfb_partition < 4; sfb_partition++) {
                    int const sfbs = gi->sfb_partition_table[sfb_partition];
                    int const slen = gi->slen[sfb_partition];
                    for (i = 0; i < sfbs; i++, sfb++) {
                        putbits2(gfc, Max(gi->scalefac[sfb], 0), slen);
                        scale_bits += slen;
                    }
                }
                data_bits += LongHuffmancodebits(gfc, gi);
            }
            data_bits += huffman_coder_count1(gfc, gi);
#ifdef DEBUG
            DEBUGF(gfc, "<%ld> ", gfc->bs.totbit - hogege);
#endif
            /* does bitcount in quantize.c agree with actual bit count? */
            assert(data_bits == gi->part2_3_length);
            assert(scale_bits == gi->part2_length);
            tot_bits += scale_bits + data_bits;
        }               /* for ch */
    }                   /* for gf */
    return tot_bits;
}                       /* main_data */



/* compute the number of bits required to flush all mp3 frames
   currently in the buffer.  This should be the same as the
   reservoir size.  Only call this routine between frames - i.e.
   only after all headers and data have been added to the buffer
   by format_bitstream().

   Also compute total_bits_output =
       size of mp3 buffer (including frame headers which may not
       have yet been send to the mp3 buffer) +
       number of bits needed to flush all mp3 frames.

   total_bytes_output is the size of the mp3 output buffer if
   lame_encode_flush_nogap() was called right now.

 */
int
compute_flushbits(const lame_internal_flags * gfc, int *total_bytes_output)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncStateVar_t const *const esv = &gfc->sv_enc;
    int     flushbits, remaining_headers;
    int     bitsPerFrame;
    int     last_ptr, first_ptr;
    first_ptr = esv->w_ptr; /* first header to add to bitstream */
    last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */
    if (last_ptr == -1)
        last_ptr = MAX_HEADER_BUF - 1;

    /* add this many bits to bitstream so we can flush all headers */
    flushbits = esv->header[last_ptr].write_timing - gfc->bs.totbit;
    *total_bytes_output = flushbits;

    if (flushbits >= 0) {
        /* if flushbits >= 0, some headers have not yet been written */
        /* reduce flushbits by the size of the headers */
        remaining_headers = 1 + last_ptr - first_ptr;
        if (last_ptr < first_ptr)
            remaining_headers = 1 + last_ptr - first_ptr + MAX_HEADER_BUF;
        flushbits -= remaining_headers * 8 * cfg->sideinfo_len;
    }


    /* finally, add some bits so that the last frame is complete
     * these bits are not necessary to decode the last frame, but
     * some decoders will ignore last frame if these bits are missing
     */
    bitsPerFrame = getframebits(gfc);
    flushbits += bitsPerFrame;
    *total_bytes_output += bitsPerFrame;
    /* round up:   */
    if (*total_bytes_output % 8)
        *total_bytes_output = 1 + (*total_bytes_output / 8);
    else
        *total_bytes_output = (*total_bytes_output / 8);
    *total_bytes_output += gfc->bs.buf_byte_idx + 1;


    if (flushbits < 0) {
#if 0
        /* if flushbits < 0, this would mean that the buffer looks like:
         * (data...)  last_header  (data...)  (extra data that should not be here...)
         */
        DEBUGF(gfc, "last header write_timing = %i \n", esv->header[last_ptr].write_timing);
        DEBUGF(gfc, "first header write_timing = %i \n", esv->header[first_ptr].write_timing);
        DEBUGF(gfc, "bs.totbit:                 %i \n", gfc->bs.totbit);
        DEBUGF(gfc, "first_ptr, last_ptr        %i %i \n", first_ptr, last_ptr);
        DEBUGF(gfc, "remaining_headers =        %i \n", remaining_headers);
        DEBUGF(gfc, "bitsperframe:              %i \n", bitsPerFrame);
        DEBUGF(gfc, "sidelen:                   %i \n", cfg->sideinfo_len);
#endif
        ERRORF(gfc, "strange error flushing buffer ... \n");
    }
    return flushbits;
}


void
flush_bitstream(lame_internal_flags * gfc)
{
    EncStateVar_t *const esv = &gfc->sv_enc;
    III_side_info_t *l3_side;
    int     nbytes;
    int     flushbits;
    int     last_ptr = esv->h_ptr - 1; /* last header to add to bitstream */
    if (last_ptr == -1)
        last_ptr = MAX_HEADER_BUF - 1;
    l3_side = &gfc->l3_side;


    if ((flushbits = compute_flushbits(gfc, &nbytes)) < 0)
        return;
    drain_into_ancillary(gfc, flushbits);

    /* check that the 100% of the last frame has been written to bitstream */
    assert(esv->header[last_ptr].write_timing + getframebits(gfc)
           == gfc->bs.totbit);

    /* we have padded out all frames with ancillary data, which is the
       same as filling the bitreservoir with ancillary data, so : */
    esv->ResvSize = 0;
    l3_side->main_data_begin = 0;
}




void
add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n)
{
    EncStateVar_t *const esv = &gfc->sv_enc;
    int     i;

    while (n-- > 0u) {
        putbits_noheaders(gfc, val, 8);

        for (i = 0; i < MAX_HEADER_BUF; ++i)
            esv->header[i].write_timing += 8;
    }
}


/*
  format_bitstream()

  This is called after a frame of audio has been quantized and coded.
  It will write the encoded audio to the bitstream. Note that
  from a layer3 encoder's perspective the bit stream is primarily
  a series of main_data() blocks, with header and side information
  inserted at the proper locations to maintain framing. (See Figure A.7
  in the IS).
  */
int
format_bitstream(lame_internal_flags * gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncStateVar_t *const esv = &gfc->sv_enc;
    int     bits, nbytes;
    III_side_info_t *l3_side;
    int     bitsPerFrame;
    l3_side = &gfc->l3_side;

    bitsPerFrame = getframebits(gfc);
    drain_into_ancillary(gfc, l3_side->resvDrain_pre);

    encodeSideInfo2(gfc, bitsPerFrame);
    bits = 8 * cfg->sideinfo_len;
    bits += writeMainData(gfc);
    drain_into_ancillary(gfc, l3_side->resvDrain_post);
    bits += l3_side->resvDrain_post;

    l3_side->main_data_begin += (bitsPerFrame - bits) / 8;

    /* compare number of bits needed to clear all buffered mp3 frames
     * with what we think the resvsize is: */
    if (compute_flushbits(gfc, &nbytes) != esv->ResvSize) {
        ERRORF(gfc, "Internal buffer inconsistency. flushbits <> ResvSize");
    }


    /* compare main_data_begin for the next frame with what we
     * think the resvsize is: */
    if ((l3_side->main_data_begin * 8) != esv->ResvSize) {
        ERRORF(gfc, "bit reservoir error: \n"
               "l3_side->main_data_begin: %i \n"
               "Resvoir size:             %i \n"
               "resv drain (post)         %i \n"
               "resv drain (pre)          %i \n"
               "header and sideinfo:      %i \n"
               "data bits:                %i \n"
               "total bits:               %i (remainder: %i) \n"
               "bitsperframe:             %i \n",
               8 * l3_side->main_data_begin,
               esv->ResvSize,
               l3_side->resvDrain_post,
               l3_side->resvDrain_pre,
               8 * cfg->sideinfo_len,
               bits - l3_side->resvDrain_post - 8 * cfg->sideinfo_len,
               bits, bits % 8, bitsPerFrame);

        ERRORF(gfc, "This is a fatal error.  It has several possible causes:");
        ERRORF(gfc, "90%%  LAME compiled with buggy version of gcc using advanced optimizations");
        ERRORF(gfc, " 9%%  Your system is overclocked");
        ERRORF(gfc, " 1%%  bug in LAME encoding library");

        esv->ResvSize = l3_side->main_data_begin * 8;
    };
    assert(gfc->bs.totbit % 8 == 0);

    if (gfc->bs.totbit > 1000000000) {
        /* to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset bit counter */
        int     i;
        for (i = 0; i < MAX_HEADER_BUF; ++i)
            esv->header[i].write_timing -= gfc->bs.totbit;
        gfc->bs.totbit = 0;
    }


    return 0;
}


static int
do_gain_analysis(lame_internal_flags * gfc, unsigned char* buffer, int minimum)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    RpgStateVar_t const *const rsv = &gfc->sv_rpg;
    RpgResult_t *const rov = &gfc->ov_rpg;
#ifdef DECODE_ON_THE_FLY
    if (cfg->decode_on_the_fly) { /* decode the frame */
        sample_t pcm_buf[2][1152];
        int     mp3_in = minimum;
        int     samples_out = -1;

        /* re-synthesis to pcm.  Repeat until we get a samples_out=0 */
        while (samples_out != 0) {

            samples_out = hip_decode1_unclipped(gfc->hip, buffer, mp3_in, pcm_buf[0], pcm_buf[1]);
            /* samples_out = 0:  need more data to decode
             * samples_out = -1:  error.  Lets assume 0 pcm output
             * samples_out = number of samples output */

            /* set the lenght of the mp3 input buffer to zero, so that in the
             * next iteration of the loop we will be querying mpglib about
             * buffered data */
            mp3_in = 0;

            if (samples_out == -1) {
                /* error decoding. Not fatal, but might screw up
                 * the ReplayGain tag. What should we do? Ignore for now */
                samples_out = 0;
            }
            if (samples_out > 0) {
                /* process the PCM data */

                /* this should not be possible, and indicates we have
                 * overflown the pcm_buf buffer */
                assert(samples_out <= 1152);

                if (cfg->findPeakSample) {
                    int     i;
                    /* FIXME: is this correct? maybe Max(fabs(pcm),PeakSample) */
                    for (i = 0; i < samples_out; i++) {
                        if (pcm_buf[0][i] > rov->PeakSample)
                            rov->PeakSample = pcm_buf[0][i];
                        else if (-pcm_buf[0][i] > rov->PeakSample)
                            rov->PeakSample = -pcm_buf[0][i];
                    }
                    if (cfg->channels_out > 1)
                        for (i = 0; i < samples_out; i++) {
                            if (pcm_buf[1][i] > rov->PeakSample)
                                rov->PeakSample = pcm_buf[1][i];
                            else if (-pcm_buf[1][i] > rov->PeakSample)
                                rov->PeakSample = -pcm_buf[1][i];
                        }
                }

                if (cfg->findReplayGain)
                    if (AnalyzeSamples
                        (rsv->rgdata, pcm_buf[0], pcm_buf[1], samples_out,
                         cfg->channels_out) == GAIN_ANALYSIS_ERROR)
                        return -6;

            }       /* if (samples_out>0) */
        }           /* while (samples_out!=0) */
    }               /* if (gfc->decode_on_the_fly) */
#endif
    return minimum;
}

static int
do_copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size)
{
    Bit_stream_struc *const bs = &gfc->bs;
    int const minimum = bs->buf_byte_idx + 1;
    if (minimum <= 0)
        return 0;
    if (size != 0 && minimum > size)
        return -1;      /* buffer is too small */
    memcpy(buffer, bs->buf, minimum);
    bs->buf_byte_idx = -1;
    bs->buf_bit_idx = 0;
    return minimum;
}

/* copy data out of the internal MP3 bit buffer into a user supplied
   unsigned char buffer.

   mp3data=0      indicates data in buffer is an id3tags and VBR tags
   mp3data=1      data is real mp3 frame data.


*/
int
copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int size, int mp3data)
{
    int const minimum = do_copy_buffer(gfc, buffer, size);
    if (minimum > 0 && mp3data) {
        UpdateMusicCRC(&gfc->nMusicCRC, buffer, minimum);

        /** sum number of bytes belonging to the mp3 stream
         *  this info will be written into the Xing/LAME header for seeking
         */
        gfc->VBR_seek_table.nBytesWritten += minimum;

        return do_gain_analysis(gfc, buffer, minimum);
    }                   /* if (mp3data) */
    return minimum;
}


void
init_bit_stream_w(lame_internal_flags * gfc)
{
    EncStateVar_t *const esv = &gfc->sv_enc;

    esv->h_ptr = esv->w_ptr = 0;
    esv->header[esv->h_ptr].write_timing = 0;

    gfc->bs.buf = (unsigned char *) malloc(BUFFER_SIZE);
    gfc->bs.buf_size = BUFFER_SIZE;
    gfc->bs.buf_byte_idx = -1;
    gfc->bs.buf_bit_idx = 0;
    gfc->bs.totbit = 0;
}

/* end of bitstream.c */


================================================
FILE: app/src/main/jni/libmp3lame/bitstream.h
================================================
/*
 *	MP3 bitstream Output interface for LAME
 *
 *	Copyright (c) 1999 Takehiro TOMINAGA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef LAME_BITSTREAM_H
#define LAME_BITSTREAM_H

int     getframebits(const lame_internal_flags * gfc);

int     format_bitstream(lame_internal_flags * gfc);

void    flush_bitstream(lame_internal_flags * gfc);
void    add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n);

int     copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int buffer_size,
                    int update_crc);
void    init_bit_stream_w(lame_internal_flags * gfc);
void    CRC_writeheader(lame_internal_flags const *gfc, char *buffer);
int     compute_flushbits(const lame_internal_flags * gfp, int *nbytes);

int     get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint);

#endif


================================================
FILE: app/src/main/jni/libmp3lame/encoder.c
================================================
/*
 *      LAME MP3 encoding engine
 *
 *      Copyright (c) 1999 Mark Taylor
 *      Copyright (c) 2000-2002 Takehiro Tominaga
 *      Copyright (c) 2000-2011 Robert Hegemann
 *      Copyright (c) 2001 Gabriel Bouvigne
 *      Copyright (c) 2001 John Dahlstrom
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* $Id: encoder.c,v 1.111 2011/05/07 16:05:17 rbrito Exp $ */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif


#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "util.h"
#include "lame_global_flags.h"
#include "newmdct.h"
#include "psymodel.h"
#include "lame-analysis.h"
#include "bitstream.h"
#include "VbrTag.h"
#include "quantize_pvt.h"



/*
 * auto-adjust of ATH, useful for low volume
 * Gabriel Bouvigne 3 feb 2001
 *
 * modifies some values in
 *   gfp->internal_flags->ATH
 *   (gfc->ATH)
 */
static void
adjust_ATH(lame_internal_flags const *const gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    FLOAT   gr2_max, max_pow;

    if (gfc->ATH->use_adjust == 0) {
        gfc->ATH->adjust_factor = 1.0; /* no adjustment */
        return;
    }

    /* jd - 2001 mar 12, 27, jun 30 */
    /* loudness based on equal loudness curve; */
    /* use granule with maximum combined loudness */
    max_pow = gfc->ov_psy.loudness_sq[0][0];
    gr2_max = gfc->ov_psy.loudness_sq[1][0];
    if (cfg->channels_out == 2) {
        max_pow += gfc->ov_psy.loudness_sq[0][1];
        gr2_max += gfc->ov_psy.loudness_sq[1][1];
    }
    else {
        max_pow += max_pow;
        gr2_max += gr2_max;
    }
    if (cfg->mode_gr == 2) {
        max_pow = Max(max_pow, gr2_max);
    }
    max_pow *= 0.5;     /* max_pow approaches 1.0 for full band noise */

    /* jd - 2001 mar 31, jun 30 */
    /* user tuning of ATH adjustment region */
    max_pow *= gfc->ATH->aa_sensitivity_p;

    /*  adjust ATH depending on range of maximum value
     */

    /* jd - 2001 feb27, mar12,20, jun30, jul22 */
    /* continuous curves based on approximation */
    /* to GB's original values. */
    /* For an increase in approximate loudness, */
    /* set ATH adjust to adjust_limit immediately */
    /* after a delay of one frame. */
    /* For a loudness decrease, reduce ATH adjust */
    /* towards adjust_limit gradually. */
    /* max_pow is a loudness squared or a power. */
    if (max_pow > 0.03125) { /* ((1 - 0.000625)/ 31.98) from curve below */
        if (gfc->ATH->adjust_factor >= 1.0) {
            gfc->ATH->adjust_factor = 1.0;
        }
        else {
            /* preceding frame has lower ATH adjust; */
            /* ascend only to the preceding adjust_limit */
            /* in case there is leading low volume */
            if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) {
                gfc->ATH->adjust_factor = gfc->ATH->adjust_limit;
            }
        }
        gfc->ATH->adjust_limit = 1.0;
    }
    else {              /* adjustment curve */
        /* about 32 dB maximum adjust (0.000625) */
        FLOAT const adj_lim_new = 31.98 * max_pow + 0.000625;
        if (gfc->ATH->adjust_factor >= adj_lim_new) { /* descend gradually */
            gfc->ATH->adjust_factor *= adj_lim_new * 0.075 + 0.925;
            if (gfc->ATH->adjust_factor < adj_lim_new) { /* stop descent */
                gfc->ATH->adjust_factor = adj_lim_new;
            }
        }
        else {          /* ascend */
            if (gfc->ATH->adjust_limit >= adj_lim_new) {
                gfc->ATH->adjust_factor = adj_lim_new;
            }
            else {      /* preceding frame has lower ATH adjust; */
                /* ascend only to the preceding adjust_limit */
                if (gfc->ATH->adjust_factor < gfc->ATH->adjust_limit) {
                    gfc->ATH->adjust_factor = gfc->ATH->adjust_limit;
                }
            }
        }
        gfc->ATH->adjust_limit = adj_lim_new;
    }
}

/***********************************************************************
 *
 *  some simple statistics
 *
 *  bitrate index 0: free bitrate -> not allowed in VBR mode
 *  : bitrates, kbps depending on MPEG version
 *  bitrate index 15: forbidden
 *
 *  mode_ext:
 *  0:  LR
 *  1:  LR-i
 *  2:  MS
 *  3:  MS-i
 *
 ***********************************************************************/

static void
updateStats(lame_internal_flags * const gfc)
{
    SessionConfig_t const *const cfg = &gfc->cfg;
    EncResult_t *eov = &gfc->ov_enc;
    int     gr, ch;
    assert(0 <= eov->bitrate_index && eov->bitrate_index < 16);
    assert(0 <= eov->mode_ext && eov->mode_ext < 4);

    /* count bitrate indices */
    eov->bitrate_channelmode_hist[eov->bitrate_index][4]++;
    eov->bitrate_channelmode_hist[15][4]++;

    /* count 'em for every mode extension in case of 2 channel encoding */
    if (cfg->channels_out == 2) {
        eov->bitrate_channelmode_hist[eov->bitrate_index][eov->mode_ext]++;
        eov->bitrate_channelmode_hist[15][eov->mode_ext]++;
    }
    for (gr = 0; gr < cfg->mode_gr; ++gr) {
        for (ch = 0; ch < cfg->channels_out; ++ch) {
            int     bt = gfc->l3_side.tt[gr][ch].block_type;
            if (gfc->l3_side.tt[gr][ch].mixed_block_flag)
                bt = 4;
            eov->bitrate_blocktype_hist[eov->bitrate_index][bt]++;
            eov->bitrate_blocktype_hist[eov->bitrate_index][5]++;
            eov->bitrate_blocktype_hist[15][bt]++;
            eov->bitrate_blocktype_hist[15][5]++;
        }
    }
}




static void
lame_encode_frame_init(lame_internal_flags * gfc, const sample_t *const inbuf[2])
{
    SessionConfig_t const *const cfg = &gfc->cfg;

    int     ch, gr;

    if (gfc->lame_encode_frame_init == 0) {
        sample_t primebuff0[286 + 1152 + 576];
        sample_t primebuff1[286 + 1152 + 576];
        int const framesize = 576 * cfg->mode_gr;
        /* prime the MDCT/polyphase filterbank with a short block */
        int     i, j;
        gfc->lame_encode_frame_init = 1;
        memset(primebuff0, 0, sizeof(primebuff0));
        memset(primebuff1, 0, sizeof(primebuff1));
        for (i = 0, j = 0; i < 286 + 576 * (1 + cfg->mode_gr); ++i) {
            if (i < framesize) {
                primebuff0[i] = 0;
                if (cfg->channels_out == 2)
                    primebuff1[i] = 0;
            }
            else {
                primebuff0[i] = inbuf[0][j];
                if (cfg->channels_out == 2)
                    primebuff1[i] = inbuf[1][j];
                ++j;
            }
        }
        /* polyphase filtering / mdct */
        for (gr = 0; gr < cfg->mode_gr; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                gfc->l3_side.tt[gr][ch].block_type = SHORT_TYPE;
            }
        }
        mdct_sub48(gfc, primebuff0, primebuff1);

        /* check FFT will not use a negative starting offset */
#if 576 < FFTOFFSET
# error FFTOFFSET greater than 576: FFT uses a negative offset
#endif
        /* check if we have enough data for FFT */
        assert(gfc->sv_enc.mf_size >= (BLKSIZE + framesize - FFTOFFSET));
        /* check if we have enough data for polyphase filterbank */
        assert(gfc->sv_enc.mf_size >= (512 + framesize - 32));
    }

}







/************************************************************************
*
* encodeframe()           Layer 3
*
* encode a single frame
*
************************************************************************
lame_encode_frame()


                       gr 0            gr 1
inbuf:           |--------------|--------------|--------------|


Polyphase (18 windows, each shifted 32)
gr 0:
window1          <----512---->
window18                 <----512---->

gr 1:
window1                         <----512---->
window18                                <----512---->



MDCT output:  |--------------|--------------|--------------|

FFT's                    <---------1024---------->
                                         <---------1024-------->



    inbuf = buffer of PCM data size=MP3 framesize
    encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY
    so the MDCT coefficints are from inbuf[ch][-MDCTDELAY]

    psy-model FFT has a 1 granule delay, so we feed it data for the 
    next granule.
    FFT is centered over granule:  224+576+224
    So FFT starts at:   576-224-MDCTDELAY

    MPEG2:  FFT ends at:  BLKSIZE+576-224-MDCTDELAY      (1328)
    MPEG1:  FFT ends at:  BLKSIZE+2*576-224-MDCTDELAY    (1904)

    MPEG2:  polyphase first window:  [0..511]
                      18th window:   [544..1055]          (1056)
    MPEG1:            36th window:   [1120..1631]         (1632)
            data needed:  512+framesize-32

    A close look newmdct.c shows that the polyphase filterbank
    only uses data from [0..510] for each window.  Perhaps because the window
    used by the filterbank is zero for the last point, so Takehiro's
    code doesn't bother to compute with it.

    FFT starts at 576-224-MDCTDELAY (304)  = 576-FFTOFFSET

*/

typedef FLOAT chgrdata[2][2];


int
lame_encode_mp3_frame(       /* Output */
                         lame_internal_flags * gfc, /* Context */
                         sample_t const *inbuf_l, /* Input */
                         sample_t const *inbuf_r, /* Input */
                         unsigned char *mp3buf, /* Output */
                         int mp3buf_size)
{                       /* Output */
    SessionConfig_t const *const cfg = &gfc->cfg;
    int     mp3count;
    III_psy_ratio masking_LR[2][2]; /*LR masking & energy */
    III_psy_ratio masking_MS[2][2]; /*MS masking & energy */
    const III_psy_ratio (*masking)[2]; /*pointer to selected maskings */
    const sample_t *inbuf[2];

    FLOAT   tot_ener[2][4];
    FLOAT   ms_ener_ratio[2] = { .5, .5 };
    FLOAT   pe[2][2] = { {0., 0.}, {0., 0.} }, pe_MS[2][2] = { {
    0., 0.}, {
    0., 0.}};
    FLOAT (*pe_use)[2];

    int     ch, gr;

    inbuf[0] = inbuf_l;
    inbuf[1] = inbuf_r;

    if (gfc->lame_encode_frame_init == 0) {
        /*first run? */
        lame_encode_frame_init(gfc, inbuf);

    }


    /********************** padding *****************************/
    /* padding method as described in 
     * "MPEG-Layer3 / Bitstream Syntax and Decoding"
     * by Martin Sieler, Ralph Sperschneider
     *
     * note: there is no padding for the very first frame
     *
     * Robert Hegemann 2000-06-22
     */
    gfc->ov_enc.padding = FALSE;
    if ((gfc->sv_enc.slot_lag -= gfc->sv_enc.frac_SpF) < 0) {
        gfc->sv_enc.slot_lag += cfg->samplerate_out;
        gfc->ov_enc.padding = TRUE;
    }



    /****************************************
    *   Stage 1: psychoacoustic model       *
    ****************************************/

    {
        /* psychoacoustic model
         * psy model has a 1 granule (576) delay that we must compensate for
         * (mt 6/99).
         */
        int     ret;
        const sample_t *bufp[2] = {0, 0}; /* address of beginning of left & right granule */
        int     blocktype[2];

        for (gr = 0; gr < cfg->mode_gr; gr++) {

            for (ch = 0; ch < cfg->channels_out; ch++) {
                bufp[ch] = &inbuf[ch][576 + gr * 576 - FFTOFFSET];
            }
            ret = L3psycho_anal_vbr(gfc, bufp, gr,
                                    masking_LR, masking_MS,
                                    pe[gr], pe_MS[gr], tot_ener[gr], blocktype);
            if (ret != 0)
                return -4;

            if (cfg->mode == JOINT_STEREO) {
                ms_ener_ratio[gr] = tot_ener[gr][2] + tot_ener[gr][3];
                if (ms_ener_ratio[gr] > 0)
                    ms_ener_ratio[gr] = tot_ener[gr][3] / ms_ener_ratio[gr];
            }

            /* block type flags */
            for (ch = 0; ch < cfg->channels_out; ch++) {
                gr_info *const cod_info = &gfc->l3_side.tt[gr][ch];
                cod_info->block_type = blocktype[ch];
                cod_info->mixed_block_flag = 0;
            }
        }
    }


    /* auto-adjust of ATH, useful for low volume */
    adjust_ATH(gfc);


    /****************************************
    *   Stage 2: MDCT                       *
    ****************************************/

    /* polyphase filtering / mdct */
    mdct_sub48(gfc, inbuf[0], inbuf[1]);


    /****************************************
    *   Stage 3: MS/LR decision             *
    ****************************************/

    /* Here will be selected MS or LR coding of the 2 stereo channels */
    gfc->ov_enc.mode_ext = MPG_MD_LR_LR;

    if (cfg->force_ms) {
        gfc->ov_enc.mode_ext = MPG_MD_MS_LR;
    }
    else if (cfg->mode == JOINT_STEREO) {
        /* ms_ratio = is scaled, for historical reasons, to look like
           a ratio of side_channel / total.
           0 = signal is 100% mono
           .5 = L & R uncorrelated
         */

        /* [0] and [1] are the results for the two granules in MPEG-1,
         * in MPEG-2 it's only a faked averaging of the same value
         * _prev is the value of the last granule of the previous frame
         * _next is the value of the first granule of the next frame
         */

        FLOAT   sum_pe_MS = 0;
        FLOAT   sum_pe_LR = 0;
        for (gr = 0; gr < cfg->mode_gr; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                sum_pe_MS += pe_MS[gr][ch];
                sum_pe_LR += pe[gr][ch];
            }
        }

        /* based on PE: M/S coding would not use much more bits than L/R */
        if (sum_pe_MS <= 1.00 * sum_pe_LR) {

            gr_info const *const gi0 = &gfc->l3_side.tt[0][0];
            gr_info const *const gi1 = &gfc->l3_side.tt[cfg->mode_gr - 1][0];

            if (gi0[0].block_type == gi0[1].block_type && gi1[0].block_type == gi1[1].block_type) {

                gfc->ov_enc.mode_ext = MPG_MD_MS_LR;
            }
        }
    }

    /* bit and noise allocation */
    if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) {
        masking = (const III_psy_ratio (*)[2])masking_MS; /* use MS masking */
        pe_use = pe_MS;
    }
    else {
        masking = (const III_psy_ratio (*)[2])masking_LR; /* use LR masking */
        pe_use = pe;
    }


    /* copy data for MP3 frame analyzer */
    if (cfg->analysis && gfc->pinfo != NULL) {
        for (gr = 0; gr < cfg->mode_gr; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                gfc->pinfo->ms_ratio[gr] = 0;
                gfc->pinfo->ms_ener_ratio[gr] = ms_ener_ratio[gr];
                gfc->pinfo->blocktype[gr][ch] = gfc->l3_side.tt[gr][ch].block_type;
                gfc->pinfo->pe[gr][ch] = pe_use[gr][ch];
                memcpy(gfc->pinfo->xr[gr][ch], &gfc->l3_side.tt[gr][ch].xr[0], sizeof(FLOAT) * 576);
                /* in psymodel, LR and MS data was stored in pinfo.  
                   switch to MS data: */
                if (gfc->ov_enc.mode_ext == MPG_MD_MS_LR) {
                    gfc->pinfo->ers[gr][ch] = gfc->pinfo->ers[gr][ch + 2];
                    memcpy(gfc->pinfo->energy[gr][ch], gfc->pinfo->energy[gr][ch + 2],
                           sizeof(gfc->pinfo->energy[gr][ch]));
                }
            }
        }
    }


    /****************************************
    *   Stage 4: quantization loop          *
    ****************************************/

    if (cfg->vbr == vbr_off || cfg->vbr == vbr_abr) {
        static FLOAT const fircoef[9] = {
            -0.0207887 * 5, -0.0378413 * 5, -0.0432472 * 5, -0.031183 * 5,
            7.79609e-18 * 5, 0.0467745 * 5, 0.10091 * 5, 0.151365 * 5,
            0.187098 * 5
        };

        int     i;
        FLOAT   f;

        for (i = 0; i < 18; i++)
            gfc->sv_enc.pefirbuf[i] = gfc->sv_enc.pefirbuf[i + 1];

        f = 0.0;
        for (gr = 0; gr < cfg->mode_gr; gr++)
            for (ch = 0; ch < cfg->channels_out; ch++)
                f += pe_use[gr][ch];
        gfc->sv_enc.pefirbuf[18] = f;

        f = gfc->sv_enc.pefirbuf[9];
        for (i = 0; i < 9; i++)
            f += (gfc->sv_enc.pefirbuf[i] + gfc->sv_enc.pefirbuf[18 - i]) * fircoef[i];

        f = (670 * 5 * cfg->mode_gr * cfg->channels_out) / f;
        for (gr = 0; gr < cfg->mode_gr; gr++) {
            for (ch = 0; ch < cfg->channels_out; ch++) {
                pe_use[gr][ch] *= f;
            }
        }
    }
    gfc->iteration_loop(gfc, (const FLOAT (*)[2])pe_use, ms_ener_ratio, masking);


    /****************************************
    *   Stage 5: bitstream formatting       *
    ****************************************/


    /*  write the frame to the bitstream  */
    (void) format_bitstream(gfc);

    /* copy mp3 bit buffer into array */
    mp3count = copy_buffer(gfc, mp3buf, mp3buf_size, 1);


    if (cfg->write_lame_tag) {
        AddVbrFrame(gfc);
    }

    if (cfg->analysis && gfc->pinfo != NULL) {
        int     framesize = 576 * cfg->mode_gr;
        for (ch = 0; ch < cfg->channels_out; ch++) {
            int     j;
            for (j = 0; j < FFTOFFSET; j++)
                gfc->pinfo->pcmdata[ch][j] = gfc->pinfo->pcmdata[ch][j + framesize];
            for (j = FFTOFFSET; j < 1600; j++) {
                gfc->pinfo->pcmdata[ch][j] = inbuf[ch][j - FFTOFFSET];
            }
        }
        gfc->sv_qnt.masking_lower = 1.0;

        set_frame_pinfo(gfc, masking);
    }

    ++gfc->ov_enc.frame_number;

    updateStats(gfc);

    return mp3count;
}


================================================
FILE: app/src/main/jni/libmp3lame/encoder.h
================================================
/*
 *      encoder.h include file
 *
 *      Copyright (c) 2000 Mark Taylor
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#ifndef LAME_ENCODER_H
#define LAME_ENCODER_H

/***********************************************************************
*
*  encoder and decoder delays
*
***********************************************************************/

/* 
 * layer III enc->dec delay:  1056 (1057?)   (observed)
 * layer  II enc->dec delay:   480  (481?)   (observed)
 *
 * polyphase 256-16             (dec or enc)        = 240
 * mdct      256+32  (9*32)     (dec or enc)        = 288
 * total:    512+16
 *
 * My guess is that delay of polyphase filterbank is actualy 240.5
 * (there are technical reasons for this, see postings in mp3encoder).
 * So total Encode+Decode delay = ENCDELAY + 528 + 1
 */

/* 
 * ENCDELAY  The encoder delay.  
 *
 * Minimum allowed is MDCTDELAY (see below)
 *  
 * The first 96 samples will be attenuated, so using a value less than 96
 * will result in corrupt data for the first 96-ENCDELAY samples.
 *
 * suggested: 576
 * set to 1160 to sync with FhG.
 */

#define ENCDELAY      576



/*
 * make sure there is at least one complete frame after the
 * last frame containing real data
 *
 * Using a value of 288 would be sufficient for a 
 * a very sophisticated decoder that can decode granule-by-granule instead
 * of frame by frame.  But lets not assume this, and assume the decoder  
 * will not decode frame N unless it also has data for frame N+1
 *
 */
/*#define POSTDELAY   288*/
#define POSTDELAY   1152



/* 
 * delay of the MDCT used in mdct.c
 * original ISO routines had a delay of 528!  
 * Takehiro's routines: 
 */

#define MDCTDELAY     48
#define FFTOFFSET     (224+MDCTDELAY)

/*
 * Most decoders, including the one we use, have a delay of 528 samples.  
 */

#define DECDELAY      528


/* number of subbands */
#define SBLIMIT       32

/* parition bands bands */
#define CBANDS        64

/* number of critical bands/scale factor bands where masking is computed*/
#define SBPSY_l       21
#define SBPSY_s       12

/* total number of scalefactor bands encoded */
#define SBMAX_l       22
#define SBMAX_s       13
#define PSFB21         6
#define PSFB12         6



/* FFT sizes */
#define BLKSIZE       1024
#define HBLKSIZE      (BLKSIZE/2 + 1)
#define BLKSIZE_s     256
#define HBLKSIZE_s    (BLKSIZE_s/2 + 1)


/* #define switch_pe        1800 */
#define NORM_TYPE     0
#define START_TYPE    1
#define SHORT_TYPE    2
#define STOP_TYPE     3

/* 
 * Mode Extention:
 * When we are in stereo mode, there are 4 possible methods to store these
 * two channels. The stereo modes -m? are using a subset of them.
 *
 *  -ms: MPG_MD_LR_LR
 *  -mj: MPG_MD_LR_LR and MPG_MD_MS_LR
 *  -mf: MPG_MD_MS_LR
 *  -mi: all
 */
#if 0
#define MPG_MD_LR_LR  0
#define MPG_MD_LR_I   1
#define MPG_MD_MS_LR  2
#define MPG_MD_MS_I   3
#endif
enum MPEGChannelMode
{   MPG_MD_LR_LR = 0
,   MPG_MD_LR_I  = 1
,   MPG_MD_MS_LR = 2
,   MPG_MD_MS_I  = 3
};

#ifndef lame_internal_flags_defined
#define lame_internal_flags_defined
struct lame_internal_flags;
typedef struct lame_internal_flags lame_internal_flags;
#endif

int     lame_encode_mp3_frame(lame_internal_flags * gfc,
                              sample_t const *inbuf_l,
                              sample_t const *inbuf_r, unsigned char *mp3buf, int mp3buf_size);

#endif /* LAME_ENCODER_H */


================================================
FILE: app/src/main/jni/libmp3lame/fft.c
================================================
/*
** FFT and FHT routines
**  Copyright 1988, 1993; Ron Mayer
**      Copyright (c) 1999-2000 Takehiro Tominaga
**
**  fht(fz,n);
**      Does a hartley transform of "n" points in the array "fz".
**
** NOTE: This routine uses at least 2 patented algorithms, and may be
**       under the restrictions of a bunch of different organizations.
**       Although I wrote it completely myself; it is kind of a derivative
**       of a routine I once authored and released under the GPL, so it
**       may fall under the free software foundation's restrictions;
**       it was worked on as a Stanford Univ project, so they claim
**       some rights to it; it was further optimized at work here, so
**       I think this company claims parts of it.  The patents are
**       held by R. Bracewell (the FHT algorithm) and O. Buneman (the
**       trig generator), both at Stanford Univ.
**       If it were up to me, I'd say go do whatever you want with it;
**       but it would be polite to give credit to the following people
**       if you use this anywhere:
**           Euler     - probable inventor of the fourier transform.
**           Gauss     - probable inventor of the FFT.
**           Hartley   - probable inventor of the hartley transform.
**           Buneman   - for a really cool trig generator
**           Mayer(me) - for authoring this particular version and
**                       including all the optimizations in one package.
**       Thanks,
**       Ron Mayer; mayer@acuson.com
** and added some optimization by
**           Mather    - idea of using lookup table
**           Takehiro  - some dirty hack for speed up
*/

/* $Id: fft.c,v 1.38 2009/04/20 21:48:00 robert Exp $ */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "util.h"
#include "fft.h"

//#include "vector/lame_intrin.h"



#define TRI_SIZE (5-1)  /* 1024 =  4**5 */

/* fft.c    */
static FLOAT window[BLKSIZE], window_s[BLKSIZE_s / 2];

static const FLOAT costab[TRI_SIZE * 2] = {
    9.238795325112867e-01, 3.826834323650898e-01,
    9.951847266721969e-01, 9.801714032956060e-02,
    9.996988186962042e-01, 2.454122852291229e-02,
    9.999811752826011e-01, 6.135884649154475e-03
};

static void
fht(FLOAT * fz, int n)
{
    const FLOAT *tri = costab;
    int     k4;
    FLOAT  *fi, *gi;
    FLOAT const *fn;

    n <<= 1;            /* to get BLKSIZE, because of 3DNow! ASM routine */
    fn = fz + n;
    k4 = 4;
    do {
        FLOAT   s1, c1;
        int     i, k1, k2, k3, kx;
        kx = k4 >> 1;
        k1 = k4;
        k2 = k4 << 1;
        k3 = k2 + k1;
        k4 = k2 << 1;
        fi = fz;
        gi = fi + kx;
        do {
            FLOAT   f0, f1, f2, f3;
            f1 = fi[0] - fi[k1];
            f0 = fi[0] + fi[k1];
            f3 = fi[k2] - fi[k3];
            f2 = fi[k2] + fi[k3];
            fi[k2] = f0 - f2;
            fi[0] = f0 + f2;
            fi[k3] = f1 - f3;
            fi[k1] = f1 + f3;
            f1 = gi[0] - gi[k1];
            f0 = gi[0] + gi[k1];
            f3 = SQRT2 * gi[k3];
            f2 = SQRT2 * gi[k2];
            gi[k2] = f0 - f2;
            gi[0] = f0 + f2;
            gi[k3] = f1 - f3;
            gi[k1] = f1 + f3;
            gi += k4;
            fi += k4;
        } while (fi < fn);
        c1 = tri[0];
        s1 = tri[1];
        for (i = 1; i < kx; i++) {
            FLOAT   c2, s2;
            c2 = 1 - (2 * s1) * s1;
            s2 = (2 * s1) * c1;
            fi = fz + i;
            gi = fz + k1 - i;
            do {
                FLOAT   a, b, g0, f0, f1, g1, f2, g2, f3, g3;
                b = s2 * fi[k1] - c2 * gi[k1];
                a = c2 * fi[k1] + s2 * gi[k1];
                f1 = fi[0] - a;
                f0 = fi[0] + a;
                g1 = gi[0] - b;
                g0 = gi[0] + b;
                b = s2 * fi[k3] - c2 * gi[k3];
                a = c2 * fi[k3] + s2 * gi[k3];
                f3 = fi[k2] - a;
                f2 = fi[k2] + a;
                g3 = gi[k2] - b;
                g2 = gi[k2] + b;
                b = s1 * f2 - c1 * g3;
                a = c1 * f2 + s1 * g3;
                fi[k2] = f0 - a;
                fi[0] = f0 + a;
                gi[k3] = g1 - b;
                gi[k1] = g1 + b;
                b = c1 * g2 - s1 * f3;
                a = s1 * g2 + c1 * f3;
                gi[k2] = g0 - a;
                gi[0] = g0 + a;
                fi[k3] = f1 - b;
                fi[k1] = f1 + b;
                gi += k4;
                fi += k4;
            } while (fi < fn);
            c2 = c1;
            c1 = c2 * tri[0] - s1 * tri[1];
            s1 = c2 * tri[1] + s1 * tri[0];
        }
        tri += 2;
    } while (k4 < n);
}


static const unsigned char rv_tbl[] = {
    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe
};

#define ch01(index)  (buffer[chn][index])

#define ml00(f) (window[i        ] * f(i))
#define ml10(f) (window[i + 0x200] * f(i + 0x200))
#define ml20(f) (window[i + 0x100] * f(i + 0x100))
#define ml30(f) (window[i + 0x300] * f(i + 0x300))

#define ml01(f) (window[i + 0x001] * f(i + 0x001))
#define ml11(f) (window[i + 0x201] * f(i + 0x201))
#define ml21(f) (window[i + 0x101] * f(i + 0x101))
#define ml31(f) (window[i + 0x301] * f(i + 0x301))

#define ms00(f) (window_s[i       ] * f(i + k))
#define ms10(f) (window_s[0x7f - i] * f(i + k + 0x80))
#define ms20(f) (window_s[i + 0x40] * f(i + k + 0x40))
#define ms30(f) (window_s[0x3f - i] * f(i + k + 0xc0))

#define ms01(f) (window_s[i + 0x01] * f(i + k + 0x01))
#define ms11(f) (window_s[0x7e - i] * f(i + k + 0x81))
#define ms21(f) (window_s[i + 0x41] * f(i + k + 0x41))
#define ms31(f) (window_s[0x3e - i] * f(i + k + 0xc1))


void
fft_short(lame_internal_flags const *const gfc,
          FLOAT x_real[3][BLKSIZE_s], int chn, const sample_t *const buffer[2])
{
    int     i;
    int     j;
    int     b;

    for (b = 0; b < 3; b++) {
        FLOAT  *x = &x_real[b][BLKSIZE_s / 2];
        short const k = (576 / 3) * (b + 1);
        j = BLKSIZE_s / 8 - 1;
        do {
            FLOAT   f0, f1, f2, f3, w;

            i = rv_tbl[j << 2];

            f0 = ms00(ch01);
            w = ms10(ch01);
            f1 = f0 - w;
            f0 = f0 + w;
            f2 = ms20(ch01);
            w = ms30(ch01);
            f3 = f2 - w;
            f2 = f2 + w;

            x -= 4;
            x[0] = f0 + f2;
            x[2] = f0 - f2;
            x[1] = f1 + f3;
            x[3] = f1 - f3;

            f0 = ms01(ch01);
            w = ms11(ch01);
            f1 = f0 - w;
            f0 = f0 + w;
            f2 = ms21(ch01);
            w = ms31(ch01);
            f3 = f2 - w;
            f2 = f2 + w;

            x[BLKSIZE_s / 2 + 0] = f0 + f2;
            x[BLKSIZE_s / 2 + 2] = f0 - f2;
            x[BLKSIZE_s / 2 + 1] = f1 + f3;
            x[BLKSIZE_s / 2 + 3] = f1 - f3;
        } while (--j >= 0);

        gfc->fft_fht(x, BLKSIZE_s / 2);
        /* BLKSIZE_s/2 because of 3DNow! ASM routine */
    }
}

void
fft_long(lame_internal_flags const *const gfc,
         FLOAT x[BLKSIZE], int chn, const sample_t *const buffer[2])
{
    int     i;
    int     jj = BLKSIZE / 8 - 1;
    x += BLKSIZE / 2;

    do {
        FLOAT   f0, f1, f2, f3, w;

        i = rv_tbl[jj];
        f0 = ml00(ch01);
        w = ml10(ch01);
        f1 = f0 - w;
        f0 = f0 + w;
        f2 = ml20(ch01);
        w = ml30(ch01);
        f3 = f2 - w;
        f2 = f2 + w;

        x -= 4;
        x[0] = f0 + f2;
        x[2] = f0 - f2;
        x[1] = f1 + f3;
        x[3] = f1 - f3;

        f0 = ml01(ch01);
        w = ml11(ch01);
        f1 = f0 - w;
        f0 = f0 + w;
        f2 = ml21(ch01);
        w = ml31(ch01);
        f3 = f2 - w;
        f2 = f2 + w;

        x[BLKSIZE / 2 + 0] = f0 + f2;
        x[BLKSIZE / 2 + 2] = f0 - f2;
        x[BLKSIZE / 2 + 1] = f1 + f3;
        x[BLKSIZE / 2 + 3] = f1 - f3;
    } while (--jj >= 0);

    gfc->fft_fht(x, BLKSIZE / 2);
    /* BLKSIZE/2 because of 3DNow! ASM routine */
}

#ifdef HAVE_NASM
extern void fht_3DN(FLOAT * fz, int n);
extern void fht_SSE(FLOAT * fz, int n);
#endif

void
init_fft(lame_internal_flags * const gfc)
{
    int     i;

    /* The type of window used here will make no real difference, but */
    /* in the interest of merging nspsytune stuff - switch to blackman window */
    for (i = 0; i < BLKSIZE; i++)
        /* blackman window */
        window[i] = 0.42 - 0.5 * cos(2 * PI * (i + .5) / BLKSIZE) +
            0.08 * cos(4 * PI * (i + .5) / BLKSIZE);

    for (i = 0; i < BLKSIZE_s / 2; i++)
        window_s[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE_s));

    gfc->fft_fht = fht;
#ifdef HAVE_NASM
    if (gfc->CPU_features.AMD_3DNow) {
        gfc->fft_fht = fht_3DN;
    }
    else if (gfc->CPU_features.SSE) {
        gfc->fft_fht = fht_SSE;
    }
    else {
        gfc->fft_fht = fht;
    }
#else
#ifdef HAVE_XMMINTRIN_H
#ifdef MIN_ARCH_SSE
    gfc->fft_fht = fht_SSE2;
#endif
#endif
#endif
}


================================================
FILE: app/src/main/jni/libmp3lame/fft.h
================================================
/*
 *	Fast Fourier Transform include file
 *
 *	Copyright (c) 2000 Mark Taylor
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef LAME_FFT_H
#define LAME_FFT_H

void    fft_long(lame_internal_flags const *const gfc, FLOAT x_real[BLKSIZE],
                 int chn, const sample_t *const data[2]);

void    fft_short(lame_internal_flags const *const gfc, FLOAT x_real[3][BLKSIZE_s],
                  int chn, const sample_t *const data[2]);

void    init_fft(lame_internal_flags * const gfc);

#endif

/* End of fft.h */


================================================
FILE: app/src/main/jni/libmp3lame/gain_analysis.c
================================================
/*
 *  ReplayGainAnalysis - analyzes input samples and give the recommended dB change
 *  Copyright (C) 2001 David Robinson and Glen Sawyer
 *  Improvements and optimizations added by Frank Klemm, and by Marcel Muller 
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  concept and filter values by David Robinson (David@Robinson.org)
 *    -- blame him if you think the idea is flawed
 *  original coding by Glen Sawyer (mp3gain@hotmail.com)
 *    -- blame him if you think this runs too slowly, or the coding is otherwise flawed
 *
 *  lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ )
 *    -- credit him for all the _good_ programming ;)
 *
 *
 *  For an explanation of the concepts and the basic algorithms involved, go to:
 *    http://www.replaygain.org/
 */

/*
 *  Here's the deal. Call
 *
 *    InitGainAnalysis ( long samplefreq );
 *
 *  to initialize everything. Call
 *
 *    AnalyzeSamples ( const Float_t*  left_samples,
 *                     const Float_t*  right_samples,
 *                     size_t          num_samples,
 *                     int             num_channels );
 *
 *  as many times as you want, with as many or as few samples as you want.
 *  If mono, pass the sample buffer in through left_samples, leave
 *  right_samples NULL, and make sure num_channels = 1.
 *
 *    GetTitleGain()
 *
 *  will return the recommended dB level change for all samples analyzed
 *  SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis().
 *
 *    GetAlbumGain()
 *
 *  will return the recommended dB level change for all samples analyzed
 *  since InitGainAnalysis() was called and finalized with GetTitleGain().
 *
 *  Pseudo-code to process an album:
 *
 *    Float_t       l_samples [4096];
 *    Float_t       r_samples [4096];
 *    size_t        num_samples;
 *    unsigned int  num_songs;
 *    unsigned int  i;
 *
 *    InitGainAnalysis ( 44100 );
 *    for ( i = 1; i <= num_songs; i++ ) {
 *        while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 )
 *            AnalyzeSamples ( left_samples, right_samples, num_samples, 2 );
 *        fprintf ("Recommended dB change for song %2d: %+6.2f dB\n", i, GetTitleGain() );
 *    }
 *    fprintf ("Recommended dB change for whole album: %+6.2f dB\n", GetAlbumGain() );
 */

/*
 *  So here's the main source of potential code confusion:
 *
 *  The filters applied to the incoming samples are IIR filters,
 *  meaning they rely on up to <filter order> number of previous samples
 *  AND up to <filter order> number of previous filtered samples.
 *
 *  I set up the AnalyzeSamples routine to minimize memory usage and interface
 *  complexity. The speed isn't compromised too much (I don't think), but the
 *  internal complexity is higher than it should be for such a relatively
 *  simple routine.
 *
 *  Optimization/clarity suggestions are welcome.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "lame.h"
#include "machine.h"
#include "gain_analysis.h"

/* for each filter: */
/* [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz, [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz */

#ifdef WIN32
#pragma warning ( disable : 4305 )
#endif

/*lint -save -e736 loss of precision */
static const Float_t ABYule[9][2 * YULE_ORDER + 1] = {
    {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851,
     -11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619,
     -12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999,
     0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027,
     0.13919314567432, 0.00288463683916},
    {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851,
     -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155,
     0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975,
     2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808,
     -0.00187763777362},
    {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653,
     -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602,
     0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049,
     0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020,
     -0.00881362733839},
    {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772,
     -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906,
     -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749,
     0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741,
     -0.02950134983287},
    {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555,
     0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326,
     -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351,
     0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925,
     -0.01760176568150},
    {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749,
     -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918,
     -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251,
     0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173,
     0.00541907748707},
    {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230,
     -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008,
     0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246,
     -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573,
     -0.00588215443421},
    {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253,
     -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999,
     0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333,
     -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503,
     -0.00749618797172},
    {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929,
     -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955,
     0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388,
     -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120,
     -0.02217936801134}
};

static const Float_t ABButter[9][2 * BUTTER_ORDER + 1] = {
    {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708},
    {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242},
    {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214},
    {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928},
    {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161},
    {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826},
    {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541},
    {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601},
    {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279}
};

/*lint -restore */

#ifdef WIN32
#pragma warning ( default : 4305 )
#endif

/* When calling this procedure, make sure that ip[-order] and op[-order] point to real data! */

static void
filterYule(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel)
{
    /*register double  y; */

    while (nSamples--) {
        *output = 1e-10 /* 1e-10 is a hack to avoid slowdown because of denormals */
            + input[0] * kernel[0]
            - output[-1] * kernel[1]
            + input[-1] * kernel[2]
            - output[-2] * kernel[3]
            + input[-2] * kernel[4]
            - output[-3] * kernel[5]
            + input[-3] * kernel[6]
            - output[-4] * kernel[7]
            + input[-4] * kernel[8]
            - output[-5] * kernel[9]
            + input[-5] * kernel[10]
            - output[-6] * kernel[11]
            + input[-6] * kernel[12]
            - output[-7] * kernel[13]
            + input[-7] * kernel[14]
            - output[-8] * kernel[15]
            + input[-8] * kernel[16]
            - output[-9] * kernel[17]
            + input[-9] * kernel[18]
            - output[-10] * kernel[19]
            + input[-10] * kernel[20];
        ++output;
        ++input;
        /* *output++ = (Float_t)y; */
    }
}

static void
filterButter(const Float_t * input, Float_t * output, size_t nSamples, const Float_t * const kernel)
{                       /*register double  y; */

    while (nSamples--) {
        *output = input[0] * kernel[0]
            - output[-1] * kernel[1]
            + input[-1] * kernel[2]
            - output[-2] * kernel[3]
            + input[-2] * kernel[4];
        ++output;
        ++input;
        /* *output++ = (Float_t)y; */
    }
}



static int ResetSampleFrequency(replaygain_t * rgData, long samplefreq);

/* returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not */

int
ResetSampleFrequency(replaygain_t * rgData, long samplefreq)
{
    int     i;

    /* zero out initial values */
    for (i = 0; i < MAX_ORDER; i++)
        rgData->linprebuf[i] = rgData->lstepbuf[i]
            = rgData->loutbuf[i]
            = rgData->rinprebuf[i]
            = rgData->rstepbuf[i]
            = rgData->routbuf[i] = 0.;

    switch ((int) (samplefreq)) {
    case 48000:
        rgData->freqindex = 0;
        break;
    case 44100:
        rgData->freqindex = 1;
        break;
    case 32000:
        rgData->freqindex = 2;
        break;
    case 24000:
        rgData->freqindex = 3;
        break;
    case 22050:
        rgData->freqindex = 4;
        break;
    case 16000:
        rgData->freqindex = 5;
        break;
    case 12000:
        rgData->freqindex = 6;
        break;
    case 11025:
        rgData->freqindex = 7;
        break;
    case 8000:
        rgData->freqindex = 8;
        break;
    default:
        return INIT_GAIN_ANALYSIS_ERROR;
    }

    rgData->sampleWindow =
        (samplefreq * RMS_WINDOW_TIME_NUMERATOR + RMS_WINDOW_TIME_DENOMINATOR -
         1) / RMS_WINDOW_TIME_DENOMINATOR;

    rgData->lsum = 0.;
    rgData->rsum = 0.;
    rgData->totsamp = 0;

    memset(rgData->A, 0, sizeof(rgData->A));

    return INIT_GAIN_ANALYSIS_OK;
}

int
InitGainAnalysis(replaygain_t * rgData, long samplefreq)
{
    if (ResetSampleFrequency(rgData, samplefreq) != INIT_GAIN_ANALYSIS_OK) {
        return INIT_GAIN_ANALYSIS_ERROR;
    }

    rgData->linpre = rgData->linprebuf + MAX_ORDER;
    rgData->rinpre = rgData->rinprebuf + MAX_ORDER;
    rgData->lstep = rgData->lstepbuf + MAX_ORDER;
    rgData->rstep = rgData->rstepbuf + MAX_ORDER;
    rgData->lout = rgData->loutbuf + MAX_ORDER;
    rgData->rout = rgData->routbuf + MAX_ORDER;

    memset(rgData->B, 0, sizeof(rgData->B));

    return INIT_GAIN_ANALYSIS_OK;
}

/* returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not */

static inline double
fsqr(const double d)
{
    return d * d;
}

int
AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples, const Float_t * right_samples,
               size_t num_samples, int num_channels)
{
    const Float_t *curleft;
    const Float_t *curright;
    long    batchsamples;
    long    cursamples;
    long    cursamplepos;
    int     i;

    if (num_samples == 0)
        return GAIN_ANALYSIS_OK;

    cursamplepos = 0;
    batchsamples = (long) num_samples;

    switch (num_channels) {
    case 1:
        right_samples = left_samples;
        break;
    case 2:
        break;
    default:
        return GAIN_ANALYSIS_ERROR;
    }

    if (num_samples < MAX_ORDER) {
        memcpy(rgData->linprebuf + MAX_ORDER, left_samples, num_samples * sizeof(Float_t));
        memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t));
    }
    else {
        memcpy(rgData->linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t));
        memcpy(rgData->rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t));
    }

    while (batchsamples > 0) {
        cursamples = batchsamples > rgData->sampleWindow - rgData->totsamp ?
            rgData->sampleWindow - rgData->totsamp : batchsamples;
        if (cursamplepos < MAX_ORDER) {
            curleft = rgData->linpre + cursamplepos;
            curright = rgData->rinpre + cursamplepos;
            if (cursamples > MAX_ORDER - cursamplepos)
                cursamples = MAX_ORDER - cursamplepos;
        }
        else {
            curleft = left_samples + cursamplepos;
            curright = right_samples + cursamplepos;
        }

        YULE_FILTER(curleft, rgData->lstep + rgData->totsamp, cursamples,
                    ABYule[rgData->freqindex]);
        YULE_FILTER(curright, rgData->rstep + rgData->totsamp, cursamples,
                    ABYule[rgData->freqindex]);

        BUTTER_FILTER(rgData->lstep + rgData->totsamp, rgData->lout + rgData->totsamp, cursamples,
                      ABButter[rgData->freqindex]);
        BUTTER_FILTER(rgData->rstep + rgData->totsamp, rgData->rout + rgData->totsamp, cursamples,
                      ABButter[rgData->freqindex]);

        curleft = rgData->lout + rgData->totsamp; /* Get the squared values */
        curright = rgData->rout + rgData->totsamp;

        i = cursamples % 8;
        while (i--) {
            rgData->lsum += fsqr(*curleft++);
            rgData->rsum += fsqr(*curright++);
        }
        i = cursamples / 8;
        while (i--) {
            rgData->lsum += fsqr(curleft[0])
                + fsqr(curleft[1])
                + fsqr(curleft[2])
                + fsqr(curleft[3])
                + fsqr(curleft[4])
                + fsqr(curleft[5])
                + fsqr(curleft[6])
                + fsqr(curleft[7]);
            curleft += 8;
            rgData->rsum += fsqr(curright[0])
                + fsqr(curright[1])
                + fsqr(curright[2])
                + fsqr(curright[3])
                + fsqr(curright[4])
                + fsqr(curright[5])
                + fsqr(curright[6])
                + fsqr(curright[7]);
            curright += 8;
        }

        batchsamples -= cursamples;
        cursamplepos += cursamples;
        rgData->totsamp += cursamples;
        if (rgData->totsamp == rgData->sampleWindow) { /* Get the Root Mean Square (RMS) for this set of samples */
            double const val =
                STEPS_per_dB * 10. * log10((rgData->lsum + rgData->rsum) / rgData->totsamp * 0.5 +
                                           1.e-37);
            size_t  ival = (val <= 0) ? 0 : (size_t) val;
            if (ival >= sizeof(rgData->A) / sizeof(*(rgData->A)))
                ival = sizeof(rgData->A) / sizeof(*(rgData->A)) - 1;
            rgData->A[ival]++;
            rgData->lsum = rgData->rsum = 0.;
            memmove(rgData->loutbuf, rgData->loutbuf + rgData->totsamp,
                    MAX_ORDER * sizeof(Float_t));
            memmove(rgData->routbuf, rgData->routbuf + rgData->totsamp,
                    MAX_ORDER * sizeof(Float_t));
            memmove(rgData->lstepbuf, rgData->lstepbuf + rgData->totsamp,
                    MAX_ORDER * sizeof(Float_t));
            memmove(rgData->rstepbuf, rgData->rstepbuf + rgData->totsamp,
                    MAX_ORDER * sizeof(Float_t));
            rgData->totsamp = 0;
        }
        if (rgData->totsamp > rgData->sampleWindow) /* somehow I really screwed up: Error in programming! Contact author about totsamp > sampleWindow */
            return GAIN_ANALYSIS_ERROR;
    }
    if (num_samples < MAX_ORDER) {
        memmove(rgData->linprebuf, rgData->linprebuf + num_samples,
                (MAX_ORDER - num_samples) * sizeof(Float_t));
        memmove(rgData->rinprebuf, rgData->rinprebuf + num_samples,
                (MAX_ORDER - num_samples) * sizeof(Float_t));
        memcpy(rgData->linprebuf + MAX_ORDER - num_samples, left_samples,
               num_samples * sizeof(Float_t));
        memcpy(rgData->rinprebuf + MAX_ORDER - num_samples, right_samples,
               num_samples * sizeof(Float_t));
    }
    else {
        memcpy(rgData->linprebuf, left_samples + num_samples - MAX_ORDER,
               MAX_ORDER * sizeof(Float_t));
        memcpy(rgData->rinprebuf, right_samples + num_samples - MAX_ORDER,
               MAX_ORDER * sizeof(Float_t));
    }

    return GAIN_ANALYSIS_OK;
}


static  Float_t
analyzeResult(uint32_t const *Array, size_t len)
{
    uint32_t elems;
    uint32_t upper;
    uint32_t sum;
    size_t  i;

    elems = 0;
    for (i = 0; i < len; i++)
        elems += Array[i];
    if (elems == 0)
        return GAIN_NOT_ENOUGH_SAMPLES;

    upper = (uint32_t) ceil(elems * (1. - RMS_PERCENTILE));
    sum = 0;
    for (i = len; i-- > 0;) {
        sum += Array[i];
        if (sum >= upper) {
            break;
        }
    }

    return (Float_t) ((Float_t) PINK_REF - (Float_t) i / (Float_t) STEPS_per_dB);
}


Float_t
GetTitleGain(replaygain_t * rgData)
{
    Float_t retval;
    unsigned int i;

    retval = analyzeResult(rgData->A, sizeof(rgData->A) / sizeof(*(rgData->A)));

    for (i = 0; i < sizeof(rgData->A) / sizeof(*(rgData->A)); i++) {
        rgData->B[i] += rgData->A[i];
        rgData->A[i] = 0;
    }

    for (i = 0; i < MAX_ORDER; i++)
        rgData->linprebuf[i] = rgData->lstepbuf[i]
            = rgData->loutbuf[i]
            = rgData->rinprebuf[i]
            = rgData->rstepbuf[i]
            = rgData->routbuf[i] = 0.f;

    rgData->totsamp = 0;
    rgData->lsum = rgData->rsum = 0.;
    return retval;
}

#if 0
static Float_t GetAlbumGain(replaygain_t const* rgData);

Float_t
GetAlbumGain(replaygain_t const* rgData)
{
    return analyzeResult(rgData->B, sizeof(rgData->B) / sizeof(*(rgData->B)));
}
#endif

/* end of gain_analysis.c */


================================================
FILE: app/src/main/jni/libmp3lame/gain_analysis.h
================================================
/*
 *  ReplayGainAnalysis - analyzes input samples and give the recommended dB change
 *  Copyright (C) 2001 David Robinson and Glen Sawyer
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  concept and filter values by David Robinson (David@Robinson.org)
 *    -- blame him if you think the idea is flawed
 *  coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA
 *    -- blame him if you think this runs too slowly, or the coding is otherwise flawed
 *
 *  For an explanation of the concepts and the basic algorithms involved, go to:
 *    http://www.replaygain.org/
 */

#ifndef GAIN_ANALYSIS_H
#define GAIN_ANALYSIS_H

#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#else
# ifdef HAVE_STDINT_H
#  include <stdint.h>
# endif
#endif

#ifdef __cplusplus
extern  "C" {
#endif


    typedef sample_t Float_t; /* Type used for filtering */


#define PINK_REF                64.82       /* 298640883795 */ /* calibration value for 89dB */


#define YULE_ORDER         10
#define BUTTER_ORDER        2
#define YULE_FILTER     filterYule
#define BUTTER_FILTER   filterButter
#define RMS_PERCENTILE      0.95 /* percentile which is louder than the proposed level */
#define MAX_SAMP_FREQ   48000L /* maximum allowed sample frequency [Hz] */
#define RMS_WINDOW_TIME_NUMERATOR    1L
#define RMS_WINDOW_TIME_DENOMINATOR 20L /* numerator / denominator = time slice size [s] */
#define STEPS_per_dB      100 /* Table entries per dB */
#define MAX_dB            120 /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */

    enum { GAIN_NOT_ENOUGH_SAMPLES = -24601, GAIN_ANALYSIS_ERROR = 0, GAIN_ANALYSIS_OK =
            1, INIT_GAIN_ANALYSIS_ERROR = 0, INIT_GAIN_ANALYSIS_OK = 1
    };

    enum { MAX_ORDER = (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER)
            , MAX_SAMPLES_PER_WINDOW = ((MAX_SAMP_FREQ * RMS_WINDOW_TIME_NUMERATOR) / RMS_WINDOW_TIME_DENOMINATOR + 1) /* max. Samples per Time slice */
    };

    struct replaygain_data {
        Float_t linprebuf[MAX_ORDER * 2];
        Float_t *linpre;     /* left input samples, with pre-buffer */
        Float_t lstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
        Float_t *lstep;      /* left "first step" (i.e. post first filter) samples */
        Float_t loutbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
        Float_t *lout;       /* left "out" (i.e. post second filter) samples */
        Float_t rinprebuf[MAX_ORDER * 2];
        Float_t *rinpre;     /* right input samples ... */
        Float_t rstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
        Float_t *rstep;
        Float_t routbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
        Float_t *rout;
        long    sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */
        long    totsamp;
        double  lsum;
        double  rsum;
        int     freqindex;
        int     first;
        uint32_t A[STEPS_per_dB * MAX_dB];
        uint32_t B[STEPS_per_dB * MAX_dB];

    };
#ifndef replaygain_data_defined
#define replaygain_data_defined
    typedef struct replaygain_data replaygain_t;
#endif




    int     InitGainAnalysis(replaygain_t * rgData, long samplefreq);
    int     AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples,
                           const Float_t * right_samples, size_t num_samples, int num_channels);
    Float_t GetTitleGain(replaygain_t * rgData);


#ifdef __cplusplus
}
#endif
#endif                       /* GAIN_ANALYSIS_H */


================================================
FILE: app/src/main/jni/libmp3lame/id3tag.c
================================================
/*
 * id3tag.c -- Write ID3 version 1 and 2 tags.
 *
 * Copyright (C) 2000 Don Melton
 * Copyright (C) 2011-2012 Robert Hegemann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * HISTORY: This source file is part of LAME (see http://www.mp3dev.org)
 * and was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au>
 * from mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1
 * tags.  Don Melton <don@blivet.com> COMPLETELY rewrote it to support version
 * 2 tags and be more conformant to other standards while remaining flexible.
 *
 * NOTE: See http://id3.org/ for more information about ID3 tag formats.
 */

/* $Id: id3tag.c,v 1.75.2.2 2012/01/08 23:49:58 robert Exp $ */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef STDC_HEADERS
# include <stddef.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
#else
# ifndef HAVE_STRCHR
#  define strchr index
#  define strrchr rindex
# endif
char   *strchr(), *strrchr();
# ifndef HAVE_MEMCPY
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif


#include "lame.h"
#include "machine.h"
#include "encoder.h"
#include "id3tag.h"
#include "lame_global_flags.h"
#include "util.h"
#include "bitstream.h"

#define lame_calloc(TYPE, COUNT) ((TYPE*)calloc(COUNT, sizeof(TYPE)))

static const char *const genre_names[] = {
    /*
     * NOTE: The spelling of these genre names is identical to those found in
     * Winamp and mp3info.
     */
    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
    "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
    "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
    "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
    "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
    "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock",
    "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
    "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
    "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
    "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
    "Native US", "Cabaret", "New Wave", "Psychedelic", "Rave",
    "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
    "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
    "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin",
    "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
    "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
    "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
    "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
    "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
    "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
    "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall",
    "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
    "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta",
    "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
    "SynthPop"
};

#define GENRE_NAME_COUNT \
    ((int)(sizeof genre_names / sizeof (const char *const)))

static const int genre_alpha_map[] = {
    123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0,
    107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2,
    139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84,
    80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35,
    100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64,
    133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92,
    67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21,
    111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130,
    144, 60, 70, 31, 72, 27, 28
};

#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))

#define GENRE_INDEX_OTHER 12


#define FRAME_ID(a, b, c, d) \
    ( ((unsigned long)(a) << 24) \
    | ((unsigned long)(b) << 16) \
    | ((unsigned long)(c) <<  8) \
    | ((unsigned long)(d) <<  0) )

typedef enum UsualStringIDs { ID_TITLE = FRAME_ID('T', 'I', 'T', '2')
        , ID_ARTIST = FRAME_ID('T', 'P', 'E', '1')
        , ID_ALBUM = FRAME_ID('T', 'A', 'L', 'B')
        , ID_GENRE = FRAME_ID('T', 'C', 'O', 'N')
        , ID_ENCODER = FRAME_ID('T', 'S', 'S', 'E')
        , ID_PLAYLENGTH = FRAME_ID('T', 'L', 'E', 'N')
        , ID_COMMENT = FRAME_ID('C', 'O', 'M', 'M') /* full text string */
} UsualStringIDs;

typedef enum NumericStringIDs { ID_DATE = FRAME_ID('T', 'D', 'A', 'T') /* "ddMM" */
        , ID_TIME = FRAME_ID('T', 'I', 'M', 'E') /* "hhmm" */
        , ID_TPOS = FRAME_ID('T', 'P', 'O', 'S') /* '0'-'9' and '/' allowed */
        , ID_TRACK = FRAME_ID('T', 'R', 'C', 'K') /* '0'-'9' and '/' allowed */
        , ID_YEAR = FRAME_ID('T', 'Y', 'E', 'R') /* "yyyy" */
} NumericStringIDs;

typedef enum MiscIDs { ID_TXXX = FRAME_ID('T', 'X', 'X', 'X')
        , ID_WXXX = FRAME_ID('W', 'X', 'X', 'X')
        , ID_SYLT = FRAME_ID('S', 'Y', 'L', 'T')
        , ID_APIC = FRAME_ID('A', 'P', 'I', 'C')
        , ID_GEOB = FRAME_ID('G', 'E', 'O', 'B')
        , ID_PCNT = FRAME_ID('P', 'C', 'N', 'T')
        , ID_AENC = FRAME_ID('A', 'E', 'N', 'C')
        , ID_LINK = FRAME_ID('L', 'I', 'N', 'K')
        , ID_ENCR = FRAME_ID('E', 'N', 'C', 'R')
        , ID_GRID = FRAME_ID('G', 'R', 'I', 'D')
        , ID_PRIV = FRAME_ID('P', 'R', 'I', 'V')
        , ID_VSLT = FRAME_ID('V', 'S', 'L', 'T') /* full text string */
        , ID_USER = FRAME_ID('U', 'S', 'E', 'R') /* full text string */
        , ID_PCST = FRAME_ID('P', 'C', 'S', 'T') /* iTunes Podcast indicator, only presence important */
        , ID_WFED = FRAME_ID('W', 'F', 'E', 'D') /* iTunes Podcast URL as TEXT FRAME !!! violates standard */
} MiscIDs;


static int
frame_id_matches(int id, int mask)
{
    int     result = 0, i, window = 0xff;
    for (i = 0; i < 4; ++i, window <<= 8) {
        int const mw = (mask & window);
        int const iw = (id & window);
        if (mw != 0 && mw != iw) {
            result |= iw;
        }
    }
    return result;
}

static int
isFrameIdMatching(int id, int mask)
{
    return frame_id_matches(id, mask) == 0 ? 1 : 0;
}

static int
test_tag_spec_flags(lame_internal_flags const *gfc, unsigned int tst)
{
    return (gfc->tag_spec.flags & tst) != 0u ? 1 : 0;
}

#if 0
static void
debug_tag_spec_flags(lame_internal_flags * gfc, const char* info)
{
    MSGF(gfc, "%s\n", info);
    MSGF(gfc, "CHANGED_FLAG  : %d\n", test_tag_spec_flags(gfc, CHANGED_FLAG )); 
    MSGF(gfc, "ADD_V2_FLAG   : %d\n", test_tag_spec_flags(gfc, ADD_V2_FLAG  )); 
    MSGF(gfc, "V1_ONLY_FLAG  : %d\n", test_tag_spec_flags(gfc, V1_ONLY_FLAG )); 
    MSGF(gfc, "V2_ONLY_FLAG  : %d\n", test_tag_spec_flags(gfc, V2_ONLY_FLAG )); 
    MSGF(gfc, "SPACE_V1_FLAG : %d\n", test_tag_spec_flags(gfc, SPACE_V1_FLAG)); 
    MSGF(gfc, "PAD_V2_FLAG   : %d\n", test_tag_spec_flags(gfc, PAD_V2_FLAG  )); 
}
#endif



static int
id3v2_add_ucs2(lame_t gfp, uint32_t frame_id, char const *lang, unsigned short const *desc, unsigned short const *text);
static int
id3v2_add_latin1(lame_t gfp, uint32_t frame_id, char const *lang, char const *desc, char const *text);

static void
copyV1ToV2(lame_t gfp, int frame_id, char const *s)
{
    lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0;
    if (gfc != 0) {
        unsigned int flags = gfc->tag_spec.flags;
        id3v2_add_latin1(gfp, frame_id, "XXX", 0, s);
        gfc->tag_spec.flags = flags;
#if 0
        debug_tag_spec_flags(gfc, "copyV1ToV2");
#endif
    }
}


static void
id3v2AddLameVersion(lame_t gfp)
{
    char    buffer[1024];
    const char *b = get_lame_os_bitness();
    const char *v = get_lame_version();
    const char *u = get_lame_url();
    const size_t lenb = strlen(b);

    if (lenb > 0) {
        sprintf(buffer, "LAME %s version %s (%s)", b, v, u);
    }
    else {
        sprintf(buffer, "LAME version %s (%s)", v, u);
    }
    copyV1ToV2(gfp, ID_ENCODER, buffer);
}

static void
id3v2AddAudioDuration(lame_t gfp, double ms)
{
    lame_internal_flags *gfc = gfp != 0 ? gfp->internal_flags : 0;
    SessionConfig_t const *const cfg = &gfc->cfg;
    char    buffer[1024];
    double const max_ulong = MAX_U_32_NUM;
    unsigned long playlength_ms;

    ms *= 1000;
    ms /= cfg->samplerate_in;
    if (ms > max_ulong) {
        playlength_ms = max_ulong;
    }
    else if (ms < 0) {
        playlength_ms = 0;
    }
    else {
        playlength_ms = ms;
    }
    sprintf(buffer, "%lu", playlength_ms);
    copyV1ToV2(gfp, ID_PLAYLENGTH, buffer);
}

void
id3tag_genre_list(void (*handler) (int, const char *, void *), void *cookie)
{
    if (handler) {
        int     i;
        for (i = 0; i < GENRE_NAME_COUNT; ++i) {
            if (i < GENRE_ALPHA_COUNT) {
                int     j = genre_alpha_map[i];
                handler(j, genre_names[j], cookie);
            }
        }
    }
}

#define GENRE_NUM_UNKNOWN 255



void
id3tag_init(lame_t gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    free_id3tag(gfc);
    memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec);
    gfc->tag_spec.genre_id3v1 = GENRE_NUM_UNKNOWN;
    gfc->tag_spec.padding_size = 128;
    id3v2AddLameVersion(gfp);
}



void
id3tag_add_v2(lame_t gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
    gfc->tag_spec.flags |= ADD_V2_FLAG;
}

void
id3tag_v1_only(lame_t gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG);
    gfc->tag_spec.flags |= V1_ONLY_FLAG;
}

void
id3tag_v2_only(lame_t gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
    gfc->tag_spec.flags |= V2_ONLY_FLAG;
}

void
id3tag_space_v1(lame_t gfp)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    gfc->tag_spec.flags &= ~V2_ONLY_FLAG;
    gfc->tag_spec.flags |= SPACE_V1_FLAG;
}

void
id3tag_pad_v2(lame_t gfp)
{
    id3tag_set_pad(gfp, 128);
}

void
id3tag_set_pad(lame_t gfp, size_t n)
{
    lame_internal_flags *gfc = gfp->internal_flags;
    gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
    gfc->tag_spec.flags |= PAD_V2_FLAG;
    gfc->tag_spec.flags |= ADD_V2_FLAG;
    gfc->tag_spec.padding_size = (unsigned int)n;
}

static int
hasUcs2ByteOrderMarker(unsigned short bom)
{
    if (bom == 0xFFFEu || bom == 0xFEFFu) {
        return 1;
    }
    return 0;
}


static unsigned short
swap_bytes(unsigned short w)
{
    return (0xff00u & (w << 8)) | (0x00ffu & (w >> 8));
}


static unsigned short
toLittleEndian(unsigned short bom, unsigned short c)
{
    if (bom == 0xFFFEu) {
        return swap_bytes(c);
    }
    return c;
}

static unsigned short
fromLatin1Char(const unsigned short* s, unsigned short c)
{
    if (s[0] == 0xFFFEu) {
        return swap_bytes(c);
    }
    return c;
}


static  size_t
local_strdup(char **dst, const char *src)
{
    if (dst == 0) {
        return 0;
    }
    free(*dst);
    *dst = 0;
    if (src != 0) {
        size_t  n;
        for (n = 0; src[n] != 0; ++n) { /* calc src string length */
        }
        if (n > 0) {    /* string length without zero termination */
            assert(sizeof(*src) == sizeof(**dst));
            *dst = lame_calloc(char, n + 1);
            if (*dst != 0) {
                memcpy(*dst, src, n * sizeof(**dst));
                (*dst)[n] = 0;
                return n;
            }
        }
    }
    return 0;
}

static  size_t
local_ucs2_strdup(unsigned short **dst, unsigned short const *src)
{
    if (dst == 0) {
        return 0;
    }
    free(*dst);         /* free old string pointer */
    *dst = 0;
    if (src != 0) {
        size_t  n;
        for (n = 0; src[n] != 0; ++n) { /* calc src string length */
        }
        if (n > 0) {    /* string length without zero termination */
            assert(sizeof(*src) >= 2);
            assert(sizeof(*src) == sizeof(**dst));
            *dst = lame_calloc(unsigned short, n + 1);
            if (*dst != 0) {
                memcpy(*dst, src, n * sizeof(**dst));
                (*dst)[n] = 0;
                return n;
            }
        }
    }
    return 0;
}


static  size_t
local_ucs2_strlen(unsigned short const *s)
{
    size_t  n = 0;
    if (s != 0) {
        while (*s++) {
            ++n;
        }
    }
    return n;
}


static size_t
local_ucs2_substr(unsigned short** dst, unsigned short const* src, size_t start, size_t end)
{
    size_t const len = 1 + 1 + ((start < end) ? (end - start) : 0);
    size_t n = 0;
    unsigned short *ptr = lame_calloc(unsigned short, len);
    *dst = ptr;
    if (ptr == 0 || src == 0) {
        return 0;
    }
    if (hasUcs2ByteOrderMarker(src[0])) {
        ptr[n++] = src[0];
        if (start == 0) {
            ++start;
        }
    }
    while (start < end) {
        ptr[n++] = src[start++];
    }
    ptr[n] = 0;
    return n;
}

static int
local_ucs2_pos(unsigned short const* str, unsigned short c)
{
    int     i;
    for (i = 0; str != 0 && str[i] != 0; ++i) {
        if (str[i] == c) {
            return i;
        }
    }
    return -1;
}

static int
local_char_pos(char const* str, char c)
{
    int     i;
    for (i = 0; str != 0 && str[i] != 0; ++i) {
        if (str[i] == c) {
            return i;
        }
    }
    return -1;
}

static int
maybeLatin1(unsigned short const* text)
{
    if (text) {
        unsigned short bom = *text++;
        while (*text) {
            unsigned short c = toLittleEndian(bom, *text++);
            if (c > 0x00fe) return 0;
        }
    }
    return 1;
}

static int searchGenre(char const* genre);
static int sloppySearchGenre(char const* genre);

static int
lookupGenre(char const* genre)
{
    char   *str;
    int     num = strtol(genre, &str, 10);
    /* is the input a string or a valid number? */
    if (*str) {
        num = searchGenre(genre);
        if (num == GENRE_NAME_COUNT) {
            num = sloppySearchGenre(genre);
        }
        if (num == GENRE_NAME_COUNT) {
            return -2; /* no common genre text found */
        }
    }
    else {
        if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
            return -1; /* number unknown */
        }
    }
    return num;
}

static unsigned char *
writeLoBytes(unsigned char *frame, unsigned short const *str, size_t n);

static char*
local_strdup_utf16_to_latin1(unsigned short const* utf16)
{
    size_t  len = local_ucs2_strlen(utf16);
    unsigned char* latin1 = lame_calloc(unsigned char, len+1);
    writeLoBytes(latin1, utf16, len);
    return (char*)latin1;
}


static int
id3tag_set_genre_utf16(lame_t gfp, unsigned short const* text)
{
    lame_internal_flags* gfc = gfp->internal_flags;
    int   ret;
    if (text == 0) {
        return -3;
    }
    if (!hasUcs2ByteOrderMarker(text[0])) {
        return -3;
    }
    if (maybeLatin1(text)) {
        char*   latin1 = local_strdup_utf16_to_latin1(text);
        int     num = lookupGenre(latin1);
        free(latin1);
        if (num == -1) return -1; /* number out of range */
        if (num >= 0) {           /* common genre found  */
            gfc->tag_spec.flags |= CHANGED_FLAG;
            gfc->tag_spec.genre_id3v1 = num;
            copyV1ToV2(gfp, ID_GENRE, genre_names[num]);
            return 0;
        }
    }
    ret = id3v2_add_ucs2(gfp, ID_GENRE, 0, 0, text);
    if (ret == 0) {
        gfc->tag_spec.flags |= CHANGED_FLAG;
        gfc->tag_spec.genre_id3v1 = GENRE_INDEX_OTHER;
    }
    return ret;
}

/*
Some existing options for ID3 tag can be specified by --tv option
as follows.
--tt <value>, --tv TIT2=value
--ta <value>, --tv TPE1=value
--tl <value>, --tv TALB=value
--ty <value>, --tv TYER=value
--tn <value>, --tv TRCK=value
--tg <value>, --tv TCON=value
(although some are not exactly same)*/

int
id3tag_set_albumart(lame_t gfp, const char *image, size_t size)
{
    int     mimetype = 0;
    unsigned char const *data = (unsigned char const *) image;
    lame_internal_flags *gfc = gfp->internal_flags;

    /* determine MIME type from the actual image data */
    if (2 < size && data[0] == 0xFF && data[1] == 0xD8) {
        mimetype = MIMETYPE_JPEG;
    }
    else if (4 < size && data[0] == 0x89 && strncmp((const char *) &data[1], "PNG", 3) == 0) {
        mimetype = MIMETYPE_PNG;
    }
    else if (4 < size && strncmp((const char *) data, "GIF8", 4) == 0) {
        mimetype = MIMETYPE_GIF;
    }
    else {
        return -1;
    }
    if (gfc->tag_spec.albumart != 0) {
        free(gfc->tag_spec.albumart);
        gfc->tag_spec.albumart = 0;
        gfc->tag_spec.albumart_size = 0;
        gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE;
    }
    if (size < 1) {
        return 0;
    }
    gfc->tag_spec.albumart = lame_calloc(unsigned char, size);
    if (gfc->tag_spec.albumart != 0) {
        memcpy(gfc->tag_spec.albumart, image, size);
        gfc->tag_spec.albumart_size = (unsigned int)size;
        gfc->tag_spec.albumart_mimetype = mimetype;
        gfc->tag_spec.flags |= CHANGED_FLAG;
        id3tag_add_v2(gfp);
    }
    return 0;
}

static unsigned char *
set_4_byte_value(unsigned char *bytes, uint32_t value)
{
    int     i;
    for (i = 3; i >= 0; --i) {
        bytes[i] = value & 0xffUL;
        value >>= 8;
    }
    return bytes + 4;
}

static uint32_t
toID3v2TagId(char const *s)
{
    unsigned int i, x = 0;
    if (s == 0) {
        return 0;
    }
    for (i = 0; i < 4 && s[i] != 0; ++i) {
        char const c = s[i];
        unsigned int const u = 0x0ff & c;
        x <<= 8;
        x |= u;
        if (c < 'A' || 'Z' < c) {
            if (c < '0' || '9' < c) {
                return 0;
            }
        }
    }
    return x;
}

static uint32_t
toID3v2TagId_ucs2(unsigned short const *s)
{
    unsigned int i, x = 0;
    unsigned short bom = 0;
    if (s == 0) {
        return 0;
    }
    bom = s[0];
    if (hasUcs2ByteOrderMarker(bom)) {
        ++s;
    }
    for (i = 0; i < 4 && s[i] != 0; ++i) {
        unsigned short const c = toLittleEndian(bom, s[i]);
        if (c < 'A' || 'Z' < c) {
            if (c < '0' || '9' < c) {
                return 0;
            }
        }
        x <<= 8;
        x |= c;
    }
    return x;
}

#if 0
static int
isNumericString(uint32_t frame_id)
{
    switch (frame_id) {
    case ID_DATE:
    case ID_TIME:
    case ID_TPOS:
    case ID_TRACK:
    case ID_YEAR:
        return 1;
    }
    return 0;
}
#endif

static int
isMultiFrame(uint32_t frame_id)
{
    switch (frame_id) {
    case ID_TXXX:
    case ID_WXXX:
    case ID_COMMENT:
    case ID_SYLT:
    case ID_APIC:
    case ID_GEOB:
    case ID_PCNT:
    case ID_AENC:
    case ID_LINK:
    case ID_ENCR:
    case ID_GRID:
    case ID_PRIV:
        return 1;
    }
    return 0;
}

#if 0
static int
isFullTextString(int frame_id)
{
    switch (frame_id) {
    case ID_VSLT:
    case ID_COMMENT:
        return 1;
    }
    return 0;
}
#endif

static FrameDataNode *
findNode(id3tag_spec const *tag, uint32_t frame_id, FrameDataNode const *last)
{
    FrameDataNode *node = last ? last->nxt : tag->v2_head;
    while (node != 0) {
        if (node->fid == frame_id) {
            return node;
        }
        node = node->nxt;
    }
    return 0;
}

static void
appendNode(id3tag_spec * tag, FrameDataNode * node)
{
    if (tag->v2_tail == 0 || tag->v2_head == 0) {
        tag->v2_head = node;
        tag->v2_tail = node;
    }
    else {
        tag->v2_tail->nxt = node;
        tag->v2_tail = node;
    }
}

static void
setLang(char *dst, char const *src)
{
    int     i;
    if (src == 0 || src[0] == 0) {
        dst[0] = 'X';
        dst[1] = 'X';
        dst[2] = 'X';
    }
    else {
        for (i = 0; i < 3 && src && *src; ++i) {
            dst[i] = src[i];
        }
        for (; i < 3; ++i) {
            dst[i] = ' ';
        }
    }
}

static int
isSameLang(char const *l1, char const *l2)
{
    char    d[3];
    int     i;
    setLang(d, l2);
    for (i = 0; i < 3; ++i) {
        char    a = tolower(l1[i]);
        char    b = tolower(d[i]);
        if (a < ' ')
            a = ' ';
        if (b < ' ')
            b = ' ';
        if (a != b) {
            return 0;
        }
    }
    return 1;
}

static int
isSameDescriptor(FrameDataNode const *node, char const *dsc)
{
    size_t  i;
    if (node->dsc.enc == 1 && node->dsc.dim > 0) {
        return 0;
    }
    for (i = 0; i < node->dsc.dim; ++i) {
        if (!dsc || node->dsc.ptr.l[i] != dsc[
Download .txt
gitextract_rnfvjqig/

├── .gitignore
├── README.md
├── app/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── build.gradle
│   ├── key02.keystore
│   ├── proguard-rules.pro
│   ├── src/
│   │   ├── androidTest/
│   │   │   └── java/
│   │   │       └── com/
│   │   │           └── convert/
│   │   │               └── mymp3convert/
│   │   │                   └── ExampleInstrumentedTest.java
│   │   ├── main/
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java/
│   │   │   │   └── com/
│   │   │   │       └── convert/
│   │   │   │           └── mymp3convert/
│   │   │   │               ├── MainActivity.java
│   │   │   │               ├── MainActivity2.kt
│   │   │   │               ├── Mp3ConvertUtil.java
│   │   │   │               ├── Mp3ConvertUtilHelper.java
│   │   │   │               ├── MyTest.java
│   │   │   │               └── test/
│   │   │   │                   └── Demo.java
│   │   │   ├── jni/
│   │   │   │   ├── NativeMp3ConvertUtil.cpp
│   │   │   │   ├── NativeMp3ConvertUtil.cpp.bak
│   │   │   │   ├── NativeMp3ConvertUtil.h
│   │   │   │   ├── NativeMyTest.cpp
│   │   │   │   ├── com_convert_mymp3convert_Mp3ConvertUtil.h
│   │   │   │   ├── com_convert_mymp3convert_MyTest.h
│   │   │   │   └── libmp3lame/
│   │   │   │       ├── VbrTag.c
│   │   │   │       ├── VbrTag.h
│   │   │   │       ├── bitstream.c
│   │   │   │       ├── bitstream.h
│   │   │   │       ├── encoder.c
│   │   │   │       ├── encoder.h
│   │   │   │       ├── fft.c
│   │   │   │       ├── fft.h
│   │   │   │       ├── gain_analysis.c
│   │   │   │       ├── gain_analysis.h
│   │   │   │       ├── id3tag.c
│   │   │   │       ├── id3tag.h
│   │   │   │       ├── l3side.h
│   │   │   │       ├── lame-analysis.h
│   │   │   │       ├── lame.c
│   │   │   │       ├── lame.h
│   │   │   │       ├── lame_global_flags.h
│   │   │   │       ├── lameerror.h
│   │   │   │       ├── machine.h
│   │   │   │       ├── mpglib_interface.c
│   │   │   │       ├── newmdct.c
│   │   │   │       ├── newmdct.h
│   │   │   │       ├── presets.c
│   │   │   │       ├── psymodel.c
│   │   │   │       ├── psymodel.h
│   │   │   │       ├── quantize.c
│   │   │   │       ├── quantize.h
│   │   │   │       ├── quantize_pvt.c
│   │   │   │       ├── quantize_pvt.h
│   │   │   │       ├── reservoir.c
│   │   │   │       ├── reservoir.h
│   │   │   │       ├── set_get.c
│   │   │   │       ├── set_get.h
│   │   │   │       ├── tables.c
│   │   │   │       ├── tables.h
│   │   │   │       ├── takehiro.c
│   │   │   │       ├── util.c
│   │   │   │       ├── util.h
│   │   │   │       ├── vbrquantize.c
│   │   │   │       ├── vbrquantize.h
│   │   │   │       ├── version.c
│   │   │   │       └── version.h
│   │   │   ├── library/
│   │   │   │   └── AndroidManifest.xml
│   │   │   └── res/
│   │   │       ├── drawable/
│   │   │       │   └── ic_launcher_background.xml
│   │   │       ├── drawable-v24/
│   │   │       │   └── ic_launcher_foreground.xml
│   │   │       ├── layout/
│   │   │       │   ├── activity_main.xml
│   │   │       │   └── activity_main2.xml
│   │   │       ├── mipmap-anydpi-v26/
│   │   │       │   ├── ic_launcher.xml
│   │   │       │   └── ic_launcher_round.xml
│   │   │       ├── values/
│   │   │       │   ├── colors.xml
│   │   │       │   ├── strings.xml
│   │   │       │   └── themes.xml
│   │   │       └── values-night/
│   │   │           └── themes.xml
│   │   └── test/
│   │       └── java/
│   │           └── com/
│   │               └── convert/
│   │                   └── mymp3convert/
│   │                       └── ExampleUnitTest.java
│   └── 说明 .txt
├── build.gradle
├── demo/
│   ├── .gitignore
│   ├── build.gradle
│   ├── libs/
│   │   └── app-release.aar
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── convert/
│       │               └── demo/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── convert/
│       │   │           └── demo/
│       │   │               └── MainActivity.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       ├── values/
│       │       │   ├── colors.xml
│       │       │   ├── strings.xml
│       │       │   └── themes.xml
│       │       └── values-night/
│       │           └── themes.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── convert/
│                       └── demo/
│                           └── ExampleUnitTest.java
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
Download .txt
SYMBOL INDEX (678 symbols across 46 files)

FILE: app/src/androidTest/java/com/convert/mymp3convert/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 18) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 20) | @Test

FILE: app/src/main/java/com/convert/mymp3convert/MainActivity.java
  class MainActivity (line 15) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 20) | @Override
    method test (line 31) | public void test(View v){
    method convert (line 37) | public void convert(View v){
    method convertByHelper01 (line 42) | public void convertByHelper01(View v){
    method convertByHelper02 (line 58) | public void convertByHelper02(View v){

FILE: app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtil.java
  class Mp3ConvertUtil (line 7) | public class Mp3ConvertUtil {
    method hello (line 13) | public static native String hello(String msg);
    method getLameVer (line 19) | public static native String getLameVer();
    method convertmp3 (line 26) | public static native void convertmp3(String wav, String mp3);
    type ConvertListener (line 31) | public interface ConvertListener{
      method notifyConvertProgress (line 32) | public void notifyConvertProgress(int progress);
      method convertFinish (line 36) | public  void convertFinish();
      method convertError (line 42) | public  void convertError(String errorMsg);
    class SimpleConvertListener (line 48) | public static class SimpleConvertListener implements ConvertListener{
      method notifyConvertProgress (line 50) | @Override
      method convertFinish (line 55) | @Override
      method convertError (line 60) | @Override
    method registerCallback (line 80) | protected static void registerCallback(String mp3TargetPath,ConvertLis...
    method removeCallback (line 91) | private static void removeCallback(String mp3TargetPath){
    method setProgress (line 103) | private static void setProgress(String outPath,int progress){
    method getProgress (line 115) | protected static int getProgress(String outPath){
    method removeProgress (line 132) | private static void removeProgress(String outPath){
    method nativeLog (line 144) | public static void nativeLog(String logTag,String logMsg) {
    method setConvertProgress (line 152) | public static void setConvertProgress(int progress,String outPath) {
    method convertFinish (line 167) | public static void convertFinish(String outPath) {
    method convertError (line 183) | public static void convertError(String errorMsg,String outPath) {

FILE: app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtilHelper.java
  class Mp3ConvertUtilHelper (line 3) | public class Mp3ConvertUtilHelper {
    method getVer (line 8) | public static String getVer(){
    method convertmp3 (line 17) | public static void convertmp3(String wavInPath, String mp3OutPath){
    method convertmp3 (line 27) | public static void convertmp3(String wavInPath, String mp3OutPath, Mp3...
    method getProgress (line 36) | public static int getProgress(String outPath){

FILE: app/src/main/java/com/convert/mymp3convert/MyTest.java
  class MyTest (line 3) | public class MyTest {
    method test (line 4) | public static native String test();

FILE: app/src/main/java/com/convert/mymp3convert/test/Demo.java
  class Demo (line 5) | public class Demo {
    method test (line 6) | private void test(){

FILE: app/src/main/jni/NativeMp3ConvertUtil.cpp
  function publishJavaProgress (line 65) | void publishJavaProgress(JNIEnv * env, jobject obj, jint progress,jstrin...
  function convertFinish (line 92) | void convertFinish(JNIEnv * env, jstring mp3Path) {
  function convertError (line 118) | void convertError(JNIEnv * env,jstring msg,jstring mp3Path) {
  function nativeLog (line 147) | void nativeLog(JNIEnv * env, jstring msg) {
  function jstring (line 175) | jstring jstrCat(JNIEnv *env,char * cstr,jstring jstr){
  function file_size (line 190) | long long file_size(char* filename){
  function JNIEXPORT (line 200) | JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_Mp3ConvertUtil_h...
  function JNIEXPORT (line 225) | JNIEXPORT jstring JNICALL
  function JNIEXPORT (line 245) | JNIEXPORT void JNICALL

FILE: app/src/main/jni/NativeMp3ConvertUtil.h
  function class (line 9) | class NativeMp3ConvertUtil {

FILE: app/src/main/jni/NativeMyTest.cpp
  function jstring (line 15) | jstring jstrCat(JNIEnv *env,char * cstr,jstring jstr){
  function JNIEXPORT (line 30) | JNIEXPORT jstring JNICALL Java_com_convert_mymp3convert_MyTest_test

FILE: app/src/main/jni/libmp3lame/VbrTag.c
  function addVbr (line 123) | static void
  function Xing_seek_table (line 150) | static void
  function print_seeking (line 174) | static void
  function AddVbrFrame (line 195) | void
  function ExtractI4 (line 205) | static int
  function CreateI4 (line 220) | static void
  function CreateI2 (line 232) | static void
  function IsVbrTag (line 241) | static int
  function setLameTagFrameHeader (line 256) | static void
  function CheckVbrTag (line 332) | int
  function GetVbrTag (line 361) | int
  function InitVbrTag (line 491) | int
  function CRC_update_lookup (line 582) | static uint16_t
  function UpdateMusicCRC (line 591) | void
  function PutLameVBR (line 614) | static int
  function skipId3v2 (line 864) | static long
  function lame_get_lametag_frame (line 899) | size_t
  function PutVbrTag (line 1029) | int

FILE: app/src/main/jni/libmp3lame/VbrTag.h
  type lame_internal_flags (line 52) | struct lame_internal_flags
  type lame_internal_flags (line 53) | typedef struct lame_internal_flags lame_internal_flags;
  type VBRTAGDATA (line 59) | typedef struct {

FILE: app/src/main/jni/libmp3lame/bitstream.c
  function calcFrameLength (line 60) | static int
  function getframebits (line 70) | int
  function get_max_frame_buffer_size_by_constraint (line 90) | int
  function putheader_bits (line 132) | static void
  function putbits2 (line 151) | inline static void
  function putbits_noheaders (line 187) | inline static void
  function drain_into_ancillary (line 225) | inline static void
  function writeheader (line 269) | inline static void
  function CRC_update (line 287) | static int
  function CRC_writeheader (line 303) | void
  function encodeSideInfo2 (line 320) | inline static void
  function huffman_coder_count1 (line 490) | inline static int
  function Huffmancode (line 560) | inline static int
  function ShortHuffmancodebits (line 638) | static int
  function LongHuffmancodebits (line 654) | static int
  function writeMainData (line 685) | inline static int
  function compute_flushbits (line 801) | int
  function flush_bitstream (line 862) | void
  function add_dummy_byte (line 892) | void
  function format_bitstream (line 917) | int
  function do_gain_analysis (line 987) | static int
  function do_copy_buffer (line 1055) | static int
  function copy_buffer (line 1078) | int
  function init_bit_stream_w (line 1096) | void

FILE: app/src/main/jni/libmp3lame/encoder.c
  function adjust_ATH (line 55) | static void
  function updateStats (line 154) | static void
  function lame_encode_frame_init (line 188) | static void
  type FLOAT (line 301) | typedef FLOAT chgrdata[2][2];
  function lame_encode_mp3_frame (line 304) | int

FILE: app/src/main/jni/libmp3lame/encoder.h
  type MPEGChannelMode (line 139) | enum MPEGChannelMode
  type lame_internal_flags (line 148) | struct lame_internal_flags
  type lame_internal_flags (line 149) | typedef struct lame_internal_flags lame_internal_flags;

FILE: app/src/main/jni/libmp3lame/fft.c
  function fht (line 63) | static void
  function fft_short (line 193) | void
  function fft_long (line 245) | void
  function init_fft (line 296) | void

FILE: app/src/main/jni/libmp3lame/gain_analysis.c
  function filterYule (line 179) | static void
  function filterButter (line 213) | static void
  function ResetSampleFrequency (line 235) | int
  function InitGainAnalysis (line 293) | int
  function fsqr (line 314) | static inline double
  function AnalyzeSamples (line 320) | int
  function Float_t (line 456) | static  Float_t
  function Float_t (line 483) | Float_t
  function Float_t (line 511) | Float_t

FILE: app/src/main/jni/libmp3lame/gain_analysis.h
  type sample_t (line 44) | typedef sample_t Float_t;
  type replaygain_data (line 69) | struct replaygain_data {
  type replaygain_t (line 94) | typedef struct replaygain_data replaygain_t;

FILE: app/src/main/jni/libmp3lame/id3tag.c
  type UsualStringIDs (line 124) | typedef enum UsualStringIDs { ID_TITLE = FRAME_ID('T', 'I', 'T', '2')
  type NumericStringIDs (line 133) | typedef enum NumericStringIDs { ID_DATE = FRAME_ID('T', 'D', 'A', 'T') /...
  type MiscIDs (line 140) | typedef enum MiscIDs { ID_TXXX = FRAME_ID('T', 'X', 'X', 'X')
  function frame_id_matches (line 158) | static int
  function isFrameIdMatching (line 172) | static int
  function test_tag_spec_flags (line 178) | static int
  function debug_tag_spec_flags (line 185) | static void
  function copyV1ToV2 (line 205) | static void
  function id3v2AddLameVersion (line 220) | static void
  function id3v2AddAudioDuration (line 238) | static void
  function id3tag_genre_list (line 262) | void
  function id3tag_init (line 280) | void
  function id3tag_add_v2 (line 293) | void
  function id3tag_v1_only (line 301) | void
  function id3tag_v2_only (line 309) | void
  function id3tag_space_v1 (line 317) | void
  function id3tag_pad_v2 (line 325) | void
  function id3tag_set_pad (line 331) | void
  function hasUcs2ByteOrderMarker (line 341) | static int
  function swap_bytes (line 351) | static unsigned short
  function toLittleEndian (line 358) | static unsigned short
  function fromLatin1Char (line 367) | static unsigned short
  function local_strdup (line 377) | static  size_t
  function local_ucs2_strdup (line 402) | static  size_t
  function local_ucs2_strlen (line 429) | static  size_t
  function local_ucs2_substr (line 442) | static size_t
  function local_ucs2_pos (line 465) | static int
  function local_char_pos (line 477) | static int
  function maybeLatin1 (line 489) | static int
  function lookupGenre (line 505) | static int
  function id3tag_set_genre_utf16 (line 541) | static int
  function id3tag_set_albumart (line 583) | int
  function toID3v2TagId (line 634) | static uint32_t
  function toID3v2TagId_ucs2 (line 655) | static uint32_t
  function isNumericString (line 681) | static int
  function isMultiFrame (line 696) | static int
  function isFullTextString (line 718) | static int
  function FrameDataNode (line 730) | static FrameDataNode *
  function appendNode (line 743) | static void
  function setLang (line 756) | static void
  function isSameLang (line 775) | static int
  function isSameDescriptor (line 795) | static int
  function isSameDescriptorUcs2 (line 810) | static int
  function id3v2_add_ucs2 (line 825) | static int
  function id3v2_add_latin1 (line 860) | static int
  function id3tag_set_userinfo_latin1 (line 896) | static int
  function id3tag_set_userinfo_ucs2 (line 912) | static int
  function id3tag_set_textinfo_utf16 (line 930) | int
  function id3tag_set_textinfo_ucs2 (line 973) | int
  function id3tag_set_textinfo_latin1 (line 979) | int
  function id3tag_set_comment_latin1 (line 1012) | int
  function id3tag_set_comment_utf16 (line 1019) | int
  function id3tag_set_comment_ucs2 (line 1029) | int
  function id3tag_set_title (line 1036) | void
  function id3tag_set_artist (line 1047) | void
  function id3tag_set_album (line 1058) | void
  function id3tag_set_year (line 1069) | void
  function id3tag_set_comment (line 1090) | void
  function id3tag_set_track (line 1105) | int
  function local_strcasecmp (line 1135) | static int
  function sloppyCompared (line 1168) | static int
  function sloppySearchGenre (line 1193) | static int
  function searchGenre (line 1206) | static int
  function id3tag_set_genre (line 1219) | int
  function sizeOfNode (line 1242) | static  size_t
  function sizeOfCommentNode (line 1268) | static  size_t
  function sizeOfWxxxNode (line 1298) | static size_t
  function id3tag_set_fieldvalue (line 1514) | int
  function id3tag_set_fieldvalue_utf16 (line 1526) | int
  function id3tag_set_fieldvalue_ucs2 (line 1556) | int
  function lame_get_id3v2_tag (line 1562) | size_t
  function id3tag_write_v2 (line 1711) | int
  function lame_get_id3v1_tag (line 1762) | size_t
  function id3tag_write_v1 (line 1812) | int

FILE: app/src/main/jni/libmp3lame/id3tag.h
  type FrameDataNode (line 20) | typedef struct FrameDataNode {
  type id3tag_spec (line 36) | typedef struct id3tag_spec {

FILE: app/src/main/jni/libmp3lame/l3side.h
  type scalefac_struct (line 29) | typedef struct {
  type III_psy_xmin (line 37) | typedef struct {
  type III_psy_ratio (line 42) | typedef struct {
  type gr_info (line 47) | typedef struct {
  type III_side_info_t (line 86) | typedef struct {

FILE: app/src/main/jni/libmp3lame/lame-analysis.h
  type plotting_data (line 34) | struct plotting_data {
  type plotting_data (line 91) | typedef struct plotting_data plotting_data;

FILE: app/src/main/jni/libmp3lame/lame.c
  function is_lame_global_flags_valid (line 68) | int
  function is_lame_internal_flags_valid (line 79) | int
  function FLOAT (line 91) | static  FLOAT
  function lame_init_params_ppflt (line 102) | static void
  function optimum_bandwidth (line 193) | static void
  function optimum_samplefreq (line 273) | static int
  function lame_init_qval (line 362) | static void
  function linear_int (line 481) | static double
  function lame_init_params (line 537) | int
  function concatSep (line 1307) | static void
  function lame_print_config (line 1323) | void
  function lame_print_internals (line 1414) | void
  function save_gain_values (line 1587) | static void
  function update_inbuffer_size (line 1618) | static int
  function calcNeeded (line 1650) | static int
  function lame_encode_buffer_sample_t (line 1694) | static int
  type PCMSampleType (line 1800) | enum PCMSampleType
  function lame_copy_inbuffer (line 1808) | static void
  function lame_encode_buffer_template (line 1861) | static int
  function lame_encode_buffer (line 1897) | int
  function lame_encode_buffer_float (line 1906) | int
  function lame_encode_buffer_ieee_float (line 1916) | int
  function lame_encode_buffer_interleaved_ieee_float (line 1926) | int
  function lame_encode_buffer_ieee_double (line 1936) | int
  function lame_encode_buffer_interleaved_ieee_double (line 1946) | int
  function lame_encode_buffer_int (line 1956) | int
  function lame_encode_buffer_long2 (line 1967) | int
  function lame_encode_buffer_long (line 1978) | int
  function lame_encode_buffer_interleaved (line 1989) | int
  function lame_encode_flush_nogap (line 2010) | int
  function lame_init_bitstream (line 2028) | int
  function lame_encode_flush (line 2064) | int
  function lame_close (line 2208) | int
  function lame_encode_finish (line 2241) | int
  function lame_mp3_tags_fid (line 2256) | void
  function lame_init_old (line 2302) | int
  function lame_global_flags (line 2418) | lame_global_flags *
  function lame_bitrate_kbps (line 2467) | void
  function lame_bitrate_hist (line 2489) | void
  function lame_stereo_mode_hist (line 2515) | void
  function lame_bitrate_stereo_mode_hist (line 2533) | void
  function lame_block_type_hist (line 2565) | void
  function lame_bitrate_block_type_hist (line 2583) | void

FILE: app/src/main/jni/libmp3lame/lame.h
  type vbr_mode (line 49) | typedef enum vbr_mode_e {
  type MPEG_mode (line 61) | typedef enum MPEG_mode_e {
  type Padding_type (line 71) | typedef enum Padding_type_e {
  type preset_mode (line 81) | typedef enum preset_mode_e {
  type asm_optimizations (line 123) | typedef enum asm_optimizations_e {
  type Psy_model (line 131) | typedef enum Psy_model_e {
  type buffer_constraint (line 138) | typedef enum buffer_constraint_e {
  type lame_global_struct (line 145) | struct lame_global_struct
  type lame_global_flags (line 146) | typedef struct lame_global_struct lame_global_flags;
  type lame_global_flags (line 147) | typedef lame_global_flags *lame_t;
  type lame_version_t (line 655) | typedef struct {
  type hip_global_struct (line 1008) | struct hip_global_struct
  type hip_global_flags (line 1009) | typedef struct hip_global_struct hip_global_flags;
  type hip_global_flags (line 1010) | typedef hip_global_flags *hip_t;
  type mp3data_struct (line 1013) | typedef struct {
  type lame_errorcodes_t (line 1304) | typedef enum {

FILE: app/src/main/jni/libmp3lame/lame_global_flags.h
  type lame_internal_flags (line 6) | struct lame_internal_flags
  type lame_internal_flags (line 7) | typedef struct lame_internal_flags lame_internal_flags;
  type short_block_t (line 11) | typedef enum short_block_e {
  type lame_global_struct (line 27) | struct lame_global_struct {

FILE: app/src/main/jni/libmp3lame/lameerror.h
  type lame_errorcodes_t (line 11) | typedef enum {

FILE: app/src/main/jni/libmp3lame/machine.h
  type FLOAT (line 135) | typedef float FLOAT;
  type FLOAT8 (line 145) | typedef double FLOAT8;
  type FLOAT (line 160) | typedef FLOAT sample_t;

FILE: app/src/main/jni/libmp3lame/mpglib_interface.c
  function lame_decode_exit (line 85) | int
  function lame_decode_init (line 93) | int
  function decode1_headersB_clipchoice (line 128) | static int
  function lame_decode1_headersB (line 247) | int
  function lame_decode1_headers (line 272) | int
  function lame_decode1 (line 281) | int
  function lame_decode_headers (line 297) | int
  function lame_decode (line 319) | int
  function hip_t (line 330) | hip_t hip_decode_init(void)
  function hip_decode_exit (line 338) | int hip_decode_exit(hip_t hip)
  function hip_decode1_unclipped (line 351) | int
  function hip_decode1_headers (line 374) | int
  function hip_decode1 (line 383) | int
  function hip_decode_headers (line 398) | int
  function hip_decode (line 420) | int
  function hip_decode1_headersB (line 428) | int
  function hip_set_pinfo (line 444) | void hip_set_pinfo(hip_t hip, plotting_data* pinfo)
  function hip_set_errorf (line 453) | void hip_set_errorf(hip_t hip, lame_report_function func)
  function hip_set_debugf (line 460) | void hip_set_debugf(hip_t hip, lame_report_function func)
  function hip_set_msgf (line 467) | void hip_set_msgf  (hip_t hip, lame_report_function func)

FILE: app/src/main/jni/libmp3lame/newmdct.c
  function window_subband (line 430) | inline static void
  function mdct_short (line 832) | inline static void
  function mdct_long (line 869) | inline static void
  function mdct_sub48 (line 944) | void

FILE: app/src/main/jni/libmp3lame/presets.c
  function min_int (line 47) | static inline int
  function max_int (line 56) | static inline int
  type vbr_presets_t (line 67) | typedef struct {
  function vbr_presets_t (line 127) | static vbr_presets_t const*
  function apply_vbr_preset (line 142) | static void
  function apply_abr_preset (line 211) | static int
  function apply_preset (line 315) | int

FILE: app/src/main/jni/libmp3lame/psymodel.c
  function FLOAT (line 213) | static  FLOAT
  function mask_add_delta (line 273) | inline static int
  function init_mask_add_max_values (line 282) | static void
  function FLOAT (line 294) | inline static FLOAT
  function convert_partition2scalefac (line 350) | static void
  function convert_partition2scalefac_s (line 395) | static void
  function convert_partition2scalefac_l (line 411) | static void
  function convert_partition2scalefac_l_to_s (line 421) | static void
  function FLOAT (line 443) | static inline FLOAT
  function FLOAT (line 458) | static  FLOAT
  function FLOAT (line 503) | static  FLOAT
  function calc_energy (line 556) | static void
  function calc_mask_index_l (line 583) | static void
  function vbrpsy_compute_fft_l (line 655) | static void
  function vbrpsy_compute_fft_s (line 707) | static void
  function vbrpsy_compute_loudness_approximation_l (line 743) | static void
  function vbrpsy_attack_detection (line 759) | static void
  function vbrpsy_skip_masking_s (line 943) | static void
  function vbrpsy_calc_mask_index_s (line 958) | static void
  function vbrpsy_compute_masking_s (line 1031) | static void
  function vbrpsy_compute_masking_l (line 1134) | static void
  function vbrpsy_compute_block_type (line 1265) | static void
  function vbrpsy_apply_block_type (line 1289) | static void
  function vbrpsy_compute_MS_thresholds (line 1326) | static void
  function L3psycho_anal_vbr (line 1397) | int
  function FLOAT (line 1605) | static  FLOAT
  function FLOAT (line 1641) | static  FLOAT
  function FLOAT (line 1690) | static  FLOAT
  function init_numline (line 1701) | static void
  function compute_bark_values (line 1794) | static void
  function init_s3_values (line 1816) | static int
  function psymodel_init (line 1867) | int

FILE: app/src/main/jni/libmp3lame/quantize.c
  function ms_convert (line 48) | static void
  function init_xrpow_core_c (line 72) | static void
  function init_xrpow_core_init (line 92) | void
  function init_xrpow (line 110) | static int
  function psfb21_analogsilence (line 159) | static void
  function init_outer_loop (line 226) | static void
  type binsearchDirection_t (line 361) | typedef enum {
  function bin_search_StepSize (line 367) | static int
  function floatcompare (line 443) | static int
  function trancate_smallspectrums (line 454) | static void
  function loop_break (line 540) | inline static int
  function penalties (line 568) | static double
  function get_klemm_noise (line 574) | static double
  function quant_compare (line 585) | inline static int
  function amp_scalefac_bands (line 720) | static void
  function inc_scalefac_scale (line 808) | static void
  function inc_subblock_gain (line 847) | static int
  function balance_noise (line 940) | inline static int
  function outer_loop (line 1010) | static int
  function iteration_finish_one (line 1213) | static void
  function VBR_encode_granule (line 1244) | static void
  function get_framebits (line 1340) | static void
  function VBR_old_prepare (line 1389) | static int
  function bitpressure_strategy (line 1453) | static void
  function VBR_old_iteration_loop (line 1490) | void
  function VBR_new_prepare (line 1582) | static int
  function VBR_new_iteration_loop (line 1645) | void
  function calc_target_bits (line 1767) | static void
  function ABR_iteration_loop (line 1900) | void
  function CBR_iteration_loop (line 1988) | void

FILE: app/src/main/jni/libmp3lame/quantize_pvt.c
  function FLOAT (line 210) | static  FLOAT
  function compute_ath (line 230) | static void
  function iteration_init (line 336) | void
  function on_pe (line 428) | int
  function reduce_side (line 492) | void
  function FLOAT (line 554) | FLOAT
  function calc_xmin (line 589) | int
  function FLOAT (line 750) | static  FLOAT
  function calc_noise (line 815) | int
  function set_pinfo (line 934) | static void
  function set_frame_pinfo (line 1044) | void

FILE: app/src/main/jni/libmp3lame/quantize_pvt.h
  type calc_noise_result (line 61) | typedef struct calc_noise_result_t {
  type calc_noise_data (line 75) | typedef struct calc_noise_data_t {

FILE: app/src/main/jni/libmp3lame/reservoir.c
  function ResvFrameBegin (line 82) | int
  function ResvMaxBits (line 174) | void
  function ResvAdjust (line 225) | void
  function ResvFrameEnd (line 238) | void

FILE: app/src/main/jni/libmp3lame/set_get.c
  function lame_set_num_samples (line 45) | int
  function lame_get_num_samples (line 56) | unsigned long
  function lame_set_in_samplerate (line 67) | int
  function lame_get_in_samplerate (line 78) | int
  function lame_set_num_channels (line 89) | int
  function lame_get_num_channels (line 103) | int
  function lame_set_scale (line 114) | int
  function lame_get_scale (line 125) | float
  function lame_set_scale_left (line 137) | int
  function lame_get_scale_left (line 148) | float
  function lame_set_scale_right (line 160) | int
  function lame_get_scale_right (line 171) | float
  function lame_set_out_samplerate (line 182) | int
  function lame_get_out_samplerate (line 202) | int
  function lame_set_analysis (line 219) | int
  function lame_get_analysis (line 236) | int
  function lame_set_bWriteVbrTag (line 248) | int
  function lame_get_bWriteVbrTag (line 265) | int
  function lame_set_decode_only (line 278) | int
  function lame_get_decode_only (line 295) | int
  function lame_set_ogg (line 316) | int
  function lame_get_ogg (line 324) | int
  function lame_set_quality (line 341) | int
  function lame_get_quality (line 359) | int
  function lame_set_mode (line 370) | int
  function MPEG_mode (line 384) | MPEG_mode
  function lame_set_mode_automs (line 408) | int
  function lame_get_mode_automs (line 425) | int
  function lame_set_force_ms (line 437) | int
  function lame_get_force_ms (line 454) | int
  function lame_set_free_format (line 466) | int
  function lame_get_free_format (line 483) | int
  function lame_set_findReplayGain (line 496) | int
  function lame_get_findReplayGain (line 513) | int
  function lame_set_decode_on_the_fly (line 526) | int
  function lame_get_decode_on_the_fly (line 549) | int
  function lame_set_findPeakSample (line 579) | int
  function lame_get_findPeakSample (line 585) | int
  function lame_set_ReplayGain_input (line 592) | int
  function lame_get_ReplayGain_input (line 598) | int
  function lame_set_ReplayGain_decode (line 606) | int
  function lame_get_ReplayGain_decode (line 615) | int
  function lame_set_nogap_total (line 627) | int
  function lame_get_nogap_total (line 637) | int
  function lame_set_nogap_currentindex (line 646) | int
  function lame_get_nogap_currentindex (line 656) | int
  function lame_set_errorf (line 667) | int
  function lame_set_debugf (line 677) | int
  function lame_set_msgf (line 687) | int
  function lame_set_brate (line 705) | int
  function lame_get_brate (line 718) | int
  function lame_set_compression_ratio (line 727) | int
  function lame_get_compression_ratio (line 737) | float
  function lame_set_copyright (line 754) | int
  function lame_get_copyright (line 771) | int
  function lame_set_original (line 783) | int
  function lame_get_original (line 800) | int
  function lame_set_error_protection (line 815) | int
  function lame_get_error_protection (line 832) | int
  function lame_set_padding_type (line 856) | int
  function Padding_type (line 864) | Padding_type
  function lame_set_extension (line 873) | int
  function lame_get_extension (line 889) | int
  function lame_set_strict_ISO (line 901) | int
  function lame_get_strict_ISO (line 917) | int
  function lame_set_disable_reservoir (line 934) | int
  function lame_get_disable_reservoir (line 951) | int
  function lame_set_experimentalX (line 964) | int
  function lame_get_experimentalX (line 975) | int
  function lame_set_quant_comp (line 983) | int
  function lame_get_quant_comp (line 993) | int
  function lame_set_quant_comp_short (line 1004) | int
  function lame_get_quant_comp_short (line 1014) | int
  function lame_set_experimentalY (line 1025) | int
  function lame_get_experimentalY (line 1035) | int
  function lame_set_experimentalZ (line 1045) | int
  function lame_get_experimentalZ (line 1055) | int
  function lame_set_exp_nspsytune (line 1066) | int
  function lame_get_exp_nspsytune (line 1077) | int
  function lame_set_VBR (line 1094) | int
  function vbr_mode (line 1107) | vbr_mode
  function lame_set_VBR_q (line 1123) | int
  function lame_get_VBR_q (line 1144) | int
  function lame_set_VBR_quality (line 1154) | int
  function lame_get_VBR_quality (line 1177) | float
  function lame_set_VBR_mean_bitrate_kbps (line 1188) | int
  function lame_get_VBR_mean_bitrate_kbps (line 1198) | int
  function lame_set_VBR_min_bitrate_kbps (line 1207) | int
  function lame_get_VBR_min_bitrate_kbps (line 1217) | int
  function lame_set_VBR_max_bitrate_kbps (line 1226) | int
  function lame_get_VBR_max_bitrate_kbps (line 1236) | int
  function lame_set_VBR_hard_min (line 1250) | int
  function lame_get_VBR_hard_min (line 1269) | int
  function lame_set_lowpassfreq (line 1289) | int
  function lame_get_lowpassfreq (line 1299) | int
  function lame_set_lowpasswidth (line 1313) | int
  function lame_get_lowpasswidth (line 1323) | int
  function lame_set_highpassfreq (line 1338) | int
  function lame_get_highpassfreq (line 1348) | int
  function lame_set_highpasswidth (line 1362) | int
  function lame_get_highpasswidth (line 1372) | int
  function lame_set_maskingadjust (line 1391) | int
  function lame_get_maskingadjust (line 1401) | float
  function lame_set_maskingadjust_short (line 1410) | int
  function lame_get_maskingadjust_short (line 1420) | float
  function lame_set_ATHonly (line 1430) | int
  function lame_get_ATHonly (line 1440) | int
  function lame_set_ATHshort (line 1451) | int
  function lame_get_ATHshort (line 1461) | int
  function lame_set_noATH (line 1472) | int
  function lame_get_noATH (line 1482) | int
  function lame_set_ATHtype (line 1493) | int
  function lame_get_ATHtype (line 1504) | int
  function lame_set_ATHcurve (line 1515) | int
  function lame_get_ATHcurve (line 1525) | float
  function lame_set_ATHlower (line 1536) | int
  function lame_get_ATHlower (line 1546) | float
  function lame_set_athaa_type (line 1557) | int
  function lame_get_athaa_type (line 1567) | int
  function lame_set_athaa_loudapprox (line 1584) | int
  function lame_get_athaa_loudapprox (line 1592) | int
  function lame_set_athaa_sensitivity (line 1602) | int
  function lame_get_athaa_sensitivity (line 1612) | float
  function lame_set_cwlimit (line 1626) | int
  function lame_get_cwlimit (line 1634) | int
  function lame_set_allow_diff_short (line 1649) | int
  function lame_get_allow_diff_short (line 1659) | int
  function lame_set_useTemporal (line 1673) | int
  function lame_get_useTemporal (line 1690) | int
  function lame_set_interChRatio (line 1702) | int
  function lame_get_interChRatio (line 1715) | float
  function lame_set_substep (line 1727) | int
  function lame_get_substep (line 1740) | int
  function lame_set_sfscale (line 1751) | int
  function lame_get_sfscale (line 1761) | int
  function lame_set_subblock_gain (line 1771) | int
  function lame_get_subblock_gain (line 1781) | int
  function lame_set_no_short_blocks (line 1792) | int
  function lame_get_no_short_blocks (line 1807) | int
  function lame_set_force_short_blocks (line 1828) | int
  function lame_get_force_short_blocks (line 1848) | int
  function lame_set_short_threshold_lrm (line 1867) | int
  function lame_get_short_threshold_lrm (line 1877) | float
  function lame_set_short_threshold_s (line 1886) | int
  function lame_get_short_threshold_s (line 1896) | float
  function lame_set_short_threshold (line 1905) | int
  function lame_set_emphasis (line 1925) | int
  function lame_get_emphasis (line 1938) | int
  function lame_get_version (line 1961) | int
  function lame_get_encoder_delay (line 1975) | int
  function lame_get_encoder_padding (line 1988) | int
  function lame_get_framesize (line 2002) | int
  function lame_get_frameNum (line 2017) | int
  function lame_get_mf_samples_to_encode (line 2029) | int
  function lame_get_size_mp3buffer (line 2041) | int     CDECL
  function lame_get_RadioGain (line 2055) | int
  function lame_get_AudiophileGain (line 2067) | int
  function lame_get_PeakSample (line 2079) | float
  function lame_get_noclipGainChange (line 2091) | int
  function lame_get_noclipScale (line 2103) | float
  function lame_get_totalframes (line 2120) | int
  function lame_set_preset (line 2158) | int
  function lame_set_asm_optimizations (line 2170) | int
  function lame_set_write_id3tag_automatic (line 2196) | void
  function lame_get_write_id3tag_automatic (line 2205) | int
  function lame_set_tune (line 2229) | void
  function lame_set_msfix (line 2239) | void
  function lame_get_msfix (line 2248) | float
  function lame_set_preset_expopts (line 2262) | int
  function lame_set_preset_notune (line 2271) | int

FILE: app/src/main/jni/libmp3lame/tables.c
  type huffcodetab (line 409) | struct huffcodetab
  type MPEG_t (line 520) | typedef enum {
  function lame_get_bitrate (line 538) | int
  function lame_get_samplerate (line 549) | int

FILE: app/src/main/jni/libmp3lame/tables.h
  type type1_t (line 26) | typedef struct {
  type type2_t (line 35) | typedef struct {
  type type34_t (line 44) | typedef struct {
  type type5_t (line 53) | typedef struct {
  type huffcodetab (line 70) | struct huffcodetab {
  type huffcodetab (line 77) | struct huffcodetab

FILE: app/src/main/jni/libmp3lame/takehiro.c
  function quantize_lines_xrpow_01 (line 113) | static void
  type fi_union (line 135) | typedef union {
  function quantize_lines_xrpow (line 144) | static void
  function quantize_lines_xrpow (line 222) | static void
  function quantize_xrpow (line 281) | static void
  function ix_max (line 423) | static int
  function count_bit_ESC (line 449) | static int
  function count_bit_noESC (line 486) | static int
  function count_bit_noESC_from2 (line 510) | static int
  function count_bit_noESC_from3 (line 538) | inline static int
  function count_bit_null (line 588) | static int count_bit_null(const int* ix, const int* end, int max, unsign...
  function choose_table_nonMMX (line 618) | static int
  function noquant_count_bits (line 654) | int
  function count_bits (line 767) | int
  function recalc_divide_init (line 809) | inline static void
  function recalc_divide_sub (line 847) | inline static void
  function best_huffman_divide (line 884) | void
  function scfsi_calc (line 964) | static void
  function best_scalefac_store (line 1021) | void
  function all_scalefactors_not_negative (line 1098) | static int
  function mpeg1_scale_bitcount (line 1135) | static int
  function mpeg2_scale_bitcount (line 1217) | static int
  function scale_bitcount (line 1318) | int
  function huffman_init (line 1334) | void

FILE: app/src/main/jni/libmp3lame/util.c
  function free_id3tag (line 48) | void
  function free_global_data (line 91) | static void
  function freegfc (line 109) | void
  function malloc_aligned (line 165) | void
  function free_aligned (line 181) | void
  function FLOAT (line 196) | static  FLOAT
  function FLOAT (line 240) | FLOAT
  function FLOAT (line 271) | FLOAT
  function FLOAT (line 285) | FLOAT
  function FindNearestBitrate (line 300) | int
  function nearestBitrateFullIndex (line 341) | int
  function map2MP3Frequency (line 390) | int
  function BitrateIndex (line 413) | int
  function SmpFrqIndex (line 433) | int
  function FLOAT (line 487) | inline static FLOAT
  function gcd (line 519) | static int
  function fill_buffer_resample (line 528) | static int
  function isResamplingNecessary (line 651) | int
  function fill_buffer (line 663) | void
  function lame_report_def (line 704) | void
  function lame_report_fnc (line 711) | void
  function lame_debugf (line 723) | void
  function lame_msgf (line 735) | void
  function lame_errorf (line 747) | void
  function has_MMX (line 776) | int
  function has_3DNow (line 786) | int
  function has_SSE (line 796) | int
  function has_SSE2 (line 810) | int
  function disable_FPE (line 824) | void
  function init_log_table (line 956) | void
  function ieee754_float32_t (line 974) | ieee754_float32_t
  function init_log_table (line 1001) | void

FILE: app/src/main/jni/libmp3lame/util.h
  type replaygain_data (line 108) | struct replaygain_data
  type replaygain_t (line 111) | typedef struct replaygain_data replaygain_t;
  type plotting_data (line 113) | struct plotting_data
  type plotting_data (line 116) | typedef struct plotting_data plotting_data;
  type aligned_pointer_t (line 125) | typedef struct {
  type Bit_stream_struc (line 140) | typedef struct bit_stream_struc {
  type VBR_seek_info_t (line 152) | typedef struct {
  type ATH_t (line 170) | typedef struct {
  type PsyConst_CB2SB_t (line 192) | typedef struct {
  type PsyConst_t (line 213) | typedef struct {
  type PsyStateVar_t (line 223) | typedef struct {
  type PsyResult_t (line 243) | typedef struct {
  type EncStateVar_t (line 250) | typedef struct {
  type EncResult_t (line 307) | typedef struct {
  type QntStateVar_t (line 322) | typedef struct {
  type RpgStateVar_t (line 345) | typedef struct {
  type RpgResult_t (line 351) | typedef struct {
  type SessionConfig_t (line 359) | typedef struct {
  type lame_internal_flags (line 466) | struct lame_internal_flags {
  type lame_internal_flags (line 552) | typedef struct lame_internal_flags lame_internal_flags;

FILE: app/src/main/jni/libmp3lame/vbrquantize.c
  type algo_s (line 40) | struct algo_s
  type algo_t (line 41) | typedef struct algo_s algo_t;
  type algo_s (line 46) | struct algo_s {
  type VOLATILE (line 77) | typedef VOLATILE union
  function vec_max_c (line 115) | inline static  float
  function find_lowest_scalefac (line 147) | inline static  uint8_t
  function k_34_4 (line 169) | inline static void
  function FLOAT (line 217) | static  FLOAT
  type calc_noise_cache (line 269) | struct calc_noise_cache {
  type calc_noise_cache_t (line 274) | typedef struct calc_noise_cache calc_noise_cache_t;
  function tri_calc_sfb_noise_x34 (line 277) | static  uint8_t
  function calc_scalefac (line 316) | static int
  function guess_scalefac_x34 (line 323) | static uint8_t
  function find_scalefac_x34 (line 346) | static  uint8_t
  function block_sf (line 394) | static int
  function quantize_x34 (line 500) | static void
  function set_subblock_gain (line 595) | static void
  function set_scalefacs (line 688) | static void
  function checkScalefactor (line 732) | static int
  function short_block_constrain (line 769) | static void
  function long_block_constrain (line 847) | static void
  function bitcount (line 984) | static void
  function quantizeAndCountBits (line 999) | static int
  function tryGlobalStepsize (line 1011) | static int
  function searchGlobalStepsizeMax (line 1040) | static void
  function sfDepth (line 1074) | static int
  function cutDistribution (line 1093) | static void
  function flattenDistribution (line 1104) | static int
  function tryThatOne (line 1140) | static int
  function outOfBitsStrategy (line 1154) | static void
  function reduce_bit_usage (line 1231) | static int
  function VBR_encode_frame (line 1254) | int

FILE: app/src/main/jni/libmp3lame/version.c
  function get_lame_version_numerical (line 203) | void

FILE: app/src/test/java/com/convert/mymp3convert/ExampleUnitTest.java
  class ExampleUnitTest (line 14) | public class ExampleUnitTest {
    method addition_isCorrect (line 15) | @Test
    method test (line 19) | @Test

FILE: demo/src/androidTest/java/com/convert/demo/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 18) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 20) | @Test

FILE: demo/src/main/java/com/convert/demo/MainActivity.java
  class MainActivity (line 12) | public class MainActivity extends AppCompatActivity {
    method onCreate (line 14) | @Override
    method click (line 20) | public void click(View v){

FILE: demo/src/test/java/com/convert/demo/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test
Condensed preview — 100 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (938K chars).
[
  {
    "path": ".gitignore",
    "chars": 109,
    "preview": "*.iml\n.gradle\n/local.properties\n.idea/\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n.cxx\nlocal.properties\n"
  },
  {
    "path": "README.md",
    "chars": 3653,
    "preview": "# MyMp3Convert\nmp3Convert\n一个mp3转换库,基于lame3来实现\n\n模块简介:\n================================================\n主要实现了wav格式向mp3格式的转"
  },
  {
    "path": "app/.gitignore",
    "chars": 6,
    "preview": "/build"
  },
  {
    "path": "app/CMakeLists.txt",
    "chars": 2112,
    "preview": "\n#指定CMake构建本地库时所需的最小版本\ncmake_minimum_required(VERSION 3.4.1)\n\n#该变量为真时会创建完整版本的Makefile\nset(CMAKE_VERBOSE_MAKEFILE on)\nset"
  },
  {
    "path": "app/build.gradle",
    "chars": 3099,
    "preview": "//plugins {\n//    id 'com.android.application'\n//}\nif(isAppLibrary.toBoolean()){\n    apply plugin: 'com.android.library'"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 750,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "app/src/androidTest/java/com/convert/mymp3convert/ExampleInstrumentedTest.java",
    "chars": 762,
    "preview": "package com.convert.mymp3convert;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationReg"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 1153,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/MainActivity.java",
    "chars": 3603,
    "preview": "package com.convert.mymp3convert;\n\nimport android.Manifest;\nimport android.os.Bundle;\nimport android.os.Environment;\nimp"
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/MainActivity2.kt",
    "chars": 307,
    "preview": "package com.convert.mymp3convert\n\nimport androidx.appcompat.app.AppCompatActivity\nimport android.os.Bundle\n\nclass MainAc"
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtil.java",
    "chars": 4779,
    "preview": "package com.convert.mymp3convert;\n\nimport android.util.Log;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\npublic clas"
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/Mp3ConvertUtilHelper.java",
    "chars": 1060,
    "preview": "package com.convert.mymp3convert;\n\npublic class Mp3ConvertUtilHelper {\n    /**\n     * 获取版本号\n     * @return\n     */\n    p"
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/MyTest.java",
    "chars": 99,
    "preview": "package com.convert.mymp3convert;\n\npublic class MyTest {\n    public static native String test();\n}\n"
  },
  {
    "path": "app/src/main/java/com/convert/mymp3convert/test/Demo.java",
    "chars": 194,
    "preview": "package com.convert.mymp3convert.test;\n\nimport com.convert.mymp3convert.Mp3ConvertUtil;\n\npublic class Demo {\n    private"
  },
  {
    "path": "app/src/main/jni/NativeMp3ConvertUtil.cpp",
    "chars": 10102,
    "preview": "//\n// Created by shaomingfa on 2021/1/14.\n//\n\n#include <string>\n#include \"libmp3lame/lame.h\"\n\n#include <jni.h>\n\n#include"
  },
  {
    "path": "app/src/main/jni/NativeMp3ConvertUtil.cpp.bak",
    "chars": 10102,
    "preview": "//\n// Created by shaomingfa on 2021/1/14.\n//\n\n#include <string>\n#include \"libmp3lame/lame.h\"\n\n#include <jni.h>\n\n#include"
  },
  {
    "path": "app/src/main/jni/NativeMp3ConvertUtil.h",
    "chars": 232,
    "preview": "//\n// Created by shaomingfa on 2021/1/14.\n//\n#include <jni.h>\n#ifndef MYMP3CONVERT_NATIVEMP3CONVERTUTIL_H\n#define MYMP3C"
  },
  {
    "path": "app/src/main/jni/NativeMyTest.cpp",
    "chars": 1317,
    "preview": "//\n// Created by shaomingfa on 2021/1/14.\n//\n#include <jni.h>\n#include <string>\n#include \"com_convert_mymp3convert_MyTes"
  },
  {
    "path": "app/src/main/jni/com_convert_mymp3convert_Mp3ConvertUtil.h",
    "chars": 1054,
    "preview": "/* DO NOT EDIT THIS FILE - it is machine generated */\n#include <jni.h>\n/* Header for class com_convert_mymp3convert_Mp3C"
  },
  {
    "path": "app/src/main/jni/com_convert_mymp3convert_MyTest.h",
    "chars": 406,
    "preview": "/* DO NOT EDIT THIS FILE - it is machine generated */\n/* Header for class com_convert_mymp3convert_MyTest */\n\n#pragma on"
  },
  {
    "path": "app/src/main/jni/libmp3lame/VbrTag.c",
    "chars": 31613,
    "preview": "/*\n *      Xing VBR tagging for LAME.\n *\n *      Copyright (c) 1999 A.L. Faber\n *      Copyright (c) 2001 Jonathan Dee\n "
  },
  {
    "path": "app/src/main/jni/libmp3lame/VbrTag.h",
    "chars": 2929,
    "preview": "/*\n *      Xing VBR tagging for LAME.\n *\n *      Copyright (c) 1999 A.L. Faber\n *\n * This library is free software; you "
  },
  {
    "path": "app/src/main/jni/libmp3lame/bitstream.c",
    "chars": 36122,
    "preview": "/*\n *      MP3 bitstream Output interface for LAME\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n *      Copyright (c) "
  },
  {
    "path": "app/src/main/jni/libmp3lame/bitstream.h",
    "chars": 1563,
    "preview": "/*\n *\tMP3 bitstream Output interface for LAME\n *\n *\tCopyright (c) 1999 Takehiro TOMINAGA\n *\n * This library is free soft"
  },
  {
    "path": "app/src/main/jni/libmp3lame/encoder.c",
    "chars": 18055,
    "preview": "/*\n *      LAME MP3 encoding engine\n *\n *      Copyright (c) 1999 Mark Taylor\n *      Copyright (c) 2000-2002 Takehiro T"
  },
  {
    "path": "app/src/main/jni/libmp3lame/encoder.h",
    "chars": 4096,
    "preview": "/*\n *      encoder.h include file\n *\n *      Copyright (c) 2000 Mark Taylor\n *\n * This library is free software; you can"
  },
  {
    "path": "app/src/main/jni/libmp3lame/fft.c",
    "chars": 9761,
    "preview": "/*\n** FFT and FHT routines\n**  Copyright 1988, 1993; Ron Mayer\n**      Copyright (c) 1999-2000 Takehiro Tominaga\n**\n**  "
  },
  {
    "path": "app/src/main/jni/libmp3lame/fft.h",
    "chars": 1227,
    "preview": "/*\n *\tFast Fourier Transform include file\n *\n *\tCopyright (c) 2000 Mark Taylor\n *\n * This library is free software; you "
  },
  {
    "path": "app/src/main/jni/libmp3lame/gain_analysis.c",
    "chars": 19486,
    "preview": "/*\n *  ReplayGainAnalysis - analyzes input samples and give the recommended dB change\n *  Copyright (C) 2001 David Robin"
  },
  {
    "path": "app/src/main/jni/libmp3lame/gain_analysis.h",
    "chars": 4202,
    "preview": "/*\n *  ReplayGainAnalysis - analyzes input samples and give the recommended dB change\n *  Copyright (C) 2001 David Robin"
  },
  {
    "path": "app/src/main/jni/libmp3lame/id3tag.c",
    "chars": 51692,
    "preview": "/*\n * id3tag.c -- Write ID3 version 1 and 2 tags.\n *\n * Copyright (C) 2000 Don Melton\n * Copyright (C) 2011-2012 Robert "
  },
  {
    "path": "app/src/main/jni/libmp3lame/id3tag.h",
    "chars": 1714,
    "preview": "\n#ifndef LAME_ID3_H\n#define LAME_ID3_H\n\n\n#define CHANGED_FLAG    (1U << 0)\n#define ADD_V2_FLAG     (1U << 1)\n#define V1_"
  },
  {
    "path": "app/src/main/jni/libmp3lame/l3side.h",
    "chars": 2414,
    "preview": "/*\n *\tLayer 3 side include file\n *\n *\tCopyright (c) 1999 Mark Taylor\n *\n * This library is free software; you can redist"
  },
  {
    "path": "app/src/main/jni/libmp3lame/lame-analysis.h",
    "chars": 3077,
    "preview": "/*\n *      GTK plotting routines source file\n *\n *      Copyright (c) 1999 Mark Taylor\n *\n * This library is free softwa"
  },
  {
    "path": "app/src/main/jni/libmp3lame/lame.c",
    "chars": 82599,
    "preview": "/* -*- mode: C; mode: fold -*- */\n/*\n *      LAME MP3 encoding engine\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n * "
  },
  {
    "path": "app/src/main/jni/libmp3lame/lame.h",
    "chars": 48851,
    "preview": "/*\n *\tInterface to MP3 LAME encoding engine\n *\n *\tCopyright (c) 1999 Mark Taylor\n *\n * This library is free software; yo"
  },
  {
    "path": "app/src/main/jni/libmp3lame/lame_global_flags.h",
    "chars": 8165,
    "preview": "#ifndef LAME_GLOBAL_FLAGS_H\n#define LAME_GLOBAL_FLAGS_H\n\n#ifndef lame_internal_flags_defined\n#define lame_internal_flags"
  },
  {
    "path": "app/src/main/jni/libmp3lame/lameerror.h",
    "chars": 637,
    "preview": "/*\n *  A collection of LAME Error Codes\n *\n *  Please use the constants defined here instead of some arbitrary\n *  value"
  },
  {
    "path": "app/src/main/jni/libmp3lame/machine.h",
    "chars": 4342,
    "preview": "/*\n *      Machine dependent defines/includes for LAME.\n *\n *      Copyright (c) 1999 A.L. Faber\n *\n * This library is f"
  },
  {
    "path": "app/src/main/jni/libmp3lame/mpglib_interface.c",
    "chars": 13828,
    "preview": "/* -*- mode: C; mode: fold -*- */\n/*\n *      LAME MP3 encoding engine\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n * "
  },
  {
    "path": "app/src/main/jni/libmp3lame/newmdct.c",
    "chars": 37124,
    "preview": "/*\n *      MP3 window subband -> subband filtering -> mdct routine\n *\n *      Copyright (c) 1999-2000 Takehiro Tominaga\n"
  },
  {
    "path": "app/src/main/jni/libmp3lame/newmdct.h",
    "chars": 993,
    "preview": "/*\n *\tNew Modified DCT include file\n *\n *\tCopyright (c) 1999 Takehiro TOMINAGA\n *\n * This library is free software; you "
  },
  {
    "path": "app/src/main/jni/libmp3lame/presets.c",
    "chars": 15429,
    "preview": "/*\n * presets.c -- Apply presets\n *\n *\tCopyright (c) 2002-2008 Gabriel Bouvigne\n *\tCopyright (c) 2007-2011 Robert Hegema"
  },
  {
    "path": "app/src/main/jni/libmp3lame/psymodel.c",
    "chars": 70574,
    "preview": "/*\n *      psymodel.c\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n *      Copyright (c) 2001-2002 Naoki Shibata\n *   "
  },
  {
    "path": "app/src/main/jni/libmp3lame/psymodel.h",
    "chars": 2024,
    "preview": "/*\n *\tpsymodel.h\n *\n *\tCopyright (c) 1999 Mark Taylor\n *\n * This library is free software; you can redistribute it and/o"
  },
  {
    "path": "app/src/main/jni/libmp3lame/quantize.c",
    "chars": 65774,
    "preview": "/*\n * MP3 quantization\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n *      Copyright (c) 1999-2003 Takehiro Tominaga\n"
  },
  {
    "path": "app/src/main/jni/libmp3lame/quantize.h",
    "chars": 1556,
    "preview": "/*\n * MP3 quantization\n *\n * Copyright (c) 1999 Mark Taylor\n *\n * This library is free software; you can redistribute it"
  },
  {
    "path": "app/src/main/jni/libmp3lame/quantize_pvt.c",
    "chars": 34061,
    "preview": "/*\n *      quantize_pvt source file\n *\n *      Copyright (c) 1999-2002 Takehiro Tominaga\n *      Copyright (c) 2000-2012"
  },
  {
    "path": "app/src/main/jni/libmp3lame/quantize_pvt.h",
    "chars": 4263,
    "preview": "/*\n *\tquantize_pvt include file\n *\n *\tCopyright (c) 1999 Takehiro TOMINAGA\n *\n * This library is free software; you can "
  },
  {
    "path": "app/src/main/jni/libmp3lame/reservoir.c",
    "chars": 10263,
    "preview": "/*\n *      bit reservoir source file\n *\n *      Copyright (c) 1999-2000 Mark Taylor\n *\n * This library is free software;"
  },
  {
    "path": "app/src/main/jni/libmp3lame/reservoir.h",
    "chars": 1221,
    "preview": "/*\n *\tbit reservoir include file\n *\n *\tCopyright (c) 1999 Mark Taylor\n *\n * This library is free software; you can redis"
  },
  {
    "path": "app/src/main/jni/libmp3lame/set_get.c",
    "chars": 51612,
    "preview": "/* -*- mode: C; mode: fold -*- */\n/*\n * set/get functions for lame_global_flags\n *\n * Copyright (c) 2001-2005 Alexander "
  },
  {
    "path": "app/src/main/jni/libmp3lame/set_get.h",
    "chars": 2587,
    "preview": "/*\n * set_get.h -- Internal set/get definitions\n *\n * Copyright (C) 2003 Gabriel Bouvigne / Lame project\n *\n * This libr"
  },
  {
    "path": "app/src/main/jni/libmp3lame/tables.c",
    "chars": 21364,
    "preview": "/*\n *\tMPEG layer 3 tables source file\n *\n *\tCopyright (c) 1999 Albert L Faber\n *\n * This library is free software; you c"
  },
  {
    "path": "app/src/main/jni/libmp3lame/tables.h",
    "chars": 2473,
    "preview": "/*\n *\tMPEG layer 3 tables include file\n *\n *\tCopyright (c) 1999 Albert L Faber\n *\n * This library is free software; you "
  },
  {
    "path": "app/src/main/jni/libmp3lame/takehiro.c",
    "chars": 38186,
    "preview": "/*\n *\tMP3 huffman table selecting and bit counting\n *\n *\tCopyright (c) 1999-2005 Takehiro TOMINAGA\n *\tCopyright (c) 2002"
  },
  {
    "path": "app/src/main/jni/libmp3lame/util.c",
    "chars": 25600,
    "preview": "/*\n *\tlame utility library source file\n *\n *\tCopyright (c) 1999 Albert L Faber\n *\tCopyright (c) 2000-2005 Alexander Leid"
  },
  {
    "path": "app/src/main/jni/libmp3lame/util.h",
    "chars": 22089,
    "preview": "/*\n *      lame utility library include file\n *\n *      Copyright (c) 1999 Albert L Faber\n *      Copyright (c) 2008 Rob"
  },
  {
    "path": "app/src/main/jni/libmp3lame/vbrquantize.c",
    "chars": 46728,
    "preview": "/*\n *\tMP3 quantization\n *\n *\tCopyright (c) 1999-2000 Mark Taylor\n *\tCopyright (c) 2000-2012 Robert Hegemann\n *\n * This l"
  },
  {
    "path": "app/src/main/jni/libmp3lame/vbrquantize.h",
    "chars": 1072,
    "preview": "/*\n * MP3 VBR quantization\n *\n * Copyright (c) 1999 Mark Taylor\n *\n * This library is free software; you can redistribut"
  },
  {
    "path": "app/src/main/jni/libmp3lame/version.c",
    "chars": 6885,
    "preview": "/*\n *      Version numbering for LAME.\n *\n *      Copyright (c) 1999 A.L. Faber\n *\n * This library is free software; you"
  },
  {
    "path": "app/src/main/jni/libmp3lame/version.h",
    "chars": 2306,
    "preview": "/*\n *      Version numbering for LAME.\n *\n *      Copyright (c) 1999 A.L. Faber\n *\n * This library is free software; you"
  },
  {
    "path": "app/src/main/library/AndroidManifest.xml",
    "chars": 889,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1702,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "chars": 1511,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "app/src/main/res/layout/activity_main2.xml",
    "chars": 426,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas."
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "chars": 378,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purpl"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 74,
    "preview": "<resources>\n    <string name=\"app_name\">MyMp3Convert</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/themes.xml",
    "chars": 834,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.M"
  },
  {
    "path": "app/src/main/res/values-night/themes.xml",
    "chars": 834,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.M"
  },
  {
    "path": "app/src/test/java/com/convert/mymp3convert/ExampleUnitTest.java",
    "chars": 1226,
    "preview": "package com.convert.mymp3convert;\n\nimport org.junit.Test;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static"
  },
  {
    "path": "app/说明 .txt",
    "chars": 1852,
    "preview": "G:\\e\\work\\test\\MyJniDemo\\app\\src\\main\\java>javac com\\example\\myjnidemo\\LameUtils.java\n\nG:\\e\\work\\test\\MyJniDemo\\app\\src\\"
  },
  {
    "path": "build.gradle",
    "chars": 658,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\nbuildscript {\n    ex"
  },
  {
    "path": "demo/.gitignore",
    "chars": 6,
    "preview": "/build"
  },
  {
    "path": "demo/build.gradle",
    "chars": 1194,
    "preview": "plugins {\n    id 'com.android.application'\n}\n\nandroid {\n    compileSdkVersion 30\n    buildToolsVersion \"30.0.3\"\n\n    def"
  },
  {
    "path": "demo/proguard-rules.pro",
    "chars": 750,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "demo/src/androidTest/java/com/convert/demo/ExampleInstrumentedTest.java",
    "chars": 746,
    "preview": "package com.convert.demo;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\ni"
  },
  {
    "path": "demo/src/main/AndroidManifest.xml",
    "chars": 720,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "demo/src/main/java/com/convert/demo/MainActivity.java",
    "chars": 661,
    "preview": "package com.convert.demo;\n\nimport androidx.appcompat.app.AppCompatActivity;\n\nimport android.os.Bundle;\nimport android.ut"
  },
  {
    "path": "demo/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "demo/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1702,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "demo/src/main/res/layout/activity_main.xml",
    "chars": 935,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "demo/src/main/res/values/colors.xml",
    "chars": 378,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"purple_200\">#FFBB86FC</color>\n    <color name=\"purpl"
  },
  {
    "path": "demo/src/main/res/values/strings.xml",
    "chars": 66,
    "preview": "<resources>\n    <string name=\"app_name\">demo</string>\n</resources>"
  },
  {
    "path": "demo/src/main/res/values/themes.xml",
    "chars": 834,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.M"
  },
  {
    "path": "demo/src/main/res/values-night/themes.xml",
    "chars": 834,
    "preview": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <!-- Base application theme. -->\n    <style name=\"Theme.M"
  },
  {
    "path": "demo/src/test/java/com/convert/demo/ExampleUnitTest.java",
    "chars": 377,
    "preview": "package com.convert.demo;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, wh"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Thu Jan 14 21:57:53 CST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1132,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "gradlew.bat",
    "chars": 2176,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "settings.gradle",
    "chars": 64,
    "preview": "include ':demo'\ninclude ':app'\nrootProject.name = \"MyMp3Convert\""
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the fanyuan/MyMp3Convert GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 100 files (875.2 KB), approximately 278.7k tokens, and a symbol index with 678 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!