Skip to content

Commit 80eb94d

Browse files
takayoshikmasayuki2009
authored andcommitted
audioutils/nxaudio: Add audio utility library for nuttx audio
Add an utility library for easier use of NuttX's Audio driver.
1 parent 40c506f commit 80eb94d

File tree

5 files changed

+472
-0
lines changed

5 files changed

+472
-0
lines changed

audioutils/nxaudio/Kconfig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see the file kconfig-language.txt in the NuttX tools repository.
4+
#
5+
6+
config AUDIOUTILS_NXAUDIO_LIB
7+
bool "NX Audio Library"
8+
default n
9+
---help---
10+
Enable support for the NX Audio library.
11+
12+
if AUDIOUTILS_NXAUDIO_LIB
13+
14+
config AUDIOUTILS_NXAUDIO_DEVPATH
15+
string "Audio Device file path"
16+
default "/dev/audio/pcm1"
17+
---help---
18+
Audio device file path of target audio device.
19+
20+
config AUDIOUTILS_NXAUDIO_MSGQNAME
21+
string "Message queue name"
22+
default "/tmp/fmaudio_mq"
23+
---help---
24+
Message queue name (file path) to communicate with audio message loop.
25+
26+
endif

audioutils/nxaudio/Make.defs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
############################################################################
2+
# apps/audioutils/nxaudio/Make.defs
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership. The
7+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance with the
9+
# License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
# License for the specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
############################################################################
20+
21+
ifeq ($(CONFIG_AUDIOUTILS_NXAUDIO_LIB),y)
22+
CONFIGURED_APPS += $(APPDIR)/audioutils/nxaudio
23+
endif

audioutils/nxaudio/Makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
############################################################################
2+
# apps/audioutils/nxaudio/Makefile
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership. The
7+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance with the
9+
# License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
# License for the specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
############################################################################
20+
21+
include $(APPDIR)/Make.defs
22+
23+
CSRCS = nxaudio.c
24+
25+
include $(APPDIR)/Application.mk

