Added Loudness Analyzer

pull/4/head
Alexander Diamadis 4 years ago
parent 4161fac661
commit c05a694844
Signed by: alex
GPG Key ID: 6A1609EFA141FD70

@ -0,0 +1,22 @@
*.asv
*.m~
*.mex*
*.o
*.obj
*.dll
*.so
*.dylib
*.a
*.lib
*.exe
*.map
*.rsp
*.tmw
*.mat
sil/
interface/_coder_*_info.*
coderassumptions/
target/
build/
debug/
*.slxc

@ -0,0 +1,783 @@
/* Copyright 2019 The Mathworks, Inc. */
/* Copied from
* fullfile(matlabroot,'extern','include','coder','coder_array','coder_array_rtw_cpp11.h') */
#ifndef _mw_coder_array_cpp11_h
#define _mw_coder_array_cpp11_h
// Usage:
//
// coder::array<T, N>: T base type of data, N number of dimensions
//
// coder::array()
// : default constructor
// coder::array(coder::array const &)
// : copy constructor (always make a deep copy of other array)
// coder::array(T const *data, SizeType const *sz)
// : Set data with sizes of this array.
// : (Data is not copied, data is not deleted)
// coder::array::operator = (coder coder::array &)
// : Assign into this array;
// : delete its previous contents (if owning the data.)
// set(T const *data, SizeType sz1, SizeType sz2, ...)
// : Set data with dimensions.
// : (Data is not copied, data is not deleted)
// set_size(SizeType sz1, SizeType sz2, ...)
// : Set sizes of array. Reallocate memory of data if needed.
// bool is_owner() : Return true if the data is owned by the class.
// void set_owner(b) : Set if the data is owned by the class.
// SizeType capacity() : How many entries are reserved by memory allocation.
// reshape( SizeType sz1, SizeType sz2, ...)
// : Reshape array to a different ND shape. Do not copy the data.
// : The number of elements must not be changed (numel()==sz1*sz2*...)
// : Return the array with possibly new number of dimensions.
// clear() : Reset array to be empty.
// SizeType numel() : Return the number of elements.
// operator [] (SizeType index) : Extract element at linear index (0 based.)
// size(SizeType dimension) : Size of array of the provided dimension.
// SizeType * size() : Return the pointer to all the sizes of this array.
// SizeType index(SizeType i1, SizeType i2, ...)
// : Compute the linear index from ND index (i1,i2,...)
// at(SizeType i1, SizeType i2, ...) : The element at index (i1,i2,...)
#include <cassert>
#include <cstring>
#include <iterator>
#include <string>
#include <vector>
#ifndef INT32_T
#include "rtwtypes.h"
#endif
namespace coder {
#ifndef CODER_ARRAY_NEW_DELETE
#define CODER_ARRAY_NEW_DELETE
#define CODER_NEW(T, N) new T[N]
#define CODER_DELETE(P) delete[](P)
#endif
using SizeType = int32_T;
namespace std = ::std;
namespace detail {
#ifndef CODER_ARRAY_DATA_PTR_DEFINED
template <typename T, typename SZ>
class data_ptr {
public:
using value_type = T;
using size_type = SZ;
data_ptr()
: data_(nullptr)
, size_(0)
, capacity_(0)
, owner_(false) {
}
data_ptr(T* _data, SZ _sz)
: data_(_data)
, size_(_sz)
, capacity_(_sz)
, owner_(false) {
}
data_ptr(data_ptr const& _other)
: data_(_other.owner_ ? nullptr : _other.data_)
, size_(_other.owner_ ? 0 : _other.size_)
, capacity_(_other.owner_ ? 0 : _other.capacity_)
, owner_(_other.owner_) {
if (owner_) {
resize(_other.size_);
(void)std::copy(_other.data_, _other.data_ + size_, data_);
}
}
~data_ptr() {
if (owner_) {
CODER_DELETE(data_);
}
}
SZ capacity() const {
return capacity_;
}
void reserve(SZ _n) {
if (_n > capacity_) {
T* const new_data{CODER_NEW(T, _n)};
(void)std::copy(data_, data_ + size_, new_data);
if (owner_) {
CODER_DELETE(data_);
}
data_ = new_data;
capacity_ = _n;
owner_ = true;
}
}
void resize(SZ _n) {
reserve(_n);
size_ = _n;
}
private:
// Prohibit use of assignment operator to prevent subtle bugs
void operator=(data_ptr<T, SZ> const& _other);
public:
void set(T* _data, SZ _sz) {
if (owner_) {
CODER_DELETE(data_);
}
data_ = _data;
size_ = _sz;
owner_ = false;
capacity_ = size_;
}
void copy(T const* const _data, SZ _size) {
if (data_ == _data) {
size_ = _size;
return;
}
if (owner_) {
CODER_DELETE(data_);
}
data_ = CODER_NEW(T, _size);
owner_ = true;
size_ = _size;
capacity_ = size_;
(void)std::copy(_data, _data + _size, data_);
}
void copy(data_ptr<T, SZ> const& _other) {
copy(_other.data_, _other.size_);
}
operator T*() {
return &data_[0];
}
operator T const *() const {
return &data_[0];
}
T& operator[](SZ _index) {
return data_[_index];
}
T const& operator[](SZ _index) const {
return data_[_index];
}
T* operator->() {
return data_;
}
T const* operator->() const {
return data_;
}
bool is_null() const {
return data_ == nullptr;
}
void clear() {
if (owner_) {
CODER_DELETE(data_);
}
data_ = nullptr;
size_ = 0;
capacity_ = 0;
owner_ = false;
}
bool is_owner() const {
return owner_;
}
void set_owner(bool _b) {
owner_ = _b;
}
private:
T* data_;
SZ size_;
SZ capacity_;
bool owner_;
};
#endif
} // namespace detail
// Implementing the random access iterator class so coder::array can be
// used in STL iterators.
template <typename T>
class array_iterator : public std::iterator<std::random_access_iterator_tag,
typename T::value_type,
typename T::size_type> {
public:
array_iterator()
: arr_(nullptr)
, i_(0) {
}
array_iterator(array_iterator<T> const& other)
: arr_(other.arr_)
, i_(other.i_) {
}
~array_iterator() {
}
typename T::value_type& operator*() const {
return (*arr_)[i_];
}
typename T::value_type* operator->() const {
return &(*arr_)[i_];
}
typename T::value_type& operator[](typename T::size_type _di) const {
return (*arr_)[i_ + _di];
}
array_iterator<T>& operator++() {
++i_;
return *this;
}
array_iterator<T>& operator--() {
--i_;
return *this;
}
array_iterator<T> operator++(int) {
array_iterator<T> cp{*this};
++i_;
return cp;
}
array_iterator<T> operator--(int) {
array_iterator<T> cp{*this};
--i_;
return cp;
}
array_iterator<T>& operator=(array_iterator<T> const& _other) {
this->i_ = _other.i_;
return *this;
}
bool operator==(array_iterator<T> const& _other) const {
return i_ == _other.i_;
}
bool operator!=(array_iterator<T> const& _other) const {
return i_ != _other.i_;
}
bool operator<(array_iterator<T> const& _other) const {
return i_ < _other.i_;
}
bool operator>(array_iterator<T> const& _other) const {
return i_ > _other.i_;
}
bool operator<=(array_iterator<T> const& _other) const {
return i_ <= _other.i_;
}
bool operator>=(array_iterator<T> const& _other) const {
return i_ >= _other.i_;
}
array_iterator<T> operator+(typename T::size_type _add) const {
array_iterator<T> cp{*this};
cp.i_ += _add;
return cp;
}
array_iterator<T>& operator+=(typename T::size_type _add) {
this->i_ += _add;
return *this;
}
array_iterator<T> operator-(typename T::size_type _subtract) const {
array_iterator<T> cp{*this};
cp.i_ -= _subtract;
return cp;
}
array_iterator<T>& operator-=(typename T::size_type _subtract) {
this->i_ -= _subtract;
return *this;
}
typename T::size_type operator-(array_iterator<T> const& _other) const {
return static_cast<typename T::size_type>(this->i_ - _other.i_);
}
array_iterator(T* _arr, typename T::size_type _i)
: arr_(_arr)
, i_(_i) {
}
private:
T* arr_;
typename T::size_type i_;
};
// Const version of the array iterator.
template <typename T>
class const_array_iterator : public std::iterator<std::random_access_iterator_tag,
typename T::value_type,
typename T::size_type> {
public:
const_array_iterator()
: arr_(nullptr)
, i_(0) {
}
const_array_iterator(const_array_iterator<T> const& other)
: arr_(other.arr_)
, i_(other.i_) {
}
~const_array_iterator() {
}
typename T::value_type const& operator*() const {
return (*arr_)[i_];
}
typename T::value_type const* operator->() const {
return &(*arr_)[i_];
}
typename T::value_type const& operator[](typename T::size_type _di) const {
return (*arr_)[i_ + _di];
}
const_array_iterator<T>& operator++() {
++i_;
return *this;
}
const_array_iterator<T>& operator--() {
--i_;
return *this;
}
const_array_iterator<T> operator++(int) {
const_array_iterator<T> copy{*this};
++i_;
return copy;
}
const_array_iterator<T> operator--(int) {
const_array_iterator copy{*this};
--i_;
return copy;
}
const_array_iterator<T>& operator=(const_array_iterator<T> const& _other) {
this->i_ = _other.i_;
return *this;
}
bool operator==(const_array_iterator<T> const& _other) const {
return i_ == _other.i_;
}
bool operator!=(const_array_iterator<T> const& _other) const {
return i_ != _other.i_;
}
bool operator<(const_array_iterator<T> const& _other) const {
return i_ < _other.i_;
}
bool operator>(const_array_iterator<T> const& _other) const {
return i_ > _other.i_;
}
bool operator<=(const_array_iterator<T> const& _other) const {
return i_ <= _other.i_;
}
bool operator>=(const_array_iterator<T> const& _other) const {
return i_ >= _other.i_;
}
const_array_iterator<T> operator+(typename T::size_type _add) const {
const_array_iterator<T> cp{*this};
cp.i_ += _add;
return cp;
}
const_array_iterator<T>& operator+=(typename T::size_type _add) {
this->i_ += _add;
return *this;
}
const_array_iterator<T> operator-(typename T::size_type _subtract) const {
const_array_iterator<T> cp{*this};
cp.i_ -= _subtract;
return cp;
}
const_array_iterator<T>& operator-=(typename T::size_type _subtract) {
this->i_ -= _subtract;
return *this;
}
typename T::size_type operator-(const_array_iterator<T> const& _other) const {
return static_cast<typename T::size_type>(this->i_ - _other.i_);
}
const_array_iterator(T const* _arr, typename T::size_type _i)
: arr_(_arr)
, i_(_i) {
}
private:
T const* arr_;
typename T::size_type i_;
typename T::size_type n_;
};
namespace detail {
// detail::numel<N>: Compile-time product of the given size vector of length N.
template <int N>
class numel {
public:
template <typename SZ>
static SZ compute(SZ _size[]) {
return _size[N - 1] * numel<N - 1>::compute(_size);
}
};
template <>
class numel<0> {
public:
template <typename SZ>
static SZ compute(SZ[]) {
return 1;
}
};
// Compute the product for a set of numeric arguments: product<int32_T>(10, 20, 30, ...) =>
// 10*20*30*...
template <typename SZ, typename First, typename... Rest>
struct product_i {
static SZ compute(First _f, Rest... _rest) {
return _f * product_i<SZ, Rest...>::compute(_rest...);
}
};
template <typename SZ, typename Last>
struct product_i<SZ, Last> {
static SZ compute(Last _l) {
return _l;
}
};
template <typename SZ, typename... Args>
SZ product(Args... args) {
return product_i<SZ, Args...>::compute(args...);
}
// Compute flat index from (column-major) ND size vector and a list of indices.
template <int I>
class index_nd {
public:
template <typename SZ>
static SZ compute(SZ const _size[], SZ const _indices[]) {
SZ const weight{numel<I - 1>::compute(_size)};
return weight * _indices[I - 1] + index_nd<I - 1>::compute(_size, _indices);
}
};
template <>
class index_nd<0> {
public:
template <typename SZ>
static SZ compute(SZ[], SZ[]) {
return 0;
}
};
template <bool Cond>
struct match_dimensions {};
template <>
struct match_dimensions<true> {
static void check() {
}
};
} // namespace detail
// Base class for code::array. SZ is the type used for sizes (currently int32_t.)
// Overloading up to 10 dimensions (not using variadic templates to
// stay compatible with C++98.)
template <typename T, typename SZ, int N>
class array_base {
public:
using value_type = T;
using size_type = SZ;
array_base() {
(void)::memset(size_, 0, sizeof(SZ) * N);
}
array_base(T* _data, SZ const* _sz)
: data_(_data, coder::detail::numel<N>::compute(_sz)) {
(void)std::copy(_sz, _sz + N, size_);
}
array_base& operator=(array_base const& _other) {
data_.copy(_other.data_);
(void)std::copy(_other.size_, _other.size_ + N, size_);
return *this;
}
template <typename... Dims>
void set(T* _data, Dims... dims) {
coder::detail::match_dimensions<N == sizeof...(dims)>::check();
data_.set(_data, coder::detail::product<SZ>(dims...));
set_size_i<0>(dims...);
}
bool is_owner() const {
return data_.is_owner();
}
void set_owner(bool b) {
data_.set_owner(b);
}
SZ capacity() const {
return data_.capacity();
}
private:
template <SZ _i, typename First, typename... Rest>
void set_size_i(First f, Rest... rest) {
size_[_i] = f;
set_size_i<_i + 1, Rest...>(rest...);
}
template <SZ _i, typename Last>
void set_size_i(Last l) {
size_[_i] = l;
}
public:
template <typename... Dims>
void set_size(Dims... dims) {
coder::detail::match_dimensions<N == sizeof...(dims)>::check();
set_size_i<0>(dims...);
ensureCapacity(numel());
}
template <SizeType N1>
array_base<T, SZ, N1> reshape_n(SZ const (&_ns)[N1]) const {
array_base<T, SZ, N1> reshaped{const_cast<T*>(&data_[0]), _ns};
return reshaped;
}
template <typename... Dims>
array_base<T, SZ, static_cast<SZ>(sizeof...(Dims))> reshape(Dims... dims) const {
SZ const ns[]{static_cast<SZ>(dims)...};
return reshape_n(ns);
}
T& operator[](SZ _index) {
return data_[_index];
}
T const& operator[](SZ _index) const {
return data_[_index];
}
void clear() {
data_.clear();
}
T* data() {
return data_;
}
T const* data() const {
return data_;
}
SZ const* size() const {
return &size_[0];
}
SZ size(SZ _index) const {
return size_[_index];
}
SZ numel() const {
return coder::detail::numel<N>::compute(size_);
}
template <typename... Dims>
SZ index(Dims... _dims) const {
coder::detail::match_dimensions<N == sizeof...(_dims)>::check();
SZ const indices[]{static_cast<SZ>(_dims)...};
return coder::detail::index_nd<static_cast<SZ>(sizeof...(_dims))>::compute(size_, indices);
}
template <typename... Dims>
T& at(Dims... _i) {
coder::detail::match_dimensions<N == sizeof...(_i)>::check();
return data_[index(_i...)];
}
template <typename... Dims>
T const& at(Dims... _i) const {
coder::detail::match_dimensions<N == sizeof...(_i)>::check();
return data_[index(_i...)];
}
array_iterator<array_base<T, SZ, N>> begin() {
return array_iterator<array_base<T, SZ, N>>(this, 0);
}
array_iterator<array_base<T, SZ, N>> end() {
return array_iterator<array_base<T, SZ, N>>(this, this->numel());
}
const_array_iterator<array_base<T, SZ, N>> begin() const {
return const_array_iterator<array_base<T, SZ, N>>(this, 0);
}
const_array_iterator<array_base<T, SZ, N>> end() const {
return const_array_iterator<array_base<T, SZ, N>>(this, this->numel());
}
protected:
coder::detail::data_ptr<T, SZ> data_;
SZ size_[N];
private:
void ensureCapacity(SZ _newNumel) {
if (_newNumel > data_.capacity()) {
SZ i{data_.capacity()};
if (i < 16) {
i = 16;
}
while (i < _newNumel) {
if (i > 1073741823) {
i = MAX_int32_T;
} else {
i *= 2;
}
}
data_.reserve(i);
}
data_.resize(_newNumel);
}
};
// The standard coder::array class with base type and number of dimensions.
template <typename T, int N>
class array : public array_base<T, SizeType, N> {
private:
using Base = array_base<T, SizeType, N>;
public:
array()
: Base() {
}
array(array<T, N> const& _other)
: Base(_other) {
}
array(Base const& _other)
: Base(_other) {
}
array(T* _data, SizeType const* _sz)
: Base(_data, _sz) {
}
};
// Specialize on char_T (row vector) for better support on strings.
template <>
class array<char_T, 2> : public array_base<char_T, SizeType, 2> {
private:
using Base = array_base<char_T, SizeType, 2>;
public:
array()
: array_base() {
}
array(array<char_T, 2> const& _other)
: Base(_other) {
}
array(Base const& _other)
: Base(_other) {
}
array(std::string const& _str) {
operator=(_str);
}
array(char_T const* const _str) {
operator=(_str);
}
array(std::vector<char_T> const& _vec) {
SizeType const n{static_cast<SizeType>(_vec.size())};
set_size(1, n);
data_.copy(&_vec[0], n);
}
array& operator=(std::string const& _str) {
SizeType const n{static_cast<SizeType>(_str.size())};
set_size(1, n);
data_.copy(_str.c_str(), n);
return *this;
}
array& operator=(char_T const* const _str) {
SizeType const n{static_cast<SizeType>(strlen(_str))};
set_size(1, n);
data_.copy(_str, n);
return *this;
}
operator std::string() const {
return std::string(static_cast<char const*>(&(*this)[0]), static_cast<int>(size(1)));
}
};
// Specialize on 2 dimensions for better support interactions with
// std::vector and row vectors.
template <typename T>
class array<T, 2> : public array_base<T, SizeType, 2> {
private:
using Base = array_base<T, SizeType, 2>;
public:
array()
: Base() {
}
array(array<T, 2> const& _other)
: Base(_other) {
}
array(Base const& _other)
: Base(_other) {
}
array(std::vector<T> const& _vec) {
operator=(_vec);
}
array& operator=(std::vector<T> const& _vec) {
SizeType n{static_cast<SizeType>(_vec.size())};
Base::set_size(1, n);
Base::data_.copy(&_vec[0], n);
return *this;
}
operator std::vector<T>() const {
T const* p{&Base::data_[0]};
return std::vector<T>(p, p + Base::numel());
}
};
// Specialize on 1 dimension for better support with std::vector and
// column vectors.
template <typename T>
class array<T, 1> : public array_base<T, SizeType, 1> {
private:
using Base = array_base<T, SizeType, 1>;
public:
array()
: Base() {
}
array(array<T, 1> const& _other)
: Base(_other) {
}
array(Base const& _other)
: Base(_other) {
}
array(std::vector<T> const& _vec) {
operator=(_vec);
}
array& operator=(std::vector<T> const& _vec) {
SizeType n{static_cast<SizeType>(_vec.size())};
Base::set_size(n);
Base::data_.copy(&_vec[0], n);
return *this;
}
operator std::vector<T>() const {
T const* p{&Base::data_[0]};
return std::vector<T>(p, p + Base::numel());
}
};
} // namespace coder
#endif

