1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #ifndef SOUND_PCM_H
6 #define SOUND_PCM_H
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <fcntl.h>
11 #include <stdarg.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <aos/list.h>
16 #include <aos/kernel.h>
17 #ifndef HAAS_AUDIO_DEMO
18 #include <sys/ioctl.h>
19 #endif
20 #include "audio_drv.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /** @defgroup a2sa_pcm_api pcm
27  *  @ingroup a2sa_api
28  * @{
29  */
30 
31 typedef unsigned long aos_pcm_uframes_t;
32 typedef signed long aos_pcm_sframes_t;
33 
34 /* AOS_PCM常用宏定义 */
35 #define AOS_PCM_BLOCK               0x00000000       /**< Blocking mode (flag for open mode) */
36 #define AOS_PCM_NONBLOCK            0x00000001       /**< Non blocking mode (flag for open mode) */
37 #define AOS_PCM_ASYNC               0x00000002       /**< Async notification (flag for open mode) */
38 #define AOS_PCM_ABORT               0x00008000       /**< In an abort state (internal, not allowed for open) */
39 #define AOS_PCM_NO_AUTO_RESAMPLE    0x00010000       /**< Disable automatic (but not forced!) rate resamplinig */
40 #define AOS_PCM_NO_AUTO_CHANNELS    0x00020000       /**< Disable automatic (but not forced!) channel conversion */
41 #define AOS_PCM_NO_AUTO_FORMAT      0x00040000       /**< Disable automatic (but not forced!) format conversion */
42 #define AOS_PCM_NO_SOFTVOL          0x00080000       /**< Disable soft volume control */
43 #define AOS_PCM_EVT_WRITE           (1 << 0)         /**< playback resource available event */
44 #define AOS_PCM_EVT_READ            (1 << 1)         /**< capture data available event */
45 #define AOS_PCM_EVT_XRUN            (1 << 2)         /**< underrun (playback) or overrun (capture) detected */
46 
47 /* PCM stream 类型定义 */
48 typedef enum {
49 	AOS_PCM_STREAM_PLAYBACK = 0,                     /**< Playback stream */
50 	AOS_PCM_STREAM_CAPTURE,                          /**< Capture stream */
51 	AOS_PCM_STREAM_LAST = AOS_PCM_STREAM_CAPTURE
52 } aos_pcm_stream_t;
53 
54 /* PCM stream 状态定义 */
55 typedef enum {
56 	AOS_PCM_STATE_IDLE = 0,                          /**< IDLE */
57 	AOS_PCM_STATE_OPEN,                              /**< Open */
58 	AOS_PCM_STATE_PREPARED,                          /**< Ready to start */
59 	AOS_PCM_STATE_RUNNING,                           /**< Running */
60 	AOS_PCM_STATE_XRUN,                              /**< Stopped: underrun (playback) or overrun (capture) detected */
61 	AOS_PCM_STATE_DRAINING,                          /**< Draining: running (playback) or stopped (capture) */
62 	AOS_PCM_STATE_PAUSED,                            /**< Paused */
63 	AOS_PCM_STATE_SUSPENDED,                         /**< Hardware is suspended */
64 	AOS_PCM_STATE_DISCONNECTED,                      /**< Hardware is disconnected */
65 	AOS_PCM_STATE_LAST = AOS_PCM_STATE_DISCONNECTED, /**< Last state */
66 	AOS_PCM_STATE_PRIVATE1 = 1024                    /**< Private - used internally in the library - do not use*/
67 } aos_pcm_state_t;
68 
69 /* PCM stream 格式定义 */
70 typedef enum {
71 	AOSRV_PCM_FORMAT_S8 = 1,                         /**< Signed 8-bit */
72 	AOSRV_PCM_FORMAT_S16_LE = 2,                     /**< Signed 16-bit, little endian */
73 	AOSRV_PCM_FORMAT_S24_LE = 3,                     /**< Signed 24-bit, little endian */
74 	AOSRV_PCM_FORMAT_S32_LE = 4,                     /**< Signed 32-bit, little endian */
75 	AOSRV_PCM_FORMAT_ALL
76 } aos_pcm_format_t;
77 
78 /* PCM stream 访问模式定义 */
79 typedef enum {
80 	AOS_PCM_ACCESS_MMAP_INTERLEAVED = 0,             /**< MMAP RW interleaved access */
81 	AOS_PCM_ACCESS_MMAP_NONINTERLEAVED,              /**< MMAP RW non-interleaved access */
82 	AOS_PCM_ACCESS_RW_INTERLEAVED,                   /**< RW interleaved access, e.g. writei/readi */
83 	AOS_PCM_ACCESS_RW_NONINTERLEAVED                 /**< RW non-interleaved access, e.g. writen/readn */
84 } aos_pcm_access_t;
85 
86 /* PCM stream 硬件参数类型 */
87 typedef struct {
88 	aos_pcm_access_t access;                         /**< aos_pcm_access_t 类型 */
89     aos_pcm_format_t format;                         /**< aos_pcm_format_t 类型 */
90     unsigned int sample_bits;                        /**< 采样精度 */
91     unsigned int frame_bits;                         /**< frame 位宽大小 */
92     unsigned int channels;                           /**< channel 通道数 */
93     unsigned int rate;                               /**< 采样率 */
94     unsigned int period_time;
95     unsigned int period_size;
96     unsigned int period_bytes;
97     unsigned int periods;
98     unsigned int buffer_time;
99     unsigned int buffer_size;
100     unsigned int buffer_bytes;
101     unsigned int tick_time;
102 } aos_pcm_hw_params_t;
103 
104 /* PCM stream 软件参数类型 */
105 typedef struct {
106 	int tstamp_mode;			                     /*< timestamp mode */
107 	unsigned int period_step;
108 	unsigned int sleep_min;			                 /*< min ticks to sleep */
109 	aos_pcm_uframes_t avail_min;		             /*< min avail frames for wakeup */
110 	aos_pcm_uframes_t xfer_align;		             /*< obsolete: xfer size need to be a multiple */
111 	aos_pcm_uframes_t start_threshold;	             /*< min hw_avail frames for automatic start */
112 	aos_pcm_uframes_t stop_threshold;	             /*< min avail frames for automatic stop */
113 	aos_pcm_uframes_t silence_threshold;             /*< min distance from noise for silence filling */
114 	aos_pcm_uframes_t silence_size;		             /*< silence block size */
115 	aos_pcm_uframes_t boundary;		                 /*< pointers wrap point */
116 	unsigned int proto;			                     /*< protocol version */
117 	unsigned int tstamp_type;		                 /*< timestamp type (req. proto >= 2.0.12) */
118 	unsigned char reserved[56];		                 /*< reserved for future */
119 } aos_pcm_sw_params_t;
120 
121 /* PCM stream 类型 */
122 typedef struct {
123 	/* mandatory */
124 	int fd;                                          /*< 该pcm设备节点的fd,通过open()获取 */
125 	aos_pcm_stream_t stream;                         /*< aos_pcm_stream_t 类型 */
126 	aos_pcm_state_t state;                           /*< aos_pcm_state_t 类型 */
127 	char *name;                                      /*< pcm stream name */
128 	int mode;
129 	int card;                                        /*< pcm stream 所属的card id */
130 	int device;                                      /*< pcm stream device id */
131 	aos_hdl_t mutex;
132     aos_hdl_t evt;
133 	aos_pcm_hw_params_t *hw_params;                  /*< pcm stream 硬件参数 */
134     aos_pcm_sw_params_t *sw_params;                  /*< pcm stream 软件参数 */
135 
136 	/* options */
137     void *open_func;
138 	long minperiodtime;
139 	int poll_fd_count;
140 	unsigned short poll_events;
141 	int setup: 1,
142 	    compat: 1;
143 	unsigned int mmap_rw: 1;
144 	unsigned int mmap_shadow: 1;
145 	unsigned int donot_close: 1;
146 	unsigned int own_state_check:1;
147 	void *private_data;
148 } aos_pcm_t;
149 
150 /* 所有声卡的PCM stream汇总 */
151 typedef struct {
152 	dlist_t list;                                    /*< 列表 */
153 	unsigned int count;                              /*< 列表中PCM Stream个数 */
154 	unsigned int allocated;
155 	const char *siface;                              /*< 默认: AOS_CTL_ELEM_IFACE_MIXER */
156 	int card;                                        /*< 当前声卡ID */
157 	int device;                                      /*< 在当前声中的设备ID */
158 	long device_input;
159 	long device_output;
160 	int stream;                                      /*< 0: Capture Stream 类型,1: Playback Stream 类型 */
161 	int show_all;
162 	char name[100];                                  /*< 当前设备名 */
163 } hint_list_t;
164 
165 /**
166  * 获取声卡card下属所有的PCM Stream
167  *
168  * @param[in]  card    声卡ID
169  * @param[out]  hints   hint_list_t类型列表
170  *
171  * @return  0 on success, negative error on failure.
172  */
173 int aos_device_name_hint(int card, void *hints);
174 
175 /**
176  * 获取声卡card下属所有的PCM Stream
177  *
178  * @param[out] **pcm    aos_pcm_t 句柄指针
179  * @param[in]  *name    pcm stream name
180  * @param[in]  stream   aos_pcm_stream_t 类型
181  * @param[in]  mode     AOS_PCM_BLOCK 或者 AOS_PCM_NONBLOCK
182  *
183  * @return  0 on success, negative error on failure.
184  */
185 int aos_pcm_open(aos_pcm_t **pcm, const char *name, aos_pcm_stream_t stream, int mode);
186 
187 /**
188  * 设置PCM Stream为prepared状态
189  *
190  * @param[in] *pcm      aos_pcm_t 句柄
191  *
192  * @return  0 on success, negative error on failure.
193  */
194 int aos_pcm_prepare(aos_pcm_t *pcm);
195 
196 /**
197  * 设置PCM Stream为START状态
198  *
199  * @param[in] *pcm      aos_pcm_t 句柄
200  *
201  * @return  0 on success, negative error on failure.
202  */
203 int aos_pcm_start(aos_pcm_t *pcm);
204 
205 /**
206  * 设置PCM Stream为wait状态, 最大超时时间timeout milisecond
207  *
208  * @param[in] *pcm      aos_pcm_t 句柄
209  * @param[in] timeout   超时时间,毫秒为单位
210  *
211  * @return  0 on success, negative error on failure.
212  */
213 int aos_pcm_wait(aos_pcm_t *pcm, int timeout);
214 
215 /**
216  * 停止PCM Stream
217  *
218  * @param[in] *pcm      aos_pcm_t 句柄
219  *
220  * @return  0 on success, negative error on failure.
221  */
222 int aos_pcm_stop(aos_pcm_t *pcm);
223 
224 /**
225  * 等待Playback PCM Stream buffer中的数据播放完成
226  *
227  * @param[in] *pcm      aos_pcm_t 句柄
228  *
229  * @return  0 on success, negative error on failure.
230  */
231 int aos_pcm_drain(aos_pcm_t *pcm);
232 
233 /**
234  * 暂停 PCM Stream
235  *
236  * @param[in] *pcm      aos_pcm_t 句柄
237  *
238  * @return  0 on success, negative error on failure.
239  */
240 int aos_pcm_pause(aos_pcm_t *pcm, int enable);
241 
242 /**
243  * 关闭 PCM Stream
244  *
245  * @param[in] *pcm      aos_pcm_t 句柄
246  *
247  * @return  0 on success, negative error on failure.
248  */
249 int aos_pcm_close(aos_pcm_t *pcm);
250 
251 /**
252  * 恢复 PCM Stream 底层硬件状态(可选)
253  *
254  * @param[in] *pcm      aos_pcm_t 句柄
255  *
256  * @return  0 on success, negative error on failure.
257  */
258 int aos_pcm_recover(aos_pcm_t *pcm);
259 
260 /**
261  * 分配 aos_pcm_hw_params_t 类型缓存区
262  *
263  * @param[out] **p      aos_pcm_hw_params_t 类型2级指针
264  *
265  * @return  0 on success, negative error on failure.
266  */
267 int aos_pcm_hw_params_alloca(aos_pcm_hw_params_t **p);
268 
269 /**
270  * 设置aos_pcm_hw_params_t 类型参数为默认参数
271  *
272  * @param[in] *params      aos_pcm_hw_params_t* 类型
273  *
274  * @return  0 on success, negative error on failure.
275  */
276 int aos_pcm_hw_params_any(aos_pcm_hw_params_t *params);
277 
278 /**
279  * 设置pcm stream的硬件参数为 *p 指向的参数
280  *
281  * @param[in] *pcm      aos_pcm_t* 类型
282  * @param[in] *p        aos_pcm_hw_params_t* 类型
283  *
284  * @return  0 on success, negative error on failure.
285  */
286 int aos_pcm_hw_params(aos_pcm_t *pcm, aos_pcm_hw_params_t *p);
287 
288 /**
289  * 根据输入参数设置pcm stream的硬件参数
290  *
291  * @param[in] *pcm        aos_pcm_t* 类型
292  * @param[in] format      aos_pcm_format_t 类型
293  * @param[in] access      aos_pcm_access_t 类型
294  * @param[in] channels    unsigned int 类型, 通道数
295  * @param[in] rate        unsigned int 类型, 采样率
296  * @param[in] soft_resample   int 类型
297  * @param[in] latency      unsigned int 类型
298  *
299  * @return  0 on success, negative error on failure.
300  */
301 int aos_pcm_set_params(aos_pcm_t *pcm, aos_pcm_format_t format, aos_pcm_access_t access, unsigned int channels,
302                        unsigned int rate, int soft_resample, unsigned int latency);
303 
304 /**
305  * 分配 aos_pcm_sw_params_t 类型缓存区
306  *
307  * @param[in] **p       aos_pcm_sw_params_t* 类型
308  *
309  * @return  0 on success, negative error on failure.
310  */
311 int aos_pcm_sw_params_alloca(aos_pcm_sw_params_t **p);
312 
313 /**
314  * 设置 aos_pcm_sw_params_t 类型参数为默认参数
315  *
316  * @param[in] *params      aos_pcm_sw_params_t* 类型
317  *
318  * @return  0 on success, negative error on failure.
319  */
320 int aos_pcm_sw_params_any(aos_pcm_sw_params_t *params);
321 
322 /**
323  * 设置pcm stream的软件参数为 *params 指向的参数
324  *
325  * @param[in] *pcm      aos_pcm_t* 类型
326  * @param[in] *params   aos_pcm_sw_params_t* 类型
327  *
328  * @return  0 on success, negative error on failure.
329  */
330 int aos_pcm_sw_params(aos_pcm_t *pcm, aos_pcm_sw_params_t *params);
331 
332 /**
333  * 以interleave格式往pcm stream写数据(e.g. CH0 -> CH1 -> CH2 -> CH0 ...)
334  *
335  * @param[in] *pcm      aos_pcm_t* 类型
336  * @param[in] *buffer   待写入的数据buffer
337  * @param[in] *size     待写入的数据buffer大小,以字节为单位
338  *
339  * @return  writen bytes number on success, negative error on failure.
340  */
341 aos_pcm_sframes_t aos_pcm_writei(aos_pcm_t *pcm, const void *buffer, aos_pcm_uframes_t size);
342 
343 /**
344  * 以interleave格式从pcm stream读数据(e.g. CH0 -> CH1 -> CH2 -> CH0 ...)
345  *
346  * @param[in] *pcm      aos_pcm_t* 类型
347  * @param[in] *buffer   存储读出数据的buffer
348  * @param[in] *size     待读出的数据大小,以字节为单位
349  *
350  * @return  read bytes number on success, negative error on failure.
351  */
352 aos_pcm_sframes_t aos_pcm_readi(aos_pcm_t *pcm, void *buffer, aos_pcm_uframes_t size);
353 
354 /**
355  * 以non-interleave格式往pcm stream写数据(e.g. CH0 -> CH0 ...-> CH0 (size 单位数据全部写完) -> CH1 -> CH1 ...)
356  *
357  * @param[in] *pcm      aos_pcm_t* 类型
358  * @param[in] *buffer   待写入的数据buffer
359  * @param[in] *size     待写入的数据buffer大小,以字节为单位
360  *
361  * @return  writen bytes number on success, negative error on failure.
362  */
363 aos_pcm_sframes_t aos_pcm_writen(aos_pcm_t *pcm, void **bufs, aos_pcm_uframes_t size);
364 
365 /**
366  * 以non-interleave格式从pcm stream读数据(e.g.  CH0 -> CH0 ...-> CH0 (size 单位数据全部读完) -> CH1 -> CH1 ...)
367  *
368  * @param[in] *pcm      aos_pcm_t* 类型
369  * @param[in] *buffer   存储读出数据的buffer
370  * @param[in] *size     待读出的数据大小,以字节为单位
371  *
372  * @return  read bytes number on success, negative error on failure.
373  */
374 aos_pcm_sframes_t aos_pcm_readn(aos_pcm_t *pcm, void **bufs, aos_pcm_uframes_t size);
375 
376 /**
377  * 暂停pcm stream,buffer中的数据仍然保留
378  *
379  * @param[in] *pcm      aos_pcm_t* 类型
380  *
381  * @return  0 on success, negative error on failure.
382  */
383 int aos_pcm_suspend(aos_pcm_t *pcm);
384 
385 /**
386  * 恢复pcm stream,buffer中遗留的数据继续读写
387  *
388  * @param[in] *pcm      aos_pcm_t* 类型
389  *
390  * @return  0 on success, negative error on failure.
391  */
392 int aos_pcm_resume(aos_pcm_t *pcm);
393 
394 /**
395  * 根据pcm stream的参数配置计算bytes个字节对应的frame帧数
396  *
397  * @param[in] *pcm      aos_pcm_t* 类型
398  * @param[in] bytes     字节数
399  *
400  * @return  aos_pcm_sframes_t on success, negative error on failure.
401  */
402 aos_pcm_sframes_t aos_pcm_bytes_to_frames(aos_pcm_t *pcm, int bytes);
403 
404 /**
405  * 根据pcm stream的参数配置计算frame帧数对应的bytes字节数
406  *
407  * @param[in] *pcm      aos_pcm_t* 类型
408  * @param[in] *frames   帧数
409  *
410  * @return  unsigned int on success, negative error on failure.
411  */
412 int aos_pcm_frames_to_bytes(aos_pcm_t *pcm, aos_pcm_sframes_t frames);
413 
414 /**
415  * @}
416  */
417 
418 #ifdef __cplusplus
419 }
420 #endif
421 #endif /* SOUND_PCM_H */
422 
423