1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23 * DAMAGE.
24 */
25
26 #include <memory>
27 #include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
28 #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
29 #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
30 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
31 #include "third_party/blink/renderer/platform/audio/audio_processor.h"
32
33 namespace blink {
34
AudioBasicProcessorHandler(NodeType node_type,AudioNode & node,float sample_rate,std::unique_ptr<AudioProcessor> processor)35 AudioBasicProcessorHandler::AudioBasicProcessorHandler(
36 NodeType node_type,
37 AudioNode& node,
38 float sample_rate,
39 std::unique_ptr<AudioProcessor> processor)
40 : AudioHandler(node_type, node, sample_rate),
41 processor_(std::move(processor)) {
42 AddInput();
43 AddOutput(1);
44 }
45
~AudioBasicProcessorHandler()46 AudioBasicProcessorHandler::~AudioBasicProcessorHandler() {
47 // Safe to call the uninitialize() because it's final.
48 Uninitialize();
49 }
50
Initialize()51 void AudioBasicProcessorHandler::Initialize() {
52 if (IsInitialized())
53 return;
54
55 DCHECK(Processor());
56 Processor()->Initialize();
57
58 AudioHandler::Initialize();
59 }
60
Uninitialize()61 void AudioBasicProcessorHandler::Uninitialize() {
62 if (!IsInitialized())
63 return;
64
65 DCHECK(Processor());
66 Processor()->Uninitialize();
67
68 AudioHandler::Uninitialize();
69 }
70
Process(uint32_t frames_to_process)71 void AudioBasicProcessorHandler::Process(uint32_t frames_to_process) {
72 AudioBus* destination_bus = Output(0).Bus();
73
74 if (!IsInitialized() || !Processor() ||
75 Processor()->NumberOfChannels() != NumberOfChannels()) {
76 destination_bus->Zero();
77 } else {
78 scoped_refptr<AudioBus> source_bus = Input(0).Bus();
79
80 // FIXME: if we take "tail time" into account, then we can avoid calling
81 // processor()->process() once the tail dies down.
82 if (!Input(0).IsConnected())
83 source_bus->Zero();
84
85 Processor()->Process(source_bus.get(), destination_bus, frames_to_process);
86 }
87 }
88
ProcessOnlyAudioParams(uint32_t frames_to_process)89 void AudioBasicProcessorHandler::ProcessOnlyAudioParams(
90 uint32_t frames_to_process) {
91 if (!IsInitialized() || !Processor())
92 return;
93
94 Processor()->ProcessOnlyAudioParams(frames_to_process);
95 }
96
97 // Nice optimization in the very common case allowing for "in-place" processing
PullInputs(uint32_t frames_to_process)98 void AudioBasicProcessorHandler::PullInputs(uint32_t frames_to_process) {
99 // Render input stream - suggest to the input to render directly into output
100 // bus for in-place processing in process() if possible.
101 Input(0).Pull(Output(0).Bus(), frames_to_process);
102 }
103
104 // As soon as we know the channel count of our input, we can lazily initialize.
105 // Sometimes this may be called more than once with different channel counts, in
106 // which case we must safely uninitialize and then re-initialize with the new
107 // channel count.
CheckNumberOfChannelsForInput(AudioNodeInput * input)108 void AudioBasicProcessorHandler::CheckNumberOfChannelsForInput(
109 AudioNodeInput* input) {
110 DCHECK(Context()->IsAudioThread());
111 Context()->AssertGraphOwner();
112
113 DCHECK_EQ(input, &this->Input(0));
114 DCHECK(Processor());
115
116 unsigned number_of_channels = input->NumberOfChannels();
117
118 if (IsInitialized() && number_of_channels != Output(0).NumberOfChannels()) {
119 // We're already initialized but the channel count has changed.
120 Uninitialize();
121 }
122
123 if (!IsInitialized()) {
124 // This will propagate the channel count to any nodes connected further down
125 // the chain...
126 Output(0).SetNumberOfChannels(number_of_channels);
127
128 // Re-initialize the processor with the new channel count.
129 Processor()->SetNumberOfChannels(number_of_channels);
130 Initialize();
131 }
132
133 AudioHandler::CheckNumberOfChannelsForInput(input);
134 }
135
NumberOfChannels()136 unsigned AudioBasicProcessorHandler::NumberOfChannels() {
137 return Output(0).NumberOfChannels();
138 }
139
RequiresTailProcessing() const140 bool AudioBasicProcessorHandler::RequiresTailProcessing() const {
141 return processor_->RequiresTailProcessing();
142 }
143
TailTime() const144 double AudioBasicProcessorHandler::TailTime() const {
145 return processor_->TailTime();
146 }
147
LatencyTime() const148 double AudioBasicProcessorHandler::LatencyTime() const {
149 return processor_->LatencyTime();
150 }
151
HasNonFiniteOutput() const152 bool AudioBasicProcessorHandler::HasNonFiniteOutput() const {
153 AudioBus* output_bus = Output(0).Bus();
154
155 for (wtf_size_t k = 0; k < output_bus->NumberOfChannels(); ++k) {
156 AudioChannel* channel = output_bus->Channel(k);
157 if (channel->length() > 0 && !std::isfinite(channel->Data()[0])) {
158 return true;
159 }
160 }
161
162 return false;
163 }
164
165 } // namespace blink
166