From dc9225f74d7ccf21301565a09258cceec94d2b2b Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Sat, 9 Nov 2024 14:45:04 +0100 Subject: [PATCH] good for now --- .gitignore | 4 +- Makefile | 2 +- include/audiofile.h | 9 ++++ include/easy.h | 1 + main.py | 70 ++++++++++++++++++++++++++++++ src/audiofile.c | 37 ++++++++++++++++ src/easy.c | 20 ++++++++- src/main.c | 102 ++++++++++++++++++++++++++++++++++++++++---- 8 files changed, 233 insertions(+), 12 deletions(-) create mode 100644 include/audiofile.h create mode 100644 main.py create mode 100644 src/audiofile.c diff --git a/.gitignore b/.gitignore index 01f9cb9..0dee4a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ build/ -.vscode/ \ No newline at end of file +.vscode/ + +*.flac \ No newline at end of file diff --git a/Makefile b/Makefile index ce06b42..d421f8c 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC ?= gcc CFLAGS = -Wall -Wextra -std=gnu17 -I include $(shell pkg-config --cflags lilv-0) -LDFLAGS = -llilv-0 +LDFLAGS = -llilv-0 -lsndfile # Directory for build outputs BUILD_DIR := build diff --git a/include/audiofile.h b/include/audiofile.h new file mode 100644 index 0000000..4bc8e7e --- /dev/null +++ b/include/audiofile.h @@ -0,0 +1,9 @@ +#ifndef AUDIOFILE_H +#define AUDIOFILE_H + +#include + +SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo); +SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info); + +#endif \ No newline at end of file diff --git a/include/easy.h b/include/easy.h index bf15334..4121626 100644 --- a/include/easy.h +++ b/include/easy.h @@ -2,6 +2,7 @@ #define EASY_H #include + const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri); #endif \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..a7a1ed5 --- /dev/null +++ b/main.py @@ -0,0 +1,70 @@ +import lilv, numpy, wave +import soundfile +from ctypes import c_float, c_int + +frames, sample_rate = soundfile.read('a.flac') +num_frames = len(frames) +print(f"{sample_rate}Hz | {int(num_frames/sample_rate/60)}:{int(num_frames/sample_rate%60)}") +print(frames.dtype) +frames = frames.astype(numpy.float32) + +world = lilv.World() +world.load_all() + +plugins = world.get_all_plugins() + +plugin = plugins.get_by_uri("http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo") + +print(plugin.get_name()) + +for i in range(plugin.get_num_ports()): + port = plugin.get_port(i) + print(f"Port {i}: {port.get_name()} = {port.get_range()[0]}") + +instance = lilv.Instance(plugin, sample_rate) + +output_left = numpy.zeros(num_frames, frames.dtype) +output_right = numpy.zeros(num_frames, frames.dtype) + +input_left_chunk = numpy.zeros(512, frames.dtype) +input_right_chunk = numpy.zeros(512, frames.dtype) +output_left_chunk = numpy.zeros(512, frames.dtype) +output_right_chunk = numpy.zeros(512, frames.dtype) + +instance.connect_port(0, input_left_chunk) +instance.connect_port(1, input_right_chunk) +instance.connect_port(2, output_left_chunk) +instance.connect_port(3, output_right_chunk) + +mode_left = numpy.array([2], dtype=numpy.int32) +instance.connect_port(5, mode_left) + +time_left = numpy.array([0.0], dtype=numpy.float32) +instance.connect_port(11, time_left) + +mode_right = numpy.array([2], dtype=numpy.int32) +instance.connect_port(16, mode_right) + +time_right = numpy.array([500.0], dtype=numpy.float32) +instance.connect_port(22, time_right) + +instance.activate() + +print(f"frames: {num_frames}\n") +for start in range(0, num_frames, 512): + end = min(start + 512, num_frames) + chunk_size = end - start + print("\033[F", start, chunk_size, end) + + input_left_chunk[:chunk_size] = frames[start:end, 0] + input_right_chunk[:chunk_size] = frames[start:end, 1] + + instance.run(chunk_size) + + output_left[start:end] = output_left_chunk[:chunk_size] + output_right[start:end] = output_right_chunk[:chunk_size] + +instance.deactivate() + +merged = numpy.column_stack((output_left, output_right)) +soundfile.write('aoutt.flac', merged, sample_rate) \ No newline at end of file diff --git a/src/audiofile.c b/src/audiofile.c new file mode 100644 index 0000000..02379e8 --- /dev/null +++ b/src/audiofile.c @@ -0,0 +1,37 @@ +#include + +SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) { + SNDFILE *sndfile = sf_open(path, SFM_READ, sfinfo); + if (sndfile == NULL) { + fprintf(stderr, "Failed to read audio file: %s\n", sf_strerror(NULL)); + return NULL; + } + + if (sfinfo->channels != 2) { + fprintf(stderr, "File must have 2 channels\n"); + sf_close(sndfile); + return NULL; + } + + int seconds = (double)sfinfo->frames / sfinfo->samplerate; + int minutes = seconds / 60; + printf("Duration: %d:%d\n", minutes, seconds % 60); + printf("Sample rate: %dHz\n\n", sfinfo->samplerate); + + return sndfile; +} + +SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info) { + SF_INFO sfinfo = {0}; + sfinfo.samplerate = og_info->samplerate; + sfinfo.format = og_info->format; + sfinfo.channels = og_info->channels; + + SNDFILE *sndfile = sf_open(path, SFM_WRITE, &sfinfo); + if (sndfile == NULL) { + fprintf(stderr, "Failed to open audio file: %s\n", sf_strerror(NULL)); + return NULL; + } + + return sndfile; +} \ No newline at end of file diff --git a/src/easy.c b/src/easy.c index 093b0f1..7a22c4b 100644 --- a/src/easy.c +++ b/src/easy.c @@ -1,4 +1,4 @@ -#include +#include "easy.h" const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri) { const LilvPlugins* plugin_list = lilv_world_get_all_plugins(world); @@ -11,6 +11,24 @@ const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri) { LilvNode *plugin_name = lilv_plugin_get_name(plugin); printf("Loaded plugin \"%s\"\n", lilv_node_as_string(plugin_name)); lilv_node_free(plugin_name); + + uint32_t n_ports = lilv_plugin_get_num_ports(plugin); + for (uint32_t i = 0; i < n_ports; i++) { + const LilvPort* port = lilv_plugin_get_port_by_index(plugin, i); + // Get port properties + const char* name = lilv_node_as_string(lilv_port_get_name(plugin, port)); + + LilvNode* def = NULL; + lilv_port_get_range(plugin, port, &def, NULL, NULL); + printf("Port %d: %s = %f\n", i, name, lilv_node_as_float(def)); + lilv_node_free(def); + } + + LilvNodes *features = lilv_plugin_get_required_features(plugin); + LILV_FOREACH(nodes, i, features) { + LilvNode *n = lilv_nodes_get(features, i); + printf("Feat: %s\n", lilv_node_as_string(n)); + } } return plugin; diff --git a/src/main.c b/src/main.c index d84925e..db61bf7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,10 @@ -#include -#include #include +#include + +#include "easy.h" +#include "audiofile.h" + +#define BUFFER_SIZE 256 // this is per channel /* http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo @@ -8,13 +12,24 @@ http://lsp-plug.in/plugins/lv2/para_equalizer_x32_lr http://calf.sourceforge.net/plugins/BassEnhancer */ -const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri); - -int main() { - LilvWorld* world = lilv_world_new(); +int main(int argc, char *argv[]) { + LilvWorld *world = lilv_world_new(); lilv_world_load_all(world); + + // load audio file + + SF_INFO sfinfo = {0}; + SNDFILE *sndfile; + if ((sndfile = audiofile_read("a.flac", &sfinfo)) == NULL) { + return 1; + } + + SNDFILE *out_sndfile; + if ((out_sndfile = audiofile_open_for_write("aout.flac", &sfinfo)) == NULL) { + return 1; + } - // + // load lilv plugin const LilvPlugin* plugin = easy_load_plugin(world, "http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo"); if (plugin == NULL) { @@ -22,8 +37,77 @@ int main() { return 1; } - // + // prepare lilv instance - LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL); + LilvInstance *instance = lilv_plugin_instantiate(plugin, sfinfo.samplerate, NULL); + + float input_left[BUFFER_SIZE]; + float input_right[BUFFER_SIZE]; + float output_left[BUFFER_SIZE]; + float output_right[BUFFER_SIZE]; + + lilv_instance_connect_port(instance, 0, input_left); // Input L + lilv_instance_connect_port(instance, 1, input_right); // Input R + lilv_instance_connect_port(instance, 2, output_left); // Output L + lilv_instance_connect_port(instance, 3, output_right); // Output R + + float sc[BUFFER_SIZE] = {0}; + lilv_instance_connect_port(instance, 4, &sc); // Output R + lilv_instance_connect_port(instance, 5, &sc); // Output R + + /*float bypass = 0.0f; + lilv_instance_connect_port(instance, 6, &bypass); + + float aa = 0.0f; + lilv_instance_connect_port(instance, 8, &aa);*/ + + /*int mode_r = 2; + float time_r = 999.0f; // ms + + lilv_instance_connect_port(instance, 5, &mode_r); // Mode Right + lilv_instance_connect_port(instance, 11, &time_r); // Time Right + + float time_dr =1.0f; // ms + lilv_instance_connect_port(instance, 13, &time_dr); // Time Right + + float aa = 0.0f; + lilv_instance_connect_port(instance, 4, &aa);*/ + + lilv_instance_activate(instance); + + // start processing + + printf("Now processing\n"); + + float buffer[BUFFER_SIZE * 2]; + float out_buffer[BUFFER_SIZE * 2]; + int frames_read; + while ((frames_read = sf_readf_float(sndfile, buffer, BUFFER_SIZE))) { + for (sf_count_t i = 0; i < frames_read; i++) { + input_left[i] = buffer[i * 2]; + input_right[i] = buffer[i * 2 + 1]; + } + + lilv_instance_run(instance, frames_read); + + for (sf_count_t i = 0; i < frames_read; i++) { + out_buffer[i * 2] = output_left[i]; + out_buffer[i * 2 + 1] = output_right[i]; + } + + sf_writef_float(out_sndfile, out_buffer, frames_read); + } + + printf("Done processing\n"); + + // end processing + + lilv_instance_deactivate(instance); + lilv_instance_free(instance); + + lilv_world_free(world); + + sf_close(sndfile); + sf_close(out_sndfile); }