@ -0,0 +1,34 @@
/* Copyright 2020 The Mathworks, Inc. */
/* Copied from fullfile(matlabroot,'extern','include','coder','coder_array','coder_bounded_array.h') */
#ifndef _mw_coder_bounded_array_h
#define _mw_coder_bounded_array_h
#ifdef MATLAB_MEX_FILE
#include "tmwtypes.h"
#else
#include "rtwtypes.h"
#endif
namespace coder {
#if __cplusplus >= 201103L
using SizeType = int32_T;
#else
typedef int32_T SizeType;
#endif
// Bounded array
template <typename T, SizeType UpperBoundSize, SizeType NumDims>
struct bounded_array {
T data[UpperBoundSize];
SizeType size[NumDims];
};
template <typename T, SizeType NumDims>
struct empty_bounded_array {
SizeType size[NumDims];
};
} // namespace coder
#endif

@ -0,0 +1,34 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: designKWeightingFilter.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef DESIGNKWEIGHTINGFILTER_H
#define DESIGNKWEIGHTINGFILTER_H
// Include Files
#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>
// Function Declarations
namespace coder {
namespace audio {
namespace internal {
void convertToFs(float sos_48kHz[6], float Fs);
}
} // namespace audio
} // namespace coder
#endif
//
// File trailer for designKWeightingFilter.h
//
// [EOF]
//

@ -0,0 +1,29 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: getLoudness.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef GETLOUDNESS_H
#define GETLOUDNESS_H
// Include Files
#include "rtwtypes.h"
#include "coder_array.h"
#include <cstddef>
#include <cstdlib>
// Function Declarations
extern void getLoudness(const coder::array<float, 2U> &data, float fs,
coder::array<float, 2U> &loudness);
#endif
//
// File trailer for getLoudness.h
//
// [EOF]
//

@ -0,0 +1,24 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: getLoudness_data.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef GETLOUDNESS_DATA_H
#define GETLOUDNESS_DATA_H
// Include Files
#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>
#endif
//
// File trailer for getLoudness_data.h
//
// [EOF]
//

@ -0,0 +1,27 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: getLoudness_initialize.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef GETLOUDNESS_INITIALIZE_H
#define GETLOUDNESS_INITIALIZE_H
// Include Files
#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>
// Function Declarations
extern void getLoudness_initialize();
#endif
//
// File trailer for getLoudness_initialize.h
//
// [EOF]
//

