lame example

#include "codec.h"          // self

#include <fstream>                  // std::ofstream
#include <stdexcept>                // std::logic_error
#include "../lameplus/lameplus.h"   // LamePlus
#include "../wave/wave.h"           // Wave

NAMESPACE_CONVIMP3_START

bool Codec::encode( const char *in_file, const char *out_file )
{
    wave::Wave pcm( in_file );

    unsigned sample_rate    = pcm.get_samples_per_sec();
    unsigned byte_rate      = pcm.get_avg_bytes_per_sec();
    unsigned channels       = pcm.get_channels();

    std::ofstream mp3( out_file, std::ios_base::binary | std::ios_base::out  );

    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;

    unsigned offset = 0;

    std::vector<char> pcm_buffer;
    pcm_buffer.reserve( sizeof(short int) * PCM_SIZE * 2 );

    unsigned char mp3_buffer[MP3_SIZE];

    lameplus::LamePlus l;

    l.set_in_samplerate( sample_rate );
    l.set_brate( byte_rate );

    if( channels == 1 )
    {
        l.set_num_channels( 1 );
        l.set_mode( MONO );
    }
    else
    {
        l.set_num_channels( channels );
    }

    l.set_VBR( vbr_default );
    l.init_params();

    while( true )
    {
        int k = ( channels == 1 ) ? 1 : 2;

        unsigned size = PCM_SIZE * k * sizeof( short int );

        pcm.get_samples( offset, size, pcm_buffer );

        unsigned read = pcm_buffer.size();

        offset += read;

        if( read > 0 )
        {
            unsigned read_shorts = read / 2;  // need number of 'short int' read

            int write = 0;

            if( channels == 1 )
            {
                write = l.encode_buffer( reinterpret_cast<short int*>( &pcm_buffer[0] ), NULL, read_shorts, mp3_buffer, MP3_SIZE );
            }
            else
            {
                write = l.encode_buffer_interleaved( reinterpret_cast<short int*>( &pcm_buffer[0] ), read_shorts, mp3_buffer, MP3_SIZE );
            }

            pcm_buffer.clear();

            mp3.write( reinterpret_cast<char*>( mp3_buffer ) , write );
        }

        if( read < size )
        {
            int write = l.encode_flush( mp3_buffer, MP3_SIZE );

            mp3.write( reinterpret_cast<char*>( mp3_buffer ), write );

            break;
        }

    };

    return true;
}

bool Codec::decode( const char *in_file, const char *out_file )
{
    std::ifstream mp3( in_file, std::ios_base::binary | std::ios_base::in );

    if( mp3.is_open() == false )
    {
        return false;
    }

    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;

    char pcm_buffer_l[ PCM_SIZE * sizeof(short int) ];
    char pcm_buffer_r[ PCM_SIZE * sizeof(short int) ];
    unsigned char mp3_buffer[MP3_SIZE];

    lameplus::LamePlus l;

    l.set_decode_only( 1 );

    if( l.init_params() == -1 )
        return false;

    lameplus::Hip       hip;

    bool got_header = false;

    wave::Wave res;

    int channels        = 0;

    while( true )
    {
        mp3.read( reinterpret_cast<char*>( mp3_buffer ), sizeof(char) * MP3_SIZE );

        int read = mp3.gcount();

        if( read <= 0 )
            break;

        int num_samples = 0;

        while( true )
        {
            if( got_header )
            {
                num_samples = hip.decode1(
                        mp3_buffer, read,
                        reinterpret_cast<short int*>( & pcm_buffer_l[0] ),
                        reinterpret_cast<short int*>( & pcm_buffer_r[0] ) );
            }
            else
            {
                lameplus::MP3Data   mp3data;

                num_samples = hip.decode1_headers(
                        mp3_buffer, read,
                        reinterpret_cast<short int*>( & pcm_buffer_l[0] ),
                        reinterpret_cast<short int*>( & pcm_buffer_r[0] ), mp3data );

                if( mp3data.is_header_parsed() )
                {
                    got_header = true;

                    channels        = mp3data.get_stereo();
                    int samplerate  = mp3data.get_samplerate();
                    int bitrate     = mp3data.get_bitrate() * 1000;

                    int bits_per_sample = bitrate / ( samplerate * channels );

                    bits_per_sample = 16;

                    res = wave::Wave( channels, samplerate, bits_per_sample );
                }
            }

            if( num_samples == 0 )
            {
                if( read > 0 )  // need more data to continue decoding
                {
                    read = 0;
                    continue;
                }
                break;
            }

            if( num_samples == -1 )
                throw std::logic_error( "Codec::decode(): decoding error" );

            if( got_header == false )
                throw std::logic_error( "Codec::decode(): got samples without header" );

            read    = 0;

            if( channels == 2 )
                res.append_samples( pcm_buffer_l, pcm_buffer_r, num_samples * sizeof( short int ) );
            else
                res.append_samples( pcm_buffer_l, num_samples * sizeof( short int ) );
        }

        if( mp3.fail() )
            break;
    }

    if( got_header == false )
        return false;

    res.save( out_file );

    return true;
}

NAMESPACE_CONVIMP3_END

### 如何在 C++ 和 Qt5.9 中集成并使用 LAME 进行音频编码 #### 准备工作 为了能够在基于Qt的应用程序中利用LAME库进行MP3文件的编码操作,需要先获取到LAME库本身及其头文件。可以通过包管理工具安装预构建版本或是从源码编译来获得最新特性。 对于Ubuntu环境而言,可以借助apt-get命令快速完成依赖项的部署[^2]: ```bash sudo apt-get update && sudo apt-get install libmp3lame-dev ``` 这样做的好处在于简化了配置流程,并且能够确保所使用的组件与其他系统级服务保持兼容性。 #### 创建Qt项目结构 启动Qt Creator新建一个Console Application类型的工程,在`.pro`文件里加入对外部静态链接库的支持声明: ```qmake QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 console TARGET = lame_example TEMPLATE = app # Add LAME library path and include directory here. LIBS += -lmp3lame INCLUDEPATH += /usr/include/lame ``` 这段设置告知QMake有关外部资源的位置信息以便后续调用时能顺利找到对应的函数定义与实现体。 #### 编写核心逻辑代码 下面给出一段简单的例子展示怎样读取WAV格式的数据流并通过LAME转换成MP3格式保存至本地磁盘: ```cpp #include <iostream> #include "lame.h" int main(int argc, char *argv[]) { FILE* pcmFile; FILE* mp3File; // Open PCM file (raw audio data). if ((pcmFile = fopen("input.pcm", "rb")) == NULL){ std::cerr << "Failed to open input file." << std::endl; return -1; } // Create MP3 output file. if((mp3File = fopen("output.mp3","wb"))==NULL){ fclose(pcmFile); std::cerr << "Failed to create output file." << std::endl; return -1; } int sampleRate=44100; /* Hz */ unsigned long numChannels=2; unsigned long bitrate=128;/* kbps */ lame_t lame=lame_init(); lame_set_in_samplerate(lame,sampleRate); lame_set_num_channels(lame,numChannels); lame_set_brate(lame,bitrate); if(lame_init_params(lame)!=0){ std::cerr << "Error initializing parameters!"<<std::endl; fclose(mp3File); fclose(pcmFile); return -1; } short int buffer[1152*2];/* Buffer size should be at least 1152 samples per channel */ unsigned char mp3buffer[16*1152]; int readSize; while(!feof(pcmFile)){ readSize=fread(buffer,sizeof(short),numChannels*1152/sizeof(short),pcmFile); int result=lame_encode_buffer_interleaved(lame,(short int*)buffer, readSize/(2*numChannels), mp3buffer,&(unsigned long) sizeof(mp3buffer)); fwrite(mp3buffer,1,result,mp3File); } // Flush remaining bits into the stream. int finalResult=lame_close(lame); fwrite(finalResult,1,lame_get_size(lame),mp3File); fclose(mp3File); fclose(pcmFile); return 0; } ``` 以上示例展示了基本的工作原理——即通过循环不断地向LAME传递原始采样数据直到处理完毕为止;最后关闭句柄之前记得清理残留位以保证生成完整的帧序列[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值