使用lame对音频文件PCM进行转码为MP3格式

1、LAME简介

LAME是目前非常优秀的一种MP3编码引擎,可以把音频文件转为MP3格式。当达到320Kbit/s以上时,LAME编码出来的音频质量几乎可以和CD的音质相媲美,并且能保证整个音频文件的体积非常小,非常适合移动端平台上的MP3文件编码。

2、LAME文件编译

2.1 LAME源码下载

https://sourceforge.net/projects/lame/files/lame 选择我们想要的版本进行下载,下载后的文件是常规的文件lame-3.99.5.tar.gz,用terminal(俗称黑框),切换到文件所在路径下,执行tar xzvf lame-3.99.5.tar.gz命令进行解压。

2.2 编译为ios使用的文件

编写shell脚本文件build_armv7.sh脚本,用脚本编译文件。

./configure \
--disable-shared \
--disable-frontend \
--host=arm-apple-drawin \
--prefix="./thin/armv7" \
CC="xcrun -sdk iphoneos clang -arch armv7" \
CFLAGS="-arch armv7 -fembed-bitcode -miphoneos-version-min=7.0" \
LDFLAGS="-arch armv7 -fembed-bitcode -miphoneos-version-min=7.0" \
make clean
make -j8
make install

--prefix:指定编译号的库放在哪个路径下;

--host:指定生成的库要运行的平台;

CC:指定编译工具编译链的路径,这里指的是gcc的路径;

CFLAGS:指定编译时的参数,-arch armv7表示库运行的目标平台,-fembed-bitcode指定打开bitcode选项,表示项目可以在enable-bitcode设置为YES的情况下使用,-miphoneos-version-min=7.0,表示最低支持的运行版本;

LDFLAGS:表示链接时的参数,与编译时参数相同;

--disable-shared:关闭动态链接库;

--disable-frontend:表示不编译出可执行文件;

把脚本放到解压出的源码中,在黑框中执行./build_armv7.sh进行编译,最后会在armv7目录下生成bin、lib、include、share四个目录,如果需要编译出其他架构的文件,修改armv7为arm64、x86_64、arm64等,执行脚本即可,最后可以通过执行lipo -create ./arm64/lib/libmp3lame.a ./armv7/bin/libmp3lame.a -output libmp3lame.a合并为一个静态库文件。

2.3 推荐另一个编译脚本

一个一个的编译有点麻烦,这里我找到一个大牛写的编译脚本,可以一次编译出所有平台的静态库文件,或者指定编译平台,并且会自动合并为一个静态库文件。大牛的写的脚本地址传送门,根据Readme文件中的说明执行,把脚本文件放到源码的文件夹的同级目录下,执行./build-lame.sh就会编译出全平台的静态库,./build-lame.sh armv7 arm64 x86_64只会编译这三个平台的静态库,脚本会默认链接输出,这里有个注意点,脚本里面写的路径是lame,所以我们把脚本所在目录修改为lame,这样才能正常编译,读者也可以修改脚本中的路径与实际路径相同。最终结果如图:

3、在ios项目中利用lame转码PCM文件为MP3

3.1 创建项目,导入静态库

3.2 编写编码工具类

mp3_encoder.hpp和mp3_encoder.cpp

//
//  Mp3Encoder.hpp
//  PhuketTour
//
//  Created by 司伟红 on 2018/12/23.
//  Copyright © 2018年 司伟红. All rights reserved.
//

#ifndef Mp3Encoder_hpp
#define Mp3Encoder_hpp

#include <stdio.h>
#import "lame.h"

class Mp3Encoder{
    private:
    FILE* pcmFile;
    FILE* mp3File;
    lame_t lameClient;
    
    public :
    Mp3Encoder();
    ~Mp3Encoder();
    int Init(const char* pcmFilePath, const char* mp3FilePath, int sampleRate, int channels, int bitRate);
    void Encode();
    void Destory();
};

#endif /* Mp3Encoder_hpp */
//
//  Mp3Encoder.cpp
//  PhuketTour
//
//  Created by 司伟红 on 2018/12/23.
//  Copyright © 2018年 司伟红. All rights reserved.
//

#include "Mp3Encoder.hpp"

Mp3Encoder::Mp3Encoder() {
}

Mp3Encoder::~Mp3Encoder() {
}

int Mp3Encoder::Init(const char *pcmFilePath, const char *mp3FilePath, int sampleRate, int channels, int bitRate){
    int ret = -1;
    pcmFile = fopen(pcmFilePath, "rb");
    if (pcmFile) {
        mp3File = fopen(mp3FilePath, "wb");
        if (mp3File) {
            lameClient = lame_init();
            lame_set_in_samplerate(lameClient, sampleRate);
            lame_set_out_samplerate(lameClient, sampleRate);
            lame_set_num_channels(lameClient, channels);
            lame_set_brate(lameClient, bitRate / 1000);
            lame_init_params(lameClient);
            ret = 0;
        }
    }
    
    return ret;
}

void Mp3Encoder::Encode(){
    int bufferSize = 1024 * 256;
    short *buffer = new short[bufferSize / 2];
    short *leftBuffer = new short[bufferSize / 4];
    short *rightBuffer = new short[bufferSize / 4];
    unsigned char* mp3_buffer = new unsigned char[bufferSize];
    size_t readBufferSize = 0;
    while ((readBufferSize = fread(buffer, 2, bufferSize / 2, pcmFile)) > 0) {
        for (int i = 0; i < readBufferSize; i++) {
            if (i % 2 == 0) {
                leftBuffer[i / 2] = buffer[i];
            } else {
                rightBuffer[i / 2] = buffer[i];
            }
        }
        size_t wroteSize = lame_encode_buffer(lameClient, (short int *) leftBuffer, (short int *) rightBuffer, (int)(readBufferSize / 2), mp3_buffer, bufferSize);
        fwrite(mp3_buffer, 1, wroteSize, mp3File);
    }
    
    delete [] buffer;
    delete [] leftBuffer;
    delete [] rightBuffer;
    delete [] mp3_buffer;
}

void Mp3Encoder::Destory(){
    if (pcmFile) {
        fclose(pcmFile);
    }
    
    if (mp3File) {
        fclose(mp3File);
        lame_close(lameClient);
    }
}

3.3 在view中添加一个按钮,点击按钮的时候调用C++方法编译出mp3文件

- (IBAction)btnClick:(UIButton *)sender {
    NSLog(@"按钮点击事件");
    Mp3Encoder *encoder = new Mp3Encoder();
    // 源文件的的路径
    const char* pcmFilePath = [[CommonUtil bundlePath:@"vocal.pcm"] cStringUsingEncoding:NSUTF8StringEncoding];
    // 要生成的mp3文件的路径
    const char *mp3FilePath = [[CommonUtil documentsPath:@"vocal.mp3"] cStringUsingEncoding:NSUTF8StringEncoding];
    int sampleRate = 44100;
    int channels = 2;
    int bitRate = 128 * 1024;
    // 初始化解码器,传入源文件路径,生成的文件路径,采样频率,声道数,码率
    encoder->Init(pcmFilePath, mp3FilePath, sampleRate, channels, bitRate);
    // 编码
    encoder->Encode();
    //关闭文件
    encoder->Destory();
    delete encoder;
    NSLog(@"Encode Success");
}

3.4 查看生成的文件,用电脑播放查看是否正常

注意,如果编译的时候没有选择x86_64平台,则不能在模拟器上运行,需要真机运行,真机文件的导出方式,需要在info.plist中增加,UIFileSharingEnabled这个Key, 并设置该值为 YES 即可,在填写完 UIFileSharingEnabled并回车后, 发现会自动更正为Application supports iTunes file sharing , 将值设置为YES 即可。然后手机连接电脑,即可看到文件,拖到电脑中可以播放是否编码成功。如图:

这就是利用lame编码PCM为mp3文件的方法。最后附上demo地址

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java本身不支持直接将PCM格式转换为mp3格式,但可以通过使用第三方库来实现此功能。 常用的Java音频库包括LAME、JAVE、FFmpeg等,其中LAME是一个流行的开源mp3编码器,JAVE是一个Java音频和视频编码器,而FFmpeg是一个跨平台的音视频处理库。 使用这些库,你可以将PCM格式音频文件转换为mp3格式。以下是使用LAME库的示例代码: ```java import java.io.*; import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D; import com.sun.media.sound.WaveFileReader; import com.sun.media.sound.WaveFileWriter; import javazoom.jl.converter.Converter; import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.decoder.OutputBitStream; import javazoom.jl.encoder.Encoder; import javazoom.jl.encoder.EncoderException; import javazoom.jl.encoder.EncoderProperties; import javazoom.jl.encoder.Bitstream; public class PCMToMP3 { public static void main(String[] args) throws IOException, EncoderException { String pcmFile = "input.pcm"; String mp3File = "output.mp3"; int sampleRate = 44100; int bitRate = 128000; int channels = 2; // Read PCM data from file FileInputStream fis = new FileInputStream(new File(pcmFile)); byte[] pcmData = new byte[fis.available()]; fis.read(pcmData); fis.close(); // Convert PCM data to MP3 format EncoderProperties props = new EncoderProperties(); props.setBitRate(bitRate); props.setChannels(channels); props.setSamplingRate(sampleRate); Converter converter = new Converter(); converter.convert(pcmData, mp3File, props); } } ``` 在此示例中,我们使用了JAVE库的Converter类将PCM数据转换为mp3格式。请注意,此示例仅适用于16位PCM音频数据。如果你的PCM数据格式不同,你需要相应地更改代码。 此外,你也可以使用其他库,如LAME或FFmpeg,以类似的方式将PCM格式转换为mp3格式

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值