Loading...
Searching...
No Matches
score-plugin-fx/Fx/Envelope.hpp
1#pragma once
2#include <Fx/Types.hpp>
3
4#include <halp/audio.hpp>
5#include <halp/callback.hpp>
6#include <halp/controls.hpp>
7#include <halp/meta.hpp>
8
9namespace Nodes
10{
11namespace Envelope
12{
13struct Node
14{
15 halp_meta(name, "Envelope")
16 halp_meta(c_name, "Envelope")
17 halp_meta(category, "Audio")
18 halp_meta(author, "ossia score")
19 halp_meta(manual_url, "https://ossia.io/score-docs/processes/analysis.html#envelope")
20 halp_meta(description, "Converts an audio signal into RMS and peak values")
21 halp_meta(uuid, "95F44151-13EF-4537-8189-0CC243341269");
22
23 using FP = double;
24 struct
25 {
26 halp::dynamic_audio_bus<"in", FP> audio;
27 } inputs;
28 struct
29 {
30 halp::callback<"rms", multichannel_output_type> rms;
31 halp::callback<"peak", multichannel_output_type> peak;
32 } outputs;
33
34 halp_flag(deprecated);
35
36 static auto get(const avnd::span<FP>& chan)
37 {
38 if(chan.size() > 0)
39 {
40 auto max = chan[0];
41 auto rms = 0.;
42 for(auto sample : chan)
43 {
44 max = std::max(max, std::abs(sample));
45 rms += sample * sample;
46 }
47 rms = std::sqrt(rms);
48 rms /= chan.size();
49
50 return std::make_pair(rms, max);
51 }
52 else
53 {
54 return std::make_pair(FP{}, FP{});
55 }
56 }
57
58 void operator()(int d)
59 {
60 auto& audio = inputs.audio;
61 switch(audio.channels)
62 {
63 case 0:
64 return;
65 case 1: {
66 auto [rms, peak] = get(audio.channel(0, d));
67 outputs.rms(rms);
68 outputs.peak(peak); // FIXME timestamp
69 break;
70 }
71 default: {
72 multichannel_output_vector peak_vec;
73 peak_vec.reserve(audio.channels);
74 multichannel_output_vector rms_vec;
75 rms_vec.reserve(audio.channels);
76 for(int i = 0; i < audio.channels; i++)
77 {
78 auto [rms, peak] = get(audio.channel(i, d));
79 rms_vec.push_back(rms);
80 peak_vec.push_back(peak);
81 }
82 outputs.rms(rms_vec);
83 outputs.peak(peak_vec); // FIXME timestamp
84 }
85 break;
86 }
87 }
88};
89}
90}
Definition score-plugin-fx/Fx/Envelope.hpp:14