• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * 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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * Unless required by applicable law or agreed to in writing, software
10  *
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.
15  */
16 
17 #include <cstdio>
18 #include <memory>
19 
20 #include <stdlib.h>
21 
22 #include <audio_utils/BiquadFilter.h>
23 #include <audio_utils/channels.h>
24 #include <audio_utils/primitives.h>
25 
26 using namespace android::audio_utils;
27 
28 // Random a coefficients here for the test.
29 static constexpr std::array<float, kBiquadNumCoefs> biquadCoefs = {
30         0.983097f, -1.966194f, 0.983097f, -1.988931f, 0.988992f};
31 
printUsage()32 void printUsage() {
33     printf("\nUsage:");
34     printf("\n     <executable> -ch:<process_channels> -fch:<file_channels> "
35         "<input_file> <out_file>");
36     printf("\nwhere,\n     <process_channels> (1 through 8) default 2");
37     printf("\n     <file_channels> (1 through 8) default 2\n");
38     printf("\n     <inputfile>  is the input file name");
39     printf("\n                  on which filtering is applied");
40     printf("\n     <outputfile> processed output file\n");
41 
42 }
43 
main(int argc,const char * argv[])44 int main(int argc, const char *argv[]) {
45 
46     if (argc < 3) {
47         printUsage();
48         return EXIT_FAILURE;
49     }
50 
51     int fileChannelCount = 2;
52     int procChannelCount = 2;
53 
54     if (argc < 3) {
55         printf("Error: missing input/output files\n");
56         printUsage();
57         return EXIT_FAILURE;
58     }
59 
60     const char *infile = argv[argc - 2];
61     const char *outfile = argv[argc - 1];
62 
63     if (infile == nullptr || outfile == nullptr) {
64         printf("Error: missing input/output files\n");
65         printUsage();
66         return EXIT_FAILURE;
67     }
68 
69     printf("%s ", infile);
70     printf("%s ", outfile);
71 
72     for (int i = 1; i < argc - 2; i++) {
73         printf("%s ", argv[i]);
74         if (!strncmp(argv[i], "-ch:", 4)) {
75             procChannelCount = atoi(argv[i] + 4);
76             if (procChannelCount < 1 || procChannelCount > 8) {
77                 printf("\nNumber of channels to process exceeds limit\n");
78                 return EXIT_FAILURE;
79             }
80         } else if (!strncmp(argv[i], "-fch:", 5)) {
81             fileChannelCount = atoi(argv[i] + 5);
82             if (fileChannelCount < 1 || fileChannelCount > 8) {
83                 printf("\nNumber of channels in the file exceeds limit\n");
84                 return EXIT_FAILURE;
85             }
86         }
87     }
88 
89     std::unique_ptr<std::FILE, decltype(&std::fclose)> finp(
90             std::fopen(infile, "rb"), &std::fclose);
91     if (finp == nullptr) {
92         printf("Cannot open input file %s\n", infile);
93         return EXIT_FAILURE;
94     }
95 
96     std::unique_ptr<std::FILE, decltype(&std::fclose)> fout(
97             std::fopen(outfile, "wb"), &std::fclose);
98     if (fout == nullptr) {
99         printf("Cannot open output file %s\n", outfile);
100         fclose(finp.get());
101         return EXIT_FAILURE;
102     }
103 
104     const size_t frameLength = 256;
105     const int maxChannelCount = std::max(fileChannelCount, procChannelCount);
106 
107     std::vector<short> in(frameLength * maxChannelCount);
108     std::vector<short> out(frameLength * maxChannelCount);
109     std::vector<float> floatIn(frameLength * procChannelCount);
110     std::vector<float> floatOut(frameLength * procChannelCount);
111     const size_t ioFrameSize = fileChannelCount * sizeof(short);
112 
113     BiquadFilter biquadFilter(procChannelCount);
114     biquadFilter.clear();
115     biquadFilter.setCoefficients(biquadCoefs);
116 
117     size_t frameCounter = 0;
118 
119     while (fread(in.data(), ioFrameSize, frameLength, finp.get()) ==
120            frameLength) {
121         if (fileChannelCount != procChannelCount) {
122             adjust_channels(in.data(), fileChannelCount, in.data(),
123                             procChannelCount, sizeof(short),
124                             frameLength * ioFrameSize);
125         }
126         memcpy_to_float_from_i16(floatIn.data(), in.data(),
127                                  frameLength * procChannelCount);
128 
129         biquadFilter.process(floatOut.data(), floatIn.data(), frameLength);
130 
131         memcpy_to_i16_from_float(out.data(), floatOut.data(),
132                                  frameLength * procChannelCount);
133         frameCounter += frameLength;
134         adjust_channels(out.data(), procChannelCount, out.data(),
135                         fileChannelCount, sizeof(short),
136                         frameLength * procChannelCount * sizeof(short));
137         fwrite(out.data(), ioFrameSize, frameLength, fout.get());
138     }
139     printf("frameCounter: [%zu]\n", frameCounter);
140 
141     return EXIT_SUCCESS;
142 }
143