blob: efc8ac232a54b53ac844dba93e788bb95c4c0dac [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,
42 FORMAT_MAX
43};
Tim Yao5351d702020-01-20 16:56:42 -080044
shu.zhang0d999582021-07-19 07:51:13 -040045static int format_tab[] = {
46 AUDIO_FORMAT_PCM_16_BIT,
47 AUDIO_FORMAT_PCM_32_BIT,
48 AUDIO_FORMAT_AC3,
49 AUDIO_FORMAT_MAT,
50 AUDIO_FORMAT_IEC61937,
51 AUDIO_FORMAT_AC4,
52 AUDIO_FORMAT_MP3,
53 AUDIO_FORMAT_AAC,
54 AUDIO_FORMAT_VORBIS,
55 AUDIO_FORMAT_FLAC
56};
57
Tim Yao5351d702020-01-20 16:56:42 -080058static const char *format_str[] = {
shu.zhang0d999582021-07-19 07:51:13 -040059 "PCM_16",
60 "PCM_32",
61 "DOLBY DD/DD+",
62 "DOLBY MAT",
63 "IEC_61937",
64 "AC4",
65 "MP3",
66 "AAC",
67 "OGG",
68 "FLAC"
Tim Yao5351d702020-01-20 16:56:42 -080069};
70
71static int format_is_pcm(int format)
72{
73 return (format == FORMAT_PCM16) || (format == FORMAT_PCM32);
74}
75
76static unsigned char *fmap(const char *fn, int *size, int *fd)
77{
78 int fd_r, r;
79 struct stat st;
80 unsigned char *p;
81
82 fd_r = open(fn, O_RDWR);
83
84 if (fd_r < 0)
85 return NULL;
86
87 *fd = fd_r;
88 r = fstat(fd_r, &st);
89 *size = st.st_size;
90 return mmap(0, st.st_size, PROT_READ|PROT_EXEC, MAP_SHARED, fd_r, 0);
91}
92
93static void funmap(unsigned char *p, int size, int fd)
94{
95 if (p && size > 0)
96 munmap(p, size);
97 if (fd >= 0)
98 close(fd);
99}
100
jing.zhang1ac869f2022-01-17 16:20:38 +0800101int isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800102static int test_stream(struct audio_stream_out *stream, unsigned char *buf, int size)
103{
104 int ret;
105 int len = size;
106 unsigned char *data = buf;
107
108 ret = stream->common.standby(&stream->common);
109 if (ret) {
110 fprintf(stderr, "%s %d, ret:%x\n",
111 __func__, __LINE__, ret);
112 return -1;
113 }
114
115 ret = stream->set_volume(stream, 1.0f, 1.0f);
116 if (ret) {
117 fprintf(stderr, "%s %d, ret:%x\n", __func__, __LINE__, ret);
118 return -1;
119 }
120
121 while (len > 0) {
122 ssize_t s = stream->write(stream, data, min(len, WRITE_UNIT));
123 if (s < 0) {
124 fprintf(stderr, "stream writing error %d\n", s);
125 break;
126 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800127 if (isstop) {
128 break;
129 }
130 printf("stream writing %d \n", s);
Tim Yao5351d702020-01-20 16:56:42 -0800131 len -= s;
132 data += s;
133 }
jing.zhang1ac869f2022-01-17 16:20:38 +0800134 isstop = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800135 return 0;
136}
137
138static void test_output_stream(audio_hw_device_t *device, unsigned char *buf, int size, struct audio_config *config)
139{
140 struct audio_stream_out *stream;
141 int ret;
142
143 printf("open output speaker...\n");
144 ret = device->open_output_stream(device,
145 0, AUDIO_DEVICE_OUT_SPEAKER,
146 AUDIO_OUTPUT_FLAG_PRIMARY, config,
147 &stream, NULL);
148 if (ret) {
149 printf("fail\n");
150 return;
151 } else {
152 printf("success\n");
153 }
154
155 test_stream(stream, buf, size);
156
157 printf("close output speaker...\n");
158 device->close_output_stream(device, stream);
159}
jing.zhang1ac869f2022-01-17 16:20:38 +0800160void handler_halplay(int sig)
161{
162 isstop=1;
163 while (isstop != 1);
164 printf("\n handler_halplay...\n");
165}
Tim Yao5351d702020-01-20 16:56:42 -0800166int main(int argc, char **argv)
167{
168 audio_hw_device_t *device;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800169 int ret, c = -1, format = FORMAT_MAX, ch = 0, sr = 0, help = 0;
Tim Yao5351d702020-01-20 16:56:42 -0800170 struct audio_config config;
171 const char *fn = NULL;
172 int size = 0;
173 unsigned char *buf;
174 int fd = -1;
175
176 if (argc == 1) {
177 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800178 printf("more param Info: halplay -h\n");
Tim Yao5351d702020-01-20 16:56:42 -0800179 return 0;
180 }
181
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800182 while ((c = getopt(argc, argv, "f:c:r:h")) != -1) {
Tim Yao5351d702020-01-20 16:56:42 -0800183 switch (c) {
184 case 'f':
185 format = atoi(optarg);
186 break;
187 case 'c':
188 ch = atoi(optarg);
189 break;
190 case 'r':
191 sr = atoi(optarg);
192 break;
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800193 case 'h':
194 help = 1;
195 break;
Tim Yao5351d702020-01-20 16:56:42 -0800196 case '?':
197 fprintf(stderr, "Error in an argument.\n");
198 return -1;
199 default:
200 return -1;
201 }
202 }
zhaopeng.yanb37dff62022-04-28 11:04:30 +0800203 if (help == 1) {
204 printf("Usage: halplay -f <format> -c <channel number> -r <sample rate> <filename>\n");
205 printf("\n-h, help\n");
206 printf("-f, sample format\n");
207 printf("-c, channels\n");
208 printf("-r, sample rate\n");
209 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");
210 printf("Some of these may not be available on selected format\n");
211 printf("the available params for PCM16 and PCM32 are:\n");
212 printf("-c 1,2,6,8\n");
213 printf("-r 32000,44100,48000\n");
214 return 0;
215 }
Tim Yao5351d702020-01-20 16:56:42 -0800216 if (optind < argc) {
217 fn = argv[optind];
218 }
219
220 if (!fn) {
221 fprintf(stderr, "No file name specified\n");
222 return -1;
223 }
224
225 if ((format < 0) || (format >= FORMAT_MAX)) {
226 int i;
227 fprintf(stderr, "Wrong format, valid format:\n");
228 for (i = 0; i < FORMAT_MAX; i++)
229 fprintf(stderr, "\t%d: %s\n", i, format_str[i]);
230 return -1;
231 }
232
233 if (format_is_pcm(format)) {
234 if ((ch < 1) || (ch > 8)) {
235 fprintf(stderr, "Wrong channel number, valid range [1-8]\n");
236 return -1;
237 }
238 if ((sr != 32000) && (sr != 44100) && (sr != 48000)) {
239 fprintf(stderr, "Invalid sample rate, valid options [32000, 44100, 48000]\n");
240 return -1;
241 }
242 if ((ch != 1) && (ch != 2) && (ch != 6) && (ch != 8)) {
243 fprintf(stderr, "Invalid channel number, valid options [1, 2, 6, 8]\n");
244 return -1;
245 }
246 }
247
248 ret = audio_hw_load_interface(&device);
249 if (ret) {
250 fprintf(stderr, "%s %d error:%d\n", __func__, __LINE__, ret);
251 return ret;
252 }
253 printf("hw version: %x\n", device->common.version);
254 printf("hal api version: %x\n", device->common.module->hal_api_version);
255 printf("module id: %s\n", device->common.module->id);
256 printf("module name: %s\n", device->common.module->name);
257
258 if (device->get_supported_devices) {
259 uint32_t support_dev = 0;
260 support_dev = device->get_supported_devices(device);
261 printf("supported device: %x\n", support_dev);
262 }
263
264 int inited = device->init_check(device);
265 if (inited) {
266 printf("device not inited, quit\n");
267 goto exit;
268 }
269
270 buf = fmap(fn, &size, &fd);
271 if (!buf) {
272 fprintf(stderr, "Error, cannot open input file\n");
273 goto exit;
274 }
275
276 /* set audio config */
277 memset(&config, 0, sizeof(config));
278
shu.zhang0d999582021-07-19 07:51:13 -0400279 switch (format) {
280 case FORMAT_PCM16:
281 case FORMAT_PCM32:
282 config.sample_rate = sr;
283 switch (ch) {
284 case 1:
285 config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
286 break;
287 case 2:
288 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
289 break;
290 case 6:
291 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
292 break;
293 case 8:
294 config.channel_mask = AUDIO_CHANNEL_OUT_7POINT1;
295 break;
296 default:
297 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
298 break;
299 }
300 break;
301
302 case FORMAT_DD:
303 case FORMAT_MAT:
304 case FORMAT_IEC61937:
305 case FORMAT_AC4:
306 config.sample_rate = 48000;
307 config.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
308 break;
309
310 case FORMAT_MP3:
311 case FORMAT_AAC:
312 case FORMAT_OGG:
313 case FORMAT_FLAC:
314 config.sample_rate = sr;
315 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
316 break;
317
318 default:
319 break;
Tim Yao5351d702020-01-20 16:56:42 -0800320 }
shu.zhang0d999582021-07-19 07:51:13 -0400321
Tim Yao5351d702020-01-20 16:56:42 -0800322 config.format = format_tab[format];
jing.zhang1ac869f2022-01-17 16:20:38 +0800323 signal(SIGINT, handler_halplay);
Tim Yao5351d702020-01-20 16:56:42 -0800324 test_output_stream(device, buf, size, &config);
325
326 funmap(buf, size, fd);
327
328exit:
329 audio_hw_unload_interface(device);
330 return 0;
331}