| @@ -34,9 +34,11 @@ public: | |||
| virtual size_t get(T* buf, size_t frames) = 0; | |||
| size_t channels() const { return m_channels; } | |||
| inline size_t channels() const { return m_channels; } | |||
| int frequency() const { return m_frequency; } | |||
| inline int frequency() const { return m_frequency; } | |||
| inline size_t frame_size() const { return channels() * sizeof(T); } | |||
| virtual ~stream() = default; | |||
| @@ -89,7 +91,7 @@ public: | |||
| virtual size_t get(T *buf, size_t frames) override | |||
| { | |||
| memset(buf, 0, frames * this->channels() * sizeof(T)); | |||
| memset(buf, 0, frames * this->frame_size()); | |||
| std::vector<T> tmp(frames * this->channels()); | |||
| for (auto s : m_streamers) | |||
| @@ -158,21 +160,52 @@ class resampler : public stream<T> | |||
| public: | |||
| resampler(std::shared_ptr<stream<T>> s, int frequency) | |||
| : stream<T>(s->channels(), frequency), | |||
| s(s) | |||
| m_in(s), | |||
| m_pos(0) | |||
| {} | |||
| virtual size_t get(T *buf, size_t frames) override | |||
| { | |||
| if (s->frequency() == this->frequency()) | |||
| return s->get(buf, frames); | |||
| if (m_in->frequency() == this->frequency()) | |||
| return m_in->get(buf, frames); | |||
| double ratio = double(m_in->frequency()) / this->frequency(); | |||
| for (size_t n = 0; n < frames; ++n, m_pos += ratio) | |||
| { | |||
| // Fill internal buffer if we don’t have enough data | |||
| while (m_cache.size() / this->channels() < size_t(m_pos) + 2) | |||
| { | |||
| // Remove obsolete frames on the left | |||
| size_t todelete = std::min(size_t(m_pos), m_cache.size() / this->channels()); | |||
| std::vector<T>(m_cache.begin() + todelete * this->channels(), m_cache.end()).swap(m_cache); | |||
| m_pos -= todelete; | |||
| // Add new frames to the right | |||
| size_t offset = m_cache.size(); | |||
| m_cache.resize(offset + frames * this->channels()); | |||
| m_in->get(&m_cache[offset], frames); | |||
| } | |||
| size_t n0 = size_t(m_pos); | |||
| float alpha = float(m_pos - n0); | |||
| for (size_t ch = 0; ch < this->channels(); ++ch) | |||
| { | |||
| buf[n * this->channels() + ch] = m_cache[n0 * this->channels() + ch] * (1.f - alpha) | |||
| + m_cache[(n0 + 1) * this->channels() + ch] * alpha; | |||
| } | |||
| } | |||
| // FIXME: implement resampling! | |||
| memset(buf, 0, frames * this->channels() * sizeof(T)); | |||
| return frames; | |||
| } | |||
| protected: | |||
| std::shared_ptr<stream<T>> s; | |||
| std::shared_ptr<stream<T>> m_in; | |||
| std::vector<T> m_cache; | |||
| double m_pos; | |||
| }; | |||
| template<typename T> | |||