RT-Thread Audio - 1. 音频框架的分析

发表在 Devices6 天前 [复制链接] 4 114

本帖最后由 liu2guang 于 2019-11-9 13:48 编辑
; d: O2 t2 f% F, [, ~& p5 y, I" w3 T' P2 V) ], \3 V
Github 上 RT-Thread 源码最新更新了关于 Audio 驱动相关的部分,让上层和底层都开发和编程简单了,不过对于大部分的开发者来说还不太熟悉这套框架的,那么笔者就这次编写音频驱动给大家分析下代码框架。# T3 [+ P. a4 F) O& F. R% H6 x
- h' n# d$ ~) x# ]8 k1 B
这里会先贴一张框架图,整个帖子都是笔者在编写开发过程中写的,可能有格式和错误,最终全部更新完毕后会整理整个系列的帖子。% K( c  d% c% U4 b* C: _! N
: \% {; C( T4 ~* v, D9 U  U
1. RT-Thread 音频架构图
  }( O+ I* c( Z+ w; b  Q: t/ y/ N3 a) ]

RT-Thread 音频架构图

RT-Thread 音频架构图

% k6 N) X. M, I' z0 @3 W' U+ A4 K4 s, z5 [3 Q! G
2. RT-Thread 音频框架的调用逻辑关系图(建议右键大图)  g; b% }# }- O8 j/ [+ a4 o
! s( H) \+ `4 _$ f+ D- ^( T3 N
! A+ j# W- l- H" Z$ ~  ]1 z2 K4 _0 x

4 _0 p) U; B- k  _% f3. RT-Thread 音频应用代码模板(以wavplay为例)
4 d5 F* ], v  p& A7 _7 p6 R0 O+ w" u: u  o( g
https://github.com/RT-Thread-packages/wavplayer
3 u1 J+ {; I& f( u# I9 L  X, h
6 `# \# R3 S7 o1 ^7 k4. RT-Thread 音频驱动代码模板- v3 z! u# y$ G; [) N; f: X
5 ~) V; ]" j! I' Y
#include "drv_sound.h"
7 j1 @* u- x3 L( d#include "drv_tina.h" 1 ]5 P4 R: ~1 j2 }
#include "drivers/audio.h"
6 T+ Z3 a6 A$ ]8 f# i( @& y+ I, p8 W
+ A" E4 D7 L2 n: U7 `#define DBG_TAG "drv_sound"5 ]5 a8 ^7 }, J7 ], Y
#define DBG_LVL DBG_LOG
+ {( ?. K( R# }( e$ Z" {+ c#define DBG_COLOR1 W. A/ J' u/ w4 w- Y8 D8 M
#include <rtdbg.h>
7 t# }2 J& X2 G, I* W: P) i; Q6 ?' Q$ p% M5 [. K- H2 t
#define TX_DMA_FIFO_SIZE (2048)+ i6 M3 m5 [+ Y- w# e! L
2 W. b: I4 l7 A: U; N- g$ |9 V/ G
struct temp_sound8 _+ ?2 b7 E0 h/ _1 A8 P9 Y
{! e) ]# v6 J+ V2 @3 f' i  E) h4 {2 v9 K
    struct rt_audio_device device; " i, v, V! d7 K3 y
    struct rt_audio_configure replay_config;0 a" {2 H! z# E/ ]# b& S& n
    int volume;! T  X  P3 q' e% H, ]3 n
    rt_uint8_t *tx_fifo;( l" F/ R" z) H+ K/ }
};" x" s. |4 \0 O. J: Y% K

8 Y) S! H2 r5 Z7 J- X7 }4 V4 l4 V4 \static rt_err_t getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)9 D! \) L+ V+ r, r1 ]
{
/ c3 E9 W" G* }# q9 M1 \' t    struct temp_sound *sound = RT_NULL;
3 X9 K5 t* l! a) F* U9 o
5 ^$ K" D! @9 S  H: ~( c    RT_ASSERT(audio != RT_NULL);
- x& o7 `* k% _    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
6 c: }. J% S4 b) o! _& q. j7 S* [' Q" W3 D& S* v: V
    return RT_EOK;
6 x' h, l8 Y5 ^# e}
) C* {" p$ B% a, u6 b2 d7 w8 k8 t9 G* C- R7 o& f% k
static rt_err_t configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)1 Q; N* _/ e: B4 z% L/ O! Y' {
{1 v% w/ {; K' `
    struct temp_sound *sound = RT_NULL;