audioutils/nxaudio/nxaudio.c

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
/****************************************************************************
2+
* apps/audioutils/nxaudio/nxaudio.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <nuttx/config.h>
26+
27+
#include <stdint.h>
28+
#include <stdio.h>
29+
#include <stdlib.h>
30+
#include <unistd.h>
31+
#include <fcntl.h>
32+
#include <mqueue.h>
33+
#include <sys/ioctl.h>
34+
#include <nuttx/audio/audio.h>
35+
36+
#include <errno.h>
37+
38+
#include <audioutils/nxaudio.h>
39+
40+
/****************************************************************************
41+
* Pre-processor Definitions
42+
****************************************************************************/
43+
44+
/****************************************************************************
45+
* Private Functions
46+
****************************************************************************/
47+
48+
/****************************************************************************
49+
* name: configure_audio
50+
****************************************************************************/
51+
52+
static int configure_audio(int fd, int ch, int fs, int bps, int chmap)
53+
{
54+
struct audio_caps_desc_s cap;
55+
56+
cap.caps.ac_len = sizeof(struct audio_caps_s);
57+
cap.caps.ac_type = AUDIO_TYPE_OUTPUT;
58+
cap.caps.ac_channels = ch;
59+
cap.caps.ac_chmap = chmap;
60+
cap.caps.ac_controls.hw[0] = fs;
61+
cap.caps.ac_controls.b[2] = bps;
62+
cap.caps.ac_controls.b[3] = 0; /* Just set 0 */
63+
64+
return ioctl(fd, AUDIOIOC_CONFIGURE, (unsigned long)(uintptr_t)&cap);
65+
}
66+
67+
/****************************************************************************
68+
* name: create_audiomq
69+
****************************************************************************/
70+
71+
static mqd_t create_audiomq(int fd, int buf_num)
72+
{
73+
mqd_t ret;
74+
struct mq_attr attr;
75+
76+
attr.mq_maxmsg = buf_num;
77+
attr.mq_msgsize = sizeof(struct audio_msg_s);
78+
attr.mq_curmsgs = 0;
79+
attr.mq_flags = 0;
80+
81+
ret = mq_open(CONFIG_AUDIOUTILS_NXAUDIO_MSGQNAME,
82+
O_RDWR | O_CREAT, 0644, &attr);
83+
if (ret >= (mqd_t)0)
84+
{
85+
int rr;
86+
if ((rr = ioctl(fd, AUDIOIOC_REGISTERMQ, (unsigned long)ret)) < 0)
87+
{
88+
printf("mq register failed: %d, %d\n", rr, errno);
89+
}
90+
}
91+
92+
return ret;
93+
}
94+
95+
/****************************************************************************
96+
* name: create_audio_buffers
97+
****************************************************************************/
98+
99+
static FAR struct ap_buffer_s **create_audio_buffers(int fd, int num, int sz)
100+
{
101+
int i;
102+
struct audio_buf_desc_s desc;
103+
FAR struct ap_buffer_s **ret;
104+
105+
ret = (FAR struct ap_buffer_s **)calloc(num, sizeof(FAR void *));
106+
107+
for (i = 0; i < num; i++)
108+
{
109+
desc.numbytes = sz;
110+
desc.u.pbuffer = &ret[i];
111+
112+
ioctl(fd, AUDIOIOC_ALLOCBUFFER, (unsigned long)(uintptr_t)&desc);
113+
}
114+
115+
return ret;
116+
}
117+
118+
/****************************************************************************
119+
* name: free_audio_buffers
120+
****************************************************************************/
121+
122+
static void free_audio_buffers(FAR struct nxaudio_s *nxaudio)
123+
{
124+
int x;
125+
struct audio_buf_desc_s desc;
126+
127+
for (x = 0; x < nxaudio->abufnum; x++)
128+
{
129+
if (nxaudio->abufs[x] != NULL)
130+
{
131+
desc.u.buffer = nxaudio->abufs[x];
132+
ioctl(nxaudio->fd, AUDIOIOC_FREEBUFFER,
133+
(unsigned long)(uintptr_t)&desc);
134+
}
135+
}
136+
137+
free(nxaudio->abufs);
138+
}
139+
140+
/****************************************************************************
141+
* Public Functions
142+
****************************************************************************/
143+
144+
/****************************************************************************
145+
* name: fin_nxaudio
146+
****************************************************************************/
147+
148+
void fin_nxaudio(FAR struct nxaudio_s *nxaudio)
149+
{
150+
free_audio_buffers(nxaudio);
151+
ioctl(nxaudio->fd, AUDIOIOC_STOP, 0);
152+
ioctl(nxaudio->fd, AUDIOIOC_UNREGISTERMQ, (unsigned long)nxaudio->mq);
153+
ioctl(nxaudio->fd, AUDIOIOC_RELEASE, 0);
154+
ioctl(nxaudio->fd, AUDIOIOC_SHUTDOWN, 0);
155+
mq_close(nxaudio->mq);
156+
mq_unlink(CONFIG_AUDIOUTILS_NXAUDIO_MSGQNAME);
157+
close(nxaudio->fd);
158+
}
159+
160+
/****************************************************************************
161+
* name: init_nxaudio
162+
****************************************************************************/
163+
164+
int init_nxaudio(FAR struct nxaudio_s *nxaudio,
165+
int fs, int bps, int chnum)
166+
{
167+
struct ap_buffer_info_s buf_info;
168+
169+
nxaudio->fd = open(CONFIG_AUDIOUTILS_NXAUDIO_DEVPATH, O_RDWR | O_CLOEXEC);
170+
if (nxaudio->fd >= 0)
171+
{
172+
if (ioctl(nxaudio->fd, AUDIOIOC_RESERVE, 0) < 0)
173+
{
174+
close(nxaudio->fd);
175+
return -1;
176+
}
177+
178+
/* Audio configuration: set channel num, FS and bps */
179+
180+
configure_audio(nxaudio->fd, chnum, fs, bps, 0);
181+
182+
nxaudio->chnum = chnum;
183+
184+
ioctl(nxaudio->fd, AUDIOIOC_GETBUFFERINFO,
185+
(unsigned long)(uintptr_t)&buf_info);
186+
187+
/* Create message queue to communicate with audio driver */
188+
189+
nxaudio->mq = create_audiomq(nxaudio->fd, buf_info.nbuffers + 8);
190+
191+
/* Create audio buffers to inject audio sample */
192+
193+
nxaudio->abufs = create_audio_buffers(nxaudio->fd,
194+
buf_info.nbuffers, buf_info.buffer_size);
195+
nxaudio->abufnum = buf_info.nbuffers;
196+
197+
return 0;
198+
}
199+
else
200+
{
201+
return -1;
202+
}
203+
}
204+
205+
/****************************************************************************
206+
* name: nxaudio_enqbuffer
207+
****************************************************************************/
208+
209+
int nxaudio_enqbuffer(FAR struct nxaudio_s *nxaudio,
210+
FAR struct ap_buffer_s *apb)
211+
{
212+
struct audio_buf_desc_s desc;
213+
214+
desc.numbytes = apb->nbytes;
215+
desc.u.buffer = apb;
216+
217+
return ioctl(nxaudio->fd, AUDIOIOC_ENQUEUEBUFFER,
218+
(unsigned long)(uintptr_t)&desc);
219+
}
220+
221+
/****************************************************************************
222+
* name: nxaudio_setvolume
223+
****************************************************************************/
224+
225+
int nxaudio_setvolume(FAR struct nxaudio_s *nxaudio, uint16_t vol)
226+
{
227+
struct audio_caps_desc_s cap_desc;
228+
229+
cap_desc.caps.ac_len = sizeof(struct audio_caps_s);
230+
cap_desc.caps.ac_type = AUDIO_TYPE_FEATURE;
231+
cap_desc.caps.ac_format.hw = AUDIO_FU_VOLUME;
232+
cap_desc.caps.ac_controls.hw[0] = vol;
233+
234+
return ioctl(nxaudio->fd, AUDIOIOC_CONFIGURE,
235+
(unsigned long)(uintptr_t)&cap_desc);
236+
}
237+
238+
/****************************************************************************
239+
* name: nxaudio_start
240+
****************************************************************************/
241+
242+
int nxaudio_start(FAR struct nxaudio_s *nxaudio)
243+
{
244+
return ioctl(nxaudio->fd, AUDIOIOC_START, 0);
245+
}
246+
247+
/****************************************************************************
248+
* name: nxaudio_start
249+
****************************************************************************/
250+
251+
int nxaudio_stop(FAR struct nxaudio_s *nxaudio)
252+
{
253+
struct audio_msg_s term_msg;
254+
255+
term_msg.msg_id = AUDIO_MSG_STOP;
256+
term_msg.u.data = 0;
257+
mq_send(nxaudio->mq, (FAR const char *)&term_msg, sizeof(term_msg), 0);
258+
259+
return OK;
260+
}
261+
262+
/****************************************************************************
263+
* name: nxaudio_msgloop
264+
****************************************************************************/
265+
266+
int nxaudio_msgloop(FAR struct nxaudio_s *nxaudio,
267+
FAR struct nxaudio_callbacks_s *cbs,
268+
unsigned long arg)
269+
{
270+
bool running = true;
271+
struct audio_msg_s msg;
272+
unsigned int prio;
273+
ssize_t size;
274+
275+
if (!cbs)
276+
{
277+
return -1;
278+
}
279+
280+
while (running)
281+
{
282+
size = mq_receive(nxaudio->mq, (FAR char *)&msg, sizeof(msg), &prio);
283+
if (size != sizeof(msg))
284+
{
285+
continue;
286+
}
287+
288+
switch (msg.msg_id)
289+
{
290+
case AUDIO_MSG_DEQUEUE:
291+
if (cbs->dequeue)
292+
{
293+
cbs->dequeue(arg, msg.u.ptr);
294+
}
295+
break;
296+
case AUDIO_MSG_COMPLETE:
297+
if (cbs->complete)
298+
{
299+
cbs->complete(arg);
300+
}
301+
break;
302+
303+
case AUDIO_MSG_STOP:
304+
running = false;
305+
break;
306+
307+
case AUDIO_MSG_USER:
308+
if (cbs->user)
309+
{
310+
cbs->user(arg, &msg, &running);
311+
}
312+
break;
313+
default:
314+
break;
315+
}
316+
}
317+
318+
return 0;
319+
}

0 commit comments

Comments
 (0)