Browse Source

Contoniue on translation freq -> midi

fanch 1 year ago
parent
commit
ca5754ea6a

+ 47 - 3
src/core/NoteSpectrum.cpp → src/common/NoteSpectrum.cpp

@@ -7,9 +7,10 @@
 
 
 #include "NoteSpectrum.h"
 #include "NoteSpectrum.h"
 
 
-NoteSpectrum::NoteSpectrum() {
-	// TODO Auto-generated constructor stub
-
+NoteSpectrum::NoteSpectrum(LADSPA_Data* data, unsigned long sample_count,  unsigned long sample_rate) {
+	m_sample_rate = sample_rate;
+	m_sample_count = sample_count;
+	_read(data);
 }
 }
 
 
 NoteSpectrum::~NoteSpectrum() {
 NoteSpectrum::~NoteSpectrum() {
@@ -17,6 +18,48 @@ NoteSpectrum::~NoteSpectrum() {
 }
 }
 
 
 
 
+void NoteSpectrum::_read(LADSPA_Data *data) {
+	// assume that each data item in [0,1]
+	const int istart = 28;
+	int ileft, iright;
+	float current_freq;
+	memset(m_values, 0, sizeof(NoteValue)*NOTE_COUNT);
+	int imax=0, jmax=0, vmax=0;
+	float max=0;
+	for(int i=0; i<m_sample_count; i++ ){
+		if(data[i]>max){
+			max=data[i];
+			imax=i;
+		}
+	}
+
+
+	// start with midi note istart (to have a suffisant frequncy)
+	for(int i=istart; i<NOTE_COUNT; i++){
+		const float target_frequency = Notes[i].frequency;
+		if(i==127){
+			i = 127;
+		}
+		if(i<=istart){
+			ileft = istart-1;
+		}else{
+			ileft = frequency_to_index(midi_to_frequency(i-0.5));
+		}
+
+		if(i==NOTE_COUNT-1){
+			iright = istart + (frequency_to_index(target_frequency)-ileft);
+		}else{
+			iright = frequency_to_index(midi_to_frequency(i+0.5));
+		}
+		set_value(data, ileft, i, iright, m_values[i]);
+
+		if(m_values[i].velocity>vmax){
+			vmax=m_values[i].velocity;
+			jmax=i;
+		}
+	}
+	return;
+}
 
 
 const Note Notes[128] = {
 const Note Notes[128] = {
 		Note(0),
 		Note(0),
@@ -148,3 +191,4 @@ const Note Notes[128] = {
 		Note(126),
 		Note(126),
 		Note(127)
 		Note(127)
 };
 };
+

+ 104 - 0
src/common/NoteSpectrum.h

@@ -0,0 +1,104 @@
+/*
+ * NoteSpectrum.h
+ *
+ *  Created on: 27 déc. 2023
+ *      Author: fanch
+ */
+
+#ifndef SRC_PLUGINS_NOTESPECTRUM_H_
+#define SRC_PLUGINS_NOTESPECTRUM_H_
+#include <string>
+#include <cstdint>
+#include <cstring>
+#include <cmath>
+#include <ladspa.h>
+
+
+
+inline float midi_to_frequency(float midi){
+	return 440.0 * pow(2, (midi-69)/12.0);
+}
+
+struct Note {
+	constexpr static const char NOTE_LETTERS[12][3]  = {"A", "A#", "B", "C", "C#", "D", "D#",  "E", "F", "F#", "G", "G#"};
+	const uint8_t NOTE_COUNT = 12;
+	std::string fullname;
+	uint8_t note;
+	int8_t octave;
+	const char* letter;
+	float frequency;
+	uint8_t midi;
+
+	Note(int m){
+		char tmp[8];
+		midi = m;
+		frequency = 440.0 * pow(2, (midi-69)/12.0);
+		octave = midi /12-1;
+		note = (midi+3) % 12;
+		letter = NOTE_LETTERS[note];
+		sprintf(tmp, "%s%d", letter, octave);
+		fullname = tmp;
+	}
+};
+
+
+
+extern const Note Notes[128];
+
+struct NoteValue {
+	uint8_t velocity;
+	uint8_t precision;
+};
+
+constexpr size_t NOTE_COUNT = 128;
+
+
+class NoteSpectrum {
+public:
+	NoteSpectrum(LADSPA_Data* data, unsigned long sample_count,  unsigned long );
+	virtual ~NoteSpectrum();
+
+	const NoteValue* get_values() const {
+		return m_values;
+	}
+
+protected:
+	inline float index_to_frequency(unsigned int index) const {
+		return index*m_sample_rate/(static_cast<float>(m_sample_count));
+	}
+
+	inline unsigned int frequency_to_index(float freq) const {
+		int index = (freq * m_sample_count) / m_sample_rate;
+		if(index<0) return 0;
+		if(index>m_sample_count) return m_sample_count;
+		return index;
+	}
+
+	inline void set_value(LADSPA_Data* data, uint32_t imin, uint32_t itarget, uint32_t imax, NoteValue& value) const {
+		const int dist = imax-imin;
+		const float target_value = data[itarget];
+		uint32_t max_index=imin, iratio;
+		float max_value=data[max_index], iter, vratio, result_dist;
+		for(int i = imin+1; i<=imax; i++){
+			iter = data[i];
+			if(max_value>iter){
+				max_value = iter;
+				max_index = i;
+			}
+		}
+		iratio = abs((max_index-itarget) / ((float) dist)); // [0, 1]
+		vratio = (max_value - target_value) / max_value; // [0, 1]
+		result_dist = sqrt(iratio*iratio + vratio*vratio);
+		value.precision =(uint8_t)(result_dist*255);
+		value.velocity = (uint8_t)(max_value * 255);
+	}
+
+	void _read(LADSPA_Data* data);
+
+
+	unsigned long m_sample_rate;
+	unsigned long m_sample_count;
+	NoteValue m_values[128];
+};
+
+#endif /* SRC_PLUGINS_NOTESPECTRUM_H_ */

+ 5 - 0
src/common/tools.cpp

@@ -7,3 +7,8 @@
 
 
 #include "tools.h"
 #include "tools.h"
 
 
+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);
+}

+ 1 - 6
src/common/tools.h

@@ -11,12 +11,7 @@
 #include <cstring>
 #include <cstring>
 #include <cstdio>
 #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);
-}
-
+bool endswith(const char* src, const char* dst);
 
 
 
 
 #endif /* SRC_COMMON_TOOLS_H_ */
 #endif /* SRC_COMMON_TOOLS_H_ */

+ 6 - 0
src/common/wscript

@@ -4,4 +4,10 @@ def build(bld):
     bld.objects(source=bld.get_sub_files(max_depth=1), 
     bld.objects(source=bld.get_sub_files(max_depth=1), 
                 target="common",
                 target="common",
                 includes = ['.','..'],
                 includes = ['.','..'],
+        )
+    
+    bld.objects(source=bld.get_sub_files(max_depth=1), 
+                target="common_sh",
+                cxxflags=bld.env.CXXFLAGS_cxxshlib,
+                includes = ['.','..'],
         )
         )

+ 0 - 47
src/core/NoteSpectrum.h

@@ -1,47 +0,0 @@
-/*
- * NoteSpectrum.h
- *
- *  Created on: 27 déc. 2023
- *      Author: fanch
- */
-
-#ifndef SRC_PLUGINS_NOTESPECTRUM_H_
-#define SRC_PLUGINS_NOTESPECTRUM_H_
-#include <string>
-#include <cstdint>
-#include <cstring>
-#include <cmath>
-
-
-struct Note {
-	constexpr static const char NOTE_LETTERS[12][3]  = {"A", "A#", "B", "C", "C#", "D", "D#",  "E", "F", "F#", "G", "G#"};
-	const uint8_t NOTE_COUNT = 12;
-	std::string fullname;
-	uint8_t note;
-	int8_t octave;
-	const char* letter;
-	float frequency;
-	uint8_t midi;
-
-	Note(int m){
-		midi = m;
-		frequency = 440.0 * pow(2, (midi-69)/12);
-		octave = midi /12-1;
-		note = (midi+3) % 12;
-		letter = NOTE_LETTERS[note];
-	}
-};
-
-
-
-extern const Note Notes[128];
-
-
-
-class NoteSpectrum {
-public:
-	NoteSpectrum();
-	virtual ~NoteSpectrum();
-};
-
-#endif /* SRC_PLUGINS_NOTESPECTRUM_H_ */

+ 1 - 2
src/core/wscript

@@ -2,8 +2,7 @@ core_sources = [
         "PluginIndex.cpp",
         "PluginIndex.cpp",
         "PluginHost.cpp",
         "PluginHost.cpp",
         "PluginInstance.cpp",
         "PluginInstance.cpp",
-        "PluginManager.cpp",
-        "NoteSpectrum.cpp"
+        "PluginManager.cpp"
 ]
 ]
 
 
 
 

+ 5 - 3
src/plugins/AudiToMidi.cpp

@@ -18,7 +18,7 @@
 #include <time.h>
 #include <time.h>
 /* The port numbers for the plugin: */
 /* The port numbers for the plugin: */
 #include "SDLWindow.h"
 #include "SDLWindow.h"
-
+#include "common/NoteSpectrum.h"
 
 
 #define PLUGIN_COUNT 1
 #define PLUGIN_COUNT 1
 #define PORT_COUNT 2
 #define PORT_COUNT 2
@@ -189,13 +189,15 @@ public:
 		if(m_output_data){
 		if(m_output_data){
 			for(unsigned int i=0; i<sc; i++){
 			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_output_data[i] =isnan(m_output_complex[i][0])?0.0:m_output_complex[i][0] ;
-				m_output_data[i] = m_output_complex[i][0];
+				m_output_data[i] = abs(m_output_complex[i][0]);
 			}
 			}
-			m_window.set_value(m_output_data, sc);
+			NoteSpectrum spect(m_output_data, sc, m_sample_rate);
+			m_window.set_value(spect.get_values(), 10);
 		}
 		}
 
 
 
 
 
 
+
 		count+=1;
 		count+=1;
 		stop = get_time_ns();
 		stop = get_time_ns();
 		/*printf("----- %d %d %lf us\n",
 		/*printf("----- %d %d %lf us\n",

+ 22 - 7
src/plugins/SDLWindow.cpp

@@ -6,7 +6,7 @@
  */
  */
 
 
 #include "SDLWindow.h"
 #include "SDLWindow.h"
