Add a simple test application for running the filtering stages on a PC.

This commit is contained in:
George Norton 2023-03-31 16:48:17 +01:00
parent e6ece89049
commit aad64a9b7d
3 changed files with 139 additions and 0 deletions

View File

@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.13)
project(ploopy_headphones_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
add_executable(filter_test
filter_test.c
../code/fix16.c
../code/bqf.c
../code/user.c
)
target_include_directories(filter_test PRIVATE ${CMAKE_SOURCE_DIR}/../code)
# TODO: user.c includes run.h to get the definition for SAMPLING_FREQ, but this
# pulls in the whole pico sdk as a dependency. A little refactoring would fix it all.
target_compile_definitions(filter_test PRIVATE
SAMPLING_FREQ=48000
RUN_H
)
target_link_libraries(filter_test
m
)

23
firmware/test/README.md Normal file
View File

@ -0,0 +1,23 @@
## filter_test
This is a basic utility for testing the Ploopy headphones filtering routines on a PC.
### Usage
Find a source file and use ffmpeg to convert it to PCM data:
```
ffmpeg -i <input file< -map 0:6 -vn -f s16le -acodec pcm_s16le input.pcm
```
Run `filter_test` to process the PCM data. The `filter_test` program takes two arguments an input file and an output file:
```
./filter_test input.pcm output.pcm
```
You can listen to the output audio using ffplay (which is usually included with ffmpeg:
```
./ffplay -f s16le -ar 48000 -ac 2 output.pcm
```
If there are no obvious problems, go ahead and flash your firmware.

View File

@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include "bqf.h"
#include "fix16.h"
#include "user.h"
bqf_coeff_t bqf_filters_left[FILTER_STAGES];
bqf_coeff_t bqf_filters_right[FILTER_STAGES];
bqf_mem_t bqf_filters_mem_left[FILTER_STAGES];
bqf_mem_t bqf_filters_mem_right[FILTER_STAGES];
const char* usage = "Usage: %s INFILE OUTFILE\n\n"
"Reads 16bit stereo PCM data from INFILE, runs it through the Ploopy headphones\n"
"filters then writes it out to OUTFILE.\n";
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stdout, usage, argv[0]);
exit(1);
}
// Load the input data into a buffer
FILE* input = fopen(argv[1], "rb");
if (!input) {
fprintf(stderr, "Cannot open input file '%s'\n", argv[1]);
exit(1);
}
// Get the file size
fseek(input , 0L , SEEK_END);
size_t input_size = ftell(input);
rewind(input);
// Allocate our input and output buffers. This could be optimized
// we dont need to store the whole input and output files in memory.
int samples = input_size / 2;
int16_t *in = (int16_t *) calloc(samples, sizeof(int16_t));
int16_t *out = (int16_t *) calloc(samples, sizeof(int16_t));
fread(in, samples, sizeof(int16_t), input);
fclose(input);
// Open the output file.
FILE* output = fopen(argv[2], "wb");
if (!output)
{
fprintf(stderr, "Cannot open output file '%s'\n", argv[2]);
exit(1);
}
// The smaple proccesing code, essentially the same as the
// code in the firmware's run.c file.
define_filters();
for (int i = 0; i < samples; i++)
{
out[i] = in[i];
}
for (int j = 0; j < FILTER_STAGES; j++)
{
for (int i = 0; i < samples; i ++)
{
// Left channel filter
fix16_t x_f16 = fix16_from_int((int16_t) out[i]);
x_f16 = bqf_transform(x_f16, &bqf_filters_left[j],
&bqf_filters_mem_left[j]);
out[i] = (int32_t) fix16_to_int(x_f16);
// Right channel filter
i++;
x_f16 = fix16_from_int((int16_t) out[i]);
x_f16 = bqf_transform(x_f16, &bqf_filters_right[j],
&bqf_filters_mem_right[j]);
out[i] = (int16_t) fix16_to_int(x_f16);
}
}
// Write out the processed audio.
fwrite(out, samples, sizeof(int16_t), output);
fclose(output);
free(in);
free(out);
}