blob: ee049e579f25d2db8ce65be4bcf041633a63da9e [file] [log] [blame]
Tim Yao5351d702020-01-20 16:56:42 -08001/*
2 * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <sys/mman.h>
19#include <fcntl.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <unistd.h>
23#include "audio_if.h"
jing.zhang1ac869f2022-01-17 16:20:38 +080024#include <signal.h>
Tim Yao5351d702020-01-20 16:56:42 -080025
26#define min(a, b) ((a) < (b) ? (a) : (b))
27#define WRITE_UNIT 4096
28
shu.zhang0d999582021-07-19 07:51:13 -040029enum audio_format {
30 FORMAT_PCM16 = 0,
31 FORMAT_PCM32,
32 FORMAT_DD,
33 FORMAT_MAT,
34 FORMAT_IEC61937,
35 FORMAT_AC4 = 5,
36 FORMAT_MP3,
37 FORMAT_AAC,
38 FORMAT_OGG,
39 FORMAT_FLAC,
40 FORMAT_MAX
41};
Tim Yao5351d702020-01-20 16:56:42 -080042
shu.zhang0d999582021-07-19 07:51:13 -040043static int format_tab[] = {
44 AUDIO_FORMAT_PCM_16_BIT,
45 AUDIO_FORMAT_PCM_32_BIT,
46 AUDIO_FORMAT_AC3,
47 AUDIO_FORMAT_MAT,
48 AUDIO_FORMAT_IEC61937,
49 AUDIO_FORMAT_AC4,
50 AUDIO_FORMAT_MP3,
51 AUDIO_FORMAT_AAC,
52 AUDIO_FORMAT_VORBIS,
53 AUDIO_FORMAT_FLAC
54};
55
Tim Yao5351d702020-01-20 16:56:42 -080056static const char *format_str[] = {
shu.zhang0d999582021-07-19 07:51:13 -040057 "PCM_16",
58 "PCM_32",
59 "DOLBY DD/DD+",
60 "DOLBY MAT",
61 "IEC_61937",
62 "AC4",
63 "MP3",
64 "AAC",
65 "OGG",
66 "FLAC"
Tim Yao5351d702020-01-20 16:56:42 -080067};
68
69static int format_is_pcm(int format)
70{
71 return (format == FORMAT_PCM16) || (format == FORMAT_PCM32);
72}
73
74static unsigned char *fmap(const char *fn, int *size, int *fd)
75{
76 int fd_r, r;
77 struct stat st;
78 unsigned char *p;
79
80 fd_r = open(fn, O_RDWR);
81
82 if (fd_r < 0)
83 return NULL;
84
85 *fd = fd_r;
86 r = fstat(fd_r, &st);
87 *size = st.st_size;
88 return mmap(0, st.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd_r, 0);
89}
90
91static void funmap(unsigned char *p, int size, int fd)
92{
93 if (p && size > 0)
94 munmap(p, size);
95 if (fd >= 0)
96 close(fd);
97}
98
jing.zhang1ac869f2022-01-17 16:20:38 +080099int isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800100static int test_stream(struct audio_stream_out *stream, unsigned char *buf, int size)
101{
102 int ret;
103 int len = size;
104 unsigned char *data = buf;
105
106 ret = stream->common.standby(&stream->common);
107 if (ret) {
108 fprintf(stderr, "%s %d, ret:%x\n",
109 __func__, __LINE__, ret);
110 return -1;
111 }
112
113 ret = stream->set_volume(stream, 1.0f, 1.0f);
114 if (ret) {
115 fprintf(stderr, "%s %d, ret:%x\n", __func__, __LINE__, ret);
116 return -1;
117 }
118
119 while (len > 0) {
120 ssize_t s = stream->write(stream, data, min(len, WRITE_UNIT));
121 if (s < 0) {
122 fprintf(stderr, "stream writing error %d\n", s);
123 break;
124 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800125 if (isstop) {
126 break;
127 }
128 printf("stream writing %d \n", s);
Tim Yao5351d702020-01-20 16:56:42 -0800129 len -= s;
130 data += s;
131 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800132 isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800133 return 0;
134}
135
136static void test_output_stream(audio_hw_device_t *device, unsigned char *buf, int size, struct audio_config *config)
137{
138 struct audio_stream_out *stream;
139 int ret;
140
141 printf("open output speaker...\n");
142 ret = device->open_output_stream(device,
143 0, AUDIO_DEVICE_OUT_SPEAKER,
144 AUDIO_OUTPUT_FLAG_PRIMARY, config,
145 &stream, NULL);
146 if (ret) {
147 printf("fail\n");
148 return;
149 } else {
150 printf("success\n");
151 }
152
153 test_stream(stream, buf, size);
154
155 printf("close output speaker...\n");
156 device->close_output_stream(device, stream);
157}
jing.zhang1ac869f2022-01-17 16:20:38 +0800158void handler_halplay(int sig)
159{
160 isstop=1;
161 while (isstop != 1);
162 printf("\n handler_halplay...\n");
163}
Tim Yao5351d702020-01-20 16:56:42 -0800164int main(int argc, char **argv)
165{
166 audio_hw_device_t *device;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800167 int ret, c = -1, format = FORMAT_MAX, ch = 0, sr = 0, help = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800168 struct audio_config config;
169 const char *fn = NULL;
170 int size = 0;
171 unsigned char *buf;
172 int fd = -1;
173
174 if (argc == 1) {
175 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800176 printf("more param Info: halplay -h\n");
Tim Yao5351d702020-01-20 16:56:42 -0800177 return 0;
178 }
179
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800180 while ((c = getopt(argc, argv, "f:c:r:h")) != -1) {
Tim Yao5351d702020-01-20 16:56:42 -0800181 switch (c) {
182 case 'f':
183 format = atoi(optarg);
184 break;
185 case 'c':
186 ch = atoi(optarg);
187 break;
188 case 'r':
189 sr = atoi(optarg);
190 break;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800191 case 'h':
192 help = 1;
193 break;
Tim Yao5351d702020-01-20 16:56:42 -0800194 case '?':
195 fprintf(stderr, "Error in an argument.\n");
196 return -1;
197 default:
198 return -1;
199 }
200 }
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800201 if (help == 1) {
202 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
203 printf("\n-h, help\n");
204 printf("-f, sample format\n");
205 printf("-c, channels\n");
206 printf("-r, sample rate\n");
207 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\n");
208 printf("Some of these may not be available on selected format\n");
209 printf("the available params for PCM16 and PCM32 are:\n");
210 printf("-c 1,2,6,8\n");
211 printf("-r 32000,44100,48000\n");
212 return 0;
213 }
Tim Yao5351d702020-01-20 16:56:42 -0800214 if (optind < argc) {
215 fn = argv[optind];
216 }
217
218 if (!fn) {
219 fprintf(stderr, "No file name specified\n");
220 return -1;
221 }
222
223 if ((format < 0) || (format >= FORMAT_MAX)) {
224 int i;
225 fprintf(stderr, "Wrong format, valid format:\n");
226 for (i = 0; i < FORMAT_MAX; i++)
227 fprintf(stderr, "\t%d: %s\n", i, format_str[i]);
228 return -1;
229 }
230
231 if (format_is_pcm(format)) {
232 if ((ch < 1) || (ch > 8)) {
233 fprintf(stderr, "Wrong channel number, valid range [1-8]\n");
234 return -1;
235 }
236 if ((sr != 32000) && (sr != 44100) && (sr != 48000)) {
237 fprintf(stderr, "Invalid sample rate, valid options [32000, 44100, 48000]\n");
238 return -1;
239 }
240 if ((ch != 1) && (ch != 2) && (ch != 6) && (ch != 8)) {
241 fprintf(stderr, "Invalid channel number, valid options [1, 2, 6, 8]\n");
242 return -1;
243 }
244 }
245
246 ret = audio_hw_load_interface(&device);
247 if (ret) {
248 fprintf(stderr, "%s %d error:%d\n", __func__, __LINE__, ret);
249 return ret;
250 }
251 printf("hw version: %x\n", device->common.version);
252 printf("hal api version: %x\n", device->common.module->hal_api_version);
253 printf("module id: %s\n", device->common.module->id);
254 printf("module name: %s\n", device->common.module->name);
255
256 if (device->get_supported_devices) {
257 uint32_t support_dev = 0;
258 support_dev = device->get_supported_devices(device);
259 printf("supported device: %x\n", support_dev);
260 }
261
262 int inited = device->init_check(device);
263 if (inited) {
264 printf("device not inited, quit\n");
265 goto exit;
266 }
267
268 buf = fmap(fn, &size, &fd);
269 if (!buf) {
270 fprintf(stderr, "Error, cannot open input file\n");
271 goto exit;
272 }
273
274 /* set audio config */
275 memset(&config, 0, sizeof(config));
276
shu.zhang0d999582021-07-19 07:51:13 -0400277 switch (format) {
278 case FORMAT_PCM16:
279 case FORMAT_PCM32:
280 config.sample_rate = sr;
281 switch (ch) {
282 case 1:
283 config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
284 break;
285 case 2:
286 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
287 break;
288 case 6:
289 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
290 break;
291 case 8:
292 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
293 break;
294 default:
295 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
296 break;
297 }
298 break;
299
300 case FORMAT_DD:
301 case FORMAT_MAT:
302 case FORMAT_IEC61937:
303 case FORMAT_AC4:
304 config.sample_rate = 48000;
305 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
306 break;
307
308 case FORMAT_MP3:
309 case FORMAT_AAC:
310 case FORMAT_OGG:
311 case FORMAT_FLAC:
312 config.sample_rate = sr;
313 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
314 break;
315
316 default:
317 break;
Tim Yao5351d702020-01-20 16:56:42 -0800318 }
shu.zhang0d999582021-07-19 07:51:13 -0400319
Tim Yao5351d702020-01-20 16:56:42 -0800320 config.format = format_tab[format];
jing.zhang1ac869f2022-01-17 16:20:38 +0800321 signal(SIGINT, handler_halplay);
Tim Yao5351d702020-01-20 16:56:42 -0800322 test_output_stream(device, buf, size, &config);
323
324 funmap(buf, size, fd);
325
326exit:
327 audio_hw_unload_interface(device);
328 return 0;
329}