refactor Audio/Device
This commit is contained in:
		| @@ -111,6 +111,7 @@ target_sources(nf7 | ||||
|     common/node_root_select_lambda.hh | ||||
|     common/ptr_selector.hh | ||||
|     common/queue.hh | ||||
|     common/ring_buffer.hh | ||||
|     common/sequencer.hh | ||||
|     common/squashed_history.hh | ||||
|     common/task.hh | ||||
| @@ -119,7 +120,6 @@ target_sources(nf7 | ||||
|     common/util_algorithm.hh | ||||
|     common/util_string.hh | ||||
|     common/value.hh | ||||
|     common/yas_audio.hh | ||||
|     common/yas_enum.hh | ||||
|     common/yas_imgui.hh | ||||
|     common/yas_imnodes.hh | ||||
|   | ||||
							
								
								
									
										102
									
								
								common/ring_buffer.hh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								common/ring_buffer.hh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <cstdint> | ||||
| #include <cstring> | ||||
| #include <tuple> | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| namespace nf7 { | ||||
|  | ||||
| class RingBuffer final { | ||||
|  public: | ||||
|   RingBuffer() = delete; | ||||
|   RingBuffer(uint64_t unit, uint64_t bufn) noexcept : | ||||
|       buf_(unit*bufn), unit_(unit), bufn_(bufn) { | ||||
|   } | ||||
|   RingBuffer(const RingBuffer&) = delete; | ||||
|   RingBuffer(RingBuffer&&) = default; | ||||
|   RingBuffer& operator=(const RingBuffer&) = delete; | ||||
|   RingBuffer& operator=(RingBuffer&&) = default; | ||||
|  | ||||
|   template <typename T> | ||||
|   uint64_t Mix(uint64_t begin, const T* ptr, uint64_t n) noexcept { | ||||
|     assert(unit_ == sizeof(T)); | ||||
|  | ||||
|     if (begin < cur_) { | ||||
|       const auto drop = cur_ - begin; | ||||
|       if (drop >= n) { | ||||
|         return cur_; | ||||
|       } | ||||
|       ptr   += drop; | ||||
|       n     -= drop; | ||||
|       begin  = cur_; | ||||
|     } | ||||
|     if (begin > cur_) { | ||||
|       const auto skip = begin - cur_; | ||||
|       n = std::min(bufn_ - skip, n); | ||||
|     } | ||||
|     auto buf = reinterpret_cast<T*>(buf_.data()); | ||||
|  | ||||
|     const auto [c, r, l] = CalcCursor(begin, n); | ||||
|     for (uint64_t i = 0; i < r; ++i) { | ||||
|       buf[c+i] += ptr[i]; | ||||
|     } | ||||
|     for (uint64_t i = 0; i < l; ++i) { | ||||
|       buf[i] += ptr[r+i]; | ||||
|     } | ||||
|     return begin + n; | ||||
|   } | ||||
|   void Take(uint8_t* ptr, uint64_t n) noexcept { | ||||
|     const auto [c, r, l] = CalcCursor(cur_, n); | ||||
|     std::memcpy(&ptr[0*unit_], &buf_[c*unit_], r*unit_); | ||||
|     std::memcpy(&ptr[r*unit_], &buf_[0*unit_], l*unit_); | ||||
|     std::memset(&buf_[c*unit_], 0, r*unit_); | ||||
|     std::memset(&buf_[0*unit_], 0, l*unit_); | ||||
|     cur_ += n; | ||||
|   } | ||||
|  | ||||
|   uint64_t Peek(uint64_t begin, uint8_t* ptr, uint64_t n) noexcept { | ||||
|     if (cur_ > bufn_) { | ||||
|       const auto actual_begin = std::max(begin, cur_-bufn_); | ||||
|       const auto pad          = std::min(n, actual_begin - begin); | ||||
|       std::memset(ptr, 0, pad*unit_); | ||||
|       begin = actual_begin; | ||||
|       ptr  += pad*unit_; | ||||
|       n    -= pad; | ||||
|     } | ||||
|     n = std::min(n, bufn_); | ||||
|  | ||||
|     const auto [c, r, l] = CalcCursor(begin, n); | ||||
|     std::memcpy(&ptr[0*unit_], &buf_[c*unit_], r*unit_); | ||||
|     std::memcpy(&ptr[r*unit_], &buf_[0*unit_], l*unit_); | ||||
|     return begin + n; | ||||
|   } | ||||
|   void Write(const uint8_t* ptr, uint64_t n) noexcept { | ||||
|     const auto [c, r, l] = CalcCursor(cur_, n); | ||||
|     std::memcpy(&buf_[c*unit_], &ptr[0*unit_], r*unit_); | ||||
|     std::memcpy(&buf_[0*unit_], &ptr[r*unit_], l*unit_); | ||||
|     cur_ += n; | ||||
|   } | ||||
|  | ||||
|   uint64_t unit() const noexcept { return unit_; } | ||||
|   uint64_t bufn() const noexcept { return bufn_; } | ||||
|   uint64_t cur() const noexcept { return cur_; } | ||||
|  | ||||
|  private: | ||||
|   std::vector<uint8_t> buf_; | ||||
|   uint64_t unit_; | ||||
|   uint64_t bufn_; | ||||
|   uint64_t cur_ = 0; | ||||
|  | ||||
|   std::tuple<uint64_t, uint64_t, uint64_t> CalcCursor( | ||||
|       uint64_t t, uint64_t n) noexcept { | ||||
|     assert(n <= bufn_); | ||||
|     const auto c = t % bufn_; | ||||
|     const auto r = std::min(bufn_ - c, n); | ||||
|     const auto l = n > r? n - r: 0; | ||||
|     return {c, r, l}; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| }  // namespace nf7 | ||||
| @@ -1,86 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <cassert> | ||||
|  | ||||
| #include <miniaudio.h> | ||||
| #include <yas/serialize.hpp> | ||||
|  | ||||
| #include "nf7.hh" | ||||
|  | ||||
|  | ||||
| namespace yas::detail { | ||||
|  | ||||
| template <size_t F> | ||||
| struct serializer< | ||||
|     type_prop::not_a_fundamental, | ||||
|     ser_case::use_internal_serializer, | ||||
|     F, | ||||
|     ma_device_type> { | ||||
|  public: | ||||
|   template <typename Archive> | ||||
|   static Archive& save(Archive& ar, const ma_device_type& t) { | ||||
|     switch (t) { | ||||
|     case ma_device_type_playback: | ||||
|       ar("playback"); | ||||
|       break; | ||||
|     case ma_device_type_capture: | ||||
|       ar("capture"); | ||||
|       break; | ||||
|     default: | ||||
|       assert(false); | ||||
|     } | ||||
|     return ar; | ||||
|   } | ||||
|   template <typename Archive> | ||||
|   static Archive& load(Archive& ar, ma_device_type& t) { | ||||
|     std::string v; | ||||
|     ar(v); | ||||
|     if (v == "playback") { | ||||
|       t = ma_device_type_playback; | ||||
|     } else if (v == "capture") { | ||||
|       t = ma_device_type_capture; | ||||
|     } else { | ||||
|       throw nf7::DeserializeException("unknown device type"); | ||||
|     } | ||||
|     return ar; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <size_t F> | ||||
| struct serializer< | ||||
|     type_prop::not_a_fundamental, | ||||
|     ser_case::use_internal_serializer, | ||||
|     F, | ||||
|     ma_device_config> { | ||||
|  public: | ||||
|   template <typename Archive> | ||||
|   static Archive& save(Archive& ar, const ma_device_config& v) { | ||||
|     serialize(ar, v); | ||||
|     return ar; | ||||
|   } | ||||
|   template <typename Archive> | ||||
|   static Archive& load(Archive& ar, ma_device_config& v) { | ||||
|     serialize(ar, v); | ||||
|     if (v.sampleRate == 0) { | ||||
|       throw nf7::DeserializeException("invalid sample rate"); | ||||
|     } | ||||
|     return ar; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   static void serialize(auto& ar, auto& v) { | ||||
|     ar(v.deviceType); | ||||
|     ar(v.sampleRate); | ||||
|     if (v.deviceType == ma_device_type_playback) { | ||||
|       ar(v.playback.format); | ||||
|       ar(v.playback.channels); | ||||
|     } else if (v.deviceType == ma_device_type_capture) { | ||||
|       ar(v.capture.format); | ||||
|       ar(v.capture.channels); | ||||
|     } else { | ||||
|       assert(false); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| }  // namespace yas::detail | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user