Files
lmms/include/SampleFrame.h
Rossmaxx 7367750823 [Code Cleanup] Cleaned up some header files and move a bit of debugging logic to cmake (#7677)
* Renamed lmms_basics.h to LmmsTypes.h and scoped it down for that purpose.

* Shifted the LMMS_STRINGIFY macro to it's own header.

* Removed the debug.h header file and use cmake to handle the macro logic.

* Remove some unused headers and include directives
2025-03-24 19:07:46 +05:30

233 lines
4.4 KiB
C++

/*
* SampleFrame.h - Representation of a stereo sample
*
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2024- Michael Gregorius
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LMMS_SAMPLEFRAME_H
#define LMMS_SAMPLEFRAME_H
#include "LmmsTypes.h"
#include "lmms_constants.h"
#include <algorithm>
#include <array>
#include <cmath>
namespace lmms
{
class SampleFrame
{
public:
SampleFrame() : SampleFrame(0., 0.)
{
}
explicit SampleFrame(sample_t value) : SampleFrame(value, value)
{
}
SampleFrame(sample_t left, sample_t right) :
m_samples({ left, right })
{
}
sample_t* data()
{
return m_samples.data();
}
const sample_t* data() const
{
return m_samples.data();
}
sample_t& left()
{
return m_samples[0];
}
const sample_t& left() const
{
return m_samples[0];
}
void setLeft(const sample_t& value)
{
m_samples[0] = value;
}
sample_t& right()
{
return m_samples[1];
}
const sample_t& right() const
{
return m_samples[1];
}
void setRight(const sample_t& value)
{
m_samples[1] = value;
}
sample_t& operator[](size_t index)
{
return m_samples[index];
}
const sample_t& operator[](size_t index) const
{
return m_samples[index];
}
SampleFrame operator+(const SampleFrame& other) const
{
return SampleFrame(left() + other.left(), right() + other.right());
}
SampleFrame& operator+=(const SampleFrame& other)
{
auto & l = left();
auto & r = right();
l += other.left();
r += other.right();
return *this;
}
SampleFrame operator*(float value) const
{
return SampleFrame(left() * value, right() * value);
}
SampleFrame& operator*=(float value)
{
setLeft(left() * value);
setRight(right() * value);
return *this;
}
SampleFrame operator*(const SampleFrame& other) const
{
return SampleFrame(left() * other.left(), right() * other.right());
}
void operator*=(const SampleFrame& other)
{
left() *= other.left();
right() *= other.right();
}
sample_t sumOfSquaredAmplitudes() const
{
return left() * left() + right() * right();
}
SampleFrame abs() const
{
return SampleFrame{std::abs(this->left()), std::abs(this->right())};
}
SampleFrame absMax(const SampleFrame& other)
{
const auto a = abs();
const auto b = other.abs();
return SampleFrame(std::max(a.left(), b.left()), std::max(a.right(), b.right()));
}
sample_t average() const
{
return (left() + right()) / 2;
}
void clamp(sample_t low, sample_t high)
{
auto & l = left();
l = std::clamp(l, low, high);
auto & r = right();
r = std::clamp(r, low, high);
}
bool containsInf() const
{
return std::isinf(left()) || std::isinf(right());
}
bool containsNaN() const
{
return std::isnan(left()) || std::isnan(right());
}
private:
std::array<sample_t, DEFAULT_CHANNELS> m_samples;
};
inline void zeroSampleFrames(SampleFrame* buffer, size_t frames)
{
// The equivalent of the following operation which yields compiler warnings
// memset(buffer, 0, sizeof(SampleFrame) * frames);
std::fill(buffer, buffer + frames, SampleFrame());
}
inline SampleFrame getAbsPeakValues(SampleFrame* buffer, size_t frames)
{
SampleFrame peaks;
for (f_cnt_t i = 0; i < frames; ++i)
{
peaks = peaks.absMax(buffer[i]);
}
return peaks;
}
inline void copyToSampleFrames(SampleFrame* target, const float* source, size_t frames)
{
for (size_t i = 0; i < frames; ++i)
{
target[i].setLeft(source[2*i]);
target[i].setRight(source[2*i + 1]);
}
}
inline void copyFromSampleFrames(float* target, const SampleFrame* source, size_t frames)
{
for (size_t i = 0; i < frames; ++i)
{
target[2*i] = source[i].left();
target[2*i + 1] = source[i].right();
}
}
} // namespace lmms
#endif // LMMS_SAMPLEFRAME_H