blob: b8f601197a2ba3cd9288bed4cddfc19abe7c8aa7 [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;
167 int ret, c = -1, format = FORMAT_MAX, ch = 0, sr = 0;
168 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");
Tim Yao5351d702020-01-20 16:56:42 -0800176 return 0;
177 }
178
179 while ((c = getopt(argc, argv, "f:c:r:")) != -1) {
180 switch (c) {
181 case 'f':
182 format = atoi(optarg);
183 break;
184 case 'c':
185 ch = atoi(optarg);
186 break;
187 case 'r':
188 sr = atoi(optarg);
189 break;
190 case '?':
191 fprintf(stderr, "Error in an argument.\n");
192 return -1;
193 default:
194 return -1;
195 }
196 }
197
198 if (optind < argc) {
199 fn = argv[optind];
200 }
201
202 if (!fn) {
203 fprintf(stderr, "No file name specified\n");
204 return -1;
205 }
206
207 if ((format < 0) || (format >= FORMAT_MAX)) {
208 int i;
209 fprintf(stderr, "Wrong format, valid format:\n");
210 for (i = 0; i < FORMAT_MAX; i++)
211 fprintf(stderr, "\t%d: %s\n", i, format_str[i]);
212 return -1;
213 }
214
215 if (format_is_pcm(format)) {
216 if ((ch < 1) || (ch > 8)) {
217 fprintf(stderr, "Wrong channel number, valid range [1-8]\n");
218 return -1;
219 }
220 if ((sr != 32000) && (sr != 44100) && (sr != 48000)) {
221 fprintf(stderr, "Invalid sample rate, valid options [32000, 44100, 48000]\n");
222 return -1;
223 }
224 if ((ch != 1) && (ch != 2) && (ch != 6) && (ch != 8)) {
225 fprintf(stderr, "Invalid channel number, valid options [1, 2, 6, 8]\n");
226 return -1;
227 }
228 }
229
230 ret = audio_hw_load_interface(&device);
231 if (ret) {
232 fprintf(stderr, "%s %d error:%d\n", __func__, __LINE__, ret);
233 return ret;
234 }
235 printf("hw version: %x\n", device->common.version);
236 printf("hal api version: %x\n", device->common.module->hal_api_version);
237 printf("module id: %s\n", device->common.module->id);
238 printf("module name: %s\n", device->common.module->name);
239
240 if (device->get_supported_devices) {
241 uint32_t support_dev = 0;
242 support_dev = device->get_supported_devices(device);
243 printf("supported device: %x\n", support_dev);
244 }
245
246 int inited = device->init_check(device);
247 if (inited) {
248 printf("device not inited, quit\n");
249 goto exit;
250 }
251
252 buf = fmap(fn, &size, &fd);
253 if (!buf) {
254 fprintf(stderr, "Error, cannot open input file\n");
255 goto exit;
256 }
257
258 /* set audio config */
259 memset(&config, 0, sizeof(config));
260
shu.zhang0d999582021-07-19 07:51:13 -0400261 switch (format) {
262 case FORMAT_PCM16:
263 case FORMAT_PCM32:
264 config.sample_rate = sr;
265 switch (ch) {
266 case 1:
267 config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
268 break;
269 case 2:
270 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
271 break;
272 case 6:
273 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
274 break;
275 case 8:
276 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
277 break;
278 default:
279 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
280 break;
281 }
282 break;
283
284 case FORMAT_DD:
285 case FORMAT_MAT:
286 case FORMAT_IEC61937:
287 case FORMAT_AC4:
288 config.sample_rate = 48000;
289 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
290 break;
291
292 case FORMAT_MP3:
293 case FORMAT_AAC:
294 case FORMAT_OGG:
295 case FORMAT_FLAC:
296 config.sample_rate = sr;
297 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
298 break;
299
300 default:
301 break;
Tim Yao5351d702020-01-20 16:56:42 -0800302 }
shu.zhang0d999582021-07-19 07:51:13 -0400303
Tim Yao5351d702020-01-20 16:56:42 -0800304 config.format = format_tab[format];
jing.zhang1ac869f2022-01-17 16:20:38 +0800305 signal(SIGINT, handler_halplay);
Tim Yao5351d702020-01-20 16:56:42 -0800306 test_output_stream(device, buf, size, &config);
307
308 funmap(buf, size, fd);
309
310exit:
311 audio_hw_unload_interface(device);
312 return 0;
313}