xref: /OK3568_Linux_fs/external/rk_pcba_test/echo_ringmic_pdm_test.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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