• ogg转到mp3


    最近工作的一个服务,把ogg格式的音频转成mp3格式,这是个http服务,  源ogg音频地址以参数的形式 传进来,解析后我把它取过来,转换后的二进制 mp3文件在http response中返回。

    1.   http server部份

      server 部份用的是 asio 中 的 server3

    2.  关于ogg, speex, mp3

      speex和ogg都是由Xiph.Org Foundation 贡献的,speex是一种codec, 一种coding(compression) format,  ogg是一种container format(media container),并且在xiph.org上这样说到,This(ogg) is our native format and the recommended container for all Xiph codecs.

      ogg programming 文档 http://www.xiph.org/ogg/doc/libogg/index.html  , decode有几个固定的步骤,上面有介绍,  speex 文档案http://speex.org/docs/   其中有manul和API reference ,  manul中有programming介绍,但不够细,像SpeexHeader就要查API reference. 

      以下是其中核心的代码

    View Code
      1 ogg_sync_state         oy;
    2 ogg_page og;
    3 ogg_packet op;
    4 ogg_stream_state os;
    5 ogg_int64_t page_granule = 0;
    6
    7 int frames_per_packet = 0;
    8 bool eos = false;
    9 int packet_count = 0;
    10 //int channels;
    11
    12 SpeexBits bits;
    13 void *st = 0;
    14 int frame_size;
    15
    16 string pcmString;
    17 short pcmBuffer[320];
    18 const int MP3_SIZE = 2000;
    19 unsigned char mp3Buffer[MP3_SIZE];
    20 int mp3EncodeSize;
    21
    22
    23 /*Init Ogg data struct*/
    24 ogg_sync_init(&oy);
    25
    26 speex_bits_init(&bits);
    27
    28 lame_t lame = lame_init();
    29 lame_set_quality(lame, 5);
    30 lame_set_in_samplerate(lame, 8000);
    31 lame_set_VBR(lame, vbr_default);
    32 lame_set_num_channels(lame, 1);
    33 lame_set_mode(lame, MONO);
    34 lame_init_params(lame);
    35
    36 char *data;
    37 data = ogg_sync_buffer(&oy, oggString.size());
    38
    39 memcpy(data, oggString.c_str(), oggString.size());
    40
    41 ogg_sync_wrote(&oy, oggString.size());
    42
    43 bool stream_init = false;
    44
    45 LOG4CPLUS_DEBUG(access_logger, " ogg decode begin");
    46
    47 while(ogg_sync_pageout(&oy, &og) == 1){
    48 if(!stream_init){
    49 ogg_stream_init(&os, ogg_page_serialno(&og));
    50 stream_init = true;
    51 }
    52 ogg_stream_pagein(&os, &og);
    53 page_granule = ogg_page_granulepos(&og);
    54
    55 while(!eos && ogg_stream_packetout(&os, &op) == 1){
    56
    57 // speex header is in first ogg packet
    58 if(packet_count == 0){
    59 LOG4CPLUS_DEBUG(access_logger,"@@@@@@@Packet header@@@@@@@");
    60 // process header
    61 SpeexHeader *header;
    62 // create a SpeexHeader from a packet
    63 header = speex_packet_to_header((char*)op.packet, op.bytes);
    64 if(!header){
    65 cout << "process header error" << endl;
    66 return -1;
    67 }
    68
    69 // cout << "mode = " << header->mode << endl;
    70
    71 SpeexMode *mode = speex_lib_get_mode(header->mode);
    72
    73 st = speex_decoder_init(mode);
    74
    75 if(!st){
    76 cout << "init speex decoder error" << endl;
    77 free(header);
    78 return -1;
    79 }
    80 speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, &frame_size);
    81 LOG4CPLUS_DEBUG(access_logger , "frame size = " << frame_size);
    82 speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, &header->rate);
    83 LOG4CPLUS_DEBUG(access_logger, "rate = " << header->rate);
    84 //if not set in header ,0 here
    85 frames_per_packet = header->frames_per_packet;
    86 LOG4CPLUS_DEBUG(access_logger, "frames_per_packet(if set in header) = " << frames_per_packet);
    87
    88 free(header);
    89 } else {
    90 if(op.e_o_s)
    91 eos = true;
    92
    93 speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
    94
    95 int loop_count = ((frames_per_packet > 0) ? frames_per_packet : bits.nbBits/frame_size) ;
    96 LOG4CPLUS_DEBUG(access_logger, "actual loop count in a packet :" << loop_count);
    97 for(int i = 0; i < loop_count; ++i){
    98 if(speex_decode_int(st, &bits, pcmBuffer) >= 0){
    99 mp3EncodeSize = lame_encode_buffer(lame, pcmBuffer, pcmBuffer, frame_size, mp3Buffer, MP3_SIZE);
    100 // cout << "mp3 size = " << mp3EncodeSize << endl;
    101 mp3String.append((char *)mp3Buffer, mp3EncodeSize);
    102 }
    103
    104 }
    105 }
    106 ++packet_count;
    107 }
    108 }
    109 mp3EncodeSize = lame_encode_flush(lame, mp3Buffer, MP3_SIZE);
    110 // cout << "mp3 flush size" << mp3EncodeSize << endl;
    111 if (mp3EncodeSize > 0){
    112 mp3String.append((char *)mp3Buffer, mp3EncodeSize);
    113 }
    114
    115 lame_close(lame);
    116
    117 speex_bits_destroy(&bits);
    118 speex_decoder_destroy(st);

    语音的转换在一个handler中进行,用libogg库.  

  • 相关阅读:
    解决Web部署 svg/woff/woff2字体 404错误
    C# 汉字转拼音
    jquery ajax返回Internal server error 500错误解决方案
    bootstrap datepicker只能选择小于今天的日期
    向txt文件追加异常日志
    C# DataTable 和List之间相互转换的方法
    js点击行选中checkbox
    bootstrap-datepicker 插件修改为中文显示
    C# 压缩/解压字符串
    c# MD5加密
  • 原文地址:https://www.cnblogs.com/livingintruth/p/2313450.html
Copyright © 2020-2023  润新知