#pragma once #include #include #include #include namespace tc::audio { class AudioInput; class AudioConsumer; namespace filter { class Filter; } namespace recorder { class AudioFilterWrapper; class AudioRecorderWrapper; enum FilterMode { BYPASS, FILTER, BLOCK }; class AudioConsumerWrapper : public Nan::ObjectWrap { friend class AudioRecorderWrapper; constexpr static auto kMaxChannelCount{2}; public: static NAN_MODULE_INIT(Init); static NAN_METHOD(NewInstance); static inline Nan::Persistent & constructor() { static Nan::Persistent my_constructor; return my_constructor; } static inline Nan::Persistent & constructor_template() { static Nan::Persistent my_constructor_template; return my_constructor_template; } AudioConsumerWrapper(AudioRecorderWrapper*, const std::shared_ptr& /* handle */); ~AudioConsumerWrapper() override; static NAN_METHOD(_get_filters); static NAN_METHOD(_unregister_filter); static NAN_METHOD(_create_filter_vad); static NAN_METHOD(_create_filter_threshold); static NAN_METHOD(_create_filter_state); static NAN_METHOD(_get_filter_mode); static NAN_METHOD(_set_filter_mode); static NAN_METHOD(toggle_rnnoise); static NAN_METHOD(rnnoise_enabled); std::shared_ptr create_filter(const std::string& /* name */, const std::shared_ptr& /* filter impl */); void delete_filter(const AudioFilterWrapper*); inline std::deque> filters() { std::lock_guard lock(this->filter_mutex_); return this->filter_; } inline FilterMode filter_mode() const { return this->filter_mode_; } inline std::shared_ptr native_consumer() { return this->_handle; } std::mutex native_read_callback_lock; std::function native_read_callback; private: AudioRecorderWrapper* _recorder; /* preprocessors */ bool rnnoise{false}; std::array rnnoise_processor{nullptr}; std::mutex execute_mutex; std::shared_ptr _handle; std::mutex filter_mutex_; std::deque> filter_; FilterMode filter_mode_{FilterMode::FILTER}; bool last_consumed = false; constexpr static auto kInternalFrameBufferCount{2}; void* internal_frame_buffer[kInternalFrameBufferCount]{nullptr}; size_t internal_frame_buffer_size[kInternalFrameBufferCount]{0}; void do_wrap(const v8::Local& /* object */); void unbind(); /* called with execute_lock locked */ void process_data(const void* /* buffer */, size_t /* samples */); void reserve_internal_buffer(int /* buffer */, size_t /* bytes */); void initialize_rnnoise(int /* channel */); struct DataEntry { void* buffer = nullptr; size_t sample_count = 0; ~DataEntry() { if(buffer) free(buffer); } }; std::mutex _data_lock; std::deque> _data_entries; Nan::callback_t<> _call_data; Nan::callback_t<> _call_ended; Nan::callback_t<> _call_started; }; } }