Browse Source

First commit

fanch 1 year ago
parent
commit
a95c7f6bd4

+ 125 - 0
src/common/AudioFile.cpp

@@ -0,0 +1,125 @@
+/*
+ * AudioFile.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "AudioFile.h"
+#include <unistd.h>
+#include <cstring>
+#include <fcntl.h>
+#include <errno.h>
+#include <cstdio>
+#include "errors.h"
+#include "cmath"
+#include "Window.h"
+
+
+void default_audio_file_option(AudioFileOption* out){
+	out->time_per_window = 1/30.0; // 30 fps
+	out->buffer_size = 2<<24; // 32 Mo
+}
+
+
+AudioFile::~AudioFile() {
+}
+
+AudioFile::AudioFile(const std::string& filename) {
+	m_buffer = NULL;
+	m_buffer_start = m_buffer_end = -1;
+	m_fd = fopen(filename.c_str(), "r");
+	if(!m_fd){
+		std::string err = std::string("Erreur impossible de lire le fichier")+filename+")";
+		throw FileNotFoundError(err);
+	}
+	_init();
+}
+
+AudioFile::AudioFile(FILE* fd){
+	m_buffer = NULL;
+	m_buffer_start = m_buffer_end = -1;
+	m_fd = fd;
+	_init();
+}
+
+
+
+char* AudioFile::_base_read(size_t size, size_t count, char* buffer){
+	size_t readed=0;
+	if((readed=fread(buffer, size, count, m_fd))!=count){
+		printf("Deamndé : %ld lu %ld\n",size*count, readed );
+		throw IOError(strerror(errno));
+	}
+	return  buffer;
+}
+
+void AudioFile::_init(){
+	default_audio_file_option(&m_options);
+	_base_read(sizeof(m_header), 1, (char*)&m_header);
+	fseek(m_fd, 0, SEEK_END);
+	int total = ftell(m_fd) - sizeof(m_header);
+	m_total_time = total / ((float)m_header.byte_per_sec);
+}
+
+
+int8_t* AudioFile::_bufferize(size_t start){
+	size_t end = start + m_options.time_per_window * m_header.bit_per_sample * m_header.sample_rate;
+	const int byte_per_sample = m_header.bit_per_sample>>3;
+	if(start>=m_buffer_start && start<m_buffer_end && end>=m_buffer_start && end<m_buffer_end){
+		return &m_buffer[start - m_buffer_start];
+	}
+	if(m_buffer) delete[] m_buffer;
+	m_buffer = new int8_t[m_options.buffer_size];
+	fseek(m_fd, sizeof(m_header) + start, SEEK_SET);
+
+	int to_read = m_options.buffer_size/byte_per_sample;
+	if(start+to_read > m_header.data_size){
+		to_read = m_header.data_size-start;
+	}
+	fread(m_buffer, byte_per_sample, m_options.buffer_size/byte_per_sample, m_fd);
+	return m_buffer;
+}
+
+Window** AudioFile::window_at_time(float time) {
+	if(time>m_total_time) return NULL;
+
+	Window** windows = new Window*[m_header.channels];
+	size_t sample_per_window = m_options.time_per_window * m_header.bit_per_sample * m_header.sample_rate;
+	for(size_t i=0; i<m_header.channels; i++)
+		windows[i] = new Window(this, sample_per_window);
+
+	size_t sample_size = m_header.bit_per_sample >> 3;
+	size_t start = sample_size * m_header.sample_rate * m_header.channels * time;
+	printf("For time %f offset = %ld + %ld\n", time, sizeof(m_header), start);
+
+	int8_t* buffer = _bufferize(start);
+	for(size_t i=0; i<sample_per_window; i++){
+		for(size_t channel=0; channel<m_header.channels; channel++){
+			windows[channel]->data[i] = _val_to_float(buffer+(i*m_header.channels+channel)*sample_size, sample_size);
+		}
+	}
+	return windows;
+}
+Window* AudioFile::window_channel_at_time(float time, int ch) {
+	if(time>m_total_time) return NULL;
+
+	size_t sample_per_window = m_options.time_per_window * m_header.bit_per_sample * m_header.sample_rate;
+
+	Window* windows = new Window(this, sample_per_window);
+
+	size_t sample_size = m_header.bit_per_sample >> 3;
+	size_t start = sample_size * m_header.sample_rate * m_header.channels * time;
+	printf("For time %f offset = %ld + %ld\n", time, sizeof(m_header), start);
+
+	int8_t* buffer = _bufferize(start);
+	for(size_t i=0; i<sample_per_window; i++){
+		for(size_t channel=0; channel<m_header.channels; channel++){
+			if(channel != (uint8_t)ch) continue;
+			windows->data[i] = _val_to_float(buffer+(i*m_header.channels+channel)*sample_size, sample_size);
+		}
+	}
+	return windows;
+}
+
+

+ 93 - 0
src/common/AudioFile.h

@@ -0,0 +1,93 @@
+/*
+ * AudioFile.h
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef AUDIOFILE_H_
+#define AUDIOFILE_H_
+#include <string>
+#include <cstdint>
+#include <cstdio>
+
+class Window;
+
+struct AudiFileHeader {
+	char riff[4]; // 0
+	uint32_t size; // 4
+	char wave[4]; // 8
+	char fmt[4]; // 12
+	uint32_t length; // 16
+	uint16_t type; // 20
+	uint16_t channels; // 22
+	uint32_t sample_rate; // 24
+	uint32_t byte_per_sec; // 28
+	uint16_t __; // 32
+	uint16_t bit_per_sample; // 34
+	char data[4]; // 36
+	uint32_t data_size; //40
+};
+
+struct AudioFileOption {
+	float time_per_window;
+	uint32_t buffer_size;
+
+};
+
+
+class AudioFile {
+public:
+	virtual ~AudioFile();
+	AudioFile(FILE* fd=NULL);
+	AudioFile(const std::string&);
+	AudioFileOption& get_options() { return m_options; }
+	AudiFileHeader& get_headers() { return m_header; }
+
+
+	Window** window_at_time(float time);
+	Window* window_channel_at_time(float time, int ch);
+	inline size_t sample_per_window(){
+		return m_options.time_per_window * m_header.bit_per_sample * m_header.sample_rate;
+	}
+
+	float m_total_time;
+
+protected:
+	FILE* m_fd;
+	AudiFileHeader m_header;
+	AudioFileOption m_options;
+	int8_t* m_buffer;
+	size_t m_buffer_start;
+	size_t m_buffer_end;
+
+
+	int8_t* _bufferize(size_t start);
+
+	void _init();
+	char* _base_read(size_t size, size_t count, char* buffer=NULL);
+
+
+
+};
+
+inline double _val_to_float(int8_t* val, int size){
+    float fval;
+    switch (size) {
+        case 1: fval=((uint8_t)*val)/((double)255); break;
+        case 2: fval=(*(int16_t*)val)/((double)32767.0); break;
+        case 3: {
+        	throw "Error not implemented";
+        	uint32_t v = *(uint32_t*)(val);
+        	fval=((v & (1<<24)))-(v&((1<<24)-1)); break;
+        }
+        case 4: fval=(*(int32_t*)val)/((double)(1<<31)); break;
+        default:
+            fprintf(stderr, "Erreur impossible de traiter des échantillons sur %d bits", size);
+            throw "Error";
+
+    }
+    return (fval/2.0f)-((float)(1<<(size-1)));
+}
+
+#endif /* AUDIOFILE_H_ */

+ 27 - 0
src/common/AudioFile_test.cpp

@@ -0,0 +1,27 @@
+/*
+ * AudioFile_test.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "AudioFile.h"
+#include <cstdio>
+#include "fft/FFT.h"
+#include "Window.h"
+int main(){
+	AudioFile file("/home/fanch/Documents/la_440.wav");
+	RealFFTW x(file.sample_per_window(), file.get_headers().sample_rate);
+	printf("total time = %f s\n", file.m_total_time);
+	for(int i=23; i<152; i++){
+
+		Window* w = file.window_channel_at_time(i, 0);
+
+		x.execute(w->data);
+		x.plot("plot.dat");
+		exit(0);
+		//28903936
+		//28608000
+	}
+//
+}

+ 32 - 0
src/common/Window.cpp

@@ -0,0 +1,32 @@
+/*
+ * Window.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "Window.h"
+Window::Window() :  data(NULL) { // @suppress("Class members should be properly initialized")
+
+}
+
+Window::Window(AudioFile* f, size_t l) : file(f), data(new double[l]), length(l) { // @suppress("Class members should be properly initialized")
+}
+
+Window::~Window() {
+	if(data) delete[] data;
+}
+
+Window::Window(const Window &other) {
+	file= other.file;
+	max = other.max;
+	min = other.min;
+	length = other.length;
+	data = new double[length];
+
+}
+
+void Window::_init(){
+
+}
+

+ 35 - 0
src/common/Window.h

@@ -0,0 +1,35 @@
+/*
+ * Window.h
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef WINDOW_H_
+#define WINDOW_H_
+#include <cstddef>
+#include "AudioFile.h"
+
+
+class Window {
+public:
+	Window();
+	virtual ~Window();
+	Window(const Window &other);
+	Window(AudioFile*, size_t length);
+
+	AudioFile* file;
+	double* data;
+	size_t length;
+	double max;
+	double min;
+	size_t sample_per_window;
+
+
+protected:
+	void _init();
+};
+
+
+
+#endif /* WINDOW_H_ */

+ 9 - 0
src/common/Window_test.cpp

@@ -0,0 +1,9 @@
+/*
+ * Window_test.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "Window.h"
+

+ 13 - 0
src/common/errors.cpp

@@ -0,0 +1,13 @@
+/*
+ * errors.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "errors.h"
+
+
+int fct(){
+	return 0;
+}

+ 54 - 0
src/common/errors.h

@@ -0,0 +1,54 @@
+/*
+ * errors.h
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef ERRORS_H_
+#define ERRORS_H_
+
+#include <string>
+class Error {
+public:
+	Error() { }
+	Error(const std::string& msg) : m_msg(msg) { }
+	Error(const char* msg) : m_msg(msg) { }
+	Error(const Error& err) : m_msg(err.m_msg) {}
+	Error& operator=(const Error& err){
+		m_msg = err.m_msg;
+		return *this;
+	}
+
+	const std::string& to_string() const {return m_msg; }
+
+protected:
+	std::string m_msg;
+
+};
+
+
+class FileNotFoundError : public Error {
+public:
+	FileNotFoundError() : Error() {}
+	FileNotFoundError(const char* s) : Error(s) {}
+	FileNotFoundError(const std::string& s) : Error(s) {}
+};
+
+class IOError : public Error {
+public:
+	IOError() : Error() {}
+	IOError(const char* s) : Error(s) {}
+	IOError(const std::string& s) : Error(s) {}
+};
+
+class MemoryError : public Error {
+public:
+	MemoryError() : Error() {}
+	MemoryError(const char* s) : Error(s) {}
+	MemoryError(const std::string& s) : Error(s) {}
+};
+
+
+
+#endif /* ERRORS_H_ */

+ 9 - 0
src/common/errors_test.cpp

@@ -0,0 +1,9 @@
+/*
+ * errors_test.cpp
+ *
+ *  Created on: 6 déc. 2023
+ *      Author: fanch
+ */
+
+#include "errors.h"
+

+ 9 - 0
src/common/tools.cpp

@@ -0,0 +1,9 @@
+/*
+ * tools.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "tools.h"
+

+ 22 - 0
src/common/tools.h

@@ -0,0 +1,22 @@
+/*
+ * tools.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_COMMON_TOOLS_H_
+#define SRC_COMMON_TOOLS_H_
+
+#include <cstring>
+#include <cstdio>
+
+bool endswith(const char* src, const char* dst){
+	int lsrc = strlen(src), ldst = strlen(dst);
+	if(lsrc<ldst) return false;
+	return !strcmp(src+lsrc-ldst, dst);
+}
+
+
+
+#endif /* SRC_COMMON_TOOLS_H_ */

+ 7 - 0
src/common/wscript

@@ -0,0 +1,7 @@
+
+
+def build(bld):
+    bld.objects(source=bld.get_sub_files(max_depth=1), 
+                target="common",
+                includes = ['.','..'],
+        )

+ 9 - 0
src/core/PluginHost.cpp

@@ -0,0 +1,9 @@
+/*
+ * PluginHost.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "PluginHost.h"
+

+ 14 - 0
src/core/PluginHost.h

@@ -0,0 +1,14 @@
+/*
+ * PluginHost.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_CORE_PLUGINHOST_H_
+#define SRC_CORE_PLUGINHOST_H_
+
+class PluginHost {
+};
+
+#endif /* SRC_CORE_PLUGINHOST_H_ */

+ 123 - 0
src/core/PluginIndex.cpp

@@ -0,0 +1,123 @@
+/*
+ * PluginHost.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "PluginIndex.h"
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <cstring>
+#include <cstdlib>
+#include <sys/types.h>
+#include <unistd.h>
+#include "common/tools.h"
+
+DllManager* DllManager::m_instance = new DllManager();
+
+void PluginEntry::load(){
+	void * plugin_handle;
+	LADSPA_Descriptor_Function descriptor;
+	m_loaded = false;
+	plugin_handle =  DllManager::open(m_path);
+	if(plugin_handle){
+		dlerror();
+		descriptor = (LADSPA_Descriptor_Function)dlsym(plugin_handle, "ladspa_descriptor");
+		const char error = dlerror() != NULL;
+		m_is_error = error;
+		if(!error){
+			int i=0;
+			const LADSPA_Descriptor* desc;
+			for(int i=0; (desc=descriptor(i)); i++){
+				m_name = desc->Name;
+				m_id = desc->UniqueID;
+				m_label = desc->Label;
+				m_ports.resize(desc->PortCount);
+				for(int i=0; i<desc->PortCount; i++){
+					m_ports[i].name = desc->PortNames[i];
+					m_ports[i].index = i;
+					LADSPA_PortDescriptor port_desc = desc->PortDescriptors[i];
+					m_ports[i].is_input = LADSPA_IS_PORT_INPUT(port_desc);
+					m_ports[i].is_output = LADSPA_IS_PORT_OUTPUT(port_desc);
+					m_ports[i].is_audio = LADSPA_IS_PORT_AUDIO(port_desc);
+					m_ports[i].is_control = LADSPA_IS_PORT_CONTROL(port_desc);
+				}
+			}
+
+			DllManager::close(plugin_handle);
+		}else{
+			m_error = error;
+			DllManager::close(plugin_handle);
+			return;
+		}
+		m_loaded = true;
+	}
+
+}
+
+void PluginIndex::list() const{
+
+}
+
+void PluginIndex::_update_dir(const std::string& dir){
+	const char * directory = dir.c_str();
+	char * full_path;
+	DIR * psDirectory;
+	long dir_len;
+	long iNeedSlash;
+	struct dirent * direntry;
+	void * pvPluginHandle;
+
+	dir_len = strlen(directory);
+	if (!dir_len) return;
+	if (directory[dir_len - 1] == '/')
+		iNeedSlash = 0;
+	else
+		iNeedSlash = 1;
+
+	psDirectory = opendir(directory);
+	if (!psDirectory) return;
+
+	while (1) {
+		direntry = readdir(psDirectory);
+		if (!direntry) {
+		  closedir(psDirectory);
+		  return;
+		}
+		printf("-> %s\n", direntry->d_name);
+		if(!endswith(direntry->d_name, ".so")){
+			continue;
+		}
+
+		full_path = (char*)new char[(dir_len+ strlen(direntry->d_name)+ 1 + iNeedSlash)];
+		strcpy(full_path, directory);
+		if (iNeedSlash)  strcat(full_path, "/");
+		strcat(full_path, direntry->d_name);
+
+		PluginEntry entry(full_path);
+		m_plugins.push_back(entry);
+		m_plugins[m_plugins.size()-1].load();
+		delete[] full_path;
+	}
+}
+
+
+void PluginIndex::update(){
+	m_plugins.clear();
+	for(size_t i=0; i<m_plugin_pathes.size(); i++){
+		_update_dir(m_plugin_pathes[i]);
+	}
+}
+
+PluginEntry& PluginIndex::load_from_path(const std::string& path){
+	for(size_t i=0; i<m_plugins.size(); i++){
+		if(m_plugins[i].path() == path){
+			return m_plugins[i];
+		}
+	}
+	PluginEntry entry(path);
+	m_plugins.push_back(entry);
+	return m_plugins[m_plugins.size() -1 ];
+}

+ 240 - 0
src/core/PluginIndex.h

@@ -0,0 +1,240 @@
+/*
+ * PluginHost.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_CORE_PLUGININDEX_H_
+#define SRC_CORE_PLUGININDEX_H_
+
+#include <ladspa.h>
+#include <string>
+#include <vector>
+#include <utility>
+#include <cstdio>
+#include <dlfcn.h>
+
+struct DllEntry {
+	std::string path;
+	int count;
+	void* ptr;
+};
+typedef std::vector<DllEntry> DllTable;
+
+class DllManager;
+class DllManager {
+
+
+public:
+	DllManager(){
+
+	}
+
+	virtual ~DllManager(){
+
+	}
+
+	void* _open(const std::string& path){
+		for(size_t i=0; i<m_table.size(); i++){
+			if(m_table[i].path == path){
+				m_table[i].count++;
+				return m_table[i].ptr;
+			}
+		}
+		DllEntry entry;
+		entry.path = path;
+		entry.count = 1;
+		entry.ptr =  dlopen(path.c_str(), RTLD_LAZY);
+		m_table.push_back(entry);
+		return entry.ptr;
+	}
+
+	void _close(void* ptr){
+
+		for(size_t i=0; i<m_table.size(); i++){
+			if(m_table[i].ptr == ptr){
+				m_table[i].count--;
+				if(m_table[i].count<=0){
+					printf("Close %s\n", m_table[i].path.c_str());
+					dlclose(m_table[i].ptr);
+					m_table.erase(m_table.begin()+i);
+				}
+				return;
+			}
+		}
+	}
+
+	static void* open(const std::string& path){
+		return DllManager::m_instance->_open(path);
+	}
+
+	static void close(void* ptr){
+		return DllManager::m_instance->_close(ptr);
+	}
+
+
+protected:
+	DllTable m_table;
+
+	static DllManager* m_instance;
+};
+
+
+
+struct PluginPort {
+
+	PluginPort() : index(0), is_input(false), is_output(false),
+			is_audio(false), is_control(false){
+	}
+
+	virtual ~PluginPort(){
+	}
+
+	std::string name;
+	int index;
+	bool is_input;
+	bool is_output;
+	bool is_audio;
+	bool is_control;
+
+
+	std::string& to_string(std::string& out) const {
+		out += "[" + name +"] ";
+		if(is_input) out+="AUDIO ";
+		if(is_output) out+="OUTPUT ";
+		if(is_audio) out+="AUDIO ";
+		if(is_control) out+="CONTROL ";
+		out+="\n";
+		return out;
+	}
+};
+
+typedef std::vector<PluginPort> PluginPorts;
+
+class PluginEntry {
+public:
+	PluginEntry(const std::string& plugin_path){
+		set_path(plugin_path);
+	}
+
+	PluginEntry(){
+		_clear();
+	}
+
+	PluginEntry(const PluginEntry& other){
+		m_loaded = other.m_loaded;
+		m_name = other.m_name;
+		m_path = other.m_path;
+		m_error = other.m_error;
+		m_is_error = other.m_is_error;
+		m_label = other.m_label;
+		m_id = other.m_id;
+		m_ports = other.m_ports;
+	}
+
+	virtual ~PluginEntry(){
+
+	}
+
+	void set_path(const std::string& path){
+		if(path == m_path) return;
+		m_loaded = false;
+		this->m_path = path;
+	}
+
+	void load();
+
+	const std::string& path() const{
+		return m_path;
+	}
+
+	std::string& to_string(std::string& out) const {
+		char tmp[1024];
+		sprintf(tmp, "=== [%s] %s%s===\n  id=%d\n  name=%s\n  label=%s\n  ports:\n",
+				m_path.c_str(),
+				(m_is_error?"Erreur: ":""),
+				(m_is_error?m_error.c_str():""),
+				m_id, m_name.c_str(), m_label.c_str());
+
+		out+=tmp;
+		for(size_t i=0; i<m_ports.size(); i++){
+			out+="    ";
+			m_ports[i].to_string(out);
+		}
+		return out;
+	}
+
+	void print() const {
+		std::string out;
+		to_string(out);
+		printf("%s\n", out.c_str());
+	}
+
+	const PluginPorts& ports() const {
+		return m_ports;
+	}
+
+protected:
+
+	void _clear(){
+		m_loaded = false;
+	}
+
+	void _read_info(){
+		m_loaded = true;
+	}
+
+	bool m_loaded;
+	std::string m_path;
+	std::string m_name;
+	std::string m_error;
+	bool m_is_error;
+	std::string m_label;
+	long m_id;
+	PluginPorts m_ports;
+
+
+	friend class PluginInstance;
+
+};
+
+class PluginIndex {
+public:
+	PluginIndex(){
+
+	}
+
+	virtual ~PluginIndex(){
+
+	}
+
+	void add_path(const std::string& path){
+		m_plugin_pathes.push_back(path);
+	}
+
+	void list() const;
+
+	void update();
+
+	PluginEntry& load_from_path(const std::string& path);
+
+
+
+	void print() const{
+		printf("%d plugins\n", m_plugins.size());
+		for(size_t i=0; i<m_plugins.size(); i++){
+			printf("Plugin '%s'\n", m_plugins[i].path().c_str());
+		}
+	}
+
+
+protected:
+	void _update_dir(const std::string& dir);
+
+	std::vector<std::string> m_plugin_pathes;
+	std::vector<PluginEntry> m_plugins;
+
+};
+
+#endif /* SRC_CORE_PLUGININDEX_H_ */

+ 68 - 0
src/core/PluginInstance.cpp

@@ -0,0 +1,68 @@
+/*
+ * PluginInstance.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "PluginManager.h"
+#include "PluginIndex.h"
+#include "PluginInstance.h"
+
+PluginInstance::PluginInstance(PluginManager& manager, PluginEntry& entry, int index, int id) :
+	m_id(id), m_index(index), m_manager(manager), m_entry(entry){
+	m_dll = DllManager::open(entry.path());
+	if(!m_dll){
+		throw "unable to open dll";
+	}
+	LADSPA_Descriptor_Function fct = (LADSPA_Descriptor_Function)dlsym(m_dll, "ladspa_descriptor");
+	if( dlerror() != NULL){
+		throw "unable to open dll 'ladspa_descripto'";
+	}
+	m_desc =  (LADSPA_Descriptor*) fct(index);
+
+	if( m_desc == NULL){
+		throw "unable to open dll 'ladspa_descripto' desc";
+	}
+	m_sample_rate = manager.sample_rate();
+	m_instance = m_desc->instantiate(m_desc, m_sample_rate);
+}
+
+PluginInstance::~PluginInstance(){
+	DllManager::close(m_dll);
+}
+
+
+void PluginInstance::disconnect(int id){
+	if(id<m_entry.m_ports.size()){
+		m_desc->connect_port(m_instance, id, NULL);
+	}
+}
+
+void PluginInstance::connect(int port_id, LADSPA_Data* data){
+	if(port_id<m_entry.m_ports.size()){
+		m_desc->connect_port(m_instance, port_id, data);
+	}
+}
+
+LADSPA_Data PluginInstance::get(int id) const{
+	return 0.0;
+}
+
+void PluginInstance::set(int id, LADSPA_Data d){
+
+}
+
+void PluginInstance::activate(){
+	m_desc->activate(m_instance);
+}
+
+void PluginInstance::desactivate(){
+	m_desc->deactivate(m_instance);
+
+}
+
+void PluginInstance::run(){
+	m_desc->run(m_instance, m_sample_rate);
+
+}

+ 72 - 0
src/core/PluginInstance.h

@@ -0,0 +1,72 @@
+/*
+ * PluginInstance.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_CORE_PLUGININSTANCE_H_
+#define SRC_CORE_PLUGININSTANCE_H_
+
+#include <ladspa.h>
+
+#include <vector>
+
+class PluginInstance;
+
+struct PluginConnection {
+
+	PluginConnection(PluginInstance *s, PluginInstance *d, LADSPA_Data *b) :
+			src(s), dst(d), buffer(b) {
+	}
+
+	PluginConnection(const PluginConnection &o) {
+		src = o.src;
+		dst = o.dst;
+		buffer = o.buffer;
+	}
+
+	PluginInstance *src;
+	PluginInstance *dst;
+	LADSPA_Data *buffer;
+};
+
+typedef std::vector<PluginConnection> PluginConnections;
+
+class PluginManager;
+class PluginEntry;
+class PluginPort;
+
+class PluginInstance {
+
+	PluginInstance(PluginManager &manager, PluginEntry &entry, int index,
+			int id);
+
+	virtual ~PluginInstance();
+	void disconnect(int id);
+	void connect(int self_id, LADSPA_Data *data);
+	LADSPA_Data get(int id) const;
+	void set(int id, LADSPA_Data d);
+	void activate();
+	void desactivate();
+	void run();
+
+	PluginEntry& entry() {
+		return m_entry;
+	}
+
+protected:
+
+	int m_id;
+	int m_index;
+	LADSPA_Handle m_instance;
+	LADSPA_Descriptor* m_desc;
+	void *m_dll;
+	PluginManager &m_manager;
+	PluginEntry &m_entry;
+	unsigned long m_sample_rate;
+
+	friend class PluginManager;
+};
+
+#endif /* SRC_CORE_PLUGININSTANCE_H_ */

+ 82 - 0
src/core/PluginManager.cpp

