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 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "third_party/blink/renderer/platform/audio/hrtf_database.h"
30
31 #include <memory>
32 #include <utility>
33
34 #include "base/memory/ptr_util.h"
35 #include "third_party/blink/public/resources/grit/blink_resources.h"
36 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
37
38 namespace blink {
39
40 const int HRTFDatabase::kMinElevation = -45;
41 const int HRTFDatabase::kMaxElevation = 90;
42 const unsigned HRTFDatabase::kRawElevationAngleSpacing = 15;
43 const unsigned HRTFDatabase::kNumberOfRawElevations =
44 10; // -45 -> +90 (each 15 degrees)
45 const unsigned HRTFDatabase::kInterpolationFactor = 1;
46 const unsigned HRTFDatabase::kNumberOfTotalElevations =
47 kNumberOfRawElevations * kInterpolationFactor;
48
HRTFDatabase(float sample_rate)49 HRTFDatabase::HRTFDatabase(float sample_rate)
50 : elevations_(kNumberOfTotalElevations), sample_rate_(sample_rate) {
51 unsigned elevation_index = 0;
52 for (int elevation = kMinElevation; elevation <= kMaxElevation;
53 elevation += kRawElevationAngleSpacing) {
54 std::unique_ptr<HRTFElevation> hrtf_elevation =
55 HRTFElevation::CreateForSubject(IDR_AUDIO_SPATIALIZATION_COMPOSITE,
56 elevation, sample_rate);
57 DCHECK(hrtf_elevation.get());
58
59 elevations_[elevation_index] = std::move(hrtf_elevation);
60 elevation_index += kInterpolationFactor;
61 }
62
63 // Now, go back and interpolate elevations.
64 if (kInterpolationFactor > 1) {
65 for (unsigned i = 0; i < kNumberOfTotalElevations;
66 i += kInterpolationFactor) {
67 unsigned j = (i + kInterpolationFactor);
68 if (j >= kNumberOfTotalElevations)
69 j = i; // for last elevation interpolate with itself
70
71 // Create the interpolated convolution kernels and delays.
72 for (unsigned jj = 1; jj < kInterpolationFactor; ++jj) {
73 float x =
74 static_cast<float>(jj) / static_cast<float>(kInterpolationFactor);
75 elevations_[i + jj] = HRTFElevation::CreateByInterpolatingSlices(
76 elevations_[i].get(), elevations_[j].get(), x, sample_rate);
77 DCHECK(elevations_[i + jj].get());
78 }
79 }
80 }
81 }
82
GetKernelsFromAzimuthElevation(double azimuth_blend,unsigned azimuth_index,double elevation_angle,HRTFKernel * & kernel_l,HRTFKernel * & kernel_r,double & frame_delay_l,double & frame_delay_r)83 void HRTFDatabase::GetKernelsFromAzimuthElevation(double azimuth_blend,
84 unsigned azimuth_index,
85 double elevation_angle,
86 HRTFKernel*& kernel_l,
87 HRTFKernel*& kernel_r,
88 double& frame_delay_l,
89 double& frame_delay_r) {
90 unsigned elevation_index = IndexFromElevationAngle(elevation_angle);
91 SECURITY_DCHECK(elevation_index < elevations_.size());
92 SECURITY_DCHECK(elevations_.size() > 0);
93
94 if (elevation_index > elevations_.size() - 1)
95 elevation_index = elevations_.size() - 1;
96
97 HRTFElevation* hrtf_elevation = elevations_[elevation_index].get();
98 DCHECK(hrtf_elevation);
99
100 hrtf_elevation->GetKernelsFromAzimuth(azimuth_blend, azimuth_index, kernel_l,
101 kernel_r, frame_delay_l, frame_delay_r);
102 }
103
IndexFromElevationAngle(double elevation_angle)104 unsigned HRTFDatabase::IndexFromElevationAngle(double elevation_angle) {
105 // Clamp to allowed range.
106 elevation_angle =
107 clampTo<double, double>(elevation_angle, kMinElevation, kMaxElevation);
108
109 unsigned elevation_index = static_cast<int>(
110 kInterpolationFactor * (elevation_angle - kMinElevation) /
111 kRawElevationAngleSpacing);
112 return elevation_index;
113 }
114
115 } // namespace blink
116