搜索
查看: 54|回复: 0

[网站] Python实现将wav转amr,并转换成hex数组

[复制链接]
发表于 2023-5-8 21:56:35 | 显示全部楼层 |阅读模式
这篇文章主要介绍了Python实现将wav转amr,并转换成hex数组方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教% z, U  b$ H! ?

. v5 S) E. }) l. }
6 Z* K  o* K$ j& s' k
+
目录! B  H2 z' D4 _7 R
! Y; K# D. G+ r1 d7 e9 {
将wav转amr,并转换成hex数组

将wav文件快速转为amr,同时将arm文件转为16进制数组,保存在对应.h文件,供嵌入式设备使用(无文件系统产品(⊙o⊙)哦)


; s6 e/ B9 \9 _9 z& K直接上代码

generate_audio_file.py

  1. from __future__ import print_function- H! p& A; z& i) `6 C# [- n  U7 ^" U
  2. from builtins import range3 }! l9 y7 ?( E; y4 Q
  3. import os: p1 e; a7 x0 a* I
  4. import wave. T# w$ p8 }' e$ s
  5. import struct
    3 y& f$ e: G: X
  6. import time* Z9 n7 B) k4 s+ k/ s0 ]1 O
  7. import re
    $ G; R, H. d- y( d' i) T% l5 F
  8. import subprocess+ h) {$ ^! W7 T: L& }5 \
  9. import binascii
    1 i! N" A) a- _) h: }  K8 u$ I
  10. # eric 2020年7月10日; Y$ I  @2 F$ T$ q: _2 @
  11. # wav文件转PCM数组
    ) y5 N3 _; r: Q/ I2 o3 e
  12. def get_wave_array_str(filename, target_bits):
    " K/ o7 s% o9 W* a
  13.     wave_read = wave.open(filename, "r")
    " m6 M; Z9 g: C. x
  14.     array_str = "// start\n\t"
      z$ x/ ]) `; L+ W' k/ f+ h  n
  15.     nchannels, sampwidth, framerate, nframes, comptype, compname = wave_read.getparams()
    ' p9 w9 O& L7 ]1 d% S3 B
  16.     sampwidth *= 84 _" l+ M) O3 d) [
  17.     for i in range(wave_read.getnframes()):- _4 i) s5 n( k. Q$ }
  18.         val, = struct.unpack("<H", wave_read.readframes(1))
    7 u" G3 J8 w' \9 m
  19.         scale_val = (1 << target_bits) - 1
    8 d. t* [1 D8 M  {4 _6 w
  20.         cur_lim   = (1 << sampwidth) - 1
    8 i/ }3 a( F; C: T) N9 R- t
  21.         # scale current data to 8-bit data, @8 o: U+ k! j3 H7 |, x8 v9 {
  22.         val       = val * scale_val / cur_lim
    ( F" l0 n0 c  G) Y. E& G
  23.         val       = int(val + ((scale_val + 1) // 2)) & scale_val
    , o! y. j# M' x8 M
  24.         array_str += "0x%02x, " % (val)
    + t5 ^2 L' r4 s. X0 Z
  25.         if (i + 1) % 16 == 0:
    , x: O: x7 ?5 f/ N: j6 H8 r: A
  26.             array_str += "\n\t"
    ) C1 b+ I4 N! p" R/ \6 J* f/ v. G1 A
  27.     return array_str1 ^& [5 ~: N) p8 t# R
  28. # PCM 数组合并
    7 `* a5 p$ j& x/ }
  29. def gen_wave_table(wav_file_list, target_file_name, scale_bits=8):# \' N5 ^  R, K& Y5 M
  30.     with open(target_file_name, "w") as audio_table:
    * }" b4 U1 e, f& K
  31.         print('#include <stdio.h>', file=audio_table)
    0 r* n, S6 p" A5 e
  32.         print("// time:{}".format(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))), file=audio_table)
    ; T; y  E+ ~+ X/ C$ e# |
  33.         print('const unsigned char audio_table[] = {', file=audio_table)) f2 e2 N4 J6 R  w: h. M
  34.         for wav in wav_file_list:. E8 N) S: W- E& x" X! S0 H
  35.             print("processing: {}".format(wav))# G/ z( ?3 `# q# l0 r
  36.             print('//name:{}\n'.format(wav), file=audio_table)' c6 i, L2 `7 r, K( T' O
  37.             print(get_wave_array_str(filename=wav, target_bits=scale_bits), file=audio_table)
    2 y" f- j" O% I& q
  38.         print('};\n', file=audio_table); P3 S- k* x& @# z/ ?& P9 W
  39.     print("Done...")
    ! V4 |& v5 o' V5 n
  40. # 获取wav文件信息, w1 S8 k, v  [$ o
  41. def get_wave_info(filename):
    * U; `4 d0 X! u/ s2 b& |
  42.     wave_read = wave.open(filename, "r")
    ( ^+ V/ t  b  V% S0 @
  43.     nchannels, sampwidth, framerate, nframes, comptype, compname = wave_read.getparams()
    ) O3 z" j) s: e( M" K) `7 \* _
  44.     print('nchannels:{}'.format(nchannels))% U" i& U8 d; W+ o/ q' V& P. Y- @* ]
  45.     print('sampwidth:{}'.format(sampwidth))) O) Z" o2 g, H, F( {7 s( |0 z
  46.     print('framerate:{}Hz'.format(framerate))" C& F- u9 L8 L) ]
  47.     print('nframes:{}'.format(nframes))( _" S* j9 j8 O
  48.     print('comptype:{}'.format(comptype))# F- I7 K2 N. E( D" l& `6 I3 p# {
  49.     print('compname:{}'.format(compname))2 Q+ T) X- V* ~' G$ b! L5 f
  50.     return framerate7 H7 a  z% g  S9 Y- w: U2 I2 J
  51. # 二进制文件转数组. ]8 w! l: ?) b$ Z$ I- y
  52. def file2array(filename,h_filename=None):8 E6 T1 u" C6 G& v5 v4 E8 e
  53.     path, name = os.path.split(filename)
    2 ~4 J" T) Z1 V
  54.     if h_filename is None:/ J1 \! p0 e" o" t% g3 ]4 p2 J; L
  55.         h_filename = os.path.join(path, name.split('.')[0] +'.h'). }# j5 v7 ?5 f8 H
  56.     array_str = '\n//total len:{} bytes\n'.format(os.path.getsize(filename))2 C! L$ B' @! E3 \
  57.     array_str += 'const unsigned char '+name.split('.')[0]+'[]={\n\t'
    $ ?9 B3 c  L) {% P
  58.     # print(array_str)6 v8 p: a" A( o! [0 R" L! G' `1 H
  59.     h_file = open(h_filename, "w")+ l3 d/ x; N$ P& E' Q. y/ U1 _
  60.     file = open(filename, 'rb')
    " ?  W' H; z2 @) N
  61.     try:5 R8 w" p: C( J# P. Y
  62.         while True:7 p. L' X* i$ p  j
  63.             chunk = file.read(16*32)  h4 q9 h' V8 G1 E2 c) w$ J2 H
  64.             if not chunk:
    7 e) U% K+ a1 Y# G, @# }8 {" L' ^4 E
  65.                 break& _6 U4 [! ?4 A5 f) }* A# I
  66.             for i in range(len(chunk)):# T7 J/ k& q# F( P, Z! t
  67.                 array_str += "0x%02x, " % (chunk[i])( I/ A" _1 K7 L% @8 N# n2 Z4 v
  68.                 if (i + 1) % 16 == 0:
    . b* O: Z3 r; D3 L! B+ @
  69.                     array_str += "\n\t"& c+ A$ \# f; j, n4 C1 m' l+ I0 X3 t
  70.             # print('get:{}'.format(binascii.b2a_hex(chunk)))
    4 t* f4 u% z% h  W+ z( E$ i- v2 {
  71.     except:
    ' W# Q' h/ b0 L
  72.         print('read ERR')7 V! r5 i6 X" \- K1 Z. m  [! P
  73.     finally:6 e7 H1 I$ V# K  q% n  h2 f$ z6 V
  74.         print('read file done!')
    / w5 r/ |" X7 r1 t' ]! p5 q
  75.         array_str += '\n};\r\n'
    $ b2 _, m2 p4 S  ]
  76.         # print('array='+array_str)5 z, [  K: }# O# X6 p* e6 U3 h4 {
  77.         print(array_str, file=h_file)1 p+ l3 ~4 A& F1 S  u( D! C5 p# L1 d
  78.     h_file.close()7 j1 T8 X# Z. \
  79.     file.close()
    & C' \1 {' z2 D: @( L6 n" f* _- B& k
  80.     return 0
    * R; O4 j) i% G2 t
  81. # ffmpeg路径" e7 ]" Z: s& W
  82. ffpeg_path = 'D:/Program Files (x86)/QveAudio/'
    6 Q5 }8 s1 q  J9 [$ |" P' c
  83. # amr文件转MP3, n3 A& p7 a/ Q! W( k
  84. def amr2mp3(amr_path,mp3_path=None):
    9 K/ M& x: [* z" B
  85.     path, name = os.path.split(amr_path)2 s0 H6 H+ \( {
  86.     if name.split('.')[-1]!='amr':- }1 P/ K! J1 j
  87.         print('not a amr file')( _9 X5 U2 [* w. k
  88.         return 0/ a. P4 z" t' `" E
  89.     if mp3_path is None or mp3_path.split('.')[-1]!='mp3':5 N" z$ ^. ^; v
  90.         mp3_path = os.path.join(path, name.split('.')[0] +'.mp3')5 I% I) p6 F+ o) `/ O/ @- P7 L
  91.     error = subprocess.call(['ffmpeg/bin/ffmpeg','-i',amr_path,mp3_path])9 q! z2 ^& C" U
  92.     print('ERR:'+error)
    + \6 O) c6 r/ h1 F! o
  93.     if error:
    ) P4 ^; D# P" e9 v
  94.         return 0, {+ z: T) ]. Y4 \+ m$ U
  95.     print ('success')
    : a: W- p0 m* P% C0 s
  96.     return mp3_path
    3 ]3 G; n% q+ C1 O/ \/ n
  97. # wav文件转amr,wav必须为8000Hz
    / f, ?7 a& r: l+ J  e7 ~0 W
  98. def wave2amr(wave_path,amr_path=None):
    $ x$ Z. c. z0 f, x* `) F) A
  99.     path, name = os.path.split(wave_path)
    & [( ?7 G& Z% F
  100.     if name.split('.')[-1]!='wav':
    : J. [, Q" C, j% j# {5 M7 r# E
  101.         print ('not a wave file')
    7 r! L% L! C5 o( Z; ^5 l
  102.         return 0) |" t% _5 q& Q/ S  A
  103.     if amr_path is None or amr_path.split('.')[-1]!='amr':8 O4 k/ n" T! J9 f$ F% _+ S
  104.         amr_path = os.path.join(path, name.split('.')[0] +'.amr')
    1 x% T7 `9 Y9 U9 a7 a( r1 j2 `
  105.     error = subprocess.call([ffpeg_path+'ffmpeg','-i',wave_path,'-y',amr_path])1 i$ b! W9 Y0 g5 y/ D9 s# W- j6 j
  106.     print('ERR:{}'.format(error))
    " h3 W$ f- C! R; n1 N" j. Y
  107.     if error:3 [: F, G/ A; g* f9 o
  108.         return 0
    6 y& i0 V" f3 N! ^  B
  109.     print ('amr success'), S. z2 ]# E" n, X% G
  110.     return amr_path' w1 Y2 \' X5 u" E* N, p
  111. # wav 格式化为8000Hz9 j# r: W) `9 B2 ^; C/ I. \3 r# O
  112. def wave2Hz8000(wave_path,out_path=None):& R% |0 V5 L2 H$ \9 E
  113.     path, name = os.path.split(wave_path)% }& I" o9 k2 u/ t0 @
  114.     if name.split('.')[-1]!='wav':
    / n+ U, S* }4 \' q) N7 o8 j
  115.         print ('not a wave file')6 y$ O8 f2 q* ?  k$ A! B6 v
  116.         return 0
    & e5 n4 k' b; _% ^' {( Q3 Q, Q9 ?9 G
  117.     if out_path is None or wave_path.split('.')[-1]!='wav':5 Q: C! j* e0 o1 y0 j6 X
  118.         out_path = os.path.join(path, name.split('.')[0] +'_8k.wav'); F" e) c2 I: [4 H6 A0 U4 K. N) d4 s
  119.     # error = subprocess.call([ffpeg_path+'ffmpeg','-i',wave_path,'-ar','8000','-y',out_path])* b- S& s: G; m& o* ?) ]
  120.     error = subprocess.call(ffpeg_path+'ffmpeg'+' -i '+wave_path+' -ar 8000 -y '+out_path)
    6 s$ V1 D6 |  o) ?+ ^; G1 p
  121.     print('ERR:{}'.format(error)). O, A9 Q  `" O! K4 b
  122.     if error:
    . W: F% @; z/ @
  123.         return 07 j: O7 O8 c  h# \% V+ m
  124.     print ('wav success')
    4 w1 U: L, f9 f2 c
  125.     return out_path. l* d" J: \) m5 J% n. l$ e, ?
  126. # 将目录下所有wav文件转为amr,并转为对应的数组文件
    7 o! S, R# Z/ O$ j2 H$ Y/ i
  127. if __name__ == '__main__':2 s5 p) d0 L* i2 M( j; U5 r
  128.     print("Generating audio array...")% J* Q" S, ~  I2 |( M/ t9 V4 [# L
  129.     # wav_list = []7 ~% n% ^" T+ V" q  o& M0 i
  130.     for filename in os.listdir("./"):* s% e+ |) p7 w, ~: c1 c
  131.         # print(os.getcwd())
    + q' ~. y1 k4 e# w' Q, F3 F4 E8 Y
  132.         if filename.endswith(".wav"):; Q% o- [1 W( L
  133.             print('src_name:',filename)% ~. {4 p1 }  f/ p6 y' x  e
  134.             framerate = get_wave_info(filename)
    . I& a1 {* u( }
  135.             if framerate != 8000:, X, R( N1 W2 E% X0 N; N- i
  136.                 print('to 8000Hz')" u, l! [4 U8 i5 z
  137.                 filename = wave2Hz8000(filename); D5 C5 r  F5 H9 f* d
  138.             amr_file = wave2amr(filename)$ x2 ], v. n* o$ G) l! l0 Z
  139.             if amr_file!=0:  M4 A4 d6 p8 x4 X* n/ r
  140.                 file2array(amr_file)) X# D+ z" f2 H& ^
  141.             # dst_name = "0_"+filename
    + v" E# |8 p9 F+ Q" _, ^# d) u
  142.             # print('dst_name:',filename)
    3 w: D% x  S1 o
  143.             # os.rename(filename, dst_name)
    ! }1 a# o* b: e; ^  x7 ^! Y$ @
  144.             # wav_list.append(filename)7 G2 F9 E5 p# @2 `
  145.     # gen_wave_table(wav_file_list=wav_list, target_file_name="audio_example_file.h")
复制代码

% n. `( X% T) K5 M% S; P  L' j/ U

以上代码实现的功能:

  • 将当前目录下的所有wav文件,转为8kHz的wav
  • 将对应的8kHz wav,转为amr
  • 将对应的amr,转为hex数组,并保存在.h文件中. \7 n4 w# D4 a$ |* E' n

注意:音频的转换用的ffmpeg,使用前需确认对应的路径

  1. ffpeg_path = 'D:/Program Files (x86)/QveAudio/'
复制代码
3 X  D2 t7 o, @8 J* e
/ Z7 w; o* f1 v7 X3 m3 J  m

. `7 A. U( J, g& N

& K0 v# a+ g3 J2 W7 G; d; U# x# I, n& F1 {- V
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

热议作品
精华帖子排行
精彩推荐

虾皮社区,成立十年了!

站长自己也搞不懂想做个什么,反正就是一直在努力的做!

Copyright © 2007-2019 xp6.org Powered by Discuz

QQ|小黑屋|手机版|Archiver|虾皮社区 ( 鲁ICP备13006813号-1 ) 鲁公网安备 37021102000261号 |网站地图
返回顶部 返回列表