@@ -0,0 +1,82 @@
+/*
+ * PluginManager.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "PluginManager.h"
+#include "PluginIndex.h"
+#include "PluginInstance.h"
+
+
+PluginManager::~PluginManager(){
+	for(LADSPA_Data* elem : m_buffers ){
+		delete[] elem;
+	}
+	for(PluginInstance* elem : m_plugins ){
+		delete elem;
+	}
+	m_buffers.clear();
+	if(m_input) delete[] m_input;
+	if(m_output) delete[] m_input;
+}
+
+void PluginManager::connect(PluginInstance *p1, int p1id, PluginInstance *p2,
+		int p2id) {
+}
+
+void PluginManager::disconnect(PluginInstance *p, int pid) {
+
+}
+
+
+
+LADSPA_Data* PluginManager::run(LADSPA_Data* input){
+	if(m_plugins.size()){
+		_copy_buffer(input, m_input);
+		for(PluginInstance* plugin : m_plugins){
+			plugin->run();
+		}
+	}else{
+		_copy_buffer(input, m_output);
+	}
+	return m_output;
+}
+
+PluginInstance* PluginManager::add_plugin(PluginEntry &p) {
+	if(!m_input || !m_output){
+		throw ("Erreur non initialisé");
+	}
+	LADSPA_Data *input = m_input, *output=m_output;
+	PluginInstance* plugin = new PluginInstance(*this, p, m_plugins.size(), m_current_id);
+	m_current_id += 1;
+
+	if(m_plugins.size()){
+		input = new LADSPA_Data[m_sample_count];
+		m_buffers.push_back(input);
+		PluginInstance* last = m_plugins[m_plugins.size()-1];
+		for(const PluginPort& port : last->entry().ports()){
+			last->connect(m_buffers.size()-1, input);
+		}
+	}
+	for(const PluginPort& port : p.ports()){
+		if(port.is_audio){
+			if(port.is_input){
+				plugin->connect(port.index, output);
+			}
+			if(port.is_output){
+				plugin->connect(port.index, output);
+			}
+		}
+	}
+	m_plugins.push_back(plugin);
+	return plugin;
+}
+
+LADSPA_Data* PluginManager::_copy_buffer(LADSPA_Data* src, LADSPA_Data* dst) {
+	for(unsigned long i=0; i<m_sample_count; i++){
+		dst[i] = src[i];
+	}
+	return dst;
+}

+ 65 - 0
src/core/PluginManager.h

@@ -0,0 +1,65 @@
+/*
+ * PluginManager.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_CORE_PLUGINMANAGER_H_
+#define SRC_CORE_PLUGINMANAGER_H_
+
+#include <ladspa.h>
+
+#include <vector>
+
+class PluginInstance;
+class PluginEntry;
+
+
+class PluginManager {
+public:
+	PluginManager() : m_sample_count(0), m_sample_rate(0){
+		m_input = m_output = NULL;
+		m_current_id = 1;
+	}
+
+	void set_rate(int sr, int sc=1024){
+		m_sample_rate = sr;
+		m_sample_count = sc;
+		if(m_input) delete[] m_input;
+		if(m_output) delete[] m_input;
+		m_input = new LADSPA_Data[m_sample_count];
+		m_output = new LADSPA_Data[m_sample_count];
+	}
+
+	virtual ~PluginManager();
+	unsigned long sample_rate() const{
+		return m_sample_rate;
+	}
+
+
+
+	void connect(PluginInstance* p1, int p1id, PluginInstance* p2, int p2id);
+	void disconnect(PluginInstance* p, int pid);
+	PluginInstance*  add_plugin(PluginEntry& p);
+	LADSPA_Data* run(LADSPA_Data*);
+
+
+
+protected:
+
+	LADSPA_Data* _copy_buffer(LADSPA_Data* src, LADSPA_Data* dst);
+
+	unsigned long m_sample_rate;
+	unsigned long m_sample_count;
+	LADSPA_Data* m_input;
+	LADSPA_Data* m_output;
+	std::vector<LADSPA_Data*> m_buffers;
+	std::vector<PluginInstance*> m_plugins;
+	unsigned int m_current_id;
+
+
+
+};
+
+#endif /* SRC_CORE_PLUGINMANAGER_H_ */

+ 16 - 0
src/core/wscript

@@ -0,0 +1,16 @@
+core_sources = [
+        "PluginIndex.cpp",
+        "PluginHost.cpp",
+        "PluginInstance.cpp",
+        "PluginManager.cpp",
+]
+
+
+
+def build(bld):
+    
+    
+    bld.objects(source=core_sources, 
+                target="core",
+                includes = ['.','..'],
+        )

+ 8 - 0
src/fft/FFT.cpp

@@ -0,0 +1,8 @@
+/*
+ * FFT.cpp
+ *
+ *  Created on: 12 déc. 2023
+ *      Author: fanch
+ */
+
+#include "FFT.h"

+ 102 - 0
src/fft/FFT.h

@@ -0,0 +1,102 @@
+/*
+ * FFT.h
+ *
+ *  Created on: 12 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef FFT_H_
+#define FFT_H_
+#include <cstdint>
+#include <cstdlib>
+#include <cstdio>
+#include <cmath>
+#include <cstddef>
+#include <fftw3.h>
+
+class RealFFT {
+public:
+	RealFFT(size_t count, uint32_t rate) : m_count(count), m_rate(rate), m_input(NULL), m_output(NULL){
+		m_input = new double[count];
+		m_output= new double[count];
+	}
+
+	virtual ~RealFFT(){
+		if(m_input){
+			delete[] m_input;
+		}
+		if(m_output){
+			delete[] m_output;
+		}
+	}
+
+	void execute(double* input){
+		_set_input(input);
+		process();
+	}
+
+	virtual void plot(const char*filename){
+		FILE* f = fopen(filename,"w");
+		for(size_t i=0; i<m_count; i++){
+			fprintf(f, "%ld %lf\n", i, m_input[i]);
+		}
+		fclose(f);
+	}
+
+protected:
+	size_t m_count;
+	uint32_t m_rate;
+	double* m_input;
+	double* m_output;
+
+	virtual void _set_input(double* input) = 0;
+
+	virtual void process() = 0;
+
+};
+
+
+class RealFFTW : public RealFFT{
+
+public:
+	RealFFTW(size_t count, uint32_t rate) : RealFFT(count, rate), m_input_complex(NULL), m_output_complex(NULL){
+		m_input_complex = fftw_alloc_complex(count);
+		m_output_complex = fftw_alloc_complex(count);
+	}
+
+
+	virtual void plot(const char*filename){
+		FILE* f = fopen(filename,"w");
+		for(size_t i=0; i<m_count; i++){
+			double d = m_output[i];
+			fprintf(f, "%f %lf\n", i*m_rate/((float)m_count), d>=0?d:-d);
+		}
+		fclose(f);
+	}
+
+protected:
+	fftw_complex* m_input_complex;
+	fftw_complex* m_output_complex;
+	virtual void process(){
+		fftw_plan p = fftw_plan_dft_1d(m_count, m_input_complex, m_output_complex, FFTW_FORWARD, FFTW_ESTIMATE);
+		fftw_execute(p);
+		fftw_destroy_plan(p);
+
+		for(size_t i=0; i<m_count; i++){
+			m_output[i] = m_output_complex[i][0];
+		}
+	}
+
+
+
+	virtual void _set_input(double* input){
+		for(size_t i=0; i<m_count; i++){
+			m_input[i] = input[i];
+			m_input_complex[i][0] = input[i];
+			m_input_complex[i][1] = 0.0;
+		}
+	}
+};
+
+
+#endif /* FFT_H_ */

+ 5 - 0
src/fft/wscript

@@ -0,0 +1,5 @@
+def build(bld):
+    bld.objects(source=bld.get_sub_files(max_depth=1), 
+                target="fft",
+                includes = ['.','..'],
+        )

+ 39 - 0
src/io/FileSoundInput.cpp

@@ -0,0 +1,39 @@
+/*
+ * FileSoundInput.cpp
+ *
+ *  Created on: 20 déc. 2023
+ *      Author: fanch
+ */
+
+#include "FileSoundInput.h"
+
+FileSoundInput::FileSoundInput(const std::string &path, unsigned int sc) {
+	m_path = path;
+	m_type = Type::FILE;
+	SF_INFO info;
+	m_fd = sf_open(m_path.c_str(), SFM_READ, &info);
+	if (!m_fd){
+		throw "Erreur de lecture de fichier";
+	}
+	m_channles = info.channels;
+	m_sample_rate = info.samplerate;
+	m_sample_size = info.format;
+	init(sc);
+}
+
+FileSoundInput::~FileSoundInput() {
+	close();
+}
+
+LADSPA_Data* FileSoundInput::_next(LADSPA_Data* x) {
+	sf_count_t len;
+	len = sf_readf_float(m_fd, x, (sf_count_t)m_sample_count);
+	if(!len) return NULL;
+	return x;
+}
+
+void FileSoundInput::close() {
+	if(m_fd){
+		sf_close(m_fd);
+	}
+}