@ -0,0 +1,27 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: getLoudness_terminate.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef GETLOUDNESS_TERMINATE_H
#define GETLOUDNESS_TERMINATE_H
// Include Files
#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>
// Function Declarations
extern void getLoudness_terminate();
#endif
//
// File trailer for getLoudness_terminate.h
//
// [EOF]
//

@ -0,0 +1,22 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: getLoudness_types.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef GETLOUDNESS_TYPES_H
#define GETLOUDNESS_TYPES_H
// Include Files
#include "rtwtypes.h"
#endif
//
// File trailer for getLoudness_types.h
//
// [EOF]
//

@ -0,0 +1,34 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: rtGetInf.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef RTGETINF_H
#define RTGETINF_H
// Include Files
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
extern real_T rtGetInf(void);
extern real32_T rtGetInfF(void);
extern real_T rtGetMinusInf(void);
extern real32_T rtGetMinusInfF(void);
#ifdef __cplusplus
}
#endif
#endif
//
// File trailer for rtGetInf.h
//
// [EOF]
//

@ -0,0 +1,32 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: rtGetNaN.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef RTGETNAN_H
#define RTGETNAN_H
// Include Files
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
extern real_T rtGetNaN(void);
extern real32_T rtGetNaNF(void);
#ifdef __cplusplus
}
#endif
#endif
//
// File trailer for rtGetNaN.h
//
// [EOF]
//

@ -0,0 +1,36 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: rt_nonfinite.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef RT_NONFINITE_H
#define RT_NONFINITE_H
// Include Files
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
extern real_T rtInf;
extern real_T rtMinusInf;
extern real_T rtNaN;
extern real32_T rtInfF;
extern real32_T rtMinusInfF;
extern real32_T rtNaNF;
#ifdef __cplusplus
}
#endif
#endif
//
// File trailer for rt_nonfinite.h
//
// [EOF]
//

@ -0,0 +1,48 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: rtwtypes.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef RTWTYPES_H
#define RTWTYPES_H
/*=======================================================================*
* Fixed width word size data types: *
* int64_T - signed 64 bit integers *
* uint64_T - unsigned 64 bit integers *
*=======================================================================*/
#if defined(__APPLE__)
#ifndef INT64_T
#define INT64_T long
#define FMT64 "l"
#if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
#define INT_TYPE_64_IS_LONG
#endif
#endif
#endif
#if defined(__APPLE__)
#ifndef UINT64_T
#define UINT64_T unsigned long
#define FMT64 "l"
#if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
#define INT_TYPE_64_IS_LONG
#endif
#endif
#endif
// Include Files
#include "tmwtypes.h"
#endif
//
// File trailer for rtwtypes.h
//
// [EOF]
//

@ -0,0 +1,31 @@
//
// Academic License - for use in teaching, academic research, and meeting
// course requirements at degree granting institutions only. Not for
// government, commercial, or other organizational use.
// File: sum.h
//
// MATLAB Coder version : 5.2
// C/C++ source code generated on : 05-Feb-2022 12:14:13
//
#ifndef SUM_H
#define SUM_H
// Include Files
#include "rtwtypes.h"
#include "coder_array.h"
#include <cstddef>
#include <cstdlib>
// Function Declarations
namespace coder {
void sum(const ::coder::array<float, 2U> &x, float y_data[], int y_size[2]);
}
#endif
//
// File trailer for sum.h
//
// [EOF]
//

