AudioBus* AudioNodeInput::pull(AudioBus* inPlaceBus, size_t framesToProcess) { ASSERT(context()->isAudioThread()); // Handle single connection case. if (numberOfRenderingConnections() == 1 && node()->internalChannelCountMode() == AudioNode::Max) { // The output will optimize processing using inPlaceBus if it's able. AudioNodeOutput* output = this->renderingOutput(0); return output->pull(inPlaceBus, framesToProcess); } AudioBus* internalSummingBus = this->internalSummingBus(); if (!numberOfRenderingConnections()) { // At least, generate silence if we're not connected to anything. // FIXME: if we wanted to get fancy, we could propagate a 'silent hint' here to optimize the downstream graph processing. internalSummingBus->zero(); return internalSummingBus; } // Handle multiple connections case. sumAllConnections(internalSummingBus, framesToProcess); return internalSummingBus; }
void AudioNodeInput::sumAllConnections(AudioBus* summingBus, size_t framesToProcess) { ASSERT(context()->isAudioThread()); // We shouldn't be calling this method if there's only one connection, since it's less efficient. ASSERT(numberOfRenderingConnections() > 1 || node()->internalChannelCountMode() != AudioNode::Max); ASSERT(summingBus); if (!summingBus) return; summingBus->zero(); AudioBus::ChannelInterpretation interpretation = node()->internalChannelInterpretation(); for (unsigned i = 0; i < numberOfRenderingConnections(); ++i) { AudioNodeOutput* output = renderingOutput(i); ASSERT(output); // Render audio from this output. AudioBus* connectionBus = output->pull(0, framesToProcess); // Sum, with unity-gain. summingBus->sumFrom(*connectionBus, interpretation); } }
void PannerNode::notifyAudioSourcesConnectedToNode(ContextRenderLock& r, AudioNode* node) { ASSERT(node); if (!node) return; // First check if this node is an AudioBufferSourceNode. If so, let it know about us so that doppler shift pitch can be taken into account. if (node->nodeType() == NodeTypeAudioBufferSource) { AudioBufferSourceNode* bufferSourceNode = reinterpret_cast<AudioBufferSourceNode*>(node); bufferSourceNode->setPannerNode(this); } else { // Go through all inputs to this node. for (unsigned i = 0; i < node->numberOfInputs(); ++i) { auto input = node->input(i); // For each input, go through all of its connections, looking for AudioBufferSourceNodes. for (unsigned j = 0; j < input->numberOfRenderingConnections(r); ++j) { auto connectedOutput = input->renderingOutput(r, j); AudioNode* connectedNode = connectedOutput->node(); notifyAudioSourcesConnectedToNode(r, connectedNode); // recurse } } } }
void AudioParam::calculateFinalValues(ContextRenderLock& r, float* values, unsigned numberOfValues, bool sampleAccurate) { bool isSafe = r.context() && values && numberOfValues; if (!isSafe) return; // The calculated result will be the "intrinsic" value summed with all audio-rate connections. if (sampleAccurate) { // Calculate sample-accurate (a-rate) intrinsic values. calculateTimelineValues(r, values, numberOfValues); } else { // Calculate control-rate (k-rate) intrinsic value. bool hasValue; float timelineValue = m_timeline.valueForContextTime(r, narrowPrecisionToFloat(m_value), hasValue); if (hasValue) m_value = timelineValue; values[0] = narrowPrecisionToFloat(m_value); } // if there are rendering connections, be sure they are ready updateRenderingState(r); size_t connectionCount = numberOfRenderingConnections(r); if (!connectionCount) return; // Now sum all of the audio-rate connections together (unity-gain summing junction). // Note that parameter connections would normally be mono, so mix down to mono if necessary. // LabSound: For some reason a bus was temporarily created here and the results discarded. // Bug still exists in WebKit top of tree. // if (m_data->m_internalSummingBus && m_data->m_internalSummingBus->length() < numberOfValues) m_data->m_internalSummingBus.reset(); if (!m_data->m_internalSummingBus) m_data->m_internalSummingBus.reset(new AudioBus(1, numberOfValues)); // point the summing bus at the values array m_data->m_internalSummingBus->setChannelMemory(0, values, numberOfValues); for (size_t i = 0; i < connectionCount; ++i) { auto output = renderingOutput(r, i); if (!output) continue; // Render audio from this output. AudioBus* connectionBus = output->pull(r, 0, AudioNode::ProcessingSizeInFrames); // Sum, with unity-gain. m_data->m_internalSummingBus->sumFrom(*connectionBus); } }
AudioBus* AudioNodeInput::bus() { ASSERT(context()->isAudioThread()); // Handle single connection specially to allow for in-place processing. if (numberOfRenderingConnections() == 1 && node()->internalChannelCountMode() == AudioNode::Max) return renderingOutput(0)->bus(); // Multiple connections case or complex ChannelCountMode (or no connections). return internalSummingBus(); }
AudioBus* AudioNodeInput::bus() { DCHECK(deferredTaskHandler().isAudioThread()); // Handle single connection specially to allow for in-place processing. if (numberOfRenderingConnections() == 1 && handler().internalChannelCountMode() == AudioHandler::Max) return renderingOutput(0)->bus(); // Multiple connections case or complex ChannelCountMode (or no connections). return internalSummingBus(); }
unsigned AudioNodeInput::numberOfRenderingChannels() { ASSERT(context()->isAudioThread()); // Find the number of channels of the rendering connection with the largest number of channels. unsigned maxChannels = 1; // one channel is the minimum allowed for (unsigned i = 0; i < numberOfRenderingConnections(); ++i) maxChannels = max(maxChannels, renderingOutput(i)->bus()->numberOfChannels()); return maxChannels; }
void AudioParam::calculateFinalValues(float* values, unsigned numberOfValues, bool sampleAccurate) { bool isGood = context() && context()->isAudioThread() && values && numberOfValues; ASSERT(isGood); if (!isGood) return; // The calculated result will be the "intrinsic" value summed with all audio-rate connections. if (sampleAccurate) { // Calculate sample-accurate (a-rate) intrinsic values. calculateTimelineValues(values, numberOfValues); } else { // Calculate control-rate (k-rate) intrinsic value. bool hasValue; float timelineValue = m_timeline.valueForContextTime(context(), narrowPrecisionToFloat(m_value), hasValue); if (hasValue) m_value = timelineValue; values[0] = narrowPrecisionToFloat(m_value); } // Now sum all of the audio-rate connections together (unity-gain summing junction). // Note that connections would normally be mono, but we mix down to mono if necessary. RefPtr<AudioBus> summingBus = AudioBus::create(1, numberOfValues, false); summingBus->setChannelMemory(0, values, numberOfValues); for (unsigned i = 0; i < numberOfRenderingConnections(); ++i) { AudioNodeOutput* output = renderingOutput(i); ASSERT(output); // Render audio from this output. AudioBus* connectionBus = output->pull(0, AudioNode::ProcessingSizeInFrames); // Sum, with unity-gain. summingBus->sumFrom(*connectionBus); } }