summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/audio_effects/eq.h
blob: 919d5292837a58b16127e2ddbc58438239fe9b45 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert

#pragma once

#ifndef MAME_EMU_AUDIO_EFFECTS_EQ_H
#define MAME_EMU_AUDIO_EFFECTS_EQ_H

#include "aeffect.h"

class audio_effect_eq : public audio_effect
{
public:
	enum { BANDS = 5 };

	audio_effect_eq(u32 sample_rate, audio_effect *def);
	virtual ~audio_effect_eq() = default;

	virtual int type() const override { return EQ; }
	virtual void apply(const emu::detail::output_buffer_flat<sample_t> &src, emu::detail::output_buffer_flat<sample_t> &dest) override;
	virtual void config_load(util::xml::data_node const *ef_node) override;
	virtual void config_save(util::xml::data_node *ef_node) const override;
	virtual void default_changed() override;

	void set_mode(u32 mode);
	void set_q(u32 band, float q);
	void set_f(u32 band, float f);
	void set_db(u32 band, float db);
	void set_low_shelf(bool active);
	void set_high_shelf(bool active);

	u32 mode() const         { return m_mode; }
	float q(u32 band) const  { return m_q[band]; }
	float f(u32 band) const  { return m_f[band]; }
	float db(u32 band) const { return m_db[band]; }
	bool low_shelf() const   { return m_low_shelf; }
	bool high_shelf() const  { return m_high_shelf; }

	bool isset_mode() const       { return m_isset_mode; }
	bool isset_q(u32 band) const  { return m_isset_q[band]; }
	bool isset_f(u32 band) const  { return m_isset_f[band]; }
	bool isset_db(u32 band) const { return m_isset_db[band]; }
	bool isset_low_shelf() const  { return m_isset_low_shelf; }
	bool isset_high_shelf() const { return m_isset_high_shelf; }

	void reset_mode();
	void reset_q(u32 band);
	void reset_f(u32 band);
	void reset_db(u32 band);
	void reset_low_shelf();
	void reset_high_shelf();

private:
	struct history {
		float m_v0, m_v1, m_v2;
		history() { m_v0 = m_v1 = m_v2 = 0; }
		void push(float v) { m_v2 = m_v1; m_v1 = m_v0; m_v0 = v; }
	};

	struct filter {
		float m_a1, m_a2, m_b0, m_b1, m_b2;
		void clear() { m_a1 = 0; m_a2 = 0; m_b0 = 1; m_b1 = 0; m_b2 = 0; }
		void apply(history &x, history &y) const {
			y.push(m_b0 * x.m_v0 + m_b1 * x.m_v1 + m_b2 * x.m_v2 - m_a1 * y.m_v0 - m_a2 * y.m_v1);
		}
	};

	u32 m_mode;
	float m_q[BANDS], m_f[BANDS], m_db[BANDS];
	bool m_low_shelf, m_high_shelf;
	std::array<filter, BANDS> m_filter;
	std::vector<std::array<history, BANDS+1>> m_history;

	bool m_isset_mode, m_isset_low_shelf, m_isset_high_shelf;
	bool m_isset_q[BANDS], m_isset_f[BANDS], m_isset_db[BANDS];

	void build_filter(u32 band);

	void build_low_shelf(u32 band);
	void build_high_shelf(u32 band);
	void build_peak(u32 band);
};

#endif