aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/plugins/PluginMixBuffer.h
blob: 55178778509e3b9e89817d679121dc0096bfd0da (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * PluginMixBuffer.h
 * -----------------
 * Purpose: Helper class for managing plugin audio input and output buffers.
 * Notes  : (currently none)
 * Authors: OpenMPT Devs
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */


#pragma once

#include "openmpt/all/BuildSettings.hpp"

#include <algorithm>
#include <array>

#if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST)
#include "mpt/base/aligned_array.hpp"
#endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST


OPENMPT_NAMESPACE_BEGIN


// At least this part of the code is ready for double-precision rendering... :>
// buffer_t: Sample buffer type (float, double, ...)
// bufferSize: Buffer size in samples
template<typename buffer_t, uint32 bufferSize>
class PluginMixBuffer
{

private:

#if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST)
	static constexpr std::align_val_t alignment = std::align_val_t{16};
	static_assert(sizeof(mpt::aligned_array<buffer_t, bufferSize, alignment>) == sizeof(std::array<buffer_t, bufferSize>));
	static_assert(alignof(mpt::aligned_array<buffer_t, bufferSize, alignment>) == static_cast<std::size_t>(alignment));
#endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST

protected:

#if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST)
	std::vector<mpt::aligned_array<buffer_t, bufferSize, alignment>> inputs;
	std::vector<mpt::aligned_array<buffer_t, bufferSize, alignment>> outputs;
#else // !(MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST)
	std::vector<std::array<buffer_t, bufferSize>> inputs;
	std::vector<std::array<buffer_t, bufferSize>> outputs;
#endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST
	std::vector<buffer_t*> inputsarray;
	std::vector<buffer_t*> outputsarray;

public:

	// Allocate input and output buffers
	bool Initialize(uint32 numInputs, uint32 numOutputs)
	{
		// Short cut - we do not need to recreate the buffers.
		if(inputs.size() == numInputs && outputs.size() == numOutputs)
		{
			return true;
		}

		try
		{
			inputs.resize(numInputs);
			outputs.resize(numOutputs);
			inputsarray.resize(numInputs);
			outputsarray.resize(numOutputs);
		} catch(mpt::out_of_memory e)
		{
			mpt::delete_out_of_memory(e);
			inputs.clear();
			inputs.shrink_to_fit();
			outputs.clear();
			outputs.shrink_to_fit();
			inputsarray.clear();
			inputsarray.shrink_to_fit();
			outputsarray.clear();
			outputsarray.shrink_to_fit();
			return false;
		}

		for(uint32 i = 0; i < numInputs; i++)
		{
			inputsarray[i] = inputs[i].data();
		}

		for(uint32 i = 0; i < numOutputs; i++)
		{
			outputsarray[i] = outputs[i].data();
		}

		return true;
	}

	// Silence all input buffers.
	void ClearInputBuffers(uint32 numSamples)
	{
		MPT_ASSERT(numSamples <= bufferSize);
		for(size_t i = 0; i < inputs.size(); i++)
		{
			std::fill(inputs[i].data(), inputs[i].data() + numSamples, buffer_t{0});
		}
	}

	// Silence all output buffers.
	void ClearOutputBuffers(uint32 numSamples)
	{
		MPT_ASSERT(numSamples <= bufferSize);
		for(size_t i = 0; i < outputs.size(); i++)
		{
			std::fill(outputs[i].data(), outputs[i].data() + numSamples, buffer_t{0});
		}
	}

	PluginMixBuffer()
	{
		Initialize(2, 0);
	}

	// Return pointer to a given input or output buffer
	const buffer_t *GetInputBuffer(uint32 index) const { return inputs[index].data(); }
	const buffer_t *GetOutputBuffer(uint32 index) const { return outputs[index].data(); }
	buffer_t *GetInputBuffer(uint32 index) { return inputs[index].data(); }
	buffer_t *GetOutputBuffer(uint32 index) { return outputs[index].data(); }

	// Return pointer array to all input or output buffers
	buffer_t **GetInputBufferArray() { return inputs.empty() ? nullptr : inputsarray.data(); }
	buffer_t **GetOutputBufferArray() { return outputs.empty() ? nullptr : outputsarray.data(); }

	bool Ok() const { return (inputs.size() + outputs.size()) > 0; }

};


OPENMPT_NAMESPACE_END