cocos-engine-external/sources/acl/compression/impl/track.impl.h

354 lines
12 KiB
C++

#pragma once
////////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT)
//
// Copyright (c) 2020 Nicholas Frechette & Animation Compression Library contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
// Included only once from track.h
#include "acl/core/iallocator.h"
#include "acl/core/string.h"
#include "acl/core/track_desc.h"
#include "acl/core/track_traits.h"
#include "acl/core/track_types.h"
#include <cstdint>
namespace acl
{
inline track::track() noexcept
: m_allocator(nullptr)
, m_data(nullptr)
, m_num_samples(0)
, m_stride(0)
, m_data_size(0)
, m_sample_rate(0.0F)
, m_type(track_type8::float1f)
, m_category(track_category8::scalarf)
, m_sample_size(0)
, m_desc()
, m_name()
{}
inline track::track(track&& other) noexcept
: m_allocator(other.m_allocator)
, m_data(other.m_data)
, m_num_samples(other.m_num_samples)
, m_stride(other.m_stride)
, m_data_size(other.m_data_size)
, m_sample_rate(other.m_sample_rate)
, m_type(other.m_type)
, m_category(other.m_category)
, m_sample_size(other.m_sample_size)
, m_desc(other.m_desc)
, m_name(std::move(other.m_name))
{
other.m_allocator = nullptr;
other.m_data = nullptr;
}
inline track::~track()
{
if (is_owner())
{
// We own the memory, free it
m_allocator->deallocate(m_data, m_data_size);
}
}
inline track& track::operator=(track&& other) noexcept
{
std::swap(m_allocator, other.m_allocator);
std::swap(m_data, other.m_data);
std::swap(m_num_samples, other.m_num_samples);
std::swap(m_stride, other.m_stride);
std::swap(m_data_size, other.m_data_size);
std::swap(m_sample_rate, other.m_sample_rate);
std::swap(m_type, other.m_type);
std::swap(m_category, other.m_category);
std::swap(m_sample_size, other.m_sample_size);
std::swap(m_desc, other.m_desc);
std::swap(m_name, other.m_name);
return *this;
}
inline void* track::operator[](uint32_t index)
{
ACL_ASSERT(index < m_num_samples, "Invalid sample index. %u >= %u", index, m_num_samples);
return m_data + (index * m_stride);
}
inline const void* track::operator[](uint32_t index) const
{
ACL_ASSERT(index < m_num_samples, "Invalid sample index. %u >= %u", index, m_num_samples);
return m_data + (index * m_stride);
}
inline uint32_t track::get_output_index() const
{
switch (m_category)
{
default:
case track_category8::scalarf: return m_desc.scalar.output_index;
case track_category8::transformf: return m_desc.transform.output_index;
}
}
template<>
inline track_desc_scalarf& track::get_description()
{
ACL_ASSERT(track_desc_scalarf::category == m_category, "Unexpected track category");
return m_desc.scalar;
}
template<>
inline track_desc_transformf& track::get_description()
{
ACL_ASSERT(track_desc_transformf::category == m_category, "Unexpected track category");
return m_desc.transform;
}
template<>
inline const track_desc_scalarf& track::get_description() const
{
ACL_ASSERT(track_desc_scalarf::category == m_category, "Unexpected track category");
return m_desc.scalar;
}
template<>
inline const track_desc_transformf& track::get_description() const
{
ACL_ASSERT(track_desc_transformf::category == m_category, "Unexpected track category");
return m_desc.transform;
}
inline track track::get_copy(iallocator& allocator) const
{
track track_;
get_copy_impl(allocator, track_);
return track_;
}
inline track track::get_ref() const
{
track track_;
get_ref_impl(track_);
return track_;
}
inline error_result track::is_valid() const
{
if (m_data == nullptr)
return error_result();
if (m_num_samples == 0xFFFFFFFFU)
return error_result("Too many samples");
if (m_sample_rate <= 0.0F || !rtm::scalar_is_finite(m_sample_rate))
return error_result("Invalid sample rate");
switch (m_category)
{
case track_category8::scalarf: return m_desc.scalar.is_valid();
case track_category8::transformf: return m_desc.transform.is_valid();
default: return error_result("Invalid category");
}
}
inline track::track(track_type8 type, track_category8 category) noexcept
: m_allocator(nullptr)
, m_data(nullptr)
, m_num_samples(0)
, m_stride(0)
, m_data_size(0)
, m_sample_rate(0.0F)
, m_type(type)
, m_category(category)
, m_sample_size(0)
, m_desc()
, m_name()
{}
inline track::track(iallocator* allocator, uint8_t* data, uint32_t num_samples, uint32_t stride, size_t data_size, float sample_rate, track_type8 type, track_category8 category, uint8_t sample_size) noexcept
: m_allocator(allocator)
, m_data(data)
, m_num_samples(num_samples)
, m_stride(stride)
, m_data_size(data_size)
, m_sample_rate(sample_rate)
, m_type(type)
, m_category(category)
, m_sample_size(sample_size)
, m_desc()
, m_name()
{}
inline void track::get_copy_impl(iallocator& allocator, track& out_track) const
{
out_track.m_allocator = &allocator;
out_track.m_data = reinterpret_cast<uint8_t*>(allocator.allocate(m_data_size));
out_track.m_num_samples = m_num_samples;
out_track.m_stride = m_stride;
out_track.m_data_size = m_data_size;
out_track.m_sample_rate = m_sample_rate;
out_track.m_type = m_type;
out_track.m_category = m_category;
out_track.m_sample_size = m_sample_size;
out_track.m_desc = m_desc;
out_track.m_name = m_name.get_copy(allocator);
std::memcpy(out_track.m_data, m_data, m_data_size);
}
inline void track::get_ref_impl(track& out_track) const
{
out_track.m_allocator = nullptr;
out_track.m_data = m_data;
out_track.m_num_samples = m_num_samples;
out_track.m_stride = m_stride;
out_track.m_data_size = m_data_size;
out_track.m_sample_rate = m_sample_rate;
out_track.m_type = m_type;
out_track.m_category = m_category;
out_track.m_sample_size = m_sample_size;
out_track.m_desc = m_desc;
out_track.m_name = m_name.get_copy();
}
template<track_type8 track_type_>
inline typename track_typed<track_type_>::sample_type& track_typed<track_type_>::operator[](uint32_t index)
{
ACL_ASSERT(index < m_num_samples, "Invalid sample index. %u >= %u", index, m_num_samples);
return *reinterpret_cast<sample_type*>(m_data + (index * m_stride));
}
template<track_type8 track_type_>
inline const typename track_typed<track_type_>::sample_type& track_typed<track_type_>::operator[](uint32_t index) const
{
ACL_ASSERT(index < m_num_samples, "Invalid sample index. %u >= %u", index, m_num_samples);
return *reinterpret_cast<const sample_type*>(m_data + (index * m_stride));
}
template<track_type8 track_type_>
inline typename track_typed<track_type_>::desc_type& track_typed<track_type_>::get_description()
{
return track::get_description<desc_type>();
}
template<track_type8 track_type_>
inline const typename track_typed<track_type_>::desc_type& track_typed<track_type_>::get_description() const
{
return track::get_description<desc_type>();
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::get_copy(iallocator& allocator) const
{
track_typed track_;
track::get_copy_impl(allocator, track_);
return track_;
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::get_ref() const
{
track_typed track_;
track::get_ref_impl(track_);
return track_;
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::make_copy(const typename track_typed<track_type_>::desc_type& desc, iallocator& allocator, const sample_type* data, uint32_t num_samples, float sample_rate, uint32_t stride)
{
const size_t data_size = size_t(num_samples) * sizeof(sample_type);
const uint8_t* data_raw = reinterpret_cast<const uint8_t*>(data);
// Copy the data manually to avoid preserving the stride
sample_type* data_copy = reinterpret_cast<sample_type*>(allocator.allocate(data_size));
for (uint32_t index = 0; index < num_samples; ++index)
data_copy[index] = *reinterpret_cast<const sample_type*>(data_raw + (index * stride));
return track_typed<track_type_>(&allocator, reinterpret_cast<uint8_t*>(data_copy), num_samples, sizeof(sample_type), data_size, sample_rate, desc);
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::make_reserve(const typename track_typed<track_type_>::desc_type& desc, iallocator& allocator, uint32_t num_samples, float sample_rate)
{
const size_t data_size = size_t(num_samples) * sizeof(sample_type);
return track_typed<track_type_>(&allocator, reinterpret_cast<uint8_t*>(allocator.allocate(data_size)), num_samples, sizeof(sample_type), data_size, sample_rate, desc);
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::make_owner(const typename track_typed<track_type_>::desc_type& desc, iallocator& allocator, sample_type* data, uint32_t num_samples, float sample_rate, uint32_t stride)
{
const size_t data_size = size_t(num_samples) * stride;
return track_typed<track_type_>(&allocator, reinterpret_cast<uint8_t*>(data), num_samples, stride, data_size, sample_rate, desc);
}
template<track_type8 track_type_>
inline track_typed<track_type_> track_typed<track_type_>::make_ref(const typename track_typed<track_type_>::desc_type& desc, sample_type* data, uint32_t num_samples, float sample_rate, uint32_t stride)
{
const size_t data_size = size_t(num_samples) * stride;
return track_typed<track_type_>(nullptr, reinterpret_cast<uint8_t*>(data), num_samples, stride, data_size, sample_rate, desc);
}
template<track_type8 track_type_>
inline track_typed<track_type_>::track_typed(iallocator* allocator, uint8_t* data, uint32_t num_samples, uint32_t stride, size_t data_size, float sample_rate, const typename track_typed<track_type_>::desc_type& desc) noexcept
: track(allocator, data, num_samples, stride, data_size, sample_rate, type, category, sizeof(sample_type))
{
m_desc = track_desc_untyped(desc);
}
template<typename track_type>
inline track_type& track_cast(track& track_)
{
ACL_ASSERT(track_type::type == track_.get_type() || track_.is_empty(), "Unexpected track type");
return static_cast<track_type&>(track_);
}
template<typename track_type>
inline const track_type& track_cast(const track& track_)
{
ACL_ASSERT(track_type::type == track_.get_type() || track_.is_empty(), "Unexpected track type");
return static_cast<const track_type&>(track_);
}
template<typename track_type>
inline track_type* track_cast(track* track_)
{
if (track_ == nullptr || (track_type::type != track_->get_type() && !track_->is_empty()))
return nullptr;
return static_cast<track_type*>(track_);
}
template<typename track_type>
inline const track_type* track_cast(const track* track_)
{
if (track_ == nullptr || (track_type::type != track_->get_type() && !track_->is_empty()))
return nullptr;
return static_cast<const track_type*>(track_);
}
}