|
本帖最后由 迷雾向前 于 2017-1-20 11:22 编辑 # R7 T& E" [! ] G& N; f 计划在机器上STF103VE 跑opus codec 进行编解码,中途停了,写一下做个记录。) X$ d# y( c, t 首先用CUBE 快速生成代码。 Clock 配置如下,我用的是内部时钟(应该没连接外部晶振): clock é ç½®
# N6 F4 W$ S7 W/ N& r* c* I Enable FreeRTOS ,heap 配置为 20K,enc 结构需要13k Ram。 FreeRTOS config
用于编解码的Task 的Stack 改为1024Word,即4K(小了会reset); ^9 L6 G) t) M, a Task Stack
, Q! R# O4 ^: x0 G0 g, E 系统heap 需要改大,* J2 e/ E" ]. F6 j1 L% D System Heap
将OPUS 代码copy 到工程里面,将如下文件加入到编译(没权限添加更多图片,只能用文字描述了) opus-1.1.3/silk/ana_filt_bank_1.c; K' A8 [ C% g5 [8 q% K opus-1.1.3/silk/bwexpander.c opus-1.1.3/silk/control_audio_bandwidth.c I$ P N- }; ^; w u& C7 }: G. } opus-1.1.3/silk/code_signs.c4 f- @$ a5 f* B opus-1.1.3/silk/CNG.c opus-1.1.3/silk/fixed/schur64_FIX.c* P |" o t; z: q; I% q opus-1.1.3/silk/control_codec.c opus-1.1.3/silk/debug.c- y0 L$ L. P1 b* P3 ] opus-1.1.3/silk/control_SNR.c opus-1.1.3/silk/fixed/residual_energy16_FIX.c/ v0 y# c% r7 Y8 j& g; ]$ s: h opus-1.1.3/silk/fixed/residual_energy_FIX.c& P5 u1 S( J) S; G2 t opus-1.1.3/silk/fixed/warped_autocorrelation_FIX.c z% v# v. M6 T: g9 _ opus-1.1.3/silk/biquad_alt.c opus-1.1.3/silk/bwexpander_32.c opus-1.1.3/silk/check_control_input.c opus-1.1.3/silk/A2NLSF.c opus-1.1.3/silk/fixed/schur_FIX.c opus-1.1.3/silk/fixed/solve_LS_FIX.c" a# }" @5 H' C. U opus-1.1.3/silk/fixed/vector_ops_FIX.c opus-1.1.3/silk/encode_pulses.c3 C) k- X/ w' ~! ]! O; } opus-1.1.3/silk/log2lin.c opus-1.1.3/silk/enc_API.c opus-1.1.3/silk/HP_variable_cutoff.c opus-1.1.3/silk/init_decoder.c opus-1.1.3/silk/init_encoder.c# L5 u# D8 I* O) X" M" b& t* A opus-1.1.3/silk/decode_indices.c" i- w$ f- R9 ^% {, _4 I opus-1.1.3/silk/inner_prod_aligned.c# @. q! h1 c6 U8 m$ S) h0 s opus-1.1.3/silk/decode_frame.c( \/ _* w8 X, | opus-1.1.3/silk/decode_pulses.c' L, u1 U7 {4 Q5 d" } opus-1.1.3/silk/gain_quant.c6 N5 o5 Z% G( f. f3 C- Z9 c4 f opus-1.1.3/silk/interpolate.c opus-1.1.3/silk/lin2log.c- h% N) V _5 X3 F i+ E+ x/ P opus-1.1.3/silk/decode_parameters.c, f4 E! T0 }, } d+ l- P opus-1.1.3/silk/dec_API.c" Z9 P" w( Z0 m) b opus-1.1.3/silk/decode_core.c& q; ]- L2 N- H, f opus-1.1.3/silk/decode_pitch.c opus-1.1.3/silk/decoder_set_fs.c r3 F2 P7 P4 D! B5 a+ _( ^/ \1 _ opus-1.1.3/silk/encode_indices.c* k9 o7 k$ \( O/ t4 ? opus-1.1.3/silk/quant_LTP_gains.c+ M ^ k2 R, \% J opus-1.1.3/silk/NSQ.c: r+ W+ Z* a' C2 D opus-1.1.3/silk/resampler.c opus-1.1.3/silk/NLSF_del_dec_quant.c opus-1.1.3/silk/NLSF2A.c% @ N6 q& q# o3 v) Y/ ]" G) [2 L opus-1.1.3/silk/NLSF_stabilize.c& ` E h9 a, D8 J( ? x opus-1.1.3/silk/NLSF_unpack.c opus-1.1.3/silk/NLSF_VQ.c opus-1.1.3/silk/LPC_inv_pred_gain.c8 e" L- b9 ?$ G; c opus-1.1.3/silk/NLSF_VQ_weights_laroia.c# n& A' s4 r" T# {- ` i opus-1.1.3/silk/pitch_est_tables.c, l, |' Z! ~6 j, x opus-1.1.3/silk/NSQ_del_dec.c opus-1.1.3/silk/PLC.c opus-1.1.3/silk/NLSF_decode.c6 a; X' t6 V3 B9 t opus-1.1.3/silk/NLSF_encode.c+ h1 |+ g5 L& M6 D* Z, ?7 m opus-1.1.3/silk/LP_variable_cutoff.c opus-1.1.3/silk/LPC_analysis_filter.c opus-1.1.3/silk/process_NLSFs.c opus-1.1.3/silk/stereo_find_predictor.c; G: v2 R: j D- `1 b/ j opus-1.1.3/silk/stereo_MS_to_LR.c opus-1.1.3/silk/resampler_private_AR2.c opus-1.1.3/silk/resampler_down2_3.c opus-1.1.3/silk/stereo_LR_to_MS.c V7 h+ e, |. ^9 r8 P opus-1.1.3/silk/stereo_encode_pred.c- l- J* h' C% m8 d: d) U8 | opus-1.1.3/silk/resampler_down2.c. B- w5 T- D9 x% j5 L opus-1.1.3/silk/sigm_Q15.c opus-1.1.3/silk/resampler_rom.c) q- C5 G* F3 Q; T" q opus-1.1.3/silk/sort.c9 |2 s7 Z( _* y/ w opus-1.1.3/silk/resampler_private_down_FIR.c opus-1.1.3/silk/resampler_private_up2_HQ.c- K1 S9 Q- P! K b opus-1.1.3/silk/stereo_decode_pred.c opus-1.1.3/silk/shell_coder.c1 n b6 C9 b& O+ o% f5 R opus-1.1.3/silk/resampler_private_IIR_FIR.c opus-1.1.3/src/repacketizer.c' J$ j; t1 O/ z$ P0 \ opus-1.1.3/silk/sum_sqr_shift.c, s6 Q: C+ @( k# a O- F opus-1.1.3/silk/table_LSF_cos.c opus-1.1.3/silk/tables_NLSF_CB_WB.c opus-1.1.3/silk/stereo_quant_pred.c opus-1.1.3/silk/VAD.c opus-1.1.3/silk/tables_gain.c opus-1.1.3/silk/tables_pulses_per_block.c #opus-1.1.3/stm32_m3/opus_main.c) E# R" y0 ~* `7 [" j" R opus-1.1.3/src/opus_encoder.c* y. h" v2 [0 i- M2 S2 @ opus-1.1.3/silk/tables_NLSF_CB_NB_MB.c opus-1.1.3/silk/tables_other.c opus-1.1.3/src/opus.c |& v$ b2 t; e& ^ i. c opus-1.1.3/silk/tables_pitch_lag.c% _7 F$ f2 x" G0 V2 v opus-1.1.3/src/opus_decoder.c opus-1.1.3/silk/VQ_WMat_EC.c8 u% o0 S6 V2 }0 a0 m# }- @6 } opus-1.1.3/silk/tables_LTP.c7 h" }: M, B6 e$ V0 O: H; e opus-1.1.3/celt/entdec.c opus-1.1.3/celt/entenc.c. T( y8 m: `. M O7 W opus-1.1.3/celt/cwrs.c: C$ Q' T, e5 a* `# P X# |, X0 j opus-1.1.3/celt/mathops.c f% n( W; r2 O5 h opus-1.1.3/celt/kiss_fft.c9 H2 r- S* c1 d opus-1.1.3/celt/celt_lpc.c opus-1.1.3/celt/mdct.c opus-1.1.3/celt/modes.c opus-1.1.3/celt/bands.c opus-1.1.3/celt/pitch.c M/ k/ M; c5 q opus-1.1.3/celt/celt_encoder.c opus-1.1.3/celt/laplace.c. ]# q4 Z, H2 j; U- w: u opus-1.1.3/celt/celt_decoder.c opus-1.1.3/celt/entcode.c opus-1.1.3/celt/celt.c* U$ i" N w. U L- s& ] opus-1.1.3/silk/fixed/noise_shape_analysis_FIX.c opus-1.1.3/silk/fixed/process_gains_FIX.c opus-1.1.3/silk/fixed/regularize_correlations_FIX.c opus-1.1.3/silk/fixed/autocorr_FIX.c opus-1.1.3/celt/quant_bands.c opus-1.1.3/silk/fixed/encode_frame_FIX.c& T& G% A# n4 F' j) ?: e0 ^, o9 s opus-1.1.3/silk/fixed/corrMatrix_FIX.c opus-1.1.3/silk/fixed/find_LTP_FIX.c opus-1.1.3/silk/fixed/pitch_analysis_core_FIX.c% ?* [$ T2 o) v opus-1.1.3/silk/fixed/prefilter_FIX.c opus-1.1.3/celt/rate.c opus-1.1.3/silk/fixed/find_pitch_lags_FIX.c& o$ j! I. F6 h: C4 q- l7 a, E opus-1.1.3/silk/fixed/burg_modified_FIX.c* M4 [. Y5 Q/ v opus-1.1.3/silk/fixed/LTP_analysis_filter_FIX.c opus-1.1.3/celt/vq.c+ \, Y. o" ]+ s$ |* {7 g9 P8 g2 X opus-1.1.3/silk/fixed/find_LPC_FIX.c opus-1.1.3/silk/fixed/find_pred_coefs_FIX.c, R$ n: Q# x0 { opus-1.1.3/silk/fixed/apply_sine_window_FIX.c opus-1.1.3/silk/fixed/k2a_FIX.c% O3 X4 o0 H3 l8 D+ {& a6 H+ | opus-1.1.3/silk/fixed/LTP_scale_ctrl_FIX.c& H& T' ^6 [. O: t- Q" \ opus-1.1.3/silk/fixed/k2a_Q16_FIX.c & V6 n2 |1 h$ L9 b5 O: Y6 M! G 我为opus-1.1.3建立了单独的group,并将这个group 的 【Override inherited settings 】勾上6 U, b6 s8 i* q$ S/ o6 Y8 ^' Y opus config
在【Proprocessor】里增加如下include 目录 $PROJ_DIR$/../opus-1.1.3/include $PROJ_DIR$/../opus-1.1.3/celt $PROJ_DIR$/../opus-1.1.3/silk $PROJ_DIR$/../opus-1.1.3/silk/fixed2 Y2 s! \$ A' x $PROJ_DIR$/../opus-1.1.3/stm32_m3 增加:HAVE_CONFIG_H 到【Defined symbols】
将【Language 1 】中的【Allow VLA】勾上,目的是#define VAR_ARRAYS 1 后能便宜通过。3 M ?- ?. b8 I! h# ` ! Z' q) D/ q* ~. E" y# l- t copy opus-1.1.3/win32 到 opus-1.1.3/stm32_m3,建立config.h 和 version.h config.h: #ifndef CONFIG_H #define CONFIG_H9 ^( \: ]6 m4 X. y; g //#define USE_ALLOCA 13 D5 j9 B) j/ m #define VAR_ARRAYS 13 |: k3 _! b2 K' l /* Comment out the next line for floating-point code */5 |% m8 l: L& F0 v1 | /*#define FIXED_POINT 1 */ s" C5 j6 t/ K7 n$ y- Q #define OPUS_BUILD 16 j4 a" a9 G" A1 l! N #define DISABLE_FLOAT_API 1 #define FIXED_POINT 1 #define REMOVE_FOR_MALLOC //以上部分内容为增加部分,其他的与win32下同名文件相同- i) i# @' P) z #endif /* CONFIG_H */ 8 x- L, I& `% i* [ version.h( \/ R/ @/ L, p- i #ifndef __VERSION_H__ #define __VERSION_H__* M$ ?" T) y0 e0 s #define PACKAGE_VERSION "1.1.3" #endif /*__VERSION_H__*/- g0 l ]7 w7 T1 C: q encode 和decode 代码: & b% V* N5 e. L0 d2 \+ F# Z4 F4 S pusDecoder *dec; static int offset = 0; int size = 0;7 y; S# s' l+ S. o4 v' f9 I- p* L const unsigned char *packet; int i = 0;4 y% O5 _0 v) L4 Z7 y* V4 U int frame_size = 0; int max_size = 0; char buffer[36];( Q2 H; |- r" Y4 ^& U8 e , F! W* B1 a& y$ W/ Q uint32_t start = osKernelSysTick();' T' i8 c+ O6 v X; j 8 ?. J- s/ h/ z* n0 n( c8 p8 m OpusEncoder *enc = NULL; static int len = 10; size = opus_encoder_get_size(channels); enc = pvPortMalloc(size); error = opus_encoder_init(enc, Fs, channels, OPUS_APPLICATION_RESTRICTED_LOWDELAY); opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));* S# m& y h9 M8 i4 u' @! B //opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));& ^6 I' M# X/ Z! U2 C opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));+ G X% ~, x. `# v8 f + N; r6 b. f7 B+ _# Z5 C$ c+ r len = opus_encode(enc, audio_frame + offset, Fs/50/*20ms*/, opus_buffer, sizeof(opus_buffer)); offset += Fs/50; if(offset >= sizeof(audio_frame)/sizeof(uint16_t))4 z* Q& d2 X3 ?7 F8 O. i7 ?7 h offset = 0;. q. a" ~: R" j3 i1 K vPortFree(enc);, W8 m6 E; ^( I; { OpusDecoder *st = (OpusDecoder *)pvPortMalloc(opus_decoder_get_size(channels)); error = opus_decoder_init(st, Fs, channels); 4 x1 U f0 m. ]) [ n. b% H frame_size = opus_decode(st, opus_buffer, len, pcm, PCM_BUFFER_SIZE, 0); 对了,我改了这两个宏,5 E, [5 K5 r3 U7 u! [ G #define MAX_FS_KHZ 8 /*16 --> 8 modify for memory*/ #define MAX_API_FS_KHZ 8 /*48 --> 8 modify for memory/9 O ^! y% ]* N: V$ ^ 原因是,如果不修改opus_encoder_get_size(1); 返回的是27k,改完后还得13k,实在是没有那么多ram3 t6 J+ N& n8 _ size = opus_encoder_get_size(1); enc = pvPortMalloc(size);! s1 W- u6 b. ^* n: t8 V 总结,64k ram 感觉刚刚够,还没有增加其他的功能,解压缩20ms 数据用了6-7ms,编码我忘记了,记得编解码用了33ms,有点高。5 l ]' x$ W/ \' j& { 声音可以用DAC(PA4)播放出来,需要外加功放,不加功放声音很不好。经过opus 压缩解压后声音损失较大,音乐还能听出来,但很多噪声。3 R- k$ L3 t* }9 R8 W. ~ |
| 谢谢分享 |
| 楼主你好,我想问一下STM3VE 用opus编解码效果如何? |
| 楼主的项目能放出来吗 感觉opus的代码很多,你上面介绍的是很多文件都不需要的 |
| 谢谢分享! |
微信公众号
手机版