blob: e2b3c77e89792b3a02e715d6aadf79c7496c2175 [file] [log] [blame]
Tim Yao5351d702020-01-20 16:56:42 -08001/*
wei.du2be69bd2023-02-25 22:53:29 +08002 * Copyright (C) 2021 Amlogic Corporation.
Tim Yao5351d702020-01-20 16:56:42 -08003 *
wei.du2be69bd2023-02-25 22:53:29 +08004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Tim Yao5351d702020-01-20 16:56:42 -08007 *
wei.du2be69bd2023-02-25 22:53:29 +08008 * http://www.apache.org/licenses/LICENSE-2.0
Tim Yao5351d702020-01-20 16:56:42 -08009 *
wei.du2be69bd2023-02-25 22:53:29 +080010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Tim Yao5351d702020-01-20 16:56:42 -080015 */
16
wei.du2be69bd2023-02-25 22:53:29 +080017
Tim Yao5351d702020-01-20 16:56:42 -080018#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/mman.h>
21#include <fcntl.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <unistd.h>
25#include "audio_if.h"
jing.zhang1ac869f2022-01-17 16:20:38 +080026#include <signal.h>
Tim Yao5351d702020-01-20 16:56:42 -080027
28#define min(a, b) ((a) < (b) ? (a) : (b))
29#define WRITE_UNIT 4096
30
shu.zhang0d999582021-07-19 07:51:13 -040031enum audio_format {
32 FORMAT_PCM16 = 0,
33 FORMAT_PCM32,
34 FORMAT_DD,
35 FORMAT_MAT,
36 FORMAT_IEC61937,
37 FORMAT_AC4 = 5,
38 FORMAT_MP3,
39 FORMAT_AAC,
40 FORMAT_OGG,
41 FORMAT_FLAC,
wei.wang1476a9fa2023-07-17 06:20:31 +000042 FORMAT_TRUE_HD,
shu.zhang0d999582021-07-19 07:51:13 -040043 FORMAT_MAX
44};
Tim Yao5351d702020-01-20 16:56:42 -080045
shu.zhang0d999582021-07-19 07:51:13 -040046static int format_tab[] = {
47 AUDIO_FORMAT_PCM_16_BIT,
48 AUDIO_FORMAT_PCM_32_BIT,
49 AUDIO_FORMAT_AC3,
50 AUDIO_FORMAT_MAT,
51 AUDIO_FORMAT_IEC61937,
52 AUDIO_FORMAT_AC4,
53 AUDIO_FORMAT_MP3,
54 AUDIO_FORMAT_AAC,
55 AUDIO_FORMAT_VORBIS,
wei.wang1476a9fa2023-07-17 06:20:31 +000056 AUDIO_FORMAT_FLAC,
57 AUDIO_FORMAT_DOLBY_TRUEHD
shu.zhang0d999582021-07-19 07:51:13 -040058};
59
Tim Yao5351d702020-01-20 16:56:42 -080060static const char *format_str[] = {
shu.zhang0d999582021-07-19 07:51:13 -040061 "PCM_16",
62 "PCM_32",
63 "DOLBY DD/DD+",
64 "DOLBY MAT",
65 "IEC_61937",
66 "AC4",
67 "MP3",
68 "AAC",
69 "OGG",
wei.wang1476a9fa2023-07-17 06:20:31 +000070 "FLAC",
71 "TRUE_HD"
Tim Yao5351d702020-01-20 16:56:42 -080072};
73
74static int format_is_pcm(int format)
75{
76 return (format == FORMAT_PCM16) || (format == FORMAT_PCM32);
77}
78
79static unsigned char *fmap(const char *fn, int *size, int *fd)
80{
81 int fd_r, r;
82 struct stat st;
83 unsigned char *p;
84
85 fd_r = open(fn, O_RDWR);
86
87 if (fd_r < 0)
88 return NULL;
89
90 *fd = fd_r;
91 r = fstat(fd_r, &st);
92 *size = st.st_size;
93 return mmap(0, st.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd_r, 0);
94}
95
96static void funmap(unsigned char *p, int size, int fd)
97{
98 if (p && size > 0)
99 munmap(p, size);
100 if (fd >= 0)
101 close(fd);
102}
103
jing.zhang1ac869f2022-01-17 16:20:38 +0800104int isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800105static int test_stream(struct audio_stream_out *stream, unsigned char *buf, int size)
106{
107 int ret;
108 int len = size;
109 unsigned char *data = buf;
110
111 ret = stream->common.standby(&stream->common);
112 if (ret) {
113 fprintf(stderr, "%s %d, ret:%x\n",
114 __func__, __LINE__, ret);
115 return -1;
116 }
117
118 ret = stream->set_volume(stream, 1.0f, 1.0f);
119 if (ret) {
120 fprintf(stderr, "%s %d, ret:%x\n", __func__, __LINE__, ret);
121 return -1;
122 }
123
124 while (len > 0) {
125 ssize_t s = stream->write(stream, data, min(len, WRITE_UNIT));
126 if (s < 0) {
127 fprintf(stderr, "stream writing error %d\n", s);
128 break;
129 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800130 if (isstop) {
131 break;
132 }
133 printf("stream writing %d \n", s);
Tim Yao5351d702020-01-20 16:56:42 -0800134 len -= s;
135 data += s;
136 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800137 isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800138 return 0;
139}
140
141static void test_output_stream(audio_hw_device_t *device, unsigned char *buf, int size, struct audio_config *config)
142{
143 struct audio_stream_out *stream;
144 int ret;
145
146 printf("open output speaker...\n");
147 ret = device->open_output_stream(device,
148 0, AUDIO_DEVICE_OUT_SPEAKER,
149 AUDIO_OUTPUT_FLAG_PRIMARY, config,
150 &stream, NULL);
151 if (ret) {
152 printf("fail\n");
153 return;
154 } else {
155 printf("success\n");
156 }
157
158 test_stream(stream, buf, size);
159
160 printf("close output speaker...\n");
161 device->close_output_stream(device, stream);
162}
jing.zhang1ac869f2022-01-17 16:20:38 +0800163void handler_halplay(int sig)
164{
165 isstop=1;
166 while (isstop != 1);
167 printf("\n handler_halplay...\n");
168}
Tim Yao5351d702020-01-20 16:56:42 -0800169int main(int argc, char **argv)
170{
171 audio_hw_device_t *device;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800172 int ret, c = -1, format = FORMAT_MAX, ch = 0, sr = 0, help = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800173 struct audio_config config;
174 const char *fn = NULL;
175 int size = 0;
176 unsigned char *buf;
177 int fd = -1;
178
179 if (argc == 1) {
180 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800181 printf("more param Info: halplay -h\n");
Tim Yao5351d702020-01-20 16:56:42 -0800182 return 0;
183 }
184
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800185 while ((c = getopt(argc, argv, "f:c:r:h")) != -1) {
Tim Yao5351d702020-01-20 16:56:42 -0800186 switch (c) {
187 case 'f':
188 format = atoi(optarg);
189 break;
190 case 'c':
191 ch = atoi(optarg);
192 break;
193 case 'r':
194 sr = atoi(optarg);
195 break;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800196 case 'h':
197 help = 1;
198 break;
Tim Yao5351d702020-01-20 16:56:42 -0800199 case '?':
200 fprintf(stderr, "Error in an argument.\n");
201 return -1;
202 default:
203 return -1;
204 }
205 }
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800206 if (help == 1) {
207 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
208 printf("\n-h, help\n");
209 printf("-f, sample format\n");
210 printf("-c, channels\n");
211 printf("-r, sample rate\n");
wei.wang1476a9fa2023-07-17 06:20:31 +0000212 printf("Recognized sample formats are: 0:PCM16 1:PCM32 2:DD 3:MAT 4:IEC61937 5:AC4 6:MP3 7:AAC 8:OGG 9:FLAC 10:true-hd\n");
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800213 printf("Some of these may not be available on selected format\n");
214 printf("the available params for PCM16 and PCM32 are:\n");
215 printf("-c 1,2,6,8\n");
216 printf("-r 32000,44100,48000\n");
217 return 0;
218 }
Tim Yao5351d702020-01-20 16:56:42 -0800219 if (optind < argc) {
220 fn = argv[optind];
221 }
222
223 if (!fn) {
224 fprintf(stderr, "No file name specified\n");
225 return -1;
226 }
227
228 if ((format < 0) || (format >= FORMAT_MAX)) {
229 int i;
230 fprintf(stderr, "Wrong format, valid format:\n");
231 for (i = 0; i < FORMAT_MAX; i++)
232 fprintf(stderr, "\t%d: %s\n", i, format_str[i]);
233 return -1;
234 }
235
236 if (format_is_pcm(format)) {
237 if ((ch < 1) || (ch > 8)) {
238 fprintf(stderr, "Wrong channel number, valid range [1-8]\n");
239 return -1;
240 }
241 if ((sr != 32000) && (sr != 44100) && (sr != 48000)) {
242 fprintf(stderr, "Invalid sample rate, valid options [32000, 44100, 48000]\n");
243 return -1;
244 }
245 if ((ch != 1) && (ch != 2) && (ch != 6) && (ch != 8)) {
246 fprintf(stderr, "Invalid channel number, valid options [1, 2, 6, 8]\n");
247 return -1;
248 }
249 }
250
251 ret = audio_hw_load_interface(&device);
252 if (ret) {
253 fprintf(stderr, "%s %d error:%d\n", __func__, __LINE__, ret);
254 return ret;
255 }
256 printf("hw version: %x\n", device->common.version);
257 printf("hal api version: %x\n", device->common.module->hal_api_version);
258 printf("module id: %s\n", device->common.module->id);
259 printf("module name: %s\n", device->common.module->name);
260
261 if (device->get_supported_devices) {
262 uint32_t support_dev = 0;
263 support_dev = device->get_supported_devices(device);
264 printf("supported device: %x\n", support_dev);
265 }
266
267 int inited = device->init_check(device);
268 if (inited) {
269 printf("device not inited, quit\n");
270 goto exit;
271 }
272
273 buf = fmap(fn, &size, &fd);
274 if (!buf) {
275 fprintf(stderr, "Error, cannot open input file\n");
276 goto exit;
277 }
278
279 /* set audio config */
280 memset(&config, 0, sizeof(config));
281
shu.zhang0d999582021-07-19 07:51:13 -0400282 switch (format) {
283 case FORMAT_PCM16:
284 case FORMAT_PCM32:
285 config.sample_rate = sr;
286 switch (ch) {
287 case 1:
288 config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
289 break;
290 case 2:
291 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
292 break;
293 case 6:
294 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
295 break;
296 case 8:
297 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
298 break;
299 default:
300 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
301 break;
302 }
303 break;
304
305 case FORMAT_DD:
306 case FORMAT_MAT:
307 case FORMAT_IEC61937:
308 case FORMAT_AC4:
309 config.sample_rate = 48000;
310 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
311 break;
312
313 case FORMAT_MP3:
314 case FORMAT_AAC:
315 case FORMAT_OGG:
316 case FORMAT_FLAC:
317 config.sample_rate = sr;
318 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
319 break;
wei.wang1476a9fa2023-07-17 06:20:31 +0000320 case FORMAT_TRUE_HD:
321 config.sample_rate = sr;
322 switch (ch) {
323 case 8:
324 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
325 break;
326 default:
327 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
328 break;
329 }
330 break;
shu.zhang0d999582021-07-19 07:51:13 -0400331
332 default:
333 break;
Tim Yao5351d702020-01-20 16:56:42 -0800334 }
shu.zhang0d999582021-07-19 07:51:13 -0400335
Tim Yao5351d702020-01-20 16:56:42 -0800336 config.format = format_tab[format];
jing.zhang1ac869f2022-01-17 16:20:38 +0800337 signal(SIGINT, handler_halplay);
Tim Yao5351d702020-01-20 16:56:42 -0800338 test_output_stream(device, buf, size, &config);
339
340 funmap(buf, size, fd);
341
342exit:
343 audio_hw_unload_interface(device);
344 return 0;
345}