The WaveNet processing pipeline manages the flow of audio through conditioning signals and multiple LayerArray stages. The pipeline consists of three main phases:
- Condition Processing: If a
_condition_dsp is provided, the input is processed through it to generate a conditioning signal. If no DSP is provided, the input is used directly as the condition. - LayerArray Processing:
- The first
LayerArray processes the input with zeroed head inputs. - Subsequent
LayerArrays process the output of the previous array (GetLayerOutputs()) and incorporate the head outputs from the previous array (GetHeadOutputs()) as part of their input.
- Head Scaling and Output: The final head output from the last
LayerArray is scaled and written to the output buffers.
This architecture allows for complex conditioning (e.g., using a convolution or RNN as a condition module) to influence the audio processing at every stage of the hierarchy.
// Step 1: Condition processing
void WaveNet::_process_condition(const int num_frames) {
if (this->_condition_dsp != nullptr) {
// Process input through condition DSP
this->_condition_dsp->process(/* input */, /* output */, num_frames);
// Copy output to condition buffer
} else {
// Use input directly as condition
this->_condition_output = this->_condition_input;
}
}
// Step 2: LayerArray processing
// First layer array
this->_layer_arrays[0].Process(input, condition, num_frames);
// Subsequent layer arrays
for (size_t i = 1; i < this->_layer_arrays.size(); i++) {
Eigen::MatrixXf& prev_output = this->_layer_arrays[i-1].GetLayerOutputs();
Eigen::MatrixXf& prev_head = this->_layer_arrays[i-1].GetHeadOutputs();
this->_layer_arrays[i].Process(prev_output, condition, prev_head, num_frames);
}
// Step 3: Head scaling and output
Eigen::MatrixXf& final_head = this->_layer_arrays.back().GetHeadOutputs();
// Apply head scale and write to output buffers