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