天天看點

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

文章目錄

前言

一、Lame庫是什麼?

二、使用步驟

0.建立native項目

1.下載下傳Lame庫

2.pcm轉MP3

3.wav轉MP3

 4、native方法如下

三、注意

總結

前言

   因為使用android錄音後生成的檔案是wav或者pcm格式,項目要求最後的檔案需要是mp3格式,于是就使用到了lame庫。

一、Lame庫是什麼?

LAME 是最好的MP3編碼器,編碼高品質MP3的最好也是唯一的選擇。

Demo放在了文章末尾,demo是一個lib庫,直接引入就可以使用的。

本demo執行個體使用的是CMakeLists的方式編譯的c庫。

二、使用步驟

0.建立native項目

建立一個native項目或者native的module,建立成功後就會自動生成cpp檔案夾和一個native.cpp、CMakeLists

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

1.下載下傳Lame庫

Lame官網

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

https://sourceforge.net/projects/lame/files/lame/

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

    下載下傳完把libmp3lame 檔案夾下的所有.c和.h檔案還有include檔案夾下的lame.h考入到建立工程的cpp檔案下

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

 demo使用的是3.99這個版本,如果你的網很慢可以使用在後面的 demo裡面的lame庫。

2.pcm轉MP3

cpp代碼如下(示例):

/************************************************************************
 *                              PCM 轉 MP3                              *
 ***********************************************************************/

Mp3Encoder *encoder;
extern "C" JNIEXPORT jint JNICALL
Java_com_meng_nativelib_NativeLib_pcmToMp3JNI(
        JNIEnv *env,
        jobject,
        jstring pcm_path,
        jstring mp3_path,
        jint sample_rate,
        jint channel,
        jint bit_rate) {
    const char *pcmPath = env->GetStringUTFChars(pcm_path, NULL);
    const char *mp3Path = env->GetStringUTFChars(mp3_path, NULL);

    encoder = new Mp3Encoder();
    int initStatus = encoder->Init(pcmPath, mp3Path, sample_rate, channel, bit_rate);
    if (initStatus != 0) {
        return -1;
    }
    encoder->Encode();

    env->ReleaseStringUTFChars(pcm_path, pcmPath);
    env->ReleaseStringUTFChars(mp3_path, mp3Path);
    return 0;
}

extern "C" JNIEXPORT void JNICALL
Java_com_meng_nativelib_NativeLib_pcmToMp3JNIDestroy(
        JNIEnv *env,
        jobject) {
    encoder->Destroy();
}
           

3.wav轉MP3

int flag = 0;
/**
 * wav轉換mp3
 */

extern "C"
JNIEXPORT void JNICALL Java_com_meng_nativelib_NativeLib_wavToMp3
        (JNIEnv *env, jobject obj, jstring jwav, jstring jmp3, jint inSamplerate, jint inChannel,
         jint outBitrate) {

    char *cwav = Jstring2CStr(env, jwav);
    char *cmp3 = Jstring2CStr(env, jmp3);

    //1.打開 wav,MP3檔案
    FILE *fwav = fopen(cwav, "rb");
    fseek(fwav, 4 * 1024, SEEK_CUR);
    FILE *fmp3 = fopen(cmp3, "wb+");

    int channel = inChannel;//單聲道

    short int wav_buffer[8192 * channel];
    unsigned char mp3_buffer[8192];

    //1.初始化lame的編碼器
    lame_t lameConvert = lame_init();

    //2. 設定lame mp3編碼的采樣率
    lame_set_in_samplerate(lameConvert, inSamplerate);
    lame_set_out_samplerate(lameConvert, inSamplerate);
    lame_set_num_channels(lameConvert, channel);
    lame_set_mode(lameConvert, MONO);
    // 3. 設定MP3的編碼方式
    lame_set_VBR(lameConvert, vbr_default);
    lame_init_params(lameConvert);
    int read;
    int write; //代表讀了多少個次 和寫了多少次
    int total = 0; // 目前讀的wav檔案的byte數目
    do {
        if (flag == 404) {
            return;
        }
        read = fread(wav_buffer, sizeof(short int) * channel, 8192, fwav);
        total += read * sizeof(short int) * channel;
        if (read != 0) {
            write = lame_encode_buffer(lameConvert, wav_buffer, NULL, read, mp3_buffer, 8192);
            //write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
        } else {
            write = lame_encode_flush(lameConvert, mp3_buffer, 8192);
        }
        //把轉化後的mp3資料寫到檔案裡
        fwrite(mp3_buffer, 1, write, fmp3);

    } while (read != 0);
    lame_mp3_tags_fid(lameConvert, fmp3);
    lame_close(lameConvert);
    fclose(fwav);
    fclose(fmp3);
}
           

 4、native方法如下

package com.meng.nativelib

object NativeLib {

    // Used to load the 'lame_lib' library on application startup.
    init {
        System.loadLibrary("lame_lib")
    }


    external fun getVersion(): String?

    /**
     * wav 轉mp3  16000,1,1
     * @param wavFilePath 源檔案路徑
     * @param mp3FilePath 生成mp3目标檔案路徑
     * @param sampleRate  Lame采樣率  最好寫 16000  Lame采樣率
     * MPEG1	MPEG2	MPEG2.5
     * 44100	22050	11025
     * 8000	    24000	12000
     * 32000	16000	8000
     *@param channels 1
     * @param bitRate 實際沒有使用
     */
    external fun wavToMp3(
        wavFilePath: String, mp3FilePath: String, sampleRate: Int, channels: Int, bitRate: Int
    )

    external fun pcmToMp3JNI(
        pcmFilePath: String, mp3FilePath: String, sampleRate: Int, channels: Int, bitRate: Int
    ): Int

    external fun pcmToMp3JNIDestroy()

}
           

三、注意

  • 在編寫的cpp代碼時一定要在方法上面添加  extern "C"(主要作用就是為了能夠正确實作C++代碼調用其他C語言代碼。加上extern "C"後,會訓示編譯器這部分代碼按C語言(而不是C++)的方式進行編譯。由于C++支援函數重載,是以編譯器編譯函數的過程中會将函數的參數類型也加到編譯後的代碼中,而不僅僅是函數名;而C語言并不支援函數重載,是以編譯C語言代碼的函數時不會帶上函數的參數類型,一般隻包括函數名。)
  • 不要忘記把新增的cpp檔案添加到CMakeLists的add_library裡面
  • 新增cpp檔案後最好對cpp檔案夾make一次(AndroidStudio的頂部Build->Make Moduie)
  • 如果編譯運作過後報沒有找到你編譯的so檔案,可以去build下面檢視是否編譯so檔案成功
    使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

 Demo位址

使用Lame庫實作wav、pcm轉mp3前言一、Lame庫是什麼?二、使用步驟三、注意總結

https://gitcode.net/weixin_41620505/pcm-and-wav-to-mp3

總結

第一次編譯還是有挺多坑的,比如上面需要注意的那幾點。