diff --git a/src/common/bitsery/ext/in-place-variant.h b/src/common/bitsery/ext/in-place-variant.h
new file mode 100644
index 00000000..5157aa26
--- /dev/null
+++ b/src/common/bitsery/ext/in-place-variant.h
@@ -0,0 +1,83 @@
+// yabridge: a Wine VST bridge
+// Copyright (C) 2020-2021 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#pragma once
+
+#include
+
+namespace bitsery {
+namespace ext {
+
+/**
+ * A temporary replacement for `bitsery::ext::StdVariant` to avoid
+ * reinitializing the object we're deserializing into if the requested variant
+ * is currently active. For storing audio buffers we use variants containing
+ * float and double vectors to have a type safe way to disambiguate between
+ * single and double precision audio, but as it turns out bitsery's
+ * `std::variant` extension would always reinitialize those objects, undoing our
+ * efforts to prevent allocations.
+ */
+template
+class InPlaceVariant : public StdVariant {
+ public:
+ template
+ void deserialize(Des& des, std::variant& obj, Fnc&&) const {
+ size_t index{};
+ details::readSize(
+ des.adapter(), index, sizeof...(Ts),
+ std::integral_constant{});
+
+ this->execIndex(index, obj, [this, &des](auto& data, auto index) {
+ constexpr size_t Index = decltype(index)::value;
+ using TElem =
+ typename std::variant_alternative>::type;
+
+ // Most of this is copied directly from the original implementation.
+ // We just added the check here to reuse the existing object if
+ // possible.
+ if (std::holds_alternative(data)) {
+ TElem& item = std::get(data);
+ this->serializeType(des, item);
+ } else {
+ TElem item = ::bitsery::Access::create();
+ this->serializeType(des, item);
+ data = std::variant(std::in_place_index_t{},
+ std::move(item));
+ }
+ });
+ }
+};
+
+template
+InPlaceVariant(Overloads...) -> InPlaceVariant;
+} // namespace ext
+
+namespace traits {
+
+template
+struct ExtensionTraits, Variant> {
+ static_assert(
+ bitsery::details::IsSpecializationOf::value,
+ "InPlaceVariant only works with std::variant");
+ using TValue = void;
+ static constexpr bool SupportValueOverload = false;
+ static constexpr bool SupportObjectOverload = true;
+ static constexpr bool SupportLambdaOverload = false;
+};
+
+} // namespace traits
+} // namespace bitsery