• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <errno.h>
7 #include <math.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 
17 #include "cras_sbc_codec.h"
18 #include "cras_plc.h"
19 
20 #define MSBC_CODE_SIZE 240
21 #define MSBC_PKT_FRAME_LEN 57
22 #define RND_SEED 7
23 
24 static const uint8_t msbc_zero_frame[] = {
25 	0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 0xb6, 0xdd,
26 	0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6,
27 	0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
28 	0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
29 	0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c
30 };
31 
generate_pl_seq(unsigned pk_count,unsigned loss_count)32 bool *generate_pl_seq(unsigned pk_count, unsigned loss_count)
33 {
34 	bool *seq = (bool *)calloc(pk_count, sizeof(*seq));
35 	srand(RND_SEED);
36 	while (loss_count > 0) {
37 		bool *missed = &seq[rand() % pk_count];
38 		if (!*missed) {
39 			*missed = true;
40 			loss_count--;
41 		}
42 	}
43 	return seq;
44 }
45 
plc_experiment(char * input_filename,float pl_percent,bool with_plc)46 void plc_experiment(char *input_filename, float pl_percent, bool with_plc)
47 {
48 	char output_filename[255];
49 	int input_fd, output_fd, rc;
50 	struct stat st;
51 	bool *pl_seq;
52 	struct cras_audio_codec *msbc_input = cras_msbc_codec_create();
53 	struct cras_audio_codec *msbc_output = cras_msbc_codec_create();
54 	struct cras_msbc_plc *plc = cras_msbc_plc_create();
55 	uint8_t buffer[MSBC_CODE_SIZE], packet_buffer[MSBC_PKT_FRAME_LEN];
56 	size_t encoded, decoded;
57 	unsigned pk_count, pl_count, count = 0;
58 
59 	input_fd = open(input_filename, O_RDONLY);
60 	if (input_fd == -1) {
61 		fprintf(stderr, "Cannout open input file %s\n", input_filename);
62 		return;
63 	}
64 
65 	if (with_plc)
66 		sprintf(output_filename, "output_%2.2f_plc.raw", pl_percent);
67 	else
68 		sprintf(output_filename, "output_%2.2f_zero.raw", pl_percent);
69 
70 	output_fd = open(output_filename, O_CREAT | O_RDWR | O_TRUNC, 0644);
71 	if (output_fd == -1) {
72 		fprintf(stderr, "Cannot open output file %s\n",
73 			output_filename);
74 		return;
75 	}
76 
77 	fstat(input_fd, &st);
78 	pk_count = st.st_size / MSBC_CODE_SIZE;
79 	pl_count = pk_count * (pl_percent / 100.0);
80 	pl_seq = generate_pl_seq(pk_count, pl_count);
81 
82 	while (1) {
83 		rc = read(input_fd, buffer, MSBC_CODE_SIZE);
84 		if (rc < 0) {
85 			fprintf(stderr, "Cannot read file %s", input_filename);
86 			return;
87 		} else if (rc == 0 || rc < MSBC_CODE_SIZE)
88 			break;
89 
90 		msbc_input->encode(msbc_input, buffer, MSBC_CODE_SIZE,
91 				   packet_buffer, MSBC_PKT_FRAME_LEN, &encoded);
92 
93 		if (pl_seq[count]) {
94 			if (with_plc) {
95 				cras_msbc_plc_handle_bad_frames(
96 					plc, msbc_output, buffer);
97 				decoded = MSBC_CODE_SIZE;
98 			} else
99 				msbc_output->decode(msbc_output,
100 						    msbc_zero_frame,
101 						    MSBC_PKT_FRAME_LEN, buffer,
102 						    MSBC_CODE_SIZE, &decoded);
103 		} else {
104 			msbc_output->decode(msbc_output, packet_buffer,
105 					    MSBC_PKT_FRAME_LEN, buffer,
106 					    MSBC_CODE_SIZE, &decoded);
107 			cras_msbc_plc_handle_good_frames(plc, buffer, buffer);
108 		}
109 
110 		count++;
111 		rc = write(output_fd, buffer, decoded);
112 		if (rc < 0) {
113 			fprintf(stderr, "Cannot write file %s\n",
114 				output_filename);
115 			return;
116 		}
117 	}
118 }
119 
main(int argc,char ** argv)120 int main(int argc, char **argv)
121 {
122 	if (argc != 3) {
123 		printf("Usage: cras_plc_test input.raw pl_percentage\n"
124 		       "This test only supports reading/writing files with "
125 		       "format:\n"
126 		       "- raw pcm\n"
127 		       "- 16000 sample rate\n"
128 		       "- mono channel\n"
129 		       "- S16_LE sample format\n");
130 		return 1;
131 	}
132 
133 	plc_experiment(argv[1], atof(argv[2]), true);
134 	plc_experiment(argv[1], atof(argv[2]), false);
135 }
136