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