( W* w, F: o8 S0 D7 M! K- p
7 y" i5 H5 t& W" v; q    RT_ASSERT(audio != RT_NULL);
& v+ s: X' a/ x' e- d    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
! B$ Y, i+ h; P2 `) w( a, ~
8 A: m% q- o0 K# }  U6 H, h    return RT_EOK; 8 }! o) p; ]9 Z  e& Z1 Z
}) y$ W! R3 Q/ x9 P% `
* d; H% X# m& `1 Y$ S8 v
static rt_err_t init(struct rt_audio_device *audio)  P# C- @6 ]2 h2 a* c, X
{! y% s* M( j2 Q2 {8 Q) o
    struct temp_sound *sound = RT_NULL;
+ p: a' T7 j: z5 o" A8 E2 h/ ^5 Q# d! U- s1 r, b2 A4 ]3 U! q
    RT_ASSERT(audio != RT_NULL);
* ^( n, j& Y6 a# C6 ~    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
8 P! y5 w; x" t' Q: b# R& \. S1 Y& J: ?0 A. s6 f* L
    return RT_EOK;
  ?3 _) T! u! c$ H/ S$ F. Y0 E}: e' p; Q. c, _2 ?
$ o4 c6 C& i' ]  ?* _
static rt_err_t start(struct rt_audio_device *audio, int stream)
  M( |5 R( y: k6 W{
" o5 ?- `$ J8 K. i' n( ?* k  n    struct temp_sound *sound = RT_NULL;( T. e1 \# p" F6 {( {

7 p0 K4 \; I- I8 K: Z* l1 E    RT_ASSERT(audio != RT_NULL); : R6 B! D; Z+ X# ^- _
    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
. U5 m' k( ?- C( [
7 g/ @& \9 U( S6 J2 e0 ^    return RT_EOK;
4 i9 u7 p6 m$ p}: d. Z+ L, K7 v5 D; \, m# T
. Y; m, K0 Q# K4 I* B
static rt_err_t stop(struct rt_audio_device *audio, int stream)
0 e, R" r& L5 e7 r9 \' y5 Q{: j7 x' W" Z/ O1 r  }$ r- i+ {
    struct temp_sound *sound = RT_NULL;
* Q1 Q; D) u3 e+ }
0 ]' y, s0 l8 C/ u5 C    RT_ASSERT(audio != RT_NULL); + h* b& y, W7 k+ b0 Q
    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;  / P( N& l; t* h* M* C- ~) W
0 a$ |7 j5 L4 r+ D5 l
    return RT_EOK;
6 |+ M, u3 U3 t3 o}4 g7 e6 J* c* Q- _, M

3 U7 y. ]) O% X8 j6 O) wrt_size_t transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)& Y" c; B) A" g4 l* ~
{# T- A: J, l8 [7 S5 ]. J, L; H, a
    struct temp_sound *sound = RT_NULL;8 y1 p' I1 C7 f) `# e/ G& D

; F3 s. D+ J' Z) h. E    RT_ASSERT(audio != RT_NULL);
2 g& u- K' ~( E    sound = (struct temp_sound *)audio->parent.user_data; (void)sound; 6 L8 s( |& @. {+ g% c

$ ]4 ~, y& g. @0 q7 K7 Y& m. g    return size; 5 h- V7 j4 |0 [. o& C2 t! v/ m) F
}
/ {. @& b4 O) X/ z) @/ y4 T8 L" x/ o; p! B
static void buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
: V! ?: |' N4 E$ z9 Q{
/ H1 ^/ M* i9 Z/ o1 A    struct temp_sound *sound = RT_NULL;! C0 S; h$ r+ Q/ _, S* m

8 o  @, W, U* m    RT_ASSERT(audio != RT_NULL);
& B, q! k" O' e6 L4 O8 e9 o4 a    sound = (struct temp_sound *)audio->parent.user_data;- H' L0 B. C% X9 ?6 C; N+ c

& g1 }* a5 [. c! F2 q1 Z; ^    /**3 A) K$ n* c( f: N
     *               TX_FIFO
2 o& {: S8 g$ ^/ |' m( B     * +----------------+----------------+
0 V! Q- a7 \4 z     * |     block1     |     block2     |
) \' d: f. e" Z! R     * +----------------+----------------+' ?, o* ~( Y" s0 M: c
     *  \  block_size  /9 C+ h+ s& \/ T/ h  E" n& g$ H
     */
$ }* Y$ z! T0 B1 @$ v    info->buffer      = sound->tx_fifo;" Q# |+ [; E3 ?
    info->total_size  = TX_DMA_FIFO_SIZE;: ^% V# ^. Q6 u( b/ _) I) A
    info->block_size  = TX_DMA_FIFO_SIZE / 2;& h2 ~/ l) c" E" V. ^( L
    info->block_count = 2;
9 x# ~: e  n+ ~3 I, J}
  g/ b6 m* _+ X3 M- V- c3 F" R1 a& V9 Z/ v
static struct rt_audio_ops ops =
+ [' a8 ]  [) @1 ^  d4 h) t7 ]{: x9 X0 E6 w# c) C$ ^, D) U  X; @  d3 k
    .getcaps     = getcaps,
8 Z' c  A# j) I: n7 e    .configure   = configure,, j9 ~5 I. [' x$ `5 d& H$ w
    .init        = init,
. B* u4 |$ j3 i; Q5 {0 E8 N: n' U    .start       = start,
9 z& D! y" j: h# v; B* M& ~0 q    .stop        = stop,) E6 a. ~, }' n* ^
    .transmit    = transmit, 6 R3 G/ V. x0 r# w; o2 `" m; P
    .buffer_info = buffer_info,0 W% n9 h6 R. q( P1 i# ]
};
7 {3 v8 ^. L+ g8 t( O8 {2 N# r; B: I, T3 j& k6 W" b
static int rt_hw_sound_init(void)" b+ g+ B. v/ \) [0 U
{4 h* [% r. e7 @/ W' }: i
    rt_uint8_t *tx_fifo = RT_NULL; & o3 m7 ]8 n2 g4 W3 A/ N
    static struct temp_sound sound = {0};
  w" ?# J' G) b# Q7 p' h' b1 c. |* y! I# w" u1 L8 p
    /* 分配 DMA 搬运 buffer */ ! |& ]6 K6 I! n
    tx_fifo = rt_calloc(1, TX_DMA_FIFO_SIZE); 9 Q* U7 L% ~$ C( D3 U' ~" D
    if(tx_fifo == RT_NULL)
. E" ?" T; B" v2 z    {
' l' p. c5 y* F% L; C        return -RT_ENOMEM;# K* C3 X; @3 X! q, T9 _' t2 Y
    }8 n% f5 b% |. @+ D- O* R/ ]' t6 q

5 G$ \' D6 K, g% k* y    sound.tx_fifo = tx_fifo;
% O4 n* _+ q+ O* M: Y9 E4 U6 e9 q+ z
    /* 注册声卡放音驱动 */
" o7 J  b! s$ E, q    sound.device.ops = &ops;
, K' {* g* \, D5 l    rt_audio_register(&sound.device, "sound0", RT_DEVICE_FLAG_WRONLY, &sound);, \$ E; G  e* L
% a: V3 n: [) i/ S( I
    return RT_EOK;
) t5 B6 B- v2 l  P5 T4 _6 e}
  _, E# f2 }3 w3 T  b% ?2 yINIT_DEVICE_EXPORT(rt_hw_sound_init);

6 O. c5 @; L4 x* l9 j7 I
& }- q9 @1 P5 \* ?* D: N' q+ ~9 Z; i, q+ A
5.  代码分析4 d" p0 i* U! T. j, k7 J

) q% V) D3 D2 y: }2 ?1 G. `( Q待后续补充。。。
" o/ e/ p- L' e5 N: e
  L9 K( L4 q0 X2 m/ W sound_temp.7z (1.09 KB, 下载次数: 7)
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 6 天前 | 显示全部楼层
前排围观 9 层音频驱动框架。。。
使用道具 举报 回复
发表于 6 天前 | 显示全部楼层
前排围观 9 层音频驱动框架。。。
使用道具 举报 回复
发表于 5 天前 | 显示全部楼层
第二张逻辑关系图显示不出来,一直在打转
使用道具 举报 回复
发表于 4 天前 | 显示全部楼层
charlown.cai 发表于 2019-11-10 09:55
8 M0 P) `; ]$ `2 j第二张逻辑关系图显示不出来,一直在打转
% ^) \! ?; W( N5 |
直接点击这个图片链接试试,图片比较大9 H; o) ^9 Z* y0 D5 t

+ m1 ^+ [; d- M5 T$ [https://note.youdao.com/yws/publ ... stamp=1573277165267
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表