blob: 81fd5a1f5fe566024ad25cb6126b0bca0b9698cf [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
*
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdio>
#include <memory>
#include <stdlib.h>
#include <audio_utils/BiquadFilter.h>
#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
using namespace android::audio_utils;
// Random a coefficients here for the test.
static constexpr std::array<float, kBiquadNumCoefs> biquadCoefs = {
0.983097f, -1.966194f, 0.983097f, -1.988931f, 0.988992f};
void printUsage() {
printf("\nUsage:");
printf("\n <executable> -ch:<process_channels> -fch:<file_channels> "
"<input_file> <out_file>");
printf("\nwhere,\n <process_channels> (1 through 8) default 2");
printf("\n <file_channels> (1 through 8) default 2\n");
printf("\n <inputfile> is the input file name");
printf("\n on which filtering is applied");
printf("\n <outputfile> processed output file\n");
}
int main(int argc, const char *argv[]) {
if (argc < 3) {
printUsage();
return EXIT_FAILURE;
}
int fileChannelCount = 2;
int procChannelCount = 2;
if (argc < 3) {
printf("Error: missing input/output files\n");
printUsage();
return EXIT_FAILURE;
}
const char *infile = argv[argc - 2];
const char *outfile = argv[argc - 1];
if (infile == nullptr || outfile == nullptr) {
printf("Error: missing input/output files\n");
printUsage();
return EXIT_FAILURE;
}
printf("%s ", infile);
printf("%s ", outfile);
for (int i = 1; i < argc - 2; i++) {
printf("%s ", argv[i]);
if (!strncmp(argv[i], "-ch:", 4)) {
procChannelCount = atoi(argv[i] + 4);
if (procChannelCount < 1 || procChannelCount > 8) {
printf("\nNumber of channels to process exceeds limit\n");
return EXIT_FAILURE;
}
} else if (!strncmp(argv[i], "-fch:", 5)) {
fileChannelCount = atoi(argv[i] + 5);
if (fileChannelCount < 1 || fileChannelCount > 8) {
printf("\nNumber of channels in the file exceeds limit\n");
return EXIT_FAILURE;
}
}
}
std::unique_ptr<std::FILE, decltype(&std::fclose)> finp(
std::fopen(infile, "rb"), &std::fclose);
if (finp == nullptr) {
printf("Cannot open input file %s\n", infile);
return EXIT_FAILURE;
}
std::unique_ptr<std::FILE, decltype(&std::fclose)> fout(
std::fopen(outfile, "wb"), &std::fclose);
if (fout == nullptr) {
printf("Cannot open output file %s\n", outfile);
fclose(finp.get());
return EXIT_FAILURE;
}
const size_t frameLength = 256;
const int maxChannelCount = std::max(fileChannelCount, procChannelCount);
std::vector<short> in(frameLength * maxChannelCount);
std::vector<short> out(frameLength * maxChannelCount);
std::vector<float> floatIn(frameLength * procChannelCount);
std::vector<float> floatOut(frameLength * procChannelCount);
const size_t ioFrameSize = fileChannelCount * sizeof(short);
BiquadFilter biquadFilter(procChannelCount);
biquadFilter.clear();
biquadFilter.setCoefficients(biquadCoefs);
size_t frameCounter = 0;
while (fread(in.data(), ioFrameSize, frameLength, finp.get()) ==
frameLength) {
if (fileChannelCount != procChannelCount) {
adjust_channels(in.data(), fileChannelCount, in.data(),
procChannelCount, sizeof(short),
frameLength * ioFrameSize);
}
memcpy_to_float_from_i16(floatIn.data(), in.data(),
frameLength * procChannelCount);
biquadFilter.process(floatOut.data(), floatIn.data(), frameLength);
memcpy_to_i16_from_float(out.data(), floatOut.data(),
frameLength * procChannelCount);
frameCounter += frameLength;
adjust_channels(out.data(), procChannelCount, out.data(),
fileChannelCount, sizeof(short),
frameLength * procChannelCount * sizeof(short));
fwrite(out.data(), ioFrameSize, frameLength, fout.get());
}
printf("frameCounter: [%zu]\n", frameCounter);
return EXIT_SUCCESS;
}