Add missing upstream sources
authorIOhannes m zmölnig (Debian/GNU) <umlaeute@debian.org>
Fri, 17 Dec 2021 08:57:56 +0000 (09:57 +0100)
committerIOhannes m zmölnig (Debian/GNU) <umlaeute@debian.org>
Fri, 17 Dec 2021 08:57:56 +0000 (09:57 +0100)
debian/copyright
debian/missing-sources/README.md [new file with mode: 0644]
debian/missing-sources/mcl-atomic-swapper/atomic-swapper.hpp [new file with mode: 0644]
debian/missing-sources/mcl-audio-buffer/audioBuffer.cpp [new file with mode: 0644]
debian/missing-sources/mcl-audio-buffer/audioBuffer.hpp [new file with mode: 0644]

index eede0c2a66aa8ff519fe560f84bd2826f4ba1210..f9f6dee11fd9a3bdc858472bd89b5a48b393859e 100644 (file)
@@ -19,6 +19,11 @@ Copyright:
  2020 Dennis Braun <d_braun@kabelmail.de>
 License: GPL-3+
 
+Files: debian/missing-sources/mcl-*
+Copyright:
+ 2021 Giovanni A. Zuliani | Monocasual
+License: GPL-3+
+
 Files: src/deps/rtaudio/RtAudio.h
  src/deps/rtaudio/RtAudio.cpp
 Copyright:
diff --git a/debian/missing-sources/README.md b/debian/missing-sources/README.md
new file mode 100644 (file)
index 0000000..cc45e02
--- /dev/null
@@ -0,0 +1,18 @@
+missing sources for giada
+=========================
+
+this directory contains sources that are missing from upstream's tarball.
+
+
+mcl-atomic-swapper
+==================
+
+is a tiny (1 source file) module released under the GPLv3+,
+maintained by giada upstream in a separate repository.
+
+mcl-audio-buffer
+================
+
+is a tiny (2 source files) module released under the GPLv3+,
+maintained by giada upstream in a separate repository.
+
diff --git a/debian/missing-sources/mcl-atomic-swapper/atomic-swapper.hpp b/debian/missing-sources/mcl-atomic-swapper/atomic-swapper.hpp
new file mode 100644 (file)
index 0000000..e3ca0d5
--- /dev/null
@@ -0,0 +1,163 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Atomic Swapper
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2021 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * This file is part of Atomic Swapper.
+ *
+ * Atomic Swapper 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.
+ *
+ * Atomic Swapper 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 Atomic Swapper. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+#ifndef MONOCASUAL_ATOMIC_SWAPPER_H
+#define MONOCASUAL_ATOMIC_SWAPPER_H
+
+#include <array>
+#include <atomic>
+
+namespace mcl
+{
+template <typename T>
+class AtomicSwapper
+{
+public:
+       class RtLock
+       {
+               friend AtomicSwapper;
+
+       public:
+               RtLock(AtomicSwapper& s)
+               : m_swapper(s)
+               {
+                       m_swapper.rt_lock();
+               }
+
+               ~RtLock()
+               {
+                       m_swapper.rt_unlock();
+               }
+
+               const T& get() const
+               {
+                       return m_swapper.rt_get();
+               }
+
+       private:
+               AtomicSwapper& m_swapper;
+       };
+
+       AtomicSwapper()
+       {
+               static_assert(std::is_assignable_v<T, T>);
+       }
+
+       /* isLocked
+       Returns true if the busy bit is currently set, that is if the realtime 
+       thread is reading its copy of data. */
+
+       bool isLocked() const
+       {
+               return m_bits.load() & BIT_BUSY;
+       }
+
+       /* get (1)
+       Returns local data for non-realtime thread. */
+
+       const T& get() const
+       {
+               return m_data[(m_bits.load() & BIT_INDEX) ^ 1];
+       }
+
+       /* get (2)
+       As above, non-const version. */
+
+       T& get()
+       {
+               return const_cast<T&>(static_cast<const AtomicSwapper&>(*this).get());
+       }
+
+       /* swap
+       Core function: swaps the realtime data with the non-realtime one. Waits for
+       the realtime thread until it has finished reading its own copy of data. Only
+       then the indexes are swapped atomically. */
+
+       void swap()
+       {
+               int bits = m_bits.load();
+
+               /* Wait for the realtime thread to finish, i.e. until the BUSY bit 
+               becomes zero. Only then, swap indexes. This will let the realtime thread 
+               to pick the updated data on its next cycle. */
+               int desired;
+               do
+               {
+                       bits    = bits & ~BIT_BUSY;               // Expected: current value without busy bit set
+                       desired = (bits ^ BIT_INDEX) & BIT_INDEX; // Desired: flipped (xor) index
+               } while (!m_bits.compare_exchange_weak(bits, desired));
+
+               bits = desired;
+
+               /* After the swap above, m_data[(bits & BIT_INDEX) ^ 1] has become the 
+               non-realtime slot and it points to the data previously read by the
+               realtime thread. That data is old, so update it: overwrite it with the 
+               realtime data in the realtime slot (m_data[bits & BIT_INDEX]) that is 
+               currently being read by the realtime thread. */
+               m_data[(bits & BIT_INDEX) ^ 1] = m_data[bits & BIT_INDEX];
+       }
+
+private:
+       static constexpr int BIT_INDEX = (1 << 0); // 0001
+       static constexpr int BIT_BUSY  = (1 << 1); // 0010
+
+       /* [realtime] lock
+       Marks the data as busy. Used when the realtime thread starts reading its own 
+       copy of data. Can't call this directly (it's private), use the scoped lock
+       RtLock class above. */
+
+       void rt_lock()
+       {
+               /* Set the busy bit and also get the current index. */
+               m_index = m_bits.fetch_or(BIT_BUSY) & BIT_INDEX;
+       }
+
+       /* [realtime] unlock
+       Marks the data as free. Used when the realtime thread is done with reading 
+       its own copy of data. Can't call this directly (it's private), use the 
+       scoped lock     RtLock class above. */
+
+       void rt_unlock()
+       {
+               m_bits.store(m_index & BIT_INDEX);
+       }
+
+       /* [realtime] get
+       Get data currently being ready by the realtime thread. Can't call this 
+       directly (it's private), use the scoped lock RtLock class above.*/
+
+       const T& rt_get() const
+       {
+               return m_data[m_bits.load() & BIT_INDEX];
+       }
+
+       std::array<T, 2> m_data;
+       std::atomic<int> m_bits{0};
+       int              m_index{0};
+};
+} // namespace mcl
+
+#endif
diff --git a/debian/missing-sources/mcl-audio-buffer/audioBuffer.cpp b/debian/missing-sources/mcl-audio-buffer/audioBuffer.cpp
new file mode 100644 (file)
index 0000000..84a7df8
--- /dev/null
@@ -0,0 +1,273 @@
+/* -----------------------------------------------------------------------------
+ *
+ * AudioBuffer
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2021 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of AudioBuffer.
+ *
+ * AudioBuffer 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.
+ *
+ * AudioBuffer 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 
+ * AudioBuffer. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+#include "audioBuffer.hpp"
+#include <algorithm>
+#include <cassert>
+
+namespace mcl
+{
+AudioBuffer::AudioBuffer()
+: m_data(nullptr)
+, m_size(0)
+, m_channels(0)
+, m_viewing(false)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer::AudioBuffer(int size, int channels)
+: AudioBuffer()
+{
+       alloc(size, channels);
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer::AudioBuffer(float* data, int size, int channels)
+: m_data(data)
+, m_size(size)
+, m_channels(channels)
+, m_viewing(true)
+{
+       assert(channels <= NUM_CHANS);
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer::AudioBuffer(const AudioBuffer& o)
+{
+       copy(o);
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer::AudioBuffer(AudioBuffer&& o)
+{
+       move(std::move(o));
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer::~AudioBuffer()
+{
+       if (!m_viewing)
+               free();
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer& AudioBuffer::operator=(const AudioBuffer& o)
+{
+       if (this == &o)
+               return *this;
+       copy(o);
+       return *this;
+}
+
+/* -------------------------------------------------------------------------- */
+
+AudioBuffer& AudioBuffer::operator=(AudioBuffer&& o)
+{
+       if (this == &o)
+               return *this;
+       move(std::move(o));
+       return *this;
+}
+
+/* -------------------------------------------------------------------------- */
+
+float* AudioBuffer::operator[](int offset) const
+{
+       assert(m_data != nullptr);
+       assert(offset < m_size);
+       return m_data + (offset * m_channels);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::clear(int a, int b)
+{
+       if (m_data == nullptr)
+               return;
+       if (b == -1)
+               b = m_size;
+       std::fill_n(m_data + (a * m_channels), (b - a) * m_channels, 0.0);
+}
+
+/* -------------------------------------------------------------------------- */
+
+int  AudioBuffer::countFrames() const { return m_size; }
+int  AudioBuffer::countSamples() const { return m_size * m_channels; }
+int  AudioBuffer::countChannels() const { return m_channels; }
+bool AudioBuffer::isAllocd() const { return m_data != nullptr; }
+
+/* -------------------------------------------------------------------------- */
+
+float AudioBuffer::getPeak(int channel) const
+{
+       assert(channel < m_channels);
+
+       float peak = 0.0f;
+       for (int i = 0; i < countFrames(); i++)
+               peak = std::max(peak, (*this)[i][channel]);
+       return peak;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::alloc(int size, int channels)
+{
+       assert(channels <= NUM_CHANS);
+
+       free();
+       m_size     = size;
+       m_channels = channels;
+       m_data     = new float[m_size * m_channels];
+       clear();
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::free()
+{
+       if (m_data == nullptr)
+               return;
+       delete[] m_data;
+       m_data     = nullptr;
+       m_size     = 0;
+       m_channels = 0;
+       m_viewing  = false;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::sum(const AudioBuffer& b, int framesToCopy, int srcOffset,
+    int destOffset, float gain, Pan pan)
+{
+       copyData<Operation::SUM>(b, framesToCopy, srcOffset, destOffset, gain, pan);
+}
+
+void AudioBuffer::set(const AudioBuffer& b, int framesToCopy, int srcOffset,
+    int destOffset, float gain, Pan pan)
+{
+       copyData<Operation::SET>(b, framesToCopy, srcOffset, destOffset, gain, pan);
+}
+
+void AudioBuffer::sum(const AudioBuffer& b, float gain, Pan pan)
+{
+       copyData<Operation::SUM>(b, -1, 0, 0, gain, pan);
+}
+
+void AudioBuffer::set(const AudioBuffer& b, float gain, Pan pan)
+{
+       copyData<Operation::SET>(b, -1, 0, 0, gain, pan);
+}
+
+/* -------------------------------------------------------------------------- */
+
+template <AudioBuffer::Operation O>
+void AudioBuffer::copyData(const AudioBuffer& b, int framesToCopy,
+    int srcOffset, int destOffset, float gain, Pan pan)
+{
+       const int  srcChannels  = b.countChannels();
+       const int  destChannels = countChannels();
+       const bool sameChannels = srcChannels == destChannels;
+
+       assert(m_data != nullptr);
+       assert(destOffset >= 0 && destOffset < m_size);
+       assert(srcChannels <= destChannels);
+
+       /* Make sure the amount of frames to copy lies within the current buffer 
+       size. */
+
+       framesToCopy = framesToCopy == -1 ? b.countFrames() : framesToCopy;
+       framesToCopy = std::min(framesToCopy, m_size - destOffset);
+
+       /* Case 1) source has less channels than this one: brutally spread source's
+       channel 0 over this one (TODO - maybe mixdown source channels first?)
+          Case 2) source has same amount of channels: copy them 1:1. */
+
+       for (int destF = 0, srcF = srcOffset; destF < framesToCopy && destF < b.countFrames(); destF++, srcF++)
+       {
+               for (int ch = 0; ch < destChannels; ch++)
+               {
+                       if constexpr (O == Operation::SUM)
+                               sum(destF + destOffset, ch, b[srcF][sameChannels ? ch : 0] * gain * pan[ch]);
+                       else
+                               set(destF + destOffset, ch, b[srcF][sameChannels ? ch : 0] * gain * pan[ch]);
+               }
+       }
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::applyGain(float g)
+{
+       for (int i = 0; i < countSamples(); i++)
+               m_data[i] *= g;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::sum(int f, int channel, float val) { (*this)[f][channel] += val; }
+void AudioBuffer::set(int f, int channel, float val) { (*this)[f][channel] = val; }
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::move(AudioBuffer&& o)
+{
+       assert(o.countChannels() <= NUM_CHANS);
+
+       m_data     = o.m_data;
+       m_size     = o.m_size;
+       m_channels = o.m_channels;
+       m_viewing  = o.m_viewing;
+
+       o.m_data     = nullptr;
+       o.m_size     = 0;
+       o.m_channels = 0;
+       o.m_viewing  = false;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void AudioBuffer::copy(const AudioBuffer& o)
+{
+       m_data     = new float[o.m_size * o.m_channels];
+       m_size     = o.m_size;
+       m_channels = o.m_channels;
+       m_viewing  = o.m_viewing;
+
+       std::copy(o.m_data, o.m_data + (o.m_size * o.m_channels), m_data);
+}
+
+/* -------------------------------------------------------------------------- */
+
+template void AudioBuffer::copyData<AudioBuffer::Operation::SUM>(const AudioBuffer&, int, int, int, float, Pan);
+template void AudioBuffer::copyData<AudioBuffer::Operation::SET>(const AudioBuffer&, int, int, int, float, Pan);
+} // namespace mcl
\ No newline at end of file
diff --git a/debian/missing-sources/mcl-audio-buffer/audioBuffer.hpp b/debian/missing-sources/mcl-audio-buffer/audioBuffer.hpp
new file mode 100644 (file)
index 0000000..9b3107f
--- /dev/null
@@ -0,0 +1,163 @@
+/* -----------------------------------------------------------------------------
+ *
+ * AudioBuffer
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2021 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of AudioBuffer.
+ *
+ * AudioBuffer 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.
+ *
+ * AudioBuffer 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 
+ * AudioBuffer. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+#ifndef MONOCASUAL_AUDIO_BUFFER_H
+#define MONOCASUAL_AUDIO_BUFFER_H
+
+#include <array>
+
+namespace mcl
+{
+/* AudioBuffer
+A class that holds a buffer filled with audio data. NOTE: currently it only
+supports 2 channels (stereo). Give it a mono stream and it will convert it to
+stereo. Give it a multichannel stream and it will throw an assertion. */
+
+class AudioBuffer
+{
+public:
+       static constexpr int NUM_CHANS = 2;
+
+       using Pan = std::array<float, NUM_CHANS>;
+
+       /* AudioBuffer (1)
+       Creates an empty (and invalid) audio buffer. */
+
+       AudioBuffer();
+
+       /* AudioBuffer (2)
+       Creates an audio buffer and allocates memory for size * channels frames. */
+
+       AudioBuffer(int size, int channels);
+
+       /* AudioBuffer (3)
+       Creates an audio buffer out of a raw pointer. AudioBuffer created this way
+       is instructed not to free the owned data on destruction. */
+
+       AudioBuffer(float* data, int size, int channels);
+
+       /* AudioBuffer(const AudioBuffer&)
+       Copy constructor. */
+
+       AudioBuffer(const AudioBuffer& o);
+
+       /* AudioBuffer(AudioBuffer&&)
+       Move constructor. */
+
+       AudioBuffer(AudioBuffer&& o);
+
+       /* ~AudioBuffer
+       Destructor. */
+
+       ~AudioBuffer();
+
+       /* operator = (const AudioBuffer& o)
+       Copy assignment operator. */
+
+       AudioBuffer& operator=(const AudioBuffer& o);
+
+       /* operator = (AudioBuffer&& o)
+       Move assignment operator. */
+
+       AudioBuffer& operator=(AudioBuffer&& o);
+
+       /* operator []
+       Given a frame 'offset', returns a pointer to it. This is useful for digging 
+       inside a frame, i.e. parsing each channel. How to use it:
+
+               for (int k=0; k<buffer->countFrames(), k++)
+                       for (int i=0; i<buffer->countChannels(); i++)
+                               ... buffer[k][i] ...
+
+       Also note that buffer[0] will give you a pointer to the whole internal data
+       array. */
+
+       float* operator[](int offset) const;
+
+       int  countFrames() const;
+       int  countSamples() const;
+       int  countChannels() const;
+       bool isAllocd() const;
+
+       /* getPeak
+       Returns the highest value from the specified channel. */
+
+       float getPeak(int channel) const;
+
+       void alloc(int size, int channels);
+       void free();
+
+       /* sum, set (1)
+       Merges (sum) or copies (set) 'framesToCopy' frames of buffer 'b' onto this 
+       one. If 'framesToCopy' is -1 the whole buffer will be copied. If 'b' has 
+       less channels than this one, they will be spread over the current ones. 
+       Buffer 'b' MUST NOT contain more channels than this one. */
+
+       void sum(const AudioBuffer& b, int framesToCopy = -1, int srcOffset = 0,
+           int destOffset = 0, float gain = 1.0f, Pan pan = {1.0f, 1.0f});
+       void set(const AudioBuffer& b, int framesToCopy = -1, int srcOffset = 0,
+           int destOffset = 0, float gain = 1.0f, Pan pan = {1.0f, 1.0f});
+
+       /* sum, set (2)
+       Same as sum, set (1) without boundaries or offsets: it just copies as much
+       as possibile. */
+
+       void sum(const AudioBuffer& b, float gain = 1.0f, Pan pan = {1.0f, 1.0f});
+       void set(const AudioBuffer& b, float gain = 1.0f, Pan pan = {1.0f, 1.0f});
+
+       /* clear
+       Clears the internal data by setting all bytes to 0.0f. Optional parameters
+       'a' and 'b' set the range. */
+
+       void clear(int a = 0, int b = -1);
+
+       void applyGain(float g);
+
+private:
+       enum class Operation
+       {
+               SUM,
+               SET
+       };
+
+       template <Operation O = Operation::SET>
+       void copyData(const AudioBuffer& b, int framesToCopy = -1,
+           int srcOffset = 0, int destOffset = 0, float gain = 1.0f,
+           Pan pan = {1.0f, 1.0f});
+
+       void move(AudioBuffer&& o);
+       void copy(const AudioBuffer& o);
+       void sum(int f, int channel, float val);
+       void set(int f, int channel, float val);
+
+       float* m_data;
+       int    m_size;
+       int    m_channels;
+       bool   m_viewing;
+};
+} // namespace mcl
+
+#endif
\ No newline at end of file