tinymp3 MP3编解码库的使用

17 篇文章 2 订阅
10 篇文章 0 订阅

tinymp3


tinymp3 mp3的编解码器官方demo,将mp3或者wav文件解码后重新压缩为mp3。用法:

image-20210416103724390

运行截图

image-20210416103808829

文件说明

  • dr_mp3.h MP3文件解码与保存库

  • dr_wav.h WAV文件解码与保存库

  • shine_mp3.h 编码器头文件

  • shine_mp3.c 编码器库

使用流程

编码器部分

初始化

  • 不同PCM采样率对应的算法
所使用的算法PCM采样率1PCM采样率2PCM采样率3
MPEG-I441004800032000
MPEG-II220502400016000
MPEG-2.511025120008000
  • 不同算法所支持的比特率
算法名字MPEG-2.5MPEG-IIMPEG-I
1-1-1-1
28832
3161640
4242448
5323256
6404064
7484880
8565696
96464112
1080128
1196160
12112192
13128224
14144256
15160320
  • 初始化参考代码
	//公共变量
	shine_config_t config;//编码器配置
    shine_t shine;//编码器句柄    
	modes stereo = STEREO;//编码模式
	//--
    set_defaults(&config);//配置复位
    stereo = STEREO;//设置模式
    config.mpeg.bitr = 128;//设置码率
    outfname="out.mp3";//设置输出的文件名(编码器不需要使用)
    config.wave.samplerate = 44100;//设置PCM流的采样率
    config.wave.channels = PCM_STEREO;//这事PCM流模式
    /* See if samplerate and bitrate are valid */
    if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0){//检测转换是否支持
        qDebug()<<"Unsupported samplerate/bitrate configuration.";
        return ;
    }
    outfile = fopen(outfname, "wb");//打开文件
    if (!outfile) {
        qDebug()<<"Could not create \"%s\".\n"+ QString(outfname);
        return;
    }
    /* Set to stereo mode if wave data is stereo, mono otherwise. */
    if (config.wave.channels > 1)
        config.mpeg.mode = STEREO;//设置音频模式
    else
        config.mpeg.mode = MONO;
    /* Initiate encoder */
    shine = shine_initialise(&config);//初始化编码器
    written=0;
    CodecState=1;//标志编码器启动
    m_audioEncodeData.clear();

数据编码

  • 数据编码代码
if(CodecState){//编码器是否初始化
    m_audioEncodeData.append(audioData);//将audioData里面的PCM数据累加到m_audioEncodeData中
    int samples_per_pass = shine_samples_per_pass(shine) * PCM_STEREO;//计算一次编码所需要的数据,uint16为单位
    for(;m_audioEncodeData.size()>samples_per_pass*2;){//循环编码
        data = shine_encode_buffer_interleaved(shine, (int16_t *)m_audioEncodeData.data(), &written);//编码
        if (write_mp3(written, data, &config) != written) {//数据写入mp3文件中
            qDebug()<<"mp3 encoder && decoder: write error";
        }
        m_audioEncodeData.remove(0,samples_per_pass*2);//将本次数据弹出
    }
}
  • 编码流程
启动
未启动
不充足
充足
读到PCM数据
编码器是否启动
数据入队列
结束
计算一帧MP3压缩所需数据
队列是否充足
数据编码
MP3帧保存
队列弹出已用数据

结束编码

  • 结束编码使用
    unsigned char *data;
    CodecState=0; //标记编码器结束
    /* Flush and write remaining data. */
    data = shine_flush(shine, &written); //产生mp3尾部数据
    write_mp3(written, data, &config);//写入尾部数据
    /* Close encoder. */
    shine_close(shine);//关闭编码器
    /* Close the MP3 file */
    fclose(outfile);//关闭文件

解码器部分

初始化

  • 初始化代码
    drmp3 mp3; // 全局变量
	if (!drmp3_init_file(&mp3, "out.mp3", NULL)) {//打开文件
        qDebug()<<"文件打开失败";
        return;
    }
	timep->start(10);//10ms的播放定时器启动,10ms为播放队列填充pcm数据保证播放的连续性(一次性解码无需使用)

数据解码

  • 一次性解码
    uint64_t totalSampleCount = 0; //返回的样本总数
    int16_t *data_in = drmp3__full_read_and_close_s16(&mp3, NULL, &totalSampleCount);//一次性解码并返回PCM数据
    if (data_in == NULL){
        qDebug()<<"解码失败";
    }
    QFile file("rawMp3");
    file.open(QIODevice::WriteOnly);
    file.write((char *)data_in,totalSampleCount);
    file.close();
    qDebug()<<"保存成功";
    return;
  • 分块解码
    //解码逻辑
	if(pcm1.size()<4096){//pcm1 为MP3解码缓冲队列
        drmp3_int16 temp[4096];//用于保存解码数据的缓冲
        drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / mp3.channels;//计算本次解码的PCM数据量
        //进行一次解码(每次解码解码器会自动往前移动)
        drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(&mp3, framesToReadRightNow, temp);
        //将缓冲数据压入MP3解码缓冲队列,注:此处使用了Qt测试平台。
        pcm1.append(QByteArray((char *)&temp[0],framesJustRead*mp3.channels*sizeof(drmp3_int16)));
        if(framesJustRead==0){
            stopDecode();
            return;
        }
    }
	//播放逻辑,以下代码与解码无关,是Qt的音频播放逻辑,可参考使用
    if (pcm1.size() > 0) {//当缓冲有数据时候
        int readSize = m_audioOutput->periodSize();//获取播放器单次播放所需数据量
        int chunks = m_audioOutput->bytesFree() / readSize;//获取当前播放器能存入的空白帧
        while (chunks) {
            QByteArray samples = pcm1.mid(0, readSize);//将所需数据放入缓冲变量
            int len = samples.size();
            pcm1.remove(0, len);//弹出已使用的数据

            if (len) updateAudioData(samples);//写入播放器
            if (len != readSize) break;

            chunks--;
        }
    }

结束解码

  • 结束代码
    qDebug()<<"结束解码";
    timep->stop();//关闭定时器
    drmp3_uninit(&mp3);//关闭解码器
    playFile->close();//关闭播放文件

mp3库地址

https://github.com/cpuimage/tinymp3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值