|
@@ -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_ */
|