1 /*
2 * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 /* flytek ringmic test require:
8 * 1. recored more than 10 seconds
9 * 2. start play before recording, stop record before stop playing
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <signal.h>
20 #include "mic_test_Linux/vibrate_test.h"
21 #include "mic_test_Linux/record_test.h"
22
23 #define LOG_TAG "echo_ringmic_test"
24 #include "common.h"
25
26 #define AUDIO_CHANNAL_CNT 8
27 #define RINGMIC_BAD_ERROR 93 /* has bad mic */
28
29 #define DEBUG_ON 0
30 #if DEBUG_ON
31 #define FLAGS O_WRONLY | O_CREAT | O_TRUNC
32 #define MODE S_IRWXU | S_IXGRP | S_IROTH | S_IXOTH
save_audio_file(char * path,char * buff,int len)33 void save_audio_file(char *path, char *buff, int len)
34 {
35 int fd = 0;
36 int ret = 0;
37 char shell_cmd[200] = {0};
38 sprintf(shell_cmd, "rm -rf %s", path);
39 system(shell_cmd);
40 if ((fd = open(path, FLAGS, MODE)) == -1) {
41 log_err("%s Create %s failed, %s\n", __func__,
42 path, strerror(errno));
43 return;
44 }
45 ret = write(fd, buff, len);
46 if (ret != len) {
47 log_err("%s Write %s failed, %s\n", __func__,
48 path, strerror(errno));
49 return;
50 }
51 log_info("%s file Saved successfully!\n", path);
52 close(fd);
53 return;
54 }
55 #else
56 void save_audio_file(char *paht, char *buff, int len);
57 #endif
58
bytesToInt(char * src,int * length)59 int *bytesToInt(char *src, int *length)
60 {
61 int value = 0, offset = 0, i = 0;
62 int *ret = NULL;
63 int int_len = 0;
64
65 int_len = (*length / 4) + 1;
66 ret = (int *)malloc(int_len * 4);
67 if (!ret)
68 return NULL;
69
70 while ((offset < *length) && (*length - offset >= 4)) {
71 value = (int)((src[offset] & 0xFF) |
72 ((src[offset + 1] & 0xFF) << 8) |
73 ((src[offset + 2] & 0xFF) << 16) |
74 ((src[offset + 3] & 0xFF) << 24));
75 offset += 4;
76 ret[i++] = value;
77 }
78
79 *length = int_len;
80 return ret;
81 }
linear_amplification(void * data,void * out,int bytes)82 int linear_amplification(void *data, void *out, int bytes)
83 {
84 int i = 0, j = 0;
85 int mChannels = AUDIO_CHANNAL_CNT;
86 for (i = 0; i < bytes / 2; ) {
87 for (j = 0; j < mChannels; j++) {
88 short raw = (*((short *)data + i + j));
89 int tmp_data = (int)raw;
90 #if 1
91 tmp_data = tmp_data << 4;
92 if(tmp_data > 32767) {
93 tmp_data = 32767;
94 } else if(tmp_data < -32768) {
95 tmp_data = -32768;
96 }
97 #endif
98 *((short *)out + i + j) = (short)tmp_data;
99 }
100 i += mChannels;
101 }
102 return 0;
103 }
104
linear_amplification4(void * data,void * out,int bytes)105 int linear_amplification4(void *data, void *out, int bytes)
106 {
107 int i = 0, j = 0;
108 int mChannels = AUDIO_CHANNAL_CNT;
109 for (i = 0; i < bytes / 2; ) {
110 for (j = 0; j < mChannels; j++) {
111 short raw = (*((short *)data + i + j));
112 int tmp_data = (int)raw;
113 #if 1
114 tmp_data = tmp_data << 4;
115 if(tmp_data > 32767) {
116 tmp_data = 32767;
117 } else if(tmp_data < -32768) {
118 tmp_data = -32768;
119 }
120 #endif
121 *((short *)out + i + j) = (short)tmp_data;
122 }
123 i += mChannels;
124 }
125 return 0;
126 }
127
128
linear_amplification5(void * data,void * out,int bytes)129 int linear_amplification5(void *data, void *out, int bytes)
130 {
131 int i = 0, j = 0;
132 int mChannels = AUDIO_CHANNAL_CNT;
133 for (i = 0; i < bytes / 2; ) {
134 for (j = 0; j < mChannels; j++) {
135 short raw = (*((short *)data + i + j));
136 int tmp_data = (int)raw;
137 #if 1
138 tmp_data = tmp_data << 6;
139 if(tmp_data > 32767) {
140 tmp_data = 32767;
141 } else if(tmp_data < -32768) {
142 tmp_data = -32768;
143 }
144 #endif
145 *((short *)out + i + j) = (short)tmp_data;
146 }
147 i += mChannels;
148 }
149 return 0;
150 }
151
152
preProcessBuffer(void * data,void * out,int bytes)153 int preProcessBuffer(void *data, void *out, int bytes)
154 {
155 int i = 0, j = 0;
156
157 for (i = 0; i < bytes / 2 ; ) {
158 for (j = 0; j < AUDIO_CHANNAL_CNT; j++) {
159 int tmp = 0;
160 short tmp_data = (*((short *)data + i + j));
161 tmp = ((tmp_data) << 16 | ((j+1) << 8)) & 0xffffff00;
162 *((int *)out + i + j) = tmp;
163 }
164 i += AUDIO_CHANNAL_CNT;
165 }
166
167 return 0;
168 }
169
add_channel(char * src,char ** dst,int len)170 static int add_channel(char *src, char **dst, int len)
171 {
172 int fd = 0;
173 int dst_len = 0;
174 int ret = 0;
175
176 dst_len = len * 2;
177 *dst = (char *)malloc(dst_len);
178 if (!*dst)
179 return -ENOMEM;
180
181 preProcessBuffer(src, *dst, len);
182
183 return dst_len;
184 }
185 /*
186 * This function includes a ring mic recording test
187 * and vibration test, select the test type by flag.
188 * flag = 0:ring mic record test.
189 * flag = 1:ring mic vibration test.
190 */
ringmic_test(char * result,int flag)191 int ringmic_test(char *result, int flag)
192 {
193 int *record_ret = NULL;
194 int fd = 0;
195 int rf_len = 0; /* record file length */
196 int pre_len = 0;
197 char *rf_buff = NULL; /* record file buffer */
198 char *pre_buff = NULL;
199 char *gain_buff = NULL;
200 int *buffer = NULL;
201 char path[128] = {0};
202 int ret = 0, i = 0;
203
204 /*
205 * According to flag choose to perform "recording test"
206 * or "vibration test". recording at least 10 seconds.
207 */
208 if (flag) {
209 log_info("Start vibration test.\n");
210 sprintf(path, "%s", "/tmp/ringmic_vibration.pcm");
211 /* Play the specified file, and recording. */
212 system("killall -9 arecord");
213 system("rm /tmp/ringmic_vibration.pcm");
214 system("aplay /data/vibration.wav &");
215 usleep(200000);
216 system("arecord -D hw:0,0 -t raw -f S16_LE -c 8 -r 16000 -d 15 /tmp/ringmic_vibration.pcm");
217 } else {
218 log_info("Start record test.\n");
219 sprintf(path, "%s", "/tmp/ringmic_record.pcm");
220 /* Play the specified file, and recording. */
221 system("killall -9 arecord");
222 system("rm /tmp/ringmic_record.pcm");
223 system("aplay /data/rectest_400hz.wav &");
224 usleep(200000);
225 system("arecord -D hw:0,0 -t raw -f S16_LE -c 8 -r 16000 -d 15 /tmp/ringmic_record.pcm");
226 }
227 system("killall -9 arecord");
228 system("killall aplay");
229
230 log_info("Parsing audio file...\n");
231 fd = open(path, O_RDONLY);
232 if (fd <= 0) {
233 log_err("open %s failed(%s).\n", path, strerror(errno));
234 return errno;
235 }
236 /* get length of the record file. */
237 rf_len = lseek(fd, 0, SEEK_END);
238 rf_buff = (char *)malloc(rf_len);
239 if (!rf_buff) {
240 close(fd);
241 return -ENOMEM;
242 }
243 memset(rf_buff, 0, rf_len);
244 /* Read from the beginning of the file. */
245 lseek(fd, 0, SEEK_SET);
246 ret = read(fd, rf_buff, rf_len);
247 if (ret != rf_len) {
248 log_err("read %s failed(%s).\n", path, strerror(errno));
249 close(fd);
250 free(rf_buff);
251 return errno;
252 }
253 close(fd);
254
255 /* Increase gain */
256 gain_buff = (char *)malloc(rf_len);
257 if (!gain_buff) {
258 close(fd);
259 free(rf_buff);
260 return -ENOMEM;
261 }
262 memset(gain_buff, 0, rf_len);
263
264 if (flag) //vibration
265 linear_amplification4(rf_buff, gain_buff, rf_len);
266 else //record
267 linear_amplification5(rf_buff, gain_buff, rf_len);
268
269 memcpy(rf_buff, gain_buff, rf_len);
270 free(gain_buff);
271 FILE *fp;
272 if (flag)
273 fp = fopen("/tmp/gain-vib.pcm", "wb");
274 else
275 fp = fopen("/tmp/gain-rec.pcm", "wb");
276 if (fp) {
277 fwrite(rf_buff, 1, rf_len, fp);
278 fclose(fp);
279 }
280
281 /* Add channel numbers to the original recording file */
282 pre_len = add_channel(rf_buff, &pre_buff, rf_len);
283 if (pre_len < 0) {
284 free(rf_buff);
285 return pre_len;
286 }
287 free(rf_buff);
288
289 if (flag)
290 fp = fopen("/tmp/addchan-vib.pcm", "wb");
291 else
292 fp = fopen("/tmp/addchan-rec.pcm", "wb");
293 if (fp) {
294 fwrite(pre_buff, 1, pre_len, fp);
295 fclose(fp);
296 }
297
298 #if 0
299 buffer = (int *)pre_buffer;
300 pre_len = (pre_len / 4);
301 #else
302 buffer = bytesToInt(pre_buff, &pre_len);
303 if (!buffer) {
304 log_err("bytesToInt() failed!\n");
305 free(pre_buff);
306 return -ENOMEM;
307 }
308 free(pre_buff);
309
310 if (flag)
311 fp = fopen("/tmp/bytesToInt-vib.pcm", "wb");
312 else
313 fp = fopen("/tmp/bytesToInt-rec.pcm", "wb");
314 if (fp) {
315 fwrite((int *)buffer+16000, 4, pre_len - 32000, fp);
316 fclose(fp);
317 }
318 #endif
319
320 /* Call library interface */
321 if (!flag) {
322 record_ret = recordTestWr((int *)buffer + 16000, pre_len - 32000);
323 printf("\n");
324 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
325 if (*(record_ret + i)) {
326 log_info("recordTest:#%d mic is bad!\n", i);
327 *result++ = 1;
328 } else {
329 log_info("recordTest:#%d mic is ok!\n", i);
330 *result++ = 0;
331 }
332 }
333
334 system("rm -rf /tmp/ringmic_record.pcm");
335 } else {
336 record_ret = vibrateTestWr((int *)buffer + 16000, pre_len - 32000);
337 printf("\n");
338 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
339 if (*(record_ret + i)) {
340 log_info("vibrationTest:#%d mic is bad!\n", i);
341 *result++ = 1;
342 } else {
343 log_info("vibrationTest:#%d mic is ok!\n", i);
344 *result++ = 0;
345 }
346 }
347
348 system("rm -rf /data/ringmic_vibration.pcm");
349 }
350
351 free(buffer);
352 return 0;
353 }
354
main()355 int main()
356 {
357 char buf[COMMAND_VALUESIZE] = {0};
358 char result[COMMAND_VALUESIZE] = RESULT_PASS;
359 unsigned char record_ret[AUDIO_CHANNAL_CNT] = {0};
360 unsigned char vibration_ret[AUDIO_CHANNAL_CNT] = {0};
361 char *start = NULL;
362 int ispass = 1;
363 int i = 0, ret = 0;
364
365 system("amixer set Master Playback 50%");
366
367 start = buf;
368 memcpy(start, "vibration:", strlen("vibration:"));
369 start = start + strlen("vibration:");
370 ret = ringmic_test(vibration_ret, 1);
371 if (ret) {
372 memcpy(start, "error", strlen("error"));
373 start += strlen("error");
374 ispass = 0;
375 } else {
376 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
377 if (vibration_ret[i]) {
378 ispass = 0;
379 *(start++) = '1' + i;
380 }
381 }
382 }
383 *start++ = ';';
384 sleep(1);
385
386 memcpy(start, "record:", strlen("record:"));
387 start = start + strlen("record:");
388 ret = ringmic_test(record_ret, 0);
389 if (ret) {
390 memcpy(start, "error", strlen("error"));
391 start += strlen("error");
392 strcpy(result, RESULT_FAIL);
393 ispass = 0;
394 } else {
395 for (i = 0; i < AUDIO_CHANNAL_CNT; i++) {
396 if (record_ret[i]) {
397 ispass = 0;
398 *(start++) = '1' + i;
399 *start++ = ' ';
400 }
401 }
402 }
403 *start++ = ';';
404
405 if (!ispass) {
406 strcpy(result, RESULT_FAIL);
407 ret = -RINGMIC_BAD_ERROR;
408 }
409
410 send_msg_to_server(buf, result, ret);
411 return 0;
412 }
413