good for now
This commit is contained in:
parent
cc6a979294
commit
dc9225f74d
8 changed files with 233 additions and 12 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
|||
build/
|
||||
.vscode/
|
||||
.vscode/
|
||||
|
||||
*.flac
|
2
Makefile
2
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
|
||||
|
|
9
include/audiofile.h
Normal file
9
include/audiofile.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef AUDIOFILE_H
|
||||
#define AUDIOFILE_H
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo);
|
||||
SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info);
|
||||
|
||||
#endif
|
|
@ -2,6 +2,7 @@
|
|||
#define EASY_H
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri);
|
||||
|
||||
#endif
|
70
main.py
Normal file
70
main.py
Normal file
|
@ -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)
|
37
src/audiofile.c
Normal file
37
src/audiofile.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <audiofile.h>
|
||||
|
||||
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;
|
||||
}
|
20
src/easy.c
20
src/easy.c
|
@ -1,4 +1,4 @@
|
|||
#include <easy.h>
|
||||
#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;
|
||||
|
|
102
src/main.c
102
src/main.c
|
@ -1,6 +1,10 @@
|
|||
#include <lilv/lilv.h>
|
||||
#include <easy.h>
|
||||
#include <stdio.h>
|
||||
#include <sndfile.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue