tinymp3解码

引言

在实际应用中由于受传输带宽等外界因素的影响,数据在传输过程中往往会被拆分成多组数据进行发送,MP3数据可能会被拆分传输,理想情况下,用户希望是按MP3数据帧的整数倍进行传输的,但往往并不能如愿以偿。MP3数据是以帧作为一个解码单元,所以需对实际数据进行解析拆解拼接成完整的数据帧进行解码。

流程图

在这里插入图片描述

代码实现


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

#define DR_MP3_IMPLEMENTATION

#include "dr_mp3.h"

#define MP3_BUF_LEN   (72)
#define PCM_BUF_LEN   (1152)

static FILE *fout = NULL;
static drmp3dec *dec = NULL;
static drmp3dec_frame_info *info = NULL;

int CheckMp3Header(const char *mp3Buf, const int len)
{
    // static char header[] = {0xFF, 0xE3, 0x28, 0xC0};
    static char header[] = {0xFF, 0xE3, 0x18, 0xC4};
    int headerLen = sizeof(header);
    int index = 0;
    while (index < len)
    {
        if (memcmp((mp3Buf+index), header, headerLen)) {
            index++;
        }
        else
            break;
    }
    printf("(%s %s LINE-%d)index: %d\n", __FILE__, __FUNCTION__, __LINE__, index);
    if (index > len)
        return -1;
    else
        return index;
}

void HandleMp3Data(const char *buf, const int len, void (*pFuncMp3Decode)(const char *mp3Data, const int len))
{
    static int restLen;
    static char restBuf[MP3_BUF_LEN];
    char mp3Buf[MP3_BUF_LEN] = {0x00};
    int handleLen = len;
    int i = 0;

    if (restLen + len > MP3_BUF_LEN) {
        while (i < len) {
            if (restLen == 0) {
                memcpy(mp3Buf, buf+i, MP3_BUF_LEN);
                i += MP3_BUF_LEN;
                handleLen -= MP3_BUF_LEN;
            }
            else {
                memcpy(mp3Buf, restBuf, restLen);
                memcpy(&(mp3Buf[restLen]), buf, MP3_BUF_LEN-restLen);
                handleLen -= (MP3_BUF_LEN-restLen);
                i += (MP3_BUF_LEN-restLen);
                restLen = 0;
            }
            
            int index = CheckMp3Header(mp3Buf, MP3_BUF_LEN);
            if (index == 0) {
                // decode
                pFuncMp3Decode(mp3Buf, MP3_BUF_LEN);
            }
            else if (index == -1) {
                // throw away
                memset(mp3Buf, 0x00, MP3_BUF_LEN);
            }
            else {
                restLen = MP3_BUF_LEN-index;
                memcpy(restBuf, mp3Buf+index, restLen);
                continue;
            }
            
            
            if (handleLen < MP3_BUF_LEN && i < len) {
                memcpy(restBuf, buf+i, handleLen);
                restLen = handleLen;
                break;
            }
            memset(mp3Buf, 0x00,  MP3_BUF_LEN);
        } 
    }
    else {
        memcpy(&(restBuf[restLen]), buf, len);
        restLen += len;
    }
}

void DecodeMp3Data(const char *mp3Data, const int mp3Len)
{
    char pcmBuf[PCM_BUF_LEN] = {0x00};
    int decLen = drmp3dec_decode_frame(dec, (drmp3_uint8 *)mp3Data, mp3Len, pcmBuf, info);
    if (decLen > 0) {
        // printf("frame_bytes(%d), channels(%d), hz(%d), layer(%d), bitrate_kbps(%d)\n", info->frame_bytes, info->channels, info->hz, info->layer, info->bitrate_kbps);
        fwrite(pcmBuf, 1, decLen << 1, fout);
        
    }
}

int main(int argc, char *argv[])
{
    FILE *fin  = fopen(argv[1], "r");
    fout = fopen(argv[2], "wb+");
    int inLen = atoi(argv[3]);

    info = (drmp3dec_frame_info *)calloc(sizeof(drmp3dec_frame_info), 1);
    dec = (drmp3dec *)calloc(sizeof(drmp3dec), 1);
    char *mp3Buf = (char *)calloc(1, inLen);
    
    fseek(fin, 50, 0);
    while (1)
    {
        int mp3Len = fread(mp3Buf, 1, inLen, fin);
        HandleMp3Data(mp3Buf, mp3Len, DecodeMp3Data);
        if (feof(fin))
           break;
    }

    free(info);
    free(dec);
    free(mp3Buf);

    fclose(fin);
    fclose(fout);

    return 0;
}

以开源库tinymp3作为解码库进行实现。

测试结果

在这里插入图片描述该MP3帧长为72,分别采取不同长度的输入进行解码,解码结果均一致。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值