parent
							
								
									2a46eecdc6
								
							
						
					
					
						commit
						a9531c86a4
					
				@ -0,0 +1,42 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <memory> | 
				
			||||||
 | 
					#include <optional> | 
				
			||||||
 | 
					#include <string> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "freertos/portmacro.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "audio_element.hpp" | 
				
			||||||
 | 
					#include "himem.hpp" | 
				
			||||||
 | 
					#include "stream_info.hpp" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace audio { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const std::size_t kPipelineBufferSize = 32 * 1024; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Pipeline { | 
				
			||||||
 | 
					 public: | 
				
			||||||
 | 
					  Pipeline(IAudioElement* output); | 
				
			||||||
 | 
					  ~Pipeline(); | 
				
			||||||
 | 
					  auto AddInput(IAudioElement* input) -> Pipeline*; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto OutputElement() const -> IAudioElement*; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto NumInputs() const -> std::size_t; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto InStreams(std::vector<MappableRegion<kPipelineBufferSize>>*, | 
				
			||||||
 | 
					                 std::vector<MutableStream>*) -> void; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto OutStream(MappableRegion<kPipelineBufferSize>*) -> MutableStream; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto GetIterationOrder() -> std::vector<Pipeline*>; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 private: | 
				
			||||||
 | 
					  IAudioElement* root_; | 
				
			||||||
 | 
					  std::vector<std::unique_ptr<Pipeline>> subtrees_; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  HimemAlloc<kPipelineBufferSize> output_buffer_; | 
				
			||||||
 | 
					  StreamInfo output_info_; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace audio
 | 
				
			||||||
@ -0,0 +1,52 @@ | 
				
			|||||||
 | 
					#include "pipeline.hpp" | 
				
			||||||
 | 
					#include "stream_info.hpp" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace audio { | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pipeline::Pipeline(IAudioElement* output) : root_(output), subtrees_() {} | 
				
			||||||
 | 
					Pipeline::~Pipeline() {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::AddInput(IAudioElement* input) -> Pipeline* { | 
				
			||||||
 | 
					  subtrees_.emplace_back(input); | 
				
			||||||
 | 
					  return subtrees_.back().get(); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::OutputElement() const -> IAudioElement* { | 
				
			||||||
 | 
					  return root_; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::NumInputs() const -> std::size_t { | 
				
			||||||
 | 
					  return subtrees_.size(); | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::InStreams( | 
				
			||||||
 | 
					    std::vector<MappableRegion<kPipelineBufferSize>>* regions, | 
				
			||||||
 | 
					    std::vector<MutableStream>* out) -> void { | 
				
			||||||
 | 
					  for (int i = 0; i < subtrees_.size(); i++) { | 
				
			||||||
 | 
					    MutableStream s = subtrees_[i]->OutStream(®ions->at(i)); | 
				
			||||||
 | 
					    out->push_back(s); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::OutStream(MappableRegion<kPipelineBufferSize>* region) | 
				
			||||||
 | 
					    -> MutableStream { | 
				
			||||||
 | 
					  return {&output_info_, region->Map(output_buffer_)}; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					auto Pipeline::GetIterationOrder() -> std::vector<Pipeline*> { | 
				
			||||||
 | 
					  std::vector<Pipeline*> to_search{this}; | 
				
			||||||
 | 
					  std::vector<Pipeline*> found; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (!to_search.empty()) { | 
				
			||||||
 | 
					    Pipeline* current = to_search.back(); | 
				
			||||||
 | 
					    to_search.pop_back(); | 
				
			||||||
 | 
					    found.push_back(current); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    to_search.insert(to_search.end(), current->subtrees_.begin(), | 
				
			||||||
 | 
					                     current->subtrees_.end()); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return found; | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace audio
 | 
				
			||||||
@ -1,2 +1,2 @@ | 
				
			|||||||
idf_component_register(SRCS "arena.cpp" INCLUDE_DIRS "include" REQUIRES "span") | 
					idf_component_register(SRCS "arena.cpp" INCLUDE_DIRS "include" REQUIRES "span" "esp_psram") | 
				
			||||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) | 
					target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,78 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstddef> | 
				
			||||||
 | 
					#include <cstdint> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esp32/himem.h" | 
				
			||||||
 | 
					#include "span.hpp" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Wrapper around an ESP-IDF himem allocation, which uses RAII to clean up after | 
				
			||||||
 | 
					 * itself. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					template <std::size_t size> | 
				
			||||||
 | 
					class HimemAlloc { | 
				
			||||||
 | 
					 public: | 
				
			||||||
 | 
					  esp_himem_handle_t handle; | 
				
			||||||
 | 
					  const bool is_valid; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  HimemAlloc() : is_valid(esp_himem_alloc(size, &handle) == ESP_OK) {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ~HimemAlloc() { | 
				
			||||||
 | 
					    if (is_valid) { | 
				
			||||||
 | 
					      esp_himem_free(handle); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Not copyable or movable.
 | 
				
			||||||
 | 
					  HimemAlloc(const HimemAlloc&) = delete; | 
				
			||||||
 | 
					  HimemAlloc& operator=(const HimemAlloc&) = delete; | 
				
			||||||
 | 
					}; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Wrapper around an ESP-IDF himem allocation, which maps a HimemAlloc into the | 
				
			||||||
 | 
					 * usable address space. Instances always contain the last memory region that | 
				
			||||||
 | 
					 * was mapped within them. | 
				
			||||||
 | 
					 */ | 
				
			||||||
 | 
					template <std::size_t size> | 
				
			||||||
 | 
					class MappableRegion { | 
				
			||||||
 | 
					 private: | 
				
			||||||
 | 
					  std::byte* bytes_; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 public: | 
				
			||||||
 | 
					  esp_himem_rangehandle_t range_handle; | 
				
			||||||
 | 
					  const bool is_valid; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  MappableRegion() | 
				
			||||||
 | 
					      : bytes_(nullptr), | 
				
			||||||
 | 
					        is_valid(esp_himem_alloc_map_range(size, &range_handle) == ESP_OK) {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ~MappableRegion() { | 
				
			||||||
 | 
					    if (bytes_ != nullptr) { | 
				
			||||||
 | 
					      esp_himem_unmap(range_handle, bytes_, size); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    if (is_valid) { | 
				
			||||||
 | 
					      esp_himem_free_map_range(range_handle); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto Get() -> cpp::span<std::byte> { | 
				
			||||||
 | 
					    if (bytes_ != nullptr) { | 
				
			||||||
 | 
					      return {}; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    return {bytes_, size}; | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto Map(const HimemAlloc<size> &alloc) -> cpp::span<std::byte> { | 
				
			||||||
 | 
					    if (bytes_ != nullptr) { | 
				
			||||||
 | 
					      ESP_ERROR_CHECK(esp_himem_unmap(range_handle, bytes_, size)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    ESP_ERROR_CHECK(esp_himem_map(alloc.handle, range_handle, 0, 0, size, 0, | 
				
			||||||
 | 
					                                  reinterpret_cast<void**>(&bytes_))); | 
				
			||||||
 | 
					    return Get(); | 
				
			||||||
 | 
					  } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Not copyable or movable.
 | 
				
			||||||
 | 
					  MappableRegion(const MappableRegion&) = delete; | 
				
			||||||
 | 
					  MappableRegion& operator=(const MappableRegion&) = delete; | 
				
			||||||
 | 
					}; | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue