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

发表在 Devices2019-11-9 13:42 [复制链接] 7 430

本帖最后由 liu2guang 于 2019-11-9 13:48 编辑 . u* X7 O  }( j

! u! e- b9 c# W2 t( t0 l; [; N( qGithub 上 RT-Thread 源码最新更新了关于 Audio 驱动相关的部分,让上层和底层都开发和编程简单了,不过对于大部分的开发者来说还不太熟悉这套框架的,那么笔者就这次编写音频驱动给大家分析下代码框架。" V8 k1 I1 N. X9 q

7 `1 Q7 t% l4 L这里会先贴一张框架图,整个帖子都是笔者在编写开发过程中写的,可能有格式和错误,最终全部更新完毕后会整理整个系列的帖子。
' Y- w6 L+ h0 F, @/ @- ?0 h) b) ?/ i# h% x1 }9 D4 W7 p9 K, G* A
1. RT-Thread 音频架构图
8 R# ^/ N8 M- `% Z9 D, R$ c' m  Z9 a( i

RT-Thread 音频架构图

RT-Thread 音频架构图
. W: J, `, m- s8 c! b2 d! \2 \
4 J: ]' ]) [0 c; n  f: b$ E, D
2. RT-Thread 音频框架的调用逻辑关系图(建议右键大图)
! r: L; H' ^; a. n, L" _1 N- j
/ x# C6 w# Z" M, D/ l
" }. p. p* u" r* @7 H1 v/ @* M) K, E' [, U5 u* j( X  r" k: h& s* `
3. RT-Thread 音频应用代码模板(以wavplay为例)
9 M, C  {, }* T$ r) b4 ~, x4 _1 X6 X" u9 t4 U5 n# l
https://github.com/RT-Thread-packages/wavplayer( G( Q1 A8 z. _! l. Q! @4 j
0 |6 J1 E% Z# A6 `
4. RT-Thread 音频驱动代码模板
1 k+ ], J, y5 k9 c: b
! \! r( B& h1 a( S; F. B' n4 z' g
#include "drv_sound.h"
! f( T4 W; @* [1 ?: b: n: z1 n#include "drv_tina.h"   a" j& G8 D4 G7 z7 P/ I, V
#include "drivers/audio.h"
, N: p$ ~' n& |! t: m0 g2 [& G+ `7 o+ q9 F
#define DBG_TAG "drv_sound": Z$ O5 N7 m/ J2 H5 O8 b- N! N
#define DBG_LVL DBG_LOG
# r- a# U* T( B8 i, a# E" z' W9 ^0 X#define DBG_COLOR5 t8 D! O: c  i) b- y
#include <rtdbg.h>
: T8 I5 u4 V# }# Q2 h% L& P6 x2 M) ~$ q4 c" J$ a& k
#define TX_DMA_FIFO_SIZE (2048)/ E+ x  u: k2 ]( r* g- z

* x3 {8 ~5 R" G& m* [struct temp_sound
  c7 D. H$ _9 t& z3 p0 ?/ ]% L{
7 u5 f; A: C; ?2 j    struct rt_audio_device device; : K- U7 l0 Z$ K
    struct rt_audio_configure replay_config;7 a1 r9 \' l+ R( {7 y
    int volume;0 ^, J9 q6 f/ r
    rt_uint8_t *tx_fifo;
9 G1 \  E9 p# f& b: \};
" K5 M3 l& G( J: [8 I5 u! @7 R& D
8 X4 L# G/ ^' T+ jstatic rt_err_t getcaps(struct rt_audio_device *audio, struct rt_audio_caps *caps)
7 ^7 @  u& X, E7 y1 p{
: r' M1 D# x' N. }. Q# c    struct temp_sound *sound = RT_NULL;  [$ A/ ^/ K4 A+ p% L; @

! D7 t% h# y; G% S" D, ~+ O    RT_ASSERT(audio != RT_NULL); ) }/ h  v8 n1 m+ @/ v- S
    sound = (struct temp_sound *)audio->parent.user_data; (void)sound; 2 A( q/ [( _2 F0 h

( {' b: Y# ~3 Q6 A, ?- h$ S    return RT_EOK; 0 P$ i* v+ H1 y8 J: c; N
}
0 I; ^+ N/ D3 F( ?% r2 S0 B, @7 |# p: |. O, n/ Z7 O# b( X
static rt_err_t configure(struct rt_audio_device *audio, struct rt_audio_caps *caps)
  H# x$ v, j8 E) `- b{
4 F( t1 J1 K- x/ S    struct temp_sound *sound = RT_NULL;3 W1 V& h' |7 r' E( I2 x3 f: `
, Z7 D9 p: S4 O2 ^+ }
    RT_ASSERT(audio != RT_NULL); + l: l4 S; x& [- f; L$ K
    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
& W7 Y" Q+ i" X5 n( b2 X
2 _" H8 \* D4 Q7 V+ v0 @    return RT_EOK; ( a. V7 e5 [. w6 J
}3 S$ ~3 G9 _/ p. d$ z/ u" m0 I
7 j  F% x7 M% M" E; ^
static rt_err_t init(struct rt_audio_device *audio). W" H- o2 ~% d5 g- U) O
{
, T( u! P  ~3 ^- }9 Z$ Q    struct temp_sound *sound = RT_NULL;0 y4 L1 b5 y; h4 F; K7 t, C

0 K6 e9 ?( I" N    RT_ASSERT(audio != RT_NULL); ; K( W6 Z% V7 ^  d% B
    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
% D$ Y3 U& ]$ P" Q! j3 o$ P( u( k+ H9 x; t3 m
    return RT_EOK;
( y6 D2 Z$ W' q* c8 G6 y}; U* d+ F6 Y1 D

' A7 U2 C* [6 t( a# i4 o& M; Estatic rt_err_t start(struct rt_audio_device *audio, int stream)3 a8 a% I0 o, f
{6 v  f; _7 [2 l- u0 _4 q$ M$ m
    struct temp_sound *sound = RT_NULL;& z9 e/ }. P! k! R5 @( d* l
, }5 V" T% h3 D  x9 u
    RT_ASSERT(audio != RT_NULL);
% g% u* L; U8 T7 N    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
+ @  {3 N2 B2 `( I. e% P
  k3 N+ `4 e; f* K    return RT_EOK;
: Y+ V/ V  d; R  N6 D3 S, N: H+ y}7 }% O' d  V# K  n8 u8 S% o
& v' y: v) O4 F
static rt_err_t stop(struct rt_audio_device *audio, int stream)3 H5 }+ m. J! s) @$ O$ J
{
/ V3 `0 A! u& |- v    struct temp_sound *sound = RT_NULL;- U* ~4 j* i2 u5 }% B5 j

8 T, Q+ o* b% P* B    RT_ASSERT(audio != RT_NULL);
+ e6 s( C: I$ }  j- t) ?: ~, k    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;  
8 z3 k; f9 f' v; n
9 F) m3 J5 n! ?% K$ L. B    return RT_EOK;
6 D0 r2 }5 B" s}  A& Q, i; k3 h# q0 ~& }
, G# @" O+ b& p/ u
rt_size_t transmit(struct rt_audio_device *audio, const void *writeBuf, void *readBuf, rt_size_t size)
4 O7 `! M0 W" W8 Q- W: B! {/ g4 K{
/ k/ n9 w6 y$ S, a/ t% }  Z) K    struct temp_sound *sound = RT_NULL;
6 V0 H  K! I; I3 v" p+ u
4 r# A( k- z2 n! X7 M    RT_ASSERT(audio != RT_NULL);
; A5 M3 I. \/ O5 q1 y- B0 o6 J: E    sound = (struct temp_sound *)audio->parent.user_data; (void)sound;
5 s8 b# V" n" Y- ?, S. Q7 `+ i& _$ _! b9 N
    return size;
, V" g) e1 U2 i; F4 N2 a0 b0 d) M}; v+ a! [2 R) c% G& `6 W- A
* I, M* V, [- `# Z% c" s' J
static void buffer_info(struct rt_audio_device *audio, struct rt_audio_buf_info *info)
# W* l/ Z: E7 |- A{
8 Q5 b  w, e) H2 w5 s* I    struct temp_sound *sound = RT_NULL;2 h  i* c0 R9 ^

# V" c* U; d  `( X9 C* E. L    RT_ASSERT(audio != RT_NULL);
* o$ B+ p# t0 H    sound = (struct temp_sound *)audio->parent.user_data;* I/ ~: d+ T; ^* j! h; u7 Y) d
" |. _! }- l) k( P% y
    /**4 S/ B8 H, ?3 z0 w
     *               TX_FIFO. y& W  Z( O* ^- Z* e
     * +----------------+----------------+- `2 s6 P2 L9 o& g. R. Q
     * |     block1     |     block2     |
# K) {6 j0 M) m$ x/ \  w4 J. H  r9 Q     * +----------------+----------------+
; W: r9 C6 T1 Y9 @     *  \  block_size  /
& i* }4 |5 o: T, a6 b     */! |. B8 s: S# X& `6 n0 E
    info->buffer      = sound->tx_fifo;
; B0 K$ H* f, I" l3 X# B5 b    info->total_size  = TX_DMA_FIFO_SIZE;1 g  n: b1 l. t  i, K9 Y  U
    info->block_size  = TX_DMA_FIFO_SIZE / 2;: w0 H0 M5 B) x6 T8 Z6 l$ r; B5 e- Q
    info->block_count = 2;' n- i6 y7 B1 T7 X
}
* J- G$ m/ [$ k# @; P+ p  b- X9 D3 H* R( A4 p
static struct rt_audio_ops ops =
" x% U; J0 n: r* H{  D4 n2 c# `' j/ u9 D" N
    .getcaps     = getcaps,4 ?+ e" Q# i  v9 H
    .configure   = configure,7 z; e$ [; m" {2 F2 c" v
    .init        = init,& _' X1 P0 k$ N9 [6 t! k
    .start       = start,
. t9 m& j" s( y% J  L: `" f    .stop        = stop,
% V& g+ m" R1 |, w- A    .transmit    = transmit,
8 A9 G3 y+ X; x    .buffer_info = buffer_info,* @; V: e: V0 m: a8 i; g
};
& O/ r1 q8 {9 C: r$ F8 w( a
1 {: w3 y: v( w1 s! Astatic int rt_hw_sound_init(void)8 v& H, H$ }, ]; |: c
{
. `: a0 x+ _9 r, D+ e/ i    rt_uint8_t *tx_fifo = RT_NULL;
# h) g9 @1 p2 O0 t) r, W. W% Z" j( C    static struct temp_sound sound = {0};
9 y. f) K1 @# X1 G  t
. {+ s7 B2 C  m; ^6 K& B    /* 分配 DMA 搬运 buffer */ 7 |$ k7 V0 `6 _' V: T
    tx_fifo = rt_calloc(1, TX_DMA_FIFO_SIZE); $ I% w8 r- n! \- P# r$ Z1 Z* e
    if(tx_fifo == RT_NULL)+ u$ b2 b* M3 ?5 v: x, e
    {
# c8 {( r/ ~" z2 ]        return -RT_ENOMEM;% @$ ?% g0 G- i2 n: j6 d
    }
1 R) x( M* Q$ r6 j
# c$ c  S& J; Z  l    sound.tx_fifo = tx_fifo;
7 ]. x- f: A  N$ a+ C! P4 L  c% l
1 r2 l' @0 a" ~5 f  U) X$ V; F    /* 注册声卡放音驱动 */5 A6 y/ I1 M0 T" p% l( M
    sound.device.ops = &ops;; z  o5 P7 I5 W) p6 v4 }8 D, E1 v
    rt_audio_register(&sound.device, "sound0", RT_DEVICE_FLAG_WRONLY, &sound);
! x* G$ B# P4 U7 ~9 C8 L& f$ R- w2 ^: s0 G- ]5 O9 C6 {4 G
    return RT_EOK;
) g, x7 P) D  M! d2 `, b}
  W8 z" y% F# j) RINIT_DEVICE_EXPORT(rt_hw_sound_init);

  s( L0 G9 X& F8 ~7 u
, [+ D! @# P8 e# N# q' a3 E- i
5.  代码分析
4 y. @' v  D8 s2 @5 \
* ~$ ]1 q5 p; V' C待后续补充。。。
  r/ l- H2 {, V( e) p9 j; ]8 r  B+ d: ~0 ~; N3 {
sound_temp.7z (1.09 KB, 下载次数: 130)
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-11-9 13:46:18 | 显示全部楼层
前排围观 9 层音频驱动框架。。。
使用道具 举报 回复
发表于 2019-11-9 14:03:51 | 显示全部楼层
前排围观 9 层音频驱动框架。。。
使用道具 举报 回复
发表于 2019-11-10 09:55:14 | 显示全部楼层
第二张逻辑关系图显示不出来,一直在打转
使用道具 举报 回复
发表于 2019-11-11 09:54:57 | 显示全部楼层
charlown.cai 发表于 2019-11-10 09:55
* d# `( \+ q5 L第二张逻辑关系图显示不出来,一直在打转
9 u3 X* T( z; X! n& b! f
直接点击这个图片链接试试,图片比较大
1 j9 x; l% I4 Z
8 V& _& A1 c$ q8 w7 Zhttps://note.youdao.com/yws/publ ... stamp=1573277165267
使用道具 举报 回复
发表于 2019-11-19 11:06:26 | 显示全部楼层
啥时候继续更新
使用道具 举报 回复
发表于 2019-11-19 11:12:27 | 显示全部楼层
XQQ 发表于 2019-11-19 11:062 e  Y) p, }, t! g
啥时候继续更新
8 h7 w8 B1 q5 A
周末更新,最近事情比较多,会更新一个系列的,这个帖子比较笔记,写的比较水
使用道具 举报 回复
发表于 2019-11-26 17:44:39 | 显示全部楼层
不赖,加油,加点文字说明一下,不然新手可能比较迷惑。
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

Powered by RT-Thread

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