Compare commits

..

No commits in common. "9dfb188d8a383272b1f34f471d867887352128a6" and "dc9225f74d7ccf21301565a09258cceec94d2b2b" have entirely different histories.

5 changed files with 81 additions and 109 deletions

View file

@ -1,10 +0,0 @@
LV2 plugins:
- Linux Studio Plugins `lv2-lsp-plugins`
C requirements (headers):
- lilv `liblilv-0-devel`
- sndfile `libsndfile-devel`
Python requirements:
- lilv `python3-lilv` (not on pypi)
- soundfile `python311-SoundFile`

68
main.py
View file

@ -1,11 +1,11 @@
import lilv, numpy, time import lilv, numpy, wave
import soundfile import soundfile
from ctypes import c_float, c_int
CHUNK_SIZE = 1024
frames, sample_rate = soundfile.read('a.flac') frames, sample_rate = soundfile.read('a.flac')
num_frames = len(frames) num_frames = len(frames)
print(f"{sample_rate}Hz | {int(num_frames/sample_rate/60)}:{int(num_frames/sample_rate%60)}") 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) frames = frames.astype(numpy.float32)
world = lilv.World() world = lilv.World()
@ -14,63 +14,57 @@ world.load_all()
plugins = world.get_all_plugins() plugins = world.get_all_plugins()
plugin = plugins.get_by_uri("http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo") plugin = plugins.get_by_uri("http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo")
if plugin is None:
print("No plugin comp_delay_x2_stereo")
exit()
print("Using:", plugin.get_name()) print(plugin.get_name())
for i in range(plugin.get_num_ports()): for i in range(plugin.get_num_ports()):
port = plugin.get_port(i) port = plugin.get_port(i)
#print(f"Port {i}: {port.get_name()} = {port.get_range()[0]}") print(f"Port {i}: {port.get_name()} = {port.get_range()[0]}")
instance = lilv.Instance(plugin, sample_rate) instance = lilv.Instance(plugin, sample_rate)
instance.connect_port(4, numpy.array([1], dtype=numpy.int32)) # while 1 is default it needs to be set as int32 for whatever reason output_left = numpy.zeros(num_frames, frames.dtype)
output_right = numpy.zeros(num_frames, frames.dtype)
knob_mode = numpy.array([2], dtype=numpy.float32) # by the way, this can't be put into connect_port, even if just the number is a variable input_left_chunk = numpy.zeros(512, frames.dtype)
instance.connect_port(16, knob_mode) input_right_chunk = numpy.zeros(512, frames.dtype)
output_left_chunk = numpy.zeros(512, frames.dtype)
knob_time = numpy.array([10.0], dtype=numpy.float32) # but this can?????? it can be any of the three output_right_chunk = numpy.zeros(512, frames.dtype)
instance.connect_port(22, knob_time)
output = numpy.zeros((num_frames, 2), frames.dtype)
input_left_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
input_right_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
output_left_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
output_right_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
instance.connect_port(0, input_left_chunk) instance.connect_port(0, input_left_chunk)
instance.connect_port(1, input_right_chunk) instance.connect_port(1, input_right_chunk)
instance.connect_port(2, output_left_chunk) instance.connect_port(2, output_left_chunk)
instance.connect_port(3, output_right_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() instance.activate()
print(f"\nFrames: {num_frames}") print(f"frames: {num_frames}\n")
print(f"Chunk size: {CHUNK_SIZE}") for start in range(0, num_frames, 512):
print(f"So {int(numpy.ceil(num_frames/CHUNK_SIZE))} iterations\n") end = min(start + 512, num_frames)
for start in range(0, num_frames, CHUNK_SIZE):
end = min(start + CHUNK_SIZE, num_frames)
chunk_size = end - start chunk_size = end - start
print(start, chunk_size, end, " \033[F") print("\033[F", start, chunk_size, end)
input_left_chunk[:chunk_size] = frames[start:end, 0] input_left_chunk[:chunk_size] = frames[start:end, 0]
input_right_chunk[:chunk_size] = frames[start:end, 1] input_right_chunk[:chunk_size] = frames[start:end, 1]
output_left_chunk.fill(0)
output_right_chunk.fill(0)
instance.run(chunk_size) instance.run(chunk_size)
output[start:end, 0] = output_left_chunk[:chunk_size] output_left[start:end] = output_left_chunk[:chunk_size]
output[start:end, 1] = output_right_chunk[:chunk_size] output_right[start:end] = output_right_chunk[:chunk_size]
print("done processing ")
instance.deactivate() instance.deactivate()
if numpy.allclose(frames, output, rtol=0.5, atol=0.5): merged = numpy.column_stack((output_left, output_right))
print("Warning: output is identical") soundfile.write('aoutt.flac', merged, sample_rate)
soundfile.write('aoutt.flac', output, sample_rate)

View file

@ -1,11 +1,9 @@
#include <audiofile.h> #include <audiofile.h>
SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) { SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) {
printf("Input file: \"%s\"\n", path);
SNDFILE *sndfile = sf_open(path, SFM_READ, sfinfo); SNDFILE *sndfile = sf_open(path, SFM_READ, sfinfo);
if (sndfile == NULL) { if (sndfile == NULL) {
fprintf(stderr, "Failed to open audio file: %s\n", sf_strerror(NULL)); fprintf(stderr, "Failed to read audio file: %s\n", sf_strerror(NULL));
return NULL; return NULL;
} }
@ -18,14 +16,12 @@ SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) {
int seconds = (double)sfinfo->frames / sfinfo->samplerate; int seconds = (double)sfinfo->frames / sfinfo->samplerate;
int minutes = seconds / 60; int minutes = seconds / 60;
printf("Duration: %d:%d\n", minutes, seconds % 60); printf("Duration: %d:%d\n", minutes, seconds % 60);
printf("Sample rate: %dHz\n", sfinfo->samplerate); printf("Sample rate: %dHz\n\n", sfinfo->samplerate);
return sndfile; return sndfile;
} }
SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info) { SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info) {
printf("Output file: \"%s\"\n", path);
SF_INFO sfinfo = {0}; SF_INFO sfinfo = {0};
sfinfo.samplerate = og_info->samplerate; sfinfo.samplerate = og_info->samplerate;
sfinfo.format = og_info->format; sfinfo.format = og_info->format;

View file

@ -12,20 +12,22 @@ const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri) {
printf("Loaded plugin \"%s\"\n", lilv_node_as_string(plugin_name)); printf("Loaded plugin \"%s\"\n", lilv_node_as_string(plugin_name));
lilv_node_free(plugin_name); lilv_node_free(plugin_name);
uint32_t nPorts = lilv_plugin_get_num_ports(plugin); uint32_t n_ports = lilv_plugin_get_num_ports(plugin);
for (uint32_t i = 0; i < nPorts; i++) { for (uint32_t i = 0; i < n_ports; i++) {
const LilvPort* port = lilv_plugin_get_port_by_index(plugin, 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 *nameNode = lilv_port_get_name(plugin, port); LilvNode* def = NULL;
const char* name = lilv_node_as_string(nameNode); lilv_port_get_range(plugin, port, &def, NULL, NULL);
lilv_node_free(nameNode); printf("Port %d: %s = %f\n", i, name, lilv_node_as_float(def));
lilv_node_free(def);
}
LilvNode* defNode = NULL; LilvNodes *features = lilv_plugin_get_required_features(plugin);
lilv_port_get_range(plugin, port, &defNode, NULL, NULL); LILV_FOREACH(nodes, i, features) {
float defaultValue = lilv_node_as_float(defNode); LilvNode *n = lilv_nodes_get(features, i);
lilv_node_free(defNode); printf("Feat: %s\n", lilv_node_as_string(n));
printf("Port %d: %s = %f\n", i, name, defaultValue);
} }
} }