@ -0,0 +1,838 @@
/*
* @(#)tmwtypes.h generated by: makeheader 5.1.5 Fri Dec 27 18:07:22 2013
*
* built from: ../../src/include/copyright.h
* ../../src/include/tmwtypes.h
*/
#if defined(_MSC_VER)
# pragma once
#endif
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
# pragma once
#endif
#ifndef tmwtypes_h
#define tmwtypes_h
/*
* Copyright 1984-2003 The MathWorks, Inc.
* All Rights Reserved.
*/
/* Copyright 1995-2013 The MathWorks, Inc. */
#ifndef __TMWTYPES__
#define __TMWTYPES__
/*
* File : tmwtypes.h
* Abstract:
* Data types for use with MATLAB/SIMULINK and the Real-Time Workshop.
*
* When compiling stand-alone model code, data types can be overridden
* via compiler switches.
*
* Define NO_FLOATS to eliminate reference to real_T, etc.
*/
#include <limits.h>
#ifdef __APPLE_CC__
#include <stdbool.h>
#endif
#define LOGICAL_IS_A_TYPE
#define SPARSE_GENERALIZATION
#ifdef NO_FLOATS
# define double double_not_allowed
# define float float_not_allowed
#endif /*NO_FLOATS*/
#ifndef NO_FLOATS
#ifndef __MWERKS__
# ifdef __STDC__
# include <float.h>
# else
# define FLT_MANT_DIG 24
# define DBL_MANT_DIG 53
# endif
#endif
#endif /*NO_FLOATS*/
/*
* The following data types cannot be overridden when building MEX files.
*/
#ifdef MATLAB_MEX_FILE
# undef CHARACTER_T
# undef INTEGER_T
# undef BOOLEAN_T
# undef REAL_T
# undef TIME_T
#endif
/*
* The uchar_T, ushort_T and ulong_T types are needed for compilers which do
* not allow defines to be specified, at the command line, with spaces in them.
*/
typedef unsigned char uchar_T;
typedef unsigned short ushort_T;
typedef unsigned long ulong_T;
#if (defined(_MSC_VER) && _MSC_VER >= 1500) \
|| defined(__x86_64__) || defined(__LP64__) \
|| defined(__LCC64__)
typedef unsigned long long ulonglong_T;
#endif
/*=======================================================================*
* Fixed width word size data types: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
* real32_T, real64_T - 32 and 64 bit floating point numbers *
*=======================================================================*/
/* When used with Real Time Workshop generated code, this
* header file can be used with a variety of compilers.
*
* The compiler could be for an 8 bit embedded processor that
* only had 8 bits per integer and 16 bits per long.
* In that example, a 32 bit integer size is not even available.
* This header file should be robust to that.
*
* For the case of an 8 bit processor, the preprocessor
* may be limited to 16 bit math like its target. That limitation
* would mean that 32 bit comparisons can't be done accurately.
* To increase robustness to this, comparisons are done against
* smaller values first. An inaccurate 32 bit comparison isn't
* attempted if the 16 bit comparison has already succeeded.
*
* Limitations on preprocessor math can also be stricter than
* for the target. There are known cases where a compiler
* targeting processors with 64 bit longs can't do accurate
* preprocessor comparisons on more than 32 bits.
*/
/* Determine the number of bits for int, long, short, and char.
* If one fails to be determined, set the number of bits to -1
*/
#ifndef TMW_BITS_PER_INT
# if INT_MAX == 0x7FL
# define TMW_BITS_PER_INT 8
# elif INT_MAX == 0x7FFFL
# define TMW_BITS_PER_INT 16
# elif INT_MAX == 0x7FFFFFFFL
# define TMW_BITS_PER_INT 32
# else
# define TMW_BITS_PER_INT -1
# endif
#endif
#ifndef TMW_BITS_PER_LONG
# if LONG_MAX == 0x7FL
# define TMW_BITS_PER_LONG 8
# elif LONG_MAX == 0x7FFFL
# define TMW_BITS_PER_LONG 16
# elif LONG_MAX == 0x7FFFFFFFL
# define TMW_BITS_PER_LONG 32
# else
# define TMW_BITS_PER_LONG -1
# endif
#endif
#ifndef TMW_BITS_PER_SHRT
# if SHRT_MAX == 0x7FL
# define TMW_BITS_PER_SHRT 8
# elif SHRT_MAX == 0x7FFFL
# define TMW_BITS_PER_SHRT 16
# elif SHRT_MAX == 0x7FFFFFFFL
# define TMW_BITS_PER_SHRT 32
# else
# define TMW_BITS_PER_SHRT -1
# endif
#endif
#ifndef TMW_BITS_PER_SCHAR
# if SCHAR_MAX == 0x7FL
# define TMW_BITS_PER_SCHAR 8
# elif SCHAR_MAX == 0x7FFFL
# define TMW_BITS_PER_SCHAR 16
# elif SCHAR_MAX == 0x7FFFFFFFL
# define TMW_BITS_PER_SCHAR 32
# else
# define TMW_BITS_PER_SCHAR -1
# endif
#endif
#ifndef TMW_CHAR_SIGNED
# if SCHAR_MAX == CHAR_MAX
# define TMW_CHAR_SIGNED 1
# else
# define TMW_CHAR_SIGNED 0
# endif
#endif
/* It is common for one or more of the integer types
* to be the same size. For example, on many embedded
* processors, both shorts and ints are 16 bits. On
* processors used for workstations, it is quite common
* for both int and long to be 32 bits.
* When there is more than one choice for typdef'ing
* a portable type like int16_T or uint32_T, in
* concept, it should not matter which choice is made.
* However, some style guides and some code checking
* tools do identify and complain about seemingly
* irrelevant differences. For example, a code
* checking tool may complain about an implicit
* conversion from int to short even though both
* are 16 bits. To reduce these types of
* complaints, it is best to make int the
* preferred choice when more than one is available.
*/
#ifndef INT8_T
# if TMW_BITS_PER_INT == 8
# define INT8_T int
# elif TMW_BITS_PER_LONG == 8
# define INT8_T long
# elif TMW_BITS_PER_SCHAR == 8
# define INT8_T signed char
# elif TMW_BITS_PER_SHRT == 8
# define INT8_T short
# endif
#endif
#ifdef INT8_T
typedef INT8_T int8_T;
#endif
#ifndef UINT8_T
# if TMW_BITS_PER_INT == 8
# define UINT8_T unsigned int
# elif TMW_BITS_PER_LONG == 8
# define UINT8_T unsigned long
# elif TMW_BITS_PER_SCHAR == 8
# define UINT8_T unsigned char
# elif TMW_BITS_PER_SHRT == 8
# define UINT8_T unsigned short
# endif
#endif
#ifdef UINT8_T
typedef UINT8_T uint8_T;
#endif
#ifndef INT16_T
# if TMW_BITS_PER_INT == 16
# define INT16_T int
# elif TMW_BITS_PER_LONG == 16
# define INT16_T long
# elif TMW_BITS_PER_SCHAR == 16
# define INT16_T signed char
# elif TMW_BITS_PER_SHRT == 16
# define INT16_T short
# endif
#endif
#ifdef INT16_T
typedef INT16_T int16_T;
#endif
#ifndef UINT16_T
# if TMW_BITS_PER_INT == 16
# define UINT16_T unsigned int
# elif TMW_BITS_PER_LONG == 16
# define UINT16_T unsigned long
# elif TMW_BITS_PER_SCHAR == 16
# define UINT16_T unsigned char
# elif TMW_BITS_PER_SHRT == 16
# define UINT16_T unsigned short
# endif
#endif
#ifdef UINT16_T
typedef UINT16_T uint16_T;
#endif
#ifndef INT32_T
# if TMW_BITS_PER_INT == 32
# define INT32_T int
# elif TMW_BITS_PER_LONG == 32
# define INT32_T long
# elif TMW_BITS_PER_SCHAR == 32
# define INT32_T signed char
# elif TMW_BITS_PER_SHRT == 32
# define INT32_T short
# endif
#endif
#ifdef INT32_T
typedef INT32_T int32_T;
#endif
#ifndef UINT32_T
# if TMW_BITS_PER_INT == 32
# define UINT32_T unsigned int
# elif TMW_BITS_PER_LONG == 32
# define UINT32_T unsigned long
# elif TMW_BITS_PER_SCHAR == 32
# define UINT32_T unsigned char
# elif TMW_BITS_PER_SHRT == 32
# define UINT32_T unsigned short
# endif
#endif
#ifdef UINT32_T
typedef UINT32_T uint32_T;
#endif
/* The following is used to emulate smaller integer types when only
* larger types are available. For example, compilers for TI C3x/C4x DSPs
* define char and short to be 32 bits, so 8 and 16 bits are not directly
* available. This target is commonly used with RTW rapid prototyping.
* Other DSPs define char to be 16 bits, so 8 bits is not directly
* available.
*/
#ifndef INT8_T
# ifdef INT16_T
# define INT8_T INT16_T
typedef INT8_T int8_T;
# else
# ifdef INT32_T
# define INT8_T INT32_T
typedef INT8_T int8_T;
# endif
# endif
#endif
#ifndef UINT8_T
# ifdef UINT16_T
# define UINT8_T UINT16_T
typedef UINT8_T uint8_T;
# else
# ifdef UINT32_T
# define UINT8_T UINT32_T
typedef UINT8_T uint8_T;
# endif
# endif
#endif
#ifndef INT16_T
# ifdef INT32_T
# define INT16_T INT32_T
typedef INT16_T int16_T;
# endif
#endif
#ifndef UINT16_T
# ifdef UINT32_T
# define UINT16_T UINT32_T
typedef UINT16_T uint16_T;
# endif
#endif
#ifndef NO_FLOATS
#ifndef REAL32_T
# ifndef __MWERKS__
# if FLT_MANT_DIG >= 23
# define REAL32_T float
# endif
# else
# define REAL32_T float
# endif
#endif
#ifdef REAL32_T
typedef REAL32_T real32_T;
#endif
#ifndef REAL64_T
# ifndef __MWERKS__
# if DBL_MANT_DIG >= 52
# define REAL64_T double
# endif
# else
# define REAL64_T double
# endif
#endif
#ifdef REAL64_T
typedef REAL64_T real64_T;
#endif
#endif /* NO_FLOATS*/
/*=======================================================================*
* Fixed width word size data types: *
* int64_T - signed 64 bit integers *
* uint64_T - unsigned 64 bit integers *
*=======================================================================*/
#ifndef INT64_T
# if defined(__APPLE__)
# define INT64_T long long
# define FMT64 "ll"
# if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
# define INT_TYPE_64_IS_LONG
# endif
# elif defined(__x86_64__) || defined(__LP64__)
# define INT64_T long
# define FMT64 "l"
# if !defined(INT_TYPE_64_IS_LONG)
# define INT_TYPE_64_IS_LONG
# endif
# elif defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
|| (defined(__WATCOMC__) && __WATCOMC__ >= 1100)
# define INT64_T __int64
# define FMT64 "I64"
# elif defined(__GNUC__) || defined(TMW_ENABLE_INT64) \
|| defined(__LCC64__)
# define INT64_T long long
# define FMT64 "ll"
# endif
#endif
#if defined(INT64_T)
# if defined(__GNUC__) && \
((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >=9)))
__extension__
# endif
typedef INT64_T int64_T;
#endif
#ifndef UINT64_T
# if defined(__APPLE__)
# define UINT64_T unsigned long long
# define FMT64 "ll"
# if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
# define INT_TYPE_64_IS_LONG
# endif
# elif defined(__x86_64__) || defined(__LP64__)
# define UINT64_T unsigned long
# define FMT64 "l"
# if !defined(INT_TYPE_64_IS_LONG)
# define INT_TYPE_64_IS_LONG
# endif
# elif defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
|| (defined(__WATCOMC__) && __WATCOMC__ >= 1100)
# define UINT64_T unsigned __int64
# define FMT64 "I64"
# elif defined(__GNUC__) || defined(TMW_ENABLE_INT64) \
|| defined(__LCC64__)
# define UINT64_T unsigned long long
# define FMT64 "ll"
# endif
#endif
#if defined(_WIN64) || (defined(__APPLE__) && defined(__LP64__)) \
|| defined(__x86_64__) \
|| defined(__LP64__)
# define INT_TYPE_64_IS_SUPPORTED
#endif
#if defined(UINT64_T)
# if defined(__GNUC__) && \
((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >=9)))
__extension__
# endif
typedef UINT64_T uint64_T;
#endif
/*===========================================================================*
* Format string modifiers for using size_t variables in printf statements. *
*===========================================================================*/
#ifndef FMT_SIZE_T
# if defined( __GNUC__ ) || defined(_STDC_C99)
# define FMT_SIZE_T "z"
# elif defined (__WATCOMC__)
# define FMT_SIZE_T "l"
# elif defined (_WIN32 )
# define FMT_SIZE_T "I"
# else
# define FMT_SIZE_T "l"
# endif
#endif
#ifndef FMT_PTRDIFF_T
# if defined(__APPLE__)
# define FMT_PTRDIFF_T "l"
# elif defined( __GNUC__ ) || defined(_STDC_C99)
# define FMT_PTRDIFF_T "t"
# elif defined (__WATCOMC__)
# define FMT_PTRDIFF_T "l"
# elif defined (_WIN32 )
# define FMT_PTRDIFF_T "I"
# else
# define FMT_PTRDIFF_T "l"
# endif
#endif
/*===========================================================================*
* General or logical data types where the word size is not guaranteed. *
* real_T - possible settings include real32_T or real64_T *
* time_T - possible settings include real64_T or uint32_T *
* boolean_T *
* char_T *
* int_T *
* uint_T *
* byte_T *
*===========================================================================*/
#ifndef NO_FLOATS
#ifndef REAL_T
# ifdef REAL64_T
# define REAL_T real64_T
# else
# ifdef REAL32_T
# define REAL_T real32_T
# endif
# endif
#endif
#ifdef REAL_T
typedef REAL_T real_T;
#endif
#ifndef TIME_T
# ifdef REAL_T
# define TIME_T real_T
# endif
#endif
#ifdef TIME_T
typedef TIME_T time_T;
#endif
#endif /* NO_FLOATS */
#ifndef BOOLEAN_T
# if defined(UINT8_T)
# define BOOLEAN_T UINT8_T
# else
# define BOOLEAN_T unsigned int
# endif
#endif
typedef BOOLEAN_T boolean_T;
#ifndef CHARACTER_T
# define CHARACTER_T char
#endif
typedef CHARACTER_T char_T;
#ifndef INTEGER_T
# define INTEGER_T int
#endif
typedef INTEGER_T int_T;
#ifndef UINTEGER_T
# define UINTEGER_T unsigned
#endif
typedef UINTEGER_T uint_T;
#ifndef BYTE_T
# define BYTE_T unsigned char
#endif
typedef BYTE_T byte_T;
/*===========================================================================*
* Define Complex Structures *
*===========================================================================*/
#ifndef NO_FLOATS
#ifndef CREAL32_T
# ifdef REAL32_T
typedef struct {
real32_T re, im;
} creal32_T;
# define CREAL32_T creal32_T
# endif
#endif
#ifndef CREAL64_T
# ifdef REAL64_T
typedef struct {
real64_T re, im;
} creal64_T;
# define CREAL64_T creal64_T
# endif
#endif
#ifndef CREAL_T
# ifdef REAL_T
typedef struct {
real_T re, im;
} creal_T;
# define CREAL_T creal_T
# endif
#endif
#endif /* NO_FLOATS */
#ifndef CINT8_T
# ifdef INT8_T
typedef struct {
int8_T re, im;
} cint8_T;
# define CINT8_T cint8_T
# endif
#endif
#ifndef CUINT8_T
# ifdef UINT8_T
typedef struct {
uint8_T re, im;
} cuint8_T;
# define CUINT8_T cuint8_T
# endif
#endif
#ifndef CINT16_T
# ifdef INT16_T
typedef struct {
int16_T re, im;
} cint16_T;
# define CINT16_T cint16_T
# endif
#endif
#ifndef CUINT16_T
# ifdef UINT16_T
typedef struct {
uint16_T re, im;
} cuint16_T;
# define CUINT16_T cuint16_T
# endif
#endif
#ifndef CINT32_T
# ifdef INT32_T
typedef struct {
int32_T re, im;
} cint32_T;
# define CINT32_T cint32_T
# endif
#endif
#ifndef CUINT32_T
# ifdef UINT32_T
typedef struct {
uint32_T re, im;
} cuint32_T;
# define CUINT32_T cuint32_T
# endif
#endif
#ifndef CINT64_T
# ifdef INT64_T
typedef struct {
int64_T re, im;
} cint64_T;
# define CINT64_T cint64_T
# endif
#endif
#ifndef CUINT64_T
# ifdef UINT64_T
typedef struct {
uint64_T re, im;
} cuint64_T;
# define CUINT64_T cuint64_T
# endif
#endif
/*=======================================================================*
* Min and Max: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
*=======================================================================*/
#define MAX_int8_T ((int8_T)(127)) /* 127 */
#define MIN_int8_T ((int8_T)(-128)) /* -128 */
#define MAX_uint8_T ((uint8_T)(255)) /* 255 */
#define MIN_uint8_T ((uint8_T)(0))
#define MAX_int16_T ((int16_T)(32767)) /* 32767 */
#define MIN_int16_T ((int16_T)(-32768)) /* -32768 */
#define MAX_uint16_T ((uint16_T)(65535)) /* 65535 */
#define MIN_uint16_T ((uint16_T)(0))
#define MAX_int32_T ((int32_T)(2147483647)) /* 2147483647 */
#define MIN_int32_T ((int32_T)(-2147483647-1)) /* -2147483648 */
#define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU)) /* 4294967295 */
#define MIN_uint32_T ((uint32_T)(0))
#if defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
|| (defined(__WATCOMC__) && __WATCOMC__ >= 1100) \
|| defined(__LCC64__)
# ifdef INT64_T
# define MAX_int64_T ((int64_T)(9223372036854775807LL))
# define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
# endif
# ifdef UINT64_T
# define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
# define MIN_uint64_T ((uint64_T)(0))
# endif
#else
# ifdef INT64_T
# ifdef INT_TYPE_64_IS_LONG
# define MAX_int64_T ((int64_T)(9223372036854775807L))
# define MIN_int64_T ((int64_T)(-9223372036854775807L-1L))
# else
# define MAX_int64_T ((int64_T)(9223372036854775807LL))
# define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
# endif
# endif
# ifdef UINT64_T
# ifdef INT_TYPE_64_IS_LONG
# define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFUL))
# define MIN_uint64_T ((uint64_T)(0))
# else
# define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
# define MIN_uint64_T ((uint64_T)(0))
# endif
# endif
#endif
#ifdef _MSC_VER
/* Conversion from unsigned __int64 to double is not implemented in windows
* and results in a compile error, thus the value must first be cast to
* signed __int64, and then to double.
*
* If the 64 bit int value is greater than 2^63-1, which is the signed int64 max,
* the macro below provides a workaround for casting a uint64 value to a double
* in windows.
*/
# define uint64_to_double(u) ( ((u) > _I64_MAX) ? \
(double)(__int64)((u) - _I64_MAX - 1) + (double)_I64_MAX + 1: \
(double)(__int64)(u) )
/* The following inline function should only be used in the macro double_to_uint64,
* as it only handles the specfic range of double between 2^63 and 2^64-1 */
__forceinline
uint64_T double_to_uint64_helper(double d) {
union double_to_uint64_union_type {
double dd;
uint64_T i64;
} di;
di.dd = d;
return (((di.i64 & 0x000fffffffffffff) | 0x0010000000000000) << 11);
}
/* The largest double value that can be cast to uint64 in windows is the
* signed int64 max, which is 2^63-1. The macro below provides
* a workaround for casting large double values to uint64 in windows.
*/
/* The magic number 18446744073709551616.0 is 2^64 */
/* The magic number 9223372036854775808.0 is 2^63 */
# define double_to_uint64(d) ( ((d) >= 18446744073709551616.0) ? \
0xffffffffffffffffULL : \
((d) < 0.0) ? 0ULL : \
((d) >= 9223372036854775808.0) ? \
double_to_uint64_helper(d) : \
(unsigned __int64)(d) )
#else
# define uint64_to_double(u) ((double)(u))
# if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__TICCSC__)
/* double_to_uint64 defined only for MSVC and UNIX */
# else
# define double_to_uint64(d) ( ((d) > 0xffffffffffffffffULL) ? \
(unsigned long long) 0xffffffffffffffffULL : \
((d) < 0) ? (unsigned long long) 0 : (unsigned long long)(d) )
# endif
#endif
#if !defined(__cplusplus) && !defined(__bool_true_false_are_defined)
#ifndef _bool_T
#define _bool_T
typedef boolean_T bool;
#ifndef false
#define false (0)
#endif
#ifndef true
#define true (1)
#endif
#endif /* _bool_T */
#endif /* !__cplusplus */
/*
* This software assumes that the code is being compiled on a target using a
* 2's complement representation for signed integer values.
*/
#if ((SCHAR_MIN + 1) != -SCHAR_MAX)
#error "This code must be compiled using a 2's complement representation for signed integer values"
#endif
/*
* Maximum length of a MATLAB identifier (function/variable/model)
* including the null-termination character.
*/
#define TMW_NAME_LENGTH_MAX 64
/*
* Maximum values for indices and dimensions
*/
#include <stddef.h>
#ifdef MX_COMPAT_32
typedef int mwSize;
typedef int mwIndex;
typedef int mwSignedIndex;
#else
typedef size_t mwSize; /* unsigned pointer-width integer */
typedef size_t mwIndex; /* unsigned pointer-width integer */
typedef ptrdiff_t mwSignedIndex; /* a signed pointer-width integer */
#endif
#if (defined(_LP64) || defined(_WIN64)) && !defined(MX_COMPAT_32)
/* Currently 2^48 based on hardware limitations */
# define MWSIZE_MAX 281474976710655UL
# define MWINDEX_MAX 281474976710655UL
# define MWSINDEX_MAX 281474976710655L
# define MWSINDEX_MIN -281474976710655L
#else
# define MWSIZE_MAX 2147483647UL
# define MWINDEX_MAX 2147483647UL
# define MWSINDEX_MAX 2147483647L
# define MWSINDEX_MIN -2147483647L
#endif
#define MWSIZE_MIN 0UL
#define MWINDEX_MIN 0UL
/** UTF-16 character type */
#if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT)
typedef char16_t CHAR16_T;
#elif defined(_MSC_VER)
typedef wchar_t CHAR16_T;
#else
typedef UINT16_T CHAR16_T;
#endif
#endif /* __TMWTYPES__ */
#endif /* tmwtypes_h */

