日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 音頻編碼之opus

音頻編碼之opus

來源:程序員人生   發布時間:2014-12-08 08:19:03 閱讀次數:7025次

最近項目中用到了語音編碼opus,在網上搜了1下,資料非常少,而且沒有1個完全的教程,現在簡單記錄下來opus的使用方法。


首先介紹1下opus


Opus

Opus編碼器 是1個有損聲音編碼的格式,由互聯網工程任務組(IETF)進來開發,適用于網絡上的實時聲音傳輸,標準格式為RFC 6716。Opus 格式是1個開放格式,使用上沒有任何專利或限制。

特性

Opus的前身是celt編碼器。在現今的有損音頻格式爭取上,具有眾多不同編碼器的AAC格式打敗了一樣很有潛力的Musepack、Vorbis等格式,而在Opus格式誕生后,情況似乎不同了。通過諸多的對照測試,低碼率下Opsu完勝曾優勢明顯的HE AAC,中碼率就已可以媲敵碼率高出30%左右的AAC格式,而高碼率下更接近原始音頻。

以上來自百度百科(PS:百度百科對opus的介紹都很少)


簡單來講,opus是1個高保真的合適在網絡中傳輸的開源的語音編碼格式,相對其他編碼格式來說,保真性更好,但體積會略微大1些。官網地址:http://www.opus-codec.org/


怎樣用呢?

首先你可使用編譯好的so庫直接使用,或也能夠使用源碼自己根據需求生成so庫來使用,固然,你也能夠直接將源碼使用到自己工程各中,這就是開源的好處。好了下面介紹如何編譯。

我是通過Eclipse來編譯的,首先在opus官網下載源代碼,解壓。

編碼工作需要ndk編程所以需要1些NDK編程的知識。

在工程中創建OpusTool類,該類用于調用native層的方法。

package com.ione.opustool; public class OpusTool { public native String nativeGetString(); public native int encode_wav_file(String in_path, String out_path); public native int decode_opus_file(String in_path, String out_path); }

其中nativeGetString()方法是用來測試jni調用是不是成功的測試方法,encode_wav_file(String in_path, String out_path);和 decode_opus_file(String in_path, String out_path);分別是用來編解碼。以上3個方法均需聲明為native,用來調用jni的c函數。然后在項目根目錄下打開命令行,使用javah命令生成.h文件,即:

javah -classpath .inclasses -d jni com.ione.opustool.OpusTool

其中.inclasses為指定OpusTool.class的路徑,-d jni為在當前目錄下生成jni文件夾,用來寄存native層代碼。回車以后便在工程的根目錄下生成了jni文件夾和com_ione_opustool_OpusTool.h文件。如:




/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_ione_opustool_OpusTool */ #ifndef _Included_com_ione_opustool_OpusTool #define _Included_com_ione_opustool_OpusTool #ifdef __cplusplus extern "C" { #endif /* * Class: com_ione_opustool_OpusTool * Method: nativeGetString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_ione_opustool_OpusTool_nativeGetString (JNIEnv *, jobject); /* * Class: com_ione_opustool_OpusTool * Method: encode_wav_file * Signature: (Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_ione_opustool_OpusTool_encode_1wav_1file (JNIEnv *, jobject, jstring, jstring); /* * Class: com_ione_opustool_OpusTool * Method: decode_opus_file * Signature: (Ljava/lang/String;Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_ione_opustool_OpusTool_decode_1opus_1file (JNIEnv *, jobject, jstring, jstring); #ifdef __cplusplus } #endif #endif

接下來復制1份com_ione_opustool_OpusTool.h文件到jni目錄,修改名稱為com_ione_opustool_OpusTool.c修改內容為:

#include <com_ione_opustool_OpusTool.h> JNIEXPORT jstring JNICALL Java_com_ione_opustool_OpusTool_nativeGetString JNIEnv * env, jobject obj) { return (*env)->NewStringUTF(env, "Hello Opus"); } JNIEXPORT jint JNICALL Java_com_ione_opustool_OpusTool_encode_1wav_1file( JNIEnv *env, jobject obj, jstring wav_path, jstring opus_path) { return 0; } JNIEXPORT jint JNICALL Java_com_ione_opustool_OpusTool_decode_1opus_1file( JNIEnv *env, jobject obj, jstring wav_path, jstring opus_path) { return 0; }
然后創建并配置makefile和android.mk文件,后面會給出。記得配置NDK_Builder。
此時可以調用OpusTool類的nativeGetString()方法查看返回數據是不是正常,若為Hello Opus 則jni調用成功。可以繼續下面的工作。

在jni目錄下創建libopus文件夾,將Opus源碼粘貼到該文件夾下,即celt、include、silk、src文件夾和config文件,固然不是所有的文件都用的上,可以根據自記得需求進行拷貝。配置好makefile等配置文件后便可編譯工程,如果編譯順利,則說明配置文件沒有問題,繼續操作。在src文件加下創建opus_tool.c文件用來進行音頻文件的編解碼的c實現。

opus_tool.c

/***************************************************************************** # -*- coding:utf⑻ -*- # author: ione # create date: 2014⑴1⑵7 *****************************************************************************/ #include "android_log.h" #include "opus.h" #include "opus_types.h" #include "opus_multistream.h" #define SAMPLE_RATE 16000 #define CHANNEL_NUM 1 #define BIT_RATE 16000 #define BIT_PER_SAMPLE 16 #define WB_FRAME_SIZE 320 #define DATA_SIZE 1024 * 1024 * 4 int encode(char* in, int len, unsigned char* opus, int* opus_len) { int err = 0; opus_int32 skip = 0; OpusEncoder *enc = opus_encoder_create(SAMPLE_RATE, CHANNEL_NUM, OPUS_APPLICATION_VOIP, &err); if (err != OPUS_OK) { fprintf(stderr, "cannnot create opus encoder: %s ", opus_strerror(err)); enc = NULL; return ⑴; } opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND)); opus_encoder_ctl(enc, OPUS_SET_BITRATE(BIT_RATE)); opus_encoder_ctl(enc, OPUS_SET_VBR(1)); opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(10)); opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC(0)); opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(OPUS_AUTO)); opus_encoder_ctl(enc, OPUS_SET_DTX(0)); opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(0)); opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip)); opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16)); short frame_size = WB_FRAME_SIZE; int frame_bytes = (frame_size << 1); opus_int16 *frame = (opus_int16 *) in; unsigned char *cbits = opus; while (len > frame_bytes) { int nbytes = opus_encode(enc, frame, frame_size, cbits + sizeof(char), 640 - sizeof(short)); if (nbytes > frame_size * 2 || nbytes < 0) { return ⑴; } cbits[0] = nbytes; frame += WB_FRAME_SIZE; cbits += nbytes + sizeof(char); len -= frame_bytes; *opus_len += nbytes + sizeof(char); } opus_encoder_destroy(enc); return 0; } int decode(unsigned char* in, int len, short* out, int* out_len) { int err = 0; opus_int32 skip = 0; *out_len = 0; OpusDecoder *dec = opus_decoder_create(SAMPLE_RATE, 1, &err); if (err != OPUS_OK) { fprintf(stderr, "cannnot decode opus: %s ", opus_strerror(err)); dec = NULL; return ⑴; } short frame_size = WB_FRAME_SIZE; opus_int16 *frame = (opus_int16 *) in; while (len > 0) { int nbytes = in[0]; if (nbytes <= 0) { return ⑴; } int decode_len = opus_decode(dec, in + sizeof(char), nbytes, out, frame_size, 0); if (decode_len != frame_size) { return ⑴; } in += sizeof(char) + nbytes; out += frame_size; len -= nbytes - sizeof(char); *out_len += frame_size; } opus_decoder_destroy(dec); return 0; } int encode_wav_file(char *in_file_path, char *out_file_path) { FILE *fin = fopen(in_file_path, "rb"); if (fin == NULL || fin == 0) { return ⑴; } char *in = (char*) malloc(DATA_SIZE); memset(in, 0, DATA_SIZE); int len = fread(in, 1, DATA_SIZE, fin); if (len == 0) { return ⑴; } FILE *fout = fopen(out_file_path, "wb"); if (fout == NULL || fout == 0) { return ⑴; } unsigned char *out = (unsigned char*) malloc(DATA_SIZE); memset(out, 0, DATA_SIZE); int out_len = 0; encode(in, len, out, &out_len); if (len < 0) { return ⑴; } fwrite(out, 1, out_len * sizeof(unsigned char), fout); free(in); free(out); fclose(fin); fclose(fout); return len; } int make_wav_header(FILE *out, int len) { int size = 0; int *sz = &size; int number; int * nm = &number; // RIFF 4 bytes fseek(out, 0, SEEK_SET); fputs("RIFF", out); // len 4 bytes len = (len + 44 - 8); fwrite(&len, 2, 1, out); number = 0; fwrite(nm, 2, 1, out); // WAVE 4 bytes + "fmt " 4 bytes fputs("WAVEfmt ", out); // size1 4 bytes number = 16; fwrite(nm, 2, 1, out); number = 0; fwrite(nm, 2, 1, out); // format tag 2 bytes number = 1; fwrite(nm, 2, 1, out); // channel 2 bytes number = CHANNEL_NUM; fwrite(nm, 2, 1, out); // sample rate 4 bytes number = SAMPLE_RATE; fwrite(nm, 2, 1, out); number = 0; fwrite(nm, 2, 1, out); //byte per seconds 4 bytes number = 22664; fwrite(nm, 2, 1, out); number = 0; fwrite(nm, 2, 1, out); // block align 2 bytes number = CHANNEL_NUM * BIT_PER_SAMPLE / 8; fwrite(nm, 2, 1, out); // bitPerSample 2 bytes number = 16; fwrite(nm, 2, 1, out); // "data" 4 bytes fputs("data", out); // size2 4 bytes size = (size - 36); fwrite(sz, 2, 1, out); number = 0; fwrite(nm, 2, 1, out); return 0; } int decode_opus_file(char *in_file_path, char *out_file_path) { printf("%s ", in_file_path); FILE *fin = fopen(in_file_path, "rb"); if (fin == NULL || fin == 0) { return ⑴; } unsigned char *in = (unsigned char *) malloc(DATA_SIZE); memset(in, 0, DATA_SIZE); int len = fread(in, 1, DATA_SIZE, fin); FILE *fout = fopen(out_file_path, "wb"); if (fout == NULL || fout == 0) { return ⑴; } short *out = (short *) malloc(DATA_SIZE); memset(out, 0, DATA_SIZE); int out_len = 0; out += 44; decode(in, len, (short *) out, &out_len); if (len < 0) { return ⑴; } fwrite(out, 1, out_len * sizeof(short), fout); int err = make_wav_header(fout, out_len); free(in); free(out); fclose(fin); fclose(fout); return out_len; }
配置makefile文件添加opus_tool.c文件,然后編譯,便可在libs目錄下生成.so文件