+ 31 - 0
src/io/FileSoundInput.h

@@ -0,0 +1,31 @@
+/*
+ * FileSoundInput.h
+ *
+ *  Created on: 20 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_IO_FILESOUNDINPUT_H_
+#define SRC_IO_FILESOUNDINPUT_H_
+#include "SoundInput.h"
+#include <string>
+#include <sndfile.h>
+
+
+
+class FileSoundInput : public SoundInputStream {
+public:
+	FileSoundInput(const std::string& path, unsigned int sample_cout = 1024);
+	~FileSoundInput();
+
+	void close();
+
+protected:
+	virtual LADSPA_Data* _next(LADSPA_Data*);
+	std::string m_path;
+	SNDFILE*	m_fd;
+
+};
+
+
+#endif /* SRC_IO_FILESOUNDINPUT_H_ */

+ 9 - 0
src/io/SoundInput.cpp

@@ -0,0 +1,9 @@
+/*
+ * SoundInput.cpp
+ *
+ *  Created on: 20 déc. 2023
+ *      Author: fanch
+ */
+
+#include "SoundInput.h"
+

+ 53 - 0
src/io/SoundInput.h

@@ -0,0 +1,53 @@
+/*
+ * SoundInput.h
+ *
+ *  Created on: 20 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_IO_SOUNDINPUT_H_
+#define SRC_IO_SOUNDINPUT_H_
+
+#include <ladspa.h>
+#include <cstdlib>
+
+class SoundInputStream {
+public:
+	~SoundInputStream(){}
+
+	enum Type {
+		REALTIME,
+		FILE
+	};
+
+	bool is_realtime() const { return m_type == Type::REALTIME; }
+	bool is_file() const { return m_type == Type::FILE; }
+
+	LADSPA_Data* next(LADSPA_Data* input= NULL){
+		if(!input){
+			input = m_buffer;
+		}
+		return _next(input);
+
+	}
+
+
+protected:
+	void init(unsigned long sc) {
+		m_sample_count = sc;
+		m_buffer = new LADSPA_Data[sc];
+	}
+
+	virtual LADSPA_Data* _next(LADSPA_Data*) = 0;
+	Type m_type;
+	unsigned long m_sample_rate;
+	unsigned int m_channles;
+	unsigned int m_sample_size;
+	unsigned int m_sample_count;
+	LADSPA_Data* m_buffer;
+
+};
+
+
+
+#endif /* SRC_IO_SOUNDINPUT_H_ */

+ 7 - 0
src/io/wscript

@@ -0,0 +1,7 @@
+def build(bld):
+    x = bld.get_sub_files(max_depth=1)
+    print(x)
+    bld.objects(source=x, 
+                target="io",
+                includes = ['.','..'],
+        )

+ 319 - 0
src/plugins/AudiToMidi.cpp

@@ -0,0 +1,319 @@
+/*
+ * AudiToMidi.cpp
+ *
+ *  Created on: 16 déc. 2023
+ *      Author: fanch
+ */
+#define LSP_LIBRARY_EXTERN  extern
+#include <cmath>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+
+#include "ladspa.h"
+
+#include <fftw3.h>
+#include <cstdint>
+#include <sched.h>
+#include <time.h>
+/* The port numbers for the plugin: */
+#include "SDLWindow.h"
+
+
+#define PLUGIN_COUNT 1
+#define PORT_COUNT 2
+#define INPUT_PORT 0
+#define OUTPUT_PORT 1
+#include <complex>
+typedef std::complex<float> Complex;
+
+
+
+class CustomFft {
+public:
+	CustomFft(float **input, float** output){
+		m_input = input;
+		m_output = output;
+		m_input_complex = NULL;
+		m_output_complex = NULL;
+	}
+
+	void set_count(int n){
+		if(m_count == n) return;
+		if(m_input_complex) delete[] m_input_complex;
+		if(m_output_complex) delete[] m_output_complex;
+		m_count = n;
+		m_input_complex = new Complex[n];
+		m_output_complex = new Complex[n];
+		for(int i=0; i<n; i++){
+			m_input_complex[i].imag(0);
+			m_output_complex[i].imag(0);
+		}
+	}
+
+	virtual ~CustomFft(){
+		if(m_input_complex) delete[] m_input_complex;
+		if(m_output_complex) delete[] m_output_complex;
+	}
+
+
+
+	void execute(){
+		for(int i=0; i<m_count; i++){
+			m_input_complex[i].real(0);
+		}
+		for(int k = 0; k < m_count; k++)
+		{
+			Complex sum(0.0,0.0);
+			for(int j = 0; j < m_count; j++)
+			{
+				int integers = -2*j*k;
+				Complex my_exponent(0.0, M_PI/m_count*(double)integers);
+				sum += (*m_input)[j] * std::exp(my_exponent);
+			}
+
+			double val = abs(sum.real());
+			(*m_output)[k]=val;
+		}
+		(*m_output)[0]=0;
+	}
+
+protected:
+
+
+
+	float **m_input;
+	float **m_output;
+	Complex *m_input_complex;
+	Complex *m_output_complex;
+
+	long m_count;
+};
+
+
+
+uint64_t get_time_ns(){
+	struct timespec start;
+
+	if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
+	  perror( "clock gettime" );
+	  exit( EXIT_FAILURE );
+	}
+	return start.tv_sec * 1000000000 + start.tv_nsec;
+}
+
+
+class AudiToMidi {
+public:
+
+
+
+
+	static  LADSPA_Handle instanciate(const LADSPA_Descriptor *, unsigned long SampleRate){
+
+		return new AudiToMidi(SampleRate);
+	}
+
+	AudiToMidi(long sample_rate) : m_input_data(NULL), m_output_data(NULL), m_sample_rate(sample_rate) {
+		m_input_complex = fftw_alloc_complex(sample_rate);
+		m_output_complex = fftw_alloc_complex(sample_rate);
+		for(unsigned int i=0; i<sample_rate; i++){
+			m_output_complex[i][1] = m_input_complex[i][1] =0  ;
+		}
+		m_dftplan = fftw_plan_dft_1d(sample_rate, m_input_complex, m_output_complex, FFTW_FORWARD, FFTW_ESTIMATE);
+
+		count = 0;
+		m_fft = new CustomFft(&m_input_data, &m_output_data);
+	}
+
+	virtual ~AudiToMidi(){
+		fftw_destroy_plan(m_dftplan);
+		fftw_free(m_input_complex);
+		fftw_free(m_output_complex);
+	}
+
+	LADSPA_Data * m_input_data;
+	LADSPA_Data * m_output_data;
+	long  m_sample_rate;
+	fftw_complex* m_input_complex;
+	fftw_complex* m_output_complex;
+	int count;
+	fftw_plan m_dftplan;
+	CustomFft* m_fft;
+	SDLWindow m_window;
+
+	void activate(){
+
+	}
+
+	void connect(unsigned long port,  LADSPA_Data * data){
+		switch (port){
+			case INPUT_PORT: m_input_data = data; break;
+			case OUTPUT_PORT: m_output_data = data; break;
+		}
+	}
+
+
+	void run(long sc){
+
+		printf("RUN !!!!!!!\n");
+		m_fft->set_count(sc);
+
+		if(!m_input_data || !m_output_data) return;
+		uint64_t start, stop;
+		start = get_time_ns();
+		for(unsigned int i=0; i<sc; i++){
+			m_input_complex[i][0] = m_input_data[i] ;
+		}
+		fftw_execute(m_dftplan);
+		for(unsigned int i=0; i<sc; i++){
+			m_output_data[i] =isnan(m_output_complex[i][0])?0.0:m_output_complex[i][0] ;
+		}
+		m_window.set_value(NULL, sc);
+		//m_fft->execute();
+		count+=1;
+		stop = get_time_ns();
+		//m_window.set_value(m_output_data, sc);
+		printf("----- %d %d %lf ms\n", count, sc, ((double)(stop-start))/1000000);
+
+
+	}
+
+};
+
+static void activate_plugin(LADSPA_Handle Instance){
+	printf("activate_plugin\n");
+	((AudiToMidi*)Instance)->activate();
+}
+
+static void connect_plugin(LADSPA_Handle Instance, unsigned long SampleCount,  LADSPA_Data * data){
+	printf("connect_plugin\n");
+	return ((AudiToMidi*)Instance)->connect(SampleCount, data);
+}
+
+
+static void run(LADSPA_Handle Instance, unsigned long SampleCount){
+	((AudiToMidi*)Instance)->run(SampleCount);
+}
+
+
+static void cleanup(LADSPA_Handle insatnce){
+	printf("cleanup\n");
+	delete (AudiToMidi *)insatnce;
+}
+
+
+typedef char *char_ptr;
+
+static inline char *
+localStrdup(const char * input) {
+  char * output = new char[strlen(input) + 1];
+  strcpy(output, input);
+  return output;
+}
+
+static LADSPA_Descriptor *g_descriptors[1] = { NULL };
+
+
+
+const LADSPA_Descriptor *
+ladspa_descriptor(unsigned long Index) {
+  if (Index < PLUGIN_COUNT){
+    return g_descriptors[Index];
+  }else
+    return NULL;
+}
+
+
+/* Global object used handle startup initialisation and shut down
+ tidying. Performs the function of the _init() and _fini() calls in
+ the C modules.*/
+class StartupShutdownHandler {
+public:
+
+	StartupShutdownHandler() {
+		SDLWindow::init();
+		struct sched_param sp = { .sched_priority = 50 };
+		//sched_setscheduler(0, SCHED_FIFO, &sp);
+
+		char **pcPortNames;
+		LADSPA_PortDescriptor *port_descriptors;
+		LADSPA_PortRangeHint *port_range_hints;
+
+		for (long plugin_index = 0; plugin_index < PLUGIN_COUNT; plugin_index++) {
+
+			g_descriptors[plugin_index] = new LADSPA_Descriptor;
+			if (g_descriptors[plugin_index] == NULL)
+				break;
+
+			g_descriptors[plugin_index]->UniqueID = 1078 + plugin_index;
+			g_descriptors[plugin_index]->Properties =	LADSPA_PROPERTY_HARD_RT_CAPABLE;
+			g_descriptors[plugin_index]->Maker = localStrdup(
+					"François GAUTRAIS");
+			g_descriptors[plugin_index]->Copyright = localStrdup("None");
+			g_descriptors[plugin_index]->PortCount = PORT_COUNT;
+			port_descriptors = new LADSPA_PortDescriptor[PORT_COUNT];
+			g_descriptors[plugin_index]->PortDescriptors =
+					(const LADSPA_PortDescriptor*) port_descriptors;
+			port_descriptors[INPUT_PORT] = LADSPA_PORT_INPUT| LADSPA_PORT_AUDIO;
+			port_descriptors[OUTPUT_PORT] = LADSPA_PORT_OUTPUT| LADSPA_PORT_AUDIO;
+
+
+			pcPortNames = new char_ptr[PORT_COUNT];
+			g_descriptors[plugin_index]->PortNames = (const char**) pcPortNames;
+			pcPortNames[INPUT_PORT] = localStrdup("Entrée");
+			pcPortNames[OUTPUT_PORT] = localStrdup("Sortie");
+
+			port_range_hints = new LADSPA_PortRangeHint[PORT_COUNT];
+			g_descriptors[plugin_index]->PortRangeHints =
+					(const LADSPA_PortRangeHint*) port_range_hints;
+
+
+			port_range_hints[INPUT_PORT].HintDescriptor = 0;
+			port_range_hints[OUTPUT_PORT].HintDescriptor = 0;
+
+			g_descriptors[plugin_index]->instantiate = AudiToMidi::instanciate;
+			g_descriptors[plugin_index]->connect_port = connect_plugin;
+			g_descriptors[plugin_index]->activate = activate_plugin;
+			g_descriptors[plugin_index]->run_adding = NULL;
+			g_descriptors[plugin_index]->set_run_adding_gain = NULL;
+			g_descriptors[plugin_index]->deactivate = NULL;
+			g_descriptors[plugin_index]->cleanup = cleanup;
+
+			switch (plugin_index) {
+			case 0:
+				g_descriptors[plugin_index]->Label = localStrdup("audio_to_midi");
+				g_descriptors[plugin_index]->Name = localStrdup("Audio to midi");
+				g_descriptors[plugin_index]->run = run;
+				break;
+			}
+		}
+	}
+
+	void deleteDescriptor(LADSPA_Descriptor *psDescriptor) {
+		unsigned long lIndex;
+		if (psDescriptor) {
+			delete[] psDescriptor->Label;
+			delete[] psDescriptor->Name;
+			delete[] psDescriptor->Maker;
+			delete[] psDescriptor->Copyright;
+			delete[] psDescriptor->PortDescriptors;
+			for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
+				delete[] psDescriptor->PortNames[lIndex];
+			delete[] psDescriptor->PortNames;
+			delete[] psDescriptor->PortRangeHints;
+			delete psDescriptor;
+		}
+	}
+
+	~StartupShutdownHandler() {
+
+		for (long plugin_index = 0; plugin_index < PLUGIN_COUNT; plugin_index++) {
+			deleteDescriptor(g_descriptors[plugin_index]);
+		}
+	}
+
+};
+
+
+static StartupShutdownHandler g_oShutdownStartupHandler;

+ 14 - 0
src/plugins/AudiToMidi.h

@@ -0,0 +1,14 @@
+/*
+ * AudiToMidi.h
+ *
+ *  Created on: 16 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_PLUGINS_AUDITOMIDI_H_
+#define SRC_PLUGINS_AUDITOMIDI_H_
+
+
+
+
+#endif /* SRC_PLUGINS_AUDITOMIDI_H_ */

+ 9 - 0
src/plugins/LadspaPluginBase.cpp

@@ -0,0 +1,9 @@
+/*
+ * LadspaPluginBase.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "LadspaPluginBase.h"
+

+ 17 - 0
src/plugins/LadspaPluginBase.h

@@ -0,0 +1,17 @@
+/*
+ * LadspaPluginBase.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_PLUGINS_LADSPAPLUGINBASE_H_
+#define SRC_PLUGINS_LADSPAPLUGINBASE_H_
+
+#include <ladspa.h>
+
+
+class LadspaPluginBase {
+};
+
+#endif /* SRC_PLUGINS_LADSPAPLUGINBASE_H_ */

+ 55 - 0
src/plugins/SDLWindow.cpp

@@ -0,0 +1,55 @@
+/*
+ * SDLWindow.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "SDLWindow.h"
+
+SDLWindow::SDLWindow(int w, int h){
+	m_w = w;
+	m_h = h;
+	m_window =  SDL_CreateWindow("Ma première application SDL2",SDL_WINDOWPOS_UNDEFINED,
+			SDL_WINDOWPOS_UNDEFINED,
+			w,
+			h,
+			SDL_WINDOW_SHOWN);
+	m_renderer = SDL_CreateRenderer(m_window, -1, 0);
+
+	m_texture = SDL_CreateTexture(m_renderer,
+		SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
+	m_pixels = new Uint32[w*h];
+}
+SDLWindow::~SDLWindow(){
+	delete[] m_pixels;
+	SDL_DestroyTexture(m_texture);
+	SDL_DestroyRenderer(m_renderer);
+}
+
+void SDLWindow::init(){
+	SDL_Init(SDL_INIT_VIDEO);
+}
+
+void SDLWindow::update(){
+	SDL_UpdateTexture(m_texture, NULL, m_pixels, m_w* sizeof(Uint32));
+	SDL_RenderClear(m_renderer);
+	SDL_RenderCopy(m_renderer, m_texture, NULL, NULL);
+	SDL_RenderPresent(m_renderer);
+}
+
+
+void SDLWindow::set_value(float* value, int size, float ratio){
+
+	for(int i=0; i<m_h; i++){
+		for(int j=0; j<m_w; j++){
+			m_pixels[j+m_w*i] = 0;
+		}
+	}
+	for(int j=0; j<m_w; j+=2){
+		int h = ((value[j]*ratio) + m_h/2);
+		m_pixels[h*m_w+j] = 0xFFFFFF00;
+		m_pixels[h*m_w+j+1] = 0xFFFFFF00;
+	}
+	update();
+}

+ 34 - 0
src/plugins/SDLWindow.h

@@ -0,0 +1,34 @@
+/*
+ * SDLWindow.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_PLUGINS_SDLWINDOW_H_
+#define SRC_PLUGINS_SDLWINDOW_H_
+
+#include <SDL2/SDL.h>
+
+class SDLWindow {
+public:
+	SDLWindow(int w=1920, int h=1080);
+	void update();
+	virtual ~SDLWindow();
+	void set_value(float* value, int size, float ratio=1);
+
+
+	static void init();
+
+protected:
+	SDL_Window* m_window;
+	int m_w;
+	int m_h;
+	SDL_Renderer* m_renderer;
+	SDL_Texture* m_texture;
+	uint32_t* 	m_pixels;
+
+};
+
+
+#endif /* SRC_PLUGINS_SDLWINDOW_H_ */

+ 34 - 0
src/plugins/TestPlugin.cpp

@@ -0,0 +1,34 @@
+/*
+ * TestPlugin.cpp
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#include "TestPlugin.h"
+#include <string>
+
+int main(int argc, char** argv){
+	try {
+		TestPlugin plugins;
+		plugins.host.add_path("/home/fanch/Programmation/audio_renderer/debug/src/plugins/");
+		//plugins.host.add_path("/usr/lib/ladspa");
+		plugins.host.update();
+		PluginEntry& plugin = plugins.host.load_from_path("/home/fanch/Programmation/audio_renderer/debug/src/plugins/libaudio_to_midi.so");
+		printf("Add plugin\n");
+		FileSoundInput fsi("/home/fanch/Programmation/LADSPA/audio_to_midi/snd/yafs1.wav");
+
+		plugins.manager.set_rate(44100, 1024);
+		plugins.manager.add_plugin(plugin);
+
+
+		LADSPA_Data* buffer;
+		while ((buffer = fsi.next(buffer))){
+			plugins.manager.run(buffer);
+		}
+
+	} catch (const char* x) {
+		printf("Erreur: %s\n", x);
+	}
+
+}

+ 28 - 0
src/plugins/TestPlugin.h

@@ -0,0 +1,28 @@
+/*
+ * TestPlugin.h
+ *
+ *  Created on: 17 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_PLUGINS_TESTPLUGIN_H_
+#define SRC_PLUGINS_TESTPLUGIN_H_
+
+#include "../core/PluginIndex.h"
+#include "../core/PluginManager.h"
+#include "../io/FileSoundInput.h"
+
+struct TestPlugin {
+	TestPlugin() {
+
+	}
+
+	PluginIndex host;
+	PluginManager manager;
+
+};
+
+
+
+
+#endif /* SRC_PLUGINS_TESTPLUGIN_H_ */

+ 45 - 0
src/plugins/wscript

@@ -0,0 +1,45 @@
+from waf.waflib.TaskGen import feature
+
+
+
+
+def build(bld):
+    
+    
+    bld.objects(source=["LadspaPluginBase.cpp"], 
+                target="plugin_base",
+                includes = ['.','..'],
+    )
+    
+    bld.objects(source=["LadspaPluginBase.cpp"], 
+                target="plugin_base_sh",
+                cxxflags=bld.env.CXXFLAGS_cxxshlib,
+                includes = ['.','..'],
+    )
+    
+    bld.objects(source=["AudiToMidi.cpp", "SDLWindow.cpp"], 
+              use="plugin_base", 
+            includes = ['.','..'],
+              target="audio_to_midi_obj")
+    
+    bld.objects(source=["AudiToMidi.cpp", "SDLWindow.cpp"], 
+              use="plugin_base_sh", 
+            includes = ['.','..'],
+                cxxflags=bld.env.CXXFLAGS_cxxshlib,
+              target="audio_to_midi_obj_sh")
+    
+    bld.shlib(target="audio_to_midi", 
+              features="cxx cxxshlib", 
+                includes = ['.','..'],
+                lib=["fftw3", "SDL2", "SDL2_image"],          
+              use=["plugin_base_sh", "audio_to_midi_obj_sh"]
+    )
+    
+    
+    bld.program(source=["TestPlugin.cpp"], 
+                target="test_plugin",
+                includes = ['.','..'],
+                features=["cxx"], 
+                lib=["SDL2", "SDL2_image", "fftw3", "sndfile"],
+                use=["plugin_base", "audio_to_midi_obj", "core", "io"]
+    )

+ 1 - 0
waftools/.gitignore

@@ -0,0 +1 @@
+/__pycache__/

+ 0 - 0
waftools/__init__.py