@ -0,0 +1,694 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LIBNYQUIST_COMMON_H
#define LIBNYQUIST_COMMON_H
#include <memory>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
#include <stdint.h>
#include <cassert>
#include <type_traits>
#include <numeric>
#include <array>
#include <map>
#include <random>
namespace nqr
{
/////////////////
// Util Macros //
/////////////////
#define F_ROUND(x) ((x) > 0 ? (x) + 0.5f : (x) - 0.5f)
#define D_ROUND(x) ((x) > 0 ? (x) + 0.5 : (x) - 0.5)
#define NO_COPY(C) C(const C &) = delete; C & operator = (const C &) = delete
#define NO_MOVE(C) NO_COPY(C); C(C &&) = delete; C & operator = (const C &&) = delete
///////////////////////
// Endian Operations //
///////////////////////
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
#define CPU_X86 1
#endif
#if defined(__arm__) || defined(_M_ARM)
#define CPU_ARM 1
#endif
#if defined(CPU_X86) && defined(CPU_ARM)
#error CPU_X86 and CPU_ARM both defined.
#endif
#if !defined(ARCH_CPU_BIG_ENDIAN) && !defined(ARCH_CPU_LITTLE_ENDIAN)
#if CPU_X86 || CPU_ARM || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define ARCH_CPU_LITTLE_ENDIAN
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ARCH_CPU_BIG_ENDIAN
#else
#error ARCH_CPU_BIG_ENDIAN or ARCH_CPU_LITTLE_ENDIAN should be defined.
#endif
#endif
#if defined(ARCH_CPU_BIG_ENDIAN) && defined(ARCH_CPU_LITTLE_ENDIAN)
#error ARCH_CPU_BIG_ENDIAN and ARCH_CPU_LITTLE_ENDIAN both defined.
#endif
static inline uint16_t Swap16(uint16_t value)
{
return (uint16_t)((value >> 8) | (value << 8));
}
static inline uint32_t Swap24(uint32_t value)
{
return (((value & 0x00ff0000) >> 16) |
((value & 0x0000ff00)) |
((value & 0x000000ff) << 16)) & 0x00FFFFFF;
}
static inline uint32_t Swap32(uint32_t value)
{
return (((value & 0x000000ff) << 24) |
((value & 0x0000ff00) << 8) |
((value & 0x00ff0000) >> 8) |
((value & 0xff000000) >> 24));
}
static inline uint64_t Swap64(uint64_t value)
{
return (((value & 0x00000000000000ffLL) << 56) |
((value & 0x000000000000ff00LL) << 40) |
((value & 0x0000000000ff0000LL) << 24) |
((value & 0x00000000ff000000LL) << 8) |
((value & 0x000000ff00000000LL) >> 8) |
((value & 0x0000ff0000000000LL) >> 24) |
((value & 0x00ff000000000000LL) >> 40) |
((value & 0xff00000000000000LL) >> 56));
}
template<typename T>
inline bool isOdd(const T x)
{
return (x & 0x1);
}
#ifdef ARCH_CPU_LITTLE_ENDIAN
#define Read16(n) (n)
#define Read24(n) (n)
#define Read32(n) (n)
#define Read64(n) (n)
#define Write16(n) (n)
#define Write24(n) (n)
#define Write32(n) (n)
#define Write64(n) (n)
#else
#define Read16(n) Swap16(n)
#define Read24(n) Swap24(n)
#define Read32(n) Swap32(n)
#define Read64(n) Swap64(n)
#define Write16(n) Swap16(n)
#define Write24(n) Swap24(n)
#define Write32(n) Swap32(n)
#define Write64(n) Swap64(n)
#endif
inline uint64_t Pack(uint32_t a, uint32_t b)
{
uint64_t tmp = (uint64_t) b << 32 | (uint64_t) a;
#ifdef ARCH_CPU_LITTLE_ENDIAN
return tmp;
#else
return Swap64(tmp);
#endif
}
inline uint32_t Pack(uint16_t a, uint16_t b)
{
uint32_t tmp = (uint32_t) b << 16 | (uint32_t) a;
#ifdef ARCH_CPU_LITTLE_ENDIAN
return tmp;
#else
return Swap32(tmp);
#endif
}
inline uint16_t Pack(uint8_t a, uint8_t b)
{
uint16_t tmp = (uint16_t) b << 8 | (uint16_t) a;
#ifdef ARCH_CPU_LITTLE_ENDIAN
return tmp;
#else
return Swap16(tmp);
#endif
}
// http://www.dsprelated.com/showthread/comp.dsp/136689-1.php
inline int32_t Pack(uint8_t a, uint8_t b, uint8_t c)
{
// uint32_t tmp = ((c & 0x80) ? (0xFF << 24) : 0x00 << 24) | (c << 16) | (b << 8) | (a << 0); // alternate method
int32_t x = (c << 16) | (b << 8) | (a << 0);
auto sign_extended = (x) | (!!((x) & 0x800000) * 0xff000000);
#ifdef ARCH_CPU_LITTLE_ENDIAN
return sign_extended;
#else
Swap32(sign_extended);
#endif
}
inline std::array<uint8_t, 3> Unpack(uint32_t a)
{
static std::array<uint8_t, 3> output;
#ifdef ARCH_CPU_LITTLE_ENDIAN
output[0] = a >> 0;
output[1] = a >> 8;
output[2] = a >> 16;
#else
output[0] = a >> 16;
output[1] = a >> 8;
output[2] = a >> 0;
#endif
return output;
}
//////////////////////////
// Resampling Utilities //
//////////////////////////
// This is a naieve implementation of a resampling filter where a lerp is used as a bad low-pass.
// It very far from the ideal case and should be used with caution (or not at all) on signals that matter.
// It is included here to upsample 44.1k to 48k for the purposes of microphone input => Opus, where the the
// nominal frequencies of speech are particularly far from Nyquist.
inline void linear_resample(const double rate, const std::vector<float> & input, std::vector<float> & output, const uint32_t samplesToProcess)
{
double virtualReadIndex = 0;
double a, b, i, sample;
uint32_t n = samplesToProcess - 1;
while (n--)
{
uint32_t readIndex = static_cast<uint32_t>(virtualReadIndex);
i = virtualReadIndex - readIndex;
a = input[readIndex + 0];
b = input[readIndex + 1];
sample = (1.0 - i) * a + i * b; // linear interpolate
output.push_back(static_cast<float>(sample));
virtualReadIndex += rate;
}
}
inline double sample_hermite_4p_3o(double x, double * y)
{
static double c0, c1, c2, c3;
c0 = y[1];
c1 = (1.0 / 2.0)*(y[2] - y[0]);
c2 = (y[0] - (5.0 / 2.0)*y[1]) + (2.0*y[2] - (1.0 / 2.0)*y[3]);
c3 = (1.0 / 2.0)*(y[3] - y[0]) + (3.0 / 2.0)*(y[1] - y[2]);
return ((c3*x + c2)*x + c1)*x + c0;
}
inline void hermite_resample(const double rate, const std::vector<float> & input, std::vector<float> & output, const uint32_t samplesToProcess)
{
double virtualReadIndex = 1;
double i, sample;
uint32_t n = samplesToProcess - 1;
while (n--)
{
uint32_t readIndex = static_cast<uint32_t>(virtualReadIndex);
i = virtualReadIndex - readIndex;
double samps[4] = { input[readIndex - 1], input[readIndex], input[readIndex + 1], input[readIndex + 2] };
sample = sample_hermite_4p_3o(i, samps); // cubic hermite interpolate over 4 samples
output.push_back(static_cast<float>(sample));
virtualReadIndex += rate;
}
}
//////////////////////////
// Conversion Utilities //
//////////////////////////
enum DitherType
{
DITHER_NONE,
DITHER_TRIANGLE
};
class Dither
{
std::uniform_real_distribution<float> distribution;
std::mt19937 gen;
float previous;
DitherType d;
public:
Dither(DitherType d) : distribution(-0.5f, +0.5f), previous(0.f), d(d) {}
float operator()(float s)
{
if (d == DITHER_TRIANGLE)
{
const float value = distribution(gen);
s = s + value - previous;
previous = value;
return s;
}
else return s;
}
};
// Signed maxes, defined for readabilty/convenience
#define NQR_INT16_MAX 32767.f
#define NQR_INT24_MAX 8388608.f
#define NQR_INT32_MAX 2147483648.f
static const float NQR_BYTE_2_FLT = 1.0f / 127.0f;
#define int8_to_float32(s) ((float) (s) * NQR_BYTE_2_FLT)
#define uint8_to_float32(s)(((float) (s) - 128) * NQR_BYTE_2_FLT)
#define int16_to_float32(s) ((float) (s) / NQR_INT16_MAX)
#define int24_to_float32(s) ((float) (s) / NQR_INT24_MAX)
#define int32_to_float32(s) ((float) (s) / NQR_INT32_MAX)
#define float32_to_int8(s) (float) (s * 127.f)
#define float32_to_uint8(s) (float) ((s * 127.f) + 128)
#define float32_to_int16(s) (float) (s * NQR_INT16_MAX)
#define float32_to_int24(s) (float) (s * NQR_INT24_MAX)
#define float32_to_int32(s) (float) (s * NQR_INT32_MAX)
//@todo add 12, 20 for flac
enum PCMFormat
{
PCM_U8,
PCM_S8,
PCM_16,
PCM_24,
PCM_32,
PCM_64,
PCM_FLT,
PCM_DBL,
PCM_END
};
template<class T> T clamp(T a, T mn, T mx) { return std::max(std::min(a, mx), mn); }
// Src data is aligned to PCMFormat
// @todo normalize?
void ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCMFormat f);
// Src data is always aligned to 4 bytes (WavPack, primarily)
void ConvertToFloat32(float * dst, const int32_t * src, const size_t N, PCMFormat f);
// Src data is always aligned to 2 bytes (IMA ADPCM, primarily)
void ConvertToFloat32(float * dst, const int16_t * src, const size_t N, PCMFormat f);
void ConvertFromFloat32(uint8_t * dst, const float * src, const size_t N, PCMFormat f, DitherType t = DITHER_NONE);
int GetFormatBitsPerSample(PCMFormat f);
PCMFormat MakeFormatForBits(int bits, bool floatingPt, bool isSigned);
//////////////////////////
// User Data + File Ops //
//////////////////////////
struct AudioData
{
int channelCount;
int sampleRate;
double lengthSeconds;
size_t frameSize; // channels * bits per sample
std::vector<float> samples;
PCMFormat sourceFormat;
//@todo: add field: channel layout
//@todo: add field: lossy / lossless
//@todo: audio data loaded (for metadata only)
//@todo: bitrate (if applicable)
//@todo: original sample rate (if applicable)
};
struct StreamableAudioData : public AudioData
{
//@todo: add field: is this format streamable?
//@todo: hold file handle
};
struct NyquistFileBuffer
{
std::vector<uint8_t> buffer;
size_t size;
};
NyquistFileBuffer ReadFile(const std::string & pathToFile);
////////////////////
// Encoding Utils //
////////////////////
struct EncoderParams
{
int channelCount;
PCMFormat targetFormat;
DitherType dither;
};
enum EncoderError
{
NoError,
InsufficientSampleData,
FileIOError,
UnsupportedSamplerate,
UnsupportedChannelConfiguration,
UnsupportedBitdepth,
UnsupportedChannelMix,
BufferTooBig,
};
//////////////////////
// Wav Format Utils //
//////////////////////
enum WaveFormatCode
{
FORMAT_UNKNOWN = 0x0, // Unknown Wave Format
FORMAT_PCM = 0x1, // PCM Format
FORMAT_ADPCM = 0x2, // Microsoft ADPCM Format
FORMAT_IEEE = 0x3, // IEEE float/double
FORMAT_ALAW = 0x6, // 8-bit ITU-T G.711 A-law
FORMAT_MULAW = 0x7, // 8-bit ITU-T G.711 µ-law
FORMAT_IMA_ADPCM = 0x11, // IMA ADPCM Format
FORMAT_EXT = 0xFFFE // Set via subformat
};
struct RiffChunkHeader
{
uint32_t id_riff; // Chunk ID: 'RIFF'
uint32_t file_size; // Entire file in bytes
uint32_t id_wave; // Chunk ID: 'WAVE'
};
struct WaveChunkHeader
{
uint32_t fmt_id; // Chunk ID: 'fmt '
uint32_t chunk_size; // Size in bytes
uint16_t format; // Format code
uint16_t channel_count; // Num interleaved channels
uint32_t sample_rate; // SR
uint32_t data_rate; // Data rate
uint16_t frame_size; // 1 frame = channels * bits per sample (also known as block align)
uint16_t bit_depth; // Bits per sample
};
struct BextChunk
{
uint32_t fmt_id; // Chunk ID: 'bext'
uint32_t chunk_size; // Size in bytes
uint8_t description[256]; // Description of the sound (ascii)
uint8_t origin[32]; // Name of the originator (ascii)
uint8_t origin_ref[32]; // Reference of the originator (ascii)
uint8_t orgin_date[10]; // yyyy-mm-dd (ascii)
uint8_t origin_time[8]; // hh-mm-ss (ascii)
uint64_t time_ref; // First sample count since midnight
uint32_t version; // Version of the BWF
uint8_t uimd[64]; // Byte 0 of SMPTE UMID
uint8_t reserved[188]; // 190 bytes, reserved for future use & set to NULL
};
struct FactChunk
{
uint32_t fact_id; // Chunk ID: 'fact'
uint32_t chunk_size; // Size in bytes
uint32_t sample_length; // number of samples per channel
};
struct ExtensibleData
{
uint16_t size;
uint16_t valid_bits_per_sample;
uint32_t channel_mask;
struct GUID
{
uint32_t data0;
uint16_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[6];
};
};
template<class C, class R>
std::basic_ostream<C,R> & operator << (std::basic_ostream<C,R> & a, const WaveChunkHeader & b)
{
return a <<
"Format ID:\t\t" << b.fmt_id <<
"\nChunk Size:\t\t" << b.chunk_size <<
"\nFormat Code:\t\t" << b.format <<
"\nChannels:\t\t" << b.channel_count <<
"\nSample Rate:\t\t" << b.sample_rate <<
"\nData Rate:\t\t" << b.data_rate <<
"\nFrame Size:\t\t" << b.frame_size <<
"\nBit Depth:\t\t" << b.bit_depth << std::endl;
}
//@todo expose speaker/channel/layout masks in the API:
enum SpeakerChannelMask
{
SPEAKER_FRONT_LEFT = 0x00000001,
SPEAKER_FRONT_RIGHT = 0x00000002,
SPEAKER_FRONT_CENTER = 0x00000004,
SPEAKER_LOW_FREQUENCY = 0x00000008,
SPEAKER_BACK_LEFT = 0x00000010,
SPEAKER_BACK_RIGHT = 0x00000020,
SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040,
SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080,
SPEAKER_BACK_CENTER = 0x00000100,
SPEAKER_SIDE_LEFT = 0x00000200,
SPEAKER_SIDE_RIGHT = 0x00000400,
SPEAKER_TOP_CENTER = 0x00000800,
SPEAKER_TOP_FRONT_LEFT = 0x00001000,
SPEAKER_TOP_FRONT_CENTER = 0x00002000,
SPEAKER_TOP_FRONT_RIGHT = 0x00004000,
SPEAKER_TOP_BACK_LEFT = 0x00008000,
SPEAKER_TOP_BACK_CENTER = 0x00010000,
SPEAKER_TOP_BACK_RIGHT = 0x00020000,
SPEAKER_RESERVED = 0x7FFC0000,
SPEAKER_ALL = 0x80000000
};
enum SpeakerLayoutMask
{
SPEAKER_MONO = (SPEAKER_FRONT_CENTER),
SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT),
SPEAKER_2POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY),
SPEAKER_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER),
SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_4POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_5POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_7POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER),
SPEAKER_5POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
SPEAKER_7POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
};
//@todo verify mask values
inline int ComputeChannelMask(const size_t channels)
{
switch (channels)
{
case 1: return SPEAKER_MONO;
case 2: return SPEAKER_STEREO;
case 3: return SPEAKER_2POINT1;
case 4: return SPEAKER_QUAD;
case 5: return SPEAKER_4POINT1;
case 6: return SPEAKER_5POINT1;
default: return -1;
}
}
/////////////////////
// Chunk utilities //
/////////////////////
struct ChunkHeaderInfo
{
uint32_t offset; // Byte offset into chunk
uint32_t size; // Size of the chunk in bytes
};
inline uint32_t GenerateChunkCode(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
#ifdef ARCH_CPU_LITTLE_ENDIAN
return ((uint32_t)((a) | ((b) << 8) | ((c) << 16) | (((uint32_t)(d)) << 24)));
#else
return ((uint32_t)((((uint32_t)(a)) << 24) | ((b) << 16) | ((c) << 8) | (d)));
#endif
}
inline char * GenerateChunkCodeChar(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
auto chunk = GenerateChunkCode(a, b, c, d);
char * outArr = new char[4];
uint32_t t = 0x000000FF;
for (size_t i = 0; i < 4; i++)
{
outArr[i] = chunk & t;
chunk >>= 8;
}
return outArr;
}
inline ChunkHeaderInfo ScanForChunk(const std::vector<uint8_t> & fileData, uint32_t chunkMarker)
{
// D[n] aligned to 16 bytes now
const uint16_t * d = reinterpret_cast<const uint16_t *>(fileData.data());
for (size_t i = 0; i < fileData.size() / sizeof(uint16_t); i++)
{
// This will be in machine endianess
uint32_t m = Pack(Read16(d[i]), Read16(d[i + 1]));
if (m == chunkMarker)
{
uint32_t cSz = Pack(Read16(d[i + 2]), Read16(d[i + 3]));
return { (uint32_t(i * sizeof(uint16_t))), cSz }; // return i in bytes to the start of the data
}
else continue;
}
return { 0, 0 };
};
inline WaveChunkHeader MakeWaveHeader(const EncoderParams param, const int sampleRate)
{
WaveChunkHeader header;
int bitdepth = GetFormatBitsPerSample(param.targetFormat);
header.fmt_id = GenerateChunkCode('f', 'm', 't', ' ');
header.chunk_size = 16;
header.format = (param.targetFormat <= PCMFormat::PCM_32) ? WaveFormatCode::FORMAT_PCM : WaveFormatCode::FORMAT_IEEE;
header.channel_count = param.channelCount;
header.sample_rate = sampleRate;
header.data_rate = sampleRate * param.channelCount * (bitdepth / 8);
header.frame_size = param.channelCount * (bitdepth / 8);
header.bit_depth = bitdepth;
return header;
}
// @todo expose this in the FLAC API
inline std::map<int, std::string> GetFlacQualityTable()
{
return {
{ 0, "0 (Fastest)" },
{ 1, "1" },
{ 2, "2" },
{ 3, "3" },
{ 4, "4" },
{ 5, "5 (Default)" },
{ 6, "6" },
{ 7, "7" },
{ 8, "8 (Highest)" },
};
}
template <typename T>
inline void DeinterleaveStereo(T * c1, T * c2, T const * src, size_t count)
{
auto src_end = src + count;
while (src != src_end)
{
*c1 = src[0];
*c2 = src[1];
c1++;
c2++;
src += 2;
}
}
template<typename T>
void InterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for (size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
const T * srcChannel = &src[ch * numFramesPerChannel];
for (size_t i = 0; i < N; i++)
{
dest[x] = srcChannel[i];
x += numChannels;
}
}
}
template<typename T>
void DeinterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for (size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
T *destChannel = &dest[ch * numFramesPerChannel];
for (size_t i = 0; i < N; i++)
{
destChannel[i] = (T)src[x];
x += numChannels;
}
}
}
template <typename T>
void StereoToMono(const T * src, T * dest, size_t N)
{
for (size_t i = 0, j = 0; i < N; i += 2, ++j)
{
dest[j] = (src[i] + src[i + 1]) / 2.0f;
}
}
template <typename T>
void MonoToStereo(const T * src, T * dest, size_t N)
{
for (size_t i = 0, j = 0; i < N; ++i, j += 2)
{
dest[j] = src[i];
dest[j + 1] = src[i];
}
}
inline void TrimSilenceInterleaved(std::vector<float> & buffer, float v, bool fromFront, bool fromEnd)
{
//@todo implement me!
}
} // end namespace nqr
#endif

