1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#include "ambisonics/ambisonic_binaural_decoder.h"
18
19#include "ambisonics/utils.h"
20#include "base/constants_and_types.h"
21
22
23namespace vraudio {
24
25AmbisonicBinauralDecoder::AmbisonicBinauralDecoder(const AudioBuffer& sh_hrirs,
26 size_t frames_per_buffer,
27 FftManager* fft_manager)
28 : fft_manager_(fft_manager),
29 freq_input_(kNumMonoChannels, NextPowTwo(input: frames_per_buffer) * 2),
30 filtered_input_(kNumMonoChannels, frames_per_buffer) {
31 CHECK(fft_manager_);
32 CHECK_NE(frames_per_buffer, 0U);
33 const size_t num_channels = sh_hrirs.num_channels();
34 const size_t filter_size = sh_hrirs.num_frames();
35 CHECK_NE(num_channels, 0U);
36 CHECK_NE(filter_size, 0U);
37 sh_hrir_filters_.reserve(n: num_channels);
38 for (size_t i = 0; i < num_channels; ++i) {
39 sh_hrir_filters_.emplace_back(
40 args: new PartitionedFftFilter(filter_size, frames_per_buffer, fft_manager_));
41 sh_hrir_filters_[i]->SetTimeDomainKernel(sh_hrirs[i]);
42 }
43}
44
45void AmbisonicBinauralDecoder::Process(const AudioBuffer& input,
46 AudioBuffer* output) {
47
48 DCHECK(output);
49 DCHECK_EQ(kNumStereoChannels, output->num_channels());
50 DCHECK_EQ(input.num_frames(), output->num_frames());
51 DCHECK_EQ(input.num_channels(), sh_hrir_filters_.size());
52
53 output->Clear();
54
55 AudioBuffer::Channel* freq_input_channel = &freq_input_[0];
56 AudioBuffer::Channel* filtered_input_channel = &filtered_input_[0];
57 AudioBuffer::Channel* output_channel_0 = &(*output)[0];
58 AudioBuffer::Channel* output_channel_1 = &(*output)[1];
59 for (size_t channel = 0; channel < input.num_channels(); ++channel) {
60 const int degree = GetPeriphonicAmbisonicDegreeForChannel(channel);
61 fft_manager_->FreqFromTimeDomain(time_channel: input[channel], freq_channel: freq_input_channel);
62 sh_hrir_filters_[channel]->Filter(input: *freq_input_channel);
63 sh_hrir_filters_[channel]->GetFilteredSignal(output: filtered_input_channel);
64 if (degree < 0) {
65 // Degree is negative: spherical harmonic is asymetric.
66 // So add contributions to the left channel and subtract from the right
67 // channel.
68 *output_channel_0 += *filtered_input_channel;
69 *output_channel_1 -= *filtered_input_channel;
70
71 } else {
72 // Degree is zero or positive: spherical harmonic is symetric.
73 // So add contributions to both left and right channels.
74 *output_channel_0 += *filtered_input_channel;
75 *output_channel_1 += *filtered_input_channel;
76 }
77 }
78}
79
80} // namespace vraudio
81

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/ambisonics/ambisonic_binaural_decoder.cc