WebAudio has nested classes. There are 18 specific sub-classes of AudioNode
. I am wondering if or how I might avoid coding things a large number of times by sub-classing.
Here is what I have for AudioNode.h
. Notice no Init()
, just protected stuff:
#ifndef AUDIO_NODE_H
#define AUDIO_NODE_H
#include <napi.h>
#include <LabSound.h>
namespace webaudio {
// being forced to set AudioNode for the wrap type is worrying
class AudioNode : public Napi::ObjectWrap<AudioNode> {
protected:
// accessors
Napi::Value ContextGetter(const Napi::CallbackInfo& info);
Napi::Value NumberOfInputsGetter(const Napi::CallbackInfo& info);
Napi::Value NumberOfOutputsGetter(const Napi::CallbackInfo& info);
Napi::Value ChannelCountGetter(const Napi::CallbackInfo& info);
Napi::Value ChannelCountModeGetter(const Napi::CallbackInfo& info);
Napi::Value ChannelInterpretationGetter(const Napi::CallbackInfo& info);
// methods
Napi::Object Connect(const Napi::CallbackInfo& info);
Napi::Object Disconnect(const Napi::CallbackInfo& info);
// internal lab references
std::shared_ptr<lab::AudioContext> m_labContext;
std::shared_ptr<lab::AnalyserNode> m_labAudioNode;
}
}
#endif
Using the AnalyserNode
as an example of a specific Node type. It would have an h file of:
#ifndef ANALYSER_NODE_H
#define ANALYSER_NODE_H
#include <AudioNode.h>
namespace webaudio {
class AnalyserNode : public AudioNode {
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
AnalyserNode(const Napi::CallbackInfo& info);
private:
Napi::Value FftSizeGetter(const Napi::CallbackInfo& info);
void FftSizeSetter(const Napi::CallbackInfo& info);
Napi::Value FrequencyBinCountGetter(const Napi::CallbackInfo& info);
Napi::Value MinDecibelsGetter(const Napi::CallbackInfo& info);
void MinDecibelsSetter(const Napi::CallbackInfo& info);
Napi::Value MaxDecibelsGetter(const Napi::CallbackInfo& info);
void MaxDecibelsSetter(const Napi::CallbackInfo& info);
Napi::Value SmoothingTimeConstantGetter(const Napi::CallbackInfo& info);
void SmoothingTimeConstantSetter(const Napi::CallbackInfo& info);
void GetFloatFrequencyData(const Napi::CallbackInfo& info);
void GetByteFrequencyData(const Napi::CallbackInfo& info);
void GetFloatTimeDomainData(const Napi::CallbackInfo& info);
void GetByteTimeDomainData(const Napi::CallbackInfo& info);
}
}
#endif
The code for the Init()
in AnalyserNode
would include the accessors & methods of super class too:
Napi::Object AnalyserNode::Init(Napi::Env env, Napi::Object exports) {
// This method is used to hook the accessor and method callbacks
Napi::Function func = DefineClass(env, "AnalyserNode", {
// accessors & methods for super class
InstanceAccessor("context", &AnalyserNode::ContextGetter, nullptr),
InstanceAccessor("numberOfInputs", &AnalyserNode::NumberOfInputsGetter, nullptr),
InstanceAccessor("numberOfOutputs", &AnalyserNode::NumberOfOutputsGetter, nullptr),
InstanceAccessor("channelCount", &AnalyserNode::ChannelCountGetter, nullptr),
InstanceAccessor("channelCountMode", &AnalyserNode::ChannelCountModeGetter, nullptr),
InstanceAccessor("channelInterpretation", &AnalyserNode::ChannelInterpretationGetter, nullptr),
InstanceMethod("connect", &AnalyserNode::Connect),
InstanceMethod("disconnect", &AnalyserNode::Disconnect),
// accessors & methods for this class
InstanceAccessor("fftSize", &AnalyserNode::FftSizeGetter, &AnalyserNode::FftSizeSetter),
InstanceAccessor("frequencyBinCount", &AnalyserNode::FrequencyBinCountGetter, nullptr),
InstanceAccessor("minDecibels", &AnalyserNode::MinDecibelsGetter, &AnalyserNode::MinDecibelsSetter),
InstanceAccessor("maxDecibels", &AnalyserNode::MaxDecibelsGetter, &AnalyserNode::MaxDecibelsSetter),
InstanceAccessor("smoothingTimeConstant", &AnalyserNode::smoothingTimeConstantGetter, &AnalyserNode::smoothingTimeConstantSetter),
InstanceMethod("getFloatFrequencyData", &AnalyserNode::getFloatFrequencyData),
InstanceMethod("getByteFrequencyData", &AnalyserNode::getByteFrequencyData),
InstanceMethod("getFloatTimeDomainData", &AnalyserNode::GetWebXRRenderTarget),
InstanceMethod("getByteTimeDomainData", &AnalyserNode::GetNativeRenderTargetProvider),
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
exports.Set("AnalyserNode", func);
env.SetInstanceData<Napi::FunctionReference>(constructor);
return exports;
}
I have not seen an example that covers anything close to this. Any thoughts?