1 /* 2 * PluginMixBuffer.h 3 * ----------------- 4 * Purpose: Helper class for managing plugin audio input and output buffers. 5 * Notes : (currently none) 6 * Authors: OpenMPT Devs 7 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. 8 */ 9 10 11 #pragma once 12 13 #include "openmpt/all/BuildSettings.hpp" 14 15 #include <algorithm> 16 #include <array> 17 18 #if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST) 19 #include "mpt/base/aligned_array.hpp" 20 #endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST 21 22 23 OPENMPT_NAMESPACE_BEGIN 24 25 26 // At least this part of the code is ready for double-precision rendering... :> 27 // buffer_t: Sample buffer type (float, double, ...) 28 // bufferSize: Buffer size in samples 29 template<typename buffer_t, uint32 bufferSize> 30 class PluginMixBuffer 31 { 32 33 private: 34 35 #if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST) 36 static constexpr std::align_val_t alignment = std::align_val_t{16}; 37 static_assert(sizeof(mpt::aligned_array<buffer_t, bufferSize, alignment>) == sizeof(std::array<buffer_t, bufferSize>)); 38 static_assert(alignof(mpt::aligned_array<buffer_t, bufferSize, alignment>) == static_cast<std::size_t>(alignment)); 39 #endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST 40 41 protected: 42 43 #if defined(MPT_ENABLE_ARCH_INTRINSICS) || defined(MPT_WITH_VST) 44 std::vector<mpt::aligned_array<buffer_t, bufferSize, alignment>> inputs; 45 std::vector<mpt::aligned_array<buffer_t, bufferSize, alignment>> outputs; 46 #else // !(MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST) 47 std::vector<std::array<buffer_t, bufferSize>> inputs; 48 std::vector<std::array<buffer_t, bufferSize>> outputs; 49 #endif // MPT_ENABLE_ARCH_INTRINSICS || MPT_WITH_VST 50 std::vector<buffer_t*> inputsarray; 51 std::vector<buffer_t*> outputsarray; 52 53 public: 54 55 // Allocate input and output buffers Initialize(uint32 numInputs,uint32 numOutputs)56 bool Initialize(uint32 numInputs, uint32 numOutputs) 57 { 58 // Short cut - we do not need to recreate the buffers. 59 if(inputs.size() == numInputs && outputs.size() == numOutputs) 60 { 61 return true; 62 } 63 64 try 65 { 66 inputs.resize(numInputs); 67 outputs.resize(numOutputs); 68 inputsarray.resize(numInputs); 69 outputsarray.resize(numOutputs); 70 } catch(mpt::out_of_memory e) 71 { 72 mpt::delete_out_of_memory(e); 73 inputs.clear(); 74 inputs.shrink_to_fit(); 75 outputs.clear(); 76 outputs.shrink_to_fit(); 77 inputsarray.clear(); 78 inputsarray.shrink_to_fit(); 79 outputsarray.clear(); 80 outputsarray.shrink_to_fit(); 81 return false; 82 } 83 84 for(uint32 i = 0; i < numInputs; i++) 85 { 86 inputsarray[i] = inputs[i].data(); 87 } 88 89 for(uint32 i = 0; i < numOutputs; i++) 90 { 91 outputsarray[i] = outputs[i].data(); 92 } 93 94 return true; 95 } 96 97 // Silence all input buffers. ClearInputBuffers(uint32 numSamples)98 void ClearInputBuffers(uint32 numSamples) 99 { 100 MPT_ASSERT(numSamples <= bufferSize); 101 for(size_t i = 0; i < inputs.size(); i++) 102 { 103 std::fill(inputs[i].data(), inputs[i].data() + numSamples, buffer_t{0}); 104 } 105 } 106 107 // Silence all output buffers. ClearOutputBuffers(uint32 numSamples)108 void ClearOutputBuffers(uint32 numSamples) 109 { 110 MPT_ASSERT(numSamples <= bufferSize); 111 for(size_t i = 0; i < outputs.size(); i++) 112 { 113 std::fill(outputs[i].data(), outputs[i].data() + numSamples, buffer_t{0}); 114 } 115 } 116 PluginMixBuffer()117 PluginMixBuffer() 118 { 119 Initialize(2, 0); 120 } 121 122 // Return pointer to a given input or output buffer GetInputBuffer(uint32 index)123 const buffer_t *GetInputBuffer(uint32 index) const { return inputs[index].data(); } GetOutputBuffer(uint32 index)124 const buffer_t *GetOutputBuffer(uint32 index) const { return outputs[index].data(); } GetInputBuffer(uint32 index)125 buffer_t *GetInputBuffer(uint32 index) { return inputs[index].data(); } GetOutputBuffer(uint32 index)126 buffer_t *GetOutputBuffer(uint32 index) { return outputs[index].data(); } 127 128 // Return pointer array to all input or output buffers GetInputBufferArray()129 buffer_t **GetInputBufferArray() { return inputs.empty() ? nullptr : inputsarray.data(); } GetOutputBufferArray()130 buffer_t **GetOutputBufferArray() { return outputs.empty() ? nullptr : outputsarray.data(); } 131 Ok()132 bool Ok() const { return (inputs.size() + outputs.size()) > 0; } 133 134 }; 135 136 137 OPENMPT_NAMESPACE_END 138