1 // Copyright (C) 2016 Lukas Lalinsky 2 // Distributed under the MIT license, see the LICENSE file for details. 3 4 #ifndef CHROMAPRINT_AUDIO_AUDIO_SLICER_H_ 5 #define CHROMAPRINT_AUDIO_AUDIO_SLICER_H_ 6 7 #include <cstddef> 8 #include <cstdint> 9 #include <cassert> 10 #include <vector> 11 #include "debug.h" 12 13 namespace chromaprint { 14 15 template <typename T> 16 class AudioSlicer { 17 public: AudioSlicer(size_t size,size_t increment)18 AudioSlicer(size_t size, size_t increment) 19 : m_size(size), m_increment(increment), m_buffer(size * 2) { 20 assert(size >= increment); 21 Reset(); 22 } 23 size()24 size_t size() const { 25 return m_size; 26 } 27 increment()28 size_t increment() const { 29 return m_increment; 30 } 31 Reset()32 void Reset() { 33 m_buffer_begin = m_buffer_end = m_buffer.begin(); 34 } 35 36 template <typename InputIt, typename ConsumerFunc> Process(InputIt begin,InputIt end,ConsumerFunc consumer)37 void Process(InputIt begin, InputIt end, ConsumerFunc consumer) { 38 size_t size = std::distance(begin, end); 39 size_t buffer_size = std::distance(m_buffer_begin, m_buffer_end); 40 41 while (buffer_size > 0 && buffer_size + size >= m_size) { 42 consumer(&(*m_buffer_begin), &(*m_buffer_end), begin, std::next(begin, m_size - buffer_size)); 43 if (buffer_size >= m_increment) { 44 std::advance(m_buffer_begin, m_increment); 45 buffer_size -= m_increment; 46 const size_t available_buffer_size = std::distance(m_buffer_end, m_buffer.end()); 47 if (buffer_size + available_buffer_size < m_size) { 48 const auto new_buffer_begin = m_buffer.begin(); 49 m_buffer_end = std::copy(m_buffer_begin, m_buffer_end, new_buffer_begin); 50 m_buffer_begin = new_buffer_begin; 51 } 52 } else { 53 m_buffer_begin = m_buffer_end = m_buffer.begin(); 54 std::advance(begin, m_increment - buffer_size); 55 size -= m_increment - buffer_size; 56 buffer_size = 0; 57 } 58 } 59 60 if (buffer_size == 0) { 61 while (size >= m_size) { 62 consumer(begin, std::next(begin, m_size), end, end); 63 std::advance(begin, m_increment); 64 size -= m_increment; 65 } 66 } 67 68 assert(buffer_size + size < m_size); 69 m_buffer_end = std::copy(begin, end, m_buffer_end); 70 } 71 72 private: 73 size_t m_size; 74 size_t m_increment; 75 std::vector<T> m_buffer; 76 typename std::vector<T>::iterator m_buffer_begin; 77 typename std::vector<T>::iterator m_buffer_end; 78 }; 79 80 }; // namespace chromaprint 81 82 #endif // CHROMAPRINT_AUDIO_AUDIO_SLICER_H_ 83