Do whatever
This commit is contained in:
parent
969f31569e
commit
60ef2dc0be
14 changed files with 513 additions and 195 deletions
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef EASY_H
|
||||
#define EASY_H
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri);
|
||||
|
||||
#endif
|
||||
8
include/plugin.h
Normal file
8
include/plugin.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef PLUGIN_H
|
||||
#define PLUGIN_H
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
const LilvPlugin* load_plugin(LilvWorld *world, const LilvPlugins *plugins, const char *uri);
|
||||
|
||||
#endif
|
||||
11
include_old/audiofile.h
Normal file
11
include_old/audiofile.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef AUDIOFILE_H
|
||||
#define AUDIOFILE_H
|
||||
|
||||
#include <sndfile.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo);
|
||||
SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info);
|
||||
int audiofile_copy_metadata(SNDFILE *source, SNDFILE *target);
|
||||
|
||||
#endif
|
||||
10
include_old/instances.h
Normal file
10
include_old/instances.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef INSTANCES_H
|
||||
#define INSTANCES_H
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
#include "plugin.h"
|
||||
|
||||
LilvInstance *create_bass_enhancer_instance(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right);
|
||||
LilvInstance *create_delay_instance(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right);
|
||||
|
||||
#endif
|
||||
8
include_old/plugin.h
Normal file
8
include_old/plugin.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef EASY_H
|
||||
#define EASY_H
|
||||
|
||||
#include <lilv/lilv.h>
|
||||
|
||||
const LilvPlugin* load_plugin(LilvWorld* world, const char* uri);
|
||||
|
||||
#endif
|
||||
111
main.py
111
main.py
|
|
@ -3,74 +3,85 @@ import soundfile
|
|||
|
||||
CHUNK_SIZE = 1024
|
||||
|
||||
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)}")
|
||||
frames = frames.astype(numpy.float32)
|
||||
def create_delay_instance(plugins, frames, sample_rate,
|
||||
input_left, input_right,
|
||||
output_left, output_right) -> lilv.Instance:
|
||||
plugin = plugins.get_by_uri("http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo")
|
||||
if plugin is None:
|
||||
raise Exception("Plugin comp_delay_x2_stereo not found")
|
||||
|
||||
world = lilv.World()
|
||||
world.load_all()
|
||||
print("Using:", plugin.get_name())
|
||||
|
||||
plugins = world.get_all_plugins()
|
||||
for i in range(plugin.get_num_ports()):
|
||||
port = plugin.get_port(i)
|
||||
#print(f"Port {i}: {port.get_name()} = {port.get_range()[0]}")
|
||||
|
||||
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()
|
||||
instance = lilv.Instance(plugin, sample_rate)
|
||||
|
||||
print("Using:", plugin.get_name())
|
||||
instance.connect_port(4, numpy.array([1], dtype=numpy.float32)) # while 1 is default it needs to be set as int32 for whatever reason
|
||||
|
||||
for i in range(plugin.get_num_ports()):
|
||||
port = plugin.get_port(i)
|
||||
#print(f"Port {i}: {port.get_name()} = {port.get_range()[0]}")
|
||||
knob_mode = numpy.array([2], dtype=numpy.float32)
|
||||
instance.connect_port(16, knob_mode)
|
||||
|
||||
instance = lilv.Instance(plugin, sample_rate)
|
||||
knob_time = numpy.array([100.0], dtype=numpy.float32)
|
||||
instance.connect_port(22, knob_time)
|
||||
|
||||
instance.connect_port(4, numpy.array([1], dtype=numpy.int32)) # while 1 is default it needs to be set as int32 for whatever reason
|
||||
instance.connect_port(0, input_left)
|
||||
instance.connect_port(1, input_right)
|
||||
instance.connect_port(2, output_left)
|
||||
instance.connect_port(3, output_right)
|
||||
|
||||
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
|
||||
instance.connect_port(16, knob_mode)
|
||||
return instance
|
||||
|
||||
knob_time = numpy.array([10.0], dtype=numpy.float32) # but this can?????? it can be any of the three
|
||||
instance.connect_port(22, knob_time)
|
||||
def main():
|
||||
frames, sample_rate = soundfile.read('source.flac')
|
||||
num_frames = len(frames)
|
||||
print(f"{sample_rate}Hz | {int(num_frames/sample_rate/60)}:{int(num_frames/sample_rate%60)}")
|
||||
frames = frames.astype(numpy.float32)
|
||||
|
||||
output = numpy.zeros((num_frames, 2), frames.dtype)
|
||||
world = lilv.World()
|
||||
world.load_all()
|
||||
|
||||
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)
|
||||
plugins = world.get_all_plugins()
|
||||
|
||||
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)
|
||||
input_left_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
|
||||
input_right_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
|
||||
|
||||
instance.activate()
|
||||
output_left_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
|
||||
output_right_chunk = numpy.zeros(CHUNK_SIZE, frames.dtype)
|
||||
|
||||
print(f"\nFrames: {num_frames}")
|
||||
print(f"Chunk size: {CHUNK_SIZE}")
|
||||
print(f"So {int(numpy.ceil(num_frames/CHUNK_SIZE))} iterations\n")
|
||||
instance = create_delay_instance(plugins, frames, sample_rate, input_left_chunk, input_right_chunk, output_left_chunk, output_right_chunk)
|
||||
|
||||
for start in range(0, num_frames, CHUNK_SIZE):
|
||||
end = min(start + CHUNK_SIZE, num_frames)
|
||||
chunk_size = end - start
|
||||
print(start, chunk_size, end, " \033[F")
|
||||
instance.activate()
|
||||
|
||||
input_left_chunk[:chunk_size] = frames[start:end, 0]
|
||||
input_right_chunk[:chunk_size] = frames[start:end, 1]
|
||||
output_left_chunk.fill(0)
|
||||
output_right_chunk.fill(0)
|
||||
print(f"\nFrames: {num_frames}")
|
||||
print(f"Chunk size: {CHUNK_SIZE}")
|
||||
print(f"We will perform {int(numpy.ceil(num_frames/CHUNK_SIZE))} iterations\n")
|
||||
|
||||
instance.run(chunk_size)
|
||||
output_total = numpy.zeros_like(frames)
|
||||
|
||||
output[start:end, 0] = output_left_chunk[:chunk_size]
|
||||
output[start:end, 1] = output_right_chunk[:chunk_size]
|
||||
for start in range(0, num_frames, CHUNK_SIZE):
|
||||
end = min(start + CHUNK_SIZE, num_frames)
|
||||
chunk_size = end - start
|
||||
print(start, chunk_size, end, " \033[F")
|
||||
|
||||
print("done processing ")
|
||||
instance.deactivate()
|
||||
input_left_chunk[:chunk_size] = frames[start:end, 0]
|
||||
input_right_chunk[:chunk_size] = frames[start:end, 1]
|
||||
output_left_chunk.fill(0)
|
||||
output_right_chunk.fill(0)
|
||||
|
||||
if numpy.allclose(frames, output, rtol=0.5, atol=0.5):
|
||||
print("Warning: output is identical")
|
||||
instance.run(chunk_size)
|
||||
|
||||
soundfile.write('aoutt.flac', output, sample_rate)
|
||||
output_total[start:end, 0] = output_left_chunk[:chunk_size]
|
||||
output_total[start:end, 1] = output_right_chunk[:chunk_size]
|
||||
|
||||
print("done processing ")
|
||||
instance.deactivate()
|
||||
|
||||
if numpy.allclose(frames, output_total, rtol=0.5, atol=0.5):
|
||||
print("Warning: output is identical")
|
||||
|
||||
soundfile.write('aoutt.flac', output_total, sample_rate)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include <audiofile.h>
|
||||
#include "audiofile.h"
|
||||
|
||||
SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) {
|
||||
printf("Input file: \"%s\"\n", path);
|
||||
|
|
|
|||
40
src/easy.c
40
src/easy.c
|
|
@ -1,40 +0,0 @@
|
|||
#include "easy.h"
|
||||
|
||||
const LilvPlugin* easy_load_plugin(LilvWorld* world, const char* uri) {
|
||||
const LilvPlugins* plugin_list = lilv_world_get_all_plugins(world);
|
||||
|
||||
LilvNode* plugin_uri = lilv_new_uri(world, uri);
|
||||
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugin_list, plugin_uri);
|
||||
lilv_node_free(plugin_uri);
|
||||
|
||||
if (plugin != NULL) {
|
||||
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 nPorts = lilv_plugin_get_num_ports(plugin);
|
||||
for (uint32_t i = 0; i < nPorts; i++) {
|
||||
const LilvPort* port = lilv_plugin_get_port_by_index(plugin, i);
|
||||
|
||||
LilvNode *nameNode = lilv_port_get_name(plugin, port);
|
||||
const char* name = lilv_node_as_string(nameNode);
|
||||
lilv_node_free(nameNode);
|
||||
|
||||
LilvNode* defNode = NULL;
|
||||
lilv_port_get_range(plugin, port, &defNode, NULL, NULL);
|
||||
float defaultValue = lilv_node_as_float(defNode);
|
||||
lilv_node_free(defNode);
|
||||
|
||||
printf("Port %d: %s = %f\n", i, name, defaultValue);
|
||||
|
||||
LilvNodes *classes = lilv_port_get_classes(plugin, port);
|
||||
LILV_FOREACH(nodes, i, classes) {
|
||||
LilvNode *n = lilv_nodes_get(classes, i);
|
||||
printf(" %s\n", lilv_node_as_uri(n));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
137
src/main.c
137
src/main.c
|
|
@ -1,73 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sndfile.h>
|
||||
#include <string.h>
|
||||
#include <lilv/lilv.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "easy.h"
|
||||
#include "audiofile.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#define BUFFER_SIZE 8192 // this is per channel
|
||||
#define BUFFER_SIZE 8192 // per channel
|
||||
|
||||
/*
|
||||
http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo
|
||||
http://lsp-plug.in/plugins/lv2/para_equalizer_x32_lr
|
||||
http://calf.sourceforge.net/plugins/BassEnhancer
|
||||
*/
|
||||
static int knob_mode = 2;
|
||||
static float knob_time = 100.0f; // milliseconds
|
||||
|
||||
LilvInstance *instance_two(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right) {
|
||||
const LilvPlugin* plugin = easy_load_plugin(world, "http://calf.sourceforge.net/plugins/BassEnhancer");
|
||||
if (plugin == NULL) {
|
||||
fprintf(stderr, "Plugin not found: BassEnhancer (from calf.sourceforge.net)\n");
|
||||
return NULL;
|
||||
}
|
||||
LilvInstance *new_delay_instance(LilvWorld *world, const LilvPlugins* plugins, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right) {
|
||||
const LilvPlugin* plugin = load_plugin(world, plugins, "http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo");
|
||||
|
||||
|
||||
LilvInstance *instance = lilv_plugin_instantiate(plugin, sample_rate, NULL);
|
||||
if (instance == NULL) {
|
||||
fprintf(stderr, "Failed to initialize instance two\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
lilv_instance_activate(instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
LilvInstance *instance_three(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right) {
|
||||
const LilvPlugin* plugin = easy_load_plugin(world, "http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo");
|
||||
if (plugin == NULL) {
|
||||
fprintf(stderr, "Plugin not found: comp_delay_x2_stereo (from lsp-plug.in)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float *knob_enabled = malloc(sizeof(float));
|
||||
*knob_enabled = 1.0f;
|
||||
float *knob_mode = malloc(sizeof(float));
|
||||
*knob_mode = 2.0f;
|
||||
float *knob_time = malloc(sizeof(float));
|
||||
*knob_time = 100.0f; // ms
|
||||
|
||||
LilvInstance *instance = lilv_plugin_instantiate(plugin, sample_rate, NULL);
|
||||
if (instance == NULL) {
|
||||
fprintf(stderr, "Failed to initialize instance three\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lilv_instance_connect_port(instance, 4, knob_enabled);
|
||||
lilv_instance_connect_port(instance, 16, knob_mode);
|
||||
lilv_instance_connect_port(instance, 22, knob_time);
|
||||
lilv_instance_connect_port(instance, 0, input_left);
|
||||
lilv_instance_connect_port(instance, 1, input_right);
|
||||
lilv_instance_connect_port(instance, 2, output_left);
|
||||
lilv_instance_connect_port(instance, 3, output_right);
|
||||
|
||||
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
|
||||
lilv_instance_connect_port(instance, 16, &knob_mode);
|
||||
lilv_instance_connect_port(instance, 22, &knob_time);
|
||||
|
||||
lilv_instance_activate(instance);
|
||||
|
||||
|
|
@ -75,62 +38,55 @@ LilvInstance *instance_three(LilvWorld *world, double sample_rate, float *input_
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <input> [output]\n", argv[0]);
|
||||
printf("Welcome to new version\n");
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s <input> <output>\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// so here we create the pointers for the input and output filenames
|
||||
char *input_filename = argv[1];
|
||||
char *output_filename;
|
||||
char *output_filename = argv[2];
|
||||
|
||||
if (argc < 3) {
|
||||
output_filename = malloc((strlen(input_filename) + 5) * sizeof(char));
|
||||
strcpy(output_filename, "out-");
|
||||
strcat(output_filename, input_filename);
|
||||
} else {
|
||||
output_filename = argv[2];
|
||||
}
|
||||
// Create lilv world. Think of it as the container for everything LV2.
|
||||
|
||||
LilvWorld *world = lilv_world_new();
|
||||
lilv_world_load_all(world);
|
||||
|
||||
// load audio file
|
||||
const LilvPlugins *plugins = lilv_world_get_all_plugins(world);
|
||||
|
||||
// Load the audio file, create the output file and copy metadata to it
|
||||
|
||||
SF_INFO sfinfo = {0};
|
||||
SNDFILE *in_sndfile;
|
||||
if ((in_sndfile = audiofile_read(input_filename, &sfinfo)) == NULL) {
|
||||
lilv_world_free(world);
|
||||
return 1;
|
||||
}
|
||||
|
||||
SNDFILE *out_sndfile;
|
||||
if ((out_sndfile = audiofile_open_for_write(output_filename, &sfinfo)) == NULL) {
|
||||
sf_close(in_sndfile);
|
||||
lilv_world_free(world);
|
||||
return 1;
|
||||
}
|
||||
|
||||
audiofile_copy_metadata(in_sndfile, out_sndfile);
|
||||
|
||||
// prepare lilv instance
|
||||
// Create buffers for processing
|
||||
|
||||
float input_left[BUFFER_SIZE];
|
||||
float input_right[BUFFER_SIZE];
|
||||
float output_left[BUFFER_SIZE];
|
||||
float output_right[BUFFER_SIZE];
|
||||
|
||||
const int instancesCount = 2;
|
||||
LilvInstance **instances = malloc(instancesCount * sizeof(LilvInstance*));
|
||||
if (instances == NULL) {
|
||||
fprintf(stderr, "mallocing instances failed: %s\n", strerror(errno));
|
||||
LilvInstance *instance = new_delay_instance(world, plugins, sfinfo.samplerate, input_left, input_right, output_left, output_right);
|
||||
if (instance == NULL) {
|
||||
sf_close(in_sndfile);
|
||||
sf_close(out_sndfile);
|
||||
lilv_world_free(world);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
|
||||
instances[0] = instance_two(world, sfinfo.samplerate, input_left, input_right, output_left, output_right);
|
||||
instances[1] = instance_three(world, sfinfo.samplerate, input_left, input_right, output_left, output_right);
|
||||
|
||||
// start processing
|
||||
|
||||
printf("Now processing\n");
|
||||
clock_t start = clock();
|
||||
|
||||
|
|
@ -138,21 +94,17 @@ int main(int argc, char *argv[]) {
|
|||
float output_buffer[BUFFER_SIZE * 2];
|
||||
int frames_read;
|
||||
while ((frames_read = sf_readf_float(in_sndfile, input_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)
|
||||
// De-interleave input file data into planar buffers (idk whatever that means but ai suggested it)
|
||||
// Basically a frame is samples * channels (2 if stereo) and a sample is a number basically and it go through each channel. In case of stereo it goes left right left right and so on.
|
||||
for (sf_count_t i = 0; i < frames_read; i++) {
|
||||
input_left[i] = input_buffer[i * 2];
|
||||
input_right[i] = input_buffer[i * 2 + 1];
|
||||
}
|
||||
|
||||
for (int i=0; i<instancesCount; i++) {
|
||||
lilv_instance_run(instances[i], frames_read);
|
||||
if (i + 1 != instancesCount) {
|
||||
memcpy(input_left, output_left, frames_read * sizeof(float));
|
||||
memcpy(input_right, output_right, frames_read * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
lilv_instance_run(instance, frames_read);
|
||||
|
||||
// Interleave the final output for writing to the file
|
||||
// In other words, undo the above
|
||||
for (sf_count_t i = 0; i < frames_read; i++) {
|
||||
output_buffer[i * 2] = output_left[i];
|
||||
output_buffer[i * 2 + 1] = output_right[i];
|
||||
|
|
@ -164,18 +116,15 @@ int main(int argc, char *argv[]) {
|
|||
clock_t end = clock();
|
||||
printf("Done processing. Took %ldms\n", (clock_t)((double)(end - start) / CLOCKS_PER_SEC * 1000));
|
||||
|
||||
// end processing
|
||||
// Free resources
|
||||
|
||||
for (int i=0; i<instancesCount; i++) {
|
||||
LilvInstance *instance = instances[i];
|
||||
lilv_instance_deactivate(instance);
|
||||
lilv_instance_free(instance);
|
||||
}
|
||||
free(instances);
|
||||
lilv_instance_deactivate(instance);
|
||||
lilv_instance_free(instance);
|
||||
|
||||
lilv_world_free(world);
|
||||
|
||||
sf_close(in_sndfile);
|
||||
sf_close(out_sndfile);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
62
src/plugin.c
Normal file
62
src/plugin.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#include "plugin.h"
|
||||
|
||||
inline void print_plugin_info(const LilvPlugin* plugin) {
|
||||
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 nPorts = lilv_plugin_get_num_ports(plugin);
|
||||
for (uint32_t i = 0; i < nPorts; i++) {
|
||||
const LilvPort* port = lilv_plugin_get_port_by_index(plugin, i);
|
||||
|
||||
LilvNode *nameNode = lilv_port_get_name(plugin, port);
|
||||
const char* name = lilv_node_as_string(nameNode);
|
||||
lilv_node_free(nameNode);
|
||||
|
||||
const LilvNode *symbolNode = lilv_port_get_symbol(plugin, port);
|
||||
const char* symbol = lilv_node_as_string(symbolNode);
|
||||
|
||||
printf("Port %d: %s (%s) = ", i, name, symbol);
|
||||
|
||||
LilvNode* minValueNode = NULL;
|
||||
LilvNode* maxValueNode = NULL;
|
||||
LilvNode* defaultValueNode = NULL;
|
||||
lilv_port_get_range(plugin, port, &defaultValueNode, &minValueNode, &maxValueNode);
|
||||
|
||||
if (lilv_node_is_float(defaultValueNode)) {
|
||||
printf("%f (%f - %f) (Float)", lilv_node_as_float(defaultValueNode), lilv_node_as_float(minValueNode), lilv_node_as_float(maxValueNode));
|
||||
} else if (lilv_node_is_int(defaultValueNode)) {
|
||||
printf("%d (%d - %d) (Integer)", lilv_node_as_int(defaultValueNode), lilv_node_as_int(minValueNode), lilv_node_as_int(maxValueNode));
|
||||
} else if (lilv_node_is_bool(defaultValueNode)) {
|
||||
printf("%s (Boolean)", lilv_node_as_bool(defaultValueNode) ? "true" : "false");
|
||||
} else if (lilv_node_is_string(defaultValueNode)) {
|
||||
printf("\"%s\" (String)", lilv_node_as_string(defaultValueNode));
|
||||
} else {
|
||||
printf("unknown (Other)");
|
||||
}
|
||||
|
||||
lilv_node_free(minValueNode);
|
||||
lilv_node_free(maxValueNode);
|
||||
lilv_node_free(defaultValueNode);
|
||||
|
||||
printf("\n");
|
||||
|
||||
const LilvNodes *classes = lilv_port_get_classes(plugin, port);
|
||||
LILV_FOREACH(nodes, i, classes) {
|
||||
const LilvNode *n = lilv_nodes_get(classes, i);
|
||||
printf(" %s\n", lilv_node_as_uri(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const LilvPlugin* load_plugin(LilvWorld* world, const LilvPlugins *plugins, const char* uri) {
|
||||
LilvNode* plugin_uri = lilv_new_uri(world, uri);
|
||||
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
|
||||
lilv_node_free(plugin_uri);
|
||||
|
||||
if (plugin != NULL) {
|
||||
print_plugin_info(plugin);
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
68
src_old/audiofile.c
Normal file
68
src_old/audiofile.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include "audiofile.h"
|
||||
|
||||
SNDFILE *audiofile_read(const char *path, SF_INFO *sfinfo) {
|
||||
printf("Input file: \"%s\"\n", path);
|
||||
|
||||
SNDFILE *sndfile = sf_open(path, SFM_READ, sfinfo);
|
||||
if (sndfile == NULL) {
|
||||
fprintf(stderr, "Failed to open 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", sfinfo->samplerate);
|
||||
|
||||
return sndfile;
|
||||
}
|
||||
|
||||
SNDFILE *audiofile_open_for_write(const char *path, SF_INFO *og_info) {
|
||||
printf("Output file: \"%s\"\n", path);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int audiofile_copy_metadata(SNDFILE *source, SNDFILE *target) {
|
||||
int err;
|
||||
SF_BROADCAST_INFO binfo;
|
||||
|
||||
if ((err = sf_command(source, SFC_GET_BROADCAST_INFO, &binfo, sizeof(binfo))) != 0) {
|
||||
printf("Failed reading BROADCAST_INFO: %s\n", sf_error_number(err));
|
||||
return 1;
|
||||
}
|
||||
if ((err = sf_command(target, SFC_SET_BROADCAST_INFO, &binfo, sizeof(binfo))) != 0) {
|
||||
printf("Failed writing BROADCAST_INFO: %s\n", sf_error_number(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
for (int i=SF_STR_FIRST; i<=SF_STR_LAST; i++) {
|
||||
const char *data = sf_get_string(source, i);
|
||||
if (data != NULL) {
|
||||
if ((err = sf_set_string(target, i, data)) != 0) {
|
||||
printf("Failed writing metadata %d (%s): %s\n", i, data, sf_error_number(err));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
60
src_old/instances.c
Normal file
60
src_old/instances.c
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "instances.h"
|
||||
|
||||
/*
|
||||
http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo
|
||||
http://lsp-plug.in/plugins/lv2/para_equalizer_x32_lr
|
||||
http://calf.sourceforge.net/plugins/BassEnhancer
|
||||
*/
|
||||
|
||||
LilvInstance *create_bass_enhancer_instance(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right) {
|
||||
const LilvPlugin* plugin = load_plugin(world, "http://calf.sourceforge.net/plugins/BassEnhancer");
|
||||
if (plugin == NULL) {
|
||||
fprintf(stderr, "Plugin not found: BassEnhancer (from calf.sourceforge.net)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
LilvInstance *instance = lilv_plugin_instantiate(plugin, sample_rate, NULL);
|
||||
if (instance == NULL) {
|
||||
fprintf(stderr, "Failed to initialize instance two\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lilv_instance_connect_port(instance, 0, input_left);
|
||||
lilv_instance_connect_port(instance, 1, input_right);
|
||||
lilv_instance_connect_port(instance, 2, output_left);
|
||||
lilv_instance_connect_port(instance, 3, output_right);
|
||||
|
||||
lilv_instance_activate(instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
LilvInstance *create_delay_instance(LilvWorld *world, double sample_rate, float *input_left, float *input_right, float *output_left, float *output_right) {
|
||||
const LilvPlugin* plugin = load_plugin(world, "http://lsp-plug.in/plugins/lv2/comp_delay_x2_stereo");
|
||||
if (plugin == NULL) {
|
||||
fprintf(stderr, "Plugin not found: comp_delay_x2_stereo (from lsp-plug.in)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LilvInstance *instance = lilv_plugin_instantiate(plugin, sample_rate, NULL);
|
||||
if (instance == NULL) {
|
||||
fprintf(stderr, "Failed to initialize instance three\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lilv_instance_connect_port(instance, 0, input_left);
|
||||
lilv_instance_connect_port(instance, 1, input_right);
|
||||
lilv_instance_connect_port(instance, 2, output_left);
|
||||
lilv_instance_connect_port(instance, 3, output_right);
|
||||
|
||||
static float knob_mode = 2.0f;
|
||||
static float knob_time = 100.0f; // milliseconds
|
||||
|
||||
lilv_instance_connect_port(instance, 16, &knob_mode);
|
||||
lilv_instance_connect_port(instance, 22, &knob_time);
|
||||
|
||||
lilv_instance_activate(instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
130
src_old/main.c
Normal file
130
src_old/main.c
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sndfile.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "audiofile.h"
|
||||
#include "instances.h"
|
||||
|
||||
#define BUFFER_SIZE 8192 // this is per channel
|
||||
|
||||
int man(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <input> [output]\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// so here we create the pointers for the input and output filenames
|
||||
char *input_filename = argv[1];
|
||||
char *output_filename;
|
||||
|
||||
// here we check if the output filename is provided, if not we create a default one
|
||||
if (argc < 3) {
|
||||
output_filename = malloc((strlen(input_filename) + 5) * sizeof(char));
|
||||
strcpy(output_filename, "out-");
|
||||
strcat(output_filename, input_filename);
|
||||
} else {
|
||||
output_filename = argv[2];
|
||||
}
|
||||
|
||||
// Create lilv world. Think of it as the container for everything LV2.
|
||||
|
||||
LilvWorld *world = lilv_world_new();
|
||||
lilv_world_load_all(world);
|
||||
|
||||
// Load the audio file, create the output file and copy metadata to it
|
||||
|
||||
SF_INFO sfinfo = {0};
|
||||
SNDFILE *in_sndfile;
|
||||
if ((in_sndfile = audiofile_read(input_filename, &sfinfo)) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
SNDFILE *out_sndfile;
|
||||
if ((out_sndfile = audiofile_open_for_write(output_filename, &sfinfo)) == NULL) {
|
||||
sf_close(in_sndfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
audiofile_copy_metadata(in_sndfile, out_sndfile);
|
||||
|
||||
// Create buffers for processing
|
||||
|
||||
float input_left[BUFFER_SIZE];
|
||||
float input_right[BUFFER_SIZE];
|
||||
float output_left[BUFFER_SIZE];
|
||||
float output_right[BUFFER_SIZE];
|
||||
|
||||
// Intermediate buffers are used for chaining
|
||||
float imm_buf_left[BUFFER_SIZE];
|
||||
float imm_buf_right[BUFFER_SIZE];
|
||||
|
||||
// Instantiate the instances
|
||||
|
||||
const int instancesCount = 2;
|
||||
LilvInstance **instances = malloc(instancesCount * sizeof(LilvInstance*));
|
||||
if (instances == NULL) {
|
||||
fprintf(stderr, "mallocing instances failed: %s\n", strerror(errno));
|
||||
sf_close(in_sndfile);
|
||||
sf_close(out_sndfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create instances of the plugins
|
||||
|
||||
instances[0] = create_bass_enhancer_instance(world, sfinfo.samplerate, input_left, input_right, imm_buf_left, imm_buf_right);
|
||||
instances[1] = create_delay_instance(world, sfinfo.samplerate, input_left, input_right, output_left, output_right);
|
||||
|
||||
// Start the processing finally
|
||||
|
||||
printf("Now processing\n");
|
||||
clock_t start = clock();
|
||||
|
||||
float input_buffer[BUFFER_SIZE * 2];
|
||||
float output_buffer[BUFFER_SIZE * 2];
|
||||
int frames_read;
|
||||
while ((frames_read = sf_readf_float(in_sndfile, input_buffer, BUFFER_SIZE))) {
|
||||
// De-interleave input file data into planar buffers (idk whatever that means but ai suggested it)
|
||||
// Basically a frame is samples * channels (2 if stereo) and a sample is a number basically and it go through each channel. In case of stereo it goes left right left right and so on.
|
||||
for (sf_count_t i = 0; i < frames_read; i++) {
|
||||
input_left[i] = input_buffer[i * 2];
|
||||
input_right[i] = input_buffer[i * 2 + 1];
|
||||
}
|
||||
|
||||
//printf("Running instance 0\n");
|
||||
//lilv_instance_run(instances[0], frames_read);
|
||||
|
||||
//printf("Running instance 1\n");
|
||||
//lilv_instance_run(instances[1], frames_read);
|
||||
|
||||
// Interleave the final output for writing to the file
|
||||
// In other words, undo the above
|
||||
for (sf_count_t i = 0; i < frames_read; i++) {
|
||||
output_buffer[i * 2] = output_left[i];
|
||||
output_buffer[i * 2 + 1] = output_right[i];
|
||||
}
|
||||
|
||||
sf_writef_float(out_sndfile, output_buffer, frames_read);
|
||||
}
|
||||
|
||||
clock_t end = clock();
|
||||
printf("Done processing. Took %ldms\n", (clock_t)((double)(end - start) / CLOCKS_PER_SEC * 1000));
|
||||
|
||||
// Free resources
|
||||
|
||||
for (int i=0; i<instancesCount; i++) {
|
||||
lilv_instance_deactivate(instances[i]);
|
||||
lilv_instance_free(instances[i]);
|
||||
}
|
||||
free(instances);
|
||||
|
||||
lilv_world_free(world);
|
||||
|
||||
sf_close(in_sndfile);
|
||||
sf_close(out_sndfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
49
src_old/plugin.c
Normal file
49
src_old/plugin.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include "plugin.h"
|
||||
|
||||
const LilvPlugin* load_plugin(LilvWorld *world, const LilvPlugins *plugins, const char *uri) {
|
||||
LilvNode* plugin_uri = lilv_new_uri(world, uri);
|
||||
const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
|
||||
lilv_node_free(plugin_uri);
|
||||
|
||||
if (plugin != NULL) {
|
||||
print_plugin_info(plugin);
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
inline print_plugin_info(const LilvPlugin* plugin) {
|
||||
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 nPorts = lilv_plugin_get_num_ports(plugin);
|
||||
for (uint32_t i = 0; i < nPorts; i++) {
|
||||
const LilvPort* port = lilv_plugin_get_port_by_index(plugin, i);
|
||||
|
||||
LilvNode *nameNode = lilv_port_get_name(plugin, port);
|
||||
const char* name = lilv_node_as_string(nameNode);
|
||||
lilv_node_free(nameNode);
|
||||
|
||||
LilvNode* defNode = NULL;
|
||||
lilv_port_get_range(plugin, port, &defNode, NULL, NULL);
|
||||
float defaultValue = lilv_node_as_float(defNode);
|
||||
lilv_node_free(defNode);
|
||||
|
||||
printf("Port %d: %s = %f\n", i, name, defaultValue);
|
||||
|
||||
if (lilv_node_is_float(defNode)) {
|
||||
printf(" Type: Float\n");
|
||||
} else if (lilv_node_is_int(defNode)) {
|
||||
printf(" Type: Integer\n");
|
||||
} else {
|
||||
printf(" Type: Other\n");
|
||||
}
|
||||
|
||||
const LilvNodes *classes = lilv_port_get_classes(plugin, port);
|
||||
LILV_FOREACH(nodes, i, classes) {
|
||||
const LilvNode *n = lilv_nodes_get(classes, i);
|
||||
printf(" %s\n", lilv_node_as_uri(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue