国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

常用的開源MP3編解碼器

這篇具有很好參考價值的文章主要介紹了常用的開源MP3編解碼器。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

由于工作需要,需對MP3進行編解碼處理,研究了幾款開源的MP3編解碼器。相對于FFMPEG來說,這幾款都屬于輕量級的編解碼器,更容易移植。

LAME

源碼下載鏈接:https://sourceforge.net/projects/lame/
支持MP3編解碼。編碼出來的MP3音色純厚、空間寬廣、低音清晰、細節(jié)表現(xiàn)良好,它獨創(chuàng)的心理音響模型技術(shù)保證了CD音頻還原的真實性,配合VBR和ABR參數(shù),音質(zhì)幾乎可以媲美CD音頻,但文件體積卻非常小,是目前主流的編碼器。

MAD

MAD(libmad)是一個開源的高精度MPEG音頻解碼庫,支持MPEG-1標準。libmad提供24-bit的PCM輸出,完全定點計算,非常適合在沒有浮點支持的嵌入式硬件平臺上使用。使用libmad提供的一系列API可以實現(xiàn)MP3文件的解碼。
源碼下載鏈接:https://sourceforge.net/projects/mad/
例程minimad.c是在運行前將整個MP3文件讀入內(nèi)存中進行處理,不適合MP3流未知的場景,需改成邊解碼邊寫入MP3的形式,即每次讀入1K MP3數(shù)據(jù),解碼完成再讀入1K,又不影響播放的連續(xù)性,方便在資源緊張的嵌入式系統(tǒng)中運用。
libmad中的mad_decoder_run()進行解碼時,首先會檢測待解碼緩沖區(qū)中是否存在數(shù)據(jù),有則解碼,沒有則調(diào)用input()函數(shù)進行裝載數(shù)據(jù),并返回MAD_FLOW_CONTINUE表示還存在數(shù)據(jù),解碼完成后調(diào)用output()函數(shù)進行處理,如此循環(huán)…直到input()函數(shù)返回MAD_FLOW_STOP表示該MP3數(shù)據(jù)流已經(jīng)完全加載,output()函數(shù)輸出后,表示該MP3文件已完成全部解碼操作。
input()函數(shù)如下,每次調(diào)用讀入FRAME_SIZE_MP3字節(jié)數(shù)據(jù):

static
enum mad_flow input(void *data,
		    struct mad_stream *stream)
{
  PT_Mp3Info ptMp3Info = (PT_Mp3Info)data;
  int ret;
  int restLen;   // unprocessed data's size
  int readLen;

  if (!feof(fin)) {
    restLen = stream->bufend - stream->next_frame;
    memcpy(ptMp3Info->inMp3, ptMp3Info->inMp3+ptMp3Info->inLen-restLen, restLen);
    readLen = FRAME_SIZE_MP3 - restLen;
    int readn = fread(ptMp3Info->inMp3+restLen, sizeof(char), readLen, fin);
    ptMp3Info->inLen = restLen + readn;
    mad_stream_buffer(stream, ptMp3Info->inMp3, ptMp3Info->inLen);
    ret = MAD_FLOW_CONTINUE;
  }
  else {
    ret = MAD_FLOW_STOP;
  }

  return ret;
}

完整代碼如下:


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include "mad.h"

#define FRAME_SIZE_MP3  (1024)

typedef struct _Mp3Info {
  unsigned char inMp3[FRAME_SIZE_MP3];
  unsigned int  inLen;
}T_Mp3Info, *PT_Mp3Info;

static FILE *fin  = NULL;
static FILE *fout = NULL;
static int decode(PT_Mp3Info ptMp3Info);


int main(int argc, char *argv[])
{
  if (argc != 3) {
    printf("%s <inMp3> <outPcm>\n", argv[0]);
    return -1;
  }
  
  fin  = fopen(argv[1], "r");
  fout = fopen(argv[2], "wb+");

  T_Mp3Info tMp3Info; 
  decode(&tMp3Info);

  fclose(fin);
  fclose(fout);

  return 0;
}


/*
 * This is the input callback. The purpose of this callback is to (re)fill
 * the stream buffer which is to be decoded. In this example, an entire file
 * has been mapped into memory, so we just call mad_stream_buffer() with the
 * address and length of the mapping. When this callback is called a second
 * time, we are finished decoding.
 */

static
enum mad_flow input(void *data,
		    struct mad_stream *stream)
{
  PT_Mp3Info ptMp3Info = (PT_Mp3Info)data;
  int ret;
  int restLen;   // unprocessed data's size
  int readLen;

  if (!feof(fin)) {
    restLen = stream->bufend - stream->next_frame;
    memcpy(ptMp3Info->inMp3, ptMp3Info->inMp3+ptMp3Info->inLen-restLen, restLen);
    readLen = FRAME_SIZE_MP3 - restLen;
    int readn = fread(ptMp3Info->inMp3+restLen, sizeof(char), readLen, fin);
    ptMp3Info->inLen = restLen + readn;
    mad_stream_buffer(stream, ptMp3Info->inMp3, ptMp3Info->inLen);
    ret = MAD_FLOW_CONTINUE;
  }
  else {
    ret = MAD_FLOW_STOP;
  }

  return ret;
}

/*
 * The following utility routine performs simple rounding, clipping, and
 * scaling of MAD's high-resolution samples down to 16 bits. It does not
 * perform any dithering or noise shaping, which would be recommended to
 * obtain any exceptional audio quality. It is therefore not recommended to
 * use this routine if high-quality output is desired.
 */

static inline
signed int scale(mad_fixed_t sample)
{
  /* round */
  sample += (1L << (MAD_F_FRACBITS - 16));

  /* clip */
  if (sample >= MAD_F_ONE)
    sample = MAD_F_ONE - 1;
  else if (sample < -MAD_F_ONE)
    sample = -MAD_F_ONE;

  /* quantize */
  return sample >> (MAD_F_FRACBITS + 1 - 16);
}

/*
 * This is the output callback function. It is called after each frame of
 * MPEG audio data has been completely decoded. The purpose of this callback
 * is to output (or play) the decoded PCM audio.
 */

static
enum mad_flow output(void *data,
		     struct mad_header const *header,
		     struct mad_pcm *pcm)
{
  unsigned int nchannels, nsamples;
  mad_fixed_t const *left_ch, *right_ch;

  /* pcm->samplerate contains the sampling frequency */

  nchannels = pcm->channels;
  nsamples  = pcm->length;
  left_ch   = pcm->samples[0];
  right_ch  = pcm->samples[1];

  while (nsamples--) {
    signed int sample;

    /* output sample(s) in 16-bit signed little-endian PCM */

    sample = scale(*left_ch++);
    char high = (sample >> 0) & 0xff;
    char low  = (sample >> 8) & 0xff;
//    putchar((sample >> 0) & 0xff);
//    putchar((sample >> 8) & 0xff);
    fwrite(&high, sizeof(char), 1, fout);
    fwrite(&low, sizeof(char), 1, fout);

    if (nchannels == 2) {
      sample = scale(*right_ch++);
//      putchar((sample >> 0) & 0xff);
//      putchar((sample >> 8) & 0xff);
      high = (sample >> 0) & 0xff;
      low  = (sample >> 8) & 0xff;
      fwrite(&high, sizeof(char), 1, fout);
      fwrite(&low, sizeof(char), 1, fout);
    }
    
  }

  return MAD_FLOW_CONTINUE;
}

/*
 * This is the error callback function. It is called whenever a decoding
 * error occurs. The error is indicated by stream->error; the list of
 * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)
 * header file.
 */

static
enum mad_flow error(void *data,
		    struct mad_stream *stream,
		    struct mad_frame *frame)
{
  PT_Mp3Info ptMp3Info = (PT_Mp3Info)data;

  fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %lu\n",
	  stream->error, mad_stream_errorstr(stream),
	  stream->this_frame - ptMp3Info->inMp3);

  /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */

  return MAD_FLOW_CONTINUE;
}

/*
 * This is the function called by main() above to perform all the decoding.
 * It instantiates a decoder object and configures it with the input,
 * output, and error callback functions above. A single call to
 * mad_decoder_run() continues until a callback function returns
 * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and
 * signal an error).
 */

static
int decode(PT_Mp3Info ptMp3Info)
{
  struct mad_decoder decoder;
  int result;

  if (ptMp3Info == NULL) {
    printf("ptMp3Info is NULL\n");
    return -1;
  }

  /* configure input, output, and error functions */

  mad_decoder_init(&decoder, ptMp3Info,
		   input, 0 /* header */, 0 /* filter */, output,
		   error, 0 /* message */);

  /* start decoding */

  result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);

  /* release the decoder */

  mad_decoder_finish(&decoder);

  return result;
}

tinymp3

支持MP3編解碼,代碼量少,適合在單片機上移植。
源碼下載鏈接:https://github.com/cpuimage/tinymp3

minimp3

僅支持MP3解碼,只有一個頭文件,適合在單片機上移植。
源碼下載鏈接:https://github.com/lieff/minimp3
minimp3的使用只需調(diào)用一個函數(shù)即可實現(xiàn)解碼

int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_sample_t *pcm, mp3dec_frame_info_t *info);

消耗的 MP3 數(shù)據(jù)的大小在定義的mp3dec_frame_info_t結(jié)構(gòu)中的frame_bytes字段中返回,必須在下一次解碼器調(diào)用之前從輸入緩沖區(qū)中刪除對應(yīng)于 frame_bytes 字段的數(shù)據(jù)。
解碼函數(shù)返回已解碼樣本的數(shù)量samples??赡艹霈F(xiàn)以下情況:
0: 在輸入緩沖區(qū)中未找到 MP3 數(shù)據(jù)
384: Layer 1
576: MPEG 2 Layer 3
1152: Otherwise

samples 和 frame_bytes 字段值:
samples > 0 和 frame_bytes > 0: 成功解碼
samples == 0 和 frame_bytes > 0: 解碼器跳過了 ID3 或無效數(shù)據(jù)
samples == 0 和 frame_bytes == 0: 數(shù)據(jù)不足

參考代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-407180.html

#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>


#define MINIMP3_IMPLEMENTATION 
#include "minimp3.h"

int main(int argc, char *argv[])
{
	unsigned char *inMp3 = NULL;
	int totalLen = 0;
	
	if (argc != 3) {
		printf("%s <inMp3> <outPcm>\n", argv[0]);
		return -1;
	}
	//打開MP3文件
	FILE* fin = fopen(argv[1], "r");

	//獲取MP3文件長度
	fseek(fin, 0, SEEK_END);
	totalLen = (int)ftell(fin);

	//讀取整個MP3文件
	fseek(fin, 0, SEEK_SET);
	inMp3 = malloc(totalLen);
	fread(inMp3, 1, totalLen, fin);
    fclose(fin);
	
	//定義mp3dec_frame_info_t
	mp3dec_frame_info_t info;
	short outPcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
	int inLen = 0;

	//逐幀解碼
	int samples = mp3dec_decode_frame(&mp3d, inMp3, totalLen, outPcm, &info);
	while(samples) {
		fwrite(outPcm, sizeof(short), samples, fout);
		inLen += info.frame_bytes;
		samples = mp3dec_decode_frame(&mp3d, inMp3 + inLen, totalLen - inLen, outPcm, &info);
	}
    
	free(inMp3);
	inMp3 = NULL;
	
	fclose(fout);
	
	return 0;
}

到了這里,關(guān)于常用的開源MP3編解碼器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 編碼器 | 基于 Transformers 的編碼器-解碼器模型

    基于 transformer 的編碼器-解碼器模型是 表征學習 和 模型架構(gòu) 這兩個領(lǐng)域多年研究成果的結(jié)晶。本文簡要介紹了神經(jīng)編碼器-解碼器模型的歷史,更多背景知識,建議讀者閱讀由 Sebastion Ruder 撰寫的這篇精彩 博文。此外,建議讀者對 自注意力 (self-attention) 架構(gòu) 有一個基本了解

    2024年02月08日
    瀏覽(28)
  • 【Transformer系列(1)】encoder(編碼器)和decoder(解碼器)

    【Transformer系列(1)】encoder(編碼器)和decoder(解碼器)

    前言 這個專欄我們開始學習transformer,自推出以來transformer在深度學習中占有重要地位,不僅在NLP領(lǐng)域,在CV領(lǐng)域中也被廣泛應(yīng)用,尤其是2021年,transformer在CV領(lǐng)域可謂大殺四方。 在論文的學習之前,我們先來介紹一些專業(yè)術(shù)語。本篇就讓我們先來認識一下encoder和decoder吧!

    2024年03月25日
    瀏覽(22)
  • 【Netty】Netty 解碼器(十二)

    【Netty】Netty 解碼器(十二)

    回顧Netty系列文章: Netty 概述(一) Netty 架構(gòu)設(shè)計(二) Netty Channel 概述(三) Netty ChannelHandler(四) ChannelPipeline源碼分析(五) 字節(jié)緩沖區(qū) ByteBuf (六)(上) 字節(jié)緩沖區(qū) ByteBuf(七)(下) Netty 如何實現(xiàn)零拷貝(八) Netty 程序引導類(九) Reactor 模型(十) 工作原理

    2024年02月07日
    瀏覽(24)
  • 22.Netty源碼之解碼器

    22.Netty源碼之解碼器

    https://mp.weixin.qq.com/s/526p5f9fgtZu7yYq5j7LiQ Netty 常用解碼器類型: ByteToMessageDecoder/ReplayingDecoder 將字節(jié)流解碼為消息對象; MessageToMessageDecoder 將一種消息類型解碼為另外一種消息類型。 自定義一次解碼器ByteToMessageDecoder解碼器,如果讀到的字節(jié)大小為4,那么認為讀取到了1個完整的數(shù)

    2024年02月14日
    瀏覽(23)
  • 23.Netty源碼之內(nèi)置解碼器

    在前兩節(jié)課我們介紹了 TCP 拆包/粘包的問題,以及如何使用 Netty 實現(xiàn)自定義協(xié)議的編解碼??梢钥吹?,網(wǎng)絡(luò)通信的底層實現(xiàn),Netty 都已經(jīng)幫我們封裝好了,我們只需要擴展 ChannelHandler 實現(xiàn)自定義的編解碼邏輯即可。 更加人性化的是,Netty 提供了很多開箱即用的解碼器,這些

    2024年02月13日
    瀏覽(26)
  • ffmpeg中的avs解碼器綜述

    ffmpeg中的avs解碼器綜述

    最近拿了一個avs的視頻流,用硬件可以解碼,但是ffmpeg自帶的卻無法解碼。 所以研究了一下,首先看ffmpeg的avs解碼器: 可以看到avs有兩個,第一個是avs 第二個是cavs. 我們先用avs來解碼,解碼的視頻是通過【 avs編碼器 】編碼的: 結(jié)果發(fā)現(xiàn)有問題,尺寸本來是640 360,結(jié)果被強

    2024年02月08日
    瀏覽(23)
  • flutter 視頻解碼器fijkplayer使用

    ? ? ? ?本人做視頻監(jiān)控項目的時候,需要去展示視頻流到用戶端,一開始使用flutter自帶的VideoPlayer播放監(jiān)控視頻,一開始沒有發(fā)現(xiàn)有什么問題,因為使用多的是Android模擬器,一直沒有使用iso模擬器或者真機測試能不能播放,直到開發(fā)接近尾聲,在ios模擬器上測試的時候發(fā)現(xiàn)

    2023年04月10日
    瀏覽(25)
  • 【NLP概念源和流】 06-編碼器-解碼器模型(6/20 部分)

    【NLP概念源和流】 06-編碼器-解碼器模型(6/20 部分)

    ????????在機器翻譯等任務(wù)中,我們必須從一系列輸入詞映射到一系列輸出詞。讀者必須注意,這與“序列標記”不同,在“序列標記”中,該任務(wù)是將序列中的每個單詞映射到預(yù)定義的類,如詞性或命名實體任務(wù)。 作者生成 ????????在上面的

    2024年02月14日
    瀏覽(50)
  • 深入了解Transformer:從編碼器到解碼器的神經(jīng)網(wǎng)絡(luò)之旅

    深入了解Transformer:從編碼器到解碼器的神經(jīng)網(wǎng)絡(luò)之旅

    自2017年問世以來,Transformer模型在自然語言處理(NLP)領(lǐng)域引發(fā)了一場革命。它的獨特設(shè)計和高效性能使其成為了解決復雜語言任務(wù)的關(guān)鍵工具。 (1)自注意力機制 Transformer的核心在于自注意力機制。它允許模型在處理每個詞時考慮句子中的所有其他詞,從而有效捕獲長距離依

    2024年01月17日
    瀏覽(26)
  • ffmpeg視頻解碼器的配置選項含義

    lowres 是 AVCodecContext 結(jié)構(gòu)體中的一個成員變量,用于指定編解碼器的降低分辨率級別。 在某些情況下,為了加快編解碼的速度或減少計算資源的消耗,可以通過設(shè)置 lowres 參數(shù)來降低編解碼器的分辨率級別。這將導致編解碼器在處理視頻時使用較低的分辨率,從而減少計算量

    2024年02月22日
    瀏覽(58)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包