@ -0,0 +1,136 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AUDIO_DECODER_H
#define AUDIO_DECODER_H
#include "Common.h"
#include <utility>
#include <map>
#include <memory>
#include <exception>
namespace nqr
{
struct BaseDecoder
{
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) = 0;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) = 0;
virtual std::vector<std::string> GetSupportedFileExtensions() = 0;
virtual ~BaseDecoder() {}
};
typedef std::pair< std::string, std::shared_ptr<nqr::BaseDecoder> > DecoderPair;
class NyquistIO
{
std::string ParsePathForExtension(const std::string & path) const;
std::shared_ptr<nqr::BaseDecoder> GetDecoderForExtension(const std::string & ext);
void BuildDecoderTable();
void AddDecoderToTable(std::shared_ptr<nqr::BaseDecoder> decoder);
std::map< std::string, std::shared_ptr<BaseDecoder> > decoderTable;
NO_MOVE(NyquistIO);
public:
NyquistIO();
~NyquistIO();
void Load(AudioData * data, const std::string & path);
void Load(AudioData * data, const std::vector<uint8_t> & buffer);
void Load(AudioData * data, const std::string & extension, const std::vector<uint8_t> & buffer);
bool IsFileSupported(const std::string & path) const;
};
struct UnsupportedExtensionEx : public std::runtime_error { UnsupportedExtensionEx() : std::runtime_error("Unsupported file extension") {} };
struct LoadPathNotImplEx : public std::runtime_error { LoadPathNotImplEx() : std::runtime_error("Loading from path not implemented") {} };
struct LoadBufferNotImplEx : public std::runtime_error { LoadBufferNotImplEx() : std::runtime_error("Loading from buffer not implemented") {} };
struct WavDecoder final : public nqr::BaseDecoder
{
WavDecoder() = default;
virtual ~WavDecoder() {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct WavPackDecoder final : public nqr::BaseDecoder
{
WavPackDecoder() = default;
virtual ~WavPackDecoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct VorbisDecoder final : public nqr::BaseDecoder
{
VorbisDecoder() = default;
virtual ~VorbisDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct OpusDecoder final : public nqr::BaseDecoder
{
OpusDecoder() = default;
virtual ~OpusDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct MusepackDecoder final : public nqr::BaseDecoder
{
MusepackDecoder() = default;
virtual ~MusepackDecoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct Mp3Decoder final : public nqr::BaseDecoder
{
Mp3Decoder() = default;
virtual ~Mp3Decoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct FlacDecoder final : public nqr::BaseDecoder
{
FlacDecoder() = default;
virtual ~FlacDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
} // end namespace nqr
#endif

@ -0,0 +1,44 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NYQUIST_ENCODERS_H
#define NYQUIST_ENCODERS_H
#include "Common.h"
namespace nqr
{
// A simplistic encoder that takes a buffer of audio, conforms it to the user's
// EncoderParams preference, and writes to disk. Be warned, does not support resampling!
// @todo support dithering, samplerate conversion, etc.
int encode_wav_to_disk(const EncoderParams p, const AudioData * d, const std::string & path);
// Assume data adheres to EncoderParams, except for bit depth and fmt which are re-formatted
// to satisfy the Ogg/Opus spec.
int encode_opus_to_disk(const EncoderParams p, const AudioData * d, const std::string & path);
} // end namespace nqr
#endif // end NYQUIST_ENCODERS_H

@ -14,7 +14,9 @@ SOURCES += \
camp.cpp \ camp.cpp \
campmode.cpp \ campmode.cpp \
cdac.cpp \ cdac.cpp \
csong.cpp \
cspeaker.cpp \ cspeaker.cpp \
delegatepathitem.cpp \
library.cpp \ library.cpp \
main.cpp \ main.cpp \
mainwindow.cpp mainwindow.cpp
@ -25,7 +27,9 @@ HEADERS += \
camp.h \ camp.h \
campmode.h \ campmode.h \
cdac.h \ cdac.h \
csong.h \
cspeaker.h \ cspeaker.h \
delegatepathitem.h \
library.h \ library.h \
mainwindow.h mainwindow.h
@ -56,7 +60,7 @@ RESOURCES += \
VERSION=1.1.0 VERSION=1.1.0
QMAKE_TARGET_PRODUCT = "PA-Calculator" QMAKE_TARGET_PRODUCT = "PA-Calculator"
QMAKE_TARGET_COMPANY = "Alexander Diamadis" QMAKE_TARGET_COMPANY = "Alexander Diamadis"
QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2021 by Alexander Diamadis (alex@dkm-tech.de)" QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2022 by Alexander Diamadis"
win32 { win32 {
commit = $$system("FOR /F \"tokens=*\" %H IN ('git rev-parse --short HEAD') DO @SET /A DECIMAL=0x%H") commit = $$system("FOR /F \"tokens=*\" %H IN ('git rev-parse --short HEAD') DO @SET /A DECIMAL=0x%H")
@ -71,4 +75,30 @@ DEFINES += APP_VERSION=\"\\\"$${VERSION}\\\"\" \
APP_COMMIT=\"\\\"$${commit}\\\"\" \ APP_COMMIT=\"\\\"$${commit}\\\"\" \
APP_COPYRIGHT=\"\\\"$${QMAKE_TARGET_COPYRIGHT}\\\"\" APP_COPYRIGHT=\"\\\"$${QMAKE_TARGET_COPYRIGHT}\\\"\"
# Library Libnyquist
macx: LIBS += -L$$PWD/../libs/libnyquist/lib-macx/ -llibnyquist
INCLUDEPATH += $$PWD/../libs/libnyquist/include
DEPENDPATH += $$PWD/../libs/libnyquist/include
macx: PRE_TARGETDEPS += $$PWD/../libs/libnyquist/lib-macx/liblibnyquist.a
macx: LIBS += -L$$PWD/../libs/libnyquist/lib-macx/ -llibwavpack
INCLUDEPATH += $$PWD/../libs/libnyquist/include
DEPENDPATH += $$PWD/../libs/libnyquist/include
macx: PRE_TARGETDEPS += $$PWD/../libs/libnyquist/lib-macx/liblibwavpack.a
# Library getLoudness
macx: LIBS += -L$$PWD/../libs/getLoudness/macx/ -lgetLoudness
macx: INCLUDEPATH += $$PWD/../libs/getLoudness/macx
macx: DEPENDPATH += $$PWD/../libs/getLoudness/macx
macx: PRE_TARGETDEPS += $$PWD/../libs/getLoudness/macx/libgetLoudness.a

@ -136,7 +136,7 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:7pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.AppleSystemUIFont'; font-size:7pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;&quot;&gt;&lt;a name=&quot;license-text&quot;&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;his 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.&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;&quot;&gt;&lt;a name=&quot;license-text&quot;&gt;&lt;/a&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;T&lt;/span&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;his 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.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;&quot;&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;&quot;&gt;&lt;span style=&quot; font-family:'Consolas','Monaco','Courier','monospace'; font-size:8pt; color:#5c5855; background-color:#ffffff;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;

@ -5,17 +5,29 @@
#include <QString> #include <QString>
#include <QDirIterator> #include <QDirIterator>
#include <QFileInfo> #include <QFileInfo>
#include <QDebug>
#include <QStringList>
#include "delegatepathitem.h"
analyzer::analyzer(QWidget *parent) : analyzer::analyzer(QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::analyzer) ui(new Ui::analyzer)
{ {
ui->setupUi(this); ui->setupUi(this);
countSongs=0;
firstAnalysisDone=false;
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "Filename"<<"Loudness in dBFS"<<"Peaklevel in dBFS"<<"corrected peak in dBFS"<<"required Correction");
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Stretch);
} }
analyzer::~analyzer() analyzer::~analyzer()
{ {
delete ui; delete ui;
if (countSongs>0){
delete [] songList;
}
} }
void analyzer::on_pushButton_clicked() void analyzer::on_pushButton_clicked()
@ -27,13 +39,56 @@ void analyzer::on_pushButton_clicked()
void analyzer::on_pushButton_calculate_clicked() void analyzer::on_pushButton_calculate_clicked()
{ {
QDirIterator it(ui->lineEdit_path->text(), QStringList() << "*.mp3", QDir::NoFilter, QDirIterator::Subdirectories); ui->pushButton_calculate->setDisabled(true);
//while (it.hasNext()) { ui->doubleSpinBox_preferredLoudness->setDisabled(true);
QFileInfo f(it.next()); if (countSongs>0){
CAudioSource src; delete [] songList;
}
src.decode(f.absoluteFilePath()); countSongs=0;
QDirIterator it_counter(ui->lineEdit_path->text(), {"*.mp3", "*.wav", "*.flac", "*.ogg"}, QDir::NoFilter, QDirIterator::Subdirectories);
while (it_counter.next()!="") {
countSongs+=1;
}
QDirIterator it(ui->lineEdit_path->text(), {"*.mp3", "*.wav"}, QDir::NoFilter, QDirIterator::Subdirectories);
unsigned int k=0;
songList=new csong[countSongs];
float preferedLoudness=ui->doubleSpinBox_preferredLoudness->value();
ui->label_progress->setText(QString("0 of ")+QString::number(countSongs)+QString(" songs analyzed"));
ui->progressBar->setMaximum(countSongs);
while (it.hasNext()) {
QFileInfo f(it.next());
songList[k].setPath(f.absoluteFilePath());
songList[k].analyze(preferedLoudness);
k++;
ui->progressBar->setValue(k);
ui->label_progress->setText(QString::number(k)+QString(" of ")+QString::number(countSongs)+QString(" songs analyzed"));
QApplication::processEvents();
}
ui->label_progress->setText(QString("done"));
ui->tableWidget->setSortingEnabled(false);
ui->tableWidget->setRowCount(countSongs);
for (unsigned int i=0;i<countSongs;i++){
for (int k=0;k<5;k++){
ui->tableWidget->setItem(i,k,&songList[i].m_widgetItem[k]);
}
}
ui->tableWidget->setItemDelegateForColumn(0, new DelegatePathItem);
ui->pushButton_calculate->setDisabled(false);
ui->doubleSpinBox_preferredLoudness->setDisabled(false);
ui->tableWidget->setSortingEnabled(true);
ui->tableWidget->sortItems(0);
firstAnalysisDone=true;
} }
void analyzer::on_doubleSpinBox_preferredLoudness_valueChanged(double arg1)
{
if (firstAnalysisDone){
for (unsigned int i=0; i<countSongs;i++){
songList[i].setNewPreferedLoudness(arg1);
}
}
}

@ -2,8 +2,9 @@
#define ANALYZER_H #define ANALYZER_H
#include <QDialog> #include <QDialog>
#include <QAudioDecoder> #include <QTableWidgetItem>
#include "csong.h"
namespace Ui { namespace Ui {
class analyzer; class analyzer;
@ -22,8 +23,15 @@ private slots:
void on_pushButton_calculate_clicked(); void on_pushButton_calculate_clicked();
void on_doubleSpinBox_preferredLoudness_valueChanged(double arg1);
private: private:
Ui::analyzer *ui; Ui::analyzer *ui;
csong * songList;
unsigned int countSongs;
bool firstAnalysisDone;
}; };
#endif // ANALYZER_H #endif // ANALYZER_H

@ -6,16 +6,25 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>432</width> <width>836</width>
<height>141</height> <height>658</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Loudness Analyzer</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@ -24,45 +33,36 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_path"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <widget class="QLineEdit" name="lineEdit_path">
<horstretch>0</horstretch> <property name="sizePolicy">
<verstretch>0</verstretch> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
</sizepolicy> <horstretch>0</horstretch>
</property> <verstretch>0</verstretch>
<property name="text"> </sizepolicy>
<string>C:/Users/fsx12/Downloads/Zeugnisverleihung</string> </property>
</property> <property name="text">
</widget> <string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="layoutDirection"> <property name="layoutDirection">
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
@ -72,34 +72,94 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox_preferredLoudness">
<property name="suffix">
<string> dBFS</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-100.000000000000000</double>
</property>
<property name="maximum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>-18.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="pushButton_calculate"> <widget class="QPushButton" name="pushButton_calculate">
<property name="text"> <property name="text">
<string>Calculate</string> <string>Calculate</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QProgressBar" name="progressBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_progress">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>ready</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBox_preferredLoudness">
<property name="suffix">
<string> dBFS</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-100.000000000000000</double>
</property>
<property name="maximum">
<double>0.000000000000000</double>
</property>
<property name="value">
<double>-18.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_recommendation">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
<item>
<widget class="QTableWidget" name="tableWidget">
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
</property>
<property name="rowCount">
<number>1</number>
</property>
<property name="columnCount">
<number>5</number>
</property>
<row/>
<column/>
<column/>
<column/>
<column/>
<column/>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

@ -0,0 +1,138 @@
#include "csong.h"
#include <QFileInfo>
#include "getLoudness.h"
#include "getLoudness_terminate.h"
#include "rt_nonfinite.h"
#include "coder_array.h"
#include <cmath>
csong::csong()
{
m_path="";
m_loudness=0;
m_peakLevel=0;
m_widgetItem=new QTableWidgetItem[5];
setWidgetProperties();
}
csong::csong(QString path)
{
m_path=path;
m_widgetItem=new QTableWidgetItem[5];
setWidgetProperties();
}
csong::~csong()
{
delete [] m_widgetItem;
}
void csong::analyze(float preferedLoudness)
{
using namespace nqr;
NyquistIO loader;
std::shared_ptr<AudioData> fileData = std::make_shared<AudioData>();
auto memory= ReadFile(m_path.toStdString());
QFileInfo fi(m_path);
loader.Load(fileData.get(),fi.suffix().toStdString(),memory.buffer);
coder::array<float, 2U> loudness;
loudness.set_size(1,1);
coder::array<float, 2U> data;
data.set_size(fileData->samples.size()/2,fileData->channelCount);
for (int idx0{0}; idx0 < data.size(0); idx0++) {
for (int idx1{0}; idx1 < data.size(1); idx1++) {
data[idx0 + data.size(0) * idx1] = fileData->samples[idx1+data.size(1)*idx0];
}
}
getLoudness(data,fileData->sampleRate,loudness);
getLoudness_terminate();
m_loudness=loudness[0];
m_widgetItem[1].setText(QString::number(m_loudness));
m_peakLevel=0;
for (unsigned int i=0;i<fileData->samples.size();i++){
if (abs(fileData->samples[i])>m_peakLevel){
m_peakLevel=abs(fileData->samples[i]);
}
}
m_peakLevel=linToDb(m_peakLevel);
if (m_peakLevel>0){
m_peakLevel=0;
}
m_widgetItem[2].setText(QString::number(m_peakLevel));
m_correction=preferedLoudness-m_loudness;
m_widgetItem[4].setText(QString::number(m_correction));
m_correctedPeakLevel=m_peakLevel+m_correction;
m_widgetItem[3].setText(QString::number(m_correctedPeakLevel));
if (m_correctedPeakLevel>0){
m_widgetItem[3].setBackground(Qt::red);
}else {
m_widgetItem[3].setBackground(Qt::white);
}
}
void csong::setNewPreferedLoudness(float preferedLoudness)
{
m_correction=preferedLoudness-m_loudness;
m_widgetItem[4].setText(QString::number(m_correction));
m_correctedPeakLevel=m_peakLevel+m_correction;
m_widgetItem[3].setText(QString::number(m_correctedPeakLevel));
if (m_correctedPeakLevel>0){
m_widgetItem[3].setBackground(Qt::red);
}else {
m_widgetItem[3].setBackground(Qt::white);
}
}
void csong::setPath(QString path)
{
m_path=path;
m_widgetItem[0].setText(m_path);
}
float csong::get_PeakLevel() const
{
return m_peakLevel;
}
float csong::get_Loudness() const
{
return m_loudness;
}
float csong::get_correctedPeakLevel() const
{
return m_correctedPeakLevel;
}
float csong::get_correction() const
{
return m_correction;
}
float csong::linToDb(float linValue)
{
return 20*std::log10f(linValue);
}
void csong::setWidgetProperties()
{
for (int i=0;i<5;i++){
m_widgetItem[i].setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
m_widgetItem[i].setTextAlignment(Qt::AlignCenter);
}
m_widgetItem[0].setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
QString csong::get_path() const{
return m_path;
}

@ -0,0 +1,40 @@
#ifndef CSONG_H
#define CSONG_H
#include <QString>
#include <QTableWidgetItem>
#include "libnyquist/Decoders.h"
#include "rtwtypes.h"
#include <cstddef>
#include <cstdlib>
class csong
{
public:
csong();
csong(QString path);
~csong();
void analyze(float preferedLoudness);
void setNewPreferedLoudness(float preferedLoudness);
void setPath(QString path);
QString get_path() const;
float get_PeakLevel() const;
float get_Loudness() const;
float get_correctedPeakLevel() const;
float get_correction() const;
float requiredCorrection;
float linToDb(float linValue);
QTableWidgetItem* m_widgetItem;
private:
float m_peakLevel;
float m_loudness;
float m_correctedPeakLevel;
float m_correction;
QString m_path;
void setWidgetProperties();
};
#endif // CSONG_H

@ -0,0 +1,28 @@
#include "delegatepathitem.h"
#include <QPainter>
#include <QApplication>
void DelegatePathItem::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (!index.isValid())
return;
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
int padding = 3;
painter->save();
painter->setClipRect(opt.rect);
opt.rect = opt.rect.adjusted(padding, padding, -padding, -padding);
painter->drawText(opt.rect, Qt::AlignLeft | Qt::AlignVCenter,
opt.fontMetrics.elidedText(opt.text, Qt::ElideLeft,
opt.rect.width()));
painter->restore();
opt.rect = option.rect;
opt.textElideMode = Qt::ElideLeft;
opt.text = "";
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
}

@ -0,0 +1,13 @@
#ifndef DELEGATEPATHITEM_H
#define DELEGATEPATHITEM_H
#include <QStyledItemDelegate>
class DelegatePathItem : public QStyledItemDelegate
{
public:
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
#endif // DELEGATEPATHITEM_H

@ -30,9 +30,6 @@ MainWindow::MainWindow(QWidget *parent)
refreshLibraryAmpModes(); refreshLibraryAmpModes();
refreshLibrarySpeaker(); refreshLibrarySpeaker();
refreshLibraryDacs(); refreshLibraryDacs();
analyzer analyzerWindow;
analyzerWindow.exec();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()

Loading…
Cancel
Save