Skip to content

Instantly share code, notes, and snippets.

@Metalhead33
Last active August 26, 2020 22:00
Show Gist options
  • Save Metalhead33/a407e6f96c8d4835781f02d8c94abdcf to your computer and use it in GitHub Desktop.
Save Metalhead33/a407e6f96c8d4835781f02d8c94abdcf to your computer and use it in GitHub Desktop.
Just random stuff.
#ifndef AUDIOBUFFER_HPP
#define AUDIOBUFFER_HPP
#include "AudioPacket.hpp"
#include <memory>
#include <cstring>
namespace Audio {
template <class Allocator = std::allocator<float>> class Buffer {
private:
float* audioData;
FrameCount frameCount;
FrameRate frameRate;
SampleCount sampleCount; // Cached for speed
ChannelCount channelCount;
InterleavingType interleavingType;
public:
// Destructor, constructor, assignment
~Buffer() {
if(audioData) Allocator::deallocate(audioData,sampleCount.var);
}
explicit Buffer(FrameCount nFrameCnt=FrameCount(0), FrameRate nFrameRate=FrameRate(0),
ChannelCount nChannelCnt=ChannelCount(1), InterleavingType nInterleavingType=InterleavingType::DONT_CARE) :
audioData(nullptr), frameCount(nFrameCnt), frameRate(nFrameRate), sampleCount(nFrameCnt.toSamples(nChannelCnt)), channelCount(nChannelCnt), interleavingType(nInterleavingType)
{
if(sampleCount.var) {
audioData = Allocator::allocate(sampleCount.var);
std::memset(audioData,0,sampleCount.toBytes());
}
}
Buffer(const Buffer& cpy) : audioData(nullptr), frameCount(cpy.frameCount), frameRate(cpy.frameRate),
sampleCount(cpy.sampleCount), channelCount(cpy.channelCount), interleavingType(cpy.interleavingType) {
if(cpy.audioData) {
audioData = Allocator::allocate(sampleCount.var);
std::memcpy(audioData,cpy.audioData,sampleCount.toBytes());
}
}
Buffer(Buffer&& mov) : audioData(mov.audioData), frameCount(mov.frameCount), frameRate(mov.frameRate),
sampleCount(mov.sampleCount), channelCount(mov.channelCount), interleavingType(mov.interleavingType) {
mov.audioData = nullptr;
}
void operator=(const Buffer& cpy) {
if(audioData) Allocator::deallocate(audioData,sampleCount.var);
this->frameCount = cpy.frameCount;
this->frameRate = cpy.frameRate;
this->sampleCount = cpy.sampleCount;
this->channelCount = cpy.channelCount;
this->interleavingType = cpy.interleavingType;
if(cpy.audioData) {
audioData = Allocator::allocate(sampleCount.var);
std::memcpy(audioData,cpy.audioData,sampleCount.toBytes());
}
}
void operator=(Buffer&& mov) {
if(audioData) Allocator::deallocate(audioData,sampleCount.var);
this->audioData = mov.audioData;
mov.audioData = nullptr;
this->frameCount = mov.frameCount;
this->frameRate = mov.frameRate;
this->sampleCount = mov.sampleCount;
this->channelCount = mov.channelCount;
this->interleavingType = mov.interleavingType;
}
// Iterator functionality
typedef float* iterator;
typedef const float* const_iterator;
inline iterator begin() { return audioData; }
inline const_iterator begin() const { return audioData; }
inline iterator end() { return &audioData[sampleCount.var]; }
inline const_iterator end() const { return &audioData[sampleCount.var]; }
// Getting stuff - SampleIndex
inline float& get(SampleIndex i) { return audioData[i.var]; }
inline const float& get(SampleIndex i) const { return audioData[i.var]; }
inline float& operator[](SampleIndex i) { return audioData[i.var]; }
inline const float& operator[](SampleIndex i) const { return audioData[i.var]; }
// Getting stuff - SampleCount
inline float& get(SampleCount i) { return audioData[i.var]; }
inline const float& get(SampleCount i) const { return audioData[i.var]; }
inline float& operator[](SampleCount i) { return audioData[i.var]; }
inline const float& operator[](SampleCount i) const { return audioData[i.var]; }
// Access data
inline float* data() { return audioData; }
inline const float* data() const { return audioData; }
inline FrameCount getFrameCount() const { return frameCount; }
inline FrameRate getFrameRate() const { return frameRate; }
inline ChannelCount getChannelCount() const { return channelCount; }
inline InterleavingType getInterleavingType() const { return interleavingType; }
inline SampleCount getSampleCount() const { return sampleCount; }
inline uintptr_t getSizeInBytes() const { return sampleCount.toBytes(); }
template <typename SecondType=double> inline SecondType toSeconds() const { return frameCount.toSeconds<SecondType>(frameRate); }
// AudioPackets
inline void toInput(Input& dst, FrameCount offset=FrameCount(0)) const {
dst.audioSource = get(offset.toSamples(channelCount));
dst.frameCount = frameCount - offset;
dst.frameRate = frameRate;
dst.channelCount = channelCount;
dst.interleavingType = interleavingType;
}
inline void toOutput(Output& dst, FrameCount offset=FrameCount(0)) {
dst.audioDestination = get(offset.toSamples(channelCount));
dst.frameCount = frameCount - offset;
dst.frameRate = frameRate;
dst.channelCount = channelCount;
dst.interleavingType = interleavingType;
}
inline Input toInput(FrameCount offset=FrameCount(0)) const { Input tmp; toInput(tmp,offset); return tmp; }
inline Output toOutput(FrameCount offset=FrameCount(0)) { Output tmp; toInput(tmp,offset); return tmp; }
};
}
#endif // AUDIOBUFFER_HPP
#ifndef AUDIOITERATOR_HPP
#define AUDIOITERATOR_HPP
#include "IntegralIterator.hpp"
#include <cstdint>
#include <cmath>
#include <type_traits>
namespace Audio {
typedef IntegralIterator<uint_fast8_t> ChannelIndex;
typedef IntegralIterable<uint_fast8_t> ChannelCount;
typedef IntegralIterator<uintptr_t> SampleIndex;
struct SampleCount : public IntegralIterable<uintptr_t> {
typedef IntegralIterable<uintptr_t> BaseType;
SampleCount(const BaseType& other) : BaseType(other) {
}
explicit SampleCount(uintptr_t num=0) : BaseType(num) {
}
inline uintptr_t toBytes() const { return var * sizeof(float); }
};
typedef IntegralIterator<uintptr_t> FrameIndex;
struct FrameRate : public IntegralIterable<uintptr_t> {
typedef IntegralIterable<uintptr_t> BaseType;
FrameRate(const BaseType& other) : BaseType(other) {
}
explicit FrameRate(uintptr_t num=0) : BaseType(num) {
}
};
struct FrameCount : public IntegralIterable<uintptr_t> {
typedef IntegralIterable<uintptr_t> BaseType;
FrameCount(const BaseType& other) : BaseType(other) {
}
explicit FrameCount(uintptr_t num=0) : BaseType(num) {
}
static inline FrameCount fromSamples(const SampleCount& samples, const ChannelCount& channels) {
return FrameCount(samples.var / uintptr_t(channels.var));
}
inline SampleCount toSamples(ChannelCount channels) const { return SampleCount(var * uintptr_t(channels.var) ); }
inline uintptr_t toBytes(ChannelCount channels) const { return SampleCount(var * uintptr_t(channels.var) ).toBytes(); }
template<typename SecondType = double> inline SecondType toSeconds(const FrameRate& framerate) const {
static_assert (std::is_floating_point<SecondType>(),"Must use floating point types when calculating seconds!");
return SecondType(var) / SecondType(framerate.var);
}
template<typename SecondType = double> static inline FrameCount fromSeconds(SecondType seconds, const FrameRate& framerate) {
static_assert (std::is_floating_point<SecondType>(),"Must use floating point types when calculating seconds!");
return FrameCount(uintptr_t(std::ceil(seconds * SecondType(framerate.var)) ) );
}
};
}
#endif // AUDIOITERATOR_HPP
#ifndef AUDIOPACKET_HPP
#define AUDIOPACKET_HPP
#include "AudioIterator.hpp"
namespace Audio {
enum class InterleavingType : std::int8_t {
DONT_CARE = -1, // We don't really care
SEQUENTIAL =
0, // Each channels are stored separately, channel by channel
INTERLEAVED = 1 // Each channels are stored together frame by frame
};
struct Input {
const float* audioSource; // Actual audio data
FrameCount frameCount; // How many frames as a whole?
FrameRate frameRate; // How many frames per second?
ChannelCount channelCount; // How many channels? frameCount * channelCount = sampleCount
InterleavingType interleavingType;
explicit Input(const float* nsrc=nullptr,FrameCount nframeCnt=FrameCount(0),FrameRate nframeRate=FrameRate(0),
ChannelCount nchannelCount=ChannelCount(0), InterleavingType ninterl = InterleavingType::DONT_CARE)
: audioSource(nsrc), frameCount(nframeCnt), frameRate(nframeRate), channelCount(nchannelCount), interleavingType(ninterl) {
}
inline SampleCount toSamples() const { return frameCount.toSamples(channelCount); }
inline uintptr_t toBytes() const { return toSamples().toBytes(); }
template <typename SecondType=double> inline SecondType toSeconds() const { return frameCount.toSeconds<SecondType>(frameRate); }
};
struct Output {
float* audioDestination; // Actual audio output
FrameCount frameCount; // How many frames as a whole?
FrameRate frameRate; // How many frames per second?
ChannelCount channelCount; // How many channels? frameCount * channelCount = sampleCount
InterleavingType interleavingType;
explicit Output(float* ndest=nullptr,FrameCount nframeCnt=FrameCount(0),FrameRate nframeRate=FrameRate(0),
ChannelCount nchannelCount=ChannelCount(0), InterleavingType ninterl = InterleavingType::DONT_CARE)
: audioDestination(ndest), frameCount(nframeCnt), frameRate(nframeRate), channelCount(nchannelCount), interleavingType(ninterl) {
}
inline SampleCount toSamples() const { return frameCount.toSamples(channelCount); }
inline uintptr_t toBytes() const { return toSamples().toBytes(); }
template <typename SecondType=double> inline SecondType toSeconds() const { return frameCount.toSeconds<SecondType>(frameRate); }
};
}
#endif // AUDIOPACKET_HPP
#ifndef INTEGRAL_ITERATOR_HPP
#define INTEGRAL_ITERATOR_HPP
template <typename T> struct IntegralIterator {
typedef T dataType;
dataType var;
explicit IntegralIterator(dataType nvar=0) : var(nvar) {
}
IntegralIterator(const IntegralIterator& cpy) : var(cpy.var) {
}
// Overloaded operators - assignment
inline IntegralIterator& operator=(const IntegralIterator& other) {
this->var = other.var;
return *this;
}
inline IntegralIterator& operator+=(const IntegralIterator& other) {
this->var += other.var;
return *this;
}
inline IntegralIterator& operator-=(const IntegralIterator& other) {
this->var -= other.var;
return *this;
}
inline IntegralIterator& operator*=(const IntegralIterator& other) {
this->var *= other.var;
return *this;
}
inline IntegralIterator& operator/=(const IntegralIterator& other) {
this->var /= other.var;
return *this;
}
inline IntegralIterator& operator%=(const IntegralIterator& other) {
this->var %= other.var;
return *this;
}
// Overloaded operators - new data
inline IntegralIterator operator+(const IntegralIterator& other) const {
IntegralIterator a(*this);
a += other.var;
return a;
}
inline IntegralIterator operator-(const IntegralIterator& other) const {
IntegralIterator a(*this);
a -= other.var;
return a;
}
inline IntegralIterator operator*(const IntegralIterator& other) const {
IntegralIterator a(*this);
a *= other.var;
return a;
}
inline IntegralIterator operator/(const IntegralIterator& other) const {
IntegralIterator a(*this);
a /= other.var;
return a;
}
inline IntegralIterator operator%(const IntegralIterator& other) const {
IntegralIterator a(*this);
a %= other.var;
return a;
}
// Overloaded operators - Comparisons
inline bool operator==(const IntegralIterator& other) {
return this->var == other.var;
}
inline bool operator!=(const IntegralIterator& other) {
return this->var != other.var;
}
inline bool operator<(const IntegralIterator& other) {
return this->var < other.var;
}
inline bool operator<=(const IntegralIterator& other) {
return this->var <= other.var;
}
inline bool operator>(const IntegralIterator& other) {
return this->var > other.var;
}
inline bool operator>=(const IntegralIterator& other) {
return this->var >= other.var;
}
// Iterator-like functionality
inline IntegralIterator& operator++() { ++var; return *this;}
inline IntegralIterator& operator--() { --var; return *this;}
inline IntegralIterator operator++(int) { IntegralIterator tmp(*this); ++var; return tmp;}
inline IntegralIterator operator--(int) { IntegralIterator tmp(*this); --var; return tmp;}
inline dataType& operator*() { return var; }
inline const dataType& operator*() const { return var; }
};
template <typename T> struct IntegralIterable {
typedef T dataType;
dataType var;
typedef IntegralIterator<T> iterator;
explicit IntegralIterable(dataType nvar=0) : var(nvar) {
}
IntegralIterable(const IntegralIterable& cpy) : var(cpy.var) {
}
// Overloaded operators - assignment
inline IntegralIterable& operator=(const IntegralIterable& other) {
this->var = other.var;
return *this;
}
inline IntegralIterable& operator+=(const IntegralIterable& other) {
this->var += other.var;
return *this;
}
inline IntegralIterable& operator-=(const IntegralIterable& other) {
this->var -= other.var;
return *this;
}
inline IntegralIterable& operator*=(const IntegralIterable& other) {
this->var *= other.var;
return *this;
}
inline IntegralIterable& operator/=(const IntegralIterable& other) {
this->var /= other.var;
return *this;
}
inline IntegralIterable& operator%=(const IntegralIterable& other) {
this->var %= other.var;
return *this;
}
// Overloaded operators - new data
inline IntegralIterable operator+(const IntegralIterable& other) const {
IntegralIterable a(*this);
a += other.var;
return a;
}
inline IntegralIterable operator-(const IntegralIterable& other) const {
IntegralIterable a(*this);
a -= other.var;
return a;
}
inline IntegralIterable operator*(const IntegralIterable& other) const {
IntegralIterable a(*this);
a *= other.var;
return a;
}
inline IntegralIterable operator/(const IntegralIterable& other) const {
IntegralIterable a(*this);
a /= other.var;
return a;
}
inline IntegralIterable operator%(const IntegralIterable& other) const {
IntegralIterable a(*this);
a %= other.var;
return a;
}
// Overloaded operators - Comparisons
inline bool operator==(const IntegralIterable& other) {
return this->var == other.var;
}
inline bool operator!=(const IntegralIterable& other) {
return this->var != other.var;
}
inline bool operator<(const IntegralIterable& other) {
return this->var < other.var;
}
inline bool operator<=(const IntegralIterable& other) {
return this->var <= other.var;
}
inline bool operator>(const IntegralIterable& other) {
return this->var > other.var;
}
inline bool operator>=(const IntegralIterable& other) {
return this->var >= other.var;
}
// Iterators
inline iterator begin() const { return iterator(0); }
inline iterator end() const { return iterator(var); }
};
#endif // INTEGRAL_ITERATOR_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment