Pitch.hpp
1 #pragma once
2 #include <Analysis/GistState.hpp>
3 #include <Analysis/Helpers.hpp>
4 #include <halp/audio.hpp>
5 #include <halp/callback.hpp>
6 #include <halp/controls.hpp>
7 #include <halp/meta.hpp>
8 
9 #if defined(OSSIA_ENABLE_KFR)
10 #include <kfr/base.hpp>
11 #include <kfr/dsp.hpp>
12 #endif
13 
14 namespace Analysis
15 {
16 #if defined(OSSIA_ENABLE_KFR)
17 struct PitchState : Analysis::GistState
18 {
19  PitchState()
20  : hipass{kfr::to_sos(
21  kfr::iir_highpass(kfr::butterworth<double>(12), 200, this->rate))}
22  {
23  }
24 
25  void filter(halp::dynamic_audio_bus_base<double>& in, int d)
26  {
27  while(hipass.size() < in.channels)
28  {
29  hipass.emplace_back(
30  kfr::to_sos(kfr::iir_highpass(kfr::butterworth<double>(12), 200, this->rate)));
31  }
32 
33  int c = 0;
34  for(double* chan : in)
35  {
36  hipass[c++].apply(chan, d);
37  }
38  }
39 
40  using hipass_t = decltype(kfr::to_sos(
41  kfr::iir_highpass(kfr::zpk<double>{}, kfr::identity<double>{})));
42  std::vector<kfr::iir_filter<double>> hipass;
43 };
44 #else
45 using PitchState = GistState;
46 #endif
47 
48 struct Pitch : PitchState
49 {
50  halp_meta(name, "Pitch detector")
51  halp_meta(c_name, "Pitch")
52  halp_meta(category, "Analysis/Pitch")
53  halp_meta(author, "ossia score, Gist library")
54  halp_meta(manual_url, "https://ossia.io/score-docs/processes/analysis.html#pitch-detection")
55  halp_meta(description, "Get the pitch of a signal")
56  halp_meta(uuid, "ed511605-8265-4b2c-8c4b-d3b189539b3b");
57 
58  struct
59  {
60  audio_in audio;
61  } inputs;
62  struct
63  {
64  value_out result;
65  } outputs;
66 
67  void operator()(int frames)
68  {
69  if(inputs.audio.channels == 0)
70  return;
71 
72 #if defined(OSSIA_ENABLE_KFR)
73  filter(inputs.audio, frames);
74 #endif
75  process<&Gist<double>::pitch>(inputs.audio, outputs.result, frames);
76  }
77 };
78 }
Definition: GistState.hpp:26
Definition: Pitch.hpp:49
Definition: Helpers.hpp:27
Definition: Helpers.hpp:19