至此,native層操作已完成,so庫也已通過編譯得到。

下1篇將會介紹如何使用該so庫。




生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 直接看av的网站 | 国产精品免费一区二区三区 | 激情五月激情综合网 | 男操女在线观看 | 三级网站视频 | 免费国产在线视频 | 欧美日韩福利视频 | 久热福利视频 | 国产精品久久久久久一区二区三区 | 99久久精品国产一区二区三区 | 亚洲狼人综合 | 国产精品久久久久久久久久免费动 | 国产成人免费视频网站视频社区 | 国产精品国产三级国产aⅴ原创 | 国产精品成人一区二区网站软件 | 国内精品影院 | 四虎4545www国产精品 | 国产一区二区三区高清视频 | 91在线亚洲 | 成人精品免费视频 | 国产日韩视频 | 久久久久久久久久综合 | 99久久久国产精品免费调教网站 | 国产高清免费观看 | 男操女 | 欧美国产精品一区二区三区 | 亚洲最大成人免费视频 | 中文字幕日韩专区 | 亚洲欧美激情精品一区二区 | 欧美电影一区 | 久久精品国产v日韩v亚洲 | 国产一二三区在线观看 | 在线观看亚洲视频 | 亚洲精品一二三 | 日日夜夜狠狠干 | 国产欧美日本在线 | 青草综合 | 国产精品久久久久久久久久久久久久 | 日韩精品视频免费专区在线播放 | 中文字幕不卡在线观看 | 在线中文字幕第一页 |