xref: /nrf52832-nimble/rt-thread/components/drivers/audio/audio.c (revision 167494296f0543431a51b6b1b83e957045294e05)
1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-05-09     Urey      first version
9  */
10 
11 #include <stdio.h>
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <rtdevice.h>
15 
16 #include <drivers/audio.h>
17 
18 #include "audio_pipe.h"
19 
20 
21 #define AUDIO_DEBUG   0
22 #if AUDIO_DEBUG
23 #define AUDIO_DBG(...)     printf("[AUDIO]:"),printf(__VA_ARGS__)
24 #else
25 #define AUDIO_DBG(...)
26 #endif
27 
28 static struct rt_audio_pipe audio_pipe;
29 
30 static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
31 {
32     rt_err_t result = RT_EOK;
33     rt_base_t level;
34     struct rt_audio_frame frame;
35 
36     RT_ASSERT(audio != RT_NULL);
37 
38     //check repaly queue is empty
39     if (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) != RT_EOK)
40     {
41         AUDIO_DBG("TX queue is empty\n");
42         result = -RT_EEMPTY;
43 
44         level = rt_hw_interrupt_disable();
45         audio->replay->activated = RT_FALSE;
46         rt_hw_interrupt_enable(level);
47 
48         goto _exit;
49     }
50 
51     if (audio->ops->transmit != RT_NULL)
52     {
53         AUDIO_DBG("audio transmit...\n");
54         if (audio->ops->transmit(audio, frame.data_ptr, RT_NULL, frame.data_size) != frame.data_size)
55         {
56             result = -RT_EBUSY;
57 
58             goto _exit;
59         }
60     }
61 
62     //pop the head frame...
63     rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
64 
65     _exit: return result;
66 }
67 
68 static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
69 {
70     struct rt_audio_frame frame;
71 
72     if (audio->replay == RT_NULL)
73         return -RT_EIO;
74     while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
75     {
76         //pop the head frame...
77         rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
78 
79         /* notify transmitted complete. */
80         if (audio->parent.tx_complete != RT_NULL)
81             audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
82     }
83 
84     return RT_EOK;
85 }
86 
87 static rt_err_t _audio_dev_init(struct rt_device *dev)
88 {
89     rt_err_t result = RT_EOK;
90     struct rt_audio_device *audio;
91 
92     RT_ASSERT(dev != RT_NULL);
93     audio = (struct rt_audio_device *) dev;
94 
95     /* initialize replay & record */
96     audio->replay = RT_NULL;
97     audio->record = RT_NULL;
98 
99     /* apply configuration */
100     if (audio->ops->init)
101         result = audio->ops->init(audio);
102 
103     return result;
104 }
105 
106 static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
107 {
108     struct rt_audio_device *audio;
109 
110     RT_ASSERT(dev != RT_NULL);
111     audio = (struct rt_audio_device *) dev;
112 
113     /* check device flag with the open flag */
114     if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
115         return -RT_EIO;
116     if ((oflag & RT_DEVICE_OFLAG_WRONLY) && !(dev->flag & RT_DEVICE_FLAG_WRONLY))
117         return -RT_EIO;
118 
119     /* get open flags */
120     dev->open_flag = oflag & 0xff;
121 
122     /* initialize the Rx/Tx structure according to open flag */
123     if (oflag & RT_DEVICE_OFLAG_WRONLY)
124     {
125         AUDIO_DBG("open audio device ,oflag = %x\n",oflag);
126         if (audio->replay == RT_NULL)
127         {
128             struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
129 
130             if (replay == RT_NULL)
131             {
132                 AUDIO_DBG("request memory for replay error\n");
133                 return -RT_ENOMEM;
134             }
135 
136             //init queue for audio replay
137             rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, CFG_AUDIO_REPLAY_QUEUE_COUNT / 2, RT_NULL);
138 
139             replay->activated = RT_FALSE;
140             audio->replay = replay;
141         }
142 
143         dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
144     }
145 
146     if (oflag & RT_DEVICE_OFLAG_RDONLY)
147     {
148         if (audio->record == RT_NULL)
149         {
150             struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
151 
152             if (record == RT_NULL)
153             {
154                 AUDIO_DBG("request memory for record error\n");
155                 return -RT_ENOMEM;
156             }
157 
158             //init pipe for record
159             {
160                 rt_uint8_t *buf = rt_malloc(CFG_AUDIO_RECORD_PIPE_SIZE);
161 
162                 if (buf == RT_NULL)
163                 {
164                     rt_free(record);
165                     AUDIO_DBG("request pipe memory error\n");
166 
167                     return -RT_ENOMEM;
168                 }
169 
170                 rt_audio_pipe_init(&audio_pipe, "recpipe", (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD), buf,
171                              CFG_AUDIO_RECORD_PIPE_SIZE);
172             }
173 
174             record->activated = RT_FALSE;
175             audio->record = record;
176         }
177 
178         //open record pipe
179         if (audio->record != RT_NULL)
180         {
181             rt_device_open(RT_DEVICE(&audio_pipe), RT_DEVICE_OFLAG_RDONLY);
182         }
183 
184         dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
185     }
186 
187     return RT_EOK;
188 }
189 
190 static rt_err_t _audio_dev_close(struct rt_device *dev)
191 {
192     struct rt_audio_device *audio;
193     RT_ASSERT(dev != RT_NULL);
194     audio = (struct rt_audio_device *) dev;
195 
196     //shutdown the lower device
197     if (audio->ops->shutdown != RT_NULL)
198         audio->ops->shutdown(audio);
199 
200     if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
201     {
202         struct rt_audio_frame frame;
203         //stop replay stream
204         audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
205 
206         //flush all frame
207         while (rt_data_queue_peak(&audio->replay->queue, &frame.data_ptr, &frame.data_size) == RT_EOK)
208         {
209             //pop the head frame...
210             rt_data_queue_pop(&audio->replay->queue, &frame.data_ptr, &frame.data_size, RT_WAITING_FOREVER);
211 
212             /* notify transmitted complete. */
213             if (audio->parent.tx_complete != RT_NULL)
214                 audio->parent.tx_complete(&audio->parent, (void *) frame.data_ptr);
215         }
216 
217         dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
218     }
219 
220     if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
221     {
222         //stop record stream
223         audio->ops->stop(audio, AUDIO_STREAM_RECORD);
224 
225         //close record pipe
226         if (audio->record != RT_NULL)
227             rt_device_close(RT_DEVICE(&audio_pipe));
228 
229         dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
230     }
231 
232     return RT_EOK;
233 }
234 
235 static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
236 {
237     struct rt_audio_device *audio;
238     RT_ASSERT(dev != RT_NULL);
239     audio = (struct rt_audio_device *) dev;
240     if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
241         return 0;
242 
243     return rt_device_read(RT_DEVICE(&audio_pipe), pos, buffer, size);
244 }
245 
246 static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
247 {
248     rt_err_t result = RT_EOK;
249     rt_base_t level;
250     struct rt_audio_device *audio;
251 
252     RT_ASSERT(dev != RT_NULL);
253     audio = (struct rt_audio_device *) dev;
254 
255     if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
256         return 0;
257 
258     AUDIO_DBG("audio write : pos = %d,buffer = %x,size = %d\n",pos,(rt_uint32_t)buffer,size);
259     //push a new frame to tx queue
260     {
261         result = rt_data_queue_push(&audio->replay->queue, buffer, size,
262         RT_WAITING_FOREVER);
263         if (result != RT_EOK)
264         {
265             AUDIO_DBG("TX frame queue push error\n");
266             rt_set_errno(-RT_EFULL);
267             return 0;
268         }
269     }
270 
271     //check tx state...
272     level = rt_hw_interrupt_disable();
273     if (audio->replay->activated != RT_TRUE)
274     {
275         audio->replay->activated = RT_TRUE;
276         rt_hw_interrupt_enable(level);
277 
278         _audio_send_replay_frame(audio);
279     }
280     else
281     {
282         rt_hw_interrupt_enable(level);
283     }
284 
285     return size;
286 }
287 
288 static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
289 {
290     rt_err_t result = RT_EOK;
291     struct rt_audio_device *audio;
292     RT_ASSERT(dev != RT_NULL);
293     audio = (struct rt_audio_device *) dev;
294 
295     //dev stat...
296     switch (cmd)
297     {
298         case AUDIO_CTL_GETCAPS:
299         {
300             struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
301 
302             AUDIO_DBG("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
303             if (audio->ops->getcaps != RT_NULL)
304             {
305                 result = audio->ops->getcaps(audio, caps);
306             }
307         }
308         break;
309         case AUDIO_CTL_CONFIGURE:
310         {
311             struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
312 
313             AUDIO_DBG("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d\n",caps->main_type,caps->sub_type);
314             if (audio->ops->configure != RT_NULL)
315             {
316                 result = audio->ops->configure(audio, caps);
317             }
318         }
319 
320         break;
321         case AUDIO_CTL_SHUTDOWN:
322         {
323             AUDIO_DBG("AUDIO_CTL_SHUTDOWN\n");
324 
325             if (audio->ops->shutdown != RT_NULL)
326                 result = audio->ops->shutdown(audio);
327 
328             //flush replay frame...
329             _audio_flush_replay_frame(audio);
330         }
331         break;
332 
333         case AUDIO_CTL_START:
334         {
335             int stream = *(int *) args;
336 
337             AUDIO_DBG("AUDIO_CTL_START: stream = %d\n",stream);
338             if (audio->ops->start != RT_NULL)
339                 result = audio->ops->start(audio, stream);
340         }
341         break;
342         case AUDIO_CTL_STOP:
343         {
344             int stream = *(int *) args;
345 
346             AUDIO_DBG("AUDIO_CTL_STOP: stream = %d\n",stream);
347             if (audio->ops->start != RT_NULL)
348                 result = audio->ops->stop(audio, stream);
349 
350             if (stream == AUDIO_STREAM_REPLAY)
351             {
352                 _audio_flush_replay_frame(audio);
353             }
354         }
355         break;
356         case AUDIO_CTL_PAUSE:
357         {
358             int stream = *(int *) args;
359 
360             AUDIO_DBG("AUDIO_CTL_PAUSE: stream = %d\n",stream);
361             if (audio->ops->start != RT_NULL)
362                 result = audio->ops->suspend(audio, stream);
363         }
364         break;
365         case AUDIO_CTL_RESUME:
366         {
367             int stream = *(int *) args;
368 
369             AUDIO_DBG("AUDIO_CTL_RESUME: stream = %d\n",stream);
370             if (audio->ops->start != RT_NULL)
371                 result = audio->ops->resume(audio, stream);
372 
373             //resume tx frame...
374             if (stream == AUDIO_STREAM_REPLAY)
375                 _audio_send_replay_frame(audio);
376         }
377         break;
378         case AUDIO_CTL_ALLOCBUFFER:
379         {
380             struct rt_audio_buf_desc *desc = (struct rt_audio_buf_desc *) args;
381 
382             if (desc)
383             {
384                 desc->data_size = AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2;
385                 desc->data_ptr = rt_mp_alloc(&audio->mp, RT_WAITING_FOREVER);
386 
387                 result = RT_EOK;
388             }
389             else result = -RT_EIO;
390         }
391         break;
392         case AUDIO_CTL_FREEBUFFER:
393         {
394             rt_uint8_t *data_ptr = (rt_uint8_t *) args;
395             if (data_ptr)
396                 rt_mp_free(data_ptr);
397         }
398         break;
399         default:
400             result = audio->ops->control(audio, cmd, args);
401         break;
402     }
403 
404     return result;
405 }
406 
407 #ifdef RT_USING_DEVICE_OPS
408 const static struct rt_device_ops audio_ops =
409 {
410     _audio_dev_init,
411     _audio_dev_open,
412     _audio_dev_close,
413     _audio_dev_read,
414     _audio_dev_write,
415     _audio_dev_control
416 };
417 #endif
418 
419 rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
420 {
421     struct rt_device *device;
422     RT_ASSERT(audio != RT_NULL);
423     device = &(audio->parent);
424 
425     device->type = RT_Device_Class_Sound;
426     device->rx_indicate = RT_NULL;
427     device->tx_complete = RT_NULL;
428 
429 #ifdef RT_USING_DEVICE_OPS
430     device->ops  = &audio_ops;
431 #else
432     device->init    = _audio_dev_init;
433     device->open    = _audio_dev_open;
434     device->close   = _audio_dev_close;
435     device->read    = _audio_dev_read;
436     device->write   = _audio_dev_write;
437     device->control = _audio_dev_control;
438 #endif
439     device->user_data = data;
440 
441     //init memory pool for replay
442     {
443         rt_uint8_t *mempool = rt_malloc(AUDIO_DEVICE_DECODE_MP_SZ);
444         rt_mp_init(&audio->mp, "adu_mp", mempool, AUDIO_DEVICE_DECODE_MP_SZ,
445         AUDIO_DEVICE_DECODE_MP_BLOCK_SZ * 2);
446     }
447 
448     /* register a character device */
449     return rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
450 }
451 
452 int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
453 {
454     int speed = 0;
455     switch (bitValue)
456     {
457         case AUDIO_SAMP_RATE_8K:
458             speed = 8000;
459         break;
460         case AUDIO_SAMP_RATE_11K:
461             speed = 11052;
462         break;
463         case AUDIO_SAMP_RATE_16K:
464             speed = 16000;
465         break;
466         case AUDIO_SAMP_RATE_22K:
467             speed = 22050;
468         break;
469         case AUDIO_SAMP_RATE_32K:
470             speed = 32000;
471         break;
472         case AUDIO_SAMP_RATE_44K:
473             speed = 44100;
474         break;
475         case AUDIO_SAMP_RATE_48K:
476             speed = 48000;
477         break;
478         case AUDIO_SAMP_RATE_96K:
479             speed = 96000;
480         break;
481         case AUDIO_SAMP_RATE_128K:
482             speed = 128000;
483         break;
484         case AUDIO_SAMP_RATE_160K:
485             speed = 160000;
486         break;
487         case AUDIO_SAMP_RATE_172K:
488             speed = 176400;
489         break;
490         case AUDIO_SAMP_RATE_192K:
491             speed = 192000;
492         break;
493         default:
494 
495         break;
496     }
497 
498     return speed;
499 }
500 
501 rt_uint32_t rt_audio_format_to_bits(rt_uint32_t format)
502 {
503     switch (format)
504     {
505         case AUDIO_FMT_PCM_U8:
506         case AUDIO_FMT_PCM_S8:
507             return 8;
508         case AUDIO_FMT_PCM_S16_LE:
509         case AUDIO_FMT_PCM_S16_BE:
510         case AUDIO_FMT_PCM_U16_LE:
511         case AUDIO_FMT_PCM_U16_BE:
512             return 16;
513         default:
514             return 32;
515     };
516 }
517 
518 void rt_audio_tx_complete(struct rt_audio_device *audio, rt_uint8_t *pbuf)
519 {
520     rt_err_t result;
521     AUDIO_DBG("audio tx complete ptr=%x...\n",(rt_uint32_t)pbuf);
522 
523     //try to send all frame
524     do
525     {
526         result = _audio_send_replay_frame(audio);
527     } while (result == RT_EOK);
528 
529     /* notify transmitted complete. */
530     if (audio->parent.tx_complete != RT_NULL)
531         audio->parent.tx_complete(&audio->parent, (void *) pbuf);
532 }
533 
534 void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
535 {
536     //save data to record pipe
537     rt_device_write(RT_DEVICE(RT_DEVICE(&audio_pipe)), 0, pbuf, len);
538 
539     /* invoke callback */
540     if (audio->parent.rx_indicate != RT_NULL)
541         audio->parent.rx_indicate(&audio->parent, len);
542 }
543 
544