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 / chan.size());
48
49 return std::make_pair(rms, max);
50 }
51 else
52 {
53 return std::make_pair(FP{}, FP{});
54 }
55 }
56
57 void operator()(int d)
58 {
59 auto& audio = inputs.audio;
60 switch(audio.channels)
61 {
62 case 0:
63 return;
64 case 1: {
65 auto [rms, peak] = get(audio.channel(0, d));
66 outputs.rms(rms);
67 outputs.peak(peak); // FIXME timestamp
68 break;
69 }
70 default: {
71 multichannel_output_vector peak_vec;
72 peak_vec.reserve(audio.channels);
73 multichannel_output_vector rms_vec;
74 rms_vec.reserve(audio.channels);
75 for(int i = 0; i < audio.channels; i++)
76 {
77 auto [rms, peak] = get(audio.channel(i, d));
78 rms_vec.push_back(rms);
79 peak_vec.push_back(peak);
80 }
81 outputs.rms(rms_vec);
82 outputs.peak(peak_vec); // FIXME timestamp
83 }
84 break;
85 }
86 }
87};
88}
89}
Definition score-plugin-fx/Fx/Envelope.hpp:14