Serenity Operating System
at master 92 lines 3.0 kB view raw
1/* 2 * Copyright (c) 2021, kleines Filmröllchen <filmroellchen@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "Effects.h" 8#include <AK/FixedArray.h> 9#include <math.h> 10 11namespace DSP::Effects { 12 13Delay::Delay(NonnullRefPtr<Transport> transport) 14 : EffectProcessor(move(transport)) 15 , m_delay_decay("Decay"_short_string, 0.01, 0.99, 0.33, Logarithmic::No) 16 , m_delay_time("Delay Time"_string, 3, 2000, 900, Logarithmic::Yes) 17 , m_dry_gain("Dry"_short_string, 0, 1, 0.9, Logarithmic::No) 18{ 19 20 m_parameters.append(m_delay_decay); 21 m_parameters.append(m_delay_time); 22 m_parameters.append(m_dry_gain); 23 24 m_delay_time.register_change_listener([this](auto const&) { 25 this->handle_delay_time_change(); 26 }); 27 handle_delay_time_change(); 28} 29 30void Delay::handle_delay_time_change() 31{ 32 // We want a delay buffer that can hold samples filling the specified number of milliseconds. 33 double seconds = static_cast<double>(m_delay_time) / 1000.0; 34 size_t sample_count = ceil(seconds * m_transport->sample_rate()); 35 if (sample_count != m_delay_buffer.size()) { 36 m_delay_buffer.resize(sample_count, true); 37 m_delay_index %= max(m_delay_buffer.size(), 1); 38 } 39} 40 41void Delay::process_impl(Signal const& input_signal, Signal& output_signal) 42{ 43 auto const& samples = input_signal.get<FixedArray<Sample>>(); 44 auto& output = output_signal.get<FixedArray<Sample>>(); 45 for (size_t i = 0; i < output.size(); ++i) { 46 auto& out = output[i]; 47 auto const& sample = samples[i]; 48 out += sample.log_multiplied(static_cast<double>(m_dry_gain)); 49 out += m_delay_buffer[m_delay_index].log_multiplied(m_delay_decay); 50 51 // This is also convenient for disabling the delay effect by setting the buffer size to 0 52 if (m_delay_buffer.size() >= 1) 53 m_delay_buffer[m_delay_index++] = out; 54 55 if (m_delay_index >= m_delay_buffer.size()) 56 m_delay_index = 0; 57 } 58} 59 60Mastering::Mastering(NonnullRefPtr<Transport> transport) 61 : EffectProcessor(move(transport)) 62 , m_pan("Pan"_short_string, -1, 1, 0, Logarithmic::No) 63 , m_volume("Volume"_short_string, 0, 1, 1, Logarithmic::No) 64 , m_muted("Mute"_short_string, false) 65{ 66 m_parameters.append(m_muted); 67 m_parameters.append(m_volume); 68 m_parameters.append(m_pan); 69} 70 71void Mastering::process_impl(Signal const& input_signal, Signal& output) 72{ 73 process_to_fixed_array(input_signal, output.get<FixedArray<Sample>>()); 74} 75 76void Mastering::process_to_fixed_array(Signal const& input_signal, FixedArray<Sample>& output) 77{ 78 if (m_muted) { 79 output.fill_with({}); 80 return; 81 } 82 83 auto const& input = input_signal.get<FixedArray<Sample>>(); 84 for (size_t i = 0; i < input.size(); ++i) { 85 auto sample = input[i]; 86 sample.log_multiply(static_cast<float>(m_volume)); 87 sample.pan(static_cast<float>(m_pan)); 88 output[i] = sample; 89 } 90} 91 92}