@@ -13,7 +13,7 @@ namespace zlp {
1313 namespace {
1414 template <size_t Mask>
1515 void dispatchMask (Controller* instance) {
16- instance->processImpl <
16+ instance->processMainImpl <
1717 (Mask & 1 ) != 0 ,
1818 (Mask & 2 ) != 0 ,
1919 (Mask & 4 ) != 0 ,
@@ -24,7 +24,7 @@ namespace zlp {
2424
2525 template <size_t ... Is>
2626 constexpr std::array<void (*)(Controller*), sizeof ...(Is)> makeDispatchTable (std::index_sequence<Is...>) {
27- return { &dispatchMask<Is>... };
27+ return {&dispatchMask<Is>...};
2828 }
2929
3030 constexpr auto dispatcher = makeDispatchTable(std::make_index_sequence<32 >{});
@@ -38,21 +38,106 @@ namespace zlp {
3838
3939 }
4040
41- void Controller::process (const bool is_bypass) {
42- processSide ();
43- processDynamicBands (stereo_data_);
44- processDynamicBands (l_data_);
45- processDynamicBands (r_data_);
46- processDynamicBands (m_data_);
47- processDynamicBands (s_data_);
48- processMain (is_bypass);
41+ void Controller::process (const std::array<float *, 4 >& buffer, const size_t num_samples, const bool is_bypass) {
42+ size_t samples_processed = 0 ;
43+ const bool requires_side = (side_status_ != SideStatus::kNotRequired );
44+
45+ while (samples_processed < num_samples) {
46+ // copy data to FIFO until reach a hop size or buffer size
47+ const size_t chunk = std::min (num_samples - samples_processed, fft_hop_size_ - fft_count_);
48+ const size_t chunk1 = std::min (chunk, fft_size_ - fft_pos_);
49+ const size_t chunk2 = chunk - chunk1;
50+ for (size_t chan = 0 ; chan < 2 ; ++chan) {
51+ std::copy_n (buffer[chan] + samples_processed, chunk1,
52+ input_fifos_[chan].data () + fft_pos_);
53+ if (chunk2 > 0 ) {
54+ std::copy_n (buffer[chan] + samples_processed + chunk1, chunk2,
55+ input_fifos_[chan].data ());
56+ }
57+ std::copy_n (output_fifos_[chan].data () + fft_pos_, chunk1,
58+ buffer[chan] + samples_processed);
59+ if (chunk2 > 0 ) {
60+ std::copy_n (output_fifos_[chan].data (), chunk2,
61+ buffer[chan] + samples_processed + chunk1);
62+ }
63+ std::fill_n (output_fifos_[chan].data () + fft_pos_, chunk1, 0 .0f );
64+ if (chunk2 > 0 ) {
65+ std::fill_n (output_fifos_[chan].data (), chunk2, 0 .0f );
66+ }
67+ }
68+ if (requires_side) {
69+ for (size_t chan = 2 ; chan < 4 ; ++chan) {
70+ std::copy_n (buffer[chan] + samples_processed, chunk1,
71+ input_fifos_[chan].data () + fft_pos_);
72+ if (chunk2 > 0 ) {
73+ std::copy_n (buffer[chan] + samples_processed + chunk1, chunk2,
74+ input_fifos_[chan].data ());
75+ }
76+ }
77+ }
78+ // forward FFT pos
79+ fft_pos_ += chunk;
80+ if (fft_pos_ >= fft_size_) {
81+ fft_pos_ -= fft_size_;
82+ }
83+ fft_count_ += chunk;
84+ // if reach a hop size, process spectrum
85+ if (fft_count_ >= fft_hop_size_) {
86+ fft_count_ = 0 ;
87+ // copy to FFT working space
88+ for (size_t chan = 0 ; chan < 2 ; ++chan) {
89+ std::copy_n (input_fifos_[chan].data () + fft_pos_, fft_size_ - fft_pos_,
90+ fft_ins_[chan].data ());
91+ if (fft_pos_ > 0 ) {
92+ std::copy_n (input_fifos_[chan].data (), fft_pos_,
93+ fft_ins_[chan].data () + fft_size_ - fft_pos_);
94+ }
95+ }
96+ if (requires_side) {
97+ for (size_t chan = 2 ; chan < 4 ; ++chan) {
98+ std::copy_n (input_fifos_[chan].data () + fft_pos_, fft_size_ - fft_pos_,
99+ fft_ins_[chan].data ());
100+ if (fft_pos_ > 0 ) {
101+ std::copy_n (input_fifos_[chan].data (), fft_pos_,
102+ fft_ins_[chan].data () + fft_size_ - fft_pos_);
103+ }
104+ }
105+ processSide ();
106+ processDynamicBands (stereo_data_);
107+ processDynamicBands (l_data_);
108+ processDynamicBands (r_data_);
109+ processDynamicBands (m_data_);
110+ processDynamicBands (s_data_);
111+ }
112+ processMain (is_bypass);
113+ // overlap-add
114+ const size_t range1 = fft_size_ - fft_pos_;
115+ for (size_t chan = 0 ; chan < 2 ; ++chan) {
116+ {
117+ auto * HWY_RESTRICT out_ptr = output_fifos_[chan].data () + fft_pos_;
118+ const auto * HWY_RESTRICT in_ptr = fft_ins_[chan].data ();
119+ for (size_t k = 0 ; k < range1; k += lanes) {
120+ const auto v_out = hn::Load (d, out_ptr + k);
121+ const auto v_in = hn::Load (d, in_ptr + k);
122+ hn::Store (hn::Add (v_out, v_in), d, out_ptr + k);
123+ }
124+ }
125+ {
126+ auto * HWY_RESTRICT out_ptr = output_fifos_[chan].data ();
127+ const auto * HWY_RESTRICT in_ptr = fft_ins_[chan].data () + range1;
128+ for (size_t k = 0 ; k < fft_pos_; k += lanes) {
129+ const auto v_out = hn::Load (d, out_ptr + k);
130+ const auto v_in = hn::Load (d, in_ptr + k);
131+ hn::Store (hn::Add (v_out, v_in), d, out_ptr + k);
132+ }
133+ }
134+ }
135+ }
136+ samples_processed += chunk;
137+ }
49138 }
50139
51140 void Controller::processSide () {
52- if (side_status_ == SideStatus::kNotRequired ) {
53- return ;
54- }
55- // side FFT FIFO in
56141 if (side_status_ == SideStatus::kLR ) {
57142 processSideLR ();
58143 } else if (side_status_ == SideStatus::kMS ) {
@@ -63,13 +148,11 @@ namespace zlp {
63148 }
64149
65150 void Controller::processMain (const bool is_bypass) {
66- // main FFT FIFO in
67151 if (is_bypass) {
68152 dispatcher[0 ](this );
69153 } else {
70154 dispatcher[dispatch_mask_](this );
71155 }
72- // main FFT FIFO out
73156 }
74157
75158 void Controller::processSideLR () {
@@ -266,7 +349,7 @@ namespace zlp {
266349 }
267350
268351 template <bool has_stereo, bool has_l, bool has_r, bool has_m, bool has_s>
269- void Controller::processImpl () {
352+ void Controller::processMainImpl () {
270353 if constexpr (!(has_stereo || has_l || has_r || has_m || has_s)) {
271354 zldsp::vector::multiply (fft_ins_[0 ].data (), window_bypass_.data (), fft_size_);
272355 zldsp::vector::multiply (fft_ins_[1 ].data (), window_bypass_.data (), fft_size_);
0 commit comments