View file

@ -1,8 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <sndfile.h> #include <sndfile.h>
#include <string.h>
#include <time.h>
#include "easy.h" #include "easy.h"
#include "audiofile.h" #include "audiofile.h"
@ -16,22 +13,6 @@ http://calf.sourceforge.net/plugins/BassEnhancer
*/ */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s <input> [output]\n", argv[0]);
return 2;
}
char *input_filename = argv[1];
char *output_filename;
if (argc < 3) {
output_filename = malloc((strlen(input_filename) + 4) * sizeof(char));
strcpy(output_filename, "out-");
strcat(output_filename, input_filename);
} else {
output_filename = argv[2];
}
LilvWorld *world = lilv_world_new(); LilvWorld *world = lilv_world_new();
lilv_world_load_all(world); lilv_world_load_all(world);
@ -39,12 +20,12 @@ int main(int argc, char *argv[]) {
SF_INFO sfinfo = {0}; SF_INFO sfinfo = {0};
SNDFILE *sndfile; SNDFILE *sndfile;
if ((sndfile = audiofile_read(input_filename, &sfinfo)) == NULL) { if ((sndfile = audiofile_read("a.flac", &sfinfo)) == NULL) {
return 1; return 1;
} }
SNDFILE *out_sndfile; SNDFILE *out_sndfile;
if ((out_sndfile = audiofile_open_for_write(output_filename, &sfinfo)) == NULL) { if ((out_sndfile = audiofile_open_for_write("aout.flac", &sfinfo)) == NULL) {
return 1; return 1;
} }
@ -60,17 +41,6 @@ int main(int argc, char *argv[]) {
LilvInstance *instance = lilv_plugin_instantiate(plugin, sfinfo.samplerate, NULL); LilvInstance *instance = lilv_plugin_instantiate(plugin, sfinfo.samplerate, NULL);
float knob_enabled = 1;
lilv_instance_connect_port(instance, 4, &knob_enabled);
float knob_mode = 2;
lilv_instance_connect_port(instance, 16, &knob_mode);
float knob_time = 50.0f; // ms
lilv_instance_connect_port(instance, 22, &knob_time);
//
float input_left[BUFFER_SIZE]; float input_left[BUFFER_SIZE];
float input_right[BUFFER_SIZE]; float input_right[BUFFER_SIZE];
float output_left[BUFFER_SIZE]; float output_left[BUFFER_SIZE];
@ -81,34 +51,54 @@ int main(int argc, char *argv[]) {
lilv_instance_connect_port(instance, 2, output_left); // Output L lilv_instance_connect_port(instance, 2, output_left); // Output L
lilv_instance_connect_port(instance, 3, output_right); // Output R lilv_instance_connect_port(instance, 3, output_right); // Output R
// start processing 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); lilv_instance_activate(instance);
printf("Now processing\n");
clock_t start = clock();
float input_buffer[BUFFER_SIZE * 2]; // start processing
float output_buffer[BUFFER_SIZE * 2];
printf("Now processing\n");
float buffer[BUFFER_SIZE * 2];
float out_buffer[BUFFER_SIZE * 2];
int frames_read; int frames_read;
while ((frames_read = sf_readf_float(sndfile, input_buffer, BUFFER_SIZE))) { while ((frames_read = sf_readf_float(sndfile, buffer, BUFFER_SIZE))) {
// a frame is 2 samples and a sample is a number basically and it go left right left right (or how many channels)
for (sf_count_t i = 0; i < frames_read; i++) { for (sf_count_t i = 0; i < frames_read; i++) {
input_left[i] = input_buffer[i * 2]; input_left[i] = buffer[i * 2];
input_right[i] = input_buffer[i * 2 + 1]; input_right[i] = buffer[i * 2 + 1];
} }
lilv_instance_run(instance, frames_read); lilv_instance_run(instance, frames_read);
for (sf_count_t i = 0; i < frames_read; i++) { for (sf_count_t i = 0; i < frames_read; i++) {
output_buffer[i * 2] = output_left[i]; out_buffer[i * 2] = output_left[i];
output_buffer[i * 2 + 1] = output_right[i]; out_buffer[i * 2 + 1] = output_right[i];
} }
sf_writef_float(out_sndfile, output_buffer, frames_read); sf_writef_float(out_sndfile, out_buffer, frames_read);
} }
clock_t end = clock(); printf("Done processing\n");
printf("Done processing. Took %ldns\n", (long)((double)(end - start) / CLOCKS_PER_SEC * 1000000));
// end processing // end processing