Restored recommendations based on acoustic similarities (using musicnn), fixes #301
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2026 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS 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.
|
||||
*
|
||||
* LMS 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 LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "core/Exception.hpp"
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
template<typename T, std::size_t Alignment>
|
||||
class AlignedHeapArray
|
||||
{
|
||||
public:
|
||||
using iterator = T*;
|
||||
using const_iterator = const T*;
|
||||
|
||||
explicit AlignedHeapArray(std::size_t count)
|
||||
: _count{ count }
|
||||
, _values{ static_cast<T*>(std::aligned_alloc(Alignment, getStorageSize(count))) }
|
||||
{
|
||||
if (!_values)
|
||||
throw LmsException{ "Allocation failed" };
|
||||
}
|
||||
|
||||
~AlignedHeapArray()
|
||||
{
|
||||
std::free(_values);
|
||||
}
|
||||
|
||||
AlignedHeapArray(const AlignedHeapArray&) = delete;
|
||||
AlignedHeapArray& operator=(const AlignedHeapArray&) = delete;
|
||||
|
||||
std::size_t size() const { return _count; }
|
||||
T* data() const { return _values; }
|
||||
T& operator[](std::size_t index) const { return _values[index]; }
|
||||
|
||||
iterator begin() const { return _values; }
|
||||
iterator end() const { return _values + _count; }
|
||||
|
||||
const_iterator cbegin() const { return _values; }
|
||||
const_iterator cend() const { return _values + _count; }
|
||||
|
||||
private:
|
||||
static std::size_t getStorageSize(std::size_t count)
|
||||
{
|
||||
const std::size_t bytes{ count * sizeof(T) };
|
||||
const std::size_t alignedBytes{ ((bytes + Alignment - 1) / Alignment) * Alignment };
|
||||
return alignedBytes;
|
||||
}
|
||||
|
||||
const std::size_t _count;
|
||||
T* _values;
|
||||
};
|
||||
} // namespace lms::core
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
|
||||
namespace lms::core
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <type_traits>
|
||||
|
||||
namespace lms::core::random
|
||||
{
|
||||
@@ -43,12 +44,36 @@ namespace lms::core::random
|
||||
return dist(getRandGenerator());
|
||||
}
|
||||
|
||||
template<typename RandomEngine, typename Container>
|
||||
requires std::is_floating_point_v<typename Container::value_type>
|
||||
void fillContainer(RandomEngine& randomEngine, Container& container, typename Container::value_type min, typename Container::value_type max)
|
||||
{
|
||||
std::uniform_real_distribution<typename Container::value_type> distrib{ min, max };
|
||||
for (auto& v : container)
|
||||
v = distrib(randomEngine);
|
||||
}
|
||||
|
||||
template<typename RandomEngine, typename Container>
|
||||
requires std::is_integral_v<typename Container::value_type>
|
||||
void fillContainer(RandomEngine& randomEngine, Container& container, typename Container::value_type min, typename Container::value_type max)
|
||||
{
|
||||
std::uniform_int_distribution<typename Container::value_type> distrib{ min, max };
|
||||
for (auto& v : container)
|
||||
v = distrib(randomEngine);
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
void shuffleContainer(Container& container)
|
||||
{
|
||||
std::shuffle(std::begin(container), std::end(container), getRandGenerator());
|
||||
}
|
||||
|
||||
template<typename RandomEngine, typename Container>
|
||||
void shuffleContainer(RandomEngine& randomEngine, Container& container)
|
||||
{
|
||||
std::shuffle(std::begin(container), std::end(container), randomEngine);
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
typename Container::const_iterator pickRandom(const Container& container)
|
||||
{
|
||||
|
||||
@@ -19,18 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
namespace lms::core::utils
|
||||
{
|
||||
template<typename Container, typename T>
|
||||
void push_back_if_not_present(Container& container, const T& val)
|
||||
{
|
||||
if (std::find(std::cbegin(container), std::cend(container), val) == std::cend(container))
|
||||
container.push_back(val);
|
||||
}
|
||||
|
||||
template<class... Ts>
|
||||
struct overloads : Ts...
|
||||
{
|
||||
|
||||
@@ -25,5 +25,20 @@
|
||||
|
||||
namespace lms::core
|
||||
{
|
||||
std::uint64_t xxHash3_64(std::span<const std::byte> buf);
|
||||
class XxHash3_64
|
||||
{
|
||||
public:
|
||||
static std::uint64_t hash(std::span<const std::byte> buf);
|
||||
|
||||
XxHash3_64();
|
||||
~XxHash3_64();
|
||||
XxHash3_64(const XxHash3_64&) = delete;
|
||||
XxHash3_64& operator=(const XxHash3_64&) = delete;
|
||||
|
||||
void update(std::span<const std::byte> buf);
|
||||
std::uint64_t digest() const;
|
||||
|
||||
private:
|
||||
void* _state{};
|
||||
};
|
||||
} // namespace lms::core
|
||||
Reference in New Issue
Block a user