-
+#include "common/NoteSpectrum.h"
 SDLWindow::SDLWindow(int w, int h){
 SDLWindow::SDLWindow(int w, int h){
 	m_w = w;
 	m_w = w;
 	m_h = h;
 	m_h = h;
@@ -40,12 +40,7 @@ void SDLWindow::update(){
 
 
 
 
 void SDLWindow::set_value(float* value, int size, float ratio){
 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;
-		}
-	}
+	memset(m_pixels, 0, sizeof(*m_pixels) * m_w*m_h );
 	for(int j=0; j<m_w; j+=2){
 	for(int j=0; j<m_w; j+=2){
 		int h = ((value[j]*ratio) + m_h/2);
 		int h = ((value[j]*ratio) + m_h/2);
 		if(h<0) h=0;
 		if(h<0) h=0;
@@ -55,3 +50,23 @@ void SDLWindow::set_value(float* value, int size, float ratio){
 	}
 	}
 	update();
 	update();
 }
 }
+
+void SDLWindow::set_value(const NoteValue* value, float ratio){
+	memset(m_pixels, 0, sizeof(*m_pixels) * m_w*m_h );
+	const int w = m_w/256;
+
+	for(int i=0; i<128; i++){
+		for(int j=i*w; j<i*w+w; j++){
+			int h = ((value[i].velocity*0.5) + m_h/2);
+			if(h<0) h=0;
+			if(h>=m_h) h=m_h-1;
+			uint32_t color =((value[i].precision) * 256 * 256) + 128*256 ;
+
+			for(int k=m_h-h; k<m_h-10; k++){
+				m_pixels[k*m_w+j] = color;
+			}
+		}
+
+	}
+	update();
+}

+ 2 - 1
src/plugins/SDLWindow.h

@@ -9,13 +9,14 @@
 #define SRC_PLUGINS_SDLWINDOW_H_
 #define SRC_PLUGINS_SDLWINDOW_H_
 
 
 #include <SDL2/SDL.h>
 #include <SDL2/SDL.h>
-
+struct NoteValue;
 class SDLWindow {
 class SDLWindow {
 public:
 public:
 	SDLWindow(int w=1920, int h=1080);
 	SDLWindow(int w=1920, int h=1080);
 	void update();
 	void update();
 	virtual ~SDLWindow();
 	virtual ~SDLWindow();
 	void set_value(float* value, int size, float ratio=1);
 	void set_value(float* value, int size, float ratio=1);
+	void set_value(const NoteValue* value, float ratio=1);
 
 
 
 
 	static void init();
 	static void init();

+ 3 - 3
src/plugins/wscript

@@ -14,7 +14,7 @@ def build(bld):
     bld.objects(source=["LadspaPluginBase.cpp"], 
     bld.objects(source=["LadspaPluginBase.cpp"], 
                 target="plugin_base_sh",
                 target="plugin_base_sh",
                 cxxflags=bld.env.CXXFLAGS_cxxshlib,
                 cxxflags=bld.env.CXXFLAGS_cxxshlib,
-                includes = ['.','..'],
+                includes = ['.','..']
     )
     )
     
     
     bld.objects(source=["AudiToMidi.cpp", "SDLWindow.cpp"], 
     bld.objects(source=["AudiToMidi.cpp", "SDLWindow.cpp"], 
@@ -32,7 +32,7 @@ def build(bld):
               features="cxx cxxshlib", 
               features="cxx cxxshlib", 
                 includes = ['.','..'],
                 includes = ['.','..'],
                 lib=["fftw3", "SDL2", "SDL2_image"],          
                 lib=["fftw3", "SDL2", "SDL2_image"],          
-              use=["plugin_base_sh", "audio_to_midi_obj_sh"]
+              use=["plugin_base_sh", "audio_to_midi_obj_sh", "common_sh"]
     )
     )
     
     
     
     
@@ -41,5 +41,5 @@ def build(bld):
                 includes = ['.','..'],
                 includes = ['.','..'],
                 features=["cxx"], 
                 features=["cxx"], 
                 lib=["SDL2", "SDL2_image", "fftw3", "sndfile"],
                 lib=["SDL2", "SDL2_image", "fftw3", "sndfile"],
-                use=["plugin_base", "audio_to_midi_obj", "core", "io"]
+                use=["plugin_base", "common", "core", "io"]
     )
     )

+ 2 - 5
wscript

@@ -29,7 +29,7 @@ class TestRecognizer:
             "target" : self.file.name.replace(".cpp", ""),
             "target" : self.file.name.replace(".cpp", ""),
             "includes" : [".", "..", str(self.src_dir), str(self.tests_dir)],
             "includes" : [".", "..", str(self.src_dir), str(self.tests_dir)],
             "lib" : ["SDL2", "SDL2_image", "fftw3", "sndfile"],
             "lib" : ["SDL2", "SDL2_image", "fftw3", "sndfile"],
-            "use" : ["io", "core", ]
+            "use" : ["io", "core", "common"]
             
             
         }
         }
     
     
@@ -139,10 +139,7 @@ def build(bld):
     bld.recurse("src/io")
     bld.recurse("src/io")
     bld.recurse("src/plugins")
     bld.recurse("src/plugins")
     bld.recurse("tests")
     bld.recurse("tests")
-    bld.program(target=APPNAME, 
-                features='cxx cxxprogram',
-                lib=['fftw3', "sndfile"], 
-                use=["common", "fft", "io"])
+
 
 
 def test(bld):
 def test(bld):